Help us learn about your current experience with the documentation. Take the survey.

从 GitHub Actions 迁移

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

如果您正在从 GitHub Actions 迁移到 GitLab CI/CD,您可以创建能够复制并增强 GitHub Action 工作流的 CI/CD 管道。

主要相似点和差异点

GitHub Actions 和 GitLab CI/CD 都用于生成管道来自动构建、测试和部署您的代码。两者都有相似之处,包括:

  • CI/CD 功能可以直接访问存储在项目仓库中的代码。
  • 管道配置使用 YAML 编写并存储在项目仓库中。
  • 管道是可配置的,可以在不同阶段运行。
  • 每个作业可以使用不同的容器镜像。

此外,两者之间还有一些重要差异:

  • GitHub 有一个市场可以下载第三方 action,这可能需要额外的支持或许可证。
  • GitLab Self-Managed 支持水平和垂直扩展,而 GitHub Enterprise Server 只支持垂直扩展。
  • GitLab 内部维护和支持所有功能,一些第三方集成可以通过模板访问。
  • GitLab 提供内置的容器注册表。
  • GitLab 具有原生的 Kubernetes 部署支持。
  • GitLab 提供细粒度的安全策略。

功能和概念比较

许多 GitHub 功能和概念在 GitLab 中都有等效的功能,提供相同的功能。

配置文件

GitHub Actions 可以使用 workflow YAML 文件 进行配置。GitLab CI/CD 默认使用 .gitlab-ci.yml YAML 文件。

例如,在 GitHub Actions 的 workflow 文件中:

on: [push]
jobs:
  hello:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello World"

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

stages:
  - hello

hello:
  stage: hello
  script:
    - echo "Hello World"

GitHub Actions workflow 语法

GitHub Actions 配置在 workflow YAML 文件中使用特定关键字定义。GitLab CI/CD 具有类似的功能,通常也使用 YAML 关键字配置。

GitHub GitLab 说明
env variables env 定义在工作流、作业或步骤中设置的变量。GitLab 使用 variables 在全局或作业级别定义 CI/CD 变量。变量也可以在 UI 中添加。
jobs stages jobs 将在工作流中运行的所有作业分组在一起。GitLab 使用 stages 将作业分组。
on 不适用 on 定义工作流的触发时间。GitLab 与 Git 紧密集成,因此不需要 SCM 轮询选项来配置触发器,但如果需要,可以按作业配置。
run 不适用 在作业中执行的命令。GitLab 在 script 关键字下使用 YAML 数组,每个命令一个条目。
runs-on tags runs-on 定义作业必须运行的 GitHub runner。GitLab 使用 tags 来选择 runner。
steps script steps 将在作业中运行的所有步骤分组在一起。GitLab 使用 script 将作业中运行的所有命令分组。
uses include uses 定义要添加到 step 的 GitHub Action。GitLab 使用 include 将来自其他文件的配置添加到作业中。

常见配置

本节介绍常用的 CI/CD 配置,展示如何从 GitHub Actions 转换为 GitLab CI/CD。

GitHub Action workflows 在发生某些事件(例如推送新提交)时生成自动化的 CI/CD 作业。GitHub Action workflow 是一个位于仓库根目录 .github/workflows 目录中的 YAML 文件。GitLab 的等效文件是 .gitlab-ci.yml 配置文件,它也位于仓库的根目录。

作业

作业是一组按特定顺序运行的命令,用于实现特定结果,例如构建容器或部署到生产环境。

例如,这个 GitHub Actions workflow 构建一个容器然后将其部署到生产环境。作业按顺序运行,因为 deploy 作业依赖于 build 作业:

on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    container: golang:alpine
    steps:
      - run: apk update
      - run: go build -o bin/hello
      - uses: actions/upload-artifact@v3
        with:
          name: hello
          path: bin/hello
          retention-days: 7
  deploy:
    if: contains( github.ref, 'staging')
    runs-on: ubuntu-latest
    container: golang:alpine
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: hello
      - run: echo "Deploying to Staging"
      - run: scp bin/hello remoteuser@remotehost:/remote/directory

