CI/CD

GitHubActions详解

转载:https://blog.csdn.net/unreliable_narrator/article/details/124468384

你可以配置一个 GitHub Actions 工作流,当代码库中的某个事件发生时触发,例如打开拉取请求或创建问题。你的工作流包含一个或多个可以顺序或并行运行的作业。每个作业将在其自己的虚拟机运行器内运行,或在容器内运行,并且有一个或多个步骤,这些步骤可以运行你定义的脚本或运行一个操作,这是一种可以简化工作流的可重用扩展。

  • Wolkflow:当代码库中发生某个事件时触发。
  • event:如打开拉取请求或创建问题。
  • jobs:一个或多个可以顺序或并行运行的任务。
  • runner:作业运行的虚拟机或容器。
  • steps:作业中的单个操作,可以运行脚本或操作。
  • action:简化工作流的可重用扩展。

什么是Github Action ?


GitHubActions是一个持续集成和持续交付的平台,它可以帮助你通过自动化的构建(包括编译、发布、自动化测试)来验证你的代码,从而尽快地发现集成错误。github于2019年11月后对该功能全面开放,现在所有的github用户可以直接使用该功能。GitHub 提供 Linux、Windows 和 macOS 虚拟机来运行您的工作流程,或者您可以在自己的数据中心或云基础架构中托管自己的自托管运行器。在使用Github Action之前首先需要了解以下前置知识:

  • 持续集成/持续交付的概念。
  • Git相关知识。
  • Linux或Windows或macOS脚本相关知识。
  • Yaml基础语法。

 

GitHub Actions 是一个自动化软件开发工作流程的平台,从想法构建到生成,开发者只需在.github/workflows 目录中添加 yml 格式文件,定义 Workflow(工作流程) 去实现 CI(持续集成)通过 了解 GitHub Actions,我们可以掌握 Workflow 中一些概念。

  • Event(触发事件):触发运行事件,例如,有人创建了 issue、PR 或者推送了代码到某个分支。
  • Job(作业):一个 Workflow 包含一个或多个 Job,默认情况下并行运行,我们可以设置让其按顺序执行,每个 Job 可以包含多个 Step
  • Step(步骤):定义每一个部分的工作内容,每一个 Step 都是一个单独的进程运行。该部分下每个项目都是一个单独操作或者 shell 脚本。

 引用官方文档的 Workflow 图,我们可以直观的看懂 EventJobStep 之间的关系:

Event(事件)

  • 作用:触发 GitHub Actions 工作流(Workflow)执行的 “起点” ,GitHub 仓库发生特定操作时,就会触发对应的 Event,进而运行工作流。
  • 常见类型
    • push:代码推送到仓库(如推送到 main 分支)时触发;
    • pull_request:创建、更新拉取请求(PR)时触发;
    • schedule:定时触发(类似 cron 任务);
    • workflow_dispatch:手动点击按钮触发(在 GitHub 页面手动运行工作流)。

 

Runner(运行器)

  • 作用:实际执行 Job 的 “载体” ,可以是 GitHub 托管的服务器(GitHub-hosted Runner),也可以是你自己配置的服务器(Self-hosted Runner)。每个 Runner 是独立的执行环境,能并行运行多个 Job(但同一时间一个 Runner 上的 Job 执行可能有资源竞争,需合理规划)。
  • 特点
    • 提供基础运行环境(如 Ubuntu、Windows、macOS 系统,预装 Docker、Git 等工具 );
    • 不同 Runner 之间环境隔离,一个 Runner 故障不影响其他 Runner。

 

Job(任务)

  • 作用:一组相关 Step 的集合,逻辑上独立的 “工作单元” 。Job 之间可以并行执行(默认),也可通过 needs 关键字设置依赖,按顺序执行。每个 Job 运行在一个 Runner 上(一个 Runner 可同时跑多个 Job,但会共享 Runner 资源 )。
  • 典型场景
    • 一个 Job 负责 “构建代码”,另一个 Job 负责 “运行测试”;
    • 一个 Job 部署到 “开发环境”,另一个 Job 部署到 “生产环境”(需依赖开发环境部署完成)。

 

