GitHub Actions 工作流
让 Agent 编写带 `permissions` 最小化、`actions` 版本 pin(commit SHA 优先)、复用 workflow 与环境保护规则的安全 YAML。
SKILL 规定 `on` 触发器范围、路径过滤、`concurrency` 组名;第三方 action 需审查供应商并优先官方或已 pin 版本。
使用 `GITHUB_TOKEN` 默认权限时显式降级;需跨仓或云资源时用 OIDC 与 cloud provider 配置,避免长期 secrets。
可复用 workflow 与 composite action 的拆分准则;自托管 runner 标签与隔离要求若适用须写明。
- 缓存:`actions/cache` 键与 restore-keys 策略,避免错误命中。
- 容器作业:镜像来源与 pull policy;与 Dockerfile 技能一致。
- 复用:`workflow_call` 输入校验与文档化默认值。
GHA 主流程(skill-flow-block)
[ 事件:push / PR / schedule / workflow_dispatch / 调用方 workflow_call ]
│
▼
[ 解析:workflow 文件匹配分支 / 路径 / activity types ]
│
▼
[ 并发:concurrency 组取消或排队;避免与部署 job 竞态 ]
│
▼
[ Job:runs-on、permissions 降级、environment 与必要 secrets ]
│
┌────────┴────────┐
▼ ▼
[ 内联 steps:uses pin(SHA)+ 显式 with ] [ 复用:workflow_call / composite / 可重用 job 模板 ]
│ │
└────────┬────────┘
▼
[ 产出:artifact、摘要、状态检查;失败时保留日志与复现命令 ]
Agent 改 YAML 时应同时检查:默认分支保护规则、required status checks 名称是否与
jobs.*.name 一致,以及是否会意外扩大 pull_request_target 风险面。
可复用工作流对照矩阵
下表对比常见「复用」形态:点击行可在下方查看 SKILL 中建议写明的要点(仅本地高亮,无网络请求)。
| 形态 | 入口 | 输入 / 密钥 | 权限边界 | 典型用途 |
|---|---|---|---|---|
| 可复用 Workflow | on.workflow_call,由调用方 uses: org/repo/.github/workflows/x.yml@ref |
inputs / secrets 显式传入;支持 outputs |
调用方与 callee 的 permissions 各自独立;跨仓需信任 ref 与 CODEOWNERS |
多仓统一 CI、发布流水线模板 |
| Composite Action | action.yml 中 runs.using: composite,uses: ./path 或公开 action |
inputs;密钥经 secrets 从调用 workflow 注入 |
与调用 job 同一 actor;适合打包多步 shell,不宜塞整条流水线 | 重复 shell 步骤、工具链安装、缓存封装 |
| 容器 / JS Action | uses: owner/action@vX 或 SHA;可选 docker:// |
with;敏感项走 secrets |
审查供应商、pin SHA;注意 post step 与缓存副作用 | 官方或社区封装好的单责任步骤 |
| Job 矩阵 | 同一 workflow 内 strategy.matrix / fail-fast |
矩阵维度作 env;不自动共享 secrets 到子组合以外 | 注意矩阵爆炸与 minutes;大矩阵拆 workflow_call 分批 | 多版本语言、多 OS、参数化测试 |
当前选中:点击表格中的一行以查看建议写入 SKILL 的侧重点。
触发器、concurrency 与路径过滤
-
on:为 PR 与 push 分别写清paths/paths-ignore;workflow_dispatch的 inputs 要有类型、默认值与说明。 -
concurrency:组名包含环境或分支占位,避免不同 PR 互相取消;部署类 job 慎用cancel-in-progress。 -
复用入口:被
workflow_call调用的 workflow 应校验inputs枚举,拒绝空字符串或危险默认分支名。
完整的可复用 workflow(reusable workflow with inputs/outputs)示例:
# .github/workflows/reusable-build.yml — 可复用 workflow
name: Reusable Build
on:
workflow_call:
inputs:
node-version:
description: 'Node.js 版本'
type: string
default: '20'
required: false
environment:
description: '部署目标环境'
type: string
required: true
secrets:
REGISTRY_TOKEN:
required: true
outputs:
image-tag:
description: '构建产物镜像 tag'
value: ${{ jobs.build.outputs.tag }}
jobs:
build:
runs-on: ubuntu-24.04
timeout-minutes: 20
outputs:
tag: ${{ steps.tag.outputs.tag }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- name: Restore build cache
uses: actions/cache@v4
with:
path: |
.next/cache
node_modules/.cache
key: build-${{ runner.os }}-${{ inputs.node-version }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
build-${{ runner.os }}-${{ inputs.node-version }}-
build-${{ runner.os }}-
- run: npm ci --prefer-offline
- run: npm run build
- id: tag
run: |
echo "tag=$(node -p "require('./package.json').version")-${{ github.sha }}" >> "$GITHUB_OUTPUT"
# ---- 调用方 workflow ----
# .github/workflows/deploy.yml
# jobs:
# build:
# uses: ./.github/workflows/reusable-build.yml
# with:
# node-version: '20'
# environment: staging
# secrets:
# REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
矩阵测试配置:多版本 × 多平台并行测试:
# 矩阵测试:Node 18/20/22 × ubuntu/windows
jobs:
test:
strategy:
fail-fast: false # 一个组合失败不停止其他
matrix:
node: ['18', '20', '22']
os: [ubuntu-24.04, windows-latest]
exclude:
- node: '18'
os: windows-latest # 排除特定组合
runs-on: ${{ matrix.os }}
name: Test Node ${{ matrix.node }} on ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'npm'
- run: npm ci
- run: npm test
permissions、OIDC 与 action pin
-
最小权限:顶层
permissions先收紧,再在 job 级按需放宽;需要写内容库时显式contents: write并说明理由。 -
OIDC:云角色信任策略绑定
sub/aud;避免把环境名或可伪造 claim 单独作为唯一条件。 - Pin:优先完整 commit SHA;标签需配合组织级允许列表或 dependabot 更新策略。
Secrets 安全传递:environments + required reviewers 手动审批配置:
# 最小权限顶层收紧 + 各 job 按需放宽 + environment 手动审批
permissions: {} # 顶层全部关闭
jobs:
test:
runs-on: ubuntu-24.04
permissions:
contents: read # 仅读源码
steps:
- uses: actions/checkout@v4
- run: npm test
deploy-prod:
runs-on: ubuntu-24.04
needs: test
# environment 绑定保护规则:在仓库 Settings > Environments 配置
# Required reviewers: 至少 1 人审批后 job 才能继续运行
environment:
name: production
url: https://myapp.example.com
permissions:
id-token: write # OIDC token
contents: read
steps:
- uses: actions/checkout@v4
# Pin action 到完整 commit SHA,而非 @v4 标签
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502
with:
role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}
- run: |
# Secrets 通过 environment 隔离,此处 ${{ secrets.DB_PASSWORD }}
# 仅在 production environment 的 job 中可见
aws ssm put-parameter \
--name "/myapp/prod/db-password" \
--value "${{ secrets.DB_PASSWORD }}" \
--type SecureString --overwrite
缓存、容器与环境保护
-
缓存:键包含 lockfile 哈希与 runner OS;
restore-keys仅作降级,文档中写明可接受的「部分命中」行为。 - 容器 job:镜像 digest、非 root、与供应链技能一致的 SBOM/扫描门禁。
- Environment:保护规则、required reviewers 与 secrets 分环境;生产部署 workflow 与仅 CI 的 workflow 分离。
缓存优化:actions/cache 的正确键设计与多层 restore-keys:
# npm 依赖缓存:精确键 + 两级降级
- name: Cache npm dependencies
uses: actions/cache@v4
id: npm-cache
with:
path: ~/.npm
# 精确键:OS + node版本 + lockfile哈希
key: npm-${{ runner.os }}-node20-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-node20-
npm-${{ runner.os }}-
# cache-hit: true 时跳过 npm install
- run: npm ci --prefer-offline
# --prefer-offline: 优先使用 ~/.npm 缓存,降低网络依赖
# Docker layer 缓存(BuildKit)
- name: Build with layer cache
uses: docker/build-push-action@v6
with:
context: .
push: false
cache-from: type=gha,scope=myapp-build
cache-to: type=gha,mode=max,scope=myapp-build
tags: myapp:${{ github.sha }}
# Terraform provider 缓存
- name: Cache Terraform providers
uses: actions/cache@v4
with:
path: ~/.terraform.d/plugin-cache
key: tf-${{ runner.os }}-${{ hashFiles('**/.terraform.lock.hcl') }}
restore-keys: |
tf-${{ runner.os }}-
---
name: github-actions-workflows
description: 安全、可复用的 GitHub Actions YAML
tags: [github-actions, ci-cd, security]
---
# 触发器与并发
1. on.push/pull_request 分别配置 paths 过滤,降低无关变更触发
2. concurrency.group 含 workflow + ref,PR 之间不互相取消
3. workflow_dispatch inputs 必须有 type、description 与合理默认值
4. workflow_call inputs 校验枚举,拒绝空字符串或保留分支名
# 权限最小化
5. 顶层 permissions: {} 全部关闭,job 级按需放宽
6. OIDC federation:id-token: write + 云 provider configure-credentials action
7. 信任策略绑定 sub(repo:org/repo:ref:refs/heads/main)+ aud 双重条件
8. Action pin:优先完整 commit SHA,配合 dependabot 自动更新
# 可复用与缓存
9. reusable workflow:inputs/secrets/outputs 显式声明,调用方 uses: ./.github/workflows/x.yml
10. Composite action:打包多步 shell,不含独立部署权限
11. actions/cache 键 = OS + 工具版本 + lockfile 哈希,restore-keys 两级降级
12. Docker layer cache via BuildKit type=gha,scope 按服务区分
# 环境与密钥
13. environment 绑定 required reviewers,生产 deploy 需人工审批
14. 生产 secrets 仅在绑定 environment 的 job 中可见,与 CI job 隔离
15. pull_request_target 触发时不执行 checkout 或运行 fork 代码
16. 不在 workflow 中输出 secrets,避免 echo / cat 暴露在日志