Skip to content

Commit 89a1c58

Browse files
committed
ci: derive the covered set from the matrix, fix the header sim, assert schedule
Three fixes from review on b13d801. The uncovered warning still named the kinds, which is the one place a stale list misleads a person rather than a job: adding a fourth kind would have had it report an example as "not built or booted" while the new job was building and booting it — a false claim in the only signal a reviewer has, since the per-example job names vanish when the matrix is filtered. It now derives the covered set from the file, and the selector publishes one kind-agnostic `selected` output that examples-verified consumes instead of binding image/zip/stream a third time. The simulated commit header now uses the entry's own prefix, and stays deliberately pessimistic: it assumes the `(deps)` scope and a three-digit update count. That is why it reads longer than the 137 the comment cites, which was measured without the scope. The report argued for dropping the scope as too strict; I kept it, because being wrong in the strict direction costs a shortened group name while being wrong in the lax direction costs a red Commit Lint on a pull request nobody wrote — which is the whole reason the assertion exists — and every Dependabot pull request in this repository is titled `chore(deps): ...`, so the scope is what Dependabot infers here. It still leaves 9 characters of headroom at the longest directory configured today, so the pessimism costs nothing. schedule.interval is now asserted. It is required for an updates entry and its absence is the worst copy-paste failure available: Dependabot rejects the whole file, so all 47 groups stop applying at once. Asserted outside the is_example gate, since an invalid root cargo or github-actions entry invalidates the file just the same. Exercised: `selected` on all four selector paths; a fourth matrix kind honoured by both the warning and `selected`; the gate reporting from the single output and still exiting 1 on a failure; a missing schedule on an example and on github-actions.
1 parent b13d801 commit 89a1c58

3 files changed

Lines changed: 46 additions & 13 deletions

File tree

