Published on

Gihub Action搭建你的工作流实现博客自动部署

Authors
  • avatar
    作者
    子君
Gihub Action搭建你的工作流实现博客自动部署

GitHub Actions 工作流搭建教程(从零开始)

📚 目录

  1. 什么是 GitHub Actions
  2. 为什么要用 GitHub Actions
  3. 核心概念详解
  4. 实战:搭建你的第一个工作流
  5. 配置 GitHub Secrets(重点)
  6. 测试工作流
  7. 常见问题和解决方案
  8. 进阶技巧

什么是 GitHub Actions

通俗来说,GitHub Actions 就是 GitHub 提供的"自动化助手"。

想象一下:

  • 你写好代码后,手动上传到服务器
  • 手动运行测试
  • 手动构建项目
  • 手动部署到生产环境

这些重复的工作,GitHub Actions 可以帮你自动完成!

GitHub Actions 能做什么?

  1. 自动运行测试:你提交代码后,自动运行测试用例
  2. 自动构建项目:自动运行 npm run build 等构建命令
  3. 自动部署:构建成功后,自动部署到服务器
  4. 定时任务:每天自动运行某个任务(比如备份数据)
  5. 代码检查:自动检查代码格式、语法错误等

为什么选择 GitHub Actions?

  • ✅ 免费:公开仓库无限使用,私有仓库也有免费额度
  • ✅ 简单:配置文件就是普通的 YAML 文件,容易理解
  • ✅ 强大:有很多现成的插件(Actions)可以直接用
  • ✅ 集成:和 GitHub 深度集成,不需要额外注册账号
  • ✅ 可视化:可以在 GitHub 页面上直观地看到运行结果

为什么要用 GitHub Actions

传统部署方式 vs GitHub Actions

传统方式(麻烦):

# 1. 本地写代码
git add .
git commit -m "更新文章"
git push

# 2. 手动登录服务器
ssh user@server

# 3. 手动拉取代码
cd /var/www/blog
git pull

# 4. 手动安装依赖
npm install

# 5. 手动构建
npm run build

# 6. 手动重启服务
pm2 restart blog

问题:

  • 每次更新都要重复这些步骤
  • 容易出错(比如忘记运行某个命令)
  • 耗时耗力

使用 GitHub Actions(省心):

# 本地写代码,一键推送
git add .
git commit -m "更新文章"
git push

# ✅ GitHub Actions 自动完成剩下的所有事情!

好处:

  • 省时间,一次配置,永久生效
  • 减少人为错误
  • 可以看到详细的构建日志
  • 自动通知构建结果

核心概念详解

1. Workflow(工作流)

简单理解:工作流就是一个"自动化脚本",定义了要做什么事情。

例子:一个部署工作流可能包含:

  • 检出代码
  • 安装依赖
  • 运行测试
  • 构建项目
  • 部署到服务器

文件位置:.github/workflows/xxx.yml

2. Event(触发事件)

简单理解:什么时候执行工作流。

常见触发方式:

触发方式说明使用场景
push推送代码时提交代码到 main 分支时自动部署
pull_request发起 PR 时合并代码前自动测试
schedule定时执行每天凌晨自动备份数据
workflow_dispatch手动触发需要时点击按钮手动运行

3. Job(任务)

简单理解:工作流中的一个"工作单元"。

例子:

jobs:
  test:# 任务1:测试
    # ...
  build:# 任务2:构建
    # ...
  deploy:# 任务3:部署
    # ...

4. Step(步骤)

简单理解:任务中的具体"操作"。

例子:

steps:
  - name: 检出代码 # 步骤1
    run: git clone ...
  - name: 安装依赖 # 步骤2
    run: npm install
  - name: 运行测试 # 步骤3
    run: npm test

5. Action(插件)

简单理解:别人写好的"功能模块",可以直接用。

例子:

  • actions/checkout:自动检出代码
  • actions/setup-node:自动安装 Node.js
  • actions/cache:自动缓存依赖

