generate-github-workflow

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Skill: Generate GitHub Workflow

技能:生成GitHub Workflow

Purpose

目标

Produce GitHub Actions workflow files that satisfy this skill’s Appendix A: Workflow output contract for a wide range of software projects. Standardized structure, triggers, and security reduce CI/CD setup cost and improve maintainability and auditability while avoiding common security and permission issues. This skill only produces workflow YAML; it does not chain to documentation or rule skills. If the user later needs README or AGENTS.md updates, invoke those skills separately.

生成符合本技能**《附录A:工作流输出规范》GitHub Actions工作流文件**,适用于各类软件项目。标准化的结构、触发器和安全设置降低了CI/CD的搭建成本,提升了可维护性和可审计性,同时避免常见的安全和权限问题。本技能仅生成工作流YAML文件,不关联文档或规则类技能。如果用户后续需要更新README或AGENTS.md,请单独调用对应技能。

Use Cases

使用场景

  • New project setup: Add CI (build, test, lint) or PR-check workflows to a new repo.
  • Unified standards: Align workflow style and naming across many repos for ops and audit.
  • Fill gaps: Add missing CI/release/scheduled workflows to legacy projects, with minimal permissions and pinned versions.
  • Scenario-based: Generate YAML for a given scenario (e.g. “run tests only on PR”, “build and publish on tag”).
When to use: When the user or project needs to “create or add GitHub workflows for the current or specified project.”
Scope: This skill’s output follows the embedded Appendix A (narrow triggers, minimal permissions, pinned versions, auditable). Generic templates (e.g. skills.sh
github-actions-templates
) are more general; this skill emphasizes security and maintainability.

  • 新项目搭建:为新仓库添加CI(构建、测试、代码检查)或PR检查工作流。
  • 统一标准:在多个仓库中对齐工作流的风格和命名,便于运维与审计。
  • 填补空白:为遗留项目添加缺失的CI/发布/定时工作流,遵循最小权限原则并固定版本。
  • 场景定制:针对特定场景生成YAML(例如“仅在PR时运行测试”、“打标签时构建并发布”)。
适用时机:当用户或项目需要“为当前或指定项目创建或添加GitHub工作流”时。
范围:本技能的输出严格遵循内置的附录A(窄触发器、最小权限、固定版本、可审计)。通用模板(如skills.sh的
github-actions-templates
)更偏向通用化,而本技能侧重安全性与可维护性。

Behavior

行为规范

Principles

核心原则

  • Appendix A is authoritative: Output YAML must satisfy Appendix A (structure, naming, security, maintainability).
  • Narrow triggers:
    on
    must specify branches/paths/tags; avoid triggering on every push. Common pattern:
    push
    /
    pull_request
    with
    branches
    or
    paths
    . Release workflows must trigger only on version tags (e.g.
    push: tags: ['v*']
    ) and live in a separate file from CI.
  • Minimal permissions: When the workflow needs repo write, PR, or Secrets, set
    permissions
    at workflow or job level to the minimum required; e.g. CI
    contents: read
    , release
    contents: write
    ,
    packages: write
    ; avoid
    all
    .
  • Pinned versions: Pin third-party actions (commit SHA or major-version tag); do not use
    @master
    or unpinned refs; prefer specific versions for security/scan actions (e.g. Trivy).
  • 附录A为权威标准:输出的YAML必须符合附录A的要求(结构、命名、安全、可维护性)。
  • 窄触发器
    on
    字段必须指定分支/路径/标签;避免每次推送都触发工作流。常见模式:
    push
    /
    pull_request
    搭配
    branches
    paths
    发布工作流必须仅在版本标签(如
    push: tags: ['v*']
    )时触发,且与CI工作流分文件存放。
  • 最小权限:当工作流需要仓库写入、PR操作或访问Secrets时,在工作流或任务级别设置
    permissions
    为所需的最小权限;例如CI设置
    contents: read
    ,发布设置
    contents: write
    packages: write
    ;避免使用
    all
    权限。
  • 固定版本:第三方Action必须固定版本(提交SHA或大版本标签);禁止使用
    @master
    或未固定的引用;安全/扫描类Action优先使用特定版本(如Trivy)。