此示例:

  • 使用 golang:alpine 容器镜像。
  • 运行一个用于构建代码的作业。
    • 将构建的可执行文件存储为 artifact。
  • 运行第二个作业部署到 staging,它还:
    • 要求构建作业成功后才能运行。
    • 要求提交目标分支为 staging
    • 使用构建的可执行文件 artifact。

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

default:
  image: golang:alpine

stages:
  - build
  - deploy

build-job:
  stage: build
  script:
    - apk update
    - go build -o bin/hello
  artifacts:
    paths:
      - bin/hello
    expire_in: 1 week

deploy-job:
  stage: deploy
  script:
    - echo "Deploying to Staging"
    - scp bin/hello remoteuser@remotehost:/remote/directory
  rules:
    - if: $CI_COMMIT_BRANCH == 'staging'
并行

在 GitHub 和 GitLab 中,作业默认并行运行。

例如,在 GitHub Actions workflow 文件中:

on: [push]
jobs:
  python-version:
    runs-on: ubuntu-latest
    container: python:latest
    steps:
      - run: python --version
  java-version:
    if: contains( github.ref, 'staging')
    runs-on: ubuntu-latest
    container: openjdk:latest
    steps:
      - run: java -version

此示例使用不同的容器镜像并行运行 Python 作业和 Java 作业。Java 作业仅在 staging 分支更改时运行。

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

python-version:
  image: python:latest
  script:
    - python --version

java-version:
  image: openjdk:latest
  rules:
    - if: $CI_COMMIT_BRANCH == 'staging'
  script:
    - java -version

在这种情况下,不需要额外配置来使作业并行运行。作业默认并行运行,每个作业在不同的 runner 上运行(假设有足够的 runner 运行所有作业)。Java 作业设置为仅在 staging 分支更改时运行。

矩阵

在 GitLab 和 GitHub 中,您都可以使用矩阵在单个管道中并行多次运行作业,但每个作业实例使用不同的变量值。

例如,在 GitHub Actions workflow 文件中:

on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Building $PLATFORM for $ARCH"
    strategy:
      matrix:
        platform: [linux, mac, windows]
        arch: [x64, x86]
  test:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Testing $PLATFORM for $ARCH"
    strategy:
      matrix:
        platform: [linux, mac, windows]
        arch: [x64, x86]
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying $PLATFORM for $ARCH"
    strategy:
      matrix:
        platform: [linux, mac, windows]
        arch: [x64, x86]

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

stages:
  - build
  - test
  - deploy

.parallel-hidden-job:
  parallel:
    matrix:
      - PLATFORM: [linux, mac, windows]
        ARCH: [x64, x86]

build-job:
  extends: .parallel-hidden-job
  stage: build
  script:
    - echo "Building $PLATFORM for $ARCH"

test-job:
  extends: .parallel-hidden-job
  stage: test
  script:
    - echo "Testing $PLATFORM for $ARCH"

deploy-job:
  extends: .parallel-hidden-job
  stage: deploy
  script:
    - echo "Deploying $PLATFORM for $ARCH"

触发器

GitHub Actions 要求您为 workflow 添加触发器。GitLab 与 Git 紧密集成,因此不需要 SCM 轮询选项来配置触发器,但如果需要,可以按作业配置。

示例 GitHub Actions 配置:

on:
  push:
    branches:
      - main

等效的 GitLab CI/CD 配置将是:

rules:
  - if: '$CI_COMMIT_BRANCH == main'

管道也可以 使用 Cron 语法进行调度

容器镜像

使用 GitLab,您可以通过使用 image 关键字 在独立的 Docker 容器中运行您的 CI/CD 作业

例如,在 GitHub Actions workflow 文件中:

jobs:
  update:
    runs-on: ubuntu-latest
    container: alpine:latest
    steps:
      - run: apk update

在此示例中,apk update 命令在 alpine:latest 容器中运行。

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

update-job:
  image: alpine:latest
  script:
    - apk update

GitLab 为每个项目提供一个 容器注册表 用于托管容器镜像。容器镜像可以直接从 GitLab CI/CD 管道构建和存储。

例如:

stages:
  - build

build-image:
  stage: build
  variables:
    IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $IMAGE .
    - docker push $IMAGE

变量