好处:不用自己写复杂的脚本,直接用别人写好的!


实战:搭建你的第一个工作流

目标

实现功能:本地代码推送到 GitHub main 分支 → GitHub 自动构建 → 部署到服务器

步骤 1:查看项目结构

你的项目目录应该是这样的:

nextjs-tailwind-blog/
├── .github/
│   └── workflows/          # 这里存放工作流配置文件
│       └── deploy-server.yml
├── src/                    # 源代码
├── data/blog/              # 博客文章
├── public/                 # 静态资源
├── package.json            # 项目配置
├── next.config.js          # Next.js 配置
└── ...

重点:.github/workflows/ 目录是存放 GitHub Actions 配置的专用目录。

步骤 2:理解你的现有工作流

让我们看看你现有的部署配置:

name: Deploy to Server

on:
  push:
    branches: [main] # 当推送到 main 分支时触发

jobs:
  deploy:
    runs-on: ubuntu-latest # 使用 Ubuntu 系统运行

    steps:
      # 1. 检出代码
      - name: Checkout code
        uses: actions/checkout@v3

      # 2. 安装 Node.js
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16' # 使用 Node.js 16 版本

      # 3. 安装依赖
      - name: Install dependencies
        run: npm install

      # 4. 构建项目
      - name: Build
        run: npm run build

      # 5. 导出静态文件
      - name: Export static files
        run: npx next export

      # 6. 设置 SSH
      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SERVER_SSH_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts

      # 7. 部署到服务器
      - name: Deploy to server
        run: |
          rsync -avz --delete \
            -e "ssh -i ~/.ssh/deploy_key -p 22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts" \
            ./out/ \
            ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.SERVER_PATH }}/

这个工作流做了什么?

  1. 触发条件:当代码推送到 main 分支时
  2. 运行环境:在 GitHub 提供的 Ubuntu 虚拟机上
  3. 执行步骤:
    • 检出你的代码
    • 安装 Node.js 16
    • 安装项目依赖
    • 构建项目
    • 导出静态文件
    • 通过 SSH 连接到你的服务器
    • 将构建好的文件同步到服务器

步骤 3:从头创建一个新的工作流

现在,假设你从来没有配置过 GitHub Actions,让我们从零开始创建。

3.1 创建工作流目录

在项目根目录下创建:

mkdir -p .github/workflows

3.2 创建工作流文件

创建文件:.github/workflows/ci-cd.yml

name: CI/CD Pipeline

# 触发条件
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  # 任务1:构建和测试
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      # 步骤1:检出代码
      - name: Checkout code
        uses: actions/checkout@v3

      # 步骤2:设置 Node.js
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: 'npm' # 启用缓存,加快构建速度

      # 步骤3:安装依赖
      - name: Install dependencies
        run: npm ci # ci 比 install 更严格,确保依赖一致

      # 步骤4:代码检查(如果有的话)
      - name: Lint
        run: npm run lint
        continue-on-error: true # 即使失败也继续

      # 步骤5:运行测试(如果有的话)
      - name: Test
        run: npm test
        continue-on-error: true # 即使失败也继续

      # 步骤6:构建项目
      - name: Build
        run: npm run build
        env:
          NODE_ENV: production

  # 任务2:部署(仅在 main 分支且构建成功后执行)
  deploy:
    needs: build-and-test # 依赖 build-and-test 任务
    if: github.ref == 'refs/heads/main' # 只在 main 分支执行
    runs-on: ubuntu-latest

    steps:
      # 步骤1:检出代码
      - name: Checkout code
        uses: actions/checkout@v3

      # 步骤2:设置 Node.js
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'
          cache: 'npm'

      # 步骤3:安装依赖
      - name: Install dependencies
        run: npm ci

      # 步骤4:构建项目
      - name: Build
        run: npm run build
        env:
          NODE_ENV: production

      # 步骤5:导出静态文件
      - name: Export
        run: npx next export

      # 步骤6:设置 SSH
      - name: Setup SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SERVER_SSH_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts

      # 步骤7:部署到服务器
      - name: Deploy to server
        run: |
          rsync -avz --delete \
            -e "ssh -i ~/.ssh/deploy_key -p 22 -o StrictHostKeyChecking=no -o UserKnownHostsFile=~/.ssh/known_hosts" \
            ./out/ \
            ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.SERVER_PATH }}/

      # 步骤8:通知部署结果
      - name: Notify success
        if: success()
        run: echo "✅ 部署成功!"

      - name: Notify failure
        if: failure()
        run: echo "❌ 部署失败!"