Tone and style

语气与风格

  • Use objective, technical language; keep workflow and step
    name
    short and readable for the Actions log.
  • Match the project stack: choose runner, package manager, and build commands by project type (Node/Python/Go/Rust) and existing conventions; if the project already has workflows, align naming and style.
  • 使用客观的技术语言;工作流和步骤的
    name
    需简短易读,便于在Actions日志中查看。
  • 匹配项目技术栈:根据项目类型(Node/Python/Go/Rust)和现有约定选择运行器、包管理器和构建命令;如果项目已有工作流,需对齐命名与风格。

Input-driven

输入驱动

  • Use the user’s scenario (e.g. “CI: run tests on PR”, “Release: build and upload on tag”) and stack (language, package manager, test/build commands) to generate the workflow; use sensible placeholders when information is missing and mark them for replacement; do not invent commands or paths.
  • 根据用户提供的场景(如“CI:PR时运行测试”、“发布:打标签时构建并上传”)和技术栈(语言、包管理器、测试/构建/发布命令)生成工作流;信息缺失时使用合理占位符并标记需替换;禁止凭空生成命令或路径。

Interaction

交互规则

  • Confirm before write: After generating YAML, list required notes (placeholders, branch names, Secret names the user must set), then ask for confirmation; do not write to
    .github/workflows/
    or commit without user confirmation.
  • Multiple files / release: If generating several workflows (e.g. CI + Release) or using write permissions (
    contents: write
    ,
    packages: write
    ), list files to be created/overwritten and permission scope, then confirm before writing.
  • Conflicts: If the target path already has a workflow with the same or overlapping purpose, warn and ask whether to overwrite or save elsewhere; do not overwrite silently.

  • 写入前确认:生成YAML后,列出必填注意事项(占位符、分支名称、用户需设置的Secret名称),然后请求用户确认;未获确认前,不得写入
    .github/workflows/
    目录或提交代码。
  • 多文件/发布场景:若生成多个工作流(如CI + 发布)或需使用写入权限(
    contents: write
    packages: write
    ),需列出待创建/覆盖的文件及权限范围,然后请求确认。
  • 冲突处理:若目标路径已存在用途相同或重叠的工作流,需发出警告并询问用户是覆盖还是保存到其他位置;禁止静默覆盖。

Input & Output

输入与输出

Input

输入

  • Scenario: Purpose (CI, PR check, release, scheduled, matrix).
  • Stack: Language and version (e.g. Node 20, Python 3.11, Go 1.21), package manager (npm/pnpm/yarn, pip, cargo), test/build/release commands.
  • Triggers: Branches (e.g.
    main
    ,
    develop
    ), path filters, optional
    workflow_dispatch
    .
  • Target path: Where to write the file(s), default
    .github/workflows/
    under project root; for multiple workflows, specify each filename (e.g.
    ci.yml
    ,
    release.yml
    ).
  • 场景:用途(CI、PR检查、发布、定时、矩阵任务)。
  • 技术栈:语言及版本(如Node 20、Python 3.11、Go 1.21)、包管理器(npm/pnpm/yarn、pip、cargo)、测试/构建/发布命令。
  • 触发器:分支(如
    main
    develop
    )、路径过滤器、可选的
    workflow_dispatch
  • 目标路径:文件写入位置,默认是项目根目录下的
    .github/workflows/
    ;若生成多个工作流,需指定每个文件名(如
    ci.yml
    release.yml
    )。

Output

输出

  • Workflow YAML: Full file content conforming to Appendix A, ready to write to
    .github/workflows/<name>.yml
    .
  • Notes: List placeholders (e.g.
    npm run test
    , branch
    main
    ), Secret names, and any items the user must configure.

  • 工作流YAML:完整的文件内容,符合附录A要求,可直接写入
    .github/workflows/<name>.yml
  • 注意事项:列出占位符(如
    npm run test
    、分支
    main
    )、Secret名称及用户需配置的所有项。

Restrictions

