GitHub Actions

GitHub Actions 是一个持续集成和持续交付(CI/CD)平台,它允许开发者在 GitHub 仓库中自动化构建、测试和部署软件项目。通过定义工作流文件(workflow),开发者可以在特定事件(如代码提交或发布标签)触发时执行一系列任务。

GitHub Actions 的主要特性:

  • 事件驱动:工作流可以基于 GitHub 上的各种事件(如 push、pull request、issue)触发。
  • 基于 YAML 文件:使用易于编写和阅读的 YAML 文件定义工作流。
  • 跨平台支持:支持在 Linux、macOS 和 Windows 环境下运行作业。
  • 安全性:通过 GitHub Secrets 管理敏感信息,确保工作流的安全性。

GitHub Actions 的主要用途:

  • 持续集成(CI):在代码每次变更时自动运行构建和测试流程,确保代码的正确性和稳定性。
  • 持续交付(CD):将代码自动部署到开发、测试或生产环境,确保软件可以快速、安全地发布。
  • 自动化任务:执行其他重复性任务,如代码格式化、依赖管理、安全扫描等。

GitHub Actions 基本概念

工作流(Workflow)

工作流(Workflow)是 GitHub Actions 的核心单元,通过 YAML 文件定义,位于 .github/workflows/ 目录下。工作流文件描述了自动化流程的具体操作步骤,包括何时触发(on)、在何种环境中运行(runs-on)、以及执行的任务(jobs 和 steps)。

graph TD
    A[Workflow]
    A --> B1[name]
    A --> B2[on]
    B2 --> C1[push]
    B2 --> C2[pull_request]
    B2 --> C3[schedule]
    B2 --> C4[workflow_dispatch]
    A --> B3[jobs]
    B3 --> D1[Job 1]
    B3 --> D2[Job 2]
    D1 --> E1[runs-on]
    D1 --> E2[needs]
    D1 --> E3[env]
    D1 --> E4[steps]
    E4 --> F1[Step 1]
    E4 --> F2[Step 2]
    F1 --> G1[uses]
    F1 --> G2[run]
    F1 --> G3[env]
    F1 --> G4[with]
    F2 --> G5[uses]
    F2 --> G6[run]
    F2 --> G7[env]
    F2 --> G8[with]
    D2 --> H1[runs-on]
    D2 --> H2[needs]
    D2 --> H3[env]
    D2 --> H4[steps]
    H4 --> I1[Step 1]
    H4 --> I2[Step 2]
    I1 --> J1[uses]
    I1 --> J2[run]
    I1 --> J3[env]
    I1 --> J4[with]
    I2 --> J5[uses]
    I2 --> J6[run]
    I2 --> J7[env]
    I2 --> J8[with]
关键字描述示例
name工作流的名称(可选)name: CI/CD Pipeline
on定义触发工作流的事件on: [push, pull_request, schedule, workflow_dispatch]
push代码推送事件push: { branches: [main] }
pull_request拉取请求事件pull_request: { branches: [main] }
schedule定时器触发schedule: [{ cron: '0 0 * * *' }]
workflow_dispatch手动触发工作流workflow_dispatch:
jobs包含一个或多个作业jobs: { build: { ... }, test: { ... }, deploy: { ... } }
runs-on指定作业运行的虚拟环境runs-on: ubuntu-latest
needs指定作业的依赖关系needs: build
env设置环境变量(作业级或步骤级)env: { NODE_ENV: production }
steps作业中的具体操作步骤steps: [ { name: Checkout code, uses: actions/checkout@v2 }, ... ]
name (Step)步骤的名称name: Checkout code
uses调用预定义的 actionuses: actions/checkout@v2
run运行命令行命令run: npm install
with传递给 action 的参数with: { node-version: '14' }

作业(Job)

**作业(Job)是工作流中独立运行的一组步骤。**作业可以在不同的虚拟环境中运行,并且可以并行或按顺序执行;作业之间可以是独立的,也可以相互依赖。

graph TD
    A[jobs]
    A --> B1[Job 1]
    A --> B2[Job 2]
    
    B1 --> C1[runs-on]
    B1 --> C2[steps]
    B1 --> C3[needs]  --> D1[依赖的Job]
    B1 --> C4[env]  --> D2[环境变量]
    
    C2 --> D3[Step 1]
    C2 --> D4[Step 2]
    
    D3 --> E1[uses]
    D3 --> E2[run]
    D3 --> E3[name]
    D3 --> E4[with] --> F1[参数]
    D3 --> E5[env]  --> F2[环境变量]
    D3 --> E6[if] --> F3[条件]
    
    D4 --> G1[uses]
    D4 --> G2[run]
    D4 --> G3[name]
    D4 --> G4[with] --> H1[参数]
    D4 --> G5[env]  --> H2[环境变量]
    D4 --> G6[if] --> H3[条件]

    B2 --> I1[runs-on]
    B2 --> I2[steps]
    B2 --> I3[needs]  --> J1[依赖的Job]
    B2 --> I4[env]  --> J2[环境变量]
    
    I2 --> K1[Step 1]
    I2 --> K2[Step 2]
    
    K1 --> L1[uses]
    K1 --> L2[run]
    K1 --> L3[name]
    K1 --> L4[with] --> M1[参数]
    K1 --> L5[env]  --> M2[环境变量]
    K1 --> L6[if] --> M3[条件]
    
    K2 --> N1[uses]
    K2 --> N2[run]
    K2 --> N3[name]
    K2 --> N4[with] --> O1[参数]
    K2 --> N5[env]  --> O2[环境变量]
    K2 --> N6[if] --> O3[条件]
