Skip to content

Commit 1b8862e

Browse files
jasperboerhofclaude
andcommitted
style(ci): make announce-pr.yml pass oxfmt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8c2015b commit 1b8862e

1 file changed

Lines changed: 123 additions & 123 deletions

File tree

.github/workflows/announce-pr.yml

Lines changed: 123 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -26,130 +26,130 @@ name: town-crier producer (announce + resolve + consensus)
2626
permissions: {}
2727

2828
on:
29-
pull_request:
30-
# labeled -> first announce; synchronize -> re-announce each new commit (re-review on push);
31-
# unlabeled/closed -> resolve (de-announce). A synchronize on an unlabelled PR is ignored by the if.
32-
types: [labeled, synchronize, unlabeled, closed]
33-
pull_request_review:
34-
# submitted -> a review landed; the consensus job checks whether 2 independent approvals now agree.
35-
types: [submitted]
29+
pull_request:
30+
# labeled -> first announce; synchronize -> re-announce each new commit (re-review on push);
31+
# unlabeled/closed -> resolve (de-announce). A synchronize on an unlabelled PR is ignored by the if.
32+
types: [labeled, synchronize, unlabeled, closed]
33+
pull_request_review:
34+
# submitted -> a review landed; the consensus job checks whether 2 independent approvals now agree.
35+
types: [submitted]
3636