在 GitLab 中,我们使用 variables 关键字在运行时定义不同的 CI/CD 变量。当您需要在管道中重用配置数据时,请使用变量。您可以在全局或按作业定义变量。

例如,在 GitHub Actions workflow 文件中:

env:
  NAME: "fern"

jobs:
  english:
    runs-on: ubuntu-latest
    env:
      Greeting: "hello"
    steps:
      - run: echo "$GREETING $NAME"
  spanish:
    runs-on: ubuntu-latest
    env:
      Greeting: "hola"
    steps:
      - run: echo "$GREETING $NAME"

在此示例中,变量为作业提供不同的输出。

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

default:
  image: ubuntu-latest

variables:
  NAME: "fern"

english:
  variables:
    GREETING: "hello"
  script:
    - echo "$GREETING $NAME"

spanish:
  variables:
    GREETING: "hola"
  script:
    - echo "$GREETING $NAME"

变量也可以通过 GitLab UI 在 CI/CD 设置下设置,您可以在其中 保护屏蔽 变量。屏蔽的变量在作业日志中隐藏,而受保护的变量只能在受保护分支或标签的管道中访问。

例如,在 GitHub Actions workflow 文件中:

jobs:
  login:
    runs-on: ubuntu-latest
    env:
      AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }}
    steps:
      - run: my-login-script.sh "$AWS_ACCESS_KEY"

如果 AWS_ACCESS_KEY 变量在 GitLab 项目设置中定义,等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

login:
  script:
    - my-login-script.sh $AWS_ACCESS_KEY

此外,GitHub ActionsGitLab CI/CD 提供内置变量,其中包含与管道和仓库相关的数据。

条件语句

当新管道启动时,GitLab 会检查管道配置以确定哪些作业应该在该管道中运行。您可以使用 rules 关键字 根据变量状态或管道类型等条件配置作业运行。

例如,在 GitHub Actions workflow 文件中:

jobs:
  deploy_staging:
    if: contains( github.ref, 'staging')
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy to staging server"

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

deploy_staging:
  stage: deploy
  script:
    - echo "Deploy to staging server"
  rules:
    - if: '$CI_COMMIT_BRANCH == staging'

Runners

Runners 是执行作业的服务。如果您使用 GitLab.com,可以使用 实例 runner 队列 来运行作业,而无需配置自己的 self-managed runner。

关于 runner 的一些关键细节:

  • Runner 可以 配置 为在实例间共享、在组间共享,或专用于单个项目。
  • 您可以使用 tags 关键字 进行更精细的控制,并将 runner 与特定作业关联。例如,您可以为需要专用、更强大或特定硬件的作业使用标签。
  • GitLab 具有 runner 自动扩展功能。使用自动扩展仅在需要时配置 runner,并在不需要时缩减规模。

例如,在 GitHub Actions workflow 文件中:

linux_job:
  runs-on: ubuntu-latest
  steps:
    - run: echo "Hello, $USER"

windows_job:
  runs-on: windows-latest
  steps:
    - run: echo "Hello, %USERNAME%"

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

linux_job:
  stage: build
  tags:
    - linux-runners
  script:
    - echo "Hello, $USER"

windows_job:
  stage: build
  tags:
    - windows-runners
  script:
    - echo "Hello, %USERNAME%"

Artifacts

在 GitLab 中,任何作业都可以使用 artifacts 关键字 定义作业完成时要存储的一组 artifact。Artifacts 是可以在后续作业中使用的文件。

例如,在 GitHub Actions workflow 文件中:

on: [push]
jobs:
  generate_cat:
    steps:
      - run: touch cat.txt
      - run: echo "meow" > cat.txt
      - uses: actions/upload-artifact@v3
        with:
          name: cat
          path: cat.txt
          retention-days: 7
  use_cat:
    needs: [generate_cat]
    steps:
      - uses: actions/download-artifact@v3
        with:
          name: cat
      - run: cat cat.txt

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

stage:
  - generate
  - use

generate_cat:
  stage: generate
  script:
    - touch cat.txt
    - echo "meow" > cat.txt
  artifacts:
    paths:
      - cat.txt
    expire_in: 1 week

use_cat:
  stage: use
  script:
    - cat cat.txt

