建立自訂的 GitHub 動作

已完成

GitHub Actions 是強大的功能,協助您從程式碼到雲端,全都輕鬆自信地來自自有存放庫。 您會在此了解不同類型的 GitHub 動作,以及用來建立自訂動作的中繼資料、語法和工作流程命令。

GitHub 動作類型

GitHub Actions 的三種類型圖表;Docker、JavaScript 和複合執行步驟動作。

動作是可用以自訂開發工作流程的個別工作。 您可以透過撰寫與存放庫互動的自訂程式碼以執行自訂工作,或使用 GitHub 社群共用的動作來建立自己的動作。 瀏覽各種動作後,您會發現三種不同類型的動作:Docker 容器動作JavaScript 動作複合執行步驟動作。 讓我們進一步了解每種動作類型。

Docker 容器動作

Docker 容器會用 GitHub Actions 程式碼封裝環境。 這表示該動作會在一致且可靠的環境中執行,因為其所有相依性都在該容器內。 如果動作需要在特定環境設定中執行,則 Docker 容器會是很好的做法,因為您可以自訂作業系統和工具。 缺點是因為作業必須建立並擷取容器,所以 Docker 容器動作通常會比 JavaScript 動作慢。

建立 Docker 容器動作之前,請先了解環境變數和 Docker 容器檔案系統的基本使用方法。 建立 Docker 容器動作所需採取的步驟簡單直接:

  1. 建立 Dockerfile,定義組合 Docker 映像的命令。
  2. 建立 action.yml 中繼資料檔案,定義動作的輸入和輸出。 將檔案中的 runs: using: 值設為 dockerruns: image: 值設為 Dockerfile
  3. 建立 entrypoint.sh 檔案以描述 Docker 映像。
  4. 使用下列檔案來認可動作,並將其推送至 GitHub:action.ymlentrypoint.shDockerfileREADME.md

JavaScript 動作

JavaScript 動作可以直接在執行器電腦上執行,並隔開動作程式碼與執行動作所用的環境。 因此會簡化動作程式碼,且執行速度會比 Docker 容器內的動作快。

您必須下載 Node.js,包括 npm,才能建立及使用封裝的 JavaScript 動作。 GitHub Actions 工具組 Node.js 為選擇性步驟,但建議使用,因為這個 Node.js 套件集合可讓您快速建立一致性更高的 JavaScript 動作。

建立 JavaScript 動作所需採取的步驟簡單且直接:

  1. 建立 action.yml 中繼資料檔案,定義動作的輸入和輸出,以及通知動作執行器如何開始執行此 JavaScript 動作。
  2. 建立 index.js 檔案,包含工具組套件、路由和其他動作函式的相關內容資訊。
  3. 使用下列檔案認可動作,並將其推送至 GitHub:action.ymlindex.jsnode_modulespackage.jsonpackage-lock.jsonREADME.md

複合執行步驟動作

複合執行步驟動作可讓您利用 Shell 指令碼重複使用動作。 您甚至可以在相同的動作中混合多個 Shell 語言。 如果您有自動化數個工作的許多 Shell 指令碼,現可將其輕鬆轉換成動作,並針對不同的工作流程重複使用。 撰寫 Shell 指令碼有時候比使用 JavaScript 或將程式碼包裝在 Docker 容器中更容易。

封裝的複合動作

封裝的復合動作會將多個步驟組合成可重複使用的單位。 這些動作是在存放庫中定義,而且可以在不同存放庫的工作流程中參考。 封裝複合動作可簡化工作流程、減少重複,並改善可維護性。

建立封裝的複合動作時,步驟會在單 action.yml 一檔案中定義。 此檔案指定輸入、輸出及命令或動作的序列。 封裝的複合動作特別適合將重複工作自動化,或將多個殼層命令結合成單一可重複使用的動作。

建立複合 qction

1.設定複合動作的目錄

您必須將複合動作放在存放庫內專屬的目錄中。

範例目錄結構:

.github/actions/my-composite-action/
├── action.yml
└── scripts/
    └── my-script.sh

2.定義 action.yml 檔案

my-composite-action 目錄中,建立檔案 action.yml

name: "My Composite Action"
description: "A reusable composite action that checks out code and sets up Node.js"