关键字描述
jobs顶级节点,包含所有作业的定义。
Job每个作业的定义,包含运行环境、步骤、依赖关系和环境变量。
runs-on指定作业运行的虚拟环境,如 ubuntu-latestwindows-latestmacos-latest
steps包含作业中所有步骤的列表。
Step每个步骤的定义,可以包含 usesrunnamewithenvif 等子字段。
uses调用预定义的 Action,例如 actions/checkout@v2
run运行命令行命令,如 npm install
name步骤名称,用于描述步骤的功能。
with传递给 Action 的参数,如 node-version: '14'
env环境变量,可以在作业级别或步骤级别定义。
if条件表达式,控制步骤或作业的执行,例如 if: github.ref == 'refs/heads/main'
needs定义作业的依赖关系,确保按顺序执行,例如 needs: [build]
matrix定义矩阵策略,用于在多个环境组合上并行运行作业。
timeout-minutes设置作业超时时间,以分钟为单位,防止作业无限制地运行。
continue-on-error如果设置为 true,即使作业失败也会继续执行后续作业。
container在指定的 Docker 容器中运行作业。
services为作业提供依赖服务,如数据库服务。

步骤(Step)

**步骤(Step)是作业中的单个任务。**步骤可以是运行命令行命令(run)或调用预定义的 action(uses)。步骤在同一个作业中按顺序执行,且共享相同的上下文,包括工作目录、环境变量等。

graph TD
    A[steps]
    A --> B1[Step 1]
    A --> B2[Step 2]
    
    B1 --> C1[name]
    B1 --> C2[uses]
    B1 --> C3[run]
    B1 --> C4[with] --> D1[参数]
    B1 --> C5[env]  --> D2[环境变量]
    B1 --> C6[if] --> D3[条件]
    B1 --> C7[continue-on-error] --> D4[错误继续]
    B1 --> C8[timeout-minutes] --> D5[超时时间]

    B2 --> E1[name]
    B2 --> E2[uses]
    B2 --> E3[run]
    B2 --> E4[with] --> F1[参数]
    B2 --> E5[env]  --> F2[环境变量]
    B2 --> E6[if] --> F3[条件]
    B2 --> E7[continue-on-error] --> F4[错误继续]
    B2 --> E8[timeout-minutes] --> F5[超时时间]
关键字描述
steps包含作业中所有步骤的列表。
name步骤名称,用于描述步骤的功能。
uses调用预定义的 Action,例如 actions/checkout@v2
run运行命令行命令,如 npm install
with传递给 Action 的参数,如 node-version: '14'
env环境变量,可以在步骤级别定义。
if条件表达式,控制步骤的执行,例如 if: github.ref == 'refs/heads/main'
continue-on-error如果设置为 true,即使步骤失败也会继续执行后续步骤。
timeout-minutes设置步骤超时时间,以分钟为单位,防止步骤无限制地运行。

Runner 和执行器(Runner)

Runner 是运行 GitHub Actions 作业的计算资源。GitHub 提供了托管 Runner,也可以使用自托管 Runner。

  • 托管 Runner:由 GitHub 提供和维护,目前支持 Linux、macOS 和 Windows。
  • 自托管 Runner:由用户提供和维护,适用于需要特殊软件或硬件环境的场景。

GitHub Actions 中 YAML 的具体示例

在 GitHub Actions 中,YAML 文件用于定义工作流的结构和行为。主要包括工作流名称、触发事件、作业和步骤等。

name: CI/CD Pipeline
 
# 定义触发事件:推送到 main 分支、拉取请求到 main 分支、定时触发、手动触发
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
  schedule:
    - cron: '0 0 * * *'
  workflow_dispatch:
 
jobs:
  build:
    # 使用 GitHub 托管的 Ubuntu 环境
    runs-on: ubuntu-latest
 
    # 矩阵策略:在多个 Node.js 版本上运行作业
    strategy:
      matrix:
        node-version: [12, 14, 16]
 
    # 作业级别环境变量
    env:
      BUILD_ENV: production
 
    steps:
      - name: Checkout code
        # 使用 actions/checkout@v2 Action 检出代码
        uses: actions/checkout@v2
 
      - name: Set up Node.js
        # 使用 actions/setup-node@v2 Action 设置 Node.js 环境
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}
 
      - name: Install dependencies
        # 运行命令安装依赖
        run: npm install
 
      - name: Build project
        # 运行命令构建项目
        run: npm run build
 
      - name: Upload build artifacts
        # 上传构建产物
        uses: actions/upload-artifact@v2
        with:
          name: build-artifacts
          path: build/
 
  test:
    # 需要等待 build 作业完成后再执行
    needs: build
    runs-on: ubuntu-latest
 
    # 矩阵策略:在多个 Node.js 版本上运行作业
    strategy:
      matrix:
        node-version: [12, 14, 16]
 
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
 
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}
 
      - name: Install dependencies
        run: npm install
 
      - name: Run tests
        # 运行命令执行测试
        run: npm test
        # 设置步骤级别的环境变量
        env:
          CI: true
 
  deploy:
    # 需要等待 test 作业完成后再执行
    needs: test
    runs-on: ubuntu-latest
 
    # 仅在推送到 main 分支时执行部署
    if: github.ref == 'refs/heads/main'
 
    steps:
      - name: Checkout code
        uses: actions/checkout@v2
 
      - name: Set up Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 14
 
      - name: Install dependencies
        run: npm install
 
      - name: Build project
        run: npm run build
 
      - name: Deploy to server
        # 使用 GitHub Secrets 管理敏感信息
        env:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
          REMOTE_USER: ${{ secrets.REMOTE_USER }}
          REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
        run: |
          echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
          ssh -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_HOST "mkdir -p ~/myapp"
          rsync -avz -e "ssh -o StrictHostKeyChecking=no" ./build/ $REMOTE_USER@$REMOTE_HOST:~/myapp/
          ssh -o StrictHostKeyChecking=no $REMOTE_USER@$REMOTE_HOST "pm2 restart myapp"

