GitHub Actions自动部署实战

一、什么是GitHub Actions?

GitHub Actions是GitHub提供的自动化工作流工具,可以自动执行代码构建、测试、部署等流程。

1.1 核心概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
┌─────────────────────────────────────────────────────────────────┐
│ GitHub Actions 工作流 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 提交代码 → 触发Workflow → 运行Job → 执行Step → 完成部署 │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Workflow(工作流) │ │
│ │ └── Job(任务) │ │
│ │ └── Step(步骤) │ │
│ │ └── Action(动作) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
概念 说明
Workflow 整个自动化流程,可在仓库设置多个
Job 一组Step,每个Workflow可多个Job(并行执行)
Step 每个Job中的具体步骤(命令或Action)
Action 可复用的步骤单元,可自定义或使用市场组件

1.2 典型使用场景

场景 说明
自动测试 每次提交自动运行测试用例
自动构建 代码提交后自动构建项目
自动部署 测试通过后自动部署到服务器
自动发布 打标签时自动发布Release
定时任务 定时执行清理/备份等任务

二、快速入门

2.1 创建第一个Workflow

1
2
3
4
5
# 1. 在仓库根目录创建 .github/workflows 目录
mkdir -p .github/workflows

# 2. 创建工作流文件
touch .github/workflows/hello.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# .github/workflows/hello.yml
name: Hello World

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
hello:
runs-on: ubuntu-latest

steps:
- name: Checkout代码
uses: actions/checkout@v4

- name: 输出Hello
run: echo "Hello, GitHub Actions!"

- name: 查看环境信息
run: |
echo "GitHub Actions真好用"
echo "当前时间: $(date)"

2.2 手动触发工作流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 添加 workflow_dispatch 实现手动触发
name: 手动部署

on:
workflow_dispatch: # 手动触发
inputs:
environment:
description: '部署环境'
required: true
default: 'test'
type: choice
options:
- test
- prod

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: 部署到 ${{ github.event.inputs.environment }}
run: echo "部署到 ${{ github.event.inputs.environment }} 环境"

三、部署静态网站到GitHub Pages

3.1 基础配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
push:
branches: [main]

permissions:
contents: write # 需要写入权限

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install Dependencies
run: npm ci

- name: Build
run: npm run build

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

3.2 Vue项目部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Vue项目
name: Deploy Vue App

on:
push:
branches: [main]

permissions:
contents: write

jobs:
build-and-deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'

- name: Install Dependencies
run: |
npm ci
npm run build

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist

3.3 Hexo博客部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# .github/workflows/hexo.yml
name: Deploy Hexo Blog

on:
push:
branches: [main]

permissions:
contents: write

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Cache npm dependencies
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-npm-

- name: Install Dependencies
run: npm ci

- name: Generate Static Files
run: npm run build

- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public

四、部署到服务器

4.1 配置SSH密钥

1
2
3
4
5
6
7
8
9
10
# 1. 生成部署密钥(服务器上)
ssh-keygen -t ed25519 -C "deploy@github-actions" -f ~/.ssh/deploy_key

# 2. 将公钥添加到服务器
cat ~/.ssh/deploy_key.pub >> ~/.ssh/authorized_keys

# 3. 将私钥添加到GitHub仓库
# 仓库 → Settings → Secrets and variables → Actions
# 新建Secret: DEPLOY_KEY
# 内容为 ~/.ssh/deploy_key 私钥

4.2 部署到VPS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# .github/workflows/deploy-vps.yml
name: Deploy to VPS

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Install Dependencies
run: npm ci

- name: Build
run: npm run build

- name: Deploy to Server
uses: appleboy/ssh-action@v0.1.0
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.DEPLOY_KEY }}
port: 22
script: |
cd /var/www/myapp
git pull origin main
npm ci
npm run build
pm2 restart all

4.3 多环境部署

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# .github/workflows/deploy-multi.yml
name: Deploy to Multiple Environments

on:
push:
branches: [main]
workflow_dispatch:
inputs:
environment:
description: 'Select environment'
required: true
default: 'test'
type: choice
options:
- test
- staging
- prod

jobs:
deploy-test:
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event.inputs.environment == 'test'
steps:
- uses: actions/checkout@v4

- name: Deploy to Test
run: |
echo "部署到测试环境"
# 部署命令...

deploy-staging:
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'staging'
steps:
- uses: actions/checkout@v4

- name: Deploy to Staging
run: |
echo "部署到预发环境"
# 部署命令...

deploy-prod:
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'prod'
needs: [deploy-staging] # 需要先部署staging
steps:
- uses: actions/checkout@v4

- name: Deploy to Production
run: |
echo "部署到生产环境"
# 部署命令...

五、自动测试

5.1 Node.js测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# .github/workflows/test.yml
name: Test

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18, 20, 22]

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install Dependencies
run: npm ci

- name: Run Tests
run: npm test

