跳至主要内容

从 CircleCI 迁移到 GitHub Actions

GitHub Actions 和 CircleCI 在配置方面有一些相似之处,这使得迁移到 GitHub Actions 相对简单。

简介

CircleCI 和 GitHub Actions 都允许您创建工作流,这些工作流可以自动构建、测试、发布、发布和部署代码。CircleCI 和 GitHub Actions 在工作流配置方面有一些相似之处

  • 工作流配置文件使用 YAML 编写并存储在存储库中。
  • 工作流包含一个或多个作业。
  • 作业包含一个或多个步骤或单个命令。
  • 步骤或任务可以重复使用并与社区共享。

有关更多信息,请参阅“了解 GitHub Actions”。

主要区别

从 CircleCI 迁移时,请考虑以下差异

  • CircleCI 的自动测试并行处理会根据用户指定的规则或历史计时信息自动对测试进行分组。此功能未内置在 GitHub Actions 中。
  • 在 Docker 容器中执行的操作对权限问题敏感,因为容器具有不同的用户映射。您可以通过不在您的 *Dockerfile* 中使用 USER 指令来避免许多此类问题。有关 GitHub 托管运行器上的 Docker 文件系统的更多信息,请参阅“使用 GitHub 托管运行器”。

迁移工作流和作业

CircleCI 在 *config.yml* 文件中定义 workflows,这允许您配置多个工作流。GitHub 每个工作流需要一个工作流文件,因此不需要您声明 workflows。您需要为 *config.yml* 中配置的每个工作流创建一个新的工作流文件。

CircleCI 和 GitHub Actions 都使用类似的语法在配置文件中配置jobs。如果您在 CircleCI 工作流中使用requires配置作业之间的任何依赖项,则可以使用等效的 GitHub Actions needs语法。有关更多信息,请参阅“GitHub Actions 的工作流语法”。

将 orbs 迁移到 actions

CircleCI 和 GitHub Actions 都提供了一种在工作流中重用和共享任务的机制。CircleCI 使用称为 orbs 的概念(以 YAML 编写)来提供人们可以在工作流中重用的任务。GitHub Actions 具有功能强大且灵活的可重用组件,称为 actions,您可以使用 JavaScript 文件或 Docker 映像构建这些组件。您可以通过编写与存储库以任何您想要的方式交互的自定义代码来创建 actions,包括与 GitHub 的 API 和任何公开可用的第三方 API 集成。例如,一个 action 可以发布 npm 模块,在创建紧急问题时发送短信警报,或部署可用于生产的环境代码。有关更多信息,请参阅“共享自动化”。

CircleCI 可以使用 YAML 锚点和别名重用工作流的部分内容。GitHub Actions 使用矩阵支持最常见的可重用性需求。有关矩阵的更多信息,请参阅“在工作流中运行作业的变体”。

使用 Docker 镜像

CircleCI 和 GitHub Actions 都支持在 Docker 镜像内运行步骤。

CircleCI 提供了一组具有常见依赖项的预构建镜像。这些镜像将USER设置为circleci,这会导致权限与 GitHub Actions 发生冲突。

我们建议您在迁移到 GitHub Actions 时停止使用 CircleCI 的预构建镜像。在许多情况下,您可以使用 actions 来安装所需的额外依赖项。

有关 Docker 文件系统的更多信息,请参阅“使用 GitHub 托管的运行器”。

有关 GitHub 托管运行器镜像上可用的工具和软件包的更多信息,请参阅“使用 GitHub 托管的运行器”。

使用变量和密钥

CircleCI 和 GitHub Actions 支持在配置文件中设置变量,并使用 CircleCI 或 GitHub UI 创建密钥。

有关更多信息,请参阅“在变量中存储信息”和“在 GitHub Actions 中使用密钥”。

缓存

CircleCI 和 GitHub Actions 提供了一种在配置文件中手动缓存文件的方法。

以下是每个系统的语法示例。

CircleCI 缓存语法

- restore_cache:
    keys:
      - v1-npm-deps-{{ checksum "package-lock.json" }}
      - v1-npm-deps-

GitHub Actions 缓存语法

- name: Cache node modules
  uses: actions/cache@v3
  with:
    path: ~/.npm
    key: v1-npm-deps-${{ hashFiles('**/package-lock.json') }}
    restore-keys: v1-npm-deps-

GitHub Actions 没有 CircleCI 的 Docker 层缓存 (或 DLC) 的等效项。

在作业之间持久化数据

CircleCI 和 GitHub Actions 都提供了在作业之间持久化数据的机制。

以下是 CircleCI 和 GitHub Actions 配置语法中的示例。

CircleCI 在作业之间持久化数据的语法

- persist_to_workspace:
    root: workspace
    paths:
      - math-homework.txt

...

- attach_workspace:
    at: /tmp/workspace

GitHub Actions 在作业之间持久化数据的语法

- name: Upload math result for job 1
  uses: actions/upload-artifact@v4
  with:
    name: homework
    path: math-homework.txt

...

- name: Download math result for job 1
  uses: actions/download-artifact@v4
  with:
    name: homework

有关更多信息,请参阅“存储和共享工作流数据”。

使用数据库和服务容器

这两个系统都允许您包含用于数据库、缓存或其他依赖项的其他容器。

在 CircleCI 中,config.yaml 中列出的第一个镜像是用于运行命令的主要镜像。GitHub Actions 使用显式部分:对主要容器使用container,并在services中列出其他容器。

以下是 CircleCI 和 GitHub Actions 配置语法中的示例。

CircleCI 使用数据库和服务容器的语法

---
version: 2.1