GitHub Actions 基础实践

创建第一个 GitHub Actions 工作流

使用模板创建工作流是快速上手 GitHub Actions 的一种方法。GitHub 提供了一些预定义的模板,帮助用户快速生成工作流配置文件,适用于常见的 CI/CD 场景,如构建、测试和部署。

使用模板

graph LR
    A[访问仓库的 Actions 页面] --> B[选择模板]
    B --> C[修改模板]
    C --> D[保存工作流文件]
  1. 访问仓库的 Actions 页面: 在 GitHub 仓库页面上,点击顶部菜单中的 “Actions” 标签,进入 Actions 页面。
  2. 选择模板: GitHub 会根据仓库中的项目类型推荐一些工作流模板。例如,对于 Node.js 项目,会推荐 Node.js CI 模板。用户可以选择一个合适的模板进行创建。
  3. 修改模板: 选择模板后,GitHub 会展示模板的 YAML 配置文件。用户可以根据需要修改该文件,例如调整触发条件、添加或删除步骤。
  4. 保存工作流文件: 修改完成后,点击 “Start commit” 按钮,将工作流文件保存到仓库的 .github/workflows/ 目录下。

手动创建

手动编写工作流文件提供了更高的灵活性和控制力,适用于复杂或特定需求的自动化流程。用户可以根据具体需求,自定义工作流的触发条件、作业和步骤。

graph LR
    A[创建工作流文件] --> B[编写 YAML 文件]
    B --> C[定义工作流名称和触发条件]
    C --> D[定义作业和步骤]
  1. 创建工作流文件: 在仓库的根目录下创建 .github/workflows/ 目录。如果该目录不存在,需要手动创建。
  2. 编写 YAML 文件:.github/workflows/ 目录下创建一个新的 YAML 文件,例如 ci.yml。在该文件中定义工作流的名称、触发条件、作业和步骤。
  3. 定义工作流名称和触发条件: 使用 name 字段定义工作流的名称,使用 on 字段定义工作流的触发条件,如 pushpull_request
  4. 定义作业和步骤: 使用 jobs 字段定义一个或多个作业,每个作业包含多个步骤。步骤可以是运行命令或调用预定义的 action。

使用预定义的 Actions

GitHub Actions 生态系统中包含大量的预定义 Actions,分为官方 Actions 和社区 Actions。官方 Actions 由 GitHub 维护和提供,质量和可靠性有保障;社区 Actions 由开源社区开发和维护,种类丰富,覆盖了各种功能需求。可以在 GitHub Marketplace 查找和使用各种 Actions,查看其文档和示例。

官方 Actions 库

Action功能说明示例
actions/checkout检查出仓库代码uses: actions/checkout@v2
actions/setup-node设置 Node.js 环境uses: actions/setup-node@v2
actions/upload-artifact上传构建工件uses: actions/upload-artifact@v2
actions/download-artifact下载构建工件uses: actions/download-artifact@v2
actions/setup-python设置 Python 环境uses: actions/setup-python@v2
actions/setup-java设置 Java 环境uses: actions/setup-java@v2
actions/setup-go设置 Go 环境uses: actions/setup-go@v3
actions/cache缓存依赖和构建结果uses: actions/cache@v2
actions/github-script在 GitHub 上运行任意脚本uses: actions/github-script@v5
actions/labeler根据文件更改自动打标签uses: actions/labeler@v2
actions/stale自动标记和关闭过期的 issues 和 PRsuses: actions/stale@v5

社区 Actions 库

Action功能说明示例
stefanzweifel/git-auto-commit-action自动提交代码更改uses: stefanzweifel/git-auto-commit-action@v4
docker/build-push-action构建并推送 Docker 镜像uses: docker/build-push-action@v2
slackapi/slack-github-action发送通知到 Slack 频道uses: slackapi/slack-github-action@v1
github/codeql-action代码安全分析和质量检查uses: github/codeql-action/analyze@v2
peter-evans/create-issue-from-file从文件创建 issueuses: peter-evans/create-issue-from-file@v2
softprops/action-gh-release发布 GitHub Releaseuses: softprops/action-gh-release@v1
peaceiris/actions-gh-pages部署静态网站到 GitHub Pagesuses: peaceiris/actions-gh-pages@v3
JamesIves/github-pages-deploy-action自动部署到 GitHub Pagesuses: JamesIves/github-pages-deploy-action@4.1.4
coverallsapp/github-action测试覆盖率报告uses: coverallsapp/github-action@v1
actions-rs/toolchain设置 Rust 工具链uses: actions-rs/toolchain@v1
microsoft/playwright-github-action运行 Playwright 测试uses: microsoft/playwright-github-action@v1

