CI/CD workflows and pipelines
July 10, 2026 · View on GitHub
GitHub Actions workflows live under .github/workflows/; Azure DevOps
pipelines live under Pipelines/. The ADO version is the default
source of truth — GitHub workflows mirror ADO behaviour except in
the narrow documented cases covered under Hard rule 1 below.
Reference doc:
Docs/Pipelines/README.md.
File inventory
| GitHub Actions | Azure DevOps | What |
|---|---|---|
.github/workflows/sentinel-deploy.yml | Pipelines/Sentinel-Deploy.yml | Weekly Mon 04:00 UTC: full deploy (Bicep + Content Hub + custom + Defender) |
.github/workflows/sentinel-drift-detect.yml | Pipelines/Sentinel-Drift-Detect.yml | Daily 06:00 UTC: detect portal-edited rules + auto-PR |
.github/workflows/sentinel-dcr-inventory.yml | Pipelines/Sentinel-DCR-Inventory.yml | On change: deploy DCR inventory runbook |
.github/workflows/sentinel-dependency-update.yml | Pipelines/Sentinel-Dependency-Update.yml | Daily 02:00 UTC: refresh dependencies.json + auto-PR |
.github/workflows/pr-validation.yml | Pipelines/Sentinel-PR-Validation.yml | On every PR: 5-job merge gate |
.github/workflows/pr-template-validation.yml | (GitHub-only) | On every PR: fail if the PR description does not fill in .github/PULL_REQUEST_TEMPLATE.md |
.github/workflows/sentinel-deploy-nightly.yml | (GitHub-only) | Daily 03:00 UTC: E2E smoke test against test workspace |
Composite actions
Two composite actions live under .github/actions/. Use these
instead of inlining Azure/login@v2 or Install-Module patterns:
./.github/actions/azure-login-oidc— OIDC federated login. Inputs:client-id,tenant-id,subscription-id,enable-azps-session(default'true')../.github/actions/setup-pwsh-modules— cached + pinned install of Pester + powershell-yaml. Inputs:pester-version,yaml-version,install-pester(set'false'for yaml-only jobs like the dep-manifest gate).
Hard rules
-
ADO is the default source of truth. When the two diverge, change ADO first, then port to GitHub. The reverse direction creates merge conflicts that are hard to spot in review.
Documented divergence is allowed in the narrow cases below. Where it exists, justify it inline (workflow comment, commit message, or PR description) and reference the forcing constraint so future readers don't mistake the divergence for drift:
-
Platform-forced divergence. A constraint that exists on one platform but not the other forces a different shape. The canonical example is GitHub's 25-input
workflow_dispatchcap (ADO has no equivalent limit), which is whysentinel-deploy.ymlexposes a singleskip_custom_content_typescomma-separated string wherePipelines/Sentinel-Deploy.ymlexposes nine separate boolean parameters. BusyBox vs GNU shell utilities in container images, GitHub-onlygh issue createpatterns in nightly workflows, and similar one-sided platform behaviours qualify. -
One-direction-first bug fixes. When a bug affects both platforms but the fix lands on one first (typically because the maintainer hit the bug there first), this is acceptable short-term but the divergence is not the end state. Track the pending port as a follow-up issue or a TODO in the PR description so it doesn't become permanent by neglect.
Drift caught in code review without a documented reason should be reverted, not retroactively justified.
-
-
Pin versions for every PSGallery / NuGet / GitHub Action you add. Workflow-level env vars (
PESTER_VERSION,YAML_VERSION,KUSTO_LANGUAGE_VERSION) are the convention. A breaking change shipped from a registry must NOT be able to silently fail a scheduled run on an unrelated repo change. -
Use
actions/checkout@v4(the latest pinned major). Don't pin to@mainor@master. -
Auth via OIDC, not service principal secrets. All federated creds use the SP set up by
Deploy/setup/Setup-ServicePrincipal.ps1; the workflow needspermissions: id-token: write. -
Schedule alignment — daily / weekly schedules must avoid stepping on each other. Current alignment:
- 02:00 UTC daily:
sentinel-dependency-update - 03:00 UTC daily:
sentinel-deploy-nightly(GH-only) - 04:00 UTC Monday:
sentinel-deploy - 06:00 UTC daily:
sentinel-drift-detect
- 02:00 UTC daily:
-
concurrency: cancel-in-progress: truefor PR-style workflows (re-runs invalidate the previous run's status check).cancel-in-progress: falsefor scheduled workflows that should accumulate (nightly E2E, drift sync — each run keeps its own context for diagnosis). -
workflow_dispatchinputs match parameters — when a workflow has both a schedule trigger and a manualworkflow_dispatchtrigger, every dispatch input must default to the same value the schedule run gets implicitly. -
Permissions block — declare
permissions:explicitly on every job (or workflow-level). Default-permissive is the wrong default for any job that touches a write API.
Path filters (ADO build-validation)
The ADO PR-validation policy currently filters on these paths:
Content/AnalyticalRules/*;Content/HuntingQueries/*;Modules/*;Deploy/*;Tools/*;Tests/*;dependencies.json
If you add a new top-level folder that should trigger PR validation
(e.g. a future Connectors/ folder), update this filter in two
places:
Pipelines/Sentinel-PR-Validation.yml—pr.paths.includeandtrigger.paths.include- The build-validation policy in ADO (Project Settings → Repos →
Repositories →
<repo>→ Policies → Branch policies formain→ Build validation). The path filter on the policy is the enforcement boundary; the YAML'spr.paths.includeis the trigger boundary.
Cross-references
- Pipeline reference:
Docs/Pipelines/README.md - Composite actions:
Docs/Deploy/PR-Validation-Setup.md - PR-validation gate reference:
Docs/Tests/Pester-Tests.md