-
Notifications
You must be signed in to change notification settings - Fork 77
97 lines (88 loc) · 4.27 KB
/
Copy pathred-master.yml
File metadata and controls
97 lines (88 loc) · 4.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
name: Red master
# build.yml and nightly.yml decide whether master is broken. This decides
# whether anyone finds out.
#
# On 2026-08-10 a parser bump missed three of the four POMs. The push build went
# red in the same minute -- the guard worked perfectly -- and master stayed
# broken for 21 hours anyway, through a second failing run, because nobody
# loaded the Actions tab. GitHub's own email goes to the actor and is easy to
# filter into nothing; a red run leaves no trace in any view you visit for
# another reason.
#
# So a failure on master opens an issue, assigns it, and keeps it open until
# every watched workflow is green again -- at which point it closes itself, so
# nobody has to remember to. All the logic is in
# .github/scripts/red-master-issue.sh; this file only feeds it the payload.
on:
workflow_run:
# Must match each workflow's `name:`, and the WATCHED list in the script.
workflows: ["Build and test", "Nightly"]
types: [completed]
# For proving the thing works without breaking master to do it. Defaults to a
# dry run: it performs every read, needs every permission the real path needs,
# and prints the mutations instead of making them.
workflow_dispatch:
inputs:
simulate:
description: "Conclusion to simulate"
type: choice
options: [failure, success]
default: failure
dry_run:
description: "Print what would happen instead of doing it"
type: boolean
default: true
permissions:
contents: read
# Serialised, because the whole design rests on there being exactly one open
# issue. Two watched workflows can finish seconds apart -- the nightly runs
# `pinned` and `latest` together, and a push can land while one is running --
# and two concurrent runs would each look for an open issue, each find none, and
# each open one.
#
# cancel-in-progress is false, and explicitly so: cancelling the earlier run
# would drop a notification about a failure, which is the one thing this
# workflow exists to prevent.
concurrency:
group: red-master
cancel-in-progress: false
jobs:
notify:
name: "Track whether master is red"
runs-on: ubuntu-latest
permissions:
issues: write # the tracking issue
actions: read # reading the other workflows' latest results
contents: read
# A cancelled run says nothing about the code, and a run on a branch or a
# pull request is not master going red. The script re-checks the branch, so
# this is a cheap filter rather than the guarantee.
if: >-
github.event_name == 'workflow_dispatch' ||
((github.event.workflow_run.conclusion == 'success' ||
github.event.workflow_run.conclusion == 'failure') &&
github.event.workflow_run.head_branch == 'master' &&
github.event.workflow_run.event != 'pull_request')
steps:
# Only the scripts are needed, and checking out the workflow_run's commit
# would mean running a script version that a pull request could have
# rewritten. Always the default branch.
- uses: actions/checkout@v4
with:
ref: master
- name: Open, update, or close the tracking issue
# Explicit, for the pipefail: with the default shell, `script | tee`
# would report tee's exit status and swallow a failure in the script.
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
CONCLUSION: ${{ github.event_name == 'workflow_dispatch' && inputs.simulate || github.event.workflow_run.conclusion }}
BRANCH: ${{ github.event_name == 'workflow_dispatch' && 'master' || github.event.workflow_run.head_branch }}
RUN_NAME: ${{ github.event_name == 'workflow_dispatch' && 'a simulated run' || github.event.workflow_run.name }}
RUN_URL: ${{ github.event_name == 'workflow_dispatch' && '' || github.event.workflow_run.html_url }}
RUN_ID: ${{ github.event.workflow_run.id }}
SHA: ${{ github.event_name == 'workflow_dispatch' && github.sha || github.event.workflow_run.head_sha }}
ACTOR: ${{ github.event.workflow_run.actor.login }}
DRY_RUN: ${{ (github.event_name == 'workflow_dispatch' && inputs.dry_run) && '1' || '0' }}
run: .github/scripts/red-master-issue.sh | tee -a "$GITHUB_STEP_SUMMARY"