inputs:
  node-version:
    description: "The Node.js version to use"
    required: true

runs:
  using: "composite"
  steps:
    - name: Checkout repository
      uses: actions/checkout@v4

    - name: Set up Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}

注意: using: “composite” 字段表示此動作是復合動作。

3.在工作流程中使用復合動作

建立複合動作之後,即可在 GitHub Actions 工作流程中參考它。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Use my composite action
        uses: ./.github/actions/my-composite-action
        with:
          node-version: '18'

如果您的複合動作是從另一個存放庫共用,請使用以下方式參考,如下所示:

uses: owner/repository/.github/actions/my-composite-action@v1

工作流程中使用的複合動作螢幕快照。

將輸出新增至複合動作

復合動作可以定義工作流程可用來在步驟或作業之間傳遞數據的輸出。 輸出特別適用於將結果或計算值從一個動作共用到另一個動作。

下列範例示範如何在複合動作中定義和使用輸出:

action.yml 中定義輸出

檔案 action.yml 會指定名為 script-result的輸出。 此輸出會從 result 步驟的 run-script 輸出中擷取值。 此步驟會 run-script 執行 Bash 命令來設定輸出值。

outputs:
  script-result:
    description: "Result from the script"
    value: ${{ steps.run-script.outputs.result }}

runs:
  using: "composite"
  steps:
    - id: run-script
      run: echo "result=Success" >> $GITHUB_OUTPUT
      shell: bash

在複合動作中定義輸出的螢幕快照。

在工作流程中運用輸出的結果

建立複合動作之後,就可以在工作流程中存取其輸出。 以下為範例:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Run composite action
        id: my-action
        uses: ./.github/actions/my-composite-action

      - name: Display result
        run: echo "Script Result: ${{ steps.my-action.outputs.script-result }}"

在此範例中:

  • 複合動作使用 uses 關鍵字來調用。
  • 請使用 script-result 語法存取輸出 steps.<step-id>.outputs.<output-name>
  • 在工作流程記錄中顯示結果。

在複合動作中定義輸出,以建立可重複使用和模組化的工作流程。 此方法可簡化數據共用,並改善可維護性。

合成動作的最佳做法

最佳做法 說明
使用版本控制 使用 v1 標記來參考穩定版本 1。
將動作保持模組化 將複合動作內的相關步驟分組。
檔輸入與輸出 action.yml 中新增輸入/輸出的描述。
發佈前測試 驗證測試存放庫中的複合動作。

工作流程中的復合動作

復合動作是將多個步驟結合至可重複使用單元來簡化工作流程的強大方式。 這些動作可讓您在單 action.yml 一檔案中定義一連串的命令或動作,讓您更輕鬆地跨工作流程維護及重複使用邏輯。

複合動作的優點:

  • 可重複使用性 - 定義一次動作,並在多個工作流程中使用它們。
  • 可維護性 - 藉由將邏輯集中化為單一動作來減少重複。
  • 模組化 - 將多個殼層命令或其他動作結合成單一單位。

開發動作以在 GitHub Actions 執行器上設定 CLI

許多 CI/CD 工作流程都需要 特定版本的 CLI 工具 ,才能與雲端服務互動、管理基礎結構或執行腳本。 雖然 GitHub 裝載的執行器已預安裝許多工具,但它們可能不會包含工作流程所需的確切版本,特別是如果是較舊或不支援的版本。 您可以建立 可重複使用的 GitHub Action ,而不是在每個工作流程中安裝必要的 CLI 版本:

  • 確保跨作業一致地安裝必要的 CLI 版本。
  • 藉由集中安裝邏輯來簡化工作流程。
  • 優化快取以加快工作流程的執行速度。

如何開發 CLI 設定動作

CLI 設定動作是以 JavaScript 為基礎的動作,可安裝和設定 GitHub 執行器上的 CLI。

建立動作的步驟:

步驟 1:設定動作目錄

若要手動建立 CLI 設定動作的目錄,請遵循下列步驟:

  1. 流覽至您的存放庫

