Files
code/skills/code-action-docker/SKILL.md
T

16 KiB
Raw Blame History


name: code-action-docker description: 以互動問答從零打造 GiteaGitHub「Docker 容器 action」:(1) 詢問 action 名稱(用於 action.yml 的 name);(2) 詢問輸入與輸出參數及其 description(盡量繁體中文、無亂碼);(3) 詢問執行此流程的目標,整理濃縮成一句話(用於 action.yml 的 description,盡量繁體中文、無亂碼);(4) 依標準實作目標——開發中需要新參數時依 ${{ gitea.* }}${{ secrets.* }}${{ vars.* }} 順序尋找、都沒有才詢問使用者是否加入 inputs;盡量以 Node.js 開發、程式檔一律放 src/、盡量詳細輸出訊息且格式統一為 doc-funcs 規範的 [階段][等級][yyyy/MM/dd HH:mm:ss]: 訊息(無階段則移除該 [],等級為 INF/WRN/ERR/TRC/DBG),並產生 action.ymlentrypoint.sh/最新 node 版本的 Dockerfile(5) 檢查是否有 doc-funcs 技能,有則完整執行 /jsc:doc-funcs,否則結束。當使用者說建立/產生一個 docker action、從零做一個容器 action、幫我問完需求後生出 action、把需求做成 node docker action,或提到 code-action-docker 時觸發。不適用於:composite action(用 code-action-composite)、只整理既有 Dockerfile(用 code-image)、非 action 專案。 argument-hint: "[--action-dir <action 根目錄>] [--node-version ]"

code-action-docker — 問答式打造 Docker 容器 actionNode 主程式)+文件化

五階段 skill:先以問答收齊需求——action 名稱(階段 1)、輸入與輸出參數(階段 2)、流程目標並濃縮成一句話(階段 3)——再依標準實作目標(階段 4:Node.js、程式檔一律放 src/、統一訊息格式,並產生 action.ymlentrypoint.sh/最新 node 版本的 Dockerfile),最後檢查是否有 doc-funcs 技能(階段 5):有則完整執行 /jsc:doc-funcs,否則結束。

階段 動作
1. 詢問 action 名稱 向使用者詢問 action 名稱 → 寫入 action.ymlname
2. 詢問輸入與輸出參數 逐一收齊 inputsoutputs(名稱、description、required、default)→ description 盡量繁體中文、無亂碼
3. 詢問流程目標 詢問此 action 要達成什麼 → 整理並濃縮成一句話,經使用者確認後寫入 action.ymldescription(盡量繁體中文、無亂碼)
4. 實作目標 盡量以 Node.js 開發、程式檔一律放 src/;訊息詳細且格式統一為 [階段][等級][時間]: 訊息doc-funcs 規範);產生 action.ymlentrypoint.sh/最新 node 版本的 Dockerfile
5. 檢查 doc-funcs 有 doc-funcs 技能 → 完整執行 /jsc:doc-funcs;沒有 → 回報後結束

