@biffo/cli 0.243.2 → 0.244.1
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.
|
@@ -53,6 +53,47 @@ cd "$root" || exit 0
|
|
|
53
53
|
# cannot run, that is a reason to stop, not to wave the push through.
|
|
54
54
|
sh scripts/biffo.sh rewrite-scope-check || exit 1
|
|
55
55
|
|
|
56
|
+
# --- Claim guard (#1231 instance 2) -------------------------------------------
|
|
57
|
+
#
|
|
58
|
+
# `scripts/claim.sh` (packaged inside `@biffo/cli`, run through the bridge
|
|
59
|
+
# above) has asked the estate's four-signal question about "is this issue
|
|
60
|
+
# taken?" since #1209 -- but nothing ever RAN it. It shipped advisory-only, so
|
|
61
|
+
# the fix for the collisions it exists to catch was itself subject to the same
|
|
62
|
+
# failure: a collision happens precisely when someone does not think to check.
|
|
63
|
+
#
|
|
64
|
+
# `--guard <branch>` is the enforced form. It derives the issue number from the
|
|
65
|
+
# branch name (`<type>/<number>-slug>`) and, when the branch names one, checks
|
|
66
|
+
# for another remote branch or another OPEN PR naming the same issue -- NEVER
|
|
67
|
+
# the `in-progress` label (three of four real collisions were "work exists,
|
|
68
|
+
# label does not") and NEVER identity (a claim on #1109 was recorded as
|
|
69
|
+
# `github-actions[bot]` because of a repo-local `user.email` override). It
|
|
70
|
+
# excludes the branch being pushed and any PR whose head IS that branch, so
|
|
71
|
+
# pushing your own branch a second time cannot block you on your own work.
|
|
72
|
+
#
|
|
73
|
+
# A branch that names no issue returns before any network call -- most
|
|
74
|
+
# branches are fine, and noise kills a gate. Measured on a branch that DOES
|
|
75
|
+
# name one: the added latency is the cost of two `gh` lookups, similar in
|
|
76
|
+
# order of magnitude to `rewrite-scope-check` above.
|
|
77
|
+
branch=$(git symbolic-ref --quiet --short HEAD) || branch=""
|
|
78
|
+
|
|
79
|
+
if [ -n "$branch" ]; then
|
|
80
|
+
sh scripts/biffo.sh claim --guard "$branch"
|
|
81
|
+
claim_status=$?
|
|
82
|
+
|
|
83
|
+
if [ "$claim_status" -eq 1 ]; then
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# $claim_status -eq 2 is "cannot tell" -- no network, gh unauthenticated, an
|
|
88
|
+
# API error -- and claim.sh has already printed a warning. Deliberately NOT
|
|
89
|
+
# blocked here: unlike every other gate in this file, this is a COORDINATION
|
|
90
|
+
# gate, not a correctness one. A false block costs the ability to push at
|
|
91
|
+
# all; a miss costs a recoverable collision caught early (every collision in
|
|
92
|
+
# #1209's own incident was caught before duplicate work merged). Set
|
|
93
|
+
# BIFFO_CLAIM_STRICT=1 to make claim.sh itself collapse cannot-tell into
|
|
94
|
+
# exit 1 instead, if you would rather block than guess.
|
|
95
|
+
fi
|
|
96
|
+
|
|
56
97
|
# Through the version-pinned CLI since #1109, so a repo cannot run a gate two
|
|
57
98
|
# versions old -- eight of them did, and tabsii-crm checked ONE thing in eight
|
|
58
99
|
# on a 700-line change and printed `verify passed` (#855). There is one copy of
|
|
@@ -2,9 +2,15 @@ name: CI
|
|
|
2
2
|
|
|
3
3
|
# Scaled down from biffo-template's own root .github/workflows/ci.yml for a
|
|
4
4
|
# single Python package: a plugin repo (per ADR-0003) extends the SDK and
|
|
5
|
-
# has no JS/TS
|
|
6
|
-
#
|
|
7
|
-
#
|
|
5
|
+
# has no JS/TS of its own.
|
|
6
|
+
#
|
|
7
|
+
# It DOES have Terraform. This comment used to claim the opposite — "no
|
|
8
|
+
# Terraform of its own; Terraform, if a plugin ships any, is provisioned by the
|
|
9
|
+
# consuming project's infra, not this repo's CI" — while the skeleton beside it
|
|
10
|
+
# shipped a whole `terraform/` module, and that untrue sentence is exactly why
|
|
11
|
+
# nothing checked it (#1244). What the consuming project provisions is the
|
|
12
|
+
# module's *instantiation*; the module's own source lives here, is edited here,
|
|
13
|
+
# and is only ever checked here. See the `terraform` job below.
|
|
8
14
|
|
|
9
15
|
on:
|
|
10
16
|
push:
|
|
@@ -108,6 +114,48 @@ jobs:
|
|
|
108
114
|
run: |
|
|
109
115
|
uv run python -m jsonschema -i biffo.plugin.json registry-schema.json
|
|
110
116
|
|
|
117
|
+
terraform:
|
|
118
|
+
name: Terraform (fmt)
|
|
119
|
+
runs-on: ${{ vars.RUNNER_LABEL || 'ubuntu-latest' }}
|
|
120
|
+
timeout-minutes: 20
|
|
121
|
+
# This repo's `terraform/` module is checked by nothing else (#1244). The
|
|
122
|
+
# skeleton shipped the module and no terraform step at all, so every plugin
|
|
123
|
+
# repo was scaffolded with Terraform that nothing looked at — confirmed live
|
|
124
|
+
# in biffo-plugin-idea-scout: three .tf files, zero terraform references
|
|
125
|
+
# across three workflows.
|
|
126
|
+
#
|
|
127
|
+
# `scripts/verify.sh` cannot substitute for this job, and deliberately does
|
|
128
|
+
# not try: its terraform check is guarded by `ci_has "terraform fmt"` so a
|
|
129
|
+
# template-shipped gate never asserts over more than the repo's own CI does
|
|
130
|
+
# (the #325 trap). A repo whose CI checks nothing therefore, correctly, gets
|
|
131
|
+
# nothing locally either. This job is what switches the local gate on.
|
|
132
|
+
#
|
|
133
|
+
# ## Why there is no `terraform validate` here
|
|
134
|
+
#
|
|
135
|
+
# Not an oversight, and do not "fix" it by adding one. `terraform/main.tf`
|
|
136
|
+
# sets `source = "../../cloud/aws/compute"`, a path relative to the module's
|
|
137
|
+
# INSTALL location (`modules/plugins/<name>/` in the consuming monorepo),
|
|
138
|
+
# not to this repo. `terraform init` in `terraform/` therefore fails with
|
|
139
|
+
#
|
|
140
|
+
# Error: Unreadable module directory
|
|
141
|
+
# Unable to evaluate directory symlink: lstat ../../cloud: no such file
|
|
142
|
+
#
|
|
143
|
+
# before `validate` is ever reached — verified against this skeleton. The
|
|
144
|
+
# module is validated where its paths resolve: by the consuming project's
|
|
145
|
+
# own `infra-validate` job, after `biffo plugin install` has copied it into
|
|
146
|
+
# place. See `terraform/README.md`, which has said so all along.
|
|
147
|
+
#
|
|
148
|
+
# fmt alone is not cosmetic. `terraform fmt -check` parses the HCL, so it
|
|
149
|
+
# exits 2 on an unparseable file and 3 on a merely unformatted one — the
|
|
150
|
+
# "a malformed .tf merges green" hole is closed by this step by itself.
|
|
151
|
+
steps:
|
|
152
|
+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
|
|
153
|
+
- uses: hashicorp/setup-terraform@v4
|
|
154
|
+
with:
|
|
155
|
+
terraform_version: '~> 1.9'
|
|
156
|
+
- name: Terraform fmt check
|
|
157
|
+
run: terraform fmt -check -recursive terraform/
|
|
158
|
+
|
|
111
159
|
security-secrets:
|
|
112
160
|
name: Secret Scan
|
|
113
161
|
runs-on: ${{ vars.RUNNER_LABEL || 'ubuntu-latest' }}
|
|
@@ -53,6 +53,47 @@ cd "$root" || exit 0
|
|
|
53
53
|
# cannot run, that is a reason to stop, not to wave the push through.
|
|
54
54
|
sh scripts/biffo.sh rewrite-scope-check || exit 1
|
|
55
55
|
|
|
56
|
+
# --- Claim guard (#1231 instance 2) -------------------------------------------
|
|
57
|
+
#
|
|
58
|
+
# `scripts/claim.sh` (packaged inside `@biffo/cli`, run through the bridge
|
|
59
|
+
# above) has asked the estate's four-signal question about "is this issue
|
|
60
|
+
# taken?" since #1209 -- but nothing ever RAN it. It shipped advisory-only, so
|
|
61
|
+
# the fix for the collisions it exists to catch was itself subject to the same
|
|
62
|
+
# failure: a collision happens precisely when someone does not think to check.
|
|
63
|
+
#
|
|
64
|
+
# `--guard <branch>` is the enforced form. It derives the issue number from the
|
|
65
|
+
# branch name (`<type>/<number>-slug>`) and, when the branch names one, checks
|
|
66
|
+
# for another remote branch or another OPEN PR naming the same issue -- NEVER
|
|
67
|
+
# the `in-progress` label (three of four real collisions were "work exists,
|
|
68
|
+
# label does not") and NEVER identity (a claim on #1109 was recorded as
|
|
69
|
+
# `github-actions[bot]` because of a repo-local `user.email` override). It
|
|
70
|
+
# excludes the branch being pushed and any PR whose head IS that branch, so
|
|
71
|
+
# pushing your own branch a second time cannot block you on your own work.
|
|
72
|
+
#
|
|
73
|
+
# A branch that names no issue returns before any network call -- most
|
|
74
|
+
# branches are fine, and noise kills a gate. Measured on a branch that DOES
|
|
75
|
+
# name one: the added latency is the cost of two `gh` lookups, similar in
|
|
76
|
+
# order of magnitude to `rewrite-scope-check` above.
|
|
77
|
+
branch=$(git symbolic-ref --quiet --short HEAD) || branch=""
|
|
78
|
+
|
|
79
|
+
if [ -n "$branch" ]; then
|
|
80
|
+
sh scripts/biffo.sh claim --guard "$branch"
|
|
81
|
+
claim_status=$?
|
|
82
|
+
|
|
83
|
+
if [ "$claim_status" -eq 1 ]; then
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
# $claim_status -eq 2 is "cannot tell" -- no network, gh unauthenticated, an
|
|
88
|
+
# API error -- and claim.sh has already printed a warning. Deliberately NOT
|
|
89
|
+
# blocked here: unlike every other gate in this file, this is a COORDINATION
|
|
90
|
+
# gate, not a correctness one. A false block costs the ability to push at
|
|
91
|
+
# all; a miss costs a recoverable collision caught early (every collision in
|
|
92
|
+
# #1209's own incident was caught before duplicate work merged). Set
|
|
93
|
+
# BIFFO_CLAIM_STRICT=1 to make claim.sh itself collapse cannot-tell into
|
|
94
|
+
# exit 1 instead, if you would rather block than guess.
|
|
95
|
+
fi
|
|
96
|
+
|
|
56
97
|
# Through the version-pinned CLI since #1109, so a repo cannot run a gate two
|
|
57
98
|
# versions old -- eight of them did, and tabsii-crm checked ONE thing in eight
|
|
58
99
|
# on a 700-line change and printed `verify passed` (#855). There is one copy of
|
package/package.json
CHANGED
package/scripts/claim.sh
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
# sh scripts/claim.sh 1234 # check, and claim if free
|
|
43
43
|
# sh scripts/claim.sh 1234 --check # report only, change nothing
|
|
44
44
|
# sh scripts/claim.sh 1234 -R owner/repo
|
|
45
|
+
# sh scripts/claim.sh --guard <branch> # pre-push gate — see below
|
|
45
46
|
#
|
|
46
47
|
# 0 free — and claimed, unless --check
|
|
47
48
|
# 1 taken, or already closed — the reason is printed
|
|
@@ -51,15 +52,50 @@
|
|
|
51
52
|
# A check that cannot see its input must not report "free".
|
|
52
53
|
#
|
|
53
54
|
# Requires `gh`, authenticated. Uses gh's embedded jq, so no jq binary needed.
|
|
55
|
+
#
|
|
56
|
+
# ## `--guard <branch>` — the pre-push gate (#1231 instance 2)
|
|
57
|
+
#
|
|
58
|
+
# The four-signal check above is advisory: nothing ever runs it for you, so a
|
|
59
|
+
# collision happens precisely when someone does not think to check. `--guard`
|
|
60
|
+
# is the enforced half, called from `.githooks/pre-push` on every push.
|
|
61
|
+
#
|
|
62
|
+
# It answers a narrower question than the plain form above, on purpose:
|
|
63
|
+
#
|
|
64
|
+
# - **Derives the issue from the branch name.** Pattern `<type>/<number>-…`,
|
|
65
|
+
# e.g. `feat/1234-thing`. A branch that does not name an issue (most of
|
|
66
|
+
# them) is skipped SILENTLY, before any network call — most branches are
|
|
67
|
+
# fine and noise kills a gate.
|
|
68
|
+
# - **Never checks the `in-progress` label.** Of four real collisions in one
|
|
69
|
+
# morning, three were "work exists, label does not" — so a gate keyed on
|
|
70
|
+
# the label would have caught one of four. This checks only what git and
|
|
71
|
+
# GitHub cannot help but know: an open PR, a remote branch.
|
|
72
|
+
# - **Never compares identity.** A claim on #1109 was recorded as
|
|
73
|
+
# `github-actions[bot]` because of a repo-local `user.email` override —
|
|
74
|
+
# usernames are not a trustworthy signal here.
|
|
75
|
+
# - **Excludes the branch being pushed, and any PR whose head IS that
|
|
76
|
+
# branch**, from counting as a conflict. Without this, pushing your own
|
|
77
|
+
# branch a second time blocks you on your own work.
|
|
78
|
+
# - **A real conflict — another branch or another open PR naming the same
|
|
79
|
+
# issue — exits 1**, naming what was found. AGENTS.md permits stealing a
|
|
80
|
+
# claim that is over an hour stale, with a comment; the message points
|
|
81
|
+
# there rather than being a dead end.
|
|
82
|
+
# - **"Cannot tell" (no network, `gh` unauthenticated, an API error) warns
|
|
83
|
+
# and exits 2 — never 1.** By default the caller should treat 2 as a pass:
|
|
84
|
+
# this is a COORDINATION gate, not a correctness one, and a false block
|
|
85
|
+
# costs the ability to push at all while a miss costs a recoverable
|
|
86
|
+
# collision caught early (see "What it cannot do" above). Set
|
|
87
|
+
# `BIFFO_CLAIM_STRICT=1` to make this script itself collapse cannot-tell
|
|
88
|
+
# into exit 1 instead, for anyone who would rather block than guess.
|
|
54
89
|
|
|
55
90
|
set -u
|
|
56
91
|
|
|
57
92
|
ISSUE=""
|
|
58
93
|
REPO=""
|
|
59
94
|
CHECK_ONLY=""
|
|
95
|
+
GUARD_BRANCH=""
|
|
60
96
|
|
|
61
97
|
usage() {
|
|
62
|
-
sed -n '2,
|
|
98
|
+
sed -n '2,84p' "$0" | sed 's/^# \{0,1\}//'
|
|
63
99
|
exit 2
|
|
64
100
|
}
|
|
65
101
|
|
|
@@ -70,6 +106,10 @@ while [ $# -gt 0 ]; do
|
|
|
70
106
|
shift 2
|
|
71
107
|
;;
|
|
72
108
|
--check) CHECK_ONLY=1; shift ;;
|
|
109
|
+
--guard)
|
|
110
|
+
GUARD_BRANCH="${2:-}"
|
|
111
|
+
shift 2
|
|
112
|
+
;;
|
|
73
113
|
-h | --help) usage ;;
|
|
74
114
|
*)
|
|
75
115
|
ISSUE="$1"
|
|
@@ -78,13 +118,6 @@ while [ $# -gt 0 ]; do
|
|
|
78
118
|
esac
|
|
79
119
|
done
|
|
80
120
|
|
|
81
|
-
case "$ISSUE" in
|
|
82
|
-
'' | *[!0-9]*)
|
|
83
|
-
echo "claim: give an issue number, e.g. sh scripts/claim.sh 1234" >&2
|
|
84
|
-
exit 2
|
|
85
|
-
;;
|
|
86
|
-
esac
|
|
87
|
-
|
|
88
121
|
RED=$(printf '\033[31m')
|
|
89
122
|
GREEN=$(printf '\033[32m')
|
|
90
123
|
YELLOW=$(printf '\033[33m')
|
|
@@ -94,12 +127,117 @@ OFF=$(printf '\033[0m')
|
|
|
94
127
|
gh_issue() { if [ -n "$REPO" ]; then gh issue "$@" --repo "$REPO"; else gh issue "$@"; fi; }
|
|
95
128
|
gh_pr() { if [ -n "$REPO" ]; then gh pr "$@" --repo "$REPO"; else gh pr "$@"; fi; }
|
|
96
129
|
|
|
130
|
+
# `git ls-remote --heads ""` fails outright ("fatal: bad repository ''") rather
|
|
131
|
+
# than falling back to the default remote — `${REPO:+url}` expands to an empty
|
|
132
|
+
# STRING ARGUMENT when $REPO is unset, not to no argument at all. That silently
|
|
133
|
+
# broke signal 3 below for every caller that does not pass -R, which is nearly
|
|
134
|
+
# all of them: the branch check never fired, and nothing noticed because the
|
|
135
|
+
# label and open-PR signals usually catch a collision first. Found while
|
|
136
|
+
# building `--guard`, which depends on this signal actually working.
|
|
137
|
+
remote_branches() {
|
|
138
|
+
if [ -n "$REPO" ]; then
|
|
139
|
+
git ls-remote --heads "https://github.com/$REPO.git"
|
|
140
|
+
else
|
|
141
|
+
git ls-remote --heads
|
|
142
|
+
fi
|
|
143
|
+
}
|
|
144
|
+
|
|
97
145
|
LABEL=in-progress
|
|
98
146
|
TAKEN=0
|
|
99
147
|
REASONS=""
|
|
100
148
|
|
|
101
149
|
note() { REASONS="${REASONS} $1\n"; TAKEN=1; }
|
|
102
150
|
|
|
151
|
+
# --- --guard <branch>: the enforced pre-push gate -----------------------------
|
|
152
|
+
#
|
|
153
|
+
# Deliberately short-circuits before any of the four-signal machinery below —
|
|
154
|
+
# it asks two of those four questions, not all four, and answers a different
|
|
155
|
+
# question ("would this push collide with someone else's live work?" rather
|
|
156
|
+
# than "is this issue free to claim?").
|
|
157
|
+
if [ -n "$GUARD_BRANCH" ]; then
|
|
158
|
+
guard_issue=$(printf '%s' "$GUARD_BRANCH" | sed -n 's#^[^/]*/\([0-9][0-9]*\)-.*#\1#p')
|
|
159
|
+
|
|
160
|
+
# No issue named by the branch — most branches, e.g.
|
|
161
|
+
# `security/brace-expansion-5-0-9`. Skip silently, and — this is the point —
|
|
162
|
+
# before touching the network at all.
|
|
163
|
+
if [ -z "$guard_issue" ]; then
|
|
164
|
+
exit 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
cannot_tell=0
|
|
168
|
+
conflict=0
|
|
169
|
+
findings=""
|
|
170
|
+
cannot_tell_reasons=""
|
|
171
|
+
|
|
172
|
+
# --- an open PR referencing the issue, excluding our own branch's PR --------
|
|
173
|
+
pr_err=$(mktemp)
|
|
174
|
+
open_prs=$(gh_pr list --state open --limit 100 --json number,title,body,headRefName \
|
|
175
|
+
--jq "[.[] | select(((.title + \" \" + .body) | test(\"(^|[^0-9])#$guard_issue([^0-9]|\$)\")) or (.headRefName | test(\"(^|[^0-9])$guard_issue([^0-9]|\$)\")))] | .[] | select(.headRefName != \"$GUARD_BRANCH\") | \"#\(.number) \(.headRefName)\"" \
|
|
176
|
+
2>"$pr_err")
|
|
177
|
+
pr_status=$?
|
|
178
|
+
pr_err_text=$(cat "$pr_err")
|
|
179
|
+
rm -f "$pr_err"
|
|
180
|
+
|
|
181
|
+
if [ "$pr_status" -ne 0 ]; then
|
|
182
|
+
cannot_tell=1
|
|
183
|
+
cannot_tell_reasons="${cannot_tell_reasons}${pr_err_text} "
|
|
184
|
+
elif [ -n "$open_prs" ]; then
|
|
185
|
+
conflict=1
|
|
186
|
+
findings="${findings} ${RED}open PR${OFF} $(printf '%s' "$open_prs" | head -1)\n"
|
|
187
|
+
fi
|
|
188
|
+
|
|
189
|
+
# --- a remote branch naming the issue, excluding our own branch -------------
|
|
190
|
+
branch_err=$(mktemp)
|
|
191
|
+
raw_branches=$(remote_branches 2>"$branch_err")
|
|
192
|
+
branch_status=$?
|
|
193
|
+
branch_err_text=$(cat "$branch_err")
|
|
194
|
+
rm -f "$branch_err"
|
|
195
|
+
|
|
196
|
+
if [ "$branch_status" -ne 0 ]; then
|
|
197
|
+
cannot_tell=1
|
|
198
|
+
cannot_tell_reasons="${cannot_tell_reasons}${branch_err_text} "
|
|
199
|
+
else
|
|
200
|
+
other_branch=$(printf '%s\n' "$raw_branches" |
|
|
201
|
+
sed 's|.*refs/heads/||' |
|
|
202
|
+
grep -E "(^|[^0-9])$guard_issue([^0-9]|$)" |
|
|
203
|
+
grep -v -x "$GUARD_BRANCH" | head -1)
|
|
204
|
+
if [ -n "$other_branch" ]; then
|
|
205
|
+
conflict=1
|
|
206
|
+
findings="${findings} ${RED}branch${OFF} $other_branch\n"
|
|
207
|
+
fi
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
if [ "$conflict" -eq 1 ]; then
|
|
211
|
+
printf '%b' "${RED}claim --guard: issue #$guard_issue looks claimed by someone else.${OFF}\n$findings"
|
|
212
|
+
echo
|
|
213
|
+
echo "${DIM}If you believe it is abandoned (no activity for over an hour), AGENTS.md${OFF}"
|
|
214
|
+
echo "${DIM}permits stealing it deliberately — say so in a comment on the issue first,${OFF}"
|
|
215
|
+
echo "${DIM}then push. Never steal a fresh claim.${OFF}"
|
|
216
|
+
exit 1
|
|
217
|
+
fi
|
|
218
|
+
|
|
219
|
+
if [ "$cannot_tell" -eq 1 ]; then
|
|
220
|
+
if [ -n "${BIFFO_CLAIM_STRICT:-}" ]; then
|
|
221
|
+
echo "${RED}claim --guard: cannot tell whether #$guard_issue is claimed elsewhere${OFF} — ${DIM}$cannot_tell_reasons${OFF}" >&2
|
|
222
|
+
echo "${DIM}BIFFO_CLAIM_STRICT=1 is set, so cannot-tell blocks the push.${OFF}" >&2
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
echo "${YELLOW}claim --guard: cannot tell whether #$guard_issue is claimed elsewhere${OFF} — ${DIM}$cannot_tell_reasons${OFF}" >&2
|
|
226
|
+
echo "${DIM}Warning and letting the push through: this is a coordination gate, not a${OFF}" >&2
|
|
227
|
+
echo "${DIM}correctness one. Set BIFFO_CLAIM_STRICT=1 to block instead of guessing.${OFF}" >&2
|
|
228
|
+
exit 2
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
exit 0
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
case "$ISSUE" in
|
|
235
|
+
'' | *[!0-9]*)
|
|
236
|
+
echo "claim: give an issue number, e.g. sh scripts/claim.sh 1234" >&2
|
|
237
|
+
exit 2
|
|
238
|
+
;;
|
|
239
|
+
esac
|
|
240
|
+
|
|
103
241
|
# --- 0. Does the issue exist, and is it still open? --------------------------
|
|
104
242
|
|
|
105
243
|
meta=$(gh_issue view "$ISSUE" --json state,title,labels \
|
|
@@ -150,7 +288,7 @@ fi
|
|
|
150
288
|
#
|
|
151
289
|
# Catches work that has been pushed but has no PR yet. Whole-number match again.
|
|
152
290
|
|
|
153
|
-
branches=$(
|
|
291
|
+
branches=$(remote_branches 2>/dev/null |
|
|
154
292
|
sed 's|.*refs/heads/||' |
|
|
155
293
|
grep -E "(^|[^0-9])$ISSUE([^0-9]|$)" 2>/dev/null)
|
|
156
294
|
|