GitHub Actions 完全指南
GitHub Actions 完全指南:从入门到精通
目录
- 前言:为什么选择 GitHub Actions?
- 基础概念详解
- 快速入门示例
- 工作流配置全解析
- 实战项目一:自动化测试与代码质量
- 实战项目二:自动化构建与部署
- 实战项目三:自动化发布与版本控制
- 高级特性与优化技巧
- 最佳实践与经验总结
- 常见问题与解决方案
- 扩展资源与工具推荐
前言:为什么选择 GitHub Actions?
公司的 Jenkins 服务器时不时就要处理磁盘空间不足、构建队列堵塞、插件版本冲突这些问题。后来接触到 GitHub Actions,才发现原来 CI/CD 还可以这么省心。
GitHub Actions 的优势主要体现在这几点:
- 零维护成本:不用自己搭建服务器,省去了运维的烦恼
- 配置即代码:所有配置都在
.github/workflows
目录下,可以像管理代码一样管理 CI/CD 流程 - 完整生态:GitHub Marketplace 上有海量现成的 Actions 可以直接使用
- 平台整合:和 GitHub 的 Issues、Projects、Pull Requests 等功能无缝集成
不过光说这些可能还是比较抽象,接下来我们通过实际的例子,一步步地把 GitHub Actions 吃透。
基础概念详解
在动手之前,我们先理清楚几个核心概念。说实话,我一开始也经常搞混,后来总结了个简单的公式:
Workflow(工作流) = Events(触发事件) + Jobs(任务) + Steps(步骤) + Actions(操作)
1. Workflow(工作流)
工作流就像是一个流水线,定义了从开始到结束的整个自动化过程。它包含了以下要素:
- 存放位置:
.github/workflows
目录 - 文件格式:YAML 格式(
.yml
或.yaml
) - 触发条件:什么情况下会执行
- 执行内容:具体要做哪些事情
2. Events(事件)
事件就是触发工作流的条件。常见的事件类型包括:
# 支持的事件类型示例
on:
push: # 推送代码时触发
branches: [ main ] # 只针对特定分支
pull_request: # PR 时触发
types: [opened, synchronized, reopened]
schedule: # 定时触发
- cron: '0 0 * * *' # 每天零点执行
workflow_dispatch: # 手动触发
repository_dispatch: # 外部事件触发
3. Jobs(任务)
任务是工作流中的执行单元,可以包含一个或多个步骤:
jobs:
build: # 任务名称
name: 构建应用 # 显示名称
runs-on: ubuntu-latest # 运行环境
environment: production # 环境名称
timeout-minutes: 30 # 超时时间
continue-on-error: false # 是否忽略错误
concurrency: production_deploy # 并发控制
每个 Job 都可以配置这些属性:
runs-on
:指定运行环境(ubuntu-latest, windows-latest, macos-latest)environment
:部署环境(比如 staging, production)timeout-minutes
:任务超时时间continue-on-error
:是否允许失败后继续执行concurrency
:控制并发执行needs
:依赖其他任务
4. Steps(步骤)
步骤是任务中的最小执行单元,按顺序执行:
steps:
- name: 检出代码 # 步骤名称
uses: actions/checkout@v2 # 使用现成的 Action
- name: 自定义命令 # 自定义步骤
run: | # 执行命令
echo "Hello"
date
shell: bash # 指定 shell
- name: 条件执行 # 带条件的步骤
if: github.ref == 'refs/heads/main'
run: echo "仅在 main 分支执行"
步骤的属性说明:
name
:步骤名称(可选)uses
:使用已有的 Actionrun
:执行命令shell
:命令解释器if
:执行条件env
:环境变量working-directory
:工作目录
5. Actions(操作)
Actions 是可重用的工作流程单元,可以是:
- 官方 Actions:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- 社区 Actions:
- uses: JamesIves/[email protected]
- 自定义 Actions:
- uses: ./.github/actions/my-action
快速入门示例
好了,概念讲完了,我们来动手创建第一个工作流。
第一步:创建工作流文件
- 在你的项目根目录下创建
.github/workflows
目录:
mkdir -p .github/workflows
- 创建工作流文件
hello.yml
:
name: Hello World
on: [push]
jobs:
hello:
runs-on: ubuntu-latest
steps:
- name: Hello Step
run: echo "Hello GitHub Actions!"
第二步:提交并推送
git add .github/workflows/hello.yml
git commit -m "Add first workflow"
git push
这时候去 GitHub 仓库的 Actions 页面,就能看到工作流执行的情况了。
工作流配置全解析
现在让我们深入了解工作流配置的各个部分。
1. 触发器配置
# 单一事件
on: push
# 多个事件
on: [push, pull_request]
# 详细配置
on:
push:
branches:
- main
- 'releases/**'
paths:
- '**.js'
- '**.jsx'
tags:
- 'v*'
pull_request:
types: [opened, synchronize]
branches: [main]
schedule:
- cron: '0 0 * * *'
2. 环境和密钥配置
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
API_KEY: ${{ secrets.API_KEY }}
steps:
- name: 使用环境变量
run: |
echo "数据库地址: $DATABASE_URL"
echo "API密钥: $API_KEY"
如何添加密钥:
- 进入仓库设置
- 选择 Secrets and variables -> Actions
- 点击 New repository secret
- 添加名称和值
3. 依赖和缓存配置
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache node modules
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install Dependencies
run: npm ci
实战项目一:自动化测试与代码质量
让我们创建一个完整的测试工作流,包含代码检查、单元测试和覆盖率报告。
name: Test & Quality Check
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install Dependencies
run: |
npm ci
npm install -g eslint jest
- name: Lint Check
run: eslint . --ext .js,.jsx
- name: Run Tests
run: jest --coverage
- name: Upload Coverage
uses: actions/upload-artifact@v2
with:
name: coverage
path: coverage/
- name: Comment Coverage
uses: romeovs/[email protected]
with:
lcov-file: ./coverage/lcov.info
github-token: ${{ secrets.GITHUB_TOKEN }}
实战项目二:自动化构建与部署
接下来是一个完整的构建和部署流程。
name: Build & Deploy
on:
push:
branches: [ main ]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install and Build
run: |
npm ci
npm run build
- name: Setup Docker
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push Docker Image
uses: docker/build-push-action@v2
with:
context: .
push: true
tags: user/app:latest
- name: Deploy to Production
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
docker pull user/app:latest
docker stop app || true
docker rm app || true
docker run -d --name app user/app:latest
实战项目三:自动化发布与版本控制
这个例子展示如何自动化发布流程:
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
- name: Build Assets
run: |
npm ci
npm run build
- name: Generate Changelog
run: |
echo "## What's Changed" > CHANGELOG.md
git log $(git describe --tags --abbrev=0)..HEAD --pretty=format:"* %s" >> CHANGELOG.md
- name: Upload Release Assets
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dist/app.zip
asset_name: app.zip
asset_content_type: application/zip
高级特性与优化技巧
1. 矩阵构建
测试多个版本或平台:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
node: [12, 14, 16]
steps:
- uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
2. 工作流复用
创建可复用的工作流:
# .github/workflows/reusable.yml
name: Reusable Workflow
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
token:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Deploy
run: echo "Deploying to ${{ inputs.environment }}"
# 调用可复用工作流
jobs:
call-workflow:
uses: ./.github/workflows/reusable.yml
with:
environment: 'production'
secrets:
token: ${{ secrets.DEPLOY_TOKEN }}
3. 并发控制
避免同时部署导致的冲突:
jobs:
deploy:
runs-on: ubuntu-latest
concurrency:
group: production_deploy
cancel-in-progress: true # 取消正在进行的部署
steps:
- name: Deploy
run: echo "Deploying..."
4. 条件执行与作业依赖
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Run Tests
run: npm test
deploy-staging:
needs: test # 依赖 test 作业
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
steps:
- name: Deploy to Staging
run: echo "Deploying to staging..."
deploy-prod:
needs: [test, deploy-staging] # 依赖多个作业
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Deploy to Production
run: echo "Deploying to production..."
5. 自定义 Actions
有时候我们需要封装一些常用的操作,这时就可以创建自己的 Action。
- 首先创建 Action 配置文件:
# .github/actions/custom-action/action.yml
name: 'Custom Action'
description: '这是一个自定义 Action'
inputs:
message:
description: '要显示的消息'
required: true
default: 'Hello'
outputs:
time:
description: '执行时间'
runs:
using: 'node16'
main: 'index.js'
- 创建 Action 的实现代码:
// .github/actions/custom-action/index.js
const core = require('@actions/core');
try {
// 获取输入
const message = core.getInput('message');
// 执行操作
console.log(`Message: ${message}`);
// 设置输出
core.setOutput('time', new Date().toISOString());
} catch (error) {
core.setFailed(error.message);
}
- 在工作流中使用自定义 Action:
jobs:
custom:
runs-on: ubuntu-latest
steps:
- uses: ./.github/actions/custom-action
with:
message: '自定义消息'
实战技巧:性能优化
1. 构建缓存优化
jobs:
build:
runs-on: ubuntu-latest
steps:
# NPM 依赖缓存
- name: Cache Dependencies
uses: actions/cache@v2
with:
path: |
~/.npm
node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
# Gradle 缓存
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
# Docker 层缓存
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
2. 作业优化技巧
- 合理使用 if 条件:
steps:
- name: Build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: npm run build
- name: Skip on Pull Request
if: github.event_name != 'pull_request'
run: echo "Skipping on PR"
- 超时控制:
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 30 # 设置作业超时时间
steps:
- name: Long Running Step
timeout-minutes: 10 # 设置步骤超时时间
run: echo "Running..."
- 失败处理:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Test
continue-on-error: true # 即使失败也继续执行
run: npm test
- name: Notify on Failure
if: failure() # 仅在失败时执行
uses: actions/github-script@v5
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '测试失败通知',
body: '工作流执行失败,请检查'
})
监控与通知
1. Slack 通知
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Slack Notification
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
fields: repo,message,commit,author,action,eventName,ref,workflow
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
if: always() # 无论成功失败都通知
2. 邮件通知
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Send Email
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 465
username: ${{ secrets.EMAIL_USERNAME }}
password: ${{ secrets.EMAIL_PASSWORD }}
subject: 构建通知 - ${{ github.repository }}
body: 工作流 ${{ github.workflow }} 执行${{ job.status }}
to: [email protected]
from: GitHub Actions
3. 状态检查
jobs:
health-check:
runs-on: ubuntu-latest
steps:
- name: Check Deployment
uses: jtalk/url-health-check-action@v2
with:
url: http://example.com/health
max-attempts: 3
retry-delay: 5s
最佳实践与安全建议
1. 安全最佳实践
- 使用最小权限原则
- 定期更新 Action 版本
- 使用 GITHUB_TOKEN 而不是个人访问令牌
- 加密敏感信息
jobs:
security:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Security Scan
uses: github/codeql-action/analyze@v1
with:
languages: javascript
2. 工作流组织建议
- 将相关的工作流放在同一目录
- 使用有意义的文件名
- 添加适当的注释
.github/workflows/
├── ci.yml # 持续集成
├── cd-staging.yml # 测试环境部署
├── cd-prod.yml # 生产环境部署
└── security.yml # 安全扫描
3. 调试技巧
- 启用调试日志:
# 设置仓库密钥
ACTIONS_RUNNER_DEBUG=true
ACTIONS_STEP_DEBUG=true
- 使用 tmate 进行远程调试:
steps:
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
if: ${{ failure() }}
常见问题与解决方案
- 构建失败问题
- 检查依赖版本
- 验证环境变量
- 查看详细日志
- 权限问题
jobs:
fix-permissions:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v2
with:
token: ${{ secrets.GITHUB_TOKEN }}
- 超时问题
- 优化构建步骤
- 增加超时时间
- 使用缓存
- 资源限制问题
- 清理工作空间
- 减少并发作业
- 优化构建过程
高级用例
1. 多环境部署
jobs:
deploy:
runs-on: ubuntu-latest
strategy:
matrix:
environment: [dev, staging, prod]
include:
- environment: dev
url: 'https://dev.example.com'
- environment: staging
url: 'https://staging.example.com'
- environment: prod
url: 'https://example.com'
environment:
name: ${{ matrix.environment }}
url: ${{ matrix.url }}
steps:
- name: Deploy
run: |
echo "Deploying to ${{ matrix.environment }}"
echo "URL: ${{ matrix.url }}"
2. 自动化文档生成
jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
- name: Generate Docs
run: |
npm ci
npm run docs
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs
3. 自动化发布流程
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v2
- name: Install dependencies
run: npm ci
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-release
结语
GitHub Actions 是一个强大的自动化工具,通过本文的学习,你应该已经掌握了从基础到高级的各种使用技巧。记住,自动化的目的是为了提高效率,选择合适的自动化策略比盲目追求自动化更重要。
最后,我建议你:
- 从小步骤开始,逐渐扩展
- 保持工作流的简单和可维护性
- 经常检查和优化现有的工作流
- 关注 GitHub Actions 的更新和新特性
如果你在使用过程中遇到任何问题,欢迎在评论区讨论。让我们一起打造更好的自动化工作流!