GitHub Actions에서 마이그레이션하기
GitHub Actions에서 마이그레이션하기 (Migrate from GitHub Actions)
GitHub Actions에서 GitLab CI/CD로 마이그레이션한다면, GitHub Action 워크플로우를 복제하고 개선하는 CI/CD 파이프라인을 만들 수 있어요.
직접 할 수도 있고, GitHub Actions to GitLab CI/CD 에이전트 스킬과 함께 선택한 에이전트를 사용할 수도 있어요.
출처: 문서
본문
주요 유사점과 차이점
GitHub Actions와 GitLab CI/CD는 모두 코드를 빌드·테스트·배포하는 과정을 자동화하는 파이프라인을 생성하는 데 사용돼요. 둘 다 다음과 같은 유사점을 공유해요:
- CI/CD 기능이 프로젝트 저장소에 저장된 코드에 직접 접근해요.
- 파이프라인 구성이 YAML로 작성되어 프로젝트 저장소에 저장돼요.
- 파이프라인을 구성할 수 있고 다른 스테이지에서 실행돼요.
- 잡마다 각각 다른 컨테이너 이미지를 사용할 수 있어요.
추가로 두 플랫폼 사이에는 몇 가지 중요한 차이점이 있어요:
- GitHub에는 타사 actions를 다운로드하는 마켓플레이스가 있는데, 추가 지원이나 라이선스가 필요할 수 있어요.
- 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 워크플로우 문법
GitHub Actions 구성은 특정 키워드를 사용해 workflow YAML 파일로 정의돼요. GitLab CI/CD도 보통 YAML 키워드로 구성되는 비슷한 기능을 가져요.
| GitHub | GitLab | Explanation |
|---|---|---|
env |
variables |
env는 워크플로우, 잡, 또는 단계에서 설정된 변수를 정의해요. GitLab은 글로벌 또는 잡 수준에서 CI/CD 변수를 정의하는 데 variables를 사용해요. 변수는 UI에서도 추가할 수 있어요. |
jobs |
stages |
jobs는 워크플로우에서 실행되는 모든 잡을 그룹화해요. GitLab은 잡을 그룹화하는 데 stages를 사용해요. |
on |
해당 없음 | on은 워크플로우가 언제 트리거되는지 정의해요. GitLab은 Git과 밀접하게 통합되어 있어 트리거용 SCM 폴링 옵션이 필요 없지만, 필요하면 잡별로 구성할 수 있어요. |
run |
해당 없음 | 잡에서 실행할 명령어예요. GitLab은 script 키워드 아래에서 실행할 명령 하나당 항목 하나씩 YAML 배열을 사용해요. |
runs-on |
tags |
runs-on은 잡이 실행되어야 하는 GitHub 러너를 정의해요. GitLab은 tags로 러너를 선택해요. |
steps |
script |
steps는 잡에서 실행되는 모든 단계를 그룹화해요. GitLab은 잡에서 실행되는 모든 명령을 script로 그룹화해요. |
uses |
include |
uses는 step에 추가할 GitHub Action을 정의해요. GitLab은 include로 다른 파일의 구성을 잡에 추가해요. |
일반적인 구성
이 섹션은 일반적으로 사용되는 CI/CD 구성을 다루며, GitHub Actions에서 GitLab CI/CD로 어떻게 변환하는지 보여줘요.
GitHub Action 워크플로우는 새 커밋 push 같은 특정 이벤트가 발생할 때 트리거되는 자동 CI/CD 잡을 생성해요. GitHub Action 워크플로우는 저장소 루트의 .github/workflows 디렉터리에 정의된 YAML 파일이에요. GitLab의 대응물은 저장소 루트 디렉터리에도 있는 .gitlab-ci.yml 설정 파일이에요.
잡 (Jobs)
잡은 특정 결과(예: 컨테이너 빌드 또는 프로덕션 배포)를 달성하기 위해 일련의 순서로 실행되는 명령 집합이에요.
예를 들어 이 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컨테이너 이미지를 사용해요.- 코드를 빌드하는 잡을 실행해요. 빌드 실행 파일을 아티팩트로 저장해요.
staging에 배포하는 두 번째 잡을 실행하는데, 이 잡은 또한:빌드 잡이 먼저 성공해야 실행돼요.대상 브랜치가staging이어야 해요.빌드 실행 파일 아티팩트를 사용해요.
이에 해당하는 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'
병렬 (Parallel)
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
이 경우 잡을 병렬로 실행하기 위한 추가 구성은 필요 없어요. 잡은 기본적으로 병렬로 실행되며, 모든 잡을 처리할 러너가 충분하다면 각자 다른 러너에서 실행돼요. Java 잡은 staging 브랜치가 변경될 때만 실행되도록 설정돼요.
매트릭스 (Matrix)
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"
트리거 (Trigger)
GitHub Actions는 워크플로우에 트리거를 추가해야 해요. GitLab은 Git과 밀접하게 통합되어 있어 트리거용 SCM 폴링 옵션이 필요 없지만, 필요하면 잡별로 구성할 수 있어요.
GitHub Actions 샘플 구성:
on:
push:
branches:
- main
이에 해당하는 GitLab CI/CD 구성:
rules:
- if: '$CI_COMMIT_BRANCH == main'
파이프라인은 Cron 문법으로 예약할 수도 있어요.
컨테이너 이미지
GitLab에서는 image 키워드를 사용해 CI/CD 잡을 별도의 격리된 Docker 컨테이너에서 실행할 수 있어요.
예를 들어 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
변수
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 Actions와 GitLab CI/CD는 파이프라인과 저장소에 관련된 데이터를 담은 내장 변수를 제공해요.
조건부 (Conditionals)
새 파이프라인이 시작되면 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)
러너는 잡을 실행하는 서비스예요. GitLab.com을 사용한다면 자체 self-managed 러너를 프로비저닝하지 않고 인스턴스 러너 플릿을 사용해 잡을 실행할 수 있어요.
러너에 대한 몇 가지 핵심 사항:
- 러너는 인스턴스, 그룹에 걸쳐 공유하거나 단일 프로젝트 전용으로 구성할 수 있어요.
tags키워드를 사용해 더 세밀하게 제어하고 러너를 특정 잡과 연결할 수 있어요. 예를 들어 전용, 더 강력한 또는 특정 하드웨어가 필요한 잡에 태그를 사용할 수 있어요.- GitLab에는 러너 자동 확장(autoscaling)이 있어요. 필요할 때만 러너를 프로비저닝하고 필요하지 않을 때는 축소하도록 자동 확장을 사용하세요.
예를 들어 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 키워드를 사용해 잡 완료 시 저장할 아티팩트 집합을 정의할 수 있어요. 아티팩트는 이후의 잡에서 사용할 수 있는 파일이에요.
예를 들어 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
캐싱
캐시는 잡이 하나 이상의 파일을 다운로드해 나중에 더 빠르게 접근하도록 저장할 때 생성돼요. 같은 캐시를 사용하는 후속 잡은 파일을 다시 다운로드할 필요가 없어 더 빨리 실행돼요. 캐시는 러너에 저장되고 분산 캐시가 활성화되면 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 키워드이며, 이를 사용해 GitLab에 내장된 템플릿 파일을 포함한 다른 파일에서 CI/CD 파이프라인을 추가할 수 있어요.
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은 SDLC의 모든 부분에서 취약점을 감지하는 다양한 보안 스캐너를 기본으로 제공해요. 템플릿을 사용해 이런 기능을 GitLab CI/CD 파이프라인에 추가할 수 있어요.
예를 들어 파이프라인에 SAST 스캐닝을 추가하려면 .gitlab-ci.yml에 다음을 추가하세요:
include:
- template: Jobs/SAST.gitlab-ci.yml
CI/CD 변수로 보안 스캐너의 동작을 사용자 정의할 수 있는데, 예를 들어 SAST 스캐너가 그렇습니다.
시크릿 관리
권한 있는 정보, 흔히 "시크릿"이라 불리는 것은 CI/CD 워크플로우에서 필요한 민감한 정보나 자격 증명이에요. 시크릿을 사용해 도구, 애플리케이션, 컨테이너, 클라우드 네이티브 환경의 보호된 리소스나 민감한 정보를 잠금 해제할 수 있어요.
GitLab의 시크릿 관리는 외부 서비스용 지원 통합 중 하나를 사용할 수 있어요. 이 서비스들은 GitLab 프로젝트 외부에 시크릿을 안전하게 저장하지만, 서비스에 대한 구독이 필요해요.
GitLab은 OIDC를 지원하는 다른 타사 서비스를 위한 OIDC 인증도 지원해요.
추가로 CI/CD 변수에 자격 증명을 저장해 잡에서 사용할 수 있게 할 수 있지만, 일반 텍스트로 저장된 시크릿은 우연히 노출될 위험이 있어요. 민감한 정보는 항상 마스킹되고 보호된 변수에 저장해야 하며, 이렇게 하면 위험의 일부를 완화할 수 있어요.
또한 .gitlab-ci.yml 파일은 프로젝트에 접근 권한이 있는 모든 사용자에게 공개되므로 절대 시크릿을 변수로 저장하지 마세요. 민감한 정보를 변수에 저장하는 것은 프로젝트, 그룹, 또는 인스턴스 설정에서만 해야 해요.
보안 가이드라인을 검토해 CI/CD 변수의 안전성을 개선하세요.
마이그레이션 계획 및 수행
다음 단계는 이 마이그레이션을 계획하고 수행하는 데 도움이 돼요.
마이그레이션 계획 만들기
마이그레이션을 시작하기 전에 마이그레이션 계획을 만들어 준비해야 해요.
전제 조건
마이그레이션 작업을 하기 전에 먼저:
- GitLab에 익숙해지세요.핵심 GitLab CI/CD 기능에 대해 읽으세요.첫 GitLab 파이프라인과 정적 사이트를 빌드·테스트·배포하는 더 복잡한 파이프라인을 만드는 튜토리얼을 따라 하세요.CI/CD YAML 문법 참조를 검토하세요.
- GitLab을 설정하고 구성하세요.
- GitLab 인스턴스를 테스트하세요.공유 GitLab.com 러너를 사용하거나 새 러너를 설치해 러너가 사용 가능한지 확인하세요.
마이그레이션 단계
- GitHub에서 GitLab으로 프로젝트를 마이그레이션하세요:(권장) GitHub Importer를 사용해 외부 SCM 제공자에서 대량 가져오기를 자동화할 수 있어요.URL로 저장소를 가져올 수 있어요.
- 각 프로젝트에
.gitlab-ci.yml을 만드세요. - GitHub Actions 잡을 GitLab CI/CD 잡으로 마이그레이션하고 머지 리퀘스트에 결과가 직접 표시되도록 구성하세요. 이 작업은 제공된 Agent Skill로 자동화할 수 있어요.
- 클라우드 배포 템플릿, 환경, Kubernetes용 GitLab 에이전트를 사용해 배포 잡을 마이그레이션하세요.
- 여러 프로젝트에서 재사용할 수 있는 CI/CD 구성이 있는지 확인하고 CI/CD 컴포넌트를 만들어 공유하세요.
- 파이프라인 효율성 문서를 확인해 GitLab CI/CD 파이프라인을 더 빠르고 효율적으로 만드는 방법을 배우세요.
추가 리소스
더 알아보기
다음으로는 마이그레이션 계획 문서와 GitLab CI/CD 시작하기 튜토리얼을 함께 보면, GitHub 뿐 아니라 다양한 CI 도구에서 체계적으로 옮기는 방법을 익힐 수 있어요. 러너 스코프 문서도 읽으면 러너 배포 계획을 세울 수 있어요.