No description
  • Python 55.4%
  • Shell 44.6%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-03 17:17:57 +08:00
tests feat: expose immutable registry digest outputs 2026-10-03 17:17:57 +08:00
.gitignore feat: expose immutable registry digest outputs 2026-10-03 17:17:57 +08:00
action.yaml feat: expose immutable registry digest outputs 2026-10-03 17:17:57 +08:00
build-push.sh feat: expose immutable registry digest outputs 2026-10-03 17:17:57 +08:00
README.md feat: expose immutable registry digest outputs 2026-10-03 17:17:57 +08:00

forgejo-docker-build-push

Forgejo Actions 用的 Composite Action,用來建置 Docker image 並推送到 Forgejo Container Registry。

此 Action 會自動:

  • 使用目前 Forgejo instance 作為 Container Registry
  • 根據 FORGEJO_REPOSITORY 自動產生 image repository
  • 將 image repository 轉成小寫
  • 使用 Forgejo username + PAT 登入 Container Registry
  • 為每次執行建立獨立的 DOCKER_CONFIG
  • 執行 docker build
  • 自動產生並推送 image tags
  • 執行完成後登出 registry
  • 清除暫存 Docker credential
  • 支援自訂 registry、image、tags、Dockerfile 與 build context

Requirements

Runner 必須能直接執行 Docker CLI,例如:

runs-on: docker-build

對應的 Forgejo Runner label 可以使用 host executor:

labels:
  - 'docker-build:host'

Runner 主機必須已安裝 Docker,且執行 Forgejo Runner 的 Linux 使用者必須能存取 Docker daemon。

例如:

sudo usermod -aG docker runner

確認:

sudo -u runner docker info

可以正常執行。

Configure Forgejo Actions credentials

建議在 Forgejo 的 User Settings → Actions 設定共用的 registry credential。

Variable

在:

/user/settings/actions/variables

建立:

REGISTRY_USERNAME

值為建立 PAT 的 Forgejo 使用者名稱。

例如:

REGISTRY_USERNAME=simbafs

Secret

在:

/user/settings/actions/secrets

建立:

REGISTRY_TOKEN

值為該 Forgejo 使用者建立的 Personal Access Token。

PAT 必須具有推送 package / Container Registry image 所需的權限。

最後會得到:

User Actions Variables:
  REGISTRY_USERNAME=simbafs

User Actions Secrets:
  REGISTRY_TOKEN=<PAT>

REGISTRY_USERNAME 不屬於敏感資訊,因此使用 Actions Variable。

REGISTRY_TOKEN 屬於 credential,因此必須使用 Actions Secret。

Usage

最基本的使用方式:

name: Build container image

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build:
    runs-on: docker-build

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Build and push
        uses: https://git.1li.tw/actions/[email protected]
        with:
          username: ${{ vars.REGISTRY_USERNAME }}
          pat: ${{ secrets.REGISTRY_TOKEN }}

假設 repository 為:

simbafs/example

Forgejo URL 為:

https://git.1li.tw

則預設 image repository 為:

git.1li.tw/simbafs/example

Authentication

此 Action 不使用 workflow 內建的 FORGEJO_TOKEN 作為 Container Registry credential。

Registry authentication 使用:

username = 建立 PAT 的 Forgejo 使用者
password = Forgejo PAT

例如:

with:
  username: ${{ vars.REGISTRY_USERNAME }}
  pat: ${{ secrets.REGISTRY_TOKEN }}

username 不一定等於 repository owner。

例如 repository 位於:

myorg/example

但 PAT 是由:

simbafs

建立,則 authentication 仍然是:

username = simbafs
PAT      = simbafs 的 PAT

而 image 可以是:

git.1li.tw/myorg/example:latest

前提是該 Forgejo 使用者有對應的 package 寫入權限。

Docker credential isolation

此 Action 不會使用:

~/.docker/config.json

每次 Action 執行都會建立獨立的暫存 DOCKER_CONFIG。

概念如下:

workflow run
    │
    ├── create temporary DOCKER_CONFIG
    │
    ├── docker login
    │
    ├── docker build
    │
    ├── docker push
    │
    ├── docker logout
    │
    └── remove temporary DOCKER_CONFIG

