Migration von GitHub-Aktionen

GitLab CI/CD und GitHub Actions weisen einige Ähnlichkeiten in der Konfiguration auf, wodurch die Migration zu GitLab CI/CD relativ einfach ist:

  • Workflow-Konfigurationsdateien sind in YAML geschrieben und werden im Repository zusammen mit dem Code gespeichert.

  • Workflows enthalten einen oder mehrere Jobs.

  • Jobs umfassen einen oder mehrere Schritte oder einzelne Befehle.

  • Jobs können entweder auf verwalteten oder selbst gehosteten Rechnern laufen.

Es gibt jedoch auch einige Unterschiede, und dieser Leitfaden wird euch die wichtigsten Unterschiede aufzeigen, damit ihr euren Workflow auf GitLab CI/CD migrieren könnt.

Jobs

Jobs in GitHub Actions sind den Jobs in GitLab CI/CD sehr ähnlich. Beide haben folgende Merkmale:

  • Jobs enthalten eine Reihe von Schritten oder Skripten, die nacheinander ausgeführt werden.

  • Jobs können auf separaten Rechnern oder in separaten Containern ausgeführt werden.

  • Jobs werden standardmäßig parallel ausgeführt, können aber auch für sequentielle Ausführung konfiguriert werden.

  • Jobs können ein Skript oder einen Shell-Befehl ausführen, wobei in GitHub-Aktionen alle Skripte mit dem Schlüssel run angegeben werden. In GitLab CI/CD werden die Skript-Schritte hingegen mit dem script-Schlüssel angegeben.

Im Folgenden findet ihr ein Beispiel für die Syntax der beiden Systeme.

GitHub Actions-Syntax für Jobs

jobs:
  my_job:
    steps:
      - uses: actions/checkout@v3
      - run: echo "Run my script here"

GitLab CI/CD-Syntax für Jobs

my_job:
  variables:
    GIT_CHECKOUT: "true"
  script:
    - echo "Run my script here"

Runners

Runner sind Maschinen, auf denen die Jobs ausgeführt werden. Sowohl GitHub Actions als auch GitLab CI/CD bieten verwaltete und selbst gehostete Varianten von Runners. In GitHub Actions wird der runs-on-Schlüssel verwendet, um Jobs auf verschiedenen Plattformen auszuführen, während dies in GitLab CI/CD mit tags erfolgt.

GitHub Actions-Syntax für Runner

my_job:
  runs-on: ubuntu-latest
  steps:
    - run: echo "Hello Pythonistas!"

GitLab CI/CD-Syntax für Runner

my_job:
  tags:
    - linux
  script:
    - echo "Hello Pythonistas!"

Docker-Images

GitHub Actions-Syntax für Docker-Images

 jobs:
   my_job:
     container: python:3.10

GitLab CI/CD-Syntax für Docker-Images

 my_job:
   image: python:3.10

Syntax für Bedingungen und Ausdrücke

GitHub Actions verwendet das if-Schlüsselwort, um zu verhindern, dass ein Job ausgeführt wird, wenn eine Bedingung nicht erfüllt ist. GitLab CI/CD verwendet rules, um zu bestimmen, ob ein Job unter einer bestimmten Bedingung ausgeführt wird.

Im Folgenden findet ihr ein Beispiel für die Syntax der beiden Systeme.

GitHub-Syntax für Bedingungen und Ausdrücke

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

GitLab-Syntax für Bedingungen und Ausdrücke

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

Neben if bietet GitLab auch noch weitere Regeln wie changes, exists, allow_failure, variables und when.

Siehe auch

Abhängigkeiten zwischen Jobs

Sowohl GitHub Actions als auch GitLab CI/CD ermöglichen euch, Abhängigkeiten für einen Job festzulegen. In beiden Systemen werden Jobs standardmäßig parallel ausgeführt, aber GitLab CI/CD verfügt über ein stages-Konzept, bei dem Jobs einer Stufe gleichzeitig ausgeführt werden, die nächste Stufe aber erst dann beginnt, wenn alle Aufträge der vorherigen Stufe abgeschlossen sind. In GitHub Actions können Abhängigkeiten zwischen Jobs explizit mit dem needs-Schlüssel nachgebildet werden.