限制条件

  • Do not violate Appendix A: Output must have
    name
    ,
    on
    ,
    jobs
    , and each job must have
    runs-on
    and
    steps
    ; do not use unpinned third-party actions or hardcoded secrets.
  • Do not over-trigger: Do not use bare
    on: push
    with no branch/path filter unless the user explicitly requests it.
  • Do not invent commands: Use placeholders for unknown test/build/release commands and mark “replace with actual command”; do not invent scripts or paths.
  • Do not ignore existing workflows: If the project already has
    .github/workflows/
    , align naming and style and avoid duplication or conflict.
  • Do not duplicate build logic: If the project uses GoReleaser, Dockerfile, etc. for build and image shape, the workflow only triggers, logs in, and passes args (e.g.
    GITHUB_TOKEN
    ,
    BUILDX_BUILDER
    ); do not reimplement that logic.

  • 不得违反附录A:输出必须包含
    name
    on
    jobs
    ,每个任务必须包含
    runs-on
    steps
    ;禁止使用未固定版本的第三方Action或硬编码密钥。
  • 避免过度触发:除非用户明确要求,否则禁止使用无分支/路径过滤的
    on: push
  • 禁止凭空生成命令:未知的测试/构建/发布命令需使用占位符并标记“替换为实际命令”;禁止凭空生成脚本或路径。
  • 不得忽略现有工作流:若项目已有
    .github/workflows/
    目录,需对齐命名与风格,避免重复或冲突。
  • 不得重复构建逻辑:若项目使用GoReleaser、Dockerfile等定义构建和镜像规则,工作流仅需触发、登录并传递参数(如
    GITHUB_TOKEN
    BUILDX_BUILDER
    );不得重新实现已有逻辑。

Self-Check

自我检查清单

  • Appendix A: Does output satisfy mandatory structure and security in Appendix A?
  • Triggers: Is
    on
    narrowed to specific branches/paths/tags?
  • Permissions and security: Are minimal
    permissions
    set? Third-party actions pinned? No hardcoded secrets?
  • Runnable: After the user replaces placeholders, can the workflow run in the target repo?
  • Stack alignment: Runner, language version, package manager, and commands match the user’s stack?
  • Step order and deps: For multi-step jobs (e.g. QEMU → Buildx → login → GoReleaser), is order correct and are ids/env vars passed? See Appendix B for Go + Docker + GoReleaser.

  • 附录A合规:输出是否满足附录A中的强制结构与安全要求?
  • 触发器设置
    on
    是否限定为特定分支/路径/标签?
  • 权限与安全:是否设置了最小
    permissions
    ?第三方Action是否固定版本?是否存在硬编码密钥?
  • 可运行性:用户替换占位符后,工作流能否在目标仓库中运行?
  • 技术栈对齐:运行器、语言版本、包管理器和命令是否匹配用户提供的技术栈?
  • 步骤顺序与依赖:多步骤任务(如QEMU → Buildx → 登录 → GoReleaser)的顺序是否正确,ID/环境变量是否正确传递?请参考附录B中Go + Docker + GoReleaser的示例。

Examples

示例

Example 1: Node CI (test + lint on PR)

示例1:Node CI(PR时运行测试+代码检查)

Input: Scenario: CI. Stack: Node 20, pnpm, test
pnpm test
, lint
pnpm lint
. Trigger:
pull_request
to
main
. File:
ci.yml
.
Expected: Single
ci.yml
with
name
e.g. “CI”;
on: pull_request: branches: [main]
; job on
ubuntu-latest
with checkout, setup Node/pnpm, install, lint, test; use official
actions/checkout
and
pnpm/action-setup
(or equivalent) pinned; no hardcoded secrets;
permissions
read-only if set.
输入:场景:CI。技术栈:Node 20、pnpm,测试命令
pnpm test
,代码检查命令
pnpm lint
。触发器:向
main
分支提交的
pull_request
。文件:
ci.yml
预期输出:单个
ci.yml
文件,
name
例如“CI”;
on: pull_request: branches: [main]
;任务运行在
ubuntu-latest
上,步骤包括检出代码、设置Node/pnpm、安装依赖、代码检查、测试;使用官方的
actions/checkout
pnpm/action-setup
(或等效Action)并固定版本;无硬编码密钥;若设置
permissions
则为只读权限。

Example 2: Go PR check with path filter

