@feigi/fleet-ctl 3.81.3 → 3.81.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/scripts/reap.sh +31 -27
- package/skills/run-team/references/ci-watcher.md +14 -3
package/package.json
CHANGED
package/scripts/reap.sh
CHANGED
|
@@ -371,10 +371,10 @@ keep() {
|
|
|
371
371
|
# at, by two DIFFERENT rules for two DIFFERENT groups. Three call sites below
|
|
372
372
|
# read `status --porcelain` (`-uall`, or `-unormal --ignored`) and are safe
|
|
373
373
|
# because git quotes PATHS; a fourth, added after this comment was first
|
|
374
|
-
# written, reads `for-each-ref
|
|
375
|
-
#
|
|
376
|
-
#
|
|
377
|
-
# checks either invariant.
|
|
374
|
+
# written, reads `for-each-ref` with a format that prints only refnames and
|
|
375
|
+
# fixed words, and is safe for an unrelated reason — a REFNAME, unlike a
|
|
376
|
+
# path, can never contain the byte at all, and a fixed word is text git
|
|
377
|
+
# itself prints. Nothing in the body checks either invariant.
|
|
378
378
|
#
|
|
379
379
|
# The path-reading three: both halves of git's answer put a control byte in
|
|
380
380
|
# a path beyond reach of the split, by two DIFFERENT rules — measured on git
|
|
@@ -394,13 +394,19 @@ keep() {
|
|
|
394
394
|
# 0x02 there either.
|
|
395
395
|
#
|
|
396
396
|
# The ref-reading fourth: no PATH-quoting rule is doing the work, because no
|
|
397
|
-
# quoting is needed —
|
|
398
|
-
#
|
|
399
|
-
#
|
|
400
|
-
#
|
|
401
|
-
# name
|
|
402
|
-
#
|
|
403
|
-
#
|
|
397
|
+
# quoting is needed — every field its format prints is either a validated
|
|
398
|
+
# refname or a fixed word git prints. git refuses to CREATE a ref whose name
|
|
399
|
+
# holds the byte at all. Measured, git 2.50.1 (Apple Git-155): `git branch
|
|
400
|
+
# "$(printf 'a\002b')"` fails outright — `fatal: 'a?b' is not a valid branch
|
|
401
|
+
# name` — and so does `git update-ref refs/heads/"$(printf 'a\002b')" HEAD`
|
|
402
|
+
# — `refusing to update ref with bad name`. `%(refname)` can only ever
|
|
403
|
+
# answer with bytes that already survived `check-ref-format` on the way in.
|
|
404
|
+
# The other two fields are fixed words: the `%(if)%(upstream)` test prints
|
|
405
|
+
# `upstream` or `no-upstream` out of the format itself, and
|
|
406
|
+
# `%(upstream:track)` prints git's own tracking words — `[gone]`, `[ahead N]`
|
|
407
|
+
# and their siblings. `%(upstream)`'s own text is never printed: it is built
|
|
408
|
+
# from the branch.<b>.merge value, which git does not validate, and a raw
|
|
409
|
+
# 0x02 written there reaches it (measured, git 2.50.1). A fifth call site joins
|
|
404
410
|
# this ref group: `rev-parse --verify refs/heads/<b>`, where
|
|
405
411
|
# `<b>` is a name the `for-each-ref` call site produced. Its stdout is an
|
|
406
412
|
# object id in hex, and what it can put on stderr is git's own fixed prose
|
|
@@ -416,10 +422,10 @@ keep() {
|
|
|
416
422
|
# -uall -z` carries the raw 0x02 straight through, `-z` being the
|
|
417
423
|
# machine-readable form that drops the quoting, and so does any command
|
|
418
424
|
# emitting CONTENT rather than paths or refnames (`log --format=%s`, `show
|
|
419
|
-
# <rev>:<path>`, both measured). The ref group
|
|
420
|
-
#
|
|
421
|
-
# warning is
|
|
422
|
-
# site a future caller might add.
|
|
425
|
+
# <rev>:<path>`, both measured). The ref group stays out of reach only while
|
|
426
|
+
# its format prints no atom built from config, such as `%(upstream)` — so
|
|
427
|
+
# this warning is aimed at the path group, at that format, and at any THIRD
|
|
428
|
+
# kind of call site a future caller might add.
|
|
423
429
|
#
|
|
424
430
|
# Left unguarded anyway, deliberately: every call site is shaped
|
|
425
431
|
# `if ! git_probe …; then keep …`, so a garbled $gp_rc can never come back 0
|
|
@@ -980,13 +986,14 @@ EOF
|
|
|
980
986
|
#
|
|
981
987
|
# The [gone] test reads $3 and the no-upstream test reads $2: a space is not
|
|
982
988
|
# legal in a branch name (measured — git refuses `has space` as invalid), so
|
|
983
|
-
# the name is always the whole of $1
|
|
984
|
-
#
|
|
985
|
-
#
|
|
986
|
-
#
|
|
987
|
-
#
|
|
988
|
-
#
|
|
989
|
-
#
|
|
989
|
+
# the name is always the whole of $1. $2 is a fixed word the format itself
|
|
990
|
+
# prints — `upstream` when the branch has one, `no-upstream` when it has
|
|
991
|
+
# none — so an unset upstream still fills $2 rather than leaving the
|
|
992
|
+
# whitespace split to drop an empty field. $3 is %(upstream:track). The
|
|
993
|
+
# tracking forms that DO carry a space, `[ahead 1]` and its siblings, split
|
|
994
|
+
# so that $3 holds `[ahead` — not `[gone]` either way. No field prints
|
|
995
|
+
# %(upstream)'s own text, which git builds from the unvalidated
|
|
996
|
+
# branch.<b>.merge value.
|
|
990
997
|
# A command substitution inside a `for ... in` word list discards its own
|
|
991
998
|
# exit status entirely, in every shell measured here (bash, dash, macOS
|
|
992
999
|
# /bin/sh): `for x in $(false); do …; done` completes at the loop's own end,
|
|
@@ -1011,10 +1018,7 @@ EOF
|
|
|
1011
1018
|
# the same reason — dying here would also abort the second sweep and the
|
|
1012
1019
|
# final `worktree prune`, neither of which this enumeration failing has
|
|
1013
1020
|
# anything to do with, over a failure that only defers reaping to a later pass.
|
|
1014
|
-
|
|
1015
|
-
# whitespace split drops the empty field, and `$2` reads the track instead, so
|
|
1016
|
-
# `$2=="upstream="` is exactly the no-upstream case and `$3` the [gone] test.
|
|
1017
|
-
if ! git_probe for-each-ref --format='%(refname) upstream=%(upstream) %(upstream:track)' refs/heads; then
|
|
1021
|
+
if ! git_probe for-each-ref --format='%(refname) %(if)%(upstream)%(then)upstream%(else)no-upstream%(end) %(upstream:track)' refs/heads; then
|
|
1018
1022
|
keep "" "could not enumerate [gone] branches — none reaped, and none reported reapable either$(gp_why)"
|
|
1019
1023
|
gone_branches=""
|
|
1020
1024
|
no_upstream=""
|
|
@@ -1032,7 +1036,7 @@ else
|
|
|
1032
1036
|
keep "" "could not enumerate [gone] branches — none reaped, and none reported reapable either"
|
|
1033
1037
|
gone_branches=""
|
|
1034
1038
|
fi
|
|
1035
|
-
if ! no_upstream=$(printf '%s\n' "$gp_out" | awk '$2=="upstream
|
|
1039
|
+
if ! no_upstream=$(printf '%s\n' "$gp_out" | awk '$2=="no-upstream"{sub(/^refs\/heads\//,"",$1); print $1}'); then
|
|
1036
1040
|
keep "" "could not enumerate branches with no upstream — none reported kept"
|
|
1037
1041
|
no_upstream=""
|
|
1038
1042
|
fi
|
|
@@ -47,14 +47,25 @@ bill a second one that `rate_limit` does not report; the boundary is per route,
|
|
|
47
47
|
so `actions/runs/<id>/jobs` is on the reported counter. Every response says
|
|
48
48
|
`X-Ratelimit-Resource: core`, so only the reset epoch and the used sequence tell
|
|
49
49
|
the two apart, and the unreported bucket's remaining count is readable only from
|
|
50
|
-
the `X-Ratelimit-Remaining` header of a call that bills it.
|
|
51
|
-
|
|
50
|
+
the `X-Ratelimit-Remaining` header of a call that bills it. GitHub's REST
|
|
51
|
+
rate-limit documentation does not describe this bucket (it says `core` covers
|
|
52
|
+
"all non-search-related resources in the REST API"), so the gate rests on
|
|
53
|
+
measurement (2026-10-13 and 2026-10-19), not on documentation. **A second pass
|
|
54
|
+
gate therefore probes it too**: one `gh api -i` read of
|
|
52
55
|
`actions/workflows?per_page=1` per tick, 1 unit of that bucket (measured
|
|
53
56
|
2026-10-13: its remaining count fell by 1 per call while `rate_limit` stood
|
|
54
57
|
still, and its reset epoch differed from `rate_limit`'s). A `ci-state` call
|
|
55
58
|
spends 4 units of it on the common path — one `gh run list` and one `gh run view`
|
|
56
59
|
cost 2 each (measured the same day) — so it is held to the same `200 + 4 × count`
|
|
57
|
-
reserve.
|
|
60
|
+
reserve. 4 is the most one call spends on this bucket for a repo with at most 100
|
|
61
|
+
workflows: 0 with no CI, 2 with no run on the PR's head, 4 otherwise. The
|
|
62
|
+
dropped-required-jobs path adds only reported-bucket calls, and the workflow-name
|
|
63
|
+
lookup pages 100 workflows per page, so a repo with more pays more per call. The
|
|
64
|
+
bucket is account-wide, not per repository: probes on three unrelated
|
|
65
|
+
repositories drew one countdown and one reset epoch (measured 2026-10-19), so
|
|
66
|
+
another run on the same token, or any `gh run` use, spends it, and its
|
|
67
|
+
DEGRADED line can fire with few open PRs on this repository. It has its own
|
|
68
|
+
global latch (`hidden_out`) and its DEGRADED and
|
|
58
69
|
RECOVERED lines name it, so a pause on this bucket is not misread as the
|
|
59
70
|
reported budget running low. An unreadable header is an outage here exactly as a
|
|
60
71
|
non-numeric `rate_limit` read is. The probe runs only when the reported-bucket
|