关于 github-actions-templates
github-actions-templates 是面向应用开发团队的 GitHub Actions 工作流模式指南,涵盖测试、构建与部署。除常见模板外,还说明密钥、权限、矩阵构建、缓存和工作流故障的处理方式。
主要功能
- 01测试与部署工作流模式
- 02Docker 构建和推送模板
- 03Kubernetes 部署与矩阵构建
- 04密钥和权限处理建议
- 05缓存问题与故障排查
适用场景
- 01为项目配置持续集成与部署
- 02自动构建并推送 Docker 镜像
- 03部署应用到 Kubernetes
- 04排查工作流中的权限或缓存问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ckorhonen/ claude-skills --skill github-actions-templates安装后在 Claude Code 中输入/github-actions-templates确认已加载。
详细介绍
GitHub Actions 模板
用于测试、构建和部署应用程序的生产就绪型 GitHub Actions 工作流模式。
用途
为各种技术栈创建高效、安全的 GitHub Actions 工作流,以实现持续集成和部署。
使用场景
- 自动化测试和部署
- 构建 Docker 镜像并推送到镜像仓库
- 部署到 Kubernetes 集群
- 运行安全扫描
- 为多个环境实现矩阵构建
常见工作流模式
模式 1:测试工作流
name: Test
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
模式 2:构建并推送 Docker 镜像
name: Build and Push
on:
push:
branches: [main]
tags: ["v*"]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
模式 3:部署到 Kubernetes
name: Deploy to Kubernetes
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-2
- name: Update kubeconfig
run: |
aws eks update-kubeconfig --name production-cluster --region us-west-2
- name: Deploy to Kubernetes
run: |
kubectl apply -f k8s/
kubectl rollout status deployment/my-app -n production
kubectl get services -n production
- name: Verify deployment
run: |
kubectl get pods -n production
kubectl describe deployment my-app -n production
模式 4:矩阵构建
name: Matrix Build
on: [push, pull_request]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
run: pytest
工作流最佳实践
- 使用指定版本的操作(@v4,而不是 @latest)
- 缓存依赖项以加快构建速度
- 使用机密存储敏感数据
- 在 PR 上实施状态检查
- 使用矩阵构建进行多版本测试
- 设置适当的权限
- 对常见模式使用可复用工作流
- 为生产环境实施审批关卡
- 添加失败通知步骤
- 对敏感工作负载使用自托管运行器
可复用工作流
# .github/workflows/reusable-test.yml
name: Reusable Test Workflow
on:
workflow_call:
inputs:
node-version:
required: true
type: string
secrets:
NPM_TOKEN:
required: true
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node-version }}
- run: npm ci
- run: npm test
使用可复用工作流:
jobs:
call-test:
uses: ./.github/workflows/reusable-test.yml
with:
node-version: "20.x"
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
安全扫描
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: "fs"
scan-ref: "."
format: "sarif"
output: "trivy-results.sarif"
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: "trivy-results.sarif"
- name: Run Snyk Security Scan
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
需要审批的部署
name: Deploy to Production
on:
push:
tags: ["v*"]
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: production
url: https://app.example.com
steps:
- uses: actions/checkout@v4
- name: Deploy application
run: |
echo "Deploying to production..."
# Deployment commands here
- name: Notify Slack
if: success()
uses: slackapi/slack-github-action@v1
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{
"text": "Deployment to production completed successfully!"
}
常见陷阱
本节记录了会导致 GitHub Actions 工作流静默或意外失败的真实故障模式和反模式。
1. 工作流语法错误
问题: YAML 缩进、引号和表达式语法是导致静默失败的最常见原因。
常见错误:
缩进错误
# ❌ WRONG - Missing indentation
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
# ✅ CORRECT
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- run: npm test
错误消息: "unexpected mapping value" or "mapping values are not allowed here"
修复方法: YAML 严格要求使用 2 个空格缩进。在工作流中使用 yamllint 等 YAML 检查工具。
表达式语法混淆
# ❌ WRONG - Using $ without github context
- run: echo ${{ matrix.node-version }}
# ❌ WRONG - Missing quotes on complex expressions
env:
MY_VAR: ${{ github.event.pull_request.title }}
# ✅ CORRECT
- run: echo "${{ matrix.node-version }}"
# ✅ CORRECT with quotes for strings
env:
MY_VAR: "${{ github.event.pull_request.title }}"
错误消息: "Unable to process template language" or "unrecognized named value"
修复方法: 对用于 Shell 命令或作为字符串的表达式始终加引号。GitHub Actions 要求正确使用引号,以确保安全展开。
多行字符串未使用管道语法
# ❌ WRONG - Multiline without | or >
- run: echo "Line 1
Line 2"
# ✅ CORRECT using pipe (preserves newlines)
- run: |
npm install
npm run build
npm test
# ✅ CORRECT using > (folds newlines)
- name: Summary
run: >
This is a long
command that spans
multiple lines
错误消息: "expected '<block end>', but found '\\n'"
修复方法: 使用 | 表示文本块(保留换行符),或使用 > 表示折叠块(将换行符折叠为空格)。
2. 机密处理错误
问题: 机密是最常被错误处理的元素。GitHub Actions 对机密何时可用有特定规则。
关键错误:
在工作流文件中硬编码机密
# ❌ ABSOLUTELY WRONG - Secret is now in git history
- run: |
aws s3 sync . s3://my-bucket \
--aws-access-key-id AKIA1234567890ABCDEF \
--aws-secret-access-key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
错误消息: 初始时没有,但这是严重的安全漏洞。
修复方法: 始终使用 ${{ secrets.SECRET_NAME }},并在 GitHub 仓库设置中定义机密。
在非机密上下文中访问机密
# ❌ WRONG - Secrets not available in if: conditionals
if: ${{ secrets.DEPLOY_KEY != '' }}
# ✅ CORRECT - Secrets work in env: blocks at job and step level
jobs:
deploy:
runs-on: ubuntu-latest
env:
MESSAGE: ${{ secrets.MY_SECRET }} # ← Works at job level
steps:
- name: Deploy
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }} # ← Works at step level
run: |
# Now DEPLOY_KEY is available here
./deploy.sh
错误消息: 机密显示为 ***(已屏蔽),但在 if: 条件中使用时实际上为空或未定义。
修复方法: 在作业或步骤级别的 env: 块中使用机密。切勿在 if: 条件中使用机密——它们在那里不可用。
忘记将输出标记为敏感内容
# ❌ WRONG - Logs leak credentials
- name: Get credentials
run: |
TOKEN=$(curl -s https://api.example.com/token)
echo "TOKEN=$TOKEN" >> $GITHUB_OUTPUT
echo "Got token: $TOKEN" # ← Logged!
# ✅ CORRECT - Mark as secret in action output
- name: Get credentials
id: creds
run: |
TOKEN=$(curl -s https://api.example.com/token)
echo "token=$TOKEN" >> $GITHUB_OUTPUT # ← Set output
# Then reference as:
# ${{ steps.creds.outputs.token }}
错误消息: 凭据以明文形式出现在工作流日志中。
修复方法: 对敏感值使用 $GITHUB_OUTPUT,切勿直接通过 echo 输出。
可复用工作流中的机密上下文错误
# ❌ WRONG - Parent secrets aren't automatically passed
jobs:
call-workflow:
uses: ./.github/workflows/deploy.yml
# secrets: inherit not specified!
# ✅ CORRECT
jobs:
call-workflow:
uses: ./.github/workflows/deploy.yml
secrets: inherit # ← Pass all parent secrets
错误消息: 工作流运行了,但被调用的工作流中的机密未定义。
修复方法: 调用需要机密的可复用工作流时,添加 secrets: inherit。
3. 权限问题
问题: GITHUB_TOKEN 默认作用域有限,而且权限很容易配置错误。
常见问题:
令牌权限不足
# ❌ WRONG - Trying to write packages with default permissions
- name: Push to Docker registry
run: |
docker push ghcr.io/${{ github.repository }}:latest
# Fails with "permission denied" because GITHUB_TOKEN lacks 'packages: write'
# ✅ CORRECT - Explicitly grant permissions
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read # Read repo code
packages: write # Write Docker images
id-token: write # For OIDC token exchange
steps:
- uses: actions/checkout@v4
- name: Push to Docker registry
run: docker push ghcr.io/${{ github.repository }}:latest
错误消息: "authentication failed, permission denied" 或 API 返回 "Insufficient permissions"
修复方法: 始终在作业级别显式声明 permissions:,并指定所需作用域(contents、packages、id-token、pull-requests、issues、deployments 等)。
尝试使用 GITHUB_TOKEN 执行它无法完成的操作
# ❌ WRONG - GITHUB_TOKEN can't trigger other workflows
- name: Trigger deployment
run: |
curl -X POST https://api.github.com/repos/${{ github.repository }}/dispatches \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-d '{"event_type":"deploy"}'
# Fails silently - GITHUB_TOKEN lacks workflow permissions
# ✅ CORRECT - Use a PAT (Personal Access Token) or GitHub App token
- name: Trigger deployment
run: |
curl -X POST https://api.github.com/repos/${{ github.repository }}/dispatches \
-H "Authorization: token ${{ secrets.WORKFLOW_PAT }}" \
-d '{"event_type":"deploy"}'
错误消息: "Resource not accessible by integration"(HTTP 403)
修复方法: GITHUB_TOKEN 无法触发工作流(repository_dispatch)。请改用存储在 secrets 中的 PAT。
跨仓库访问失败
# ❌ WRONG - GITHUB_TOKEN only has access to current repo
- name: Clone another repo
run: |
git clone https://github.com/other-org/private-repo.git
# Fails - GITHUB_TOKEN has no access
# ✅ CORRECT - Use a PAT with repo access
- name: Clone another repo
run: |
git clone https://x-access-token:${{ secrets.CROSS_REPO_PAT }}@github.com/other-org/private-repo.git
错误消息: "fatal: could not read Username for 'https://github.com': terminal prompts disabled"
修复方法: 使用具有 repo 或 read:repo_hook 权限范围的 Personal Access Token(PAT)进行跨仓库访问。
4. 矩阵策略失败
问题: 矩阵构建功能强大,但当组合有误或错误使用 exclude/include 时,可能会悄无声息地失败。
常见陷阱:
步骤中未定义矩阵上下文
# ❌ WRONG - Using matrix variables that don't exist
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
# No 'version' defined here
steps:
- run: echo "Version is ${{ matrix.version }}" # ← Empty!
# ✅ CORRECT - Define all matrix variables used
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
version: ['1.0', '2.0']
steps:
- run: echo "Building for ${{ matrix.os }} v${{ matrix.version }}"
错误消息: 日志中的矩阵变量为空或未定义。
修复方法: 步骤中引用的所有变量都必须在 strategy.matrix 中定义。
exclude/include 语法错误
# ❌ WRONG - Invalid exclude syntax
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: ['18', '20']
exclude:
- os: windows-latest, node-version: '18' # ← Comma not allowed here
# ✅ CORRECT - Proper exclude syntax
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: ['18', '20']
exclude:
- os: windows-latest
node-version: '18'
# ✅ Using include for specific combinations
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
include:
- os: windows-latest
node-version: '20' # ← Only windows + node 20
错误消息: 工作流在验证阶段解析失败。
修复方法: exclude 和 include 使用 YAML 列表语法,每个属性各占一行。
笛卡尔积膨胀
# ❌ WRONG - Creates 4 × 3 × 2 × 5 = 120 jobs unexpectedly
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest, linux-arm64]
node-version: ['16', '18', '20']
npm-version: ['8', '9']
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
# This is excessive and wastes CI minutes
# ✅ CORRECT - Use include for specific combinations
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
node-version: '20'
npm-version: '9'
- os: macos-latest
node-version: '20'
npm-version: '9'
- os: windows-latest
node-version: '18'
npm-version: '8'
错误消息: 没有错误,但 CI 开支突然翻了四倍。
修复方法: 使用 include 定义特定组合,而不是让矩阵生成笛卡尔积。
5. 缓存错误
问题: GitHub Actions 的缓存策略较为保守——过期缓存可能保留数月,导致难以查明的构建失败。
关键问题:
过期缓存导致反复失败
# ❌ WRONG - Cache key doesn't change, stale deps stay cached
- uses: actions/cache@v3
with:
path: node_modules
key: deps-${{ runner.os }} # ← Never changes!
restore-keys: |
deps-${{ runner.os }}
# ✅ CORRECT - Include lockfile hash in cache key
- uses: actions/cache@v3
with:
path: node_modules
key: deps-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
deps-${{ runner.os }}-
错误消息: 构建在本地通过,却在 CI 中因难以理解的模块错误而失败。
修复方法: 始终在缓存键中包含依赖锁定文件的哈希值:npm 使用 ${{ hashFiles('**/package-lock.json') }},pip 使用 ${{ hashFiles('**/requirements.txt') }}。
语言运行时的缓存路径错误
# ❌ WRONG - Caching wrong path, cache misses happen
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20.x"
- uses: actions/cache@v3
with:
path: /tmp/node_modules # ← Wrong path!
key: deps-${{ hashFiles('package-lock.json') }}
# ✅ CORRECT - Let action handle caching, or use right path
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "20.x"
cache: "npm" # ← Let the action handle caching
# OR if manual caching:
- uses: actions/cache@v3
with:
path: ~/.npm # ← Correct npm cache location
key: npm-${{ hashFiles('package-lock.json') }}
错误消息: 工作流运行缓慢,反复下载依赖项。
修复方法: 使用 setup-node@v4 内置的 cache: 参数,或缓存语言运行时的官方缓存目录(例如 ~/.npm、~/.pip-cache)。
缓存失效竞争条件
# ❌ WRONG - Multiple branches writing to same cache
branches:
- main
- develop
- '*'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/cache@v3
with:
path: dist
key: build-${{ hashFiles('package.json') }}
# develop branch builds with old deps, overwrites cache
# main branch then gets develop's stale build artifacts
# ✅ CORRECT - Include branch in cache key or read-only on non-main
- uses: actions/cache@v3
with:
path: dist
key: build-${{ github.ref }}-${{ hashFiles('package.json') }}
restore-keys: |
build-refs/heads/main-
build-refs/heads/develop-
错误消息: 合并后出现难以查明的测试失败(缓存受到其他分支的污染)。
修复方法: 在缓存键中包含 ${{ github.ref }},以隔离各分支的缓存;或者在非主分支上使用只读模式。
Docker 层缓存未保留
# ❌ WRONG - Rebuilds every layer despite cache-from
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myimage:latest
# cache-from: type=gha missing!
# ✅ CORRECT - Use GitHub Actions cache backend
- uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myimage:latest
cache-from: type=gha
cache-to: type=gha,mode=max
错误消息: 尽管本地缓存正常工作,Docker 构建仍然非常缓慢。
修复方法: 始终在 docker/build-push-action 中包含 cache-from: type=gha 和 cache-to: type=gha,mode=max,以便在多次运行之间缓存各层。
调试工作流
工作流失败时的实用技巧:
- 启用调试日志: 在仓库设置中设置
ACTIONS_STEP_DEBUG=truesecret,以查看详细日志 - 检查权限: API 调用失败时,检查作业的
permissions:块 - 验证 YAML: 推送前,在本地对工作流文件运行
yamllint - 在本地测试矩阵: 在本地测试脚本中模拟矩阵组合
- 检查缓存: 在 GitHub 界面的“Actions” → “Caches”下查看缓存条目
- 检查 secrets: 确认所有
${{ secrets.NAME }}均已在仓库设置中定义
相关技能
gitlab-ci-patterns- 用于 GitLab CI 工作流deployment-pipeline-design- 用于流水线架构secrets-management- 用于 secrets 管理