Skip to content

Act 本地 GitHub Actions 测试指南

概述

Act 是一个用于在本地运行 GitHub Actions 的工具,能够在不推送代码到 GitHub 的情况下测试和调试工作流程。本指南基于实际项目使用经验,详细介绍了 act 的配置、使用方法和常见问题解决方案。

安装

bash
# macOS
brew install act

# Linux
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

# Windows
choco install act-cli

# 或者使用 GitHub Releases 下载二进制文件

基础配置

1. 容器镜像配置

Act 使用 Docker 容器来模拟 GitHub Actions 环境。推荐使用官方镜像:

bash
# 创建 .actrc 文件配置默认镜像
echo "-P ubuntu-latest=catthehacker/ubuntu:act-latest" > ~/.actrc

# 指定容器架构(特别是在 Apple Silicon Mac 上)
echo "--container-architecture linux/amd64" >> ~/.actrc

2. Secrets 配置

创建 .secrets 文件管理敏感信息(重要:将此文件添加到 .gitignore):

bash
# .secrets 文件示例
GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
MY_SECRET=secret_value
API_KEY=your_api_key

最佳实践

  • Act 会自动读取项目根目录下的 .secrets 文件
  • 每行一个键值对,格式为 KEY=value
  • 注释行以 # 开头
  • 确保 .secrets 文件在 .gitignore

3. 环境变量配置

创建 .env 文件管理环境变量:

bash
# .env 文件示例
NODE_ENV=development
DEBUG=true

基本使用

常用命令

bash
# 列出所有工作流
act --list

# 运行默认事件 (push)
act

# 运行特定事件
act pull_request
act workflow_dispatch

# 运行特定工作流文件
act --workflows .github/workflows/ci.yml

# 运行特定 job
act --job test

# 干运行模式(不实际执行,仅验证语法)
act --dryrun

# 详细日志
act --verbose

事件数据配置

创建自定义事件文件

对于复杂的事件测试,可以创建自定义的事件 JSON 文件:

bash
# PR 事件示例
# .act-artifacts/test-pr-event.json
{
  "action": "synchronize",
  "number": 123,
  "pull_request": {
    "id": 123456789,
    "number": 123,
    "state": "open",
    "title": "Test PR",
    "user": {
      "login": "testuser"
    },
    "head": {
      "ref": "feature/test-branch",
      "sha": "abc123def456"
    },
    "base": {
      "ref": "master",
      "sha": "def456abc123"
    }
  },
  "repository": {
    "name": "your-repo",
    "full_name": "owner/your-repo"
  }
}
bash
# 手动触发事件示例
# .act-artifacts/test-workflow-dispatch.json
{
  "inputs": {
    "environment": "staging",
    "version": "1.0.0"
  },
  "repository": {
    "name": "your-repo",
    "full_name": "owner/your-repo"
  },
  "ref": "refs/heads/master"
}

使用自定义事件

bash
act pull_request --eventpath .act-artifacts/test-pr-event.json
act workflow_dispatch --eventpath .act-artifacts/test-workflow-dispatch.json

高级配置

本地 Actions 配置

当外部 Actions 下载失败时,可以使用本地 Actions:

bash
# 方法1: 使用 --local-repository 参数
act --local-repository actions/checkout@v4=~/.cache/act/actions-checkout@v4

# 方法2: 使用离线模式(需要预先下载)
act --action-offline-mode

# 方法3: 预先手动克隆 actions(解决认证问题)
git clone https://github.com/actions/checkout.git ~/.cache/act/actions-checkout@v4
git -C ~/.cache/act/actions-checkout@v4 checkout v4

网络代理配置

在网络受限环境下:

bash
# 设置代理
export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890

# 运行 act
act pull_request

Docker 配置优化

bash
# 使用特权模式(解决权限问题)
act --privileged

# 添加容器权限
act --container-cap-add SYS_PTRACE

# 禁用镜像拉取(如果已存在)
act --pull=false

# 保持容器用于调试
act --reuse

项目特定配置

性能测试工作流

基于我们的项目经验,测试性能工作流的完整配置:

bash
# 创建测试事件文件目录
mkdir -p .act-artifacts

# PR 触发测试事件
cat > .act-artifacts/test-pr-go-changes.json << 'EOF'
{
  "action": "synchronize",
  "number": 123,
  "pull_request": {
    "id": 123456789,
    "number": 123,
    "state": "open",
    "title": "Add new Go feature",
    "user": {"login": "testuser"},
    "head": {"ref": "feature/new-go-feature", "sha": "abc123def456"},
    "base": {"ref": "master", "sha": "def456abc123"}
  },
  "repository": {
    "name": "lz-stash",
    "full_name": "FixIterate/lz-stash"
  }
}
EOF

# 手动触发测试事件
cat > .act-artifacts/test-workflow-dispatch.json << 'EOF'
{
  "inputs": {
    "branch": "master",
    "benchmark_time": "5s"
  },
  "repository": {
    "name": "lz-stash",
    "full_name": "FixIterate/lz-stash"
  },
  "ref": "refs/heads/master"
}
EOF

# 运行测试命令
act pull_request \
  --workflows .github/workflows/performance-test.yml \
  --eventpath .act-artifacts/test-pr-go-changes.json \
  --secret-file .secrets \
  --platform ubuntu-latest=catthehacker/ubuntu:act-latest

act workflow_dispatch \
  --workflows .github/workflows/performance-test.yml \
  --eventpath .act-artifacts/test-workflow-dispatch.json \
  --secret-file .secrets \
  --platform ubuntu-latest=catthehacker/ubuntu:act-latest

Go 文件变更检测测试

创建脚本验证 Go 文件变更检测逻辑:

bash
# .act-artifacts/test-file-changes.sh
#!/bin/bash
set -e

echo "🧪 测试 Go 文件变更检测逻辑"

# 模拟不同的文件变更场景
test_scenarios=(
  "main.go cmd/cli.go"  # Go 文件变更 - 应该触发
  "README.md docs/api.md"  # 文档变更 - 不应该触发
  "go.mod go.sum"  # 依赖变更 - 应该触发
  "main.go README.md"  # 混合变更 - 应该触发
)

for scenario in "${test_scenarios[@]}"; do
  echo "📋 测试场景: $scenario"
  
  # 检测逻辑
  GO_FILES=$(echo "$scenario" | grep -E '\.(go|mod|sum)$' || true)
  
  if [ -n "$GO_FILES" ]; then
    echo "✅ 检测到 Go 文件变更,会触发性能测试"
  else
    echo "⏭️  未检测到 Go 文件变更,跳过性能测试"
  fi
  echo ""
done

常见问题与解决方案

1. Actions 下载认证问题

问题: authentication required: Support for password authentication was removed on August 13, 2021

原因:

  • GitHub 禁用了密码认证
  • 网络代理可能影响访问
  • 即使是公开仓库也可能遇到此问题

解决方案:

方法1: 使用 GitHub CLI 认证(推荐)

bash
# 方式1: 从项目 .secrets 文件读取 token
if [ -f .secrets ]; then
  TOKEN=$(grep "GITHUB_TOKEN=" .secrets | cut -d'=' -f2)
  echo "$TOKEN" | gh auth login --with-token
else
  echo "未找到 .secrets 文件"
fi

# 方式2: 从环境变量读取
export GITHUB_TOKEN=$(grep "GITHUB_TOKEN=" .secrets | cut -d'=' -f2)
echo "$GITHUB_TOKEN" | gh auth login --with-token

# 验证认证状态
gh auth status

方法2: 网络代理配置

bash
# 配置代理环境变量
export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890
export all_proxy=socks5://127.0.0.1:7890

# 运行 act(首次下载 actions)
act --dryrun

方法3: 使用离线模式(需要先成功下载一次)

bash
# 步骤1: 首次运行让 act 下载并缓存 actions
# 可能需要配置代理或认证
act --dryrun

# 步骤2: 后续使用离线模式,避免重复下载
act --action-offline-mode --dryrun

重要提示:

  • 避免使用 git 全局配置修改认证方式,这会影响所有 Git 操作,存在安全风险
  • 手动克隆 Actions 通常无效,除非明确使用 --action-offline-mode--local-repository 参数
  • 推荐先通过代理或 GitHub CLI 认证让 act 成功下载一次,然后使用离线模式
  • Act 会自动读取项目根目录下的 .secrets 文件,但 Actions 下载认证是独立的问题
  • 对于团队协作,建议在项目文档中说明网络配置要求

2. Docker 平台兼容性问题

问题: ARM64 vs AMD64 平台问题,特别是在 Apple Silicon Mac 上

解决方案:

bash
# 指定平台架构
act --platform ubuntu-latest=catthehacker/ubuntu:act-latest \
    --container-architecture linux/amd64

# 或者在 .actrc 中永久配置
echo "--container-architecture linux/amd64" >> ~/.actrc

3. 网络连接超时

问题: Actions 下载或容器拉取超时

解决方案:

