GitLab CI/CD에서 GitHub Actions로 마이그레이션하기
GitLab CI/CD에서 GitHub Actions로 마이그레이션하기
GitHub Actions와 GitLab CI/CD는 구성상 몇 가지 유사점을 공유하기 때문에 GitHub Actions로의 마이그레이션이 비교적 간단할 수 있어요. 이 가이드에서는 두 시스템의 차이점과 마이그레이션 시 유의할 점을 알려드릴게요.
출처: 문서
본문
Introduction
자세한 내용은 Understanding GitHub Actions 문서를 참고하세요.
Key differences
GitLab CI/CD에서 마이그레이션할 때 다음 차이점을 고려하세요.
- GitLab CI/CD는 GitLab UI에서 파이프라인을 만들고 프로젝트에 저장되는 구성 파일을 자동으로 만드는 UI 도구를 제공해요. GitHub Actions는 워크플로우를 정의하기 위해 YAML 파일을 직접 사용해요.
- GitLab CI/CD에서 파이프라인 구성은 하나의 구성 파일(.gitlab-ci.yml)에 저장돼요. GitHub에서는 각 워크플로우가 저장소의
.github/workflows디렉터리에 별도의 YAML 파일로 저장돼요. - GitLab CI/CD는 구성 파일에서
stages를 사용해서 파이프라인 단계를 정의하고, 각 job을 특정 stage와 연결해요. GitHub Actions는 워크플로우당 하나의 job만 가지거나, 각 job이 별도의 명시적 의존성을 가질 수 있어요. - GitLab CI/CD에서 job은 기본적으로 병렬로 실행되고,
stages및needs키워드로 순서가 제어돼요. GitHub Actions에서 job은 기본적으로 병렬로 실행되고,needs키워드로 의존성이 제어돼요. - GitLab CI/CD는 파이프라인을 구성하는 데 사용할 수 있는 다양한 실행기(runners)를 제공해요. GitHub Actions는 GitHub에서 호스팅하는 러너 또는 자체 호스팅 러너에서 실행돼요.
- GitLab CI/CD는
git명령을before_script의 일부로 자동으로 실행하지 않아요. GitHub Actions의 워크플로우 단계는 후속 단계가 저장소 코드와 상호작용할 수 있도록 기본적으로 저장소를 체크아웃하지 않아요. 워크플로우가 저장소 코드에 접근해야 한다면actions/checkout액션을 사용해야 해요.
GitHub workflow files
GitLab CI/CD에서는 파이프라인 구성이 하나의 .gitlab-ci.yml 파일에 저장돼요. 자세한 내용은 GitLab 문서의 GitLab CI/CD Pipelines을 참고하세요.
GitHub에서는 각 워크플로우가 저장소의 .github/workflows 디렉터리에 별도의 파일로 저장돼요. 자세한 내용은 Workflows 문서를 참고하세요.
Jobs and steps
GitLab 파이프라인의 job은 GitHub 워크플로우의 job과 유사해요. 기본적인 GitLab job과 GitHub workflow job을 비교해서 각각이 어떻게 정의되는지 살펴볼게요.
두 시스템 모두에서 job에는 다음 특성이 있어요.
- job은 순차적으로 실행되는 일련의 단계를 포함해요.
- job은 각 job이 원하는 구성을 실행하기 위한 별도의 실행기 또는 컨테이너를 사용해요.
GitLab 파이프라인의 기본 job 정의는 다음과 같아요.
job1:
script:
- echo "This job runs in the default shell"
- echo "This is a second step in the same job"
GitHub 워크플로우의 기본 job 정의는 다음과 같아요.
job1:
steps:
- run: echo "This job runs in the default shell"
- run: echo "This is a second step in the same job"
GitLab CI/CD에서 각 파이프라인 실행기에는 IMAGE, SCRIPT, SHELL 같은 사전 정의된 변수가 있고, 여기에는 실행기의 정보가 저장돼요. GitHub Actions는 runner 컨텍스트를 사용해서 실행기 정보에 접근할 수 있어요. 자세한 내용은 Contexts 및 Variables 문서를 참고하세요.
Script steps
워크플로우 또는 파이프라인의 단계로 스크립트나 셸 명령을 실행할 수 있어요.
GitLab에서 각 스크립트 단계는 script 키 아래에 나열되어 있고 단일 job에서 순차적으로 실행돼요. GitLab에서 스크립트는 before_script, script, after_script에 정의할 수 있고 실행 순서는 before_script → script → after_script예요.
GitHub Actions에서 모든 스크립트는 run 키로 지정돼요. 하나의 run 키 안에서 여러 셸 명령을 그룹화할 수 있고, 각 단계는 워크플로우 파일의 steps 아래에 정의돼요.
GitLab CI/CD에서 스크립트 단계의 문법:
job1:
before_script:
- echo "This step runs before the script steps"
script:
- echo "This step runs in the default shell"
- echo "This step runs in the default shell"
after_script:
- echo "This step runs after the script steps"
GitHub Actions에서 스크립트 단계의 문법:
job1:
steps:
- run: echo "This step runs before the script steps"
- run: |
echo "This step runs in the default shell"
echo "This step runs in the default shell"
- run: echo "This step runs after the script steps"
Outputs
GitLab CI/CD는 dotenv 아티팩트를 사용해서 job 간에 데이터를 공유할 수 있어요. GitHub Actions에서 job은 outputs 키워드를 사용해서 다른 job과 데이터를 공유할 수 있어요. 자세한 내용은 Workflow syntax for GitHub Actions 문서를 참고하세요.
GitLab CI/CD에서 job 출력을 정의하는 방법:
job1:
variables:
MY_VARIABLE: "Hello World"
script:
- echo "job1 completed"
GitHub Actions에서 job 출력을 정의하는 방법:
job1:
outputs:
my_variable: ${{ steps.my_step.outputs.my_variable }}
steps:
- id: my_step
run: echo "my_variable=Hello World" >> "$GITHUB_OUTPUT"
Dependencies between jobs
GitLab CI/CD에서 job 간의 의존성은 needs 키워드로 정의돼요. GitHub Actions에서 job 간의 의존성은 needs 키워드로도 정의돼요. GitLab에서는 needs가 이전 stage의 job을 참조하는 데 사용되고, GitHub Actions에서는 needs가 다른 job을 참조하는 데 사용돼요.
GitLab CI/CD에서 job 의존성을 정의하는 방법:
stages:
- build
- test
build:
stage: build
script:
- echo "Building"
test:
stage: test
needs: ["build"]
script:
- echo "Testing"
GitHub Actions에서 job 의존성을 정의하는 방법:
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: echo "Building"
test:
runs-on: ubuntu-latest
needs: ["build"]
steps:
- run: echo "Testing"
자세한 내용은 Workflow syntax for GitHub Actions 문서를 참고하세요.
Caching
GitLab CI/CD와 GitHub Actions는 모두 구성 파일에서 파일을 수동으로 캐시하는 방법을 제공해요.
GitLab CI/CD에서 캐싱의 문법:
job1:
cache:
paths:
- vendor/bundle
GitHub Actions에서 캐싱의 문법:
- name: Cache
uses: actions/cache@v4
with:
path: vendor/bundle
key: ${{ runner.os }}-${{ hashFiles('**/Gemfile.lock') }}
자세한 내용은 Caching dependencies to speed up workflows 문서를 참고하세요.
Artifacts
GitLab CI/CD와 GitHub Actions는 모두 job이 생성한 파일을 보존하고 후속 job에서 사용할 수 있는 메커니즘을 제공해요.
GitLab CI/CD에서 job 간 아티팩트 공유:
job1:
script:
- echo "Hello World" > math-homework.txt
artifacts:
paths:
- math-homework.txt
GitHub Actions에서 job 간 아티팩트 공유:
job1:
steps:
- run: echo "Hello World" > math-homework.txt
- name: Upload math result for job 1
uses: actions/upload-artifact@v4
with:
name: homework
path: math-homework.txt
자세한 내용은 Workflow artifacts 문서를 참고하세요.
Using variables and secrets
GitLab CI/CD와 GitHub Actions는 모두 구성 파일에서 변수를 설정하고 GitLab 또는 GitHub UI를 사용해서 secret을 만들 수 있어요.
GitLab CI/CD에서 파이프라인 변수 정의:
variables:
MY_VARIABLE: "Hello World"
GitHub Actions에서 워크플로우 변수 정의:
env:
MY_VARIABLE: "Hello World"
자세한 내용은 Variables 및 Using secrets in GitHub Actions 문서를 참고하세요.
Using databases and service containers
두 시스템 모두 데이터베이스, 캐싱 또는 기타 의존성을 위한 추가 컨테이너를 포함시킬 수 있어요.
GitLab CI/CD에서 서비스 컨테이너 정의:
job1:
services:
- postgres:11
variables:
POSTGRES_PASSWORD: ""
POSTGRES_DB: ruby25
script:
- bundle exec rake test
GitHub Actions에서 서비스 컨테이너 정의:
job1:
services:
postgres:
image: postgres:11
env:
POSTGRES_PASSWORD: ""
POSTGRES_DB: ruby25
ports:
- 5432:5432
# Add a health check
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- run: bundle exec rake test
자세한 내용은 Communicating with Docker service containers 문서를 참고하세요.
Complete Example
다음은 실제 세계의 예시예요. 왼쪽은 실제 GitLab Pipeline 정의이고, 오른쪽은 그에 상응하는 GitHub Actions 워크플로우예요.
GitLab Pipeline (유지관리 관리 예시)
stages:
- build
- test
variables:
DATABASE_URL: postgres://postgres@localhost:5432/test
build:
stage: build
services:
- postgres:12.5
before_script:
- bundle install --path vendor/bundle
script:
- bundle exec rake db:create
- bundle exec rake db:migrate
- bundle exec rake build
test:
stage: test
services:
- postgres:12.5
before_script:
- bundle install --path vendor/bundle
script:
- bundle exec rake test
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: Ruby
on:
push:
branches: [ main ]
jobs:
build_and_test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['3.0']
services:
postgres:
image: postgres:12.5
env:
POSTGRES_PASSWORD: ""
POSTGRES_DB: ruby25
ports:
- 5432:5432
# Add a health check
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
env:
DATABASE_URL: postgres://postgres@localhost:5432/ruby25
steps:
- uses: actions/checkout@v6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true
- name: Install dependencies
run: bundle install
- name: Setup database
run: |
bundle exec rake db:create
bundle exec rake db:migrate
- name: Build
run: bundle exec rake build
- name: Test
run: bundle exec rake test