.github/scripts/check-example-config.sh

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ for update in config["updates"]:
159159
)
160160
configured.add(key)
161161
162+
# schedule.interval is required for an updates entry, and its absence is the worst of
163+
# the copy-paste failures: Dependabot rejects the whole file, so all 47 groups stop
164+
# applying at once and every example reverts to one pull request per advisory. Asserted
165+
# for every entry, not just examples — an invalid root cargo or github-actions entry
166+
# invalidates the file just the same.
167+
if not (update.get("schedule") or {}).get("interval"):
168+
problems.append(f"{where}: needs `schedule.interval`; without it Dependabot "
169+
"rejects the whole config and none of the grouping applies.")
170+
162171
# The two grouping assertions below apply to example entries only. Everything else in
163172
# this script is scoped to examples/ — `found` comes from `git ls-files examples`, the
164173
# stale check filters on the prefix — and applying them to the root cargo and
@@ -186,6 +195,8 @@ for update in config["updates"]:
186195
problems.append(f"{where}: needs `open-pull-requests-limit: 0`, or version "
187196
"updates come back on for it.")
188197
198+
prefix = (update.get("commit-message") or {}).get("prefix")
199+
189200
# `patterns` is the other half of the grouping claim: a group with
190201
# patterns: ["lodash"] satisfies the applies-to assertion above while leaving every
191202
# other advisory for that example ungrouped, which is the state this file exists to
@@ -206,8 +217,20 @@ for update in config["updates"]:
206217
# that, so the next example could reintroduce it — headroom is 11 characters
207218
# at the longest directory configured today.
208219
for directory in directories:
209-
header = (f"chore(deps): bump the {group_name} group in {directory} "
210-
"with 5 updates")
220+
# Built from this entry's own prefix, and deliberately pessimistic in two
221+
# ways: it assumes the `(deps)` scope and a three-digit update count.
222+
#
223+
# The scope is why this reads 6 characters longer than the 137 the comment
224+
# above cites, which was measured without it. Dependabot infers a
225+
# conventional-commit scope from history — every existing Dependabot pull
226+
# request here is titled `chore(deps): ...` — and an explicit prefix
227+
# without `include: scope` should drop it, but being wrong in the strict
228+
# direction costs a shortened group name, while being wrong in the lax
229+
# direction costs a red Commit Lint on a pull request nobody wrote, weeks
230+
# later. That is the whole point of this assertion. It still leaves 9
231+
# characters of headroom at the longest directory configured today.
232+
header = (f"{prefix or 'chore'}(deps): bump the {group_name} group in "
233+
f"{directory} with 100 updates")
211234
if len(header) > COMMITLINT_HEADER_MAX:
212235
problems.append(
213236
f"{where}: group {group_name!r} makes a "
@@ -226,7 +249,6 @@ for update in config["updates"]:
226249
# list comes back empty and the assertion falls back to "a prefix is set", which is
227250
# the part that matters; a wrong-but-present prefix would then be caught by Commit
228251
# Lint on the pull request that adds the entry.
229-
prefix = (update.get("commit-message") or {}).get("prefix")
230252
if not prefix:
231253
problems.append(f"{where}: needs `commit-message.prefix`, or Commit Lint rejects "
232254
"the header Dependabot generates.")

.github/scripts/select-examples.sh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ fi
4646
# jobs would run and die in fromJSON('') with an error unrelated to the real cause.
4747
emit_all() {
4848
local kind matrix
49+
echo "selected=$(jq -r '[.[][] | .name] | sort | join(", ")' "$MATRIX")" >>"$GITHUB_OUTPUT"
4950
for kind in "${KINDS[@]}"; do
5051
# `has` rather than a bare `.$kind`: jq prints the literal `null` and exits 0 for a
5152
# missing key, so a renamed top-level key in the matrix file wrote `stream=null`,
@@ -127,6 +128,7 @@ if [[ -z "$example_paths" ]]; then
127128
for kind in "${KINDS[@]}"; do
128129
echo "$kind=[]" >>"$GITHUB_OUTPUT"
129130
done
131+
echo "selected=" >>"$GITHUB_OUTPUT"
130132
exit 0
131133
fi
132134

@@ -139,8 +141,12 @@ echo "Changed examples: $names"
139141
# say it out loud: a reviewer reading one green aggregate check cannot otherwise tell
140142
# that the bump they are approving was never launched, because the per-example job names
141143
# disappear when the matrix is filtered.
144+
# `.[][]` rather than naming the kinds: this is the reviewer's only signal that a bump
145+
# was not built or booted, so a stale kind list here would claim an example is unverified
146+
# while a new job is in fact verifying it — a false statement in the one place someone
147+
# reads. Same reason KINDS is derived above.
142148
uncovered="$(jq -r --argjson names "$names" \
143-
'([.image, .zip, .stream] | flatten | map(.name)) as $covered
149+
'[.[][] | .name] as $covered
144150
| [$names[] | select(IN($covered[]) | not)] | join(", ")' "$MATRIX")"
145151
if [[ -n "$uncovered" ]]; then
146152
echo "::warning::No matrix entry builds or boots: $uncovered — this run verifies templates only for them."
@@ -150,6 +156,13 @@ if [[ -n "$uncovered" ]]; then
150156
fi
151157
fi
152158

159+
# One kind-agnostic list of what was selected, so examples-verified can report it without
160+
# binding the kinds a third time.
161+
selected="$(jq -r --argjson names "$names" \
162+
'[.[][] | .name] as $covered | [$names[] | select(IN($covered[]))] | sort | join(", ")' \
163+
"$MATRIX")"
164+
echo "selected=$selected" >>"$GITHUB_OUTPUT"
165+
153166
for kind in "${KINDS[@]}"; do
154167
# Same has() assertion as emit_all: without it a renamed top-level key fails here with
155168
# jq's bare "Cannot iterate over null", naming neither the file nor the key, while the

.github/workflows/examples.yaml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ jobs:
6868
image: ${{ steps.filter.outputs.image }}
6969
zip: ${{ steps.filter.outputs.zip }}
7070
stream: ${{ steps.filter.outputs.stream }}
71+
# Every selected example name, kind-agnostic, so examples-verified can say what it
72+
# verified without binding each kind again.
73+
selected: ${{ steps.filter.outputs.selected }}
7174
steps:
7275
- uses: actions/checkout@v4
7376
with:
@@ -453,9 +456,7 @@ jobs:
453456
- name: Check the verification results
454457
env:
455458
RESULTS: ${{ join(needs.*.result, ' ') }}
456-
IMAGE: ${{ needs.select.outputs.image }}
457-
ZIP: ${{ needs.select.outputs.zip }}
458-
STREAM: ${{ needs.select.outputs.stream }}
459+
SELECTED: ${{ needs.select.outputs.selected }}
459460
run: |
460461
echo "job results: $RESULTS"
461462
for result in $RESULTS; do
@@ -473,12 +474,9 @@ jobs:
473474
# arrive here green having built and booted nothing. Say which it was, because a
474475
# reviewer reading this one check has nothing else to go on — the per-example job
475476
# names vanish when the matrix is filtered, which is why this job exists.
476-
verified=$(jq -rn \
477-
--argjson image "${IMAGE:-[]}" --argjson zip "${ZIP:-[]}" --argjson stream "${STREAM:-[]}" \
478-
'[$image, $zip, $stream] | flatten | map(.name) | unique | join(", ")')
479-
if [[ -n "$verified" ]]; then
480-
echo "Built and booted: $verified"
481-
echo "**Verified:** $verified" >>"$GITHUB_STEP_SUMMARY"
477+
if [[ -n "${SELECTED:-}" ]]; then
478+
echo "Built and booted: $SELECTED"
479+
echo "**Verified:** $SELECTED" >>"$GITHUB_STEP_SUMMARY"
482480
else
483481
echo "No example was built or booted; this run verified templates only."
484482
echo "**No example was built or booted** — template validation only." \

0 commit comments

Comments
 (0)