Skip to content

Commit cbc3f7f

Browse files
Add pipeline analysis next-steps workflow (#48154)
* Adding a new github actions workflow to trigger on pipeline failures. * Updated copilot feedback. * Update .github/workflows/pipeline-analysis-next-steps.md Co-authored-by: Daniel Jurek <djurek@microsoft.com> * Updated with feedback. * Add temporary test pipeline for gh-aw trigger validation * Revert "Add temporary test pipeline for gh-aw trigger validation" This reverts commit 12764ed. * . (#48155) * Delete test-trigger-pipeline.yml * Removed manual runs from trigger. Updated comments --------- Co-authored-by: Daniel Jurek <djurek@microsoft.com>
1 parent 5608fba commit cbc3f7f

3 files changed

Lines changed: 1939 additions & 0 deletions

File tree

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Pipeline Analysis - Next Steps (trigger / dispatcher)
2+
#
3+
# Plain GitHub Actions workflow that watches for a pull request's Azure DevOps CI to finish
4+
# in a failure state, then dispatches the agentic workflow `pipeline-analysis-next-steps.md`
5+
# (compiled to `pipeline-analysis-next-steps.lock.yml`) to analyze the failure and post a
6+
# "Pipeline Analysis Next Steps" comment.
7+
#
8+
# Why a separate trigger workflow (mirrors azure-sdk-for-net's mgmt-review):
9+
# * `check_run` is not a pull_request event, so the agentic workflow cannot resolve the
10+
# target PR on its own. This job extracts the PR number and passes it as an explicit
11+
# workflow_dispatch input (and `aw_context`) so the agent comments on the right PR.
12+
# * Keeps the privileged Copilot run (copilot-requests) isolated in the agentic workflow;
13+
# this dispatcher only needs `actions: write` to start it.
14+
#
15+
# CI note: azure-sdk-for-python's PR builds roll up into a single Azure Pipelines check run
16+
# named `python - pullrequest` per commit (its per-stage jobs are `python - pullrequest (...)`,
17+
# which do NOT end in `- pullrequest`). We trigger on `check_run` and gate on the name ending
18+
# in `- pullrequest` plus a failing conclusion, so the analysis fires once per failing PR CI
19+
# run and ignores unrelated checks. This mirrors azure-sdk-for-net's `net - pullrequest` gate.
20+
name: Pipeline Analysis - Next Steps Trigger
21+
22+
on:
23+
check_run:
24+
types: [completed]
25+
26+
permissions:
27+
actions: write # dispatch the agentic (lock) workflow
28+
contents: read
29+
pull-requests: read
30+
31+
jobs:
32+
dispatch-next-steps:
33+
# Only react to a failing Azure DevOps PR-CI check run whose name ends in `- pullrequest`;
34+
# ignore every other check run (github-actions, policy service, SDL sub-jobs, and this
35+
# workflow's own runs).
36+
if: >
37+
github.event.check_run.check_suite.app.slug == 'azure-pipelines' &&
38+
endsWith(github.event.check_run.name, '- pullrequest') &&
39+
github.event.check_run.conclusion == 'failure'
40+
runs-on: ubuntu-latest
41+
steps:
42+
- name: Dispatch pipeline next-steps analysis
43+
env:
44+
GH_TOKEN: ${{ github.token }}
45+
REPOSITORY: ${{ github.repository }}
46+
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
47+
PR_NUMBER: ${{ github.event.check_run.pull_requests[0].number }}
48+
CI_CONCLUSION: ${{ github.event.check_run.conclusion }}
49+
CI_HEAD_SHA: ${{ github.event.check_run.head_sha }}
50+
run: |
51+
set -euo pipefail
52+
53+
# Fork PRs do not populate check_run.pull_requests; fall back to matching an open
54+
# PR by head SHA (same-repo branches only).
55+
find_open_pr_for_head_sha() {
56+
local head_sha="$1"
57+
[ -z "$head_sha" ] && return 0
58+
gh api --paginate "repos/$REPOSITORY/pulls?state=open&per_page=100" \
59+
--jq ".[] | select(.head.sha == \"$head_sha\") | [.updated_at, .number] | @tsv" |
60+
sort -r |
61+
sed -n '1s/^[^\t]*\t//p'
62+
}
63+
64+
dispatch_next_steps() {
65+
local pr_number="$1"
66+
local conclusion="$2"
67+
local head_sha="$3"
68+
69+
if [ -z "$pr_number" ]; then
70+
echo "No pull request associated with this check run; nothing to do."
71+
return 0
72+
fi
73+
74+
if [ "$(gh pr view "$pr_number" --repo "$REPOSITORY" --json isDraft --jq '.isDraft')" = "true" ]; then
75+
echo "Skipping draft PR #$pr_number."
76+
return 0
77+
fi
78+
79+
# Do not analyze a superseded commit: if the completed check run's SHA no longer
80+
# matches the PR head, the author has already pushed newer code.
81+
local current_head_sha
82+
current_head_sha="$(gh pr view "$pr_number" --repo "$REPOSITORY" --json headRefOid --jq '.headRefOid')"
83+
if [ -n "$head_sha" ] && [ "$head_sha" != "$current_head_sha" ]; then
84+
echo "Skipping PR #$pr_number; check run SHA $head_sha no longer matches head $current_head_sha."
85+
return 0
86+
fi
87+
88+
local aw_context
89+
aw_context="$(printf '{"item_type":"pull_request","item_number":%s}' "$pr_number")"
90+
91+
gh workflow run pipeline-analysis-next-steps.lock.yml \
92+
--repo "$REPOSITORY" \
93+
--ref "$DEFAULT_BRANCH" \
94+
-f aw_context="$aw_context" \
95+
-f pr_number="$pr_number" \
96+
-f ci_conclusion="$conclusion" \
97+
-f ci_head_sha="$head_sha"
98+
echo "Dispatched pipeline next-steps analysis for PR #$pr_number."
99+
}
100+
101+
if [ -z "$PR_NUMBER" ]; then
102+
PR_NUMBER="$(find_open_pr_for_head_sha "$CI_HEAD_SHA")"
103+
fi
104+
dispatch_next_steps "$PR_NUMBER" "$CI_CONCLUSION" "$CI_HEAD_SHA"

0 commit comments

Comments
 (0)