Merge pull request #300 from cndgrr/build/267-labeler-scope
fix(labels): the scope map locates again — changelog.d/** is every PR
This commit is contained in:
commit
b2a3e43ae4
3 changed files with 113 additions and 2 deletions
28
.github/labeler.yml
vendored
28
.github/labeler.yml
vendored
|
|
@ -7,6 +7,18 @@
|
||||||
# these globs implement. Scopes locate, they do not alert — a path that maps
|
# these globs implement. Scopes locate, they do not alert — a path that maps
|
||||||
# to nothing is fine (the mapping is advisory), so these rows chase the big
|
# to nothing is fine (the mapping is advisory), so these rows chase the big
|
||||||
# surfaces, not every file.
|
# surfaces, not every file.
|
||||||
|
#
|
||||||
|
# A row that matches everything is worse than a missing one: it costs the
|
||||||
|
# same silence and adds a wrong answer. `changelog.d/**` sat under
|
||||||
|
# scope:release-flow until #267 measured it — the last 20 PRs (#197–#263)
|
||||||
|
# all carried scope:release-flow and 3 of them touched a release surface,
|
||||||
|
# because BUILDER.md makes every behavior change write a fragment, so the
|
||||||
|
# glob was "any PR that changes behavior" by doctrine. CHANGELOG.md stays:
|
||||||
|
# the same doctrine forbids editing it for an entry, so only the release PR
|
||||||
|
# does. The other rows #267 added — the issueflow reconciler, the three
|
||||||
|
# unmapped guard actions, RELEASES.md, README (which this tree spells
|
||||||
|
# README.md, so the old glob could match nothing) — are the same read of the
|
||||||
|
# same file, gaps rather than wrong answers.
|
||||||
scope:release-flow:
|
scope:release-flow:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
|
|
@ -18,7 +30,6 @@ scope:release-flow:
|
||||||
- bin/**
|
- bin/**
|
||||||
- VERSION
|
- VERSION
|
||||||
- CHANGELOG.md
|
- CHANGELOG.md
|
||||||
- changelog.d/**
|
|
||||||
- drills/**
|
- drills/**
|
||||||
- test/decide.test.sh
|
- test/decide.test.sh
|
||||||
- test/facts.test.sh
|
- test/facts.test.sh
|
||||||
|
|
@ -30,14 +41,20 @@ scope:guards:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- actions/changelog-armed/**
|
- actions/changelog-armed/**
|
||||||
|
- actions/changelog-assembled/**
|
||||||
- actions/changelog-monotonic/**
|
- actions/changelog-monotonic/**
|
||||||
|
- actions/docs-sync/**
|
||||||
- actions/drill-recorded/**
|
- actions/drill-recorded/**
|
||||||
- actions/refs-not-closing/**
|
- actions/refs-not-closing/**
|
||||||
|
- actions/runner-isolated/**
|
||||||
- .github/workflows/refs-guard.yml
|
- .github/workflows/refs-guard.yml
|
||||||
- test/changelog-armed.test.sh
|
- test/changelog-armed.test.sh
|
||||||
|
- test/changelog-assembled.test.sh
|
||||||
- test/changelog-monotonic.test.sh
|
- test/changelog-monotonic.test.sh
|
||||||
|
- test/docs-sync.test.sh
|
||||||
- test/drill-recorded.test.sh
|
- test/drill-recorded.test.sh
|
||||||
- test/refs-not-closing.test.sh
|
- test/refs-not-closing.test.sh
|
||||||
|
- test/runner-isolated.test.sh
|
||||||
scope:labels:
|
scope:labels:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
|
|
@ -45,19 +62,26 @@ scope:labels:
|
||||||
- .github/workflows/self-labels.yml
|
- .github/workflows/self-labels.yml
|
||||||
- .github/labeler.yml
|
- .github/labeler.yml
|
||||||
- .github/labels.conf
|
- .github/labels.conf
|
||||||
|
- actions/issueflow-reconcile/**
|
||||||
- actions/labels-reconcile/**
|
- actions/labels-reconcile/**
|
||||||
- actions/labels-scope/**
|
- actions/labels-scope/**
|
||||||
|
# shared by both reconcilers; lib/** keeps scope:release-flow too,
|
||||||
|
# and a mixed file honestly wears both labels (#267 D4)
|
||||||
|
- lib/read.sh
|
||||||
|
- lib/ruling.sh
|
||||||
- LABELS.md
|
- LABELS.md
|
||||||
|
- test/issueflow-reconcile.test.sh
|
||||||
- test/labels.test.sh
|
- test/labels.test.sh
|
||||||
- test/labels-reconcile.test.sh
|
- test/labels-reconcile.test.sh
|
||||||
- test/labels-scope.test.sh
|
- test/labels-scope.test.sh
|
||||||
scope:docs:
|
scope:docs:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- README
|
- README.md
|
||||||
- docs/**
|
- docs/**
|
||||||
- AGENTS.md
|
- AGENTS.md
|
||||||
- BUILDER.md
|
- BUILDER.md
|
||||||
|
- RELEASES.md
|
||||||
- REVIEWER.md
|
- REVIEWER.md
|
||||||
- TRIAGE.md
|
- TRIAGE.md
|
||||||
- CONTRIBUTING.md
|
- CONTRIBUTING.md
|
||||||
|
|
|
||||||
19
changelog.d/267.md
Normal file
19
changelog.d/267.md
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- `scope:release-flow` no longer rides every pull request: `changelog.d/**`
|
||||||
|
is out of its path map. Doctrine makes every behavior change write a
|
||||||
|
fragment, so the glob labelled 20 of the last 20 PRs while 3 touched a
|
||||||
|
release surface. `CHANGELOG.md` stays, as only the release PR edits it
|
||||||
|
(#267).
|
||||||
|
- The issue-flow reconciler and its test now derive `scope:labels`, the scope
|
||||||
|
that already names the taxonomy they reconcile (#267).
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `README.md` and `RELEASES.md` derive `scope:docs`, and the
|
||||||
|
`changelog-assembled`, `docs-sync` and `runner-isolated` actions and tests
|
||||||
|
derive `scope:guards`; all five were mapped nowhere. The docs block matched
|
||||||
|
a literal `README`, which this tree does not carry (#267).
|
||||||
|
- `lib/read.sh` and `lib/ruling.sh` derive `scope:labels` beside
|
||||||
|
`scope:release-flow`. Both reconcilers share them, and a mixed file wears
|
||||||
|
both labels rather than `lib/**` being re-carved into a row per file (#267).
|
||||||
|
|
@ -107,6 +107,74 @@ EOF
|
||||||
check "derive: the real mapping labels this test file" 0 \
|
check "derive: the real mapping labels this test file" 0 \
|
||||||
"scope:labels" derive_labels "$real_rows" 'test/labels-scope.test.sh'
|
"scope:labels" derive_labels "$real_rows" 'test/labels-scope.test.sh'
|
||||||
|
|
||||||
|
# --- the real mapping locates: one file set in, the whole label set out ---
|
||||||
|
# #267 measured the old map at 100% recall / 15% precision — 20 of the last
|
||||||
|
# 20 PRs wore scope:release-flow and 3 touched a release surface — so these
|
||||||
|
# cases assert the DERIVED SET WHOLE, brackets and all. A substring check
|
||||||
|
# cannot tell scope:labels from scope:labels plus a wrong second label, and
|
||||||
|
# a wrong second label is the whole defect.
|
||||||
|
derives() { # <newline-separated paths> → "[label,label]" for the real map
|
||||||
|
printf '[%s]\n' "$(derive_labels "$real_rows" "$1" | paste -sd, -)"
|
||||||
|
}
|
||||||
|
files() { printf '%s\n' "$@"; }
|
||||||
|
|
||||||
|
# D1: a fragment is written by every behavior change (BUILDER.md), so it
|
||||||
|
# carries no locating information. Asserted as an empty set on its own, not
|
||||||
|
# as an absence inside a longer list: this is the case that fails first if
|
||||||
|
# the glob is ever restored.
|
||||||
|
check "derive: a fragment-only path derives nothing at all" 0 \
|
||||||
|
"[]" derives 'changelog.d/999.md'
|
||||||
|
|
||||||
|
# D2: the issue-flow sweep is a reconciler of the label taxonomy
|
||||||
|
check "derive: the issueflow reconciler is scope:labels" 0 \
|
||||||
|
"[scope:labels]" derives 'actions/issueflow-reconcile/issueflow-reconcile.sh'
|
||||||
|
check "derive: the issueflow reconciler's test is scope:labels" 0 \
|
||||||
|
"[scope:labels]" derives 'test/issueflow-reconcile.test.sh'
|
||||||
|
|
||||||
|
# the reported bug, replayed: #261's exact file set wore scope:release-flow,
|
||||||
|
# inherited from its fragment, pointing at the one surface it does not touch
|
||||||
|
check "derive: #261's file set is scope:labels alone" 0 "[scope:labels]" \
|
||||||
|
derives "$(files actions/issueflow-reconcile/issueflow-reconcile.sh \
|
||||||
|
changelog.d/252.md test/issueflow-reconcile.test.sh)"
|
||||||
|
|
||||||
|
# D1's cost, checked rather than assumed: dropping the fragment glob must
|
||||||
|
# not cost the release surface its label
|
||||||
|
check "derive: a release PR is still scope:release-flow" 0 \
|
||||||
|
"[scope:release-flow]" \
|
||||||
|
derives "$(files VERSION CHANGELOG.md drills/0.6.0.md changelog.d/236.md)"
|
||||||
|
|
||||||
|
# D3: the docs block matched a literal README this tree does not have
|
||||||
|
check "derive: README.md is scope:docs" 0 "[scope:docs]" derives 'README.md'
|
||||||
|
check "derive: RELEASES.md is scope:docs" 0 "[scope:docs]" derives 'RELEASES.md'
|
||||||
|
check "derive: TRIAGE.md is scope:docs" 0 "[scope:docs]" derives 'TRIAGE.md'
|
||||||
|
|
||||||
|
# D3: three guard actions and their tests were in no block at all. Each of
|
||||||
|
# the six paths is asserted ALONE, never bundled with its sibling: a set
|
||||||
|
# holding both the action and its test derives scope:guards when either row
|
||||||
|
# matches, so one row could be deleted with the case still green — the six
|
||||||
|
# rows have to be six assertions to be six protections (#300 round).
|
||||||
|
for guard in changelog-assembled docs-sync runner-isolated; do
|
||||||
|
check "derive: actions/$guard is scope:guards" 0 "[scope:guards]" \
|
||||||
|
derives "actions/$guard/$guard.sh"
|
||||||
|
check "derive: $guard's test is scope:guards" 0 "[scope:guards]" \
|
||||||
|
derives "test/$guard.test.sh"
|
||||||
|
done
|
||||||
|
|
||||||
|
# D4: lib/ is genuinely mixed, so the shared files wear both labels rather
|
||||||
|
# than lib/** being re-carved into a row per file
|
||||||
|
check "derive: lib/ruling.sh is release-flow AND labels" 0 \
|
||||||
|
"[scope:release-flow,scope:labels]" derives 'lib/ruling.sh'
|
||||||
|
check "derive: lib/read.sh is release-flow AND labels" 0 \
|
||||||
|
"[scope:release-flow,scope:labels]" derives 'lib/read.sh'
|
||||||
|
check "derive: lib/version.sh is release-flow only" 0 \
|
||||||
|
"[scope:release-flow]" derives 'lib/version.sh'
|
||||||
|
|
||||||
|
# D6: the map stays advisory. An unmapped path derives an empty set and
|
||||||
|
# exits 0 — a guard that redded here would fail every PR touching FLEET.md
|
||||||
|
# or ci.yml, neither of which this map claims.
|
||||||
|
check "derive: an unmapped path is silence, not an error" 0 "[]" \
|
||||||
|
derives "$(files FLEET.md .github/workflows/ci.yml)"
|
||||||
|
|
||||||
# refusals: unsupported shapes fail loudly, naming the label
|
# refusals: unsupported shapes fail loudly, naming the label
|
||||||
cat >"$TMP/allglobs.yml" <<'EOF'
|
cat >"$TMP/allglobs.yml" <<'EOF'
|
||||||
scope:x:
|
scope:x:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue