📚 为什么要用 GitHub Actions 自动化部署 AI Agent?
话说江湖传闻,有个程序员每天手动部署OpenClaw,结果有一天他突然顿悟:"我这是在用AI,为啥还要手动干活?"
于是,GitHub Actions 降临了。它就像是给你的AI Agent请了个24小时不睡觉的管家,你只管写代码,剩下的事儿它全包了。
"手动部署一时爽,一直手动一直爽?不不不,自动化才是真的爽!GitHub Actions让你从重复劳动中解脱,去做更有创造力的事情。"
🎯 核心价值
⏰ 时间就是生命
手动部署一次要15分钟?GitHub Actions让你喝口茶的功夫就搞定了。人生苦短,何必浪费在重复劳动上?
🎯 一致性保证
人总会犯错,但机器不会。每次部署都是标准化的流程,再也不用担心"在我机器上能跑"的尴尬。
🔄 快速迭代
push代码 → 自动测试 → 自动部署 → 自动通知。整个流程丝滑如德芙,让你专注在代码本身。
🛡️ 安全合规
自动执行安全扫描、代码审查、依赖检查。就像给你的Agent装了个24小时监控摄像头。
📊 可视化管理
每一次部署都有详细日志,出了问题秒定位。比查水表还清楚。
🌍 多环境支持
开发、测试、生产环境一键切换。就像切换电视频道一样简单(暴露年龄的比喻)。
🔄 典型 CI/CD 工作流
┌─────────────┐
│ 开发者提交代码 │
│ (git push) │
└──────┬──────┘
│
▼
┌─────────────┐
│ GitHub Actions │
│ 触发工作流 │
└──────┬──────┘
│
├─▶ 代码检查 (Lint)
├─▶ 单元测试
├─▶ 构建 Docker 镜像
├─▶ 推送到镜像仓库
├─▶ 部署到环境
└─▶ 发送通知
🛠️ 配置步骤详解
第一步:创建 GitHub Actions 工作流文件
在你的OpenClaw项目根目录下,创建 .github/workflows/deploy.yml 文件。这个文件就像是给你的AI Agent写的操作手册。
📁 目录结构
your-openclaw-project/
├── .github/
│ └── workflows/
│ └── deploy.yml ← 这就是我们要创建的文件
├── Dockerfile
├── openclaw.json
└── skills/
第二步:编写基础工作流配置
下面是一个基础的OpenClaw部署工作流配置,包含了从代码检查到部署的完整流程:
name: OpenClaw CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
env:
DOCKER_REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: 运行 Lint
run: npm run lint
- name: 运行测试
run: npm test
- name: 检查 OpenClaw 配置
run: |
npm install -g openclaw
openclaw config validate
build:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: 登录到 GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 构建 Docker 镜像
run: |
docker build -t ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest .
docker tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: 推送 Docker 镜像
run: |
docker push ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
docker push ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
记得在 GitHub 仓库的 Settings → Secrets and variables → Actions 中添加必要的 secrets,比如 GITHUB_TOKEN(通常自动提供)和其他敏感信息。
第三步:配置多环境部署
真实世界的部署通常有多个环境,让我们来配置一个完整的多环境部署策略:
deploy-dev:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
environment: development
steps:
- name: 部署到开发环境
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.DEV_SERVER_HOST }}
username: ${{ secrets.DEV_SERVER_USER }}
key: ${{ secrets.DEV_SERVER_SSH_KEY }}
script: |
cd /opt/openclaw
docker-compose pull
docker-compose up -d
docker system prune -f
- name: 健康检查
run: |
sleep 10
curl -f http://${{ secrets.DEV_SERVER_HOST }}:3000/health || exit 1
- name: 发送飞书通知
if: always()
uses: foxundermoon/feishu-action@v2
with:
url: ${{ secrets.FEISHU_WEBHOOK_URL }}
msg_type: text
content: |
开发环境部署完成 ✅
提交: ${{ github.sha }}
作者: ${{ github.actor }}
状态: ${{ job.status }}
deploy-prod:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- name: 手动审批
uses: trstringer/manual-approval@v1
with:
secret: ${{ github.TOKEN }}
approvers: admin1,admin2
minimum-approvals: 1
- name: 部署到生产环境
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.PROD_SERVER_HOST }}
username: ${{ secrets.PROD_SERVER_USER }}
key: ${{ secrets.PROD_SERVER_SSH_KEY }}
script: |
cd /opt/openclaw
docker-compose pull
docker-compose up -d --no-deps openclaw
docker system prune -f
- name: 发送部署通知
if: always()
run: |
curl -X POST ${{ secrets.DISCORD_WEBHOOK_URL }} \
-H "Content-Type: application/json" \
-d '{
"embeds": [{
"title": "🚀 OpenClaw 生产环境部署",
"description": "部署完成",
"color": 65280,
"fields": [
{"name": "版本", "value": "${{ github.sha }}", "inline": true},
{"name": "状态", "value": "${{ job.status }}", "inline": true}
]
}]
}'
🏆 最佳实践
🎯 分支策略:Git Flow 的妙趣版
- main 分支:生产环境专属,只接受来自 develop 的合并
- develop 分支:开发主分支,所有新功能都从这里出发
- feature/* 分支:功能开发分支,开发完成后合并回 develop
- hotfix/* 分支:紧急修复分支,直接合并到 main 和 develop
🔐 环境管理:安全第一
使用 GitHub Environments
在 GitHub 仓库设置中配置 Environments(环境),可以:
- 设置环境变量(加密存储)
- 配置部署保护规则(必需审批)
- 限制哪些分支可以部署到该环境
# 示例:在不同环境中使用不同的配置
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ github.ref == 'refs/heads/main' && 'production' || 'development' }}
steps:
- name: 使用环境专属配置
run: |
echo "部署到 ${{ environment.name }} 环境"
./deploy.sh --env ${{ environment.name }}
env:
API_KEY: ${{ secrets.API_KEY }}
DB_URL: ${{ secrets.DB_URL }}
🧪 自动测试:Quality First
测试是自动化的基石,没有测试的CI/CD就像没有调料的方便面——能吃,但没味儿。
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- name: 使用 Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: 运行单元测试
run: npm run test:unit
- name: 运行集成测试
run: npm run test:integration
env:
OPENCLAW_TEST_MODE: true
- name: 运行 Skills 测试
run: |
npm install -g openclaw
openclaw skills test --all
- name: 上传测试报告
if: always()
uses: actions/upload-artifact@v4
with:
name: test-reports-${{ matrix.node-version }}
path: |
coverage/
test-results/
🏷️ 版本自动标记:让版本管理飞起来
每次部署都手动打tag?太土了!让GitHub Actions自动帮你做:
tag-version:
needs: deploy-prod
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 生成版本号
id: version
run: |
VERSION=$(date +'%Y.%m.%d')-${{ github.run_number }}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "生成的版本号: $VERSION"
- name: 创建 Git Tag
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git tag -a v${{ steps.version.outputs.version }} -m "自动发布版本 v${{ steps.version.outputs.version }}"
git push origin v${{ steps.version.outputs.version }}
- name: 创建 GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version.outputs.version }}
name: Release v${{ steps.version.outputs.version }}
body: |
## 🚀 自动发布
本次发布包含以下变更:
${{ github.event.head_commit.message }}
## 📦 Docker 镜像
```bash
docker pull ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}
```
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
💻 完整 Workflow 文件代码示例
下面是一个生产级别的完整 GitHub Actions workflow 文件,包含了所有最佳实践:
name: OpenClaw 完整 CI/CD 流程
on:
push:
branches: [ main, develop, 'feature/*' ]
pull_request:
branches: [ main, develop ]
# 环境变量
env:
DOCKER_REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
NODE_VERSION: '22'
# 权限设置
permissions:
contents: read
packages: write
deployments: write
jobs:
# ==================== 第一阶段:代码质量检查 ====================
lint-and-format:
name: 🔍 代码质量检查
runs-on: ubuntu-latest
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: 运行 ESLint
run: npm run lint
- name: 检查代码格式
run: npm run format:check
- name: 类型检查
run: npm run type-check
# ==================== 第二阶段:测试 ====================
test:
name: 🧪 运行测试
runs-on: ubuntu-latest
needs: lint-and-format
strategy:
matrix:
test-group: [unit, integration, e2e]
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置 Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- name: 安装依赖
run: npm ci
- name: 运行 ${{ matrix.test-group }} 测试
run: npm run test:${{ matrix.test-group }}
env:
OPENCLAW_TEST_MODE: true
OPENCLAW_LOG_LEVEL: debug
- name: 上传测试报告
if: always()
uses: actions/upload-artifact@v4
with:
name: test-report-${{ matrix.test-group }}
path: coverage/
# ==================== 第三阶段:构建 ====================
build:
name: 🏗️ 构建 Docker 镜像
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
image-digest: ${{ steps.build.outputs.digest }}
steps:
- name: 检出代码
uses: actions/checkout@v4
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3
- name: 登录到 GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 提取元数据
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=sha,format=short
type=schedule,pattern={{date 'YYYYMMDD'}}
- name: 构建并推送
id: build
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
build-args: |
NODE_VERSION=${{ env.NODE_VERSION }}
BUILD_DATE=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}
# ==================== 第四阶段:部署到开发环境 ====================
deploy-dev:
name: 🚀 部署到开发环境
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/develop'
environment:
name: development
url: https://dev.openclaw.example.com
steps:
- name: 部署到服务器
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USER }}
key: ${{ secrets.DEV_SSH_KEY }}
script: |
cd /opt/openclaw-dev
echo "拉取最新镜像..."
docker-compose -f docker-compose.dev.yml pull
echo "重启服务..."
docker-compose -f docker-compose.dev.yml up -d --remove-orphans
echo "清理旧镜像..."
docker system prune -f
echo "部署完成!"
- name: 健康检查
run: |
echo "等待服务启动..."
sleep 15
for i in {1..5}; do
if curl -f https://dev.openclaw.example.com/health; then
echo "✅ 健康检查通过"
exit 0
fi
echo "重试 $i/5..."
sleep 10
done
echo "❌ 健康检查失败"
exit 1
- name: 发送飞书通知
if: always()
uses: foxundermoon/feishu-action@v2
with:
url: ${{ secrets.FEISHU_WEBHOOK_DEV }}
msg_type: interactive
content: |
{
"config": {"wide_screen_mode": true},
"elements": [
{"tag": "div", "text": {"tag": "lark_md", "content": "**🚀 开发环境部署完成**"}},
{"tag": "div", "text": {"tag": "lark_md", "content": "**版本:** ${{ github.sha }}\n**分支:** develop\n**状态:** ${{ job.status }}\n**执行者:** ${{ github.actor }}"}},
{"tag": "action", "actions": [{"tag": "button", "text": {"tag": "plain_text", "content": "查看详情"}, "url": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}", "type": "default"}]}
]
}
# ==================== 第五阶段:部署到生产环境 ====================
deploy-prod:
name: 🎯 部署到生产环境
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://openclaw.example.com
steps:
- name: 审批检查
run: echo "等待生产环境部署审批..."
- name: 部署到生产服务器
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.PROD_HOST }}
username: ${{ secrets.PROD_USER }}
key: ${{ secrets.PROD_SSH_KEY }}
script: |
cd /opt/openclaw-prod
echo "📦 拉取最新镜像..."
docker-compose pull openclaw
echo "🔄 滚动更新服务..."
docker-compose up -d --no-deps openclaw
echo "🧹 清理旧资源..."
docker system prune -f
echo "✅ 部署完成!"
- name: 生产环境健康检查
run: |
echo "等待服务完全启动..."
sleep 30
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" https://openclaw.example.com/health)
if [ "$RESPONSE" = "200" ]; then
echo "✅ 生产环境健康检查通过"
else
echo "❌ 生产环境健康检查失败 (HTTP $RESPONSE)"
exit 1
fi
- name: 创建 GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ github.run_number }}
name: "Release v${{ github.run_number }} (Production)"
body: |
## 🎉 生产环境发布
**版本:** v${{ github.run_number }}
**提交:** ${{ github.sha }}
**发布时间:** ${{ github.event.head_commit.timestamp }}
### 📝 变更日志
${{ github.event.head_commit.message }}
### 🔗 相关链接
- [查看提交](https://github.com/${{ github.repository }}/commit/${{ github.sha }})
- [完整日志](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: 发送多渠道通知
if: always()
run: |
# 飞书通知
curl -X POST ${{ secrets.FEISHU_WEBHOOK_PROD }} \
-H "Content-Type: application/json" \
-d '{
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "🎯 生产环境部署",
"content": [[
{"tag": "text", "text": "部署完成\n版本: v${{ github.run_number }}\n状态: ${{ job.status }}"}
]]
}
}
}
}'
# Discord 通知
curl -X POST ${{ secrets.DISCORD_WEBHOOK_URL }} \
-H "Content-Type: application/json" \
-d '{
"embeds": [{
"title": "🚀 OpenClaw Production Deploy",
"color": 65280,
"fields": [
{"name": "Version", "value": "v${{ github.run_number }}", "inline": true},
{"name": "Commit", "value": "${{ github.sha }}", "inline": true},
{"name": "Status", "value": "${{ job.status }}", "inline": true}
]
}]
}'
# ==================== 工作流运行后清理 ====================
cleanup:
name: 🧹 清理
runs-on: ubuntu-latest
if: always()
needs: [lint-and-format, test, build, deploy-dev, deploy-prod]
steps:
- name: 清理临时文件
run: echo "清理完成"
"有些部署,就像重庆森林里的凤梨罐头,过期了就再也回不来了。但有了GitHub Actions,每一次部署都像是王家卫电影里的镜头——精准、优雅、从不拖泥带水。"
🔗 相关链接
"曾经有一份完美的CI/CD配置摆在我面前,我没有珍惜,直到上线前一晚才后悔莫及。人世间最痛苦的事莫过于此。如果上天给我一个机会再来一次,我会对那个YAML文件说三个字:我会写。如果非要在这份配置上加一个版本号,我希望是——v1.0.0!"