在运维AI应用时,我们经常需要不断更新代码并重新部署。每次手动SSH登录服务器、拉取代码、编译并重启服务不仅繁琐,还容易出错。本文将分享如何利用GitHub Actions实现OpenHands(一个私有的AI编程助手)的全自动部署流程,让代码一旦推送到GitHub仓库就能自动部署到生产服务器,无需任何人工干预。
现状问题
目前,我们的部署流程相当繁琐:
1. ssh登录服务器
2. tmux a -t DaTou进入会话
3. Ctrl+C终止当前运行的程序
4. git pull拉取最新代码
5. make build编译代码
6. authbind --deep make run启动服务
这个过程完全是手动的,既浪费时间又容易因操作失误导致服务异常。如何实现全自动化呢?
解决方案对比
方案 | 复杂度 | 实时性 | 可观测性 | 适用场景 |
---|---|---|---|---|
Cron定时检查 | ★★☆☆☆ | ★★☆☆☆ | ★☆☆☆☆ | 简单项目、低频更新 |
Webhook触发部署 | ★★★☆☆ | ★★★★★ | ★★☆☆☆ | 中型项目、需要即时部署 |
GitHub Actions | ★★★☆☆ | ★★★★★ | ★★★★★ | 各种规模项目、需要完整部署流程 |
专业CI/CD平台 | ★★★★★ | ★★★★★ | ★★★★★ | 企业级应用、复杂部署需求 |
经过对比,GitHub Actions显然是最适合我们需求的解决方案:它能提供即时部署、完整记录,且与GitHub仓库无缝集成。
实施方案:使用GitHub Actions自动部署
第一步:准备服务器环境
首先,需要在服务器上设置SSH密钥,使GitHub Actions能够安全地连接:
# 在服务器上生成SSH密钥对
ssh-keygen -t ed25519 -C "github-actions-deploy"
# 一路回车即可,不要设置密码
# 将公钥添加到authorized_keys
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
第二步:创建部署脚本
在服务器上创建一个脚本来处理代码拉取、编译和重启服务的过程:
# 创建部署脚本
nano ~/deploy_openhands.sh
填入以下内容:
#!/bin/bash
# 设置工作目录和日志文件
REPO_DIR="/path/to/your/openhands/repo"
LOG_FILE="/path/to/deploy_logs.log"
CONDA_ENV="DaTou"
# 记录日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
# 切换到仓库目录
cd "$REPO_DIR" || { log "Failed to cd to $REPO_DIR"; exit 1; }
log "Starting deployment process"
# 拉取最新代码
log "Pulling latest code from repository"
git pull
# 初始化conda
log "Initializing conda environment"
# 以下行确保conda命令在bash中可用
source $(conda info --base)/etc/profile.d/conda.sh
# 激活conda环境
log "Activating conda environment: $CONDA_ENV"
conda activate $CONDA_ENV
# 编译代码
log "Building application"
make build
if [ $? -ne 0 ]; then
log "Build failed"
exit 1
fi
# 确保tmux会话存在
if ! tmux has-session -t DaTou 2>/dev/null; then
log "Creating new tmux session: DaTou"
tmux new-session -d -s DaTou
else
# 停止当前运行的程序
log "Stopping current application in tmux session"
tmux send-keys -t DaTou C-c
# 等待程序优雅退出
sleep 5
fi
# 启动应用程序
log "Starting application"
tmux send-keys -t DaTou "cd $REPO_DIR && authbind --deep make run" C-m
log "Deployment completed successfully"
别忘了使脚本可执行:
chmod +x ~/deploy_openhands.sh
第三步:设置GitHub仓库密钥
在GitHub仓库中添加必要的密钥:
- 进入GitHub仓库页面
- 点击"Settings" > "Secrets and variables" > "Actions"
- 点击"New repository secret"
- 添加以下密钥:
SSH_PRIVATE_KEY
: 服务器上生成的SSH私钥(cat ~/.ssh/id_ed25519
的内容)SSH_HOST
: 服务器IP或域名SSH_USER
: 服务器用户名(例如ubuntu
)SSH_PORT
: SSH端口(通常为22)
第四步:创建GitHub Actions工作流
在你的仓库中创建一个工作流文件:
mkdir -p .github/workflows
nano .github/workflows/deploy.yml
填入以下内容:
name: Deploy OpenHands
on:
push:
branches: [ main ] # 替换为你的主分支名称
# 手动触发选项
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
~/deploy_openhands.sh
第五步:确保系统重启后服务自动启动
创建一个systemd服务,确保服务器重启后应用自动启动:
sudo nano /etc/systemd/system/openhands.service
添加以下内容:
[Unit]
Description=OpenHands AI Assistant Service
After=network.target
[Service]
Type=oneshot
User=ubuntu # 替换为你的用户名
ExecStart=/bin/bash -c "tmux has-session -t DaTou || tmux new-session -d -s DaTou"
ExecStart=/bin/bash -c "tmux send-keys -t DaTou 'cd /path/to/your/openhands/repo && authbind --deep make run' C-m"
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
启用服务:
sudo systemctl enable openhands.service
sudo systemctl start openhands.service
工作原理
整个自动部署流程工作流程如下:
- 代码推送触发:当开发者将代码推送到GitHub仓库的主分支时,GitHub Actions自动触发
- 安全连接服务器:Actions使用SSH密钥安全连接到服务器
- 执行部署脚本:执行预先定义的部署脚本,完成代码拉取、编译和应用重启
- 日志记录:整个过程的日志都被记录,方便问题排查
GitHub Actions自动部署流程图 (点击展开)
高级配置与优化
添加部署通知
在工作流文件中添加部署通知:
steps:
# ... 其他步骤
- name: Send deployment notification
if: always()
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_COLOR: ${{ job.status }}
SLACK_TITLE: OpenHands Deployment
SLACK_MESSAGE: 'Deployment ${{ job.status }}'
添加部署前测试
确保代码质量后再部署:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: make test
deploy:
needs: test
runs-on: ubuntu-latest
# ... 部署步骤
区分环境配置
使用不同分支部署到不同环境:
on:
push:
branches:
- main # 生产环境
- staging # 测试环境
常见问题与解决方案
1. SSH连接失败
检查以下几点:
- 确保服务器防火墙允许SSH连接
- 验证SSH密钥格式是否正确(复制时可能丢失换行)
- 检查用户权限是否正确
解决方法:
# 检查SSH配置
sudo cat /etc/ssh/sshd_config | grep PubkeyAuthentication
# 确保值为yes
# 检查authorized_keys权限
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
2. 部署脚本执行失败
常见原因是路径错误或权限问题:
# 检查脚本可执行权限
chmod +x ~/deploy_openhands.sh
# 手动执行脚本并查看错误
bash -x ~/deploy_openhands.sh
3. 应用启动但无法访问
可能是端口绑定问题或防火墙设置:
# 检查应用是否正在运行
ps aux | grep make
# 检查端口是否被正确监听
sudo netstat -tulpn | grep 80
使用体验与效果
实施GitHub Actions自动部署后,我们的开发流程显著改善:
- 节省时间:从手动部署的10分钟减少到完全自动化
- 减少错误:消除了人工操作可能导致的失误
- 提高可见性:可以在GitHub界面上清晰看到每次部署的状态和日志
- 团队协作:团队成员无需了解服务器细节即可完成部署
部署频率从原来的每周2-3次增加到每天多次,大大加快了功能迭代和问题修复的速度。
总结
通过GitHub Actions实现自动部署,我们将繁琐的手动部署过程转变为完全自动化的工作流。这不仅提高了开发效率,还增强了系统稳定性。对于任何需要频繁更新的Web应用或AI服务,这种自动部署方案都是极具价值的。
最重要的是,这套方案易于实施且维护成本低,即使是小型团队也能轻松应用。相比专业CI/CD平台,GitHub Actions为我们提供了一个免费且强大的自动化部署解决方案。
如果你有任何自动部署的经验或其他方案,欢迎在评论区分享!