Step(步骤)

  • 作用:Job 的最小执行单元,按顺序依次执行 。每个 Step 可以是:
    • 运行命令(run:执行 shell 脚本、编译代码等 );
    • 使用 Action(uses:复用别人写好的自动化逻辑,比如 actions/checkout@v4 拉取代码 );
    • 设置环境变量、上传 / 下载 artifacts 等操作。

 

结合图示的流程解释

触发流程

某个 Event(如代码 push 到仓库)发生 → 触发 GitHub Actions 工作流 → 工作流里定义的 Job 分配给 Runner 执行。

图示结构对应

  • Event:作为触发源,启动整个工作流。
  • Runner 1 & Runner 2:两个独立的执行环境,分别跑不同的 Job(也可跑同一 Job ,但图示是分开跑不同 Job 场景 )。
  • Job 1(在 Runner 1 上):包含 4 个 Step,依次执行 Run action(比如用 actions/setup-java@v4 配置 Java 环境 )→ Run script(比如执行 mvn clean 清理项目 )→ Run script(执行 mvn package 打包代码 )→ Run action(比如用 actions/upload-artifact@v4 上传打包好的文件 )。
  • Job 2(在 Runner 2 上):包含 3 个 Step,依次执行 Run action(比如用 docker/login-action@v3 登录镜像仓库 )→ Run script(执行 docker build 构建镜像 )→ Run script(执行 docker push 推送镜像 )。

 

实际场景举例(完整 Workflow 配置)

以下用一个 “Java 项目构建 + 镜像推送” 的工作流,对应图示概念:

name: Java CI & Docker Push  # 工作流名称
on:
  push:
    branches: [ "main" ]  # Event:代码推送到 main 分支时触发