使用预定义的 Actions 可以简化工作流配置,快速实现复杂功能。流行的预定义 Actions 通常经过广泛测试和使用,具有较高的可靠性和易用性。

步骤:

  1. 选择 Action: 在 GitHub Marketplace 或官方文档中查找需要的 Action,阅读其使用说明和示例。

  2. 添加到工作流: 在工作流文件的 steps 部分,使用 uses 关键字引用选定的 Action,并根据需求传递参数。

  3. 具体示例: 使用 actions/checkoutactions/setup-node Actions 的工作流示例:

    jobs:
      build:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout code
          uses: actions/checkout@v2 # 该 Action 用于将仓库代码检出到 Runner 的工作目录。此步骤通常是工作流的第一步,用于获取最新代码。
        - name: Set up Node.js
          uses: actions/setup-node@v2
          with:
            node-version: '14'
        - name: Install dependencies
          run: npm install
        - name: Run tests
          run: npm test

    示例解析:

    • actions/checkout
    • actions/setup-node:该 Action 用于设置 Node.js 环境。通过传递 node-version 参数,指定要使用的 Node.js 版本。
    • run:使用 run 关键字直接运行命令行命令,如安装依赖和运行测试。

运行基本的 CI 流程

构建

构建工具用于自动化编译、打包和依赖管理,是 CI 流程的重要组成部分。Maven 和 Gradle 是常见的 Java 项目构建工具,其他语言也有类似的工具,如 Node.js 的 npm 和 Python 的 pip。

步骤:

  1. 设置构建环境: 在工作流文件中,配置运行环境和必要的依赖工具。例如,在 Java 项目中,通常需要设置 JDK 环境。
  2. 添加构建步骤:steps 部分,使用 run 关键字执行构建工具的命令,如 mvn installgradle build

示例: 集成 Maven 的工作流文件示例:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up JDK
      uses: actions/setup-java@v2
      with:
        java-version: '11'
    - name: Build with Maven
      run: mvn install

集成 Gradle 的工作流文件示例:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up JDK
      uses: actions/setup-java@v2
      with:
        java-version: '11'
    - name: Build with Gradle
      run: gradle build

测试

单元测试和集成测试是保证代码质量和功能正确性的关键步骤。通过在工作流中集成测试步骤,可以在每次代码变更时自动运行测试,及时发现和修复问题。

步骤:

  1. 配置测试环境: 确保工作流中包含必要的依赖工具和环境设置,以便能够运行测试。例如,在 Node.js 项目中,需要安装依赖包。
  2. 添加测试步骤:steps 部分,使用 run 关键字执行测试命令,如 npm testmvn testgradle test

示例: 添加单元测试和集成测试的工作流文件示例(Node.js 项目):

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'
    - name: Install dependencies
      run: npm install
    - name: Run unit tests
      run: npm test
    - name: Run integration tests
      run: npm run integration-test

添加单元测试和集成测试的工作流文件示例(Java 项目):

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up JDK
      uses: actions/setup-java@v2
      with:
        java-version: '11'
    - name: Build with Maven
      run: mvn install
    - name: Run unit tests
      run: mvn test
    - name: Run integration tests
      run: mvn verify

GitHub Actions 进阶操作

自定义 Actions

创建和发布 JavaScript Actions

JavaScript Actions 是基于 Node.js 环境执行的自定义 Actions,适用于编写需要复杂逻辑或与 Node.js 生态系统集成的任务。它们可以复用现有的 npm 包,并且易于调试和测试。

  1. 初始化项目: 使用 npm init 初始化一个新的 Node.js 项目,并安装必要的依赖。

    $ mkdir my-action
    $ cd my-action
    $ npm init -y
    $ npm install @actions/core @actions/github
  2. 编写代码: 创建 index.js 文件,编写 Action 的核心逻辑。

    const core = require('@actions/core');
    const github = require('@actions/github');
     
    try {
      const nameToGreet = core.getInput('who-to-greet');
      console.log(`Hello ${nameToGreet}!`);
      const time = new Date().toTimeString();
      core.setOutput("time", time);
    } catch (error) {
      core.setFailed(error.message);
    }
  3. 创建 Action 元数据文件: 在项目根目录下创建 action.yml 文件,定义 Action 的元数据。

    name: 'Hello World'
    description: 'Greet someone and print the current time'
    inputs:
      who-to-greet:
        description: 'The name of the person to greet'
        required: true
        default: 'World'
    runs:
      using: 'node12'
      main: 'index.js'
  4. 发布 Action: 将代码提交到 GitHub 仓库,并打标签发布。

    $ git add .
    $ git commit -m "Initial commit"
    $ git tag -a -m "Initial release" v1
    $ git push --follow-tags
  5. **示例使用:**在工作流中使用自定义的 JavaScript Action:

    jobs:
      greet:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Greet
          uses: my-org/my-action@v1
          with:
            who-to-greet: 'John Doe'