示例2:带路径过滤的Go PR检查

Input: Scenario: PR check. Stack: Go 1.21, test
go test ./...
. Trigger only when
go.mod
or
*.go
change. File:
pr-check.yml
.
Expected:
on.pull_request
with
paths: ['**.go', 'go.mod']
; job with
actions/setup-go
pinned, steps checkout, setup Go, go test;
permissions
omitted or
contents: read
if no write needed.
输入:场景:PR检查。技术栈:Go 1.21,测试命令
go test ./...
。仅当
go.mod
*.go
文件变更时触发。文件:
pr-check.yml
预期输出
on.pull_request
包含
paths: ['**.go', 'go.mod']
;任务使用固定版本的
actions/setup-go
,步骤包括检出代码、设置Go环境、运行测试;无需写入权限时,
permissions
可省略或设置为
contents: read

Example 3: Go release (Docker + GHCR + GoReleaser)

示例3:Go发布(Docker + GHCR + GoReleaser)

Input: Scenario: CD/release. Stack: Go, Docker multi-arch (amd64/arm64), GoReleaser for image and GitHub Release. Trigger: only
push
tags
v*
. File:
release.yml
.
Expected:
on: push: tags: ['v*']
;
permissions
include
contents: write
,
packages: write
. Steps: Checkout (
fetch-depth: 0
) → Set up Go (
go-version-file: go.mod
, cache) → Set up QEMU (
linux/amd64
,
linux/arm64
) → Set up Docker Buildx (
id: buildx
, same platforms) → Login to GHCR (
docker/login-action
,
ghcr.io
) → GoReleaser (
goreleaser/goreleaser-action
pinned, pass
GITHUB_TOKEN
and
BUILDX_BUILDER: ${{ steps.buildx.outputs.name }}
). Do not reimplement logic defined in
.goreleaser.yaml
/Dockerfile. See Appendix B.
输入:场景:CD/发布。技术栈:Go、Docker多架构(amd64/arm64),使用GoReleaser生成镜像并创建GitHub Release。触发器:仅在推送
v*
标签时触发。文件:
release.yml
预期输出
on: push: tags: ['v*']
permissions
包含
contents: write
packages: write
。步骤:检出代码(
fetch-depth: 0
)→ 设置Go环境(
go-version-file: go.mod
,启用缓存)→ 设置QEMU(
linux/amd64
,
linux/arm64
)→ 设置Docker Buildx(
id: buildx
,指定相同平台)→ 登录GHCR(
docker/login-action
ghcr.io
)→ 运行GoReleaser(固定版本的
goreleaser/goreleaser-action
,传递
GITHUB_TOKEN
BUILDX_BUILDER: ${{ steps.buildx.outputs.name }}
)。不得重新实现
.goreleaser.yaml
/Dockerfile中已定义的逻辑。详见附录B

Example 4 (edge): Minimal info

示例4(边缘场景):信息极简

Input: Project: legacy-api. No description. Language and commands unknown. User wants “at least one CI placeholder workflow”.
Expected: Produce one structurally complete, Appendix A–compliant YAML; use placeholders for runner and steps (e.g. “Specify runner and install/test commands”) and mark “to be replaced”; keep
on
narrow (e.g.
pull_request: branches: [main]
); do not invent test or build commands; keep
name
,
on
,
jobs
,
runs-on
,
steps
, and recommended fields (e.g.
permissions
) so the user can fill in later.

输入:项目:legacy-api。无详细描述。语言与命令未知。用户需求:“至少生成一个CI占位符工作流”。
预期输出:生成一个结构完整、符合附录A要求的YAML文件;运行器和步骤使用占位符(如“指定运行器和安装/测试命令”)并标记“待替换”;
on
设置为窄范围(如
pull_request: branches: [main]
);不得凭空生成测试或构建命令;保留
name
on
jobs
runs-on
steps
及推荐字段(如
permissions
),方便用户后续补充。

Appendix A: Workflow output contract

附录A:工作流输出规范

The following are mandatory for workflow files produced by this skill; use this appendix for self-check.
Scope: YAML workflow files produced by this skill for a project’s
.github/workflows/
.
以下为本技能生成的工作流文件的强制要求;请使用本附录进行自我检查。
范围:本技能为项目
.github/workflows/
目录生成的YAML工作流文件。

