GitLab CI
포털은 GitHub Action을 미러링하는 include 가능한 GitLab CI 템플릿을 제공합니다 — 스캔을 트리거하고 최종 상태까지 폴링한 다음 빌드 게이트 를 평가합니다. 템플릿은 단일 잡이며, 어떤 필드든 확장하거나 오버라이드할 수 있습니다.
현재 릴리스의 포털 PR-코멘트 통합은 GitHub 전용입니다. templates/gitlab-ci.yml의 MR-코멘트 잡은 요청을 스테이징하지만, 백엔드 services/sca_comment.py는 api.github.com 호출만 알고 있습니다 — GitLab repo_full_name으로 호출하면 404가 반환됩니다. GitLab Notes API 클라이언트가 도착할 때까지 GitLab 측에서는 빌드 게이트의 종료 코드를 사용하세요.
GitLab CI/CD를 사용하는 GitLab 프로젝트를 운영하는 엔지니어. 포털용 API Key가 필요합니다 — API keys 참고.
빠른 시작
# .gitlab-ci.yml
include:
- remote: 'https://raw.githubusercontent.com/trustedoss/trusca/v0.10.0/templates/gitlab-ci.yml'
variables:
TRUSTEDOSS_API_URL: 'https://trustedoss.example.com'
TRUSTEDOSS_PROJECT_ID: '01H7XYZ…'
# TRUSTEDOSS_API_KEY는 masked CI/CD 변수입니다 — 여기에 절대 적지 마세요.
베이스 템플릿은 hidden입니다 — 직접 만든 잡에서 extend해 materialize해야 하며, 베이스를 extend하지 않는 파이프라인은 SCA를 자동 트리거하지 않습니다. 다음과 같은 잡을 추가하세요.
sca:
extends: .trustedoss-sca
셋업
1. API Key 생성
포털에서 Project Settings → CI/CD → API keys → New API key. 허용 동작 — scan:trigger, scan:read, report:download. API keys 참고.
2. masked CI/CD 변수로 Key 저장
GitLab 프로젝트에서 Settings → CI/CD → Variables → Add variable.
- Key —
TRUSTEDOSS_API_KEY - Value — 전체 Key(
tos_<prefix>_<secret>) - Type —
Variable - Flags — Masked(yes), Protected(
main한정 권장)
masked 플래그는 잡 로그에 Key가 그대로 노출되는 것을 막습니다.
3. URL과 프로젝트 ID 설정
TRUSTEDOSS_API_URL과 TRUSTEDOSS_PROJECT_ID는 다음 중 하나에 둘 수 있습니다.
.gitlab-ci.yml의variables:(읽기 권한자에게 보임).- 또는 CI/CD 변수(여러 환경을 운영한다면 더 나은 선택).
어느 쪽이든 TRUSTEDOSS_API_KEY만 masked여야 합니다.
변수
| 변수 | 필수 | 기본값 | 설명 |
|---|---|---|---|
TRUSTEDOSS_API_URL | yes | — | 포털 base URL. |
TRUSTEDOSS_API_KEY | yes | — | API Key(masked CI/CD 변수). |
TRUSTEDOSS_PROJECT_ID | yes | — | 프로젝트 UUID. |
TRUSTEDOSS_SCAN_KIND | no | source | source 또는 container. |
TRUSTEDOSS_FAIL_ON_GATE | no | true | true이면 게이트 실패 시 잡이 1로 종료. |
TRUSTEDOSS_POLL_TIMEOUT | no | 1800 | 최종 상태까지 기다리는 최대 초. |
TRUSTEDOSS_POLL_INTERVAL | no | 30 | 폴링 간격(초). |
TRUSTEDOSS_POST_MR_COMMENT | no | true | 향후 GitLab Notes API 통합용 예약. 현재 릴리스에서는 요청이 스테이징되지만 백엔드가 전송할 수 없습니다 — 위 경고 참고. |
레시피
Advisory 모드
include:
- remote: 'https://raw.githubusercontent.com/trustedoss/trusca/v0.10.0/templates/gitlab-ci.yml'
variables:
TRUSTEDOSS_API_URL: 'https://trustedoss.example.com'
TRUSTEDOSS_PROJECT_ID: '01H7XYZ…'
TRUSTEDOSS_FAIL_ON_GATE: 'false'
잡은 green을 유지하고 MR 노트는 그대로 게시됩니다.
보호된 브랜치에서만 실행
include한 잡의 rules를 오버라이드:
include:
- remote: 'https://raw.githubusercontent.com/trustedoss/trusca/v0.10.0/templates/gitlab-ci.yml'
.trustedoss-sca:
rules:
- if: '$CI_COMMIT_REF_PROTECTED == "true"'
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
컨테이너 스캔을 별도 잡으로
include:
- remote: 'https://raw.githubusercontent.com/trustedoss/trusca/v0.10.0/templates/gitlab-ci.yml'
trustedoss:scan-container:
extends: .trustedoss-sca
variables:
TRUSTEDOSS_SCAN_KIND: 'container'
태그 핀
재현 가능한 파이프라인을 위해 include URL을 main이 아닌 릴리스 태그(v0.10.0)에 핀하세요.
템플릿 해부 (고급)
러너가 include를 위해 GitHub에 도달하지 못하는 등의 이유로 잡을 복사·인라인해야 한다면 표준 형태는 다음과 같습니다.
.trustedoss-sca:
image: alpine:3.20
stage: test
before_script:
- apk add --no-cache curl jq bash ca-certificates
script:
- bash -c '
set -euo pipefail;
SCAN_ID=$(curl -fsS -X POST
-H "Authorization: Bearer ${TRUSTEDOSS_API_KEY}"
-H "Content-Type: application/json"
-d "{\"kind\": \"${TRUSTEDOSS_SCAN_KIND:-source}\"}"
"${TRUSTEDOSS_API_URL}/v1/projects/${TRUSTEDOSS_PROJECT_ID}/scans"
| jq -r .id);
echo "scan_id=$SCAN_ID";
# 최종 상태까지 폴링 …
# 게이트 평가, MR 노트 게시, 0/1 종료
'
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
전체 표준 버전은 templates/gitlab-ci.yml에 있습니다. fork 전에 읽어 보세요 — 다시 구현하고 싶지 않은 엣지 케이스(폴링 중 네트워크 단절, masked-token 회전)를 다룹니다.
ref가 보존 키가 되는 방식
템플 릿은 파이프라인의 ref를 스캔 metadata로 전달합니다 — 브랜치 파이프라인에서는 CI_COMMIT_REF_NAME(브랜치), merge_request_event에서는 MR IID(refs/merge-requests/<iid>/head). 포털은 그 ref를 정규화하고(refs/heads/main → main, refs/merge-requests/7/head → mr-7) (project, 정규화된 ref)를 보존 키로 사용합니다 — 키별 최신 성공 스캔이 live로 남고 이전 것을 supersede합니다.
설정할 것은 없습니다 — 브랜치·MR에서 템플릿을 실행하면 브랜치별·MR별 그룹화가 올바르게 동작합니다. 스캔을 영구 보존하려면(태그 릴리스용) metadata.release 라벨과 함께 트리거하십시오. 전체 모델과 release 면제는 스캔 보존 페이지에서 다룹니다.
브랜치 / 머지 보호
모든 MR에 SCA를 강제하려면:
- Settings → Repository → Protected branches —
main을 보호. - Settings → Merge requests → Merge checks — "Pipelines must succeed"를 켜기.
SCA 잡(.trustedoss-sca를 extend한 잡)이 실패하는 MR은 머지할 수 없습니다.