配置 GitHub Secrets(重点)

什么是 GitHub Secrets?

通俗解释:Secrets 就是 GitHub 帮你"安全存储"敏感信息的地方。

为什么要用 Secrets?

❌ 错误做法:直接把敏感信息写在代码里

# ❌ 这样做很危险!
- name: Deploy
  run: |
    rsync ./out/ user@123.45.67.89:/var/www/blog
    # SSH 密码直接暴露在代码里!

问题:

  • 代码可能被别人看到(比如开源项目)
  • Git 历史会永久保存这些信息
  • 密码泄露风险极大

✅ 正确做法:使用 Secrets

# ✅ 这样做很安全!
- name: Deploy
  run: |
    rsync ./out/ ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }}:${{ secrets.SERVER_PATH }}/
    # 敏感信息从 Secrets 中读取,代码里看不到

详细步骤:如何创建 Secrets

步骤 1:打开 GitHub 仓库

  1. 在浏览器中打开你的 GitHub 仓库
  2. 确保你有管理员的权限(能看到 Settings)

步骤 2:进入 Secrets 设置页面

方法一(传统方式):

  1. 点击仓库上方的 Settings(设置)标签
  2. 在左侧菜单中找到 Secrets and variables → Actions
  3. 点击 New repository secret 按钮

方法二(新界面):

  1. 点击仓库上方的 Settings(设置)标签
  2. 在左侧菜单中找到 Secrets and variables → Actions
  3. 在右侧点击 New repository secret

步骤 3:添加第一个 Secret

让我们以添加 SSH 私钥 为例:

页面内容:

Name: [输入框]
Value: [输入框,支持多行]
Add secret [按钮]

填写内容:

  1. Name(名称):SERVER_SSH_KEY

    • 名称只能包含字母、数字和下划线
    • 建议使用大写字母,便于识别
    • 名称一旦创建不能修改,只能删除重建
  2. Value(值):你的 SSH 私钥内容

如何获取 SSH 私钥?

在你的本地电脑上:

# 查看私钥内容
cat ~/.ssh/id_rsa

或者:

# 查看私钥内容(如果有其他私钥)
cat ~/.ssh/id_ed25519

复制私钥时的注意事项:

✅ 正确复制:

  • 包含 -----BEGIN OPENSSH PRIVATE KEY----- 开头
  • 包含 -----END OPENSSH PRIVATE KEY----- 结尾
  • 包含中间所有的内容
  • 保持完整的换行符

❌ 错误复制:

  • 只复制了中间部分,没有开头结尾
  • 添加了额外的空格或换行
  • 复制了公钥而不是私钥

复制示例:

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBq8z7vKlQXp7m9nKqJjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKj
...(中间很多行)...
KjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKjKj
-----END OPENSSH PRIVATE KEY-----
  1. 点击 Add secret 按钮保存

步骤 4:继续添加其他 Secrets

按照同样的方式,继续添加其他需要的 Secrets:

Secret 2:服务器地址

Name: SERVER_HOST
Value: your-server.com

如何获取服务器地址?

# 查看你的服务器地址
hostname -I
# 或者直接用 IP 地址,比如:123.45.67.89

Secret 3:服务器用户名

Name: SERVER_USER
Value: root

如何获取用户名?

# 查看当前用户
whoami
# 常见的用户名:root, ubuntu, admin 等

Secret 4:服务器路径

Name: SERVER_PATH
Value: /var/www/blog

