前言
最近做了一个 apk,每次更新都要手动进行打包,再把 apk 分发出去,麻烦!
上网冲浪的时候,发现了这个 android_builder,发现 GitHub Actions
还是很香的,了解一下。
什么是 GitHub Actions
GitHub Actions 是 GitHub 推出的持续集成(CI/CD)服务,于 2018 年 10 月推出。它允许开发者在 GitHub 仓库中直接自动化软件开发工作流程。
核心概念:
- Workflow(工作流):自动化流程,由一个或多个 Job 组成
- Job(任务):一组在同一运行器上执行的步骤(Step)
- Step(步骤):单个任务,可以运行命令或使用 Action
- Action(动作):可复用的工作流代码单元,是最小的可移植构建块
- Runner(运行器):执行工作流的服务器,GitHub 提供托管运行器(Ubuntu、Windows、macOS)
主要优势:
- 🚀 与 GitHub 深度集成,无需第三方 CI/CD 工具
- 💰 对公开仓库免费,私有仓库每月有免费额度
- 🔧 丰富的预构建 Actions 可直接使用
- 🌐 支持多种操作系统和编程语言
- 📦 社区驱动,有大量开源 Actions 可用
基础语法
GitHub Actions 使用 YAML 格式配置文件,存放在仓库的 .github/workflows/
目录下。
基本结构
yaml
name: 工作流名称
# 触发条件
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# 任务列表
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v3
- name: 运行命令
run: echo "Hello, GitHub Actions!"
触发器(Triggers)
1. Push 事件
yaml
on:
push:
branches:
- main
- 'releases/**'
paths:
- '**.js'
2. Pull Request 事件
yaml
on:
pull_request:
types: [opened, synchronize, reopened]
3. 定时触发(Cron)
yaml
on:
schedule:
- cron: '0 0 * * *' # 每天午夜运行
4. 手动触发
yaml
on:
workflow_dispatch:
inputs:
environment:
description: '部署环境'
required: true
default: 'staging'
5. 多个事件组合
yaml
on: [push, pull_request, workflow_dispatch]
常用配置项
环境变量
yaml
env:
NODE_VERSION: '18'
jobs:
build:
runs-on: ubuntu-latest
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
steps:
- run: echo $NODE_VERSION
矩阵策略(Matrix)
yaml
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14, 16, 18]
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
条件执行
yaml
steps:
- name: 仅在主分支运行
if: github.ref == 'refs/heads/main'
run: echo "这是主分支"
依赖关系
yaml
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: npm run build
deploy:
needs: build # 等待 build 完成
runs-on: ubuntu-latest
steps:
- run: npm run deploy
实际应用示例
1. 前端项目 CI/CD
场景: React 项目的自动化测试、构建和部署
yaml
name: Frontend CI/CD
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 设置 Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: 代码检查
run: npm run lint
- name: 运行测试
run: npm test
- name: 构建项目
run: npm run build
- name: 部署到 GitHub Pages
if: github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
2. 后端测试
场景: Go 语言项目的自动化测试和代码覆盖率
yaml
name: Go API Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:14
env:
POSTGRES_PASSWORD: postgres
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: 设置 Go 环境
uses: actions/setup-go@v4
with:
go-version: '1.21'
- name: 下载依赖
run: go mod download
- name: 运行测试
run: go test -v -race -coverprofile=coverage.txt -covermode=atomic ./...
- name: 上传代码覆盖率
uses: codecov/codecov-action@v3
with:
files: ./coverage.txt
3. 自动发布版本
场景: 创建 Tag 时自动发布 Release
yaml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 构建二进制文件
run: |
GOOS=linux GOARCH=amd64 go build -o app-linux-amd64
GOOS=windows GOARCH=amd64 go build -o app-windows-amd64.exe
GOOS=darwin GOARCH=amd64 go build -o app-darwin-amd64
- name: 创建 Release
uses: softprops/action-gh-release@v1
with:
files: |
app-linux-amd64
app-windows-amd64.exe
app-darwin-amd64
body: |
## 更新内容
- 功能改进
- Bug 修复
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4. 定时任务
场景: 每天自动爬取数据并提交
yaml
name: Daily Data Sync
on:
schedule:
- cron: '0 2 * * *' # 每天凌晨 2 点
workflow_dispatch: # 支持手动触发
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 设置 Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: 安装依赖
run: pip install -r requirements.txt
- name: 运行爬虫
run: python scraper.py
- name: 提交更改
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add data/
git diff --quiet && git diff --staged --quiet || (git commit -m "chore: update data [skip ci]" && git push)
5. Docker 镜像构建与发布
场景: 自动构建并推送 Docker 镜像到 Docker Hub
yaml
name: Docker Build and Push
on:
push:
branches: [ main ]
tags: [ 'v*' ]
jobs:
docker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v2
- name: 登录 Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: 提取元数据
id: meta
uses: docker/metadata-action@v4
with:
images: myusername/myapp
- name: 构建并推送
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
6. 代码质量检查
场景: 自动进行代码审查和安全扫描
yaml
name: Code Quality
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 运行 ESLint
uses: reviewdog/action-eslint@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 运行安全扫描
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
format: 'sarif'
output: 'trivy-results.sarif'
- name: 上传扫描结果
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
运行机制
工作原理
-
事件触发:当仓库中发生特定事件(push、PR、issue 等)时,GitHub 会检查是否有对应的工作流配置
-
Runner 分配:GitHub 从 Runner 池中分配一个可用的运行器(或使用自托管 Runner)
-
环境准备:
- 创建虚拟环境(VM 或容器)
- 克隆仓库代码
- 设置环境变量
-
执行步骤:
- 按顺序执行每个 Step
- 每个 Step 可以是 Shell 命令或 Action
- Step 之间共享文件系统但不共享环境变量(除非显式传递)
-
结果报告:
- 收集执行日志
- 报告成功/失败状态
- 可选:发送通知、创建 Check Run
Action 复用机制
Action 可以通过三种方式引用:
- 公共仓库 :
uses: actions/checkout@v3
- 私有仓库 :
uses: owner/repo@ref
- 本地路径 :
uses: ./.github/actions/my-action
Action 本质是:
- JavaScript Action:Node.js 脚本
- Docker Action:Docker 容器
- Composite Action:组合多个步骤
Secrets 管理
GitHub Actions 使用加密存储来保护敏感信息:
- Secrets 在传输和存储时都经过加密
- 日志输出会自动屏蔽 Secrets 内容
- Secrets 仅对有权限的工作流可见
- 支持仓库级、组织级和环境级 Secrets
并发与限制
并发限制:
- 公共仓库:20 个并发任务
- 私有仓库:根据计费方案不同(5-180 个)
使用限制:
- 每个工作流最多运行 72 小时
- 每个 Job 最多 6 小时
- API 请求限制:1000 次/小时
- Artifact 存储:90 天自动删除
免费额度(私有仓库):
- Linux:2000 分钟/月
- Windows:1000 分钟/月(2 倍计费)
- macOS:200 分钟/月(10 倍计费)