GitHub Actions 实现 CI/CD

前言
很多新手在使用 GitHub Actions 做 CI/CD 时,都会遇到三个问题:触发规则看不懂、海外环境拉依赖超时、部署配置明文泄露、结构混乱看不懂全流程。
本文重新梳理通俗易懂、循序渐进的结构:先搞懂 CI/CD 是什么 → 学会 GitHub Actions 语法 → Python 入门 CI 案例 → 企业级全栈 Go+Vue+MySQL+Redis CD 实战
一、CI / CD 核心概念(人话版)
1. CI 持续集成(只管「代码合并、检测、测试」)
开发者写完代码频繁提交到远程仓库,GitHub Actions 自动帮你:拉代码、装依赖、跑测试、检查语法错误。
作用:提前发现 Bug、代码冲突、依赖缺失,保证主干代码永远是可用状态,多人协作不会崩代码。
2. CD 持续部署(只管「打包、上传、上线」)
CI 测试全部通过后,自动打包前后端代码、通过 SCP 上传到业务服务器、重启服务、刷新页面,实现提交代码即自动上线。
适用场景:Go后端 + Vue前端 + MySQL + Redis 全栈项目自动发布。
二、GitHub Actions 核心组成(必懂)
所有自动化流程,都由四个部分组成:
-
Workflow(工作流):整个自动化文件,一个 yml 就是一套流水线
-
on(触发条件):什么时候执行流水线(push、PR、定时、手动等)
-
jobs(任务):需要执行的大任务(测试任务、部署任务)
-
steps(步骤):每个任务里的具体执行步骤,从上到下依次执行
文件固定存放路径:.github/workflows/xxx.yml
三、入门案例:Python 项目 CI 自动测试(零基础打底)
基于官方示例仓库,完成最基础的「提交代码自动测试」流程。
3.1 完整配置文件
yaml
name: "Test"
# 流水线触发条件
on:
push:
branches:
- main
pull_request:
branches:
- main
types: [ opened ]
# 执行任务
jobs:
test:
runs-on: ubuntu-latest
container: astral/uv:python3.12-bookworm-slim
steps:
- name: Checkout 拉取代码
uses: actions/checkout@v6
- name: 安装项目依赖
run: uv sync
- name: 执行单元测试
run: uv run pytest tests/
3.2 逐行通俗讲解
1)触发规则 on
-
push 触发:只要往 main 分支推送代码,自动跑流水线
-
pull_request 触发:只在「针对 main 分支新建 PR」时触发,更新代码、合并、关闭不重复执行
-
优势:只针对主干分支校验,避免无效运行,节省资源
2)运行环境
-
runs-on: ubuntu-latest:使用 GitHub 提供的 Ubuntu 云端服务器 -
container:启动独立 Python 容器,环境纯净、隔离,不会出本地能跑、线上报错的问题
3)执行步骤 steps
-
checkout:必写步骤,把仓库代码下载到云端服务器
-
uv sync:快速安装 Python 项目所有依赖
-
pytest:自动执行所有单元测试,拦截代码 Bug
四、多技术栈通用 CI 命令(直接抄)
不同项目,只需要替换依赖安装和测试命令即可:
-
Python:uv sync / pip install -r requirements.txt && pytest
-
Vue/Node:npm install / npm ci && npm test / npm run lint
-
Golang:go mod download && go test ./... -v
五、企业级实战:Go+Vue+MySQL+Redis 完整 CI/CD
这是本文核心:先 CI 自动校验代码,全部通过后再 CD 自动部署上线,适配前后端分离 + 数据库 + 缓存的真实项目。
5.1 项目架构说明
-
后端:Golang 接口服务,依赖 MySQL 存业务数据、Redis 做缓存
-
前端:Vue3 静态页面,打包后 Nginx 部署
-
部署流程:云端代理加速装依赖 → 测试校验 → 打包前后端 → SCP 上传服务器 → 重启服务生效
5.2 重点优化:国内镜像代理(解决超时失败)
GitHub 服务器在海外,直接拉取 Go、NPM 依赖极慢、容易超时,必须配置国内镜像:
-
Go 代理:
https://goproxy.cn,direct -
NPM 镜像:
https://registry.npmmirror.com
5.3 脱敏版核心配置文件(无明文密码)
项目路径:Backend/config/config.yml,已完全脱敏,线上敏感信息统一使用服务器本地配置或环境变量,杜绝密码泄露。
yaml
database:
dsn: ${DB_USER}:${DB_PASS}@tcp(你的数据库IP:3306)/你的库名?charset=utf8mb4&parseTime=True&loc=Local
MaxIdleConns: 11
MaxOpenCons: 114
redis:
addr: 你的RedisIP:6379
DB: 0
Password: "${REDIS_PASS}"
安全规范 :开发环境可本地填写明文,上传仓库、CI/CD 流水线绝对禁止明文账号密码,统一使用环境变量托管。
5.4 完整可直接运行 CI/CD 流水线(最终版)
yaml
name: "Go-Vue-FullStack-CICD"
# 触发策略:推送主干 / PR合并后触发部署
on:
push:
branches:
- main
pull_request:
branches:
- main
types: [closed]
jobs:
# 第一阶段:CI 代码检测、依赖安装、单元测试
ci-test:
runs-on: ubuntu-latest
steps:
- name: 拉取完整代码
uses: actions/checkout@v6
# Go 国内代理加速
- name: 配置Go国内代理
run: |
go env -w GOPROXY=https://goproxy.cn,direct
go env -w GOSUMDB=off
- name: 安装Go依赖
run: go mod download
- name: Go单元测试
run: go test ./... -v
# Vue 国内镜像加速
- name: 配置NPM淘宝镜像
run: npm config set registry https://registry.npmmirror.com
- name: 安装前端依赖
run: npm install
- name: 前端代码校验
run: npm run lint
# 第二阶段:CD 自动部署(CI成功才执行)
cd-deploy:
needs: ci-test
if: github.event.pull_request.merged == true || github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- name: 拉取代码
uses: actions/checkout@v6
# 后端打包
- name: 打包Go后端程序
run: |
go env -w GOPROXY=https://goproxy.cn,direct
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./server ./main.go
# 前端打包
- name: 打包Vue前端静态资源
run: |
npm config set registry https://registry.npmmirror.com
npm install
npm run build
# 免密SSH配置
- name: 加载服务器SSH私钥
uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
# SCP上传:程序、配置、前端资源
- name: 上传文件至业务服务器
env:
SERVER_IP: ${{ secrets.SERVER_IP }}
SERVER_USER: ${{ secrets.SERVER_USER }}
run: |
scp -o StrictHostKeyChecking=no ./server $SERVER_USER@$SERVER_IP:/home/project/backend/
scp -o StrictHostKeyChecking=no ./Backend/config/config.yml $SERVER_USER@$SERVER_IP:/home/project/backend/Backend/config/
scp -o StrictHostKeyChecking=no -r ./dist $SERVER_USER@$SERVER_IP:/home/project/frontend/
# 远程重启服务
- name: 远程重启服务并校验中间件
env:
SERVER_IP: ${{ secrets.SERVER_IP }}
SERVER_USER: ${{ secrets.SERVER_USER }}
run: |
ssh -o StrictHostKeyChecking=no $SERVER_USER@$SERVER_IP << EOF
pkill -f ./server || true
cd /home/project/backend && nohup ./server > server.log 2>&1 &
nginx -s reload
systemctl status mysql --no-pager
systemctl status redis --no-pager
EOF
六、关键机制通俗解读
6.1 为什么要分 CI、CD 两个任务?
-
CI阶段 :代码有错、测试失败、依赖安装失败 → 直接终止,不上线,保证不会发布坏代码
-
CD阶段:只有 CI 全部通过、代码合并到主干才自动部署,安全可控
6.2 SCP 自动部署原理
通过 GitHub 仓库私密变量存放服务器私钥、IP、账号,流水线免密登录服务器,自动覆盖代码与配置、重启服务,全程无人工干预、无明文泄露。
6.3 必须配置的 GitHub Secrets(安全核心)
仓库 → Settings → Secrets and variables → Actions,添加:
-
SSH_PRIVATE_KEY:服务器私钥 -
SERVER_IP:服务器公网IP -
SERVER_USER:服务器登录账号
七、完整工作闭环(总结)
-
开发者推送代码 / 合并 PR 到 main 分支
-
自动配置国内镜像,加速安装 Go/Vue 依赖
-
自动跑单元测试、代码校验,拦截错误代码
-
校验通过后自动打包前后端项目
-
SCP 上传程序 + 脱敏配置文件到服务器
-
重启 Go 服务、刷新 Nginx、校验 MySQL/Redis 状态
-
完成全自动 CI/CD 上线
八、避坑总结(新手必看)
-
禁止仓库上传明文数据库、Redis 账号密码,统一使用变量/服务器本地配置
-
海外环境必须配置 Go、NPM 国内镜像,否则必超时
-
区分 PR 打开和 PR 合并触发,避免频繁无效部署
-
先杀旧进程再启动新进程,防止端口占用上线失败