輸出規範(務必遵守)

  • 語言:所有面向使用者的輸出(問題、計畫、進度、總結)一律使用繁體中文(台灣用語);僅識別字、檔名、git/docker 指令、API 路徑、程式碼等技術標識保留原文,不可使用簡體字。
  • 編碼無亂碼:凡輸出含繁體中文、全形標點、emoji,一律 UTF-8(不含 BOM,不得出現問號方框或錯碼。產生的 action.ymlsrc/*.jsentrypoint.shDockerfileREADME.md 同樣需 UTF-8(不含 BOM);action.yml 內的中文 namedescription/參數說明必須能被 YAML 正確解析與顯示。
  • 問答原則:階段 13 是必要輸入,缺一不可;使用者已在呼叫時提供的答案不再重複詢問,未提供的必須以 AskUserQuestion(或明確反問)取得,不得臆測代答。階段 4 起除必要決策外直接執行到完成。
  • 不破壞既有工作:若 action 根目錄已存在 action.ymlsrc/entrypoint.shDockerfile,覆寫前先回報並確認;工作區有未提交變更時提醒使用者先 commit/備份;絕不 reset --hardcheckout -fclean,也不刪除使用者既有原始碼。
  • 不擴及無關檔案:本 skill 只產生/修改 action 根目錄內的 action.ymlsrc/entrypoint.shDockerfilepackage.json,以及階段 5 由 doc-funcs 流程處理的目標;排除 node_modules.git.docsbinobj/第三方依賴。

參數

格式:[--action-dir <action 根目錄>] [--node-version <node tag>]

  • --action-dir <action 根目錄>action 專案根目錄。省略時預設目前工作目錄
  • --node-version <node tag>Dockerfile 的 node base image tag(如 2222-alpinelts)。省略時預設使用最新 node 版本node:latest,見階段 4)。

階段 1~3 的答案(名稱、輸入輸出參數、目標)不設 CLI 參數;使用者若已在呼叫訊息中口述,直接採用、不再重問。


階段 1:詢問 action 名稱

向使用者詢問 action 名稱,用於 action.ymlname

  • 使用者已在呼叫時提供 → 直接採用並回報。
  • 未提供 → 以 AskUserQuestion(自由輸入為主,可依目錄名/repo 名給 2~3 個建議選項)詢問,不得自行編造
  • 名稱不得為空;可為繁體中文或英文,原樣寫入 name,不擅自翻譯或改寫。

階段 2:詢問輸入與輸出參數

向使用者收齊 action 的輸入(inputs)與輸出(outputs)參數,逐項確認:

  • 每個輸入:參數名稱(建議 kebab-case)、description盡量繁體中文、無亂碼)、是否必填(required)、預設值(default,選填)。
  • 每個輸出:參數名稱、description盡量繁體中文、無亂碼)。
  • 使用者明確表示「無輸入」或「無輸出」→ 對應區塊留空(省略該區塊),不硬造參數。
  • description 缺漏時反問補齊,不編造;使用者堅持留空則標示「(未提供)」。
  • 收齊後輸出整理表(名稱/必填/預設值/說明)讓使用者確認,再進入階段 3。

實作對應(供階段 4 使用):輸入在容器內以 INPUT_<大寫參數名> 環境變數取得(-_);輸出以附加 name=value$GITHUB_OUTPUT 檔案寫出。

階段 3:詢問執行此流程的目標

向使用者詢問此 action 要達成什麼目標(要處理什麼、產出什麼、成功/失敗準則):

  • 追問到「可實作」為止:不清楚的環節(資料來源、外部指令、失敗時的行為)必須問清,不得臆測
  • 將目標整理並濃縮成一句話(盡量繁體中文、無亂碼),向使用者確認後寫入 action.ymldescription
  • 完整目標描述(含細節與邊界)保留於回報與階段 4 的實作依據,不因濃縮而遺失。

階段 4:實作目標(Node.js、src/、統一訊息格式)

依階段 1~3 收齊的需求實作 action,遵守以下標準:

4.0 開發中需要參數時的來源優先序

實作過程中發現需要某個參數(例如 repo 資訊、token、環境設定)而階段 2 的 inputs 沒有時,依下列順序尋找來源,前者可用就不往後找

  1. ${{ gitea.* }} contextrunner 內建 context(如 gitea.repositorygitea.refgitea.actorgitea.token);docker action 執行期對應 runner 注入的 GITHUB_*GITEA_* 環境變數(如 GITHUB_REPOSITORYGITHUB_REF),主程式直接讀 process.env 即可。
  2. ${{ secrets.* }}repoorg 的 secrets(機敏值:token、密碼、金鑰)。
  3. ${{ vars.* }}repoorg 的 variables(非機敏設定值)。
  4. 以上都沒有 → 以 AskUserQuestion 詢問使用者是否要把該參數加入 inputs(加入則回到階段 2 規格補齊名稱/descriptionrequireddefault,並同步 action.yml);不得臆測預設值或硬編碼

注意:secrets.*vars.* 無法在 action.ymlinputs.default 直接引用,須由呼叫端 workflow 以 with:env: 傳入(如 with: token: ${{ secrets.MY_TOKEN }});採用這類來源時,在 README 使用範例中示範呼叫端如何帶入,機敏值一律不落地、不輸出明文(log 需遮蔽)。

4.1 盡量以 Node.js 開發,程式檔一律放 src/

  • 主程式與所有模組盡量以 Node.js 撰寫;只有目標必須依賴外部工具時,才以 child_processexecFileSyncspawnSync)在 Node 內呼叫,不另寫 shellpython 主程式。
  • 所有 .js.mjs.cjs一律放在 src/ 資料夾內,主程式入口統一為 src/index.js;需要相依套件時於 src/ 建立 package.jsonmain 指向入口檔),不擅自新增與目標無關的相依。
  • 輸入用 process.env.INPUT_* 讀取(必填缺漏 → 輸出 ERR 訊息並以非零 exit code 結束);輸出寫入 process.env.GITHUB_OUTPUT

4.2 盡量詳細輸出訊息,格式統一

  • 執行過程盡量詳細輸出:開始/結束、讀到的輸入、每個關鍵步驟、外部指令與結果、寫出的輸出、警告與錯誤。

  • 每一則訊息格式固定為(與 doc-funcs 第 6 步的 [{階段}?][{等級}][{時間}]: {訊息} 規範一致):

    [階段][等級][yyyy/MM/dd HH:mm:ss]: 訊息
    
    • 階段:該訊息所屬的流程階段名稱(如 讀取輸入執行寫出結果),選填;沒有階段時整個 [階段] 區塊移除,即 [等級][yyyy/MM/dd HH:mm:ss]: 訊息
    • 等級:必為 INFWRNERRTRCDBG 其中之一(一般資訊 INF、警告 WRN、錯誤 ERR、細部追蹤 TRC、除錯 DBG)。
    • 時間:台灣時區(Asia/Taipei),固定 yyyy/MM/dd HH:mm:ss
  • 一行一則訊息:每則訊息獨立一行輸出,不得多則併成一坨。

  • src/logger.js 實作共用 logger(產生時間戳、組合前綴、INF/WRN/ERR/TRC/DBG 各一個方法、可帶階段名稱),主程式一律經由它輸出;ERRconsole.error,其餘走 console.log

  • 錯誤處理:可預期錯誤輸出 ERR 訊息並 process.exit(1);未捕捉例外亦須被攔截(process.on('uncaughtException'/'unhandledRejection'))以 ERR 格式輸出後非零結束。

4.3 產生 action.yml

以階段 12 的答案組出 action.yml(中文內容 UTF-8、無亂碼):

name: <階段 1 的 action 名稱>
description: <階段 3 濃縮的一句話>
inputs:
  <參數名>:
    description: <階段 2 的說明(盡量繁體中文)>
    required: true|false
    default: <預設值(若有)>
outputs:
  <參數名>:
    description: <階段 2 的說明(盡量繁體中文)>
runs:
  using: docker
  image: Dockerfile
  entrypoint: entrypoint.sh

無輸入/輸出時省略對應區塊。

4.4 產生 entrypoint.sh

在 action 根目錄產生 entrypoint.sh:啟動 node 主程式前,先輸出 action 名稱/用途/更新時間,且每則輸出同樣遵守 4.2 訊息格式(階段用 啟動):

#!/bin/sh
set -e

# action 啟動訊息:名稱/用途/更新時間(此檔由 code-action-docker 產生)
echo "[啟動][INF][<產生當下 Asia/Taipei 時間>]: Action<action 名稱>"
echo "[啟動][INF][<產生當下 Asia/Taipei 時間>]: 用途:<action.yml 的 description>"
echo "[啟動][INF][<產生當下 Asia/Taipei 時間>]: 更新時間:<產生當下 Asia/Taipei 時間>"

# 啟動 node 主程式(以 exec 取代 shell,正確處理訊號與 exit code
exec node /action/src/index.js "$@"
  • 「更新時間」為產生此檔當下的時間戳(TZ='Asia/Taipei' date +'%Y/%m/%d %H:%M:%S'),寫成檔內固定字串;名稱/用途取自階段 13。
  • 賦予可執行權限:chmod +x entrypoint.sh(並於 git 標記為可執行)。

4.5 產生 Dockerfile(使用最新 node 版本)

在 action 根目錄產生 Dockerfilebase image 使用最新 node 版本,採多階段建置縮小最終映像,內容依 src/ 實作量身決定(有相依才裝、需要 OS 工具才 apt-get install,用不到的不硬塞):

# syntax=docker/dockerfile:1

# 1. 參數處理:node 版本以 ARG 注入(預設最新版;--node-version 可覆寫)
ARG NODE_VERSION=latest
ARG NODE_RUNTIME=slim

# ---- build 階段:安裝相依 ----
FROM node:${NODE_VERSION} AS build
WORKDIR /action

# 2. 安裝套件:先帶相依描述以利 layer 快取(有 lockfile 用 npm ci
COPY src/package*.json /action/src/
RUN if [ -f /action/src/package.json ]; then \
        cd /action/src && (npm ci --omit=dev || npm install --omit=dev); \
    fi

# 3. 複製檔案:帶入主程式與入口
COPY src/ /action/src/
COPY entrypoint.sh /action/entrypoint.sh

# 4. 執行程序:賦予 entrypoint 執行權限
RUN chmod +x /action/entrypoint.sh

# 5. 縮小映像檔:runtime 改用 slim 基底,只帶必要產物
FROM node:${NODE_RUNTIME} AS runtime
WORKDIR /action
COPY --from=build /action /action

# 6. 設定入口:以 entrypoint.sh 啟動 node 主程式
ENTRYPOINT ["/action/entrypoint.sh"]
  • 版號對齊:預設 build 基底 node:latest、runtime 基底 node:slim沒有 node:latest-slim 這個 tag,故以獨立 NODE_RUNTIME 參數帶入);帶 --node-version 22 時設 NODE_VERSION=22NODE_RUNTIME=22-slim
  • 主程式以 child_process 呼叫外部執行檔(如 gitopenssl)時,於 runtime 階段補 apt-get install 對應套件並清快取。
  • 自我檢查entrypoint.shnode /action/src/index.js 路徑須與 DockerfileWORKDIRCOPY 落點一致。

4.6 驗證

  • node --check src/*.js 驗證語法;有 package.json 時執行 npm install(或 npm ci)確認相依可解析。
  • 環境有 docker 時執行 docker build . 驗證映像可建置;無法執行時明確說明原因並標註風險。

階段 5:檢查是否有 doc-funcs 技能

實作完成後,檢查目前環境是否有 doc-funcs 技能(可用 skill 清單中是否存在 doc-funcs,含 /jsc:doc-funcs 等帶前綴形式):

  • → 以階段 4 的 action 根目錄為目標,完整執行 /jsc:doc-funcs 流程(判斷語言 → 掃描 function 與指令檔 → 建立 .docs/ 草稿 → 詢問使用者如何實作 → 寫回 → 保守優化 → 重建 README → 清理草稿 → 驗證)。doc-funcs 會涵蓋本次產出:src/ 內各 function 的 JSDoc、entrypoint.shDockerfile 逐行註解、重建 README;其「如何實作」詢問由使用者於該流程內裁示。本 skill 4.2 的訊息格式即 doc-funcs 第 6 步的 [{階段}?][{等級}][{時間}]: {訊息} 規範,兩者一致,doc-funcs 流程覆蓋指令檔時直接沿用。
  • 沒有 → 回報「未偵測到 doc-funcs 技能,略過文件化」後結束,不自行模擬 doc-funcs 流程。

總結

各階段執行後輸出:

  • 階段 13:action 名稱、輸入/輸出參數整理表、濃縮後的一句話 description。
  • 階段 4:產出檔案清單(action.ymlsrc/index.jssrc/logger.jssrc/package.json(若有)、entrypoint.shDockerfile)與各自相對路徑、採用的 node 版本、驗證結果(語法檢查/npmdocker build)。
  • 階段 5:是否偵測到 doc-funcs;有則附 doc-funcs 流程的處理結果(文件化的 function 與指令檔、重建的 README)。
  • 提醒使用者於提交前確認 entrypoint.sh 有可執行權限、容器能正確啟動。

呼叫方式

格式:[--action-dir <action 根目錄>] [--node-version <node tag>] — 全部可省略(根目錄預設目前工作目錄;node 版本預設最新)。

助理 呼叫
Claude Code / Antigravity /jsc:code-action-docker,或 /jsc:code-action-docker --action-dir ~/work/my-action --node-version 22
Codex $code-action-docker,或 $code-action-docker --action-dir ~/work/my-action,或用 /skills 選單
OpenCode 描述需求(如「幫我從零建一個 docker action:先問我名稱、輸入輸出參數與目標,用 node 實作放在 src/,訊息格式統一,最後跑 doc-funcs 補文件」)自動觸發