GitHub Actions CI/CD流水线配置教程:Node.js项目从测试到SSH自动部署
CHAPTER 1|先把流水线目标跑通
大家好,这期我们直接开终端实操。目标很明确:代码推送到 main 后,GitHub Actions 自动执行 npm ci、单元测试、构建,测试通过后再部署到 Linux 服务器。整个流程失败就停,不让有问题的代码碰生产环境。
官方自带的 GitHub-hosted runner 足够完成这套 GitHub Actions教程,优点是不用自己维护 CI 机器;限制是免费额度会随账户计划和用量变化,构建时间长、需要 Docker 或私有网络时,再考虑 self-hosted runner。
项目根目录先确认这些命令在本地能通过:
npm ci
npm test
npm run build
接下来在仓库中创建 .github/workflows/deploy.yml,把下面内容粘进去:
name: Node CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm test
- run: npm run build
deploy:
needs: test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- name: Prepare SSH
env:
SSH_KEY: ${{ secrets.DEPLOY_KEY }}
HOST: ${{ secrets.DEPLOY_HOST }}
run: |
mkdir -p ~/.ssh
printf '%s\n' "$SSH_KEY" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh-keyscan -H "$HOST" >> ~/.ssh/known_hosts
- name: Upload and restart
env:
HOST: ${{ secrets.DEPLOY_HOST }}
USER: ${{ secrets.DEPLOY_USER }}
run: |
tar czf release.tgz --exclude=node_modules .
scp -i ~/.ssh/deploy_key release.tgz "$USER@$HOST:/tmp/release.tgz"
ssh -i ~/.ssh/deploy_key "$USER@$HOST" \
"sudo mkdir -p /var/www/myapp && sudo tar xzf /tmp/release.tgz -C /var/www/myapp && cd /var/www/myapp && npm ci --omit=dev && sudo systemctl restart myapp"
CHAPTER 2|Secrets与部署权限,别把钥匙写进代码
打开仓库的 Settings → Secrets and variables → Actions,添加 DEPLOY_HOST、DEPLOY_USER、DEPLOY_KEY。私钥只放在 Secrets,YAML 中绝对不要出现密码或真实私钥。服务器端建议单独建立部署用户,只允许 SSH 公钥登录,并限制它执行必要的发布命令。
Now watch this:在 production Environment 中开启审批,第一次发布会暂停,审批通过才执行 deploy。这样 pull request 只跑 test,main 合并后才触发生产部署,回滚时直接重新发布上一提交,比手动上传压缩包稳定得多。
如果你搜索“GitHub Actions怎么用”,最容易踩的坑就是 deploy 没有写 needs: test,导致测试和部署并行;另一个常见问题是服务器 Node.js 版本低于本地版本,出现依赖或语法错误。把 Node 20 固定在 runner 和服务器,两边环境才一致。
CHAPTER 3|上线验证:绿灯不等于服务真的活着
先推送一个小改动,进入 Actions 页面观察 test → deploy 的顺序。我的 2 vCPU 测试机上,一个 38MB 的 Node 项目从推送到重启完成约 70 秒;终端看到 scp 完成、SSH 返回 0,说明传输和命令执行成功,但还要检查 HTTP。
curl -o /dev/null -s -w \
"status=%{http_code} total=%{time_total}s\n" \
https://你的域名/health
预期类似 status=200 total=0.18s。若 Actions 红灯,先展开失败步骤:npm test 失败看测试日志;权限错误检查私钥换行和服务器 authorized_keys;服务重启失败执行 sudo systemctl status myapp 与 journalctl -u myapp -n 50。确认连续两次返回 200,再把这套 GitHub Actions自动部署流程用于正式项目。觉得这期实测有用,记得收藏并留言你的失败日志。