3737
jobs:
38-
announce:
39-
if: >-
40-
(github.event.action == 'labeled' && github.event.label.name == 'Agent Review Requested') ||
41-
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'Agent Review Requested'))
42-
runs-on: ubuntu-latest
43-
steps:
44-
- name: Announce to the crier
45-
env:
46-
CRIER_URL: ${{ vars.TOWN_CRIER_URL }}
47-
CRIER_TOKEN: ${{ secrets.TOWN_CRIER_TOKEN }}
48-
PR_URL: ${{ github.event.pull_request.html_url }}
49-
REPO: ${{ github.repository }}
50-
TITLE: ${{ github.event.pull_request.title }}
51-
REQUESTER: ${{ github.event.pull_request.user.login }}
52-
# The head SHA is the change detector: a re-announce with the same head is a no-op on the
53-
# bus; a new head reopens the thread for a fresh review round.
54-
HEAD_OID: ${{ github.event.pull_request.head.sha }}
55-
run: |
56-
# Missing provisioning is a config error — fail LOUD so it can't pass silently.
57-
if [ -z "$CRIER_URL" ] || [ -z "$CRIER_TOKEN" ]; then
58-
echo "::error::town-crier not provisioned — set the TOWN_CRIER_URL variable + TOWN_CRIER_TOKEN secret"
59-
exit 1
60-
fi
61-
# jq builds the JSON so a PR title with quotes can't break the payload.
62-
# A bus hiccup is not the PR's fault — degrade to a warning, keep the check green.
63-
curl -fsS --max-time 10 -X POST "$CRIER_URL/announce" \
64-
-H "Authorization: Bearer $CRIER_TOKEN" \
65-
-H "Content-Type: application/json" \
66-
-d "$(jq -n \
67-
--arg pr "$PR_URL" \
68-
--arg repo "$REPO" \
69-
--arg title "$TITLE" \
70-
--arg requester "$REQUESTER" \
71-
--arg head_oid "$HEAD_OID" \
72-
'{pr_url:$pr, repo:$repo, title:$title, requester:$requester, head_oid:$head_oid}')" \
73-
|| echo "::warning::town-crier announce failed (transient bus issue?) — not blocking the PR"
38+
announce:
39+
if: >-
40+
(github.event.action == 'labeled' && github.event.label.name == 'Agent Review Requested') ||
41+
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'Agent Review Requested'))
42+
runs-on: ubuntu-latest
43+
steps:
44+
- name: Announce to the crier
45+
env:
46+
CRIER_URL: ${{ vars.TOWN_CRIER_URL }}
47+
CRIER_TOKEN: ${{ secrets.TOWN_CRIER_TOKEN }}
48+
PR_URL: ${{ github.event.pull_request.html_url }}
49+
REPO: ${{ github.repository }}
50+
TITLE: ${{ github.event.pull_request.title }}
51+
REQUESTER: ${{ github.event.pull_request.user.login }}
52+
# The head SHA is the change detector: a re-announce with the same head is a no-op on the
53+
# bus; a new head reopens the thread for a fresh review round.
54+
HEAD_OID: ${{ github.event.pull_request.head.sha }}
55+
run: |
56+
# Missing provisioning is a config error — fail LOUD so it can't pass silently.
57+
if [ -z "$CRIER_URL" ] || [ -z "$CRIER_TOKEN" ]; then
58+
echo "::error::town-crier not provisioned — set the TOWN_CRIER_URL variable + TOWN_CRIER_TOKEN secret"
59+
exit 1
60+
fi
61+
# jq builds the JSON so a PR title with quotes can't break the payload.
62+
# A bus hiccup is not the PR's fault — degrade to a warning, keep the check green.
63+
curl -fsS --max-time 10 -X POST "$CRIER_URL/announce" \
64+
-H "Authorization: Bearer $CRIER_TOKEN" \
65+
-H "Content-Type: application/json" \
66+
-d "$(jq -n \
67+
--arg pr "$PR_URL" \
68+
--arg repo "$REPO" \
69+
--arg title "$TITLE" \
70+
--arg requester "$REQUESTER" \
71+
--arg head_oid "$HEAD_OID" \
72+
'{pr_url:$pr, repo:$repo, title:$title, requester:$requester, head_oid:$head_oid}')" \
73+
|| echo "::warning::town-crier announce failed (transient bus issue?) — not blocking the PR"
7474
75-
resolve:
76-
if: (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'Agent Review Requested')) || (github.event.action == 'unlabeled' && github.event.label.name == 'Agent Review Requested')
77-
runs-on: ubuntu-latest
78-
steps:
79-
- name: Resolve on the crier
80-
env:
81-
CRIER_URL: ${{ vars.TOWN_CRIER_URL }}
82-
CRIER_TOKEN: ${{ secrets.TOWN_CRIER_TOKEN }}
83-
PR_URL: ${{ github.event.pull_request.html_url }}
84-
ACTION: ${{ github.event.action }}
85-
MERGED: ${{ github.event.pull_request.merged }}
86-
run: |
87-
if [ -z "$CRIER_URL" ] || [ -z "$CRIER_TOKEN" ]; then
88-
echo "::error::town-crier not provisioned — set the TOWN_CRIER_URL variable + TOWN_CRIER_TOKEN secret"
89-
exit 1
90-
fi
91-
if [ "$ACTION" = "unlabeled" ]; then
92-
NOTE="review label removed"
93-
elif [ "$MERGED" = "true" ]; then
94-
NOTE="merged"
95-
else
96-
NOTE="closed without merge"
97-
fi
98-
curl -fsS --max-time 10 -X POST "$CRIER_URL/resolve" \
99-
-H "Authorization: Bearer $CRIER_TOKEN" \
100-
-H "Content-Type: application/json" \
101-
-d "$(jq -n --arg pr "$PR_URL" --arg note "$NOTE" '{pr_url:$pr, note:$note}')" \
102-
|| echo "::warning::town-crier resolve failed (transient bus issue?) — not blocking the PR"
75+
resolve:
76+
if: (github.event.action == 'closed' && contains(github.event.pull_request.labels.*.name, 'Agent Review Requested')) || (github.event.action == 'unlabeled' && github.event.label.name == 'Agent Review Requested')
77+
runs-on: ubuntu-latest
78+
steps:
79+
- name: Resolve on the crier
80+
env:
81+
CRIER_URL: ${{ vars.TOWN_CRIER_URL }}
82+
CRIER_TOKEN: ${{ secrets.TOWN_CRIER_TOKEN }}
83+
PR_URL: ${{ github.event.pull_request.html_url }}
84+
ACTION: ${{ github.event.action }}
85+
MERGED: ${{ github.event.pull_request.merged }}
86+
run: |
87+
if [ -z "$CRIER_URL" ] || [ -z "$CRIER_TOKEN" ]; then
88+
echo "::error::town-crier not provisioned — set the TOWN_CRIER_URL variable + TOWN_CRIER_TOKEN secret"
89+
exit 1
90+
fi
91+
if [ "$ACTION" = "unlabeled" ]; then
92+
NOTE="review label removed"
93+
elif [ "$MERGED" = "true" ]; then
94+
NOTE="merged"
95+
else
96+
NOTE="closed without merge"
97+
fi
98+
curl -fsS --max-time 10 -X POST "$CRIER_URL/resolve" \
99+
-H "Authorization: Bearer $CRIER_TOKEN" \
100+
-H "Content-Type: application/json" \
101+
-d "$(jq -n --arg pr "$PR_URL" --arg note "$NOTE" '{pr_url:$pr, note:$note}')" \
102+
|| echo "::warning::town-crier resolve failed (transient bus issue?) — not blocking the PR"
103103
104-
consensus:
105-
# A review landed — if it's an approval on a labelled PR, retire the bus thread once TWO independent
106-
# approvals agree with no outstanding change request. We read the live count (filtered to the current
107-
# head, so stale approvals can't satisfy consensus) rather than tracking it on the bus.
108-
if: >-
109-
github.event.review.state == 'approved' &&
110-
contains(github.event.pull_request.labels.*.name, 'Agent Review Requested')
111-
runs-on: ubuntu-latest
112-
permissions:
113-
pull-requests: read # read the PR's reviews to count approvals (GITHUB_TOKEN, this job only)
114-
steps:
115-
- name: Resolve on consensus
116-
env:
117-
CRIER_URL: ${{ vars.TOWN_CRIER_URL }}
118-
CRIER_TOKEN: ${{ secrets.TOWN_CRIER_TOKEN }}
119-
GH_TOKEN: ${{ github.token }}
120-
REPO: ${{ github.repository }}
121-
PR_NUMBER: ${{ github.event.pull_request.number }}
122-
PR_URL: ${{ github.event.pull_request.html_url }}
123-
HEAD_OID: ${{ github.event.pull_request.head.sha }}
124-
run: |
125-
if [ -z "$CRIER_URL" ] || [ -z "$CRIER_TOKEN" ]; then
126-
echo "::error::town-crier not provisioned — set the TOWN_CRIER_URL variable + TOWN_CRIER_TOKEN secret"
127-
exit 1
128-
fi
129-
# Tally the LATEST opinionated review per reviewer (ignore COMMENTED/PENDING), counting an
130-
# approval ONLY if it was cast at the CURRENT head — a stale approval from an earlier push must
131-
# not satisfy consensus on a reopened thread (correct regardless of dismiss_stale_reviews).
132-
# NDJSON via --paginate --jq '.[]' then slurp with jq -s — avoids `gh api --slurp` (newer-gh only).
133-
tally="$(gh api --paginate "repos/$REPO/pulls/$PR_NUMBER/reviews" --jq '.[]' \
134-
| jq -s --arg head "$HEAD_OID" '
135-
map(select(.state == "APPROVED" or .state == "CHANGES_REQUESTED" or .state == "DISMISSED"))
136-
| group_by(.user.login) | map(max_by(.submitted_at))
137-
| {approved: (map(select(.state == "APPROVED" and .commit_id == $head)) | length),
138-
changes: (map(select(.state == "CHANGES_REQUESTED")) | length),
139-
who: (map(select(.state == "APPROVED" and .commit_id == $head)) | map(.user.login) | join(", "))}' \
140-
)" || { echo "::warning::could not read PR reviews (transient?) — not blocking the PR"; exit 0; }
141-
approved="$(printf '%s' "$tally" | jq -r '.approved')"
142-
changes="$(printf '%s' "$tally" | jq -r '.changes')"
143-
who="$(printf '%s' "$tally" | jq -r '.who')"
144-
echo "approvals=$approved changes_requested=$changes approvers=[$who]"
145-
# Consensus = >= 2 distinct CURRENT-HEAD approvals AND no outstanding change request.
146-
if [ "${approved:-0}" -lt 2 ] || [ "${changes:-0}" -ne 0 ]; then
147-
echo "no consensus yet — leaving the thread open for another turn"
148-
exit 0
149-
fi
150-
NOTE="consensus: ${approved} approvals (${who}) @${HEAD_OID:0:12}"
151-
curl -fsS --max-time 10 -X POST "$CRIER_URL/resolve" \
152-
-H "Authorization: Bearer $CRIER_TOKEN" \
153-
-H "Content-Type: application/json" \
154-
-d "$(jq -n --arg pr "$PR_URL" --arg note "$NOTE" '{pr_url:$pr, note:$note}')" \
155-
|| echo "::warning::town-crier consensus-resolve failed (transient bus issue?) — not blocking the PR"
104+
consensus:
105+
# A review landed — if it's an approval on a labelled PR, retire the bus thread once TWO independent
106+
# approvals agree with no outstanding change request. We read the live count (filtered to the current
107+
# head, so stale approvals can't satisfy consensus) rather than tracking it on the bus.
108+
if: >-
109+
github.event.review.state == 'approved' &&
110+
contains(github.event.pull_request.labels.*.name, 'Agent Review Requested')
111+
runs-on: ubuntu-latest
112+
permissions:
113+
pull-requests: read # read the PR's reviews to count approvals (GITHUB_TOKEN, this job only)
114+
steps:
115+
- name: Resolve on consensus
116+
env:
117+
CRIER_URL: ${{ vars.TOWN_CRIER_URL }}
118+
CRIER_TOKEN: ${{ secrets.TOWN_CRIER_TOKEN }}
119+
GH_TOKEN: ${{ github.token }}
120+
REPO: ${{ github.repository }}
121+
PR_NUMBER: ${{ github.event.pull_request.number }}
122+
PR_URL: ${{ github.event.pull_request.html_url }}
123+
HEAD_OID: ${{ github.event.pull_request.head.sha }}
124+
run: |
125+
if [ -z "$CRIER_URL" ] || [ -z "$CRIER_TOKEN" ]; then
126+
echo "::error::town-crier not provisioned — set the TOWN_CRIER_URL variable + TOWN_CRIER_TOKEN secret"
127+
exit 1
128+
fi
129+
# Tally the LATEST opinionated review per reviewer (ignore COMMENTED/PENDING), counting an
130+
# approval ONLY if it was cast at the CURRENT head — a stale approval from an earlier push must
131+
# not satisfy consensus on a reopened thread (correct regardless of dismiss_stale_reviews).
132+
# NDJSON via --paginate --jq '.[]' then slurp with jq -s — avoids `gh api --slurp` (newer-gh only).
133+
tally="$(gh api --paginate "repos/$REPO/pulls/$PR_NUMBER/reviews" --jq '.[]' \
134+
| jq -s --arg head "$HEAD_OID" '
135+
map(select(.state == "APPROVED" or .state == "CHANGES_REQUESTED" or .state == "DISMISSED"))
136+
| group_by(.user.login) | map(max_by(.submitted_at))
137+
| {approved: (map(select(.state == "APPROVED" and .commit_id == $head)) | length),
138+
changes: (map(select(.state == "CHANGES_REQUESTED")) | length),
139+
who: (map(select(.state == "APPROVED" and .commit_id == $head)) | map(.user.login) | join(", "))}' \
140+
)" || { echo "::warning::could not read PR reviews (transient?) — not blocking the PR"; exit 0; }
141+
approved="$(printf '%s' "$tally" | jq -r '.approved')"
142+
changes="$(printf '%s' "$tally" | jq -r '.changes')"
143+
who="$(printf '%s' "$tally" | jq -r '.who')"
144+
echo "approvals=$approved changes_requested=$changes approvers=[$who]"
145+
# Consensus = >= 2 distinct CURRENT-HEAD approvals AND no outstanding change request.
146+
if [ "${approved:-0}" -lt 2 ] || [ "${changes:-0}" -ne 0 ]; then
147+
echo "no consensus yet — leaving the thread open for another turn"
148+
exit 0
149+
fi
150+
NOTE="consensus: ${approved} approvals (${who}) @${HEAD_OID:0:12}"
151+
curl -fsS --max-time 10 -X POST "$CRIER_URL/resolve" \
152+
-H "Authorization: Bearer $CRIER_TOKEN" \
153+
-H "Content-Type: application/json" \
154+
-d "$(jq -n --arg pr "$PR_URL" --arg note "$NOTE" '{pr_url:$pr, note:$note}')" \
155+
|| echo "::warning::town-crier consensus-resolve failed (transient bus issue?) — not blocking the PR"

0 commit comments

Comments
 (0)