顯示 JavaScript 動作之根存放庫結構的螢幕快照。

  1. 建立動作的新目錄
    在資料夾內my-cli-action建立名為 .github/actions 的新目錄。 這可確保您的動作已組織,並遵循 GitHub 建議的自定義動作結構。

  2. 流覽至新目錄
    變更為新建立的目錄,以開始為動作新增檔案:

  3. 確認目錄結構
    建立目錄之後,您的存放庫結構看起來應該像這樣:

your-repository/
├── .github/
│   ├── actions/
│   │   ├── my-cli-action/

'.github/actions' 內 JavaScript 動作目錄結構的螢幕快照。

您現在已準備好繼續為 CLI 設定動作建立 action.yml 檔案和其他必要檔案。

步驟 2:定義action.yml元數據檔案

建立action.yml檔案來描述動作。

name: "Setup MyCLI"
description: "Installs MyCLI and adds it to the PATH"
author: "Your Name"

inputs:
  version:
    description: "The CLI version to install"
    required: false
    default: "latest"

runs:
  using: "node16"
  main: "index.js"

為何 使用:node16? 此動作會使用 Node.js 16 執行 JavaScript 程式代碼。

JavaScript GitHub Action 的 YAML 元數據檔案螢幕快照。

步驟 3:建立 JavaScript 腳本以安裝 CLI

在相同的目錄中,建立名為 index.js 的檔案,並新增下列程式代碼:

const core = require('@actions/core');
const { execSync } = require('child_process');

async function run() {
  try {
    const version = core.getInput('version') || 'latest';
    
    console.log(`Installing MyCLI version: ${version}...`);

    execSync(`curl -fsSL https://cli.example.com/install.sh | sh`, { stdio: 'inherit' });

    console.log("MyCLI installed successfully.");
  } catch (error) {
    core.setFailed(`Installation failed: ${error.message}`);
  }
}

run();

上述 JavaScript 程式代碼會使用 core.getInput() 來擷取指定為輸入的 CLI 版本。 然後,它會執行 curl 命令來下載並安裝 CLI。 如果安裝程式失敗,動作會使用core.setFailed() 將工作流程標示為失敗。

GitHub Action 中 index.js JavaScript 程式代碼的螢幕快照。

步驟 4:在本機測試動作

