@safemotionkr/ci-bridge
v0.1.0
Published
GitLab-to-GitHub Actions CI bridge templates, scripts, and project initializer.
Readme
ci-bridge
ci-bridge는 self-hosted GitLab CI를 메인 CI/CD 오케스트레이터로 유지하면서, GitHub Actions를 외부 실행 agent처럼 호출하기 위한 공통 브릿지 프로젝트입니다.
GitLab은 파이프라인 흐름, 승인, 배포 조건을 관리하고 GitHub Actions는 테스트, Docker build, Docker push처럼 무거운 작업을 실행합니다.
전체 구조
GitLab self-hosted project
|
| 1. include templates/github-actions-agent.yml
v
GitLab CI job: github_actions_agent
|
| 2. workflow_dispatch API 호출
v
GitHub mirror repository
|
| 3. GitHub Actions 실행(test, docker-build 등)
v
GitLab CI job polling
|
| 4. success면 GitLab job 성공, 실패/취소/타임아웃이면 GitLab job 실패
v
GitLab pipeline continues or stopsGitLab과 GitHub의 역할 분리
| 영역 | 역할 | | --- | --- | | GitLab CI | 메인 오케스트레이터, 변수/권한 관리, 배포 stage 제어 | | GitHub mirror repo | GitHub Actions workflow 실행 위치 | | GitHub Actions | test, docker-build, docker-push 같은 외부 실행 agent | | ci-bridge | GitLab에서 GitHub Actions를 호출하고 결과를 polling하는 공통 스크립트/템플릿 |
저장소 구조
ci-bridge/
README.md
LICENSE
.gitignore
templates/
github-actions-agent.yml
scripts/
common.sh
trigger-github-action.sh
wait-github-action.sh
examples/
gitlab/
.gitlab-ci.yml
github/
agent.yml
reusable-agent.yml
docs/
setup.md
variables.md
security.md빠른 시작
1. GitHub mirror repo에 workflow 추가
GitHub mirror repo에 아래 파일을 추가합니다.
.github/workflows/agent.yml내용은 이 저장소의 examples/github/agent.yml을 복사해서 사용합니다.
2. GitHub Secrets 설정
Docker push를 사용할 경우 GitHub mirror repo에 다음 Secrets를 설정합니다.
REGISTRY_USERREGISTRY_PASSWORD
테스트만 실행한다면 위 Secrets는 필요하지 않습니다.
3. GitLab Project Variables 설정
GitLab 프로젝트의 Settings → CI/CD → Variables에 다음 변수를 설정합니다.
GITHUB_TOKEN=<GitHub fine-grained PAT>권장 설정:
- Masked: enabled
- Protected: protected branch/tag에서만 사용할 경우 enabled
4. GitLab CI에 템플릿 include
최소 적용 예시는 다음과 같습니다.
stages:
- external_ci
include:
- project: "safemotion/ci-bridge"
ref: "main"
file: "/templates/github-actions-agent.yml"
variables:
CI_BRIDGE_REPO_URL: "https://git.safemotion.kr/safemotion/ci-bridge.git"
CI_BRIDGE_REF: "main"
GITHUB_OWNER: "safemotion-mirror"
GITHUB_REPO: "my-service"
GITHUB_WORKFLOW_FILE: "agent.yml"
GITHUB_REF: "main"
EXTERNAL_CI_TASKS: "test,docker-build"
DOCKER_IMAGE_NAME: "registry.example.com/my-service"
DOCKER_IMAGE_TAG: "$CI_COMMIT_SHORT_SHA"GITHUB_TOKEN은 YAML에 쓰지 말고 GitLab CI/CD Variable로 등록하세요.
npx로 새 프로젝트 자동 세팅
ci-bridge를 npm 패키지로 배포하면 새 프로젝트에서 다음 명령 하나로 인터랙티브 세팅을 시작할 수 있습니다.
npx @safemotionkr/ci-bridge initCLI가 GitHub owner/repo, 실행 task, Docker image, ci-bridge GitLab project 등을 순서대로 물어보고 파일을 생성합니다. 옵션을 미리 넘겨서 non-interactive로도 실행할 수 있습니다.
npx @safemotionkr/ci-bridge init --write \
--github-owner safemotion-mirror \
--github-repo my-service \
--tasks test,docker-build \
--docker-image registry.example.com/my-service \
--ci-bridge-project safemotion/ci-bridge \
--ci-bridge-repo-url https://git.safemotion.kr/safemotion/ci-bridge.git생성되는 파일:
.gitlab-ci.yml
.github/workflows/agent.yml인터랙티브 모드에서는 실제 파일 생성 여부를 묻습니다. Non-interactive 모드에서는 기본이 dry-run이며, 실제 파일을 쓰려면 --write를 붙입니다. 기존 파일이 있으면 안전을 위해 덮어쓰지 않습니다. 기존 파일을 백업하고 교체하려면 --force를 함께 사용합니다.
npx @safemotionkr/ci-bridge init --dry-run --github-owner safemotion-mirror
npx @safemotionkr/ci-bridge init --write --github-owner safemotion-mirror --github-repo my-service자동 생성 후에도 민감정보는 직접 등록해야 합니다.
- GitLab CI/CD Variable:
GITHUB_TOKEN - GitHub Actions Secrets, docker-build 사용 시:
REGISTRY_USER,REGISTRY_PASSWORD
GitLab ci-bridge 저장소 접근 권한
ci-bridge를 GitLab private project로 운영한다면 새 프로젝트가 safemotion/ci-bridge를 읽을 수 있어야 합니다. 접근은 두 단계에서 필요합니다.
- Pipeline 생성 시점: GitLab이
include: project: "safemotion/ci-bridge"의 템플릿 파일을 읽습니다. - Job 실행 시점: Runner가
CI_BRIDGE_REPO_URL을git clone해서scripts/*.sh를 실행합니다.
private project에서는 CI_JOB_TOKEN을 포함한 clone URL을 사용하는 것을 권장합니다.
variables:
CI_BRIDGE_REPO_URL: "https://gitlab-ci-token:${CI_JOB_TOKEN}@git.safemotion.kr/safemotion/ci-bridge.git"
CI_BRIDGE_REF: "main"이 방식을 쓰려면 safemotion/ci-bridge 프로젝트에서 다른 프로젝트의 CI_JOB_TOKEN 접근을 허용해야 합니다. GitLab 설정에서 job token allowlist 또는 inbound job token scope를 확인하세요.
체크리스트:
- 새 프로젝트가
safemotion/ci-bridge의templates/github-actions-agent.yml을 include할 권한이 있는가? - GitLab Runner job이
CI_BRIDGE_REPO_URL을 clone할 권한이 있는가? CI_JOB_TOKEN접근 허용 범위에 새 프로젝트 또는 그룹이 포함되어 있는가?CI_BRIDGE_REF가 실제 존재하는 branch/tag인가?
동작 흐름
GitLab pipeline에서
github_actions_agentjob이 실행됩니다.job은
ci-bridge저장소를 clone합니다.scripts/trigger-github-action.sh가 GitHubworkflow_dispatchAPI를 호출합니다.스크립트는 다음 형식의 고유
run_key를 생성하고github_run_key.txt에 저장합니다.${CI_PROJECT_PATH_SLUG}-${CI_PIPELINE_ID}-${CI_JOB_ID}scripts/wait-github-action.sh가 GitHub workflow runs API를 polling합니다.display_title또는name에서run_key가 포함된 run을 찾습니다.run이
completed가 될 때까지 기다립니다.conclusion=success이면 GitLab job도 성공합니다.failure,cancelled,timed_out,action_required또는 알 수 없는 non-success 결론이면 GitLab job이 실패합니다.
GitLab 변수 설정 방법
프로젝트별로 보통 아래 변수만 바꾸면 됩니다.
GITHUB_OWNER
GITHUB_REPO
GITHUB_WORKFLOW_FILE
GITHUB_REF
EXTERNAL_CI_TASKS
DOCKER_IMAGE_NAME
DOCKER_IMAGE_TAG
GITHUB_TOKEN전체 변수 설명은 docs/variables.md를 확인하세요.
GitHub Secrets 설정 방법
GitHub mirror repo의 Settings → Secrets and variables → Actions에서 설정합니다.
REGISTRY_USER
REGISTRY_PASSWORDDocker build/push를 사용하지 않으면 생략할 수 있습니다.
프로젝트에 적용하는 방법
ci-bridge저장소를 GitLab에 생성합니다.- 각 GitLab 프로젝트에서
templates/github-actions-agent.yml을 include합니다. - 각 GitHub mirror repo에
examples/github/agent.yml을.github/workflows/agent.yml로 복사합니다. - GitLab에는
GITHUB_TOKEN을 CI/CD Variable로 등록합니다. - GitHub에는 registry push용 Secrets를 등록합니다.
- GitLab merge request 또는 branch pipeline을 실행합니다.
실패 시 확인할 것
- GitLab
GITHUB_TOKEN이 설정되어 있고 masked/protected 정책 때문에 누락되지 않았는지 확인합니다. - GitHub token에 대상 repo의 Actions workflow dispatch 권한이 있는지 확인합니다.
GITHUB_OWNER,GITHUB_REPO,GITHUB_WORKFLOW_FILE,GITHUB_REF값이 올바른지 확인합니다.- GitHub workflow 파일이 기본 브랜치에 존재하는지 확인합니다.
- mirror repo에 GitLab commit SHA가 실제로 mirror되어 있는지 확인합니다.
- Docker push 실패 시
REGISTRY_USER,REGISTRY_PASSWORD,DOCKER_IMAGE_NAME,DOCKER_IMAGE_TAG를 확인합니다. - GitLab job log에 출력되는 GitHub Actions run URL을 열어 실패 step을 확인합니다.
보안 권장사항
- GitHub token은 fine-grained PAT를 사용하고 필요한 repository 권한만 부여합니다.
GITHUB_TOKEN은 GitLab Project/Group Variable로 설정하고 YAML에 저장하지 않습니다.- protected branch/tag에서만 실행한다면 Protected variable을 사용합니다.
- 토큰은 Masked variable로 설정합니다.
- GitHub Actions에는 GitLab 고권한 토큰을 넣지 않는 것을 권장합니다.
- Docker registry credential은 GitHub Secrets로 관리합니다.
- GitHub Actions가 GitLab로 callback하는 방식보다 GitLab CI가 GitHub Actions 결과를 polling하는 구조를 기본으로 사용합니다.
더 자세한 내용은 docs/security.md를 확인하세요.
예시
- GitLab CI 예시:
examples/gitlab/.gitlab-ci.yml - GitHub workflow_dispatch 예시:
examples/github/agent.yml - GitHub reusable workflow 예시:
examples/github/reusable-agent.yml
npm Trusted Publishing
npm 배포는 장기 NPM_TOKEN 대신 GitHub Actions OIDC 기반 Trusted Publishing을 권장합니다. 이 저장소에는 다음 workflow가 포함되어 있습니다.
.github/workflows/publish-npm.yml배포 절차:
- npmjs.com에서
@safemotionkr/ci-bridge패키지의 Trusted Publisher를 추가합니다. - Publisher는 GitHub Actions를 선택합니다.
- GitHub organization/user, repository, workflow filename을 정확히 입력합니다.
- Workflow filename:
publish-npm.yml
- Workflow filename:
- GitHub에서 release를 publish하거나 workflow를 수동 실행합니다.
workflow는 id-token: write 권한으로 OIDC 토큰을 사용해 npm에 publish합니다. 따라서 GitHub Secrets에 NPM_TOKEN을 저장하지 않아도 됩니다.
주의: npm Trusted Publishing은 npm에 등록한 GitHub repository와 workflow filename이 실제 값과 정확히 일치해야 합니다. package metadata의 repository.url도 실제 GitHub mirror repository에 맞게 설정하는 것을 권장합니다.
개발/배포 명령
이 저장소는 npm 패키지 검증과 배포를 위해 Makefile을 제공합니다.
make help # 사용 가능한 명령 확인
make test # Node CLI, bash 스크립트, npm 패키지 dry-run 검증
make build # npm 배포용 tarball 생성
make publish-dry-run # npm publish dry-run
make publish # npmjs에 @safemotionkr/ci-bridge 배포
make clean # 생성된 .tgz 삭제make publish는 사전에 npm login으로 safemotionkr 계정에 로그인되어 있고, 패키지 publish 권한이 있어야 합니다.
라이선스
MIT License. 자세한 내용은 LICENSE를 확인하세요.