缓存

当作业下载一个或多个文件并保存以便将来更快访问时,会创建一个 cache。使用相同缓存的后续作业无需再次下载文件,因此执行速度更快。缓存存储在 runner 上,如果启用了 分布式缓存,则会上传到 S3。

例如,在 GitHub Actions workflow 文件中:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - run: echo "This job uses a cache."
    - uses: actions/cache@v3
      with:
        path: binaries/
        key: binaries-cache-$CI_COMMIT_REF_SLUG

等效的 GitLab CI/CD .gitlab-ci.yml 文件将是:

cache-job:
  script:
    - echo "This job uses a cache."
  cache:
    key: binaries-cache-$CI_COMMIT_REF_SLUG
    paths:
      - binaries/

模板

在 GitHub 中,Action 是一组需要频繁重复执行的复杂任务,并保存起来以便重用而无需重新定义 CI/CD 管道。在 GitLab 中,与 action 等效的是 include 关键字,它允许您 添加来自其他文件的 CI/CD 管道,包括 GitLab 内置的模板文件。

示例 GitHub Actions 配置:

- uses: hashicorp/[email protected]

等效的 GitLab CI/CD 配置将是:

include:
  - template: Terraform.gitlab-ci.yml

在这些示例中,setup-terraform GitHub action 和 Terraform.gitlab-ci.yml GitLab 模板不是完全匹配的。这两个示例只是为了展示如何重用复杂配置。

安全扫描功能

GitLab 提供了各种开箱即用的 安全扫描器 来检测 SLDC 所有部分的漏洞。您可以通过使用模板将这些功能添加到您的 GitLab CI/CD 管道中。

例如,要将 SAST 扫描添加到您的管道中,请将以下内容添加到您的 .gitlab-ci.yml

include:
  - template: Jobs/SAST.gitlab-ci.yml

您可以使用 CI/CD 变量自定义安全扫描器的行为,例如使用 SAST 扫描器

密钥管理

特权信息,通常称为 “secrets”,是您在 CI/CD 工作流中需要的敏感信息或凭据。您可能使用 secrets 来解锁受保护资源或工具、应用程序、容器和云原生环境中的敏感信息。

对于 GitLab 中的密钥管理,您可以使用外部服务的支持集成之一。这些服务安全地将 secrets 存储在您的 GitLab 项目之外,但您必须订阅该服务:

GitLab 还支持 OIDC 身份验证 用于支持 OIDC 的其他第三方服务。

此外,您可以通过将凭据存储在 CI/CD 变量中来使其对作业可用,但以明文存储的 secrets 容易意外暴露。您应该始终将敏感信息存储在 屏蔽受保护 的变量中,这可以减轻一些风险。

此外,切勿将 secrets 作为变量存储在您的 .gitlab-ci.yml 文件中,该文件对项目所有用户可见。将敏感信息存储在变量中应仅在 项目、组或实例设置 中完成。

查看 安全指南 以提高您的 CI/CD 变量安全性。

规划和执行迁移

以下推荐步骤列表是在观察到能够快速完成此迁移的组织后创建的。

创建迁移计划

在开始迁移之前,您应该创建一个 迁移计划 来为迁移做准备。

先决条件

在进行任何迁移工作之前,您应该首先:

  1. 熟悉 GitLab。
  2. 设置和配置 GitLab。
  3. 测试您的 GitLab 实例。
    • 确保 runners 可用,要么使用共享的 GitLab.com runners,要么安装新的 runners。

迁移步骤

  1. 将项目从 GitHub 迁移到 GitLab:
  2. 在每个项目中创建一个 .gitlab-ci.yml
  3. 将 GitHub Actions 作业迁移到 GitLab CI/CD 作业,并配置它们以直接在合并请求中显示结果。
  4. 通过使用 云部署模板环境GitLab agent for Kubernetes 来迁移部署作业。
  5. 检查是否有任何 CI/CD 配置可以在不同项目间重用,然后创建和共享 CI/CD 模板
  6. 查看 管道效率文档 了解如何使您的 GitLab CI/CD 管道更快、更高效。

其他资源

如果您有此处未回答的问题,GitLab 社区论坛 可能是一个很好的资源。