- name: Upload Coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}

5.2 Python测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# .github/workflows/python-test.yml
name: Python Test

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ['3.10', '3.11', '3.12']

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov

- name: Run Tests
run: pytest --cov=. --cov-report=xml

- name: Upload Coverage
uses: codecov/codecov-action@v3

六、Docker自动化

6.1 自动构建镜像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# .github/workflows/docker.yml
name: Build and Push Docker

on:
push:
branches: [main]
tags: ['v*']

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Extract Metadata
id: meta
uses: docker/metadata-action@v5
with:
images: myapp/myapp
tags: |
type=ref,event=branch
type=sha
type=match,pattern=v(.+)

- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=myapp/myapp:latest
cache-to: type=inline

6.2 自动部署Docker Compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# .github/workflows/docker-compose.yml
name: Deploy with Docker Compose

on:
push:
branches: [main]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install Docker Compose
run: |
sudo curl -L "https://github.com/docker/compose/releases/download/v2.23.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Pull latest images
run: docker-compose pull

- name: Restart services
run: docker-compose up -d

- name: Check health
run: |
sleep 10
curl -f http://localhost:8080/health || exit 1

七、定时任务

7.1 定时清理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# .github/workflows/cleanup.yml
name: Scheduled Cleanup

on:
schedule:
# 每天凌晨3点执行
- cron: '0 3 * * *'
workflow_dispatch: # 也可手动触发

jobs:
cleanup:
runs-on: ubuntu-latest

steps:
- name: Cleanup old data
run: |
echo "清理7天前的日志"
find /path/to/logs -type f -mtime +7 -delete
echo "清理完成"

7.2 定时备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# .github/workflows/backup.yml
name: Daily Backup

on:
schedule:
# 每天凌晨2点
- cron: '0 2 * * *'

jobs:
backup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Backup Database
run: |
mysqldump -h ${{ secrets.DB_HOST }} -u ${{ secrets.DB_USER }} -p${{ secrets.DB_PASSWORD }} myapp > backup_$(date +%Y%m%d).sql

- name: Upload to S3
uses: actions/upload-artifact@v3
with:
name: backup
path: backup_*.sql
retention-days: 30

八、常用Action推荐

Action 说明 用途
actions/checkout 检出代码 必备
actions/setup-node Node.js环境 Node项目
actions/setup-python Python环境 Python项目
appleboy/ssh-action SSH远程 服务器部署
peaceiris/actions-gh-pages GitHub Pages 静态网站
docker/login-action Docker登录 镜像推送
docker/build-push-action 构建推送 镜像构建
codecov/codecov-action 代码覆盖率 测试报告
actions/cache 缓存 加速构建

九、Secrets配置

9.1 添加Secret

1
2
3
4
5
1. 进入仓库 → Settings
2. 左侧Secrets and variables → Actions
3. 点击 New repository secret
4. 输入Name和Value
5. 点击 Add secret

9.2 常用Secrets

Name 说明 示例
DEPLOY_KEY SSH私钥 —–BEGIN OPENSSH PRIVATE KEY—–
SERVER_HOST 服务器IP 192.168.1.100
SERVER_USER 服务器用户名 root
DOCKERHUB_TOKEN Docker Hub令牌 xxx
AWS_ACCESS_KEY_ID AWS访问密钥 xxx
AWS_SECRET_ACCESS_KEY AWS密钥 xxx

十、调试技巧

10.1 本地测试

1
2
3
4
5
6
7
8
9
10
11
# 安装 act(本地运行GitHub Actions)
# https://github.com/nektos/act

# 列出工作流
act -l

# 运行指定工作流
act -W .github/workflows/deploy.yml

# 运行指定Job
act -j deploy

10.2 查看日志

1
2
3
4
1. 进入仓库 → Actions
2. 选择具体工作流运行
3. 查看每个Job的日志
4. 失败的Step会标红

十一、实战案例:完整CI/CD流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# .github/workflows/ci-cd.yml
name: CI/CD Pipeline

on:
push:
branches: [main]
pull_request:
branches: [main]

env:
NODE_VERSION: '20'
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
# 代码检查
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm run lint

# 单元测试
test:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
- run: npm ci
- run: npm test --if-present
- run: npm run test:coverage --if-present

# 构建镜像
build:
runs-on: ubuntu-latest
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=ref,event=branch

- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

# 部署到服务器
deploy:
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4

- name: Deploy to Server
uses: appleboy/ssh-action@v0.1.0
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.DEPLOY_KEY }}
script: |
cd /var/www/myapp
docker-compose pull
docker-compose up -d
docker system prune -f

参考资料


持续更新中…欢迎收藏!

#GitHub #CI/CD #自动化 #DevOps #教程


GitHub Actions自动部署实战
https://r0f2.my/post/17-github-actions-cicd/
作者
JA
发布于
2026年2月13日
许可协议