CI Template Reference¶
Every hidden job provided by
orchestrator/ci-templates, with its Docker image, required variables, and purpose. Extend these jobs in your project's.gitlab-ci.ymlusing theextends:keyword.
How to Use a Template Job¶
All template jobs are defined as hidden jobs (names start with .). Extend them in your pipeline and override only what differs:
Any key you define in your job overrides the corresponding key from the template. Keys not specified in your job are inherited from the template.
Python Templates (.gitlab-ci-python.yml)¶
For FastAPI services, background workers, the executor CLI, and cwiq-common.
| Template Job | Image | Required Variables | Purpose |
|---|---|---|---|
.python-lint |
python:3.12-slim |
SOURCE_PATH |
Runs ruff check and ruff format --check against $SOURCE_PATH |
.python-typecheck |
python:3.12-slim |
SOURCE_PATH |
Runs mypy $SOURCE_PATH for static type checking |
.python-test |
python:3.12-slim |
SOURCE_PATH |
Runs pytest with coverage; includes PostgreSQL and Redis as GitLab services |
.python-integration-test |
python:3.12-slim |
SOURCE_PATH |
Integration tests; runs only on main and develop; uses the large runner |
.python-semgrep |
semgrep/semgrep:latest |
— | SAST scan with rulesets p/python, p/secrets, p/owasp-top-ten; outputs semgrep-results.sarif and semgrep-results.json |
.python-build |
python:3.12-slim |
— | Builds a Python wheel with python -m build |
.python-publish |
python:3.12-slim |
— | Publishes the wheel to the GitLab Package Registry via Twine; runs on version tags only |
Example: Python Service Pipeline¶
include:
- project: 'orchestrator/ci-templates'
ref: main
file:
- '/.gitlab-ci-common.yml'
- '/.gitlab-ci-python.yml'
- '/.gitlab-ci-trivy.yml'
- '/.gitlab-ci-scan.yml'
variables:
SOURCE_PATH: src
lint:
extends: .python-lint
stage: validate
tags: [small]
typecheck:
extends: .python-typecheck
stage: validate
tags: [small]
semgrep:
extends: .python-semgrep
stage: validate
tags: [small]
test:
extends: .python-test
stage: test
tags: [small]
Node.js Templates (.gitlab-ci-node.yml)¶
For the UI project (React 18 / TypeScript).
| Template Job | Image | Required Variables | Purpose |
|---|---|---|---|
.node-lint |
node:20-alpine |
— | Runs npm run lint (ESLint) |
.node-typecheck |
node:20-alpine |
— | Runs tsc --noEmit to check TypeScript types |
.node-test |
node:20-alpine |
— | Runs npm run test -- --run with Vitest coverage |
.node-semgrep |
semgrep/semgrep:latest |
— | SAST scan with rulesets p/javascript, p/typescript, p/react, p/secrets |
.node-build |
node:20-alpine |
— | Runs npm run build; produces the dist/ static bundle |
.node-e2e |
playwright:v1.40.0-focal |
E2E_ADMIN_USERNAME, E2E_ADMIN_PASSWORD |
Playwright E2E tests against DEV; runs on main and develop only |
.node-publish |
node:20-alpine |
— | Publishes the npm package to the GitLab npm registry; version tags only |
E2E tests require a running DEV environment
The .node-e2e template runs against https://orchestrator.dev.cwiq.io. It will fail if the DEV environment is down. E2E credentials are fetched from Vault (secret/orchestrator/e2e-test-user) at runtime.
Common Templates (.gitlab-ci-common.yml)¶
Shared infrastructure templates used by both Python and Node.js services.
| Template Job | Image | Purpose |
|---|---|---|
.docker-build |
gcr.io/kaniko-project/executor:debug (via Nexus proxy) |
Builds the Docker image with Kaniko and pushes to Nexus; writes build.env with IMAGE_TAG |
.docker-push-latest |
docker:27 + dind service |
Re-tags the image as latest and pushes to Nexus; main branch only |
.ansible-deploy |
cytopia/ansible-runner |
Runs an Ansible playbook on the ansible server via SSH; used for infrastructure-level deployments |
.health-check |
curlimages/curl |
Curls a health endpoint with 30 retries at 5-second intervals; fails if the endpoint does not return 200 within the retry window |
Scan Templates (.gitlab-ci-trivy.yml and .gitlab-ci-scan.yml)¶
| Template Job | Image | Purpose |
|---|---|---|
.trivy-fs-scan |
aquasec/trivy:0.69.3 |
Scans the repository filesystem for secrets and misconfigurations; exits non-zero on CRITICAL secrets findings |
.trivy-image-scan |
aquasec/trivy:0.69.3 |
Scans the built Docker image for CVEs; runs on main only; uses IMAGE_TAG from build.env |
.defectdojo-import |
alpine:latest |
Uploads Trivy image scan results to DefectDojo via REST API; uses Vault JWT to fetch the API token |
.sonarqube-scan |
sonarsource/sonar-scanner-cli:latest |
Runs SonarQube analysis and uploads to sonarqube.shared.cwiq.io; uses Vault JWT to fetch the project token; main branch only |
Deprecated security templates
The templates .python-security and .node-security still exist in the file for backward compatibility but are deprecated. Do not use them in new or existing pipelines. Use .python-semgrep and .node-semgrep instead. The deprecated templates will be removed in a future release of ci-templates.
Vault Authentication in Templates¶
Templates that call external services (SonarQube, DefectDojo, Nexus) authenticate via Vault JWT. The pattern is the same in every template:
before_script:
- |
# Fetch Vault token using GitLab CI_JOB_JWT_V2
VAULT_TOKEN=$(curl -s --request POST \
"${VAULT_ADDR}/v1/auth/jwt/login" \
--data "{\"jwt\": \"${CI_JOB_JWT_V2}\", \"role\": \"gitlab-ci\"}" \
| python3 -c "import sys, json; print(json.load(sys.stdin)['auth']['client_token'])")
# Fetch service credentials from Vault
NEXUS_CREDS=$(curl -s --header "X-Vault-Token: ${VAULT_TOKEN}" \
"${VAULT_ADDR}/v1/secret/nexus/svc-orchestrator")
The VAULT_ADDR variable comes from the group-level CI/CD variable. The Vault JWT role gitlab-ci is pre-configured with policies that allow reading the secrets each template needs.
Related Documentation¶
- Pipeline Overview — How templates fit into the overall pipeline
- Pipeline Stages — Detailed stage and job breakdown
- Branch Rules & Workflow — Which templates run on which branches
- Vault JWT Auth — How the Vault JWT authentication pattern works
- Kaniko Docker Builds — The
.docker-buildtemplate in detail