例如同一台 runner 同時執行兩個 job:

job A
└── /tmp/forgejo-docker....A/
    └── config.json

job B
└── /tmp/forgejo-docker....B/
    └── config.json

兩個 job 不會共用:

/home/runner/.docker/config.json

Action 結束後,暫存 Docker config 也會被刪除。

Default image name

如果沒有指定 image,Action 會使用:

FORGEJO_REPOSITORY

並搭配目前 Forgejo instance 的 hostname。

例如:

FORGEJO_SERVER_URL=https://git.1li.tw
FORGEJO_REPOSITORY=Simbafs/MyApp

會得到:

git.1li.tw/simbafs/myapp

Repository path 會自動轉成小寫。

Default tags

若沒有指定 tags,Action 會根據 Forgejo event 自動決定 tags。

Branch push

例如 push 到:

main

預設推送:

git.1li.tw/simbafs/example:latest
git.1li.tw/simbafs/example:<commit-sha>

例如:

git.1li.tw/simbafs/example:latest
git.1li.tw/simbafs/example:4a71c989bf0a...

Tag push

例如:

git tag v1.2.3
git push origin v1.2.3

預設推送:

git.1li.tw/simbafs/example:v1.2.3
git.1li.tw/simbafs/example:latest

Inputs

username

Required: true

建立 Forgejo PAT 的使用者名稱。

建議使用 user-level Actions Variable:

username: ${{ vars.REGISTRY_USERNAME }}

例如:

simbafs

pat

Required: true

具有 Container Registry / package write 權限的 Forgejo PAT。

建議使用 user-level Actions Secret:

pat: ${{ secrets.REGISTRY_TOKEN }}

PAT 只會透過:

docker login --password-stdin

傳給 Docker。


registry

Required: false

預設使用目前的 Forgejo instance。

若未指定,Action 會從:

FORGEJO_SERVER_URL

取得 registry hostname。

例如:

registry: registry.example.com

也可以傳入:

registry: https://registry.example.com

URL scheme 會自動移除。


image

Required: false

預設:

FORGEJO_REPOSITORY

例如目前 repository:

simbafs/example

會使用:

git.1li.tw/simbafs/example

也可以指定不同的 image repository:

image: simbafs/custom-image

結果:

git.1li.tw/simbafs/custom-image

通常不需要在 image 中加入 registry hostname。


tags

Required: false

自訂要 build 與 push 的 tags。

使用 newline-separated 格式:

tags: |
  latest
  stable
  1.2.3

將會推送:

git.1li.tw/owner/repository:latest
git.1li.tw/owner/repository:stable
git.1li.tw/owner/repository:1.2.3

指定 tags 後,不會使用預設的 branch / tag tagging 規則。


context

Required: false

Default:

.

Docker build context。

例如:

context: ./src

等同:

docker build ./src

dockerfile

Required: false

Default:

Dockerfile

例如:

dockerfile: docker/production.Dockerfile

等同:

docker build \
  --file docker/production.Dockerfile \
  .

Outputs

以下新增輸出需使用包含此變更的新版本(預定 v1.1.0,發布後才可引用):

  • digest:本次成功推送的 registry manifest digest,例如 sha256:…。
  • image-ref:完整的 registry/owner/app@sha256:…,可直接交給 manifest PR action。
  • image:保留既有 repository 輸出,並修正 composite action output 映射。

每次 build 先推送獨立的 ci-* tag,取得與本次 build 綁定的 digest,再發布原本的 tags。 所有 push 成功且 digest 一致才輸出結果;同 host 的 alias tag/push 以 flock 序列化。 Linux runner 需有 flock、sha256sum、sed 與 tee。執行結束會移除獨立 local tag; registry 的 ci-* tag 保留作為該 digest 的引用,清理時需保留部署與回復所需版本。

搭配 forgejo-k8s-image-pr 時,將 ${{ steps.image.outputs.image-ref }} 傳入其 image-ref。 本 action 不直接取得 k8s repo PAT,也不建立 PR。

image

完整的 image repository,不包含 tag。