如何确定服务器路径?

在你的服务器上:

# 查看你的网站目录
ls -la /var/www/
# 或者自定义路径:/home/user/blog

Secrets 列表示例

配置完成后,你的 Secrets 列表应该是这样的:

NameCreated atUpdated at
SERVER_HOST2024-03-152024-03-15
SERVER_PATH2024-03-152024-03-15
SERVER_SSH_KEY2024-03-152024-03-15
SERVER_USER2024-03-152024-03-15

Secrets 使用方法

在工作流文件中,使用 secrets.xxx 的方式引用:

- name: Deploy
  run: |
    echo "用户名: ${{ secrets.SERVER_USER }}"
    echo "服务器: ${{ secrets.SERVER_HOST }}"
    echo "路径: ${{ secrets.SERVER_PATH }}"

注意:

  • Secrets 在运行时才会被替换
  • 在工作流日志中,Secrets 的值会被隐藏(显示为 ***)
  • 这样即使有人查看日志,也看不到你的敏感信息

Secrets 的安全性

✅ 安全特性:

  1. 加密存储:Secrets 在 GitHub 上是加密存储的
  2. 日志隐藏:在日志中自动隐藏 Secrets 的值
  3. 权限控制:只有有权限的人才能看到和管理 Secrets
  4. 版本隔离:不同环境可以使用不同的 Secrets

❌ 注意事项:

  1. 不要在代码、注释中暴露 Secrets
  2. 定期轮换(更换)重要的 Secrets
  3. 不要在公开仓库中存放生产环境的 Secrets
  4. 使用最小权限原则(SSH 用户不要用 root)

Secrets 常见错误

错误 1:名称写错

# ❌ 错误
echo "${{ secrets.SEREVER_HOST }}"

# ✅ 正确
echo "${{ secrets.SERVER_HOST }}"

错误 2:没有创建 Secret

Error: 输入项未在 'SERVER_SSH_KEY' 处找到

解决方法:

  1. 检查 Secrets 是否已创建
  2. 检查名称是否拼写正确
  3. 检查是否有权限访问

错误 3:SSH 私钥格式错误

Error: Permission denied (publickey)

可能原因:

  1. 复制了公钥而不是私钥
  2. 复制时缺少开头或结尾
  3. 复制了额外的空格或换行
  4. 私钥格式不对(应该是 OPENSSH 格式)

解决方法:

  1. 重新复制私钥,确保完整
  2. 确认是私钥(通常文件名是 id_rsa 或 id_ed25519)
  3. 删除旧 Secret,重新创建

测试工作流

方法 1:通过代码推送触发

# 修改一个文件(随便改点什么)
echo "test" >> README.md

# 提交并推送
git add .
git commit -m "测试 GitHub Actions"
git push

然后去 GitHub 查看运行情况:

  1. 打开你的 GitHub 仓库
  2. 点击 Actions 标签
  3. 你会看到一个新的工作流正在运行
  4. 点击进去可以查看详细的运行日志

方法 2:通过 GitHub 界面触发

如果你的工作流配置了 workflow_dispatch:

  1. 打开 GitHub 仓库
  2. 点击 Actions 标签
  3. 选择你的工作流
  4. 点击右侧的 Run workflow 按钮

查看运行结果

成功的界面

✅ CI/CD Pipeline
  ✅ build-and-test (3m 20s)
    ✅ Checkout code (2s)
    ✅ Setup Node.js (10s)
    ✅ Install dependencies (45s)
    ✅ Lint (5s)
    ✅ Test (30s)
    ✅ Build (2m 8s)
  ✅ deploy (1m 15s)
    ✅ Checkout code (2s)
    ✅ Setup Node.js (10s)
    ✅ Install dependencies (45s)
    ✅ Build (2m 8s)
    ✅ Export (5s)
    ✅ Setup SSH (2s)
    ✅ Deploy to server (3s)
    ✅ Notify success (0s)

失败的界面

