如何在多个GitHub CI作业中复用services配置代码
GitHub Actions 消除CI作业重复services配置的可行方案
针对同一份工作流文件内多作业复用services配置、且不共享运行中容器实例的需求,有两种成熟实现方案,优先推荐第一种轻量化方案:
方案1:使用YAML原生锚点与合并语法(同文件复用首选)
GitHub Actions 工作流本身是标准YAML格式,原生支持锚点(&)、别名(*)和合并键(<<)能力,完全可以在不引入额外抽象的前提下实现配置复用,且每个作业会独立启动属于自己的service容器,不会出现实例共享的问题。
具体实现步骤:
- 在工作流顶层添加一个GitHub不会识别解析的自定义键(惯例以
x-开头,比如x-common-config),把重复的services配置挂在这个键下并定义锚点 - 在需要用到这套配置的作业下,通过YAML合并语法直接引用锚点即可
示例代码如下:
name: CI on: [push, pull_request] # 顶层自定义节点,GitHub Actions会自动忽略该节点下的配置,仅用于存放公共锚点 x-common-services: &common-services postgres: image: postgres:13 env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: postgres ports: - 5432:5432 # Set health checks to wait until postgres has started # tmpfs for faster DB in RAM options: >- --mount type=tmpfs,destination=/var/lib/postgresql/data --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 chrome: image: seleniarm/standalone-chromium:4.1.2-20220227 ports: - 4444:4444 env: DB_HOST: localhost CHROMEDRIVER_HOST: localhost RAILS_ENV: test jobs: rspec: runs-on: ubuntu-latest services: <<: *common-services steps: # 原有RSpec相关执行步骤 - uses: actions/checkout@v4 # ... 其余步骤 cucumber: runs-on: ubuntu-latest services: <<: *common-services steps: # 原有Cucumber相关执行步骤 - uses: actions/checkout@v4 # ... 其余步骤
如果某个作业需要对公共services配置做微调(比如给chrome加额外环境变量、改postgres端口),直接在引用后覆写对应字段即可,不会影响其他作业的配置:
services: <<: *common-services chrome: <<: *common-services.chrome env: <<: *common-services.chrome.env CUSTOM_CHROME_FLAG: "enabled"
方案2:使用可复用工作流(跨多工作流文件复用场景)
如果你这套services配置后续需要在多个独立的工作流文件(比如不同分支的CI、定时巡检CI)中复用,可以把整套测试作业逻辑抽成GitHub Actions原生支持的可复用工作流,把测试执行命令作为输入参数对外暴露,RSpec和Cucumber作业分别调用该可复用工作流、传入不同的测试命令即可。
该方案同样会为每次调用独立启动service容器,不存在实例共享问题,但抽象成本比YAML锚点高,仅适合跨文件复用场景。
注意:不要尝试将services配置抽到复合动作(composite action)中,目前GitHub Actions的复合动作不支持定义services字段,该方案不可行。
内容的提问来源于stack exchange,提问作者tsvallender
相关产品推荐
相关产品推荐

