-
Notifications
You must be signed in to change notification settings - Fork 1
96 lines (91 loc) · 4.77 KB
/
Copy pathissue-contract-guard.yml
File metadata and controls
96 lines (91 loc) · 4.77 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
# Contract gate for the HUMAN path (#1035).
#
# The agent path is gated inline, as a post-step of triage-dispatch.yml's
# `execute` job: that job creates issues as GITHUB_TOKEN, and GitHub suppresses
# workflow runs for GITHUB_TOKEN-raised events, so an `issues` trigger would
# never fire for them — the exact reason triage-dispatch.yml itself runs on
# workflow_run. This workflow covers what that inline step cannot: a per-cause
# issue a person opens by hand, through .github/ISSUE_TEMPLATE/failure-root-cause.yml
# or otherwise. Those are raised by a user account, so `issues` fires normally.
#
# Reports, never blocks. A malformed issue keeps its evidence and gets a comment
# naming the gaps plus a label; nothing is closed or rejected.
name: Issue Contract Guard
on:
issues:
# `edited` closes the loop: fixing the body re-runs the check, and the guard
# comment is updated in place rather than a new one being appended.
types: [opened, edited]
# Manual entry: run the identical composite action against a chosen issue, or
# over a `since` window, printing the verdict without mutating anything by
# default.
#
# NOTE on what this does and does not buy. GitHub requires a workflow_dispatch
# workflow to exist on the DEFAULT branch before it can be dispatched at all
# (API 404s otherwise), so this could NOT validate the very PR that introduced
# it. What it does buy, from here on: every later change to this guard is
# testable from its own branch (`gh workflow run ... --ref <branch>`), and the
# guard can be re-run on demand against any issue.
#
# `since` exists because the SWEEP path had no on-demand entry at all (#1037).
# That path only ever runs as an inline post-step of triage-dispatch.yml's
# `execute` job, which fires on a human "pode abrir" after a red daily — and in
# the automation's whole lifetime that has happened ZERO times (every
# triage-dispatch run to date is a `propose`). So the one code path documented as
# failing silently by construction was also the only one that could not be
# exercised. Dispatching it here runs the identical composite action, on a real
# runner, against real issues, and prints `Contract guard: N checked, …`.
workflow_dispatch:
inputs:
issue:
description: "Issue number to check. Leave empty when using `since`."
required: false
since:
description: "ISO-8601 timestamp (e.g. 2026-07-30T11:34:00Z) — sweep every daily-failure issue created at or after it. Mutually exclusive with `issue`."
required: false
dry_run:
description: "Print the verdict without commenting or labelling"
type: boolean
default: true
# Only issues: write — this workflow never touches code.
permissions:
issues: write
contents: read
jobs:
guard:
name: Dedicated-issue contract
# Cheap pre-filter on the event path. The action still classifies by title and
# skips the umbrella, but there is no reason to spin a runner for unrelated
# issues. The manual path is gated on a trusted actor instead — without that,
# any collaborator who can dispatch could make the guard comment on an
# arbitrary issue (same guard triage-dispatch.yml puts on its dispatch entry).
if: >-
(github.event_name == 'issues' &&
contains(github.event.issue.labels.*.name, 'daily-failure')) ||
(github.event_name == 'workflow_dispatch' &&
contains(fromJSON('["rafaelgiln","Victor-w-Madeira","daniellicnerski1"]'), github.actor))
runs-on: ubuntu-latest
timeout-minutes: 5
concurrency:
# An edit burst must not race itself into duplicate comments.
# A sweep has no issue number, so it groups by run id instead of collapsing
# every dispatched sweep onto one cancel-in-progress group.
group: issue-contract-guard-${{ github.event.issue.number || inputs.issue || github.run_id }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v7
# The action prefers `issue` when both arrive, which would silently ignore a
# `since` the dispatcher typed. Say so instead — a guard that quietly checks
# something other than what was asked is the class of bug #1037 is about.
- name: Reject an ambiguous dispatch
if: github.event_name == 'workflow_dispatch' && inputs.issue != '' && inputs.since != ''
run: |
echo "::error::pass either issue or since, not both — the action would use issue and ignore since."
exit 1
- uses: ./.github/actions/guard-dedicated-issue
with:
issue: ${{ github.event.issue.number || inputs.issue }}
# Empty on the `issues` path, so single-issue behaviour is unchanged.
since: ${{ inputs.since }}
dry_run: ${{ inputs.dry_run || false }}
github_token: ${{ github.token }}