❌ CI/CD Pipeline
  ✅ build-and-test (3m 20s)
    ✅ Checkout code (2s)
    ✅ Setup Node.js (10s)
    ✅ Install dependencies (45s)
    ❌ Lint (5s)

点击失败的步骤,可以看到详细的错误信息。


常见问题和解决方案

问题 1:SSH 连接失败

错误信息:

Error: Host key verification failed

原因:GitHub Actions 第一次连接你的服务器,需要确认服务器身份。

解决方法:

在工作流中添加 ssh-keyscan:

- name: Setup SSH
  run: |
    mkdir -p ~/.ssh
    echo "${{ secrets.SERVER_SSH_KEY }}" > ~/.ssh/deploy_key
    chmod 600 ~/.ssh/deploy_key
    ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts

问题 2:权限不足

错误信息:

Error: Permission denied (publickey)

原因:SSH 密钥配置不正确。

解决方法:

  1. 确认使用的是私钥,不是公钥
  2. 确认私钥格式正确
  3. 确认服务器的 ~/.ssh/authorized_keys 中有对应的公钥

问题 3:构建失败

错误信息:

Error: Build failed

原因:项目构建有问题。

解决方法:

  1. 先在本地运行 npm run build,确认能成功
  2. 检查依赖是否完整
  3. 查看详细的构建日志,找到具体错误

问题 4:部署路径不存在

错误信息:

Error: No such file or directory

原因:服务器上的目标目录不存在。

解决方法:

在工作流中添加创建目录的步骤:

- name: Create target directory
  run: |
    ssh -i ~/.ssh/deploy_key ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} \
      "mkdir -p ${{ secrets.SERVER_PATH }}"

问题 5:工作流运行时间过长

原因:每次都重新安装依赖,没有使用缓存。

解决方法:

启用依赖缓存:

- uses: actions/setup-node@v3
  with:
    node-version: '16'
    cache: 'npm' # 添加这一行

进阶技巧

1. 并发控制

避免多个工作流同时运行:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

2. 条件执行

只在特定条件下执行某个步骤:

- name: Deploy
  if: success() && github.ref == 'refs/heads/main'
  run: npm run deploy

3. 矩阵构建

同时在多个环境中测试:

strategy:
  matrix:
    node-version: [14, 16, 18]
    os: [ubuntu-latest, windows-latest]

runs-on: ${{ matrix.os }}

4. 通知功能

构建成功或失败后发送通知:

- name: Notify on success
  if: success()
  run: echo "部署成功!"

- name: Notify on failure
  if: failure()
  run: echo "部署失败,请检查日志!"

5. 手动触发

允许在 GitHub 界面手动触发工作流:

on:
  workflow_dispatch:
    inputs:
      environment:
        description: '部署环境'
        required: true
        default: 'production'
        type: choice
        options:
          - staging
          - production

总结

完整流程回顾

  1. 创建工作流文件:.github/workflows/ci-cd.yml
  2. 配置 Secrets:在 GitHub 设置中添加敏感信息
  3. 推送代码:git push 触发工作流
  4. 自动执行:GitHub Actions 自动运行构建和部署
  5. 查看结果:在 GitHub Actions 页面查看运行日志

关键要点

  1. Secrets 的安全性:

    • 永远不要在代码中硬编码敏感信息
    • 使用 GitHub Secrets 安全存储
    • 定期轮换重要密码
  2. 工作流的调试:

    • 使用详细的日志输出
    • 分阶段执行,便于定位问题
    • 查看 Actions 页面的运行日志
  3. 性能优化:

    • 使用缓存加速构建
    • 避免重复安装依赖
    • 合理设置并发控制

下一步

  1. 测试:创建一个工作流并测试
  2. 优化:根据实际情况优化配置
  3. 扩展:添加更多功能(如通知、多环境部署等)
  4. 学习:探索 GitHub Marketplace 中的更多 Actions

文档版本: 2.0 最后更新: 2026-03-15

希望这份详细的教程能帮助你成功搭建 GitHub Actions 工作流!