jobs:
  build-project:  # Job 1:构建 Java 项目
    runs-on: ubuntu-latest  # 分配到 GitHub 托管的 Ubuntu Runner
    steps:
      - name: Checkout code  # Step 1:拉取代码(用官方 Action)
        uses: actions/checkout@v4

      - name: Set up JDK 17  # Step 2:配置 Java 环境(用官方 Action)
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Build with Maven  # Step 3:执行 Maven 打包命令
        run: mvn clean package -DskipTests

      - name: Upload artifact  # Step 4:上传打包结果(用官方 Action)
        uses: actions/upload-artifact@v4
        with:
          name: my-app.jar
          path: target/*.jar

  push-docker:  # Job 2:构建并推送 Docker 镜像
    runs-on: self-hosted  # 分配到自托管 Runner(比如你自己的服务器)
    needs: build-project  # 依赖 Job 1,等 Job 1 完成再执行
    steps:
      - name: Checkout code  # Step 1:拉取代码(复用代码仓库)
        uses: actions/checkout@v4

      - name: Login to Docker Hub  # Step 2:登录镜像仓库(用官方 Action)
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build Docker image  # Step 3:构建 Docker 镜像
        run: docker build -t my-docker-image:latest .

      - name: Push Docker image  # Step 4:推送镜像到仓库
        run: docker push my-docker-image:latest

 

流程对应概念:

  • Eventpush 到 main 分支,触发工作流。
  • Runner
    • build-project Job 跑在 GitHub 托管的 ubuntu-latest Runner;
    • push-docker Job 跑在你自己配置的 self-hosted Runner(需提前按前文步骤配置 )。
  • Job
    • build-project 负责代码构建、打包、上传产物;
    • push-docker 依赖 build-project,负责镜像构建、推送。
  • Step:每个 Job 里的步骤,按顺序执行,用 uses 调用 Action 或 run 执行命令。

 

关键逻辑补充

  1. Job 并行与依赖
    • 若不设置 needs,多个 Job 会并行执行(充分利用多 Runner 资源 );
    • 设置 needs: [job-name] 后,Job 会按依赖顺序串行执行(比如先构建再测试,再部署 )。
  2. Runner 选择策略
    • runs-on: ubuntu-latest(GitHub 托管):无需自己维护服务器,适合公共仓库或无特殊环境需求的场景;
    • runs-on: self-hosted(自托管):可访问私有网络、使用自定义硬件 / 软件环境,适合企业内部项目、需特殊依赖的场景。
  3. Step 执行结果
    • 每个 Step 执行失败(返回非 0 状态码 ),整个 Job 会终止;
    • 可通过 continue-on-error: true 让 Step 失败时继续执行后续 Step(需权衡场景使用 )。

什么是Yaml ?


编写GithubAction的流程时,需要创建一个workflow工作流,workflow必须存储在你的项目库根路径下的.github/workflows目录中,每一个 workflow对应一个具体的.yml 文件(或者 .yaml)。
yml是YAML(YAML Ain’t Markup Language)语言的文件,以数据为中心,比properties、xml等更适合做配置文件,主要有以下几个特点:

  • 大小写敏感。
  • 使用缩进表示层级关系。
  • 缩进只能使用空格,不能用 TAB 字符。
  • 缩进的空格数量不重要,只要层级相同的元素左对齐即可。
  • ‘#’ 表示注释。

 

Github Action基本概念


  •   workflow: 一个 workflow 就是一个完整的工作流过程,每个workflow 包含一组 jobs任务。
  •   job : jobs任务包含一个或多个job ,每个 job包含一系列的 steps 步骤。
  •   step : 每个 step 步骤可以执行指令或者使用一个 action 动作。
  •   action : 每个 action 动作就是一个通用的基本单元。

 

Github Action 的使用限制


在使用免费版本的Github Action是有如下限制的:

  作业执行时间 – 工作流中的每个作业最多可以运行 6 小时的执行时间。如果作业达到此限制,该作业将终止且无法完成。

  工作流运行时间 – 每个工作流运行限制为 35 天。如果工作流运行达到此限制,则工作流运行将被取消。此时间段包括执行持续时间以及等待和批准所花费的时间。

  API 请求 – 您可以在一小时内跨存储库中的所有操作执行多达 1000 个 API 请求。如果超出此限制,其他 API 调用将失败,这可能会导致作业失败。

  并发作业 – 可以在帐户中运行的并发作业数取决于 GitHub 计划,如下表所示。如果超出,则任何其他作业都将排队。

  作业矩阵 – 作业矩阵每次工作流运行最多可以生成 256 个作业。此限制适用于 GitHub 托管和自托管的运行程序。

  工作流运行队列 – 每个存储库的排队时间间隔不超过 500 个工作流运行,间隔为 10 秒。如果工作流运行达到此限制,则工作流运行将终止且无法完成。

具体以最新版官方文档为主:usage-limits-billing-and-administration

GitHub 计划并发作业总数最大并发 macOS 作业数
自由205
专业版405
团队605
企业18050

 

GitHubAction的使用


workflow

在项目库根路径下的.github/workflows目录中创建一个.yml 文件(或者 .yaml):

name: hello-github-actions
# 触发 workflow 的事件
on:
  push:
    # 分支随意
    branches:
      - master
# 一个workflow由执行的一项或多项job
jobs:
  # 一个job任务,任务名为build
  build:
    #运行在最新版ubuntu系统中
    runs-on: ubuntu-latest
    #步骤合集
    steps:
      #新建一个名为checkout_actions的步骤
      - name: checkout_actions
        #使用checkout@v2这个action获取源码
        uses: actions/checkout@v2 
      #使用建一个名为setup-node的步骤
      - name: setup-node
        #使用setup-node@v1这个action
        uses: actions/setup-node@v1
        #指定某个action 可能需要输入的参数
        with:
          node-version: '14'
      - name: npm install and build
        #执行执行某个shell命令或脚本
        run: |
          npm install
          npm run build
      - name: commit push
        #执行执行某个shell命令或脚本
        run: |
          git config --global user.email xxx@163.com
          git config --global user.name xxxx
          git add .
          git commit -m "update" -a
          git push
         # 环境变量
        env:
          email: xxx@163.com

 

name

Workflow的名字,随便可以设置,就是工作流的名字。如果省略该字段,默认为当前 workflow 的文件名。

name: hello-github-actions

 

on

触发的事件,可以是一个事件数组。在代码仓库Push时触发:

#push时触发
on: push

可以用数组指定多个条件触发:

#push和merge时触发
on: [push, merge]

还可以对条件进行限制触发:

#当master分支push时触发,可以限定分支或标签。
on:
  push:
    branches:
      - master

完整的事件列表,请查看官方文档。除了代码库事件,GitHub Actions 也支持外部事件触发,或者定时运行。

 

jobs

1.job

jobs表示要执行的一项或多项任务。jobs可以包含一个或多个job,一个job就是一个任务,这个任务可以包含多个步骤(steps):

jobs:
  job1:
    ...
  job2:
    ...     

需要注意的是每一个Job都是并发执行的并不是按照申明的先后顺序执行的, 如果多个job 之间存在依赖关系,那么你可能需要使用 needs :

jobs:
  job1:
  
  job2:
    needs: job1
  
  job3:
    needs: [job1, job2]

这里的needs声明了job2 必须等待 job1 成功完成,job3必须等待 job1 和 job2依次成功完成。因此,这个 workflow 的运行顺序依次为:job1、job2、job3。needs字段指定当前任务的依赖关系,即运行顺序。

 

ー2.job->runs-on

runs-on字段指定运行所需要的虚拟机环境。它是必填字段,目前可用的虚拟机如下:

  •     ubuntu-latest,ubuntu-18.04或ubuntu-16.04。
  •     windows-latest,windows-2019或windows-2016。
  •     macOS-latest或macOS-10.14
jobs:
  job1:
    runs-on: ubuntu-18.04
  job2:
    runs-on: macos-10.15
  job3:
    runs-on: windows-2019

github 会提供一个配置很不错的服务器做为 runner,Windows 和 Linux 虚拟机的硬件规格:

  •     2 核处理器。
  •     7 GB 内存。
  •     14 GB 固态硬盘空间。

macOS 虚拟机的硬件规格:

  •     3 核处理器。
  •     14 GB 内存。
  •     14 GB 固态硬盘空间。

如果你有网络时延的需求,(比如推送及拉取镜像时产生的网络时延),你也可以自建runner

 

ー3.job->env

使用env可以给该任务或者是步骤配置环境变量:

env:
   name: "zhangsan"
 run: |
   echo $name

环境变量可以配置在以下地方:

  •   jobs->job->env
  •   jobs->job->steps.env

 

ー4.job->steps

steps字段指定每个 Job 的运行步骤,每个job由多个step构成,它会从上至下依次执行。steps可以包含一个或多个步骤,每个 step 步骤可以有:

  •    name:步骤名称,步骤的名称。
  •    env:该步骤所需的环境变量。
  •     id : 每个步骤的唯一标识符
  •    uses : 使用哪个action,这个表示使用别人预先设置好的Actions,比如因为我代码中要用到python,所以就用了actions/setup-python@v1来设置python环境,不用我自己设置了。
  •    with: 指定某个action 可能需要输入的参数。
  •      run: 执行哪些指令,具体运行什么命令行代码。
  •      continue-on-error : 设置为 true 允许此步骤失败job 仍然通过。
  •     timeout-minutes : step 的超时时间。
...
name: Sync To Gitee
on: [ push ]
jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
    #创建一个打印环境变量的步骤
    - name: PrintName
      env:
        name: "zhangsan"
      run: |
        echo $name
    #创建一个安装Python环境的步骤    
    - name: SetUpPython
      uses: actions/setup-python@v1
      with:
        python-version: 3.7
    #创建一个安装Python包的步骤 
    - name: Install dependencies
      run: |
          python -m pip install --upgrade pip
          pip install requests
          pip install bs4
          pip install lxml

使用uses指的是这一步骤需要先调用哪个 Action。 Action 是组成工作流最核心最基础的元素。 每个 Action 可以看作封装的独立脚本,有自己的操作逻辑,我们只需要 uses 并通过 with 传入参数即可。 比如 actions/checkout@v2 就是官方社区贡献的用来拉取仓库分支的 Action, 你不需要考虑安装 git 命令工具,只需要把分支参数传入即可。

 

5.Action

Github Actions 是GitHub的持续集成服务。持续集成由很多操作组成,比如登录远程服务器,发布内容到第三方服务等等,这些相同的操作完全可以提取出来制作成脚本供所有人使用。GitHub允许开发者把每个操作写成独立的脚本文件,存放到代码仓库,使得其他开发者可以引用该脚本,这个脚本就是一个Action。如果你需要某种功能的Action可以从GitHub社区共享的action官方市场查找,也可以自己编程Action开源出来供大家使用。既然 actions 是代码仓库,当然就有版本的概念,用户可以引用某个具体版本的 action。 下面都是合法的 action 引用:

actions/setup-node@74bc508 # 指向一个 commit
actions/setup-node@v1.0 # 指向一个标签
actions/setup-node@master # 指向一个分支

 

GitHub Actions 中使用密文


在持续集成的过程中,我们可能会使用到自己的敏感数据,这些数据不应该被开源并泄露。那么如何才能安全的使用这些敏感数据呢?GithubActions提供了Secrets变量来实现这一效果。我们可以在 github repo 上依次点击 Settings -> Secrets-> Actions->New repository secret创建一个敏感数据例如:OSS_KEY_ID,OSS_KEY_SECRET, 然后我们就可以在GithubAction脚本中使用这一变量了:

-  name:  setup  aliyun  oss
    uses:  manyuanrong/setup-ossutil@master
    with:
        endpoint:  oss-cn-beijing.aliyuncs.com
        access-key-id:  ${{  secrets.OSS_KEY_ID  }}
        access-key-secret:  ${{  secrets.OSS_KEY_SECRET  }}

这里的secret就是一种context,描述 CI/CD 一个workflow 中的上下文信息,使用${{ expression }}语法表示。更多context信息可以参考官方文档

 

GitHubAction执行结果


对于GitHubAction的执行流程我们可以通过repo 上依次点击Actions就可以看到Action的状态和执行结果等信息:

 

 

GitHub Runner补充说明


GitHub Runner 是一款开源工具,用于执行 GitHub Actions 工作流里的任务,能让代码构建、测试、部署等 CI/CD(持续集成 / 持续部署 )流程在特定环境中运行,确保这些流程高效、可靠执行,连接 GitHub 仓库接收任务指令,是自动化流程的 “执行器” 。

分类及特点

  • GitHub 托管 Runner(GitHub-hosted Runner)
    • 由 GitHub 提供和维护,运行在 GitHub 的基础设施上,支持 Linux、Windows、macOS 系统 。
    • 优点是无需自己管理服务器,开箱即用,能快速执行工作流;GitHub 会自动处理环境配置、软件更新等,比如预装了常见的开发工具(Git、Docker 等 )。
    • 缺点是受 GitHub 资源限制,有并发数、运行时长(一般单任务最长 6 小时左右 )等约束;且运行环境相对固定,难自定义特殊依赖。
    • 示例:开发小型开源项目时,用 runs-on: ubuntu-latest 就能快速在 GitHub 提供的 Ubuntu 环境中构建、测试代码 。
  • 自托管 Runner(Self-hosted Runner)
    • 部署在用户自己的服务器、虚拟机、容器等环境中,可自主控制运行环境 。
    • 优点是能访问私有网络资源(如公司内网数据库、私有镜像仓库 );可自定义硬件配置(像用高性能 GPU 跑深度学习相关 CI/CD 任务 );摆脱 GitHub 托管 Runner 的资源限制,适合复杂、定制化场景 。
    • 缺点是需自己维护服务器,保障其在线、处理软件更新、解决环境依赖等问题,增加了运维成本 。
    • 示例:企业内部项目要连接内网数据库做自动化测试,就可在公司内网服务器部署自托管 Runner,配置 runs-on: self-hosted 让工作流在该环境执行 。

 

GitHub Actions 支持将 GitHub 托管的 Runner 和 自托管的 Runner 结合使用


GitHub Actions 支持将 GitHub 托管的 Runner 和 自托管的 Runner 结合使用,这种混合配置模式非常灵活,适合复杂场景。以下是具体实现方式和典型场景:

在工作流中指定不同 Runner

通过 runs-on 参数为不同 Job 指定不同类型的 Runner:

jobs:
  build:
    runs-on: ubuntu-latest  # GitHub 托管 Runner
    steps:
      - name: Build code
        run: mvn clean package

  deploy:
    runs-on: self-hosted  # 自托管 Runner
    needs: build
    steps:
      - name: Deploy to production
        run: docker-compose up -d

  

典型应用场景

1. 复杂依赖任务

  • 场景:项目部分任务依赖特殊环境(如私有数据库、特定硬件驱动)。
  • 方案
    • 简单任务(如代码编译)使用 GitHub 托管 Runner。
    • 依赖私有资源的任务(如集成测试)使用自托管 Runner,通过内网访问数据库。

2. 性能优化

  • 场景:部分任务需要高性能计算资源(如 GPU 训练、大规模编译)。
  • 方案
    • 日常任务使用 GitHub 托管 Runner。
    • 高性能任务使用自托管 Runner(配置 GPU 服务器或高内存机器)。

3. 安全合规要求

  • 场景:敏感代码处理或合规性检查需要内部网络环境。
  • 方案
    • 非敏感任务(如单元测试)使用 GitHub 托管 Runner。
    • 敏感任务(如合规扫描)使用自托管 Runner,部署在企业内网。

4. 资源成本控制

  • 场景:长期运行的任务(如压力测试)会消耗大量 GitHub 托管资源。
  • 方案
    • 短期任务使用 GitHub 托管 Runner。
    • 长期任务使用自托管 Runner,避免 GitHub 资源限制和额外费用。

 

以下是一个结合两种 Runner 的完整工作流:

name: Hybrid CI/CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest  # GitHub 托管 Runner
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Build with Maven
        run: mvn clean package -DskipTests

  test-unit:
    runs-on: ubuntu-latest  # GitHub 托管 Runner
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Run unit tests
        run: mvn test

  test-integration:
    runs-on: self-hosted  # 自托管 Runner(可访问内网数据库)
    needs: build
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
      - name: Run integration tests
        run: mvn verify -Dspring.profiles.active=integration
        env:
          DB_URL: jdbc:mysql://internal-db-server:3306/test

  deploy:
    runs-on: self-hosted  # 自托管 Runner(部署到生产环境)
    needs: [test-unit, test-integration]
    steps:
      - name: Deploy to production
        run: |
          docker login my-private-registry
          docker pull my-app:${{ github.sha }}
          docker-compose up -d

 

在 GitHub Actions 工作流中,Runner 的执行顺序主要由 Job 之间的依赖关系决定


在 GitHub Actions 工作流中,Runner 的执行顺序主要由 Job 之间的依赖关系决定,而不是 Runner 类型本身。无论是 GitHub 托管 Runner 还是自托管 Runner,Job 的执行顺序遵循以下规则:

Job 依赖决定执行顺序

1. 通过 needs 参数明确依赖

如果 Job A 在 needs 中指定依赖 Job B,则 Job B 会先执行,Job A 等待其完成后再运行。例如:

jobs:
  build:  # 使用 GitHub 托管 Runner
    runs-on: ubuntu-latest
    steps:
      - run: echo "Building..."

  test:  # 使用自托管 Runner
    runs-on: self-hosted
    needs: build  # 依赖 build 任务完成后才执行
    steps:
      - run: echo "Testing..."

  deploy:  # 使用自托管 Runner
    runs-on: self-hosted
    needs: test  # 依赖 test 任务完成后才执行
    steps:
      - run: echo "Deploying..."

执行顺序build → test → deploy,与 Runner 类型无关,仅由 needs 依赖链决定。

 

无依赖时并行执行

如果多个 Job 之间没有 needs 依赖,且运行在不同 Runner 上,则会并行执行(前提是 Runner 资源可用)。例如:

jobs:
  frontend:
    runs-on: ubuntu-latest  # GitHub 托管
    steps: [...]

  backend:
    runs-on: self-hosted    # 自托管
    steps: [...]

执行顺序frontend  backend 同时启动,并行运行。

 

同一 Runner 上的 Job 顺序

如果多个 Job 被分配到 同一自托管 Runner(通过标签或配置指定),则它们会按工作流中的顺序排队执行(因为单个 Runner 同一时间只能运行一个 Job)。例如:

jobs:
  job1:
    runs-on: [self-hosted, my-server]  # 同一自托管 Runner
    steps: [...]

  job2:
    runs-on: [self-hosted, my-server]  # 同一自托管 Runner
    steps: [...]

执行顺序job1 先执行,完成后 job2 再执行(即使没有 needs 依赖)。

 

典型场景中的顺序控制

混合 Runner 与依赖链结合

jobs:
  # 1. 编译任务(GitHub 托管 Runner)
  build:
    runs-on: ubuntu-latest
    steps: [...]

  # 2. 单元测试(GitHub 托管 Runner),依赖 build
  test-unit:
    runs-on: ubuntu-latest
    needs: build
    steps: [...]

  # 3. 集成测试(自托管 Runner),依赖 test-unit
  test-integration:
    runs-on: self-hosted
    needs: test-unit
    steps: [...]

  # 4. 部署(自托管 Runner),依赖所有测试
  deploy:
    runs-on: self-hosted
    needs: [test-unit, test-integration]
    steps: [...]

执行顺序
build → test-unit → test-integration → deploy,严格按依赖链顺序,不同 Runner 类型不影响顺序。

 

并行任务与 Runner 分配

jobs:
  # 并行任务 1:前端构建(GitHub 托管)
  build-frontend:
    runs-on: ubuntu-latest
    steps: [...]

  # 并行任务 2:后端测试(自托管)
  test-backend:
    runs-on: self-hosted
    steps: [...]

  # 汇总任务(自托管),依赖前两个任务
  deploy:
    runs-on: self-hosted
    needs: [build-frontend, test-backend]
    steps: [...]

执行顺序:
build-frontend 和 test-backend 并行执行 → deploy 等待两者完成后执行。

 

总结:Runner 与顺序的关系

  1. Runner 类型不直接决定顺序:顺序由 Job 之间的 needs 依赖关系控制,与 Runner 是 GitHub 托管还是自托管无关。
  2. 同一 Runner 上的任务串行执行:若多个 Job 分配到同一自托管 Runner(无并行配置),则按工作流中的顺序排队执行。
  3. 并行执行的条件
    • 无 needs 依赖的 Job 会并行执行(前提是有足够 Runner 资源)。
    • GitHub 托管 Runner 支持并行任务数受限于账号配额(如免费用户通常限制为 2 个并行作业)。

通过合理设计 needs 依赖和 Runner 分配,可以精确控制任务执行顺序,同时利用混合 Runner 架构的灵活性。

最后的示例


使用GitHubAction实现Push代码发送邮件通知功能。 主要通过 GitHub Action 监听代码 push 事件,并发送邮件(前提是邮箱需要开通 SMTP 服务)。
在项目中 ./github/workflows/ 路径下添加 .yml 或者 .yaml文件,名字可以随便取。在这里我取名为 github-action-email.yml:

name: github-action-email
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    # 检出代码
    - name: CheckoutRepo
      uses: actions/checkout@v2
    # 获取master分支上最新一条提交的git log  
    - name: GetLastLog
      id: git_log
      uses: Edisonboy/latest-git-log-action@main
      with:
        tag: origin/master
    # 发送邮件    
    - name: Send email
      uses: dawidd6/action-send-mail@v3
      with:
        server_address: smtp.qq.com
        server_port: 465
        username: ${{secrets.MAIL_USERNAME}}
        password: ${{secrets.MAIL_PASSWORD}}
        subject: Github Actions job result
        to: ${{secrets.MAIL_TOUSERNAME}}
        from: ${{secrets.MAIL_USERNAME}}
        body: ${{github.repository}} push log : ${{steps.git_log.outputs.log}}
  •   secrets.XXX : GitHub 允许仓库所有者创建和管理需要保密性的参数。例如邮件的账号和密码都是属于敏感参数。 可以通过项目Settings -> Secrets -> Actions配置密码,在这里我们添加 MAIL_USERNAME、MAIL_PASSWORD、MAIL_TOUSERNAME 三个配置参数(注意:这里的密码是指 SMTP 服务的授权密码)。
  •   上下文:可以访问工作流程运行、运行器环境、作业及步骤相关信息的方式${{github.repository}}:当前仓库的的所有者和仓库名称。${{steps.git_log_outputs.log}} :获取step id 为 git_log 的输出集。

因为我们定义 push 为触发条件,所以当我们只有push 代码后,我们定义的 GitHub Action 才会被执行。然后在 GitHub 上的 Action 能够实时看到当前的执行状态。