Concept map
The same idea under three names. Use this when you know how to do something on one platform and need the equivalent on another.
| Concept | GitHub Actions | Azure DevOps | GitLab CI/CD |
|---|---|---|---|
| Pipeline file | .github/workflows/*.yml | azure-pipelines.yml (any path) | .gitlab-ci.yml |
| Structure | workflow › job › step | pipeline › stage › job › step | pipeline › stage › job › script |
| Compute | Runner: GitHub-hosted or self-hosted | Agent: Microsoft-hosted, Managed DevOps Pools, self-hosted | Runner: GitLab-hosted or self-managed |
| Reuse | Reusable workflows, composite actions | Templates with template and extends | include, CI/CD components, extends |
| Central enforcement | Org rulesets that require workflows | Required template check on protected resources | Scan execution, approval and pipeline execution policies |
| Built-in token | GITHUB_TOKEN, scoped by permissions | System.AccessToken, scoped by job authorization scope | CI_JOB_TOKEN, scoped by the job token allowlist |
| OIDC to cloud | permissions: id-token: write | Service connection with workload identity federation | id_tokens: with aud |
| Secrets | Repository, organization and environment secrets | Secret variables, Key Vault-linked variable groups, secure files | Protected, masked and hidden CI/CD variables; Vault via secrets: |
| Deployment gate | Environments: required reviewers, branch rules, wait timer | Environments: approvals and checks | Protected environments: deployment approvals |
| Serialize deploys | concurrency | Exclusive lock check, lockBehavior | resource_group |
| Fork contributions | pull_request with read-only token, approval for outside contributors | Fork builds without secrets, comment to trigger | Fork MR pipelines run in the fork |
| Injection trap | ${{ }} inside run | $(macro) inside script | Re-parsing with sh -c or eval |
| Pinning | Actions by full commit SHA, enforceable by policy | Template repositories by ref tag; images by digest | Includes by ref; components by exact version |
Security features side by side
What each platform gives you natively, and what it costs. GitHub and Azure DevOps both sell Secret Protection and Code Security as separate products; on GitHub they are free for public repositories.
| Capability | GitHub | Azure DevOps | GitLab |
|---|---|---|---|
| Secret scanning | Secret Protection, with push protection | Secret Protection, with push protection (Azure Repos only) | Secret Detection job (Free); secret push protection (Ultimate) |
| SAST | CodeQL via Code Security | CodeQL tasks via Code Security | SAST template (Free); Advanced SAST (Ultimate) |
| Dependency scanning | Dependency review and Dependabot | Dependency scanning task (Code Security) | Dependency Scanning v2 (Ultimate) |
| IaC and containers | Third-party scanners, results via SARIF | Third-party scanners, results via the Publish task | SAST-IaC and Container Scanning templates (Free) |
| Merge gate on findings | Ruleset: require code scanning results | Branch policy build validation; scanner exit codes | Merge request approval policy (Ultimate) |
| Signing and provenance | Artifact attestations: SLSA provenance and SBOM | Notation with Azure Key Vault | Sigstore keyless signing with id_tokens |
| Pipeline lint | CodeQL actions language | Third-party (poutine) | Third-party (poutine) |
Hardening checklist
Thirty-two controls, grouped the same way as the tutorials. Choose a platform to see only its instructions.