Nachfolgend findet ihr ein Beispiel für die Syntax für jedes System. Die Workflows beginnen mit zwei parallel laufenden Jobs mit den Namen unit-test und lint. Wenn diese Jobs abgeschlossen sind, wird ein weiterer Job mit dem Namen deploy-to-stage ausgeführt. Wenn deploy-to-stage abgeschlossen ist, wird schließlich der Auftrag deploy-to-prod ausgeführt.

GitHub Actions-Syntax für Abhängigkeiten zwischen Jobs

jobs:
  unit-test:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Running unit tests... This will take about 60 seconds."
      - run: sleep 60
      - run: echo "Code coverage is 0%"

  lint:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Linting code... This will take about 10 seconds."
      - run: sleep 10
      - run: echo "No lint issues found."

  deploy-to-stage:
    runs-on: ubuntu-latest
    needs: [unit-test,lint]
    steps:
      - run: echo "Deploying application in staging environment..."
      - run: echo "Application successfully deployed to staging."

  deploy-to-prod:
    runs-on: ubuntu-latest
    needs: [deploy-to-stage]
    steps:
      - run: echo "Deploying application in production environment..."
      - run: echo "Application successfully deployed to production."

GitLab CI/CD-Syntax für Abhängigkeiten zwischen Jobs

stages:
  - test
  - stage
  - prod

unit-test:
  stage: test
  script:
    - echo "Running unit tests... This will take about 60 seconds."
    - sleep 60
    - echo "Code coverage is 0%"

lint:
  stage: test
  script:
    - echo "Linting code... This will take about 10 seconds."
    - sleep 10
    - echo "No lint issues found."

deploy-to-stage:
  stage: stage
  script:
    - echo "Deploying application in staging environment..."
    - echo "Application successfully deployed to staging."

deploy-to-prod:
  stage: prod
  script:
    - echo "Deploying application in production environment..."
    - echo "Application successfully deployed to production."

Artefakte

Sowohl GitHub Actions als auch GitLab CI/CD können Dateien und Verzeichnisse, die von einem Job erstellt wurden, als Artefakte hochladen. Diese Artefakte können verwendet werden, um Daten über mehrere Jobs hinweg zu erhalten.

Im Folgenden findet ihr ein Beispiel für die Syntax der beiden Systeme.

GitHub Actions Syntax für Artefakte

- name: Archive code coverage results
  uses: actions/upload-artifact@v3
  with:
    name: code-coverage-report
    path: output/test/code-coverage.html

GitLab CI/CD-Syntax für Artefakte

script:
artifacts:
  paths:
    - output/test/code-coverage.html

Datenbanken und Service-Container

Beide Systeme ermöglichen euch, zusätzliche Container für Datenbanken, Caching oder andere Abhängigkeiten einzubinden.

GitHub Actions verwendet den container-Schlüssel, während in GitLab CI/CD ein Container für den Job mit dem image-Schlüssel angegeben wird. In beiden Systemen werden zusätzliche Service-Container mit dem services-Schlüssel angegeben.

Im Folgenden findet ihr ein Beispiel für die Syntax der beiden Systeme.

GitHub Actions-Syntax für Datenbanken und Service-Container

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      postgres:
        image: postgres
        env:
          POSTGRES_USER: postgres
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: postgres
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: Python
        uses: actions/checkout@v3
        uses: actions/setup-python@v4
        with:
          python-version: '3.10'

      - name: Test with pytest
        run: python -m pytest
        env:
          DATABASE_URL: 'postgres://postgres:postgres@localhost:${{ job.services.postgres.ports[5432] }}/postgres'

GitLab CI/CD-Syntax für Datenbank- und -Service-Container

test:
  variables:
    POSTGRES_PASSWORD: postgres
    POSTGRES_HOST: postgres
    POSTGRES_PORT: 5432
  image: python:latest
  services:
    - postgres
  script:
    - python -m pytest

Zuordnungen

GitHub

GitLab

Konzepte

actions/upload-artifact@v2

artifacts

actions/cache@v2

cache

actions/download-artifact@v2

dependencies

environment

environment

container

image

actions/deploy-pages@main

pages

actions/create-release@v1

release

run

script, after_script, before_script, trigger

