feat(ci): close nightly failure issues when the stage recovers - #41
Open
noodlemctwoodle wants to merge 2 commits into
Open
feat(ci): close nightly failure issues when the stage recovers#41noodlemctwoodle wants to merge 2 commits into
noodlemctwoodle wants to merge 2 commits into
Conversation
The nightly E2E validation workflow had no recovery path. report-failure opens and refreshes an issue on every stage failure, but nothing ever closed one, so a failure that had already been fixed stayed open indefinitely and the nightly-failure label stopped meaning "currently broken". Issue #28 is the worked example: deploy-defender-detections failed every night from 4 June because the workflow passed -SubscriptionId to Deploy-DefenderDetections.ps1, which accepts only BasePath, IsGov and WhatIf. The restructure in #27 rewrote that invocation and the stage has been green every night since 8 July, but the issue was still open 16 days later with 33 "Re-failed" comments and no indication it was fixed. Files modified: - .github/workflows/sentinel-deploy-nightly.yml - Added a report-recovery job: needs the same five deploy jobs, conditional always(), own permissions block (issues: write, contents: read). For each stage whose result is 'success' it finds the matching open issue, comments with a link to the passing run, and closes it. - Updated the header comment's failure-handling section to describe the recovery path. - Docs/Pipelines/Deploy-Nightly.md - Added the job to the stage diagram and a "7. report-recovery" section covering both restrictions below. Two deliberate restrictions: - Only 'success' counts as recovery. A skipped stage is not evidence that anything was fixed (deploy-infrastructure skips on every run where the workspace already exists), so it leaves any open issue alone. - The lookup filters on the nightly-failure label and matches the title exactly, rather than reusing the fuzzy 'in:title' search from the failure path. Closing the wrong issue is worse than opening a duplicate, so it must not match a human-filed issue with a similar title. always() rather than a success condition because recovery is per stage: one stage can go green in the same run where another fails, and both the close and the open should happen. Testing: - Extracted the job's script as YAML actually parses it, substituted the needs.*.result expressions, and ran it against a stubbed gh with a fixture containing both issue #28 and a decoy issue whose title shares its prefix. It closed 28 and left the decoy alone, with the comment rendering correctly. - Exercised three run shapes: all-green-with-routine-skip, mixed (one stage recovered while another still fails), and all-red. Correct behaviour in each, exiting 0. - Rewrote an earlier associative-array version after local testing showed 'declare -A' needs bash 4. The runner has bash 5, but the plain-list form has no version dependency and stays testable anywhere. - Workflow confirmed to parse as valid YAML, with report-recovery present and its if/needs/permissions as intended. No ADO counterpart: Pipelines/ has no nightly equivalent, so this is GitHub-only and the cross-platform parity rule does not apply. Refs #28
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an automated “recovery” path to the GitHub-only nightly E2E deploy validation workflow so that stage-tracking issues get closed once the relevant stage is green again, keeping the nightly-failure label meaningful.
Changes:
- Add a new
report-recoveryjob that runs withalways()and closes matching opennightly-failureissues for stages that succeeded. - Update the nightly workflow header comments to document the new recovery behaviour.
- Extend the nightly deploy workflow documentation to include
report-recoveryand its restrictions.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
.github/workflows/sentinel-deploy-nightly.yml |
Adds report-recovery job to close stage failure issues after recovery. |
Docs/Pipelines/Deploy-Nightly.md |
Documents the new recovery job and updates the workflow stage description. |
Comment on lines
107
to
+112
| deploy-defender-detections Deploy-DefenderDetections.ps1 -WhatIf. | ||
| ▼ | ||
| report-failure Runs only if any prior job failed. | ||
| ▼ | ||
| report-recovery Always runs. Closes the tracking issue for | ||
| any stage that is green again. |
Comment on lines
+110
to
+112
| ▼ | ||
| report-recovery Always runs. Closes the tracking issue for | ||
| any stage that is green again. |
Comment on lines
+446
to
+451
| NUM=$(gh issue list \ | ||
| --state open \ | ||
| --label nightly-failure \ | ||
| --limit 100 \ | ||
| --json number,title \ | ||
| | jq -r --arg t "$TITLE" '[.[] | select(.title == $t) | .number] | first // empty') |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Suppressed comments (2)
Docs/Pipelines/Deploy-Nightly.md:112
- The stage diagram (and the surrounding wording about a linear chain) implies
report-recoveryruns after and depends onreport-failure(via the ▼ arrow). In the workflow,report-recoverydoes notneedreport-failureand can run even whenreport-failureis skipped, so the diagram should show the two reporting jobs as independent follow-ons after the deploy chain completes.
report-failure Runs only if any prior job failed.
▼
report-recovery Always runs. Closes the tracking issue for
any stage that is green again.
.github/workflows/sentinel-deploy-nightly.yml:410
report-recoveryrunsgh issue ...commands without checking out the repo and without specifying the target repository (--repo/GH_REPO). When the job runs outside a git checkout,ghcan fail to resolve which repo to query/close issues in, which would make this job fail even on an all-green run.
- name: Close issues for stages that are now green
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a
report-recoveryjob to the nightly E2E validation workflow that closes a stage's tracking issue when that stage goes green again. Documents it inDocs/Pipelines/Deploy-Nightly.md.Why is this change needed?
The nightly workflow had no recovery path.
report-failureopens and refreshes an issue on every stage failure, but nothing ever closed one. A failure that had already been fixed stayed open indefinitely, and thenightly-failurelabel stopped meaning "currently broken".Issue #28 is the worked example.
deploy-defender-detectionsfailed every night from 4 June because the workflow passed-SubscriptionIdtoDeploy-DefenderDetections.ps1, which accepts onlyBasePath,IsGovandWhatIf:The restructure in #27 (a7b2ab2, 7 July 09:50 BST) rewrote that invocation to
-BasePath+-WhatIf. The timing is exact: the 7 July nightly ran at 04:22 and failed, the 8 July ran at 04:03 and passed. The stage has been green every night since, including today. But #28 was still open 16 days later carrying 33 "Re-failed" comments and no signal that it was fixed, which is precisely the confusion this job removes.Worth noting the underlying deploy bug is already fixed and needs nothing here. Verified that today's run genuinely executed the Defender job rather than skipping it, and that the production deploy at
sentinel-deploy.ymlsplats onlyBasePathand optionalWhatIf, so Monday's deploy carries no latent version of it.What does this change do?
Adds
report-recovery:needsthe same five deploy jobs, conditionalalways(), with its ownpermissions: { issues: write, contents: read }. For each stage whose result issuccessit finds the matching open issue, comments with a link to the passing run, and closes it.always()rather than a success condition because recovery is per stage: one stage can go green in the same run where another fails, and both the close and the open should happen.Two deliberate restrictions:
successcounts as recovery. Askippedstage is not evidence that anything was fixed (deploy-infrastructureskips on every run where the workspace already exists), so it leaves any open issue alone.in:titlesearch from the failure path. Closing the wrong issue is worse than opening a duplicate, so it must not match a human-filed issue with a similar title.What does this fix or affect?
Refs #28. Deliberately does not close it by hand: leaving it open means the first run after merge closes it automatically, which proves the job works end to end against the real case.
No behavioural change to any existing job.
report-recoveryonly ever closes issues carrying thenightly-failurelabel whose title matches a stage name exactly.Type of change
Files changed (high level)
.github/workflows/sentinel-deploy-nightly.yml- newreport-recoveryjob; header comment updated to describe the recovery pathDocs/Pipelines/Deploy-Nightly.md- job added to the stage diagram, plus a section covering both restrictionsPre-merge checklist
./Tools/Invoke-PRValidation.ps1 -RepoPath .)az bicep build --file Infra/sentinel/main.bicep --stdout > /dev/null)dependencies.jsonregenerated if KQL content changed (./Tools/Build-DependencyManifest.ps1 -Mode Generate)Parity is ticked as not applicable:
Pipelines/has no nightly equivalent, so this is GitHub-only. Bicep,dependencies.jsonand Pester are unticked because no Bicep, KQL or test files are touched; the CI gate runs them regardless.Testing
needs.*.resultexpressions, and ran it against a stubbedgh. The fixture contained both issue Nightly E2E deploy validation failed: deploy-defender-detections #28 and a decoy whose title shares its full prefix (... deploy-defender-detections (my notes)). It closed 28, left the decoy alone, and rendered the comment correctly with the backticks literal and the blank line preserved.declare -Aneeds bash 4. The runner has bash 5 so it would have worked, but the plain-list form has no version dependency and stays testable anywhere, so it was rewritten.report-recoverypresent and itsif/needs/permissionsas intended.Not smoke tested against a live run, since the job only fires on the schedule from the default branch. The first nightly after merge is the real test, and #28 is the case it should close.
Related