A.1 File and path

A.1 文件与路径

  • Location: Must live under the target project’s
    .github/workflows/
    .
  • Naming:
    kebab-case
    , extension
    .yml
    or
    .yaml
    ; name should reflect purpose (e.g.
    ci.yml
    ,
    pr-check.yml
    ,
    release.yml
    ).
  • One file, one workflow: One file defines one workflow; split into multiple files for complex cases; avoid many unrelated jobs in one file.
  • 存放位置:必须位于目标项目的
    .github/workflows/
    目录下。
  • 命名规则:采用
    kebab-case
    命名法,扩展名为
    .yml
    .yaml
    ;名称需反映工作流用途(如
    ci.yml
    pr-check.yml
    release.yml
    )。
  • 单文件单工作流:一个文件定义一个工作流;复杂场景需拆分为多个文件;避免在一个文件中包含多个无关任务。

A.2 Required structure

A.2 强制结构

Each workflow YAML must contain (order recommended):
FieldRequiredDescription
name
YesDisplay name in GitHub UI; short and readable (e.g. “CI”, “PR check”, “Release”).
on
YesTriggers:
push
,
pull_request
,
workflow_dispatch
, etc.; must narrow branch/path/tag; avoid broad
on: push
with no filter.
jobs
YesAt least one job; each job must have
runs-on
and
steps
.
jobs.<id>.runs-on
YesRunner (e.g.
ubuntu-latest
).
jobs.<id>.steps
YesList of steps; each step has
name
(human-readable) and
uses
or
run
.
Optional but recommended:
permissions
,
concurrency
,
env
.
每个工作流YAML必须包含以下字段(推荐顺序):
字段是否必填描述
name
GitHub UI中显示的名称;简短易读(如“CI”、“PR检查”、“发布”)。
on
触发器:
push
pull_request
workflow_dispatch
等;必须限定分支/路径/标签;避免无过滤的宽泛
on: push
jobs
至少包含一个任务;每个任务必须有
runs-on
steps
jobs.<id>.runs-on
运行器(如
ubuntu-latest
)。
jobs.<id>.steps
步骤列表;每个步骤需有
name
(人类可读)和
uses
run
可选但推荐的字段:
permissions
concurrency
env

A.3 Naming and readability

A.3 命名与可读性

  • Job id:
    kebab-case
    , clear meaning (e.g.
    build
    ,
    test
    ,
    lint
    ,
    deploy-preview
    ).
  • Step name: Short, scannable description for the Actions log.
  • Workflow name: Align with filename and other workflows in the repo.
  • 任务ID:采用
    kebab-case
    ,含义清晰(如
    build
    test
    lint
    deploy-preview
    )。
  • 步骤名称:简短易懂,便于在Actions日志中快速扫描。
  • 工作流名称:与文件名及仓库内其他工作流保持一致。

A.4 Security and minimal permissions

A.4 安全与最小权限

  • Permissions: If
    permissions
    is not set, GitHub uses default
    GITHUB_TOKEN
    permissions. For sensitive operations, set
    permissions
    at workflow or job level to the minimum needed. By type: CI (build/test/scan only) →
    contents: read
    ; release (Release, GHCR push) → explicit
    contents: write
    ,
    packages: write
    ; avoid default or
    all
    .
  • Secrets: Inject secrets via Secrets; never hardcode keys, tokens, or passwords in YAML.
  • Third-party actions: Prefer official or widely used actions; pin version (commit SHA or major-version tag); do not use
    @master
    or unpinned; use specific versions for security/scan actions to reduce drift.
  • 权限设置:若未设置
    permissions
    ,GitHub会使用
    GITHUB_TOKEN
    的默认权限。对于敏感操作,需在工作流或任务级别设置
    permissions
    为所需的最小权限。按场景分类:CI(仅构建/测试/扫描)→
    contents: read
    ;发布(创建Release、推送GHCR镜像)→ 显式设置
    contents: write
    packages: write
    ;避免使用默认权限或
    all
  • 密钥管理:通过Secrets注入密钥;禁止在YAML中硬编码密钥、令牌或密码。
  • 第三方Action:优先选择官方或广泛使用的Action;固定版本(提交SHA或大版本标签);禁止使用
    @master
    或未固定的引用;安全/扫描类Action需使用特定版本以减少版本漂移。