jobs:

  ruby-26:
    docker:
      - image: circleci/ruby:2.6.3-node-browsers-legacy
        environment:
          PGHOST: localhost
          PGUSER: administrate
          RAILS_ENV: test
      - image: postgres:10.1-alpine
        environment:
          POSTGRES_USER: administrate
          POSTGRES_DB: ruby26
          POSTGRES_PASSWORD: ""

    working_directory: ~/administrate

    steps:
      - checkout

      # Bundle install dependencies
      - run: bundle install --path vendor/bundle

      # Wait for DB
      - run: dockerize -wait tcp://127.0.0.1:5432 -timeout 1m

      # Setup the environment
      - run: cp .sample.env .env

      # Setup the database
      - run: bundle exec rake db:setup

      # Run the tests
      - run: bundle exec rake

workflows:
  version: 2
  build:
    jobs:
      - ruby-26
...

- attach_workspace:
    at: /tmp/workspace

GitHub Actions 使用数据库和服务容器的语法

name: Containers

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest
    container: circleci/ruby:2.6.3-node-browsers-legacy

    env:
      PGHOST: postgres
      PGUSER: administrate
      RAILS_ENV: test

    services:
      postgres:
        image: postgres:10.1-alpine
        env:
          POSTGRES_USER: administrate
          POSTGRES_DB: ruby25
          POSTGRES_PASSWORD: ""
        ports:
          - 5432:5432
        # Add a health check
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

    steps:
      # This Docker file changes sets USER to circleci instead of using the default user, so we need to update file permissions for this image to work on GH Actions.
      # See https://docs.github.com/actions/using-github-hosted-runners/about-github-hosted-runners#docker-container-filesystem

      - name: Setup file system permissions
        run: sudo chmod -R 777 $GITHUB_WORKSPACE /github /__w/_temp
      - uses: actions/checkout@v4
      - name: Install dependencies
        run: bundle install --path vendor/bundle
      - name: Setup environment configuration
        run: cp .sample.env .env
      - name: Setup database
        run: bundle exec rake db:setup
      - name: Run tests
        run: bundle exec rake

有关更多信息,请参阅“关于服务容器”。

完整示例

下面是一个现实世界的示例。左侧显示了 thoughtbot/administrator 存储库的实际 CircleCI config.yml。右侧显示了 GitHub Actions 等效项。

CircleCI 的完整示例

---
version: 2.1

commands:
  shared_steps:
    steps:
      - checkout

      # Restore Cached Dependencies
      - restore_cache:
          name: Restore bundle cache
          key: administrate-{{ checksum "Gemfile.lock" }}

      # Bundle install dependencies
      - run: bundle install --path vendor/bundle

      # Cache Dependencies
      - save_cache:
          name: Store bundle cache
          key: administrate-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle

      # Wait for DB
      - run: dockerize -wait tcp://127.0.0.1:5432 -timeout 1m

      # Setup the environment
      - run: cp .sample.env .env

      # Setup the database
      - run: bundle exec rake db:setup

      # Run the tests
      - run: bundle exec rake

default_job: &default_job
  working_directory: ~/administrate
  steps:
    - shared_steps
    # Run the tests against multiple versions of Rails
    - run: bundle exec appraisal install
    - run: bundle exec appraisal rake

jobs:
  ruby-25:
    <<: *default_job
    docker:
      - image: circleci/ruby:2.5.0-node-browsers
        environment:
          PGHOST: localhost
          PGUSER: administrate
          RAILS_ENV: test
      - image: postgres:10.1-alpine
        environment:
          POSTGRES_USER: administrate
          POSTGRES_DB: ruby25
          POSTGRES_PASSWORD: ""

  ruby-26:
    <<: *default_job
    docker:
      - image: circleci/ruby:2.6.3-node-browsers-legacy
        environment:
          PGHOST: localhost
          PGUSER: administrate
          RAILS_ENV: test
      - image: postgres:10.1-alpine
        environment:
          POSTGRES_USER: administrate
          POSTGRES_DB: ruby26
          POSTGRES_PASSWORD: ""

workflows:
  version: 2
  multiple-rubies:
    jobs:
      - ruby-26
      - ruby-25

GitHub Actions 的完整示例

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# GitHub recommends pinning actions to a commit SHA.
# To get a newer version, you will need to update the SHA.
# You can also reference a tag or branch, but the action may change without warning.

name: Containers

on: [push]

jobs:
  build:

    strategy:
      matrix:
        ruby: ['2.5', '2.6.3']

    runs-on: ubuntu-latest

    env:
      PGHOST: localhost
      PGUSER: administrate
      RAILS_ENV: test

    services:
      postgres:
        image: postgres:10.1-alpine
        env:
          POSTGRES_USER: administrate
          POSTGRES_DB: ruby25
          POSTGRES_PASSWORD: ""
        ports:
          - 5432:5432
        # Add a health check
        options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

    steps:
      - uses: actions/checkout@v4
      - name: Setup Ruby
        uses: eregon/use-ruby-action@ec02537da5712d66d4d50a0f33b7eb52773b5ed1
        with:
          ruby-version: ${{ matrix.ruby }}
      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: vendor/bundle
          key: administrate-${{ matrix.image }}-${{ hashFiles('Gemfile.lock') }}
      - name: Install postgres headers
        run: |
          sudo apt-get update
          sudo apt-get install libpq-dev
      - name: Install dependencies
        run: bundle install --path vendor/bundle
      - name: Setup environment configuration
        run: cp .sample.env .env
      - name: Setup database
        run: bundle exec rake db:setup
      - name: Run tests
        run: bundle exec rake
      - name: Install appraisal
        run: bundle exec appraisal install
      - name: Run appraisal
        run: bundle exec appraisal rake