Files
cleanup-release/README.md
T
2026-07-11 12:26:31 +00:00

376 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Gitea Docker Container Action 範本
Docker container(容器)action 讓你把整個執行環境打包成一個 Docker image:action 在你指定的容器內執行,環境、相依套件、工具版本全部固定,跨機器結果一致。適合需要特定系統套件、編譯環境或非 JavaScript 語言撰寫的 action。
本文件整理 Docker container action `action.yml` 中**所有可用參數、說明與限制**,包含 `Dockerfile` 撰寫注意事項,並特別標出 **Gitea 與 GitHub Actions 的差異**
> 語法基準:Gitea Actions 以相容 GitHub Actions metadata 語法為目標,但兩者有明確差異(見「Gitea vs GitHub」章節)。Gitea 端的行為亦受底層 [`act`](https://gitea.com/gitea/act) runner 版本影響,實作前建議以測試機驗證。
>
> ⚠️ **平台限制**Docker container action **只能在 Linux runner 上執行**,且該 runner 必須安裝 Docker。Windows / macOS runner 不支援。
---
## 目錄
- [完整結構總覽](#完整結構總覽)
- [頂層參數](#頂層參數)
- [`inputs`(輸入參數)](#inputs輸入參數)
- [`outputs`(輸出)](#outputs輸出)
- [`runs`(執行設定)](#runs執行設定)
- [`Dockerfile` 撰寫注意事項](#dockerfile-撰寫注意事項)
- [Docker action 的限制與注意事項](#docker-action-的限制與注意事項)
- [Gitea vs GitHub Actions 差異](#gitea-vs-github-actions-差異)
- [本 repo 範例對照](#本-repo-範例對照)
- [參考來源](#參考來源)
---
## 完整結構總覽
```yaml
name: 'Gitea Docker Template' # 必填
description: 'Gitea Docker 範本' # 必填
author: 'Jeffery' # 選填
inputs: # 選填,定義輸入參數
message:
description: '輸入訊息'
required: false
default: 'Hello, World!'
outputs: # 選填,定義輸出(docker action 只宣告,不用 value
message:
description: '輸出訊息'
runs: # 必填
using: 'docker' # 必填,固定為 docker
image: 'Dockerfile' # 必填,本機 Dockerfile 或 docker://image
# entrypoint: '/entrypoint.sh' # 選填,覆寫 Dockerfile 的 ENTRYPOINT
# pre-entrypoint: '/setup.sh' # 選填,主程式前執行(另開容器)
# post-entrypoint: '/cleanup.sh' # 選填,主程式後執行(另開容器)
env: # 選填,容器內環境變數
GREETING: ${{ inputs.message }}
args: # 選填,傳給 ENTRYPOINT 的參數(取代 CMD
- ${{ inputs.message }}
branding: # 選填(Marketplace 用,Gitea 內部可省略)
icon: 'activity'
color: 'blue'
```
> 📌 `action.yml`(或 `action.yaml`)放在 action repo 根目錄;`image: 'Dockerfile'` 時,`Dockerfile` 也放在同一目錄。
---
## 頂層參數
| 參數 | 必填 | 說明 |
|------|------|------|
| `name` | ✅ | Action 名稱。 |
| `description` | ✅ | Action 簡短說明。 |
| `author` | ❌ | 作者名稱。 |
| `inputs` | ❌ | 輸入參數定義(見下)。 |
| `outputs` | ❌ | 輸出定義(見下)。 |
| `runs` | ✅ | 執行設定;docker 固定用 `using: 'docker'` + `image`。 |
| `branding` | ❌ | Marketplace 顯示用的 `icon``color``color``white`/`black`/`yellow`/`blue`/`green`/`orange`/`red`/`purple`/`gray-dark``icon` 為 Feather 圖示名稱)。 |
---
## `inputs`(輸入參數)
每個 input 是 `inputs.<input_id>` 底下的一組設定:
| 欄位 | 必填 | 說明 |
|------|------|------|
| `description` | ✅ | 參數說明。 |
| `required` | ❌ | 是否必填,布林值,預設 `false`。 |
| `default` | ❌ | 預設值;呼叫端沒傳時採用。**只能是字串**。 |
| `deprecationMessage` | ❌ | 標記此 input 已棄用,使用時發出警告訊息。 |
### Docker action 怎麼取用 input
這是 Docker action **與 composite action 最大的差異**。GitHub / Gitea 會把每個 input 轉成環境變數 `INPUT_<NAME>`
- 名稱轉大寫、空白換成底線。例:input `octocat-eye-color` → 環境變數 `INPUT_OCTOCAT_EYE_COLOR`
- input `message``INPUT_MESSAGE`
```yaml
inputs:
message:
description: '輸入訊息'
required: false
default: 'Hello, World!'
```
容器內就能直接讀:
```sh
echo "$INPUT_MESSAGE"
```
> ⚠️ **關鍵限制**`INPUT_*` 環境變數**只在 GitHub 官方 runner 保證自動注入**。若要跨環境(尤其 Gitea/`act`)可靠取值,官方建議**用 `args` 明確把 input 傳進容器**,或在 `runs.env` 自行對應一次(見下方 `runs.env`)。不要單靠 `INPUT_*` 而不驗證。
**呼叫端傳值**(用 `with`):
```yaml
- uses: ./
with:
message: 'Hi there'
```
> input 值一律是**字串**;數字、布林傳進來也會變字串(例如 `"true"`),比較時要留意。
---
## `outputs`(輸出)
Docker action 的 output **只需宣告 `description`****不用**(也不能)像 composite 那樣寫 `value`
| 欄位 | 必填 | 說明 |
|------|------|------|
| `description` | ✅ | 輸出說明。 |
**在容器內設定 output** → 寫入 `$GITHUB_OUTPUT` 檔案(該檔案路徑由 runner 掛載進容器):
```yaml
outputs:
message:
description: '輸出訊息'
```
`entrypoint.sh` 內:
```sh
echo "message=Hello from docker" >> "$GITHUB_OUTPUT"
```
**呼叫端取用 output**
```yaml
- id: docker-template
uses: ./
- run: echo "${{ steps.docker-template.outputs.message }}"
```
> 📦 output 大小限制:單一 job 的 output 上限 **1 MB**,整個 workflow run 所有 output 合計上限 **50 MB**。
---
## `runs`(執行設定)
Docker action 的核心。`using` 固定為 `docker`,其餘欄位:
| 欄位 | 必填 | 說明 |
|------|------|------|
| `using` | ✅ | 固定為 `'docker'`。 |
| `image` | ✅ | 要跑的 image:本機 `Dockerfile`(檔名必須正好是 `Dockerfile`),或遠端 image 用 `docker://` 前綴(如 `docker://alpine:3.20``docker://gcr.io/...`)。 |
| `entrypoint` | ❌ | 覆寫 Dockerfile 的 `ENTRYPOINT`Dockerfile 沒設時等於補上。建議用絕對路徑(如 `/entrypoint.sh`)。 |
| `pre-entrypoint` | ❌ | 在主 `entrypoint` **之前**執行的前置腳本。**會另開一個新容器**(同 base image),runtime 狀態與主容器不同——需保留的狀態要放進 workspace、`HOME`,或用 `STATE_` 變數傳遞。 |
| `post-entrypoint` | ❌ | 主 `entrypoint` 完成後執行的清理腳本,行為同 `pre-entrypoint`(另開容器)。 |
| `pre-if` | ❌ | 條件式,控制 `pre-entrypoint` 是否執行;預設一定跑。 |
| `post-if` | ❌ | 條件式,控制 `post-entrypoint` 是否執行;預設一定跑。 |
| `args` | ❌ | 字串陣列,啟動時傳給容器 `ENTRYPOINT` 的參數,**取代 Dockerfile 的 `CMD`**。 |
| `env` | ❌ | key/value map,容器啟動時設定的環境變數。 |
### `image`Dockerfile vs 遠端 image
```yaml
# 用本機 Dockerfile(每次執行前會 build
runs:
using: 'docker'
image: 'Dockerfile'
# 直接拉遠端 image(不用自帶 Dockerfile,啟動快)
runs:
using: 'docker'
image: 'docker://alpine:3.20'
```
### `args`:怎麼把值送進容器
`args` 取代 `CMD`,會被當作參數接在 `ENTRYPOINT` 後面:
```yaml
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.message }} # → entrypoint.sh 的 $1
- 'foo' # → $2
- 'bar' # → $3
```
> ⚠️ 若 `args` 裡放的是**環境變數字串**(如 `- $GREETING`),在 exec-form 的 `ENTRYPOINT` **不會被展開**。要展開變數,讓 entrypoint 走一層 shell`sh -c`),或改用 `runs.env` 傳值(見下)。
### `env`:明確傳環境變數(推薦)
比起依賴 `INPUT_*` 自動注入,用 `runs.env` 把 input 對應成自訂環境變數,跨環境最穩:
```yaml
runs:
using: 'docker'
image: 'Dockerfile'
env:
GREETING: ${{ inputs.message }}
```
容器內直接 `echo "$GREETING"`
---
## `Dockerfile` 撰寫注意事項
Docker action 的 `Dockerfile` 有幾條**強制或強烈建議**的規則,踩到會直接失敗或讀不到檔案:
1. **`FROM` 必須是第一行**
建議用官方 image + 明確版本標籤(如 `python:3.12-slim`),別用 `latest`Debian/Alpine 系列較穩。
2. **不要用 `USER`**
Docker action **必須以預設的 root 執行**。加了 `USER` 會導致**無法存取 `GITHUB_WORKSPACE`**(掛載進來的 repo 目錄)。
3. **不要用 `WORKDIR` 指定 entrypoint 位置**
runner 會自動把 `GITHUB_WORKSPACE` 掛載上來並設為工作目錄(路徑放在 `$GITHUB_WORKSPACE` 環境變數)。`entrypoint`/腳本一律用**絕對路徑**(如 `/entrypoint.sh`),不要依賴 `WORKDIR`
4. **`ENTRYPOINT` 用 exec formJSON 陣列)**
Docker 官方建議寫 `ENTRYPOINT ["/entrypoint.sh"]`
- **exec form**`args` 能正確以獨立參數傳入,但**不做環境變數展開**(`ENTRYPOINT ["echo", "$GITHUB_SHA"]` 印出的是字面字串)。
- **shell form**`ENTRYPOINT /entrypoint.sh` 會走 shell,可展開變數,但 `args` 傳遞行為不同。
- 需要在 entrypoint 展開變數時,用 `ENTRYPOINT ["sh", "-c", "echo $GITHUB_SHA"]`,或寫一支 `entrypoint.sh` 腳本自行處理。
5. **`CMD` 會被 `args` 蓋掉**
`action.yml``args` 取代 `CMD`。若 action 允許不帶 `args` 也能跑,就在 `Dockerfile``CMD` 提供預設值,並在 README 說明必要參數。
6. **`entrypoint.sh` 腳本規範**
- 開頭要有 shebang`#!/bin/sh`(或 `#!/bin/bash`,視 base image 而定)。
- 要可執行:`chmod +x entrypoint.sh`(並在 git 中保留執行權限)。
- 腳本會收到 `action.yml``args` 作為位置參數(`$1`, `$2`, …)。
---
## Docker action 的限制與注意事項
以下是實務上最容易踩雷的地方:
1. **只能跑在 Linux runner,且要有 Docker**
Windows / macOS runner 一律不支援 Docker container action。
2. **`INPUT_*` 不保證可靠,優先用 `args` / `env`**
GitHub 官方 runner 會自動注入 `INPUT_<NAME>`,但這在自架 / Gitea 環境未必成立。要穩定取 input,用 `args` 傳位置參數,或 `runs.env` 對應成自訂環境變數。
3. **`pre-entrypoint` / `post-entrypoint` 是「另開容器」**
它們**不共用主 entrypoint 容器的 runtime 狀態**(不是同一個容器內的前後腳本)。要跨階段保留狀態,寫進 `GITHUB_WORKSPACE``HOME`,或用 `STATE_` 變數。
4. **本機 `image: 'Dockerfile'` 每次會 build**
用本機 Dockerfile 時,執行前會先 build image,較慢;想加速可改用 `docker://` 拉預先建好的 image。
5. **只有 `GITHUB_WORKSPACE` 是持久且共用的**
容器內對檔案系統的改動,通常只有掛載進來的 `GITHUB_WORKSPACE` 會被後續 step 看到;其他路徑(如 `/tmp`)在跨 step / 跨 action 時不保證保留。
6. **exec-form `ENTRYPOINT` 不展開變數**
如上「Dockerfile 注意事項」第 4 點,需要展開就走 `sh -c` 或 entrypoint 腳本。
7. **`args` 是字串陣列,順序即位置參數**
`args` 的順序對應 entrypoint 的 `$1`, `$2`…;輸入值全是字串。
8. **不支援 `runs.steps`**
那是 composite action 專屬。Docker action 只有一個容器進入點(`entrypoint`)+選配的 pre/post。
---
## Gitea vs GitHub Actions 差異
Gitea Actions **不是** GitHub Actions 的 100% 複製品。撰寫 Docker action 時特別注意:
| 項目 | Gitea 行為 |
|------|-----------|
| **runner 需求** | 執行 Docker action 的 `act_runner` 主機必須裝 Docker,且 runner label 對應到支援容器的環境。`runs-on` 只接受 `runs-on: xyz``runs-on: [xyz]`,不支援複雜表達式。 |
| **`pre-entrypoint` / `post-entrypoint`** | ⚠️ 早期 `act` 版本**完全不執行** pre/post-entrypoint(見 [`nektos/act#2363`](https://github.com/nektos/act/issues/2363),已於 PR #2394 修復)。Gitea 內建的 `act` 版本若較舊可能仍無效——**使用前務必在測試機驗證**。 |
| **`INPUT_*` 注入** | 是否自動注入 `INPUT_<NAME>` 取決於 runner 版本,別假設一定有;優先用 `args` / `env` 明確傳值。 |
| **表達式函式** | 依官方比較文件,**僅保證支援 `always()`**`success()` / `failure()` / `cancelled()` / `hashFiles()` 等視 `act` runner 版本而定,寫 `if:`(含 `pre-if` / `post-if`)前先在測試機驗證。 |
| **`uses` 支援絕對 URL** | 可寫 `uses: https://github.com/owner/repo@v1``uses: http://your_gitea/owner/repo@branch`,不限同站 action。 |
| **Go actions** | Gitea 額外支援 `using: 'go'` 寫 Go actionGitHub 沒有);`docker` / `node` / `composite` 皆支援。 |
| **context 檢查較寬鬆** | Gitea 不檢查 context 可用性,`env` context 可用在比 GitHub 更多的位置(但不代表可攜,跨到 GitHub 會失敗)。 |
| **被忽略的 job 欄位** | `jobs.<job_id>.timeout-minutes``jobs.<job_id>.continue-on-error``jobs.<job_id>.environment` 會被忽略。 |
| **annotations / problem matchers** | 不支援,會被忽略。 |
| **`permissions` scope** | 支援 `permissions`,但沒有 GitHub 專屬的 `statuses` / `checks` / `deployments` / `id-token` / `security-events` / `pages`Gitea 有自己的 `code` / `releases` / `wiki` / `projects`。 |
> 上表以 Gitea 官方文件為準;`act` runner 持續更新,部分限制(尤其表達式函式與 pre/post-entrypoint)可能隨版本放寬,仍以你環境的實測為準。
---
## 本 repo 範例對照
一個典型 Docker container action 由三個檔案組成,放在 repo 根目錄:
**1. `action.yml`** — action 定義
```yaml
name: 'Gitea Docker Template'
description: 'Gitea Docker 範本'
author: 'Jeffery'
inputs:
message:
description: '輸入訊息'
required: false
default: 'Hello, World!'
outputs:
message:
description: '輸出訊息'
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.message }}
```
**2. `Dockerfile`** — 執行環境
```dockerfile
FROM alpine:3.20
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
```
**3. `entrypoint.sh`** — 主程式
```sh
#!/bin/sh
set -e
# $1 來自 action.yml 的 args(呼叫端 with.message
MESSAGE="$1"
echo "Docker action 收到訊息:$MESSAGE"
# 設定 output 供後續 step 使用
echo "message=$MESSAGE" >> "$GITHUB_OUTPUT"
```
**呼叫端**workflow)用法:
```yaml
- name: 3. Testing
id: docker-template
uses: ./
with:
message: 'Hi there'
- name: 4. Feedback
run: echo "${{ steps.docker-template.outputs.message }}"
```
> ️ 本 repo 目前的 [`action.yml`](./action.yml) 仍為 composite 範本;要改為 Docker action,依上方三件套調整 `action.yml` 並新增 `Dockerfile`、`entrypoint.sh`。
---
## 參考來源
- [GitHub Actions — Metadata syntax for actions](https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax)
- [GitHub Actions — Dockerfile support for GitHub Actions](https://docs.github.com/en/actions/sharing-automations/creating-actions/dockerfile-support-for-github-actions)
- [GitHub Actions — Creating a Docker container action](https://docs.github.com/en/actions/tutorials/creating-a-docker-container-action)
- [Gitea — Compared to GitHub Actions](https://docs.gitea.com/usage/actions/comparison)
- [Gitea — Actions FAQ](https://docs.gitea.com/usage/actions/faq)
- [nektos/act#2363 — pre/post-entrypoint of Docker actions not executed](https://github.com/nektos/act/issues/2363)