A.5 Maintainability

A.5 可维护性

  • CI vs CD (recommended): CI only builds, tests, and scans; no release. CD (image push, GitHub Release) runs only on version tags (e.g.
    v*
    ). Use separate files (e.g.
    ci.yml
    ,
    release.yml
    ); do not mix “run on every push” and “release only on tag” in one workflow.
  • Reuse: Extract common logic into Composite Actions or reusable workflows.
  • Comments: Briefly comment non-obvious triggers, matrix strategy, or env usage; keep comments short.
  • Project alignment: Runner, language version, package manager, and commands must match the target project; if the project has existing workflows, align style and naming.
  • CI与CD分离(推荐):CI仅负责构建、测试和扫描;不包含发布操作。CD(镜像推送、GitHub Release)仅在版本标签(如
    v*
    )时触发。使用单独文件(如
    ci.yml
    release.yml
    );禁止在一个工作流中混合“每次推送都运行”和“仅打标签时发布”的逻辑。
  • 复用逻辑:将通用逻辑提取为Composite Actions或可复用工作流。
  • 注释规范:对非直观的触发器、矩阵策略或环境变量使用简短注释;注释需简洁。
  • 项目对齐:运行器、语言版本、包管理器和命令必须匹配目标项目;若项目已有工作流,需对齐风格与命名。

A.6 Self-check (producer)

A.6 生成者自我检查清单

After producing the workflow:
  • File is under
    .github/workflows/
    with a kebab-case name.
  • Contains
    name
    ,
    on
    ,
    jobs
    ; each job has
    runs-on
    and
    steps
    .
  • on
    is narrowed to specific branches/paths/tags.
  • No hardcoded secrets; third-party actions pinned (specific version for security/scan).
  • Step and job names are clear; consistent with project stack and existing workflow style.
  • YAML is valid (indent, no duplicate keys); step order and dependencies are correct.

生成工作流后:
  • 文件位于
    .github/workflows/
    目录下,采用
    kebab-case
    命名。
  • 包含
    name
    on
    jobs
    ;每个任务有
    runs-on
    steps
  • on
    限定为特定分支/路径/标签。
  • 无硬编码密钥;第三方Action已固定版本(安全/扫描类Action使用特定版本)。
  • 步骤与任务名称清晰;与项目技术栈及现有工作流风格一致。
  • YAML格式有效(缩进正确,无重复键);步骤顺序与依赖关系正确。

Appendix B: Go + Docker + GHCR + GoReleaser

附录B:Go + Docker + GHCR + GoReleaser 规范

Conventions and practices for Go + Docker + GHCR + GoReleaser workflows; follow together with the main skill and Appendix A when generating or editing such workflows.
以下为Go + Docker + GHCR + GoReleaser工作流的约定与实践;生成或编辑此类工作流时,请同时遵循本技能核心规则与附录A。

B.1 Layout

B.1 布局

  • CI and CD separate: Two workflows.
    • CI (e.g.
      ci.yml
      ):
      push
      /
      pull_request
      to main branch. Build, test, security scan only; no release.
    • CD (e.g.
      release.yml
      ): Only on
      push
      of version tags (e.g.
      v*
      ). Publish image and GitHub Release.
  • Do not mix “run on every push” and “release only on tag” in one workflow.
  • CI与CD分离:分为两个工作流。
    • CI(如
      ci.yml
      ):在向主分支推送或提交PR时触发。仅负责构建、测试、安全扫描;不包含发布操作
    • CD(如
      release.yml
      ):仅在推送
      v*
      版本标签时触发。负责发布镜像与GitHub Release。
  • 禁止在一个工作流中混合“每次推送都运行”和“仅打标签时发布”的逻辑。

B.2 Permissions

