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.

flowchart TD
  GL["GitLab · compliance-calitii/sarc<br/><b>Source of truth</b>"]
  GH["GitHub · Freundcloud/SARC<br/>full mirror"]
  ADO["Azure DevOps · olaffreund0455/SARC<br/>full mirror"]
  GL -->|"scheduled mirror · twice daily · force-push"| GH
  GL -->|"scheduled mirror · twice daily · force-push"| ADO
  classDef sot fill:#12233b,stroke:#3a6ea5,color:#dce8f7;
  classDef mir fill:#1c1c22,stroke:#4a4a55,color:#e6e6ee;
  class GL sot;
  class GH,ADO mir;

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:

Stage GitLab CI GitHub Actions Azure DevOps
Validate (yaml + shell + terraform + helm) .gitlab/ci/templates/validate-*.yml .github/workflows/_reusable-validate.yml ci/azuredevops/stages/validate.yml
Build portal image build-portal.yml _reusable-build-portal.yml ci/azuredevops/stages/build.yml
Build podtato image build-podtato.yml _reusable-build-podtato.yml (Azure-only on ADO)
Security scans (SAST, SCA, container, secret, IaC) security-scans.yml _reusable-security-scans.yml security-native.yml (MSDO + AdvSec)
Evidence Vault / Fides attestations fides-attest.yml _reusable-fides-attest.yml ci/azuredevops/stages/fides-attest.yml
SBOM + license check sbom.yml _reusable-sbom.yml (part of MSDO bundle)
ServiceNow CR enrichment servicenow-cr-enrich.yml _reusable-servicenow-cr-enrich.yml ci/azuredevops/stages/servicenow.yml
Deploy (Helm) deploy-helm.yml deploy-helm-{aws,azure,gcp}.yml ci/azuredevops/stages/deploy.yml (Azure-only)
Post-deploy Evidence Vault report postsync-fides-report.yml _reusable-postsync-fides-report.yml (via env Approvals + ServiceNow check)
DAST dast-podtato.yml dast-postsync-qa.yml dast.yml

For each CI, the underlying shell scripts in scripts/ci/ (fides-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 Evidence Vault risk score via scripts/ci/fides-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.