创建和发布 Docker Actions

Docker Actions 运行在 Docker 容器中,适用于需要特定环境或依赖的任务。通过 Docker,可以确保 Action 在各种环境中具有一致的运行行为。

  1. 创建 Dockerfile: 在项目根目录下创建 Dockerfile,定义容器的构建过程。

    FROM node:12-alpine
    COPY . /my-action
    WORKDIR /my-action
    RUN npm install
    ENTRYPOINT ["node", "/my-action/index.js"]
  2. 编写代码: 创建 index.js 文件,编写 Action 的核心逻辑。

    const core = require('@actions/core');
    const github = require('@actions/github');
     
    try {
      const nameToGreet = core.getInput('who-to-greet');
      console.log(`Hello ${nameToGreet}!`);
      const time = new Date().toTimeString();
      core.setOutput("time", time);
    } catch (error) {
      core.setFailed(error.message);
    }
  3. 创建 Action 元数据文件: 在项目根目录下创建 action.yml 文件,定义 Action 的元数据。

    name: 'Hello World'
    description: 'Greet someone and print the current time'
    inputs:
      who-to-greet:
        description: 'The name of the person to greet'
        required: true
        default: 'World'
    runs:
      using: 'docker'
      image: 'Dockerfile'
  4. 发布 Action: 将代码提交到 GitHub 仓库,并打标签发布。

    $ git add .
    $ git commit -m "Initial commit"
    $ git tag -a -m "Initial release" v1
    $ git push --follow-tags
  5. 示例使用: 在工作流中使用自定义的 Docker Action:

    jobs:
      greet:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Greet
          uses: my-org/my-action@v1
          with:
            who-to-greet: 'Jane Doe'

使用 Composite Actions 复用步骤

Composite Actions 允许将多个步骤组合成一个 Action,以便在多个工作流中复用。适用于需要多个步骤的复杂任务。

步骤:

  1. 创建 Composite Action 文件: 在项目根目录下创建 action.yml 文件,定义 Composite Action。

    name: 'Greet and Time'
    description: 'Greet someone and print the current time'
    inputs:
      who-to-greet:
        description: 'The name of the person to greet'
        required: true
        default: 'World'
    runs:
      using: 'composite'
      steps:
      - run: echo "Hello ${{ inputs.who-to-greet }}!"
      - run: echo "The current time is ${{ steps.time.outputs.time }}"
        id: time
        shell: bash
  2. 发布 Composite Action: 将代码提交到 GitHub 仓库,并打标签发布。

    $ git add .
    $ git commit -m "Initial commit"
    $ git tag -a -m "Initial release" v1
    $ git push --follow-tags
  3. 示例使用: 在工中使用自定义的 Composite Action:

jobs:
  greet_and_time:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Greet and Time
      uses: my-org/greet-and-time@v1
      with:
        who-to-greet: 'Alice'

使用 GitHub Secrets 进行安全管理

添加和管理 Secrets

Secrets 是 GitHub 提供的一种安全管理敏感信息的方法,用于存储诸如 API 密钥、凭据和其他机密数据。Secrets 可以在工作流中安全地引用,而不暴露实际值。

步骤:

  1. 添加 Secrets: 在 GitHub 仓库页面,进入 “Settings” “Secrets” “Actions”,点击 “New repository secret” 添加新的 Secret。
    • Name:为 Secret 取一个名称,例如 MY_SECRET.
    • Value:输入 Secret 的值,例如 super-secret-value.
  2. 管理 Secrets: Secrets 可以通过 GitHub 界面进行添加、编辑和删除。注意:Secret 值一旦保存,不能直接查看,只能通过工作流引用。

在工作流中安全地使用 Secrets

在工作流中,可以通过 ${{ secrets.SECRET_NAME }} 的语法安全地引用 Secrets。GitHub Actions 会在运行时将该表达式替换为实际的 Secret 值。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Use Secret
      run: echo "The secret is ${{ secrets.MY_SECRET }}"

示例解析:

  • secrets.MY_SECRET:引用名称为 MY_SECRET 的 Secret。GitHub Actions 会在运行时自动替换为 Secret 的实际值。

设置条件化执行和并行作业

使用 if 表达式设置条件化执行

if 表达式允许根据条件控制工作流的执行。例如,可以在特定分支上执行特定步骤,或在测试失败时停止后续步骤。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Run tests
      run: npm test
    - name: Deploy
      if: github.ref == 'refs/heads/main' && success()
      run: ./deploy.sh

示例解析:

  • if: github.ref == 'refs/heads/main' && success():仅在当前分支为 main 且前一步骤成功时执行 deploy 步骤。

配置并行作业和依赖关系

默认情况下,GitHub Actions 中的作业是并行运行的。通过配置 needs 关键字,可以定义作业之间的依赖关系,确保某些作业按顺序执行。

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Build project
      run: npm build
 
  test:
    runs-on: ubuntu-latest
    needs: build
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Run tests
      run: npm test
 
  deploy:
    runs-on: ubuntu-latest
    needs: [build, test]
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Deploy project
      run: ./deploy.sh

示例解析:

  • needs: build:表示 test 作业依赖 build 作业,test 作业将在 build 作业完成后执行。
  • needs: [build, test]:表示 deploy 作业依赖 buildtest 作业,deploy 作业将在 buildtest 作业完成后执行。