hashicorp/vault-action@v2.5.0

secrets

services

services

runs-on

tags

timeout-minutes

timeout

Umgebungsvariablen

${{ github.api_url }}

CI_API_V4_URL

${{ github.workspace }}

CI_BUILDS_DIR

${{ github.ref }}

CI_COMMIT_BRANCH, CI_COMMIT_REF_NAME, CI_COMMIT_REF_SLUG, CI_COMMIT_TAG, CI_MERGE_REQUEST_REF_PATH

${{ github.sha }}

CI_COMMIT_SHA, CI_COMMIT_SHORT_SHA

${{ github.job }}

CI_JOB_ID, CI_JOB_NAME

${{ github.event_name == 'workflow_dispatch' }}

CI_JOB_MANUAL

${{ job.status }}

CI_JOB_STATUS

${{ github.server_url }}/${{ github.repository }}

CI_MERGE_REQUEST_PROJECT_URL

${{ github.token }}

CI_NODE_INDEX

${{ strategy.job-total }}

CI_NODE_TOTAL

${{ github.repository}}/${{ github.workflow }}

CI_PIPELINE_ID

${{ github.workflow }}

CI_PIPELINE_IID

${{ github.event_name }}

CI_PIPELINE_SOURCE

${{ github.actions }}

CI_PIPELINE_TRIGGERED

${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

CI_PIPELINE_URL

${{ github.workspace }}

CI_PROJECT_DIR

${{ github.repository }}

CI_PROJECT_ID CI_PROJECT_PATH_SLUG, CI_PROJECT_PATH, CI_MERGE_REQUEST_PROJECT_ID, CI_MERGE_REQUEST_PROJECT_PATH

${{ github.event.repository.name }}

CI_PROJECT_NAME

${{ github.repository_owner }}

CI_PROJECT_NAMESPACE CI_PROJECT_ROOT_NAMESPACE

${{ github.event.repository.full_name }}

CI_PROJECT_TITLE

${{ github.server_url }}/${{ github.repository }}

CI_PROJECT_URL

${{ github.event.repository.clone_url }}

CI_REPOSITORY_URL

${{ runner.os }}

CI_RUNNER_EXECUTABLE_ARCH

${{ github.server_url }}

CI_SERVER_HOST, CI_SERVER_URL

${{ github.actions }}

CI_SERVER, GITLAB_CI

${{ github.actor }}

GITLAB_USER_EMAIL, GITLAB_USER_ID, GITLAB_USER_LOGIN, GITLAB_USER_NAME

${{ github.event_path }}

TRIGGER_PAYLOAD

${{ github.event.pull_request.assignees }}

CI_MERGE_REQUEST_ASSIGNEES

${{ github.event.pull_request.number }}

CI_MERGE_REQUEST_ID, CI_MERGE_REQUEST_IID

${{ github.event.pull_request.labels }}

CI_MERGE_REQUEST_LABELS

${{ github.event.pull_request.milestone }}

CI_MERGE_REQUEST_MILESTONE

${{ github.event.pull_request.head.ref }}

CI_MERGE_REQUEST_SOURCE_BRANCH_NAME, CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME

${{ github.event.pull_request.head.sha }}

CI_MERGE_REQUEST_SOURCE_BRANCH_SHA, CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA

${{ github.event.pull_request.head.repo.full_name }}

CI_MERGE_REQUEST_SOURCE_BRANCH_SHA, CI_MERGE_REQUEST_SOURCE_PROJECT_PATH

${{ github.event.pull_request.head.repo.url }}

CI_MERGE_REQUEST_SOURCE_PROJECT_URL

${{ github.event.pull_request.base.ref }}

CI_MERGE_REQUEST_TARGET_BRANCH_NAME, CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME

${{ github.event.pull_request.base.sha }}

CI_MERGE_REQUEST_TARGET_BRANCH_SHA, CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA

${{ github.event.pull_request.title }}

CI_MERGE_REQUEST_TITLE

${{ github.event.pull_request.number }}

CI_EXTERNAL_PULL_REQUEST_IID

${{ github.event.pull_request.head.repo.full_name }}

CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY

${{ github.event.pull_request.base.repo.full_name }}

RCI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY