Skip redundant PR triggers (Draft<->Open state transitions)#4303
Skip redundant PR triggers (Draft<->Open state transitions)#4303paulmedynski wants to merge 2 commits into
Conversation
Add a gate stage to PR pipelines that detects when a build was triggered by a state-only PR transition (Draft<->Open) rather than meaningful changes. The gate queries the Azure DevOps builds API for the most recent successful build of the same PR and compares the merge commit SHA. If unchanged and a prior build succeeded, downstream stages are skipped via condition cascade. - New: eng/pipelines/stages/detect-redundant-trigger-stage.yml - Modified: dotnet-sqlclient-ci-core.yml (skipRedundantTrigger parameter) - Modified: both sqlclient-pr-*-pipeline.yml (pass skipRedundantTrigger: true)
There was a problem hiding this comment.
Pull request overview
This PR adds an optional “redundant trigger” gate to PR validation pipelines to short-circuit runs that are triggered by Draft ↔ Open state transitions (or similar non-code changes) when the PR merge commit SHA hasn’t changed and a prior run already succeeded.
Changes:
- Introduces a new gating stage template that queries the Azure DevOps Builds API and emits an output variable indicating whether the run is meaningful.
- Adds a
skipRedundantTriggerparameter to the shared CI core template and wires in an initial gate + no-op stage that cascades downstream stage skipping. - Enables this behavior in both PR validation pipelines (Project and Package reference modes).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| eng/pipelines/stages/detect-redundant-trigger-stage.yml | New stage template that queries prior successful builds for the same PR merge ref and emits meaningful=true/false. |
| eng/pipelines/dotnet-sqlclient-ci-core.yml | Adds skipRedundantTrigger parameter and prepends the gate stages when enabled. |
| eng/pipelines/sqlclient-pr-project-ref-pipeline.yml | Enables skipRedundantTrigger for PR validation (Project reference mode). |
| eng/pipelines/sqlclient-pr-package-ref-pipeline.yml | Enables skipRedundantTrigger for PR validation (Package reference mode). |
- Use $SYSTEM_ACCESSTOKEN env var instead of $(System.AccessToken) macro
expansion in curl to avoid accidental logging/expansion
- Add HTTP status code validation with safe fallback (meaningful=true)
when the Builds API is unavailable or returns errors
- Add Build.Reason check to skip gate for non-PR triggers (manual reruns)
- Move debug output to a separate conditional step using template-time
${{ if eq(parameters.debug, true) }} instead of runtime string comparison
|
/azp run |
|
Azure Pipelines successfully started running 2 pipeline(s). |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4303 +/- ##
==========================================
- Coverage 66.04% 64.69% -1.35%
==========================================
Files 275 279 +4
Lines 42976 66219 +23243
==========================================
+ Hits 28383 42843 +14460
- Misses 14593 23376 +8783
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| HTTP_CODE=$(curl -s -o /tmp/api_response.json -w "%{http_code}" \ | ||
| -H "Authorization: Bearer $SYSTEM_ACCESSTOKEN" "$API_URL") | ||
|
|
||
| if [[ "$HTTP_CODE" -lt 200 || "$HTTP_CODE" -ge 300 ]]; then | ||
| echo "##[warning]Builds API returned HTTP $HTTP_CODE — defaulting to meaningful build." | ||
| echo "##vso[task.setvariable variable=meaningful;isOutput=true]true" | ||
| exit 0 |
Pull request was converted to draft
Skip redundant PR pipeline triggers
Adds an optional gate stage to PR validation pipelines that short-circuits runs triggered by Draft ↔ Open state transitions (or similar non-code changes) when the merge commit SHA has not changed since the last successful build.
Problem
Azure DevOps PR triggers fire on every PR state change — including Draft/Open transitions that do not alter the code. This causes redundant pipeline runs that waste compute and clutter the build history.
Solution
A new Detect Redundant Trigger stage template queries the Azure DevOps Builds API:
Build.Reasonis notPullRequest(e.g., manual queue), always proceedsBuild.SourceVersion(the PR merge commit) against the most recent successful build for the same PR/definitionmeaningful=falseand downstream stages are skipped via implicit dependency cascademeaningful=true(safe fallback — always builds)Skipped pipeline runs still report a green ✓ status (Azure DevOps treats skipped stages as success).
Design
detect_redundant_trigger_stageoutputsmeaningful=false, the intermediate stage condition evaluates false → it is skipped → all downstream stages with defaultsucceeded()condition are also skipped.skipRedundantTrigger: trueinextendsparameters.Files Changed
eng/pipelines/stages/detect-redundant-trigger-stage.ymleng/pipelines/dotnet-sqlclient-ci-core.ymlskipRedundantTriggerparameter + conditional gate stageseng/pipelines/sqlclient-pr-project-ref-pipeline.ymlskipRedundantTriggereng/pipelines/sqlclient-pr-package-ref-pipeline.ymlskipRedundantTriggerSafety & Robustness
meaningful=true(build always proceeds on failure)$SYSTEM_ACCESSTOKENenv var (avoids macro expansion in script)${{ if eq(parameters.debug, true) }})