集成第三方服务(如 Slack、AWS、Azure)

使用 Webhooks 和自定义 Notifications

Webhooks 允许工作流在特定事件发生时向外部服务发送 HTTP 请求,实现与外部服务的集成和通知。自定义 Notifications 可用于在工作流执行过程中发送通知,例如 Slack 通知。

示例: 向 Slack 发送通知:

  1. 创建 Slack Webhook URL: 在 Slack 工作区中,创建一个新的 Webhook URL。

  2. 添加 Slack Webhook URL 到 Secrets: 在 GitHub 仓库中添加一个新的 Secret,例如 SLACK_WEBHOOK_URL,保存 Webhook URL。

  3. 在工作流中使用 Webhook URL:

    jobs:
      notify:
        runs-on: ubuntu-latest
        steps:
        - name: Send notification to Slack
          run: |
            curl -X POST -H 'Content-type: application/json' \
            --data '{"text":"Build completed successfully!"}' \
            ${{ secrets.SLACK_WEBHOOK_URL }}

示例解析:

  • secrets.SLACK_WEBHOOK_URL:引用名称为 SLACK_WEBHOOK_URL 的 Secret,用于发送 HTTP 请求到 Slack Webhook URL。

部署到 AWS、Azure、GCP 等云服务

GitHub Actions 可以与各大云服务平台(如 AWS、Azure、GCP)集成,实现自动化部署。通过使用官方或社区提供的 Actions,可以简化部署流程。

部署到 AWS S3:

  1. 添加 AWS 凭证到 Secrets: 在 GitHub 仓库中添加 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY Secrets。

  2. 在工作流中配置部署步骤:

    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout code
          uses: actions/checkout@v2
        - name: Upload to S3
          uses: aws-actions/configure-aws-credentials@v1
          with:
            aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
            aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
            aws-region: us-west-2
        - name: Sync S3 bucket
          run: |
            aws s3 sync . s3://my-bucket --exclude ".git/*"

示例解析:

  • aws-actions/configure-aws-credentials@v1:配置 AWS 凭证和区域。
  • aws s3 sync:使用 AWS CLI 将代码同步到 S3 存储桶。

通知集成(如 Slack、Microsoft Teams)

除了 Webhooks,GitHub Actions 还可以通过官方和社区 Actions 发送通知到各种消息平台,如 Slack 和 Microsoft Teams。这些通知可以用于报告工作流状态、构建结果等。

发送通知到 Microsoft Teams:

  1. 创建 Microsoft Teams Webhook URL: 在 Microsoft Teams 中,创建一个新的 Webhook URL。

  2. 添加 Webhook URL 到 Secrets: 在 GitHub 仓库中添加一个新的 Secret,例如 TEAMS_WEBHOOK_URL,保存 Webhook URL。

  3. 在工作流中使用 Webhook URL:

    jobs:
      notify:
        runs-on: ubuntu-latest
        steps:
        - name: Send notification to Microsoft Teams
          run: |
            curl -H 'Content-Type: application/json' \
            -d '{"title": "Build Notification", "text": "The build has completed successfully!"}' \
            ${{ secrets.TEAMS_WEBHOOK_URL }}

示例解析:

  • secrets.TEAMS_WEBHOOK_URL:引用名称为 TEAMS_WEBHOOK_URL 的 Secret,用于发送 HTTP 请求到 Microsoft Teams Webhook URL。

GitHub Actions 高级实践

持续交付(CD)流程

配置持续交付流水线

持续交付(CD)是软件工程中的一项实践,旨在通过自动化部署过程,使软件能够随时发布到任何环境。GitHub Actions 提供了强大的工具支持配置和管理 CD 流水线。

步骤:

  1. 创建工作流文件:.github/workflows/ 目录下创建一个新的工作流文件,例如 cd.yml

  2. 定义触发条件: 配置工作流在合适的事件发生时触发,如代码推送到主分支或发布标签创建。

    on:
      push:
        branches:
          - main
      release:
        types: [created]
  3. 配置作业: 定义 CD 流水线的各个作业,包括构建、测试和部署。

name: CD Pipeline
 
on:
  push:
    branches:
      - main
  release:
    types: [created]
 
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Build project
      run: npm build
 
  test:
    runs-on: ubuntu-latest
    needs: build
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Run tests
      run: npm test
 
  deploy:
    runs-on: ubuntu-latest
    needs: [build, test]
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Deploy to production
      run: ./deploy.sh

自动化版本发布和部署

自动化版本发布和部署确保软件能够快速、安全地交付给用户,减少人为操作和错误。GitHub Actions 可以自动执行版本号管理、构建工件发布和部署到目标环境。

