Skip to content

Multi-CI architecture

SARC’s compliance pipeline runs on three CIs in parallel today. The customer adopts whichever they already own; no migration is required to deploy SARC.

GitLab.com/compliance-calitii/sarc SOURCE OF TRUTH
│ (scheduled mirror, 2x/day)
┌───────────────────────────┐ ┌────────────────────────────┐
│ GitHub: Freundcloud/SARC │ │ Azure DevOps: olaffreund- │
│ (full mirror) │ │ 0455/SARC/SARC (mirror) │
└───────────────────────────┘ └────────────────────────────┘

GitLab is authoritative. Mirrors are force-pushed twice daily via scheduled jobs in .gitlab/ci/templates/mirror-sync.yml. Don’t commit directly to GitHub or ADO main — the next mirror push overwrites it.

The same compliance pipeline runs identically across all three CIs:

StageGitLab CIGitHub ActionsAzure DevOps
Validate (yaml + shell + terraform + helm).gitlab/ci/templates/validate-*.yml.github/workflows/_reusable-validate.ymlci/azuredevops/stages/validate.yml
Build portal imagebuild-portal.yml_reusable-build-portal.ymlci/azuredevops/stages/build.yml
Build podtato imagebuild-podtato.yml_reusable-build-podtato.yml(Azure-only on ADO)
Security scans (SAST, SCA, container, secret, IaC)security-scans.yml_reusable-security-scans.ymlsecurity-native.yml (MSDO + AdvSec)
Kosli attestationskosli-attest.yml_reusable-kosli-attest.ymlci/azuredevops/stages/kosli-attest.yml
SBOM + license checksbom.yml_reusable-sbom.yml(part of MSDO bundle)
ServiceNow CR enrichmentservicenow-cr-enrich.yml_reusable-servicenow-cr-enrich.ymlci/azuredevops/stages/servicenow.yml
Deploy (Helm)deploy-helm.ymldeploy-helm-{aws,azure,gcp}.ymlci/azuredevops/stages/deploy.yml (Azure-only)
Post-deploy Kosli reportpostsync-kosli-report.yml_reusable-postsync-kosli-report.yml(via env Approvals + ServiceNow check)
DASTdast-podtato.ymldast-postsync-qa.ymldast.yml

For each CI, the underlying shell scripts in scripts/ci/ (kosli-attest.sh, servicenow-cr.sh, gitops-bump-tag.sh, etc.) are the same. The CI-specific YAML is just orchestration on top.

ADO is intentionally scoped to Azure only, podtato-head only — it’s parallel CI for Azure deploys, not a full CI replacement. GitLab handles everything (Source of truth + AWS deploys + Azure deploys + portal). GitHub Actions has full parity (every workflow GitLab has).

Per-cloud terraform ownership (current):

  • AWS terraform → GitLab CI runs it
  • Azure terraform → Azure DevOps runs it
  • GCP terraform → GitHub Actions runs it

This split mirrors which CI is most engaged for each cloud; in principle any CI could run any cloud’s Terraform.

scripts/ci/promote.sh orchestrates dev → qa → prod promotion:

  1. Generate release notes (HTML)
  2. Compute Kosli risk score via scripts/ci/kosli-score.sh
  3. Create ServiceNow CR with risk score + release notes
  4. Enrich CR with SBOM + SARIF artifacts via scripts/ci/servicenow-cr-enrich.sh
  5. Upload bulk attestations via scripts/ci/servicenow-upload-attestations.sh
  6. qa: auto-approve if compliant; prod: manual approval only
  7. Bump gitops image tag via scripts/ci/gitops-bump-tag.sh

This runs identically across GitLab + GitHub. ADO uses the same shell scripts wrapped in stage YAML.

Historical: SARC’s parent KARC was a GitLab-first project. Migrating that away would be expensive for no real gain. GitLab Premium also has the strongest compliance-framework feature (downstream compliance templates), which SARC’s customers use.

The mirror topology means the CHOICE of GitLab as source of truth is not visible to a customer who only uses GitHub or ADO — they get an identical experience.