bash
# 配置代理
export https_proxy=http://127.0.0.1:7890
export http_proxy=http://127.0.0.1:7890

# 使用 HTTP/1.1(避免 HTTP/2 问题)
git config --global http.version HTTP/1.1

# 增加超时时间
git config --global http.postBuffer 524288000

4. 容器权限问题

问题: 文件权限或系统调用权限不足

解决方案:

bash
# 使用特权模式
act --privileged

# 添加特定权限
act --container-cap-add SYS_PTRACE

# 绑定工作目录而不是复制
act --bind

5. Secrets 读取失败

问题: 工作流无法读取 secrets

解决方案:

  • 确保 .secrets 文件格式正确(KEY=value
  • 检查文件编码为 UTF-8
  • 使用 --secret-file 参数明确指定路径
  • 检查权限:chmod 600 .secrets

6. 工作流语法错误

问题: YAML 语法错误导致工作流无法解析

解决方案:

bash
# 使用 actionlint 检查语法
brew install actionlint
actionlint .github/workflows/*.yml

# 使用 act 干运行验证
act --dryrun

# 检查 YAML 语法
yamllint .github/workflows/

调试技巧

日志分析

bash
# 生成详细日志
act --verbose > act.log 2>&1

# 分析错误模式
grep -i error act.log
grep -i fail act.log
grep -i timeout act.log

# JSON 格式日志
act --json

分步调试

bash
# 仅验证语法
act --dryrun

# 运行特定 job
act --job test

# 保持容器用于调试
act --reuse

# 进入容器调试
docker exec -it <container_id> /bin/bash

性能分析

bash
# 禁用不必要的拉取
act --pull=false

# 禁用重建
act --rebuild=false

# 使用缓存
act --action-cache-path ~/.cache/act

最佳实践

1. 目录结构

建议的项目目录结构:

.act-artifacts/
├── test-events/           # 测试事件文件
│   ├── pr-go-changes.json
│   ├── workflow-dispatch.json
│   └── push-main.json
├── scripts/               # 测试脚本
│   ├── test-file-changes.sh
│   └── validate-workflow.sh
└── output/               # 测试输出
    ├── performance-results/
    └── logs/

2. 测试流程

推荐的测试流程:

  1. 静态验证: 使用 --dryrun 验证语法
  2. 单步测试: 使用 --job 测试特定任务
  3. 完整测试: 运行完整工作流
  4. 场景测试: 测试不同触发条件

3. CI/CD 集成

Pre-commit Hook

bash
#!/bin/bash
# .git/hooks/pre-commit

echo "🧪 运行 Act 测试..."
act --dryrun

if [ $? -ne 0 ]; then
  echo "❌ 工作流验证失败"
  exit 1
fi

echo "✅ 工作流验证通过"

Makefile 集成

makefile
# Makefile
.PHONY: test-workflows test-pr test-dispatch

test-workflows:
 @echo "🧪 测试所有工作流..."
 act --dryrun

test-pr:
 @echo "🧪 测试 PR 工作流..."
 act pull_request \
  --eventpath .act-artifacts/test-pr-go-changes.json \
  --secret-file .secrets

test-dispatch:
 @echo "🧪 测试手动触发工作流..."
 act workflow_dispatch \
  --eventpath .act-artifacts/test-workflow-dispatch.json \
  --secret-file .secrets

test-all: test-workflows test-pr test-dispatch

4. 性能优化

bash
# 创建 .actrc 配置文件
cat > ~/.actrc << 'EOF'
# 默认平台配置
-P ubuntu-latest=catthehacker/ubuntu:act-latest

# 容器架构
--container-architecture linux/amd64

# 缓存配置
--action-cache-path ~/.cache/act

# 性能优化
--pull=false
--rebuild=false
EOF

故障排除

常见错误处理

  1. 容器启动失败: 检查 Docker 服务和权限
  2. 网络连接问题: 配置代理或使用离线模式
  3. 权限问题: 使用 --privileged 或调整文件权限
  4. 资源不足: 增加 Docker 资源限制
  5. 版本不兼容: 更新 act 到最新版本

日志收集

bash
# 收集完整诊断信息
act --verbose --json > act-debug.log 2>&1

# 系统信息
act --version
docker --version
git --version

# 环境检查
echo "Act cache: $(ls -la ~/.cache/act/ 2>/dev/null || echo 'None')"
echo "Docker images: $(docker images | grep act)"

参考资源

总结

Act 是测试 GitHub Actions 的强大工具,通过合理配置和使用,可以大大提高 CI/CD 开发效率。关键要点:

  1. 正确配置环境: Secrets、环境变量、镜像
  2. 创建测试数据: 事件文件、输入参数
  3. 分步骤测试: 从语法验证到完整流程
  4. 处理常见问题: 网络、权限、兼容性
  5. 集成开发流程: Pre-commit、Makefile、脚本化

通过本指南的实践,能够有效地在本地环境中开发和调试 GitHub Actions 工作流。

实战经验总结

GitHub Actions 工作流测试实践

基于本项目的实际 GitHub Actions 故障排查和 act 测试经验:

工作流失败案例分析

问题场景: GitHub Actions 工作流 performance-test.yml 在 master 分支直接推送时失败

  • 原始问题: 工作流尝试为直接推送到 master 的提交查找对应的 PR,但直接推送没有关联的 PR
  • 失败步骤: "Find related PR" 步骤在 workflow_run 触发器下无法找到对应的 PR

解决方案:

  1. 改变触发策略: 从 workflow_run 改为 pull_request + workflow_dispatch
  2. 添加文件过滤: 仅在 Go 相关文件变更时触发性能测试
  3. 简化脚本逻辑: 避免在 GitHub Actions 中使用复杂的内联脚本

Act 测试配置最佳实践

推荐测试流程:

bash
# 1. 干运行验证语法
act pull_request --workflows .github/workflows/performance-test.yml \
  --eventpath .act-artifacts/test-pr-go-changes.json \
  --dryrun

# 2. 验证事件数据和触发条件
act workflow_dispatch --workflows .github/workflows/performance-test.yml \
  --eventpath .act-artifacts/test-workflow-dispatch.json \
  --dryrun

# 3. 实际执行测试(如果语法验证通过)
act pull_request --workflows .github/workflows/performance-test.yml \
  --eventpath .act-artifacts/test-pr-go-changes.json \
  --secret-file .secrets \
  --platform ubuntu-latest=catthehacker/ubuntu:act-latest

常见陷阱和避免方案

陷阱1: 网络认证问题

  • 现象: authentication required: Support for password authentication was removed
  • 误区: 认为需要为公开仓库配置认证
  • 正解: 配置代理或使用离线模式,避免修改全局 Git 配置

陷阱2: Actions 缓存失效

  • 现象: 手动克隆 Actions 后仍然重新下载
  • 误区: 认为手动克隆会被 act 自动识别
  • 正解: 必须配合 --action-offline-mode--local-repository 使用

陷阱3: 平台兼容性问题

  • 现象: 在 Apple Silicon Mac 上运行失败
  • 误区: 使用默认的 ARM64 容器
  • 正解: 明确指定 --container-architecture linux/amd64

项目特定配置示例

完整的 act 测试命令:

bash
# 配置环境
export https_proxy=http://127.0.0.1:7890  # 如需代理
export http_proxy=http://127.0.0.1:7890

# 运行测试
act pull_request \
  --workflows .github/workflows/performance-test.yml \
  --eventpath .act-artifacts/test-pr-go-changes.json \
  --secret-file .secrets \
  --platform ubuntu-latest=catthehacker/ubuntu:act-latest \
  --container-architecture linux/amd64 \
  --verbose

事件文件模板 (.act-artifacts/test-pr-go-changes.json):

json
{
  "action": "synchronize",
  "number": 123,
  "pull_request": {
    "id": 123456789,
    "number": 123,
    "state": "open",
    "title": "Add new Go feature",
    "user": {"login": "testuser"},
    "head": {"ref": "feature/new-go-feature", "sha": "abc123def456"},
    "base": {"ref": "master", "sha": "def456abc123"}
  },
  "repository": {
    "name": "lz-stash",
    "full_name": "FixIterate/lz-stash"
  }
}

教训和建议

  1. Always 先干运行: 使用 --dryrun 验证语法和逻辑,避免浪费时间
  2. 渐进式测试: 从单个 job 到完整工作流,逐步验证
  3. 事件数据准确性: 确保测试事件数据与实际场景匹配
  4. 网络环境隔离: 在网络受限环境下优先考虑离线模式
  5. 避免全局配置更改: 不要为了解决 act 问题而修改系统级 Git 配置

性能优化建议

bash
# 创建 .actrc 文件优化默认配置
cat > ~/.actrc << 'EOF'
-P ubuntu-latest=catthehacker/ubuntu:act-latest
--container-architecture linux/amd64
--action-cache-path ~/.cache/act
--action-offline-mode
EOF

这些实战经验能够帮助团队快速解决 act 使用中的常见问题,提高 CI/CD 开发效率。

基于 MIT 许可证发布