步骤:

  1. 版本号管理: 在构建完成后,使用脚本自动更新版本号。
  2. 发布构建工件: 使用 actions/upload-artifact 将构建工件上传到 GitHub,或使用 actions/create-release 创建 GitHub Release。
  3. 自动部署: 配置部署步骤,将构建工件部署到目标环境。
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14'
    - name: Build project
      run: npm build
    - name: Upload build artifacts
      uses: actions/upload-artifact@v2
      with:
        name: build-artifacts
        path: build/
 
  release:
    runs-on: ubuntu-latest
    needs: build
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Create GitHub Release
      uses: actions/create-release@v1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: v1.0.0
        release_name: Release v1.0.0
        draft: false
        prerelease: false
    - name: Upload release assets
      uses: actions/upload-release-asset@v1
      with:
        upload_url: ${{ steps.create_release.outputs.upload_url }}
        asset_path: ./build/
        asset_name: build-artifacts.zip
        asset_content_type: application/zip
 
  deploy:
    runs-on: ubuntu-latest
    needs: release
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Deploy to production
      run: ./deploy.sh

使用矩阵构建不同环境和配置

定义矩阵策略

矩阵策略允许在多个环境和配置下并行运行作业,确保代码在不同平台、依赖版本和配置下的兼容性和稳定性。

步骤:

  1. 定义矩阵: 在工作流文件中使用 matrix 关键字定义多个变量组合。
  2. 配置作业: 配置作业使用矩阵变量运行。
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12, 14, 16]
        os: [ubuntu-latest, windows-latest, macos-latest]
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}
    - name: Install dependencies
      run: npm install
    - name: Run tests
      run: npm test

针对不同操作系统和依赖版本运行作业

使用矩阵策略,可以针对不同操作系统和依赖版本并行运行作业,验证代码在多种环境下的行为。

示例: 在多个操作系统和 Node.js 版本上运行测试:

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        node-version: [12, 14, 16]
        os: [ubuntu-latest, windows-latest, macos-latest]
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Setup Node.js
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}
    - name: Install dependencies
      run: npm install
    - name: Run tests
      run: npm test

部署到 Kubernetes

使用 kubectlkustomize 进行 Kubernetes 部署

kubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群。kustomize 允许在 Kubernetes 原生清单上进行声明式配置管理。使用它们可以实现自动化 Kubernetes 部署。

步骤:

  1. 配置 Kubernetes 凭证: 在 GitHub Secrets 中添加 Kubernetes 配置,例如 KUBE_CONFIG.
  2. 编写部署步骤: 在工作流中使用 kubectlkustomize 部署应用。
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up kubectl
      uses: azure/setup-kubectl@v1
      with:
        version: 'v1.18.0'
    - name: Deploy to Kubernetes
      env:
        KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
      run: |
        kubectl apply -k ./kustomize

集成 Helm Charts

Helm 是 Kubernetes 的包管理工具,使用 Charts 定义、安装和管理 Kubernetes 应用。通过 Helm 可以简化 Kubernetes 应用的部署和管理。

步骤:

  1. 添加 Helm 凭证: 在 GitHub Secrets 中添加 Helm 凭证,例如 HELM_REPO_URLHELM_REPO_AUTH.
  2. 编写部署步骤: 在工作流中使用 Helm 部署应用。
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up Helm
      uses: azure/setup-helm@v1
    - name: Deploy with Helm
      env:
        HELM_REPO_URL: ${{ secrets.HELM_REPO_URL }}
        HELM_REPO_AUTH: ${{ secrets.HELM_REPO_AUTH }}
      run: |
        helm repo add my-repo $HELM_REPO_URL --username $HELM_REPO_AUTH
        helm upgrade --install my-release my-repo/my-chart

4.3.3 配置自动扩展和滚动更新

自动扩展和滚动更新是 Kubernetes 提供的功能,用于动态调整应用实例数量和无停机时间更新应用。配置这些功能可以提高应用的弹性和可靠性。

步骤:

  1. 编写 Kubernetes 配置文件: 使用 HPA(Horizontal Pod Autoscaler)和 Rolling Update 策略配置文件。
  2. 在工作流中应用配置: 使用 kubectl 命令应用这些配置。
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Set up kubectl
      uses: azure/setup-kubectl@v1
      with:
        version: 'v1.18.0'
    - name: Apply Kubernetes configuration
      env:
        KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
      run: |
        kubectl apply -f k8s/deployment.yaml
        kubectl apply -f k8s/hpa.yaml

性能优化和故障排查

优化工作流运行时间

优化工作流运行时间可以提高开发效率,减少等待时间。通过并行执行任务、缓存依赖和减少不必要的步骤可以实现优化。

步骤:

  1. 使用缓存: 使用 actions/cache 缓存依赖,减少重复下载和安装时间。
  2. 并行执行任务: 将独立的任务配置为并行执行,减少总运行时间。
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Cache npm dependencies
      uses: actions/cache@v2
      with:
        path: ~/.npm
        key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
        restore-keys: |
          ${{ runner.os }}-node-
    - name: Install dependencies
      run: npm install
    - name: Build project
      run: npm build

日志和调试

通过分析日志可以排查工作流中的问题。GitHub Actions 提供详细的日志记录,可以在执行过程中查看每个步骤的输出。

步骤:

  1. 启用调试日志: 在工作流文件中设置 ACTIONS_STEP_DEBUG 环境变量为 true
  2. 查看运行日志: 在 GitHub Actions 界面查看每个作业和步骤的详细日志。
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      ACTIONS_STEP_DEBUG: true
    steps:
    - name: Checkout code
      uses: actions/checkout@v2
    - name: Run tests
      run: npm test

监控和告警设置

通过监控和告警可以及时发现和处理问题,确保工作流的稳定运行。可以使用外部服务(如 Prometheus 和 Grafana)或集成通知(如 Slack)实现监控和告警。