在工作流程中使用動作之前,請先在 GitHub 裝載的執行器上進行測試。
在存放庫中建立工作流程檔案 (.github/workflows/test.yml:

name: Test MyCLI Setup

on:
  push:
    branches:
      - main
      - feature/*

1.觸發工作流程
工作流程會在推送至主分支及符合功能/* 模式的任何分支時觸發。 您可以調整此設定,以便符合存放庫的分支策略。

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

2.複製存放庫
動作/checkout@v4動作是用來將存放庫複製到執行器上。 這可確保工作流程可以存取存放庫的檔案。

      - name: Install MyCLI
        uses: ./.github/actions/my-cli-action
        with:
          version: '1.2.3'

3.執行自定義動作
uses: ./.github/actions/my-cli-action 這一行會在本機參考自訂動作。 請確定已正確設定動作目錄和action.yml檔案。 版本輸入會指定要安裝的 CLI 版本,在此案例中為 1.2.3 版。

      - name: Verify CLI Installation
        run: |
          echo "Checking MyCLI version..."
          mycli --version

4.確認 CLI 安裝
此步驟會執行 Shell 命令,以確認 CLI 已成功安裝。 它會執行 mycli --version 來檢查已安裝 CLI 的版本。

JavaScript GitHub Action 測試結果的螢幕快照。

在本機測試

若要在本機測試此工作流程,請使用 act CLI 工具:

act -j test

這會模擬本機電腦上的 GitHub Actions 環境,讓您在推送變更之前對工作流程進行偵錯和驗證。

最佳化提示:快取

若要改善工作流程效能,請使用 actions/cache 動作快取 CLI 安裝目錄:

      - name: Cache MyCLI
        uses: actions/cache@v4
        with:
          path: ~/.mycli
          key: mycli-${{ runner.os }}-${{ inputs.version }}

這可確保後續執行會重複使用快取的 CLI 安裝,以減少安裝時間。

CLI 設定動作的最佳做法

最佳做法 說明
使用版本控制 允許使用者透過 inputs.version指定 CLI 版本。
正確處理錯誤 使用 core.setFailed() 來在發生錯誤時退出。
快取 CLI 安裝 使用 actions/cache優化工作流程效能。
提供檔 說明README.md中的使用方式和輸入。

針對 JavaScript 動作進行疑難解答

使用以 JavaScript 為基礎的 GitHub Actions 時,您可能會在工作流程執行期間遇到非預期的行為、錯誤或失敗。 本單元提供技術和工具,協助您識別並解決JavaScript動作中的問題。

常見疑難解答案例

問題 可能原因 建議的修正
動作失敗並顯示堆疊追蹤 index.js 中的語法或執行時期錯誤 使用 console.log() 並檢查日誌
輸入為 undefined 輸入名稱不正確或輸入遺漏 請驗證 action.yml 及輸入的傳遞方式
未設定環境變數 core.exportVariableprocess.env 使用不當 檢閱設定變數的程式碼
找不到檔案 遺漏相對路徑 請使用 __dirname 或完整檔案路徑
快取未還原 錯誤 keypath 檢查快取組態和金鑰

使用記錄進行偵錯

使用 core.infocore.debugconsole.log 記錄訊息

const core = require('@actions/core');

core.info("This is an info message");
core.debug("This is a debug message");
console.log("This is a raw console log");

✅ 針對偵錯記錄使用 core.debug - 只有在ACTIONS_STEP_DEBUG設定為 true 時,才會顯示這些記錄。

啟用偵錯記錄

您可以藉由設定下列秘密來啟用步驟層級偵錯記錄

ACTIONS_STEP_DEBUG=true

若要啟用 執行器診斷記錄,請設定:

ACTIONS_RUNNER_DEBUG=true

設定秘密已進行偵錯

  1. 移至 GitHub 存放庫。
  2. 流覽至 [ 設定>秘密和變數>動作]。
  3. 使用下列名稱與值新增秘密:
    • ACTIONS_STEP_DEBUGtrue
    • ACTIONS_RUNNER_DEBUGtrue

檢查工作流程記錄

當工作流程失敗時,請在 [動作] 索引標籤中按一下失敗的作業。展開各步驟以:

  • 檢視詳細記錄
  • 檢查標準輸出 (stdout)
  • 請參閱腳本的退出碼
  • 識別未處理的例外狀況

🔍 範例記錄輸出

Error: Cannot find module '@actions/core'
Require stack:
- /home/runner/work/_actions/my-org/my-action/index.js

✅ 修正:執行 npm install @actions/core 並提交 node_modules (或使用 ncc 打包操作)。

在本機測試您的動作

使用 act — CLI 工具,在本機執行 GitHub Actions。 範例:

act -j test

🛠 請務必在本機測試時正確模擬您的 GitHub 環境。

優雅地處理錯誤

擷取例外狀況並失敗,並顯示有幫助的訊息:

try {
  // your logic
} catch (error) {
  core.setFailed(`Action failed with error: ${error.message}`);
}

🔁 這可確保 GitHub 會在錯誤時停止工作流程,並提供可讀取的記錄。

偵錯 JavaScript 動作的最佳做法

實踐 說明
使用 core.debug() 除非啟用偵錯,否則隱藏詳細資訊記錄。
驗證action.yml 請確定已正確定義輸入和輸出。
套件代碼 使用 @vercel/ncc 將 JavaScript 編譯成單一檔案。 這可減少相依性,並確保包含所有必要的模組,以防止遺失檔案所造成的運行時錯誤。
使用 act 進行測試 在本機模擬執行以加快反覆項目的速度。
使用 try/catch 防止工作流程悄然失敗。

針對 Docker 容器動作進行疑難解答

Docker 容器動作很強大,可在 GitHub Actions 工作流程中封裝複雜的工具和環境。 不過,由於這些動作的隔離運行時間環境,偵錯這些動作比 JavaScript 動作更具挑戰性。 本單元將引導您找出、診斷和解決 Docker 型動作的問題。

Docker 容器動作中的常見問題

問題 原因 建議的修正
動作無法啟動 ENTRYPOINTCMD 設定錯誤 確認 Dockerfile 正確使用 ENTRYPOINT
遺漏相依性 相依性未安裝或設定錯誤 確定映像中已安裝所有套件
未收到輸入 INPUT_ 未存取環境變數 使用 process.env.INPUT_<INPUT_NAME> (或殼層對等項)
找不到檔案 容器內的檔案路徑不正確 使用絕對路徑或驗證目錄結構
權限遭拒 檔案或腳本缺少執行許可權 在 Dockerfile 中新增RUN chmod +x <script>
網路相關失敗 無法存取外部服務 驗證網路設定和重試邏輯

瞭解 Docker 動作生命週期

在進行疑難解答之前,瞭解 Docker 容器動作的執行方式有助於。

1. 工作流程觸發程式

GitHub Actions 工作流程會開始回應已設定的事件,例如 pushpull_request或手動 workflow_dispatch

2. 執行器設定

GitHub 會佈建新的虛擬機( 執行器)來執行工作流程。 執行器會下載動作定義並解析相依性來準備環境。

3. 動作解析

如果在其 runs.using: docker 檔案中指定 action.yml,GitHub 會將其辨識為基於 Docker 的動作。

4. 映像建置或提取

GitHub 會建置動作 Dockerfile 中所定義的 Docker 映射,或在指定時提取預先建置的映射。 此映像會定義執行動作程式代碼的環境。

5. 容器執行

執行程式會啟動 Docker 容器、掛載工作區,並插入環境變數,包括在工作流程中定義的機密資訊和輸入。

6. 進入點執行

GitHub 會從容器內的 Dockerfile 執行 entrypoint 命令。 這是自定義動作邏輯執行的位置,通常是腳本或應用程式。

7. 結果處理

容器動作所設定的任何輸出會由執行器擷取,並傳遞至工作流程中的後續步驟。 完成後,容器會關閉並捨棄執行器。

注意:Docker 容器操作會在乾淨且隔離的環境中執行。 檔案系統狀態、已安裝的工具和環境變數都必須定義在 Dockerfile 內。

偵錯技術

1. 新增記錄

在進入點指令碼中使用 echo、printf 或記錄陳述式:

echo "Starting Docker action..."
echo "Input VALUE: $INPUT_VALUE"

記錄所有重要輸入和步驟,以診斷失敗發生的位置。

2.在本機建置和測試

在您的計算機上使用 Docker 來模擬容器行為:

docker build -t my-action .
docker run -e INPUT_NAME=value my-action

確保環境變數與 GitHub 設定的一樣。

3.使用 act CLI 來模擬 GitHub 工作流程

安裝 act 工具以在本地執行您的 GitHub 工作流程:

act -j test-job

非常適合在工作流程中測試 Docker 動作,而不需要推送至 GitHub。

4.驗證 Dockerfile 組態

請確定您定義 ENTRYPOINT 或 CMD。 將您的文稿複製到映像,並授與他們執行許可權:

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

5.檢查 GitHub 記錄

按一下失敗的工作流程執行,展開各步驟並檢查:

  • Docker 建置記錄
  • 來自容器的標準輸出和標準錯誤
  • 結束代碼和堆疊追蹤 🔍 記錄通常會顯示遺漏的封裝、語法問題或權限錯誤。

範例:進入點錯誤

Error: container_linux.go:380: starting container process caused "exec: \"/entrypoint.sh\": permission denied"

✅ 修正:在 Dockerfile 中新增 RUN chmod +x /entrypoint.sh。

環境變數對應

GitHub 輸入 Docker 環境變數
with: name: test INPUT_NAME=test
GITHUB_WORKSPACE 對應至 /github/workspace
GITHUB_EVENT_NAME 觸發工作流程的事件
echo "Input was $INPUT_NAME"
echo "Working dir: $GITHUB_WORKSPACE"

使用疑難解答祕密

將這些機密資訊新增至您的存放庫或組織,以啟用額外的日誌記錄功能:

祕密 描述
ACTIONS_STEP_DEBUG 啟用偵錯日誌
ACTIONS_RUNNER_DEBUG 啟用執行器診斷

Docker 動作偵錯的最佳做法

最佳做法 為什麼
盡可能使用記錄 協助追蹤失敗點
一律設定 chmod +x 避免 Shell 腳本的權限錯誤
驗證文本中的輸入 早期攔截遺漏或格式不正確的輸入
將容器相依性最小化 較小的映像更容易偵錯
在本機使用 docker run 或 act 進行測試 更快速的迭代和立即的反饋