B.2 权限设置

  • Set
    permissions
    explicitly. CI:
    contents: read
    . Release:
    contents: write
    ,
    packages: write
    . Do not use
    all
    .
  • 显式设置
    permissions
    。CI:
    contents: read
    。发布:
    contents: write
    packages: write
    。禁止使用
    all
    权限。

B.3 Steps and order

B.3 步骤与顺序

Go
  • Use
    actions/setup-go@v5
    with
    go-version-file: go.mod
    . Enable
    cache: true
    . For release, checkout with
    fetch-depth: 0
    (needed for GoReleaser); CI can use the same for consistency.
CI (example order)
  1. Checkout (
    fetch-depth: 0
    )
  2. Set up Go (go.mod + cache)
  3. go test ./...
  4. govulncheck:
    go install golang.org/x/vuln/cmd/govulncheck@latest
    then
    govulncheck ./...
  5. Docker Buildx (setup only, single platform)
  6. Build image for scanning: single arch
    linux/amd64
    ,
    push: false
    ,
    load: true
    , tag e.g.
    local/your-app:ci-${{ github.sha }}
  7. Trivy on that image:
    severity: HIGH,CRITICAL
    ,
    ignore-unfixed: true
    ,
    exit-code: 1
    so CI fails on findings
Multi-arch in Release only; CI scans single arch for speed.
Release (example order)
  1. Checkout (
    fetch-depth: 0
    )
  2. Set up Go (go.mod + cache)
  3. Set up QEMU:
    docker/setup-qemu-action
    ,
    platforms: linux/amd64,linux/arm64
  4. Set up Docker Buildx:
    id: buildx
    ,
    driver: docker-container
    ,
    platforms: linux/amd64,linux/arm64
  5. Login to GHCR:
    docker/login-action
    , registry
    ghcr.io
    , password
    secrets.GHCR_TOKEN || secrets.GITHUB_TOKEN
    ,
    logout: true
  6. GoReleaser:
    goreleaser/goreleaser-action@v6
    ,
    args: release --clean
    , env
    GITHUB_TOKEN
    and
    BUILDX_BUILDER: ${{ steps.buildx.outputs.name }}
QEMU before Buildx; Buildx
platforms
must match QEMU. GoReleaser needs the Buildx builder name for multi-arch, so set
id: buildx
and pass
BUILDX_BUILDER
.
Go环境设置
  • 使用
    actions/setup-go@v5
    并指定
    go-version-file: go.mod
    。启用
    cache: true
    。发布场景下,检出代码时需设置
    fetch-depth: 0
    (GoReleaser需要完整提交历史);CI场景下可采用相同设置以保持一致性。