例如:

git.1li.tw/simbafs/example

使用方式:

- name: Build and push
  id: image
  uses: https://git.1li.tw/actions/[email protected]
  with:
    username: ${{ vars.REGISTRY_USERNAME }}
    pat: ${{ secrets.REGISTRY_TOKEN }}

- name: Show image
  run: |
    echo "${{ steps.image.outputs.image }}"

Examples

Build on every push to main

name: Build container

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: docker-build

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Build and push
        uses: https://git.1li.tw/actions/[email protected]
        with:
          username: ${{ vars.REGISTRY_USERNAME }}
          pat: ${{ secrets.REGISTRY_TOKEN }}

預設推送:

:latest
:<commit-sha>

Publish image from Git tags

name: Publish release image

on:
  push:
    tags:
      - 'v*.*.*'

jobs:
  publish:
    runs-on: docker-build

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Build and push
        uses: https://git.1li.tw/actions/[email protected]
        with:
          username: ${{ vars.REGISTRY_USERNAME }}
          pat: ${{ secrets.REGISTRY_TOKEN }}

例如 push:

v1.2.3

後會產生:

:v1.2.3
:latest

Build from main and release tags

name: Build container

on:
  push:
    branches:
      - main
    tags:
      - 'v*.*.*'
  workflow_dispatch:

jobs:
  build:
    runs-on: docker-build

    steps:
      - name: Checkout
        uses: actions/checkout@v6

      - name: Build and push
        uses: https://git.1li.tw/actions/[email protected]
        with:
          username: ${{ vars.REGISTRY_USERNAME }}
          pat: ${{ secrets.REGISTRY_TOKEN }}

Push 到 main:

:latest
:<commit-sha>

Push tag v1.2.3:

:v1.2.3
:latest

Custom image name

- name: Build and push
  uses: https://git.1li.tw/actions/[email protected]
  with:
    username: ${{ vars.REGISTRY_USERNAME }}
    pat: ${{ secrets.REGISTRY_TOKEN }}
    image: simbafs/backend

結果:

git.1li.tw/simbafs/backend

Custom tags

- name: Build and push
  uses: https://git.1li.tw/actions/[email protected]
  with:
    username: ${{ vars.REGISTRY_USERNAME }}
    pat: ${{ secrets.REGISTRY_TOKEN }}
    tags: |
      staging
      build-${{ forgejo.run_number }}

Custom Dockerfile

- name: Build and push
  uses: https://git.1li.tw/actions/[email protected]
  with:
    username: ${{ vars.REGISTRY_USERNAME }}
    pat: ${{ secrets.REGISTRY_TOKEN }}
    dockerfile: docker/production.Dockerfile
    context: .

Versioning

目前建議固定使用:

uses: https://git.1li.tw/actions/[email protected]

v1.0.0 是固定的 Git tag,因此 workflow 不會因為 Action repository 後續更新而自動改變行為。

未來若發布新版本,例如:

v1.0.1
v1.1.0
v2.0.0

使用端應明確修改版本:

uses: https://git.1li.tw/actions/[email protected]

這樣可以確保 workflow 使用的 Action 版本明確且可重現。

如果需要更嚴格的 supply-chain control,也可以直接固定完整 Git commit SHA。

Security

此 Action 會在 runner 上執行:

docker login
docker build
docker push

若 runner 使用:

docker-build:host

這類 host executor,workflow command 會直接以 Forgejo Runner 的 Linux 使用者身分執行。

如果該使用者具有 Docker daemon 存取權,例如屬於:

docker

group,則 workflow 對 runner 主機具有非常高的權限。

因此只應允許受信任的 repository 與使用者修改或觸發這類 workflow。

另外:

  • REGISTRY_TOKEN 應遵循最小權限原則。
  • 不應將 PAT 直接寫在 workflow YAML。
  • 不應將 PAT 放在 Actions Variable。
  • Action 不會把 registry credential 留在 runner 的永久 Docker config。
  • 每次執行使用獨立暫存 DOCKER_CONFIG。
  • Action 結束後會執行 logout 並移除暫存 credential。

License

依此 repository 所使用的 License 為準。