步骤:

  1. 集成监控工具: 在工作流中集成 Prometheus、Grafana 等监控工具,收集和可视化指标数据。
  2. 设置告警通知: 在工作流中配置告警通知,通过 Slack 或 Email 接收告警信息。

示例: 通过 Slack 发送告警通知:

jobs:
  notify:
    runs-on: ubuntu-latest
    steps:
    - name: Send notification to Slack
      run: |
        curl -X POST -H 'Content-type: application/json' \
        --data '{"text":"Build failed!"}' \
        ${{ secrets.SLACK_WEBHOOK_URL }}

GitHub Actions 与其他 CI/CD 工具的对比

CI/CD 工具用于自动化软件构建、测试和部署过程,确保快速和可靠的发布周期。不同的工具有各自的优势和特点,适合不同规模和需求的项目。

Jenkins

Jenkins 是一个开源的自动化服务器,广泛用于构建、部署和自动化任何项目。由于其强大的插件生态系统和可扩展性,Jenkins 成为许多企业的首选 CI/CD 工具。

优点:

  • 开源和可扩展性:庞大的插件库,可以满足几乎所有的 CI/CD 需求。
  • 广泛的社区支持:活跃的社区和丰富的资源(文档、教程、插件)。
  • 可自托管:完全控制构建环境和安全性,适用于企业内部部署。

缺点:

  • 复杂性:设置和维护可能需要大量时间和经验。
  • 用户界面:传统界面可能不够直观,需要学习曲线。
  • 资源消耗:自托管模式需要管理服务器资源。

适用场景:

  • 需要高度定制化和控制的企业级项目。
  • 复杂的构建和部署流水线。

示例:

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean install'
            }
        }
        stage('Test') {
            steps {
                sh 'mvn test'
            }
        }
        stage('Deploy') {
            steps {
                sh './deploy.sh'
            }
        }
    }
}

Travis CI

Travis CI 是一个基于云的 CI 服务,特别适合开源项目。它提供简单的配置和与 GitHub 的深度集成。

优点:

  • 简单易用:配置文件简洁明了,适合快速上手。
  • 开源友好:免费提供给开源项目。
  • GitHub 集成:无缝集成 GitHub 仓库。

缺点:

  • 有限的自定义:相比 Jenkins,Travis CI 的自定义能力较弱。
  • 资源限制:免费版有并发构建和资源使用限制。
  • 速度和稳定性:在高峰期可能会出现构建排队和延迟。

适用场景:

  • 开源项目。
  • 需要快速上手和简便配置的小型项目。

示例:

language: java
jdk:
  - openjdk11
script:
  - mvn clean install
  - mvn test
deploy:
  provider: script
  script: ./deploy.sh
  on:
    branch: main

CircleCI

CircleCI 是一个基于云的 CI/CD 工具,提供灵活的配置和强大的并行执行能力,支持多种编程语言和框架。

优点:

  • 并行执行:支持并行化构建和测试,加快 CI/CD 流水线速度。
  • 灵活配置:通过 YAML 文件配置流水线,支持多种语言和环境。
  • 集成和扩展:与 GitHub、Bitbucket 和 Docker 集成良好。

缺点:

  • 成本:高级功能和更多资源需要付费。
  • 复杂配置:高级功能可能需要复杂的配置和调试。
  • 资源限制:免费版有并发和资源使用限制。

适用场景:

  • 需要高并发和快速构建的大型项目。
  • 希望在云端管理 CI/CD 流水线的项目。

示例:

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/openjdk:11
    steps:
      - checkout
      - run: mvn clean install
      - run: mvn test
workflows:
  version: 2
  build-and-test:
    jobs:
      - build

GitLab CI

GitLab CI 是 GitLab 集成的 CI/CD 工具,提供完整的 DevOps 生命周期管理,适合从代码托管到部署的全流程管理。

优点:

  • 集成性:与 GitLab 无缝集成,支持整个 DevOps 生命周期。
  • 自托管:提供自托管和云端版本,满足不同企业需求。
  • 安全性:内置的安全扫描和代码质量检查功能。

缺点:

  • 复杂性:全面的功能可能需要较长的学习曲线。
  • 资源管理:自托管版本需要额外的资源管理和维护。
  • 界面:某些高级功能的界面和配置可能不够直观。

适用场景:

  • 需要一体化 DevOps 解决方案的企业。
  • 希望在同一平台上管理代码、CI/CD 和部署的项目。

示例:

stages:
  - build
  - test
  - deploy
 
build:
  stage: build
  script:
    - mvn clean install
 
test:
  stage: test
  script:
    - mvn test
 
deploy:
  stage: deploy
  script:
    - ./deploy.sh
  only:
    - main

比较总结

特性JenkinsTravis CICircleCIGitLab CI
开源/商业开源商业,开源项目免费商业,开源项目有限免费开源,商业版
托管方式自托管云服务云服务,自托管云服务,自托管
扩展性
配置复杂度
社区支持
适用项目类型大型企业项目,复杂流水线开源项目,小型项目需要高并发和快速构建的项目希望全流程管理的企业项目

不同的 CI/CD 工具各有优劣,选择合适的工具需要根据项目规模、复杂度和团队需求进行综合考虑。