CI步骤示例顺序
  1. 检出代码(
    fetch-depth: 0
  2. 设置Go环境(读取go.mod + 启用缓存)
  3. 运行测试:
    go test ./...
  4. 漏洞检查:
    go install golang.org/x/vuln/cmd/govulncheck@latest
    然后运行
    govulncheck ./...
  5. 设置Docker Buildx(仅初始化,单平台)
  6. 构建镜像用于扫描:单架构
    linux/amd64
    push: false
    load: true
    ,标签示例
    local/your-app:ci-${{ github.sha }}
  7. Trivy镜像扫描:
    severity: HIGH,CRITICAL
    ignore-unfixed: true
    exit-code: 1
    (发现高危漏洞时CI失败)
仅在发布场景下使用多架构;CI场景下使用单架构扫描以提升速度。
发布步骤示例顺序
  1. 检出代码(
    fetch-depth: 0
  2. 设置Go环境(读取go.mod + 启用缓存)
  3. 设置QEMU:
    docker/setup-qemu-action
    ,指定
    platforms: linux/amd64,linux/arm64
  4. 设置Docker Buildx:
    id: buildx
    driver: docker-container
    ,指定相同平台
  5. 登录GHCR:
    docker/login-action
    , registry
    ghcr.io
    ,密码
    secrets.GHCR_TOKEN || secrets.GITHUB_TOKEN
    logout: true
  6. 运行GoReleaser:固定版本的
    goreleaser/goreleaser-action@v6
    ,参数
    args: release --clean
    ,传递环境变量
    GITHUB_TOKEN
    BUILDX_BUILDER: ${{ steps.buildx.outputs.name }}
QEMU需在Buildx之前初始化;Buildx的
platforms
必须与QEMU一致。GoReleaser需要Buildx构建器名称以支持多架构,因此需为Buildx步骤设置
id: buildx
并传递
BUILDX_BUILDER
参数。

B.4 Relation to repo config

B.4 与仓库配置的关系

  • Docker image: Shape is defined in
    .goreleaser.yaml
    and Dockerfile; workflow does not duplicate build logic.
  • GHCR: Image path and tagging in GoReleaser config; workflow only logs in and passes
    GITHUB_TOKEN
    and Buildx builder.
  • Makefile: Local build/test can stay; CI steps can align with Make targets but need not depend on them.
  • Docker镜像:镜像定义由
    .goreleaser.yaml
    和Dockerfile负责;工作流不得重复构建逻辑。
  • GHCR:镜像路径与标签规则由GoReleaser配置定义;工作流仅需登录并传递
    GITHUB_TOKEN
    和Buildx构建器参数。
  • Makefile:本地构建/测试逻辑可保留;CI步骤可与Make目标对齐,但无需依赖Makefile。

B.5 When editing

B.5 编辑注意事项

  1. Full flow: Changing one job may affect the whole flow; verify checkout → Go → QEMU → Buildx → login → GoReleaser order and deps.
  2. Action versions: Use current major versions (e.g.
    checkout@v4
    ,
    setup-go@v5
    ,
    setup-buildx-action@v3
    ,
    goreleaser-action@v6
    ); check changelog for breaking changes when upgrading.
  3. Trivy: Pin version (e.g.
    @0.33.1
    ) to avoid CI breakage from behavior changes.
  4. YAML: Check indent and no duplicate keys; validate with a tool after edits.
  1. 全流程校验:修改单个任务可能影响整个流程;需验证检出代码→Go环境→QEMU→Buildx→登录→GoReleaser的顺序与依赖关系。
  2. Action版本:使用当前大版本(如
    checkout@v4
    setup-go@v5
    setup-buildx-action@v3
    goreleaser-action@v6
    );升级时需查看变更日志以避免破坏性更新。
  3. Trivy版本:固定Trivy版本(如
    @0.33.1
    )以避免因行为变更导致CI失败。
  4. YAML格式:检查缩进与重复键;编辑后使用工具验证YAML有效性。

B.6 Lessons learned

B.6 经验总结

IssueApproach
Single workflow too largeSplit into CI + Release: CI for build/test/scan, Release only on tag via GoReleaser; clearer permissions and logic.
GHCR auth too complexUse minimal login (
docker/login-action
+ token); avoid heavy auth-verify that can false-fail.
Multi-arch manifest validation failsPull and validate per platform instead of generic manifest pull.
Date/version format inconsistentUse one format (e.g. ISO8601) in workflow and Dockerfile; add
dist/
to
.gitignore
if using GoReleaser output.
GoReleaser multi-arch build failsGoReleaser needs Buildx builder: set id: buildx on Buildx step and pass BUILDX_BUILDER: ${{ steps.buildx.outputs.name }}.
Version driftUse reasonable version constraints and check release notes when upgrading; validate on a branch first.
Inspect workflow history:
git log --oneline -- .github/workflows/

问题解决方案
单个工作流过于庞大拆分为CI + 发布:CI负责构建/测试/扫描,发布仅在打标签时通过GoReleaser执行;权限与逻辑更清晰。
GHCR认证过于复杂使用极简登录方式(
docker/login-action
+ 令牌);避免使用易误判的复杂认证校验。
多架构清单验证失败按平台分别拉取并验证镜像,而非拉取通用清单。
日期/版本格式不一致在工作流与Dockerfile中使用统一格式(如ISO8601);若使用GoReleaser输出,需将
dist/
添加到
.gitignore
GoReleaser多架构构建失败GoReleaser需要Buildx构建器:为Buildx步骤设置id: buildx并传递BUILDX_BUILDER: ${{ steps.buildx.outputs.name }}
版本漂移使用合理的版本约束,升级前查看发布说明;先在分支上验证。
查看工作流历史
git log --oneline -- .github/workflows/

References

参考资料