CodeClimate 기반 Code Quality 스캐닝 구성하기
CodeClimate 기반 Code Quality 스캐닝 구성하기 (더 이상 사용하지 않음)
Code Quality에는 Code-Quality.gitlab-ci.yaml이라는 내장 CI/CD 템플릿이 포함되어 있어요. 이 템플릿은 오픈소스 CodeClimate 스캐닝 엔진에 기반한 스캔을 실행합니다. 다만 이 기능은 더 이상 사용하지 않게 되었으니 주의하세요.
출처: 문서
본문
- 티어(Tier): Free, Premium, Ultimate
- 제공 방식(Offering): GitLab.com, GitLab Self-Managed, GitLab Dedicated
이 기능은 GitLab 17.3에서 더 이상 사용하지 않기로 결정되었고 19.0에서 제거될 예정이에요. 대신 지원되는 도구의 결과를 직접 통합하세요. 이 변경은 호환성을 깨는 변경(breaking change)이에요.
CodeClimate 엔진은 다음을 실행해요:
CodeClimate 기반 스캐닝 활성화하기
전제 조건:
- GitLab CI/CD 구성(
.gitlab-ci.yml)에test스테이지가 포함되어 있어야 해요. - 인스턴스 러너를 사용한다면 Code Quality job이 Docker-in-Docker 워크플로로 구성되어야 해요. 이 워크플로를 쓸 때는 리포트가 저장되도록
/builds볼륨이 매핑되어야 합니다. - 프라이빗 러너를 사용한다면 Code Quality 분석을 더 효율적으로 실행하기 위해 권장되는 대체 구성을 사용해야 해요.
- 러너에 생성된 Code Quality 파일을 저장할 충분한 디스크 공간이 있어야 해요. 예를 들어 GitLab 프로젝트에서는 파일이 약 7 GB입니다.
Code Quality를 활성화하려면 다음 중 하나를 하세요:
- Auto DevOps를 활성화 — 여기 Auto Code Quality가 포함돼요.
.gitlab-ci.yml파일에 Code Quality 템플릿을 포함:include: - template: Jobs/Code-Quality.gitlab-ci.yml이제 파이프라인에서 Code Quality가 실행돼요.
GitLab Self-Managed에서 악의적인 행위자가 Code Quality job 정의를 손상시키면 러너 호스트에서 권한 있는 Docker 명령을 실행할 수 있어요. 적절한 접근 제어 정책이 있으면 신뢰할 수 있는 행위자에게만 접근을 허용해서 이 공격 벡터를 완화합니다.
CodeClimate 기반 스캐닝 비활성화하기
$CODE_QUALITY_DISABLED CI/CD 변수가 있으면 code_quality job은 실행되지 않아요. 변수 정의 방법에 대한 자세한 내용은 GitLab CI/CD 변수를 참고하세요.
Code Quality를 비활성화하려면 CODE_QUALITY_DISABLED라는 사용자 지정 CI/CD 변수를 만들어요. 대상은:
CodeClimate 분석 플러그인 구성하기
기본적으로 code_quality job은 CodeClimate을 다음으로 구성해요:
- 특정 플러그인 집합을 사용.
- 해당 플러그인에 기본 구성을 사용.
더 많은 언어를 스캔하려면 플러그인을 더 활성화할 수 있어요. code_quality job이 기본으로 활성화하는 플러그인을 비활성화할 수도 있습니다.
예를 들어 SonarJava 분석기를 사용하려면:
- 리포지토리 루트에
.codeclimate.yml이라는 파일을 추가해요. - 리포지토리 루트의
.codeclimate.yml파일에 플러그인의 활성화 코드를 추가해요:version: "2" plugins: sonar-java: enabled: true
이렇게 하면 프로젝트에 포함된 기본 .codeclimate.yml의 plugins: 섹션에 SonarJava가 추가됩니다.
plugins: 섹션 변경은 기본 .codeclimate.yml의 exclude_patterns 섹션에는 영향을 주지 않아요. 파일과 폴더 제외에 대한 자세한 내용은 Code Climate 문서를 참고하세요.
스캔 job 설정 커스터마이즈하기
GitLab CI/CD YAML에서 CI/CD 변수를 설정해서 code_quality 스캔 job의 동작을 바꿀 수 있어요.
Code Quality job을 구성하려면:
- 템플릿을 포함한 뒤, Code Quality job과 같은 이름의 job을 선언해요.
- job의 stanza에 추가 키를 지정해요.
예시는 HTML 형식으로 출력 다운로드를 참고하세요.
사용 가능한 CI/CD 변수
사용 가능한 CI/CD 변수를 정의하면 Code Quality를 커스터마이즈할 수 있어요:
| CI/CD 변수 | 설명 |
|---|---|
CODECLIMATE_DEBUG |
Code Climate 디버그 모드를 활성화하려면 설정. |
CODECLIMATE_DEV |
CLI가 알지 못하는 엔진을 실행할 수 있는 --dev 모드를 활성화하려면 설정. |
CODECLIMATE_PREFIX |
CodeClimate 엔진의 모든 docker pull 명령에 사용할 접두사를 설정. 오프라인 스캐닝에 이 변수를 사용하세요. 자세한 내용은 프라이빗 컨테이너 이미지 레지스트리 사용을 참고하세요. |
CODECLIMATE_REGISTRY_USERNAME |
CODECLIMATE_PREFIX에서 파싱한 레지스트리 도메인의 사용자 이름을 지정하려면 설정. |
CODECLIMATE_REGISTRY_PASSWORD |
CODECLIMATE_PREFIX에서 파싱한 레지스트리 도메인의 비밀번호를 지정하려면 설정. |
CODE_QUALITY_DISABLED |
Code Quality job이 실행되지 않게 방지. |
CODE_QUALITY_IMAGE |
전체 접두사 이미지 이름으로 설정. 이미지는 job 환경에서 접근 가능해야 해요. |
ENGINE_MEMORY_LIMIT_BYTES |
엔진의 메모리 한도를 설정. 기본값: 1,024,000,000 bytes. |
REPORT_STDOUT |
일반 리포트 파일 대신 STDOUT으로 리포트를 출력하려면 설정. |
REPORT_FORMAT |
생성되는 리포트 파일의 형식을 제어하려면 설정. json 또는 html. |
SOURCE_CODE |
스캔할 소스 코드 경로. 복제된 소스가 저장된 디렉터리의 절대 경로여야 해요. |
TIMEOUT_SECONDS |
codeclimate analyze 명령의 엔진 컨테이너별 사용자 지정 타임아웃. 기본값: 900초 (15분). |
출력
Code Quality는 발견된 문제 상세를 담은 리포트를 출력해요. 이 리포트의 내용은 내부적으로 처리되고 결과가 UI에 표시됩니다. 리포트는 code_quality job의 job 아티팩트로도 출력되며 이름은 gl-code-quality-report.json이에요. 선택적으로 리포트를 HTML 형식으로도 출력할 수 있어요. 예를 들어 HTML 형식 파일을 GitLab Pages에 게시하면 더 쉽게 검토할 수 있습니다.
JSON 및 HTML 형식으로 출력하기
Code Quality 리포트를 JSON과 HTML 형식으로 출력하려면 추가 job을 만들어요. 이를 위해서는 Code Quality를 파일 형식마다 한 번씩, 두 번 실행해야 해요.
Code Quality 리포트를 HTML 형식으로 출력하려면 extends: code_quality를 사용해 템플릿에 다른 job을 추가해요:
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
code_quality_html:
extends: code_quality
variables:
REPORT_FORMAT: html
artifacts:
paths: [gl-code-quality-report.html]
JSON과 HTML 파일 모두 job 아티팩트로 출력돼요. HTML 파일은 artifacts.zip job 아티팩트에 포함됩니다.
HTML 형식만 출력하기
Code Quality 리포트를 HTML 형식으로만 다운로드하려면 REPORT_FORMAT을 html로 설정해서 code_quality job의 기본 정의를 재정의해요.
이 경우 JSON 형식 파일이 생성되지 않으므로, Code Quality 결과가 MR 위젯, 파이프라인 리포트, 변경 뷰에는 표시되지 않아요.
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
code_quality:
variables:
REPORT_FORMAT: html
artifacts:
paths: [gl-code-quality-report.html]
HTML 파일은 job 아티팩트로 출력돼요.
MR 파이프라인에서 Code Quality 사용하기
기본 Code Quality 구성은 code_quality job이 MR 파이프라인에서 실행되는 것을 허용하지 않아요.
Code Quality가 MR 파이프라인에서 실행되게 하려면 code quality rules 또는 workflow: rules를 현재 rules와 일치하도록 재정의하세요.
예를 들어:
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
code_quality:
rules:
- if: $CODE_QUALITY_DISABLED
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event" # Run code quality job in merge request pipelines
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run code quality job in pipelines on the default branch (but not in other branch pipelines)
- if: $CI_COMMIT_TAG # Run code quality job in pipelines for tags
CodeClimate 이미지 다운로드 방식 변경하기
CodeClimate 엔진은 각 플러그인을 실행할 컨테이너 이미지를 다운로드해요. 기본적으로 이미지는 Docker Hub에서 다운로드됩니다. 성능을 개선하거나, Docker Hub 속도 제한을 우회하거나, 프라이빗 레지스트리를 사용하기 위해 이미지 소스를 변경할 수 있어요.
Dependency Proxy로 이미지 다운로드하기
Dependency Proxy를 사용해 의존성 다운로드 시간을 줄일 수 있어요.
전제 조건:
- 프로젝트의 그룹에 Dependency Proxy가 활성화되어 있어야 해요.
Dependency Proxy를 참조하려면 .gitlab-ci.yml 파일에서 다음 변수를 구성해요:
CODE_QUALITY_IMAGECODECLIMATE_PREFIXCODECLIMATE_REGISTRY_USERNAMECODECLIMATE_REGISTRY_PASSWORD
예를 들어:
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
code_quality:
variables:
## You must add a trailing slash to `$CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX`.
CODECLIMATE_PREFIX: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/
CODECLIMATE_REGISTRY_USERNAME: $CI_DEPENDENCY_PROXY_USER
CODECLIMATE_REGISTRY_PASSWORD: $CI_DEPENDENCY_PROXY_PASSWORD
인증을 사용해 Docker Hub 사용하기
Code Quality 이미지의 대체 소스로 Docker Hub를 사용할 수 있어요.
전제 조건:
- 프로젝트에 사용자 이름과 비밀번호를 보호된 CI/CD 변수로 추가해요.
DockerHub를 사용하려면 .gitlab-ci.yml 파일에서 다음 변수를 구성해요:
CODECLIMATE_PREFIXCODECLIMATE_REGISTRY_USERNAMECODECLIMATE_REGISTRY_PASSWORD
예시:
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
code_quality:
variables:
CODECLIMATE_PREFIX: "registry-1.docker.io/"
CODECLIMATE_REGISTRY_USERNAME: $DOCKERHUB_USERNAME
CODECLIMATE_REGISTRY_PASSWORD: $DOCKERHUB_PASSWORD
프라이빗 컨테이너 이미지 레지스트리 사용하기
프라이빗 컨테이너 이미지 레지스트리를 사용하면 이미지 다운로드 시간과 외부 의존성을 줄일 수 있어요. 컨테이너 실행 방식이 중첩되어 있으므로, 개별 엔진의 CodeClimate 후속 docker pull 명령에 전달할 레지스트리 접두사를 구성해야 합니다.
다음 변수들이 필요한 모든 이미지 pull을 다룰 수 있어요:
CODE_QUALITY_IMAGE: job 환경에서 접근 가능한 어디든 위치할 수 있는 전체 접두사 이미지 이름. 자신의 복사본을 호스팅하려면 여기서 GitLab 컨테이너 레지스트리를 사용할 수 있어요.CODECLIMATE_PREFIX: 의도한 컨테이너 이미지 레지스트리의 도메인. CodeClimate CLI가 지원하는 구성 옵션이에요. 다음을 지켜야 해요: - 마지막 슬래시(/)를 포함하세요. -https://같은 프로토콜 접두사를 포함하지 마세요.CODECLIMATE_REGISTRY_USERNAME:CODECLIMATE_PREFIX에서 파싱한 레지스트리 도메인의 사용자 이름을 지정하는 선택 변수.CODECLIMATE_REGISTRY_PASSWORD:CODECLIMATE_PREFIX에서 파싱한 레지스트리 도메인의 비밀번호를 지정하는 선택 변수.
include:
- template: Jobs/Code-Quality.gitlab-ci.yml
code_quality:
variables:
CODE_QUALITY_IMAGE: "my-private-registry.local:12345/codequality:0.85.24"
CODECLIMATE_PREFIX: "my-private-registry.local:12345/"
이 예시는 GitLab Code Quality에 특화된 것이에요. 레지스트리 미러로 DinD를 구성하는 일반적인 방법은 Docker-in-Docker 서비스용 레지스트리 미러 활성화를 참고하세요.
필요한 이미지
기본 .codeclimate.yml에는 다음 이미지가 필요해요:
codeclimate/codeclimate-structure:latestcodeclimate/codeclimate-csslint:latestcodeclimate/codeclimate-coffeelint:latestcodeclimate/codeclimate-duplication:latestcodeclimate/codeclimate-eslint:latestcodeclimate/codeclimate-fixme:latestcodeclimate/codeclimate-rubocop:rubocop-0-92
사용자 지정 .codeclimate.yml 구성 파일을 사용한다면 지정한 플러그인을 프라이빗 컨테이너 레지스트리에 추가해야 해요.
Runner 구성 변경하기
CodeClimate은 각 분석 단계에 대해 별도 컨테이너를 실행해요. CodeClimate 기반 스캔이 실행되거나 더 빠르게 실행되도록 Runner 구성을 조정해야 할 수 있어요.
프라이빗 러너 사용하기
프라이빗 러너가 있다면 다음 이유로 Code Quality 성능 향상을 위해 이 구성을 사용해야 해요:
- 권한 모드(privileged mode)를 사용하지 않음.
- Docker-in-Docker를 사용하지 않음.
- 모든 CodeClimate 이미지를 포함한 Docker 이미지가 캐시되어 이후 job에서 다시 가져오지 않음.
이 대체 구성은 소켓 바인딩으로 Runner의 Docker 데몬을 job 환경과 공유해요. 이 구성을 구현하기 전에 제한 사항을 고려하세요.
프라이빗 러너를 사용하려면:
- 새 러너를 등록해요:
$ gitlab-runner register --executor "docker" \ --docker-image="docker:cli" \ --url "https://gitlab.com/" \ --description "cq-sans-dind" \ --docker-volumes "/cache" \ --docker-volumes "/builds:/builds" \ --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \ --registration-token="<project_token>" \ --non-interactive - 선택 사항이지만 권장: 빌드 디렉터리를
/tmp/builds로 설정해서 job 아티팩트가 러너 호스트에서 주기적으로 정리되게 해요. 이 단계를 건너뛰면 기본 빌드 디렉터리(/builds)를 직접 정리해야 해요. 이전 단계의gitlab-runner register에 다음 두 플래그를 추가하면 됩니다.--builds-dir "/tmp/builds" --docker-volumes "/tmp/builds:/tmp/builds" # Use this instead of --docker-volumes "/builds:/builds"결과 구성:[[runners]] name = "cq-sans-dind" url = "https://gitlab.com/" token = "<project_token>" executor = "docker" builds_dir = "/tmp/builds" [runners.docker] tls_verify = false image = "docker:cli" privileged = false disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock", "/tmp/builds:/tmp/builds"] shm_size = 0 [runners.cache] [runners.cache.s3] [runners.cache.gcs] - 템플릿이 만든
code_qualityjob에 두 가지 재정의를 적용해요:include: - template: Jobs/Code-Quality.gitlab-ci.yml code_quality: services: # Shut off Docker-in-Docker tags: - cq-sans-dind # Set this job to only run on our new specialized runner
이제 Code Quality가 표준 Docker 모드로 실행돼요.
프라이빗 러너로 CodeClimate rootless 실행하기
프라이빗 러너를 사용하고 Code Quality 스캔을 rootless Docker 모드로 실행하려면, 제대로 실행되도록 몇 가지 특별한 변경이 필요해요. 소켓 바인딩 변경이 다른 job에 문제를 일으킬 수 있으므로 Code Quality job만 실행하는 전용 러너가 필요할 수 있어요.
rootless 프라이빗 러너를 사용하려면:
- 새 러너를 등록해요:
/run/user/<gitlab-runner-user>/docker.sock을gitlab-runner사용자의 로컬docker.sock경로로 바꾸세요.$ gitlab-runner register --executor "docker" \ --docker-image="docker:cli" \ --url "https://gitlab.com/" \ --description "cq-rootless" \ --tag-list "cq-rootless" \ --locked="false" \ --access-level="not_protected" \ --docker-volumes "/cache" \ --docker-volumes "/tmp/builds:/tmp/builds" \ --docker-volumes "/run/user/<gitlab-runner-user>/docker.sock:/run/user/<gitlab-runner-user>/docker.sock" \ --token "<project_token>" \ --non-interactive \ --builds-dir "/tmp/builds" \ --env "DOCKER_HOST=unix:///run/user/<gitlab-runner-user>/docker.sock" \ --docker-host "unix:///run/user/<gitlab-runner-user>/docker.sock"결과 구성:[[runners]] name = "cq-rootless" url = "https://gitlab.com/" token = "<project_token>" executor = "docker" builds_dir = "/tmp/builds" environment = ["DOCKER_HOST=unix:///run/user/<gitlab-runner-user>/docker.sock"] [runners.docker] tls_verify = false image = "docker:cli" privileged = false disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = ["/cache", "/run/user/<gitlab-runner-user>/docker.sock:/run/user/<gitlab-runner-user>/docker.sock", "/tmp/builds:/tmp/builds"] shm_size = 0 host = "unix:///run/user/<gitlab-runner-user>/docker.sock" [runners.cache] [runners.cache.s3] [runners.cache.gcs] - 템플릿이 만든
code_qualityjob에 다음 재정의를 적용해요:code_quality: services: variables: DOCKER_SOCKET_PATH: /run/user/997/docker.sock tags: - cq-rootless
이제 Code Quality가 표준 Docker 모드와 rootless로 실행돼요.
Code quality로 rootless Podman을 사용해 Docker를 실행하려는 경우에도 같은 구성이 필요해요. /run/user/<gitlab-runner-user>/docker.sock을 시스템의 올바른 podman.sock 경로(예: /run/user/<gitlab-runner-user>/podman/podman.sock)로 바꾸세요.
Kubernetes 또는 OpenShift 러너 구성하기
Code Quality를 사용하려면 컨테이너 안의 Docker(Docker-in-Docker)를 설정해야 해요. Kubernetes 실행기는 Docker-in-Docker를 지원합니다.
Code Quality job이 Kubernetes 실행기에서 실행되도록 하려면:
- Docker 데몬과 통신하는 데 TLS를 사용한다면 실행기가 권한 모드로 실행되어야 해요. 또한 인증서 디렉터리가 볼륨 마운트로 지정되어야 해요.
- Code Quality job이 시작되기 전에 DinD 서비스가 완전히 시작되지 않을 수 있어요. 자세한 내용은 Kubernetes 실행기 문제 해결을 참고하세요. 이 문제를 해결하려면
before_script로 Docker 데몬이 완전히 시작될 때까지 기다리세요. 예시는 다음 섹션의.gitlab-ci.yml구성에서 볼 수 있어요.
Kubernetes
Kubernetes에서 Code Quality를 실행하려면:
- Docker in Docker 서비스가
config.toml파일에 서비스 컨테이너로 추가되어야 해요. - 서비스 컨테이너의 Docker 데몬이 TCP와 UNIX 소켓을 모두 수신해야 해요. Code Quality가 두 소켓을 모두 필요로 하기 때문이에요.
- Docker 소켓이 볼륨으로 공유되어야 해요.
Docker 요구 사항 때문에 서비스 컨테이너에 privileged 플래그를 활성화해야 해요.
[runners.kubernetes]
[runners.kubernetes.service_container_security_context]
privileged = true
allow_privilege_escalation = true
[runners.kubernetes.volumes]
[[runners.kubernetes.volumes.empty_dir]]
mount_path = "/var/run/"
name = "docker-sock"
[[runners.kubernetes.services]]
alias = "dind"
command = [
"--host=tcp://0.0.0.0:2375",
"--host=unix://var/run/docker.sock",
"--storage-driver=overlay2"
]
entrypoint = ["dockerd"]
name = "docker:29.1.4-dind"
GitLab Runner Helm Chart를 사용한다면 values.yaml 파일의 config 필드에 앞선 Kubernetes 구성은 사용할 수 있어요.
가장 좋은 전체 성능을 제공하는 overlay2 스토리지 드라이버를 사용하려면:
- Docker CLI가 통신하는
DOCKER_HOST를 지정해요. DOCKER_DRIVER변수를 빈 값으로 설정해요.
Docker 데몬이 완전히 부팅될 때까지 기다리려면 HEALTHCHECK_TCP_PORT 변수를 설정하거나 before_script 섹션을 사용하세요.
include:
- template: Code-Quality.gitlab-ci.yml
code_quality:
services: []
variables:
DOCKER_HOST: tcp://dind:2375
DOCKER_DRIVER: ""
before_script:
- while ! docker info > /dev/null 2>&1; do sleep 1; done
OpenShift
OpenShift에서는 GitLab Runner Operator를 사용해야 해요. 서비스 컨테이너의 Docker 데몬에 스토리지를 초기화할 권한을 주려면 /var/lib 디렉터리를 볼륨 마운트로 마운트해야 해요.
/var/lib 디렉터리를 볼륨 마운트로 마운트할 수 없다면 --storage-driver를 vfs로 설정할 수 있어요. vfs 값을 선택하면 성능에 부정적인 영향이 있을 수 있습니다.
Docker 데몬 권한을 구성하려면:
- 이 구성 템플릿으로
config.toml파일을 만들어 러너 구성을 커스터마이즈해요:
[[runners]]
[runners.kubernetes]
[runners.kubernetes.service_container_security_context]
privileged = true
allow_privilege_escalation = true
[runners.kubernetes.volumes]
[[runners.kubernetes.volumes.empty_dir]]
mount_path = "/var/run/"
name = "docker-sock"
[[runners.kubernetes.volumes.empty_dir]]
mount_path = "/var/lib/"
name = "docker-data"
[[runners.kubernetes.services]]
alias = "dind"
command = [
"--host=tcp://0.0.0.0:2375",
"--host=unix://var/run/docker.sock",
"--storage-driver=overlay2"
]
entrypoint = ["dockerd"]
name = "docker:29.1.4-dind"
- 사용자 지정 구성을 러너에 설정해요.
- 선택 사항. 빌드 Pod에
privileged서비스 계정을 연결해요. 이는 OpenShift 클러스터 설정에 따라 달라집니다:oc create sa dind-sa oc adm policy add-scc-to-user anyuid -z dind-sa oc adm policy add-scc-to-user -z dind-sa privileged [runners.kubernetes]섹션에 권한을 설정해요.- job 정의는 Kubernetes 경우와 동일하게 유지해요:
include: - template: Code-Quality.gitlab-ci.yml code_quality: services: [] variables: DOCKER_HOST: tcp://dind:2375 DOCKER_DRIVER: "" before_script: - while ! docker info > /dev/null 2>&1; do sleep 1; done
볼륨과 Docker 스토리지
Docker는 모든 데이터를 /var/lib 볼륨에 저장하므로 볼륨이 커질 수 있어요. 클러스터 전체에서 Docker-in-Docker 스토리지를 재사용하려면 Persistent Volumes을 대안으로 사용할 수 있어요.