14 KiB
name: code-action-docker
description: 以互動問答從零打造 Gitea/GitHub「Docker 容器 action」:(1) 詢問 action 名稱(用於 action.yml 的 name);(2) 詢問輸入與輸出參數及其 description(盡量繁體中文、無亂碼);(3) 詢問執行此流程的目標,整理濃縮成一句話(用於 action.yml 的 description,盡量繁體中文、無亂碼);(4) 依標準實作目標——盡量以 Node.js 開發、程式檔一律放 src/、盡量詳細輸出訊息且格式統一為 [yyyy/MM/dd HH:mm:ss][階段][等級]: 訊息(無階段則移除該 [],等級為 INF/WRN/ERR/TRC/DBG),並產生 action.yml/entrypoint.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 容器 action(Node 主程式)+文件化
五階段 skill:先以問答收齊需求——action 名稱(階段 1)、輸入與輸出參數(階段 2)、流程目標並濃縮成一句話(階段 3)——再依標準實作目標(階段 4:Node.js、程式檔一律放 src/、統一訊息格式,並產生 action.yml/entrypoint.sh/最新 node 版本的 Dockerfile),最後檢查是否有 doc-funcs 技能(階段 5):有則完整執行 /jsc:doc-funcs,否則結束。
| 階段 | 動作 |
|---|---|
| 1. 詢問 action 名稱 | 向使用者詢問 action 名稱 → 寫入 action.yml 的 name |
| 2. 詢問輸入與輸出參數 | 逐一收齊 inputs/outputs(名稱、description、required、default)→ description 盡量繁體中文、無亂碼 |
| 3. 詢問流程目標 | 詢問此 action 要達成什麼 → 整理並濃縮成一句話,經使用者確認後寫入 action.yml 的 description(盡量繁體中文、無亂碼) |
| 4. 實作目標 | 盡量以 Node.js 開發、程式檔一律放 src/;訊息詳細且格式統一為 [yyyy/MM/dd HH:mm:ss][階段][等級]: 訊息;產生 action.yml/entrypoint.sh/最新 node 版本的 Dockerfile |
| 5. 檢查 doc-funcs | 有 doc-funcs 技能 → 完整執行 /jsc:doc-funcs;沒有 → 回報後結束 |
輸出規範(務必遵守)
- 語言:所有面向使用者的輸出(問題、計畫、進度、總結)一律使用繁體中文(台灣用語);僅識別字、檔名、git/docker 指令、API 路徑、程式碼等技術標識保留原文,不可使用簡體字。
- 編碼無亂碼:凡輸出含繁體中文、全形標點、emoji,一律 UTF-8(不含 BOM),不得出現問號方框或錯碼。產生的
action.yml、src/*.js、entrypoint.sh、Dockerfile、README.md同樣需 UTF-8(不含 BOM);action.yml內的中文name/description/參數說明必須能被 YAML 正確解析與顯示。 - 問答原則:階段 1~3 是必要輸入,缺一不可;使用者已在呼叫時提供的答案不再重複詢問,未提供的必須以
AskUserQuestion(或明確反問)取得,不得臆測代答。階段 4 起除必要決策外直接執行到完成。 - 不破壞既有工作:若 action 根目錄已存在
action.yml/src//entrypoint.sh/Dockerfile,覆寫前先回報並確認;工作區有未提交變更時提醒使用者先 commit/備份;絕不reset --hard/checkout -f/clean,也不刪除使用者既有原始碼。 - 不擴及無關檔案:本 skill 只產生/修改 action 根目錄內的
action.yml、src/、entrypoint.sh、Dockerfile、package.json,以及階段 5 由 doc-funcs 流程處理的目標;排除node_modules/.git/.docs/bin/obj/第三方依賴。
參數
格式:[--action-dir <action 根目錄>] [--node-version <node tag>]
--action-dir <action 根目錄>:action 專案根目錄。省略時預設目前工作目錄。--node-version <node tag>:Dockerfile的 node base image tag(如22、22-alpine、lts)。省略時預設使用最新 node 版本(node:latest,見階段 4)。
階段 1~3 的答案(名稱、輸入輸出參數、目標)不設 CLI 參數;使用者若已在呼叫訊息中口述,直接採用、不再重問。
階段 1:詢問 action 名稱
向使用者詢問 action 名稱,用於 action.yml 的 name:
- 使用者已在呼叫時提供 → 直接採用並回報。
- 未提供 → 以
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.yml的description。 - 完整目標描述(含細節與邊界)保留於回報與階段 4 的實作依據,不因濃縮而遺失。
階段 4:實作目標(Node.js、src/、統一訊息格式)
依階段 1~3 收齊的需求實作 action,遵守以下標準:
4.1 盡量以 Node.js 開發,程式檔一律放 src/
- 主程式與所有模組盡量以 Node.js 撰寫;只有目標必須依賴外部工具時,才以
child_process(execFileSync/spawnSync)在 Node 內呼叫,不另寫 shell/python 主程式。 - 所有
.js/.mjs/.cjs一律放在src/資料夾內,主程式入口統一為src/index.js;需要相依套件時於src/建立package.json(main指向入口檔),不擅自新增與目標無關的相依。 - 輸入用
process.env.INPUT_*讀取(必填缺漏 → 輸出ERR訊息並以非零 exit code 結束);輸出寫入process.env.GITHUB_OUTPUT。
4.2 盡量詳細輸出訊息,格式統一
-
執行過程盡量詳細輸出:開始/結束、讀到的輸入、每個關鍵步驟、外部指令與結果、寫出的輸出、警告與錯誤。
-
每一則訊息格式固定為:
[yyyy/MM/dd HH:mm:ss][階段][等級]: 訊息- 時間:台灣時區(Asia/Taipei),固定
yyyy/MM/dd HH:mm:ss。 - 階段:該訊息所屬的流程階段名稱(如
讀取輸入、執行、寫出結果);沒有階段時整個[階段]區塊移除,即[yyyy/MM/dd HH:mm:ss][等級]: 訊息。 - 等級:必為
INF/WRN/ERR/TRC/DBG其中之一(一般資訊 INF、警告 WRN、錯誤 ERR、細部追蹤 TRC、除錯 DBG)。
- 時間:台灣時區(Asia/Taipei),固定
-
一行一則訊息:每則訊息獨立一行輸出,不得多則併成一坨。
-
在
src/logger.js實作共用 logger(產生時間戳、組合前綴、INF/WRN/ERR/TRC/DBG各一個方法、可帶階段名稱),主程式一律經由它輸出;ERR走console.error,其餘走console.log。 -
錯誤處理:可預期錯誤輸出
ERR訊息並process.exit(1);未捕捉例外亦須被攔截(process.on('uncaughtException'/'unhandledRejection'))以ERR格式輸出後非零結束。
4.3 產生 action.yml
以階段 1~2 的答案組出 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 "[<產生當下 Asia/Taipei 時間>][啟動][INF]: Action:<action 名稱>"
echo "[<產生當下 Asia/Taipei 時間>][啟動][INF]: 用途:<action.yml 的 description>"
echo "[<產生當下 Asia/Taipei 時間>][啟動][INF]: 更新時間:<產生當下 Asia/Taipei 時間>"
# 啟動 node 主程式(以 exec 取代 shell,正確處理訊號與 exit code)
exec node /action/src/index.js "$@"
- 「更新時間」為產生此檔當下的時間戳(
TZ='Asia/Taipei' date +'%Y/%m/%d %H:%M:%S'),寫成檔內固定字串;名稱/用途取自階段 1/3。 - 賦予可執行權限:
chmod +x entrypoint.sh(並於 git 標記為可執行)。
4.5 產生 Dockerfile(使用最新 node 版本)
在 action 根目錄產生 Dockerfile,base 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=22、NODE_RUNTIME=22-slim。 - 主程式以
child_process呼叫外部執行檔(如git、openssl)時,於 runtime 階段補apt-get install對應套件並清快取。 - 自我檢查:
entrypoint.sh的node /action/src/index.js路徑須與Dockerfile的WORKDIR/COPY落點一致。
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.sh/Dockerfile逐行註解、重建 README;其「如何實作」詢問由使用者於該流程內裁示。既有訊息一律維持本 skill 4.2 的[yyyy/MM/dd HH:mm:ss][階段][等級]: 訊息格式,不得被改寫成其他欄位順序。 - 沒有 → 回報「未偵測到 doc-funcs 技能,略過文件化」後結束,不自行模擬 doc-funcs 流程。
總結
各階段執行後輸出:
- 階段 1~3:action 名稱、輸入/輸出參數整理表、濃縮後的一句話 description。
- 階段 4:產出檔案清單(
action.yml、src/index.js、src/logger.js、src/package.json(若有)、entrypoint.sh、Dockerfile)與各自相對路徑、採用的 node 版本、驗證結果(語法檢查/npm/docker 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 補文件」)自動觸發 |