fix: preserve claims linked by open Refs PRs

This commit is contained in:
Andriujose 2026-08-03 15:49:57 +00:00
parent 19ae4aedd1
commit e133924887
3 changed files with 41 additions and 3 deletions

View file

@ -139,6 +139,16 @@ refs_references() { # PR body on stdin -> local issue numbers named by Refs
| awk -F '\t' '$1 == "LOCAL" { print $2 }' | sort -nu
}
open_pr_issues() { # records on stdin: CLOSING|BODY<TAB>value -> issue numbers
local kind value
while IFS=$'\t' read -r kind value; do
case "$kind" in
CLOSING) [ -n "$value" ] && printf '%s\n' "$value" ;;
BODY) refs_references <<<"$value" ;;
esac
done | sort -nu
}
unchecked_criteria() { # issue body on stdin -> unchecked task-list lines verbatim
awk '
/^[[:space:]]*([-*]|[0-9]+\.)[[:space:]]+\[[[:space:]]\]/ {
@ -503,16 +513,22 @@ main() {
fi
owner="${REPO%%/*}"
name="${REPO#*/}"
# crew#321 released a live claim because the open side read only closing
# links while the merged side parsed Refs bodies. One parser now supplies
# the local body references on both sides, so transition and reclaim agree.
OPEN_PR_ISSUES="$(gh api graphql --paginate -f owner="$owner" -f name="$name" -f query='
query($owner: String!, $name: String!, $endCursor: String) {
repository(owner: $owner, name: $name) {
pullRequests(first: 100, states: OPEN, after: $endCursor) {
nodes { closingIssuesReferences(first: 100) { nodes { number } } }
nodes { body closingIssuesReferences(first: 100) { nodes { number } } }
pageInfo { hasNextPage endCursor }
}
}
}' --jq '.data.repository.pullRequests.nodes[].closingIssuesReferences.nodes[].number' \
| sort -nu)"
}' --jq '.data.repository.pullRequests.nodes[]
| (.closingIssuesReferences.nodes[].number
| ["CLOSING", tostring] | @tsv),
((.body // "") | split("\n")[] | ["BODY", .] | @tsv)' \
| open_pr_issues)"
MERGED_REF_PR_RECORDS="$(gh api graphql --paginate -f owner="$owner" -f name="$name" -f query='
query($owner: String!, $name: String!, $endCursor: String) {
repository(owner: $owner, name: $name) {

3
changelog.d/241.md Normal file
View file

@ -0,0 +1,3 @@
### Fixed
- Preserve active claims when an open local pull request links them with `Refs #N`.

View file

@ -95,6 +95,13 @@ check "empty labels do not exempt a claimed issue" 0 "SWEEP" claim_clock_exempt
refs_body=$'Refs #12\nAlso refs: #8 and heavy-duty/rig#4.\nCloses #99\nNot refs-ish #7\nfix refs parsing from #200\nCloses #40; refs: none\nRefs #175 (split from #150)'
check "Refs parser returns only references owned by a valid Refs marker" 0 "" \
test "$(refs_references <<<"$refs_body")" = $'8\n12\n175'
open_records=$'BODY\tRefs #5\nCLOSING\t9\nBODY\tRefs heavy-duty/rig#112\nBODY\tRefs #5\nCLOSING\t5'
check "open PR linkage unions closing and local Refs body references" 0 $'5\n9' \
open_pr_issues <<<"$open_records"
check "cross-repo Refs never enter the local open PR set" 0 "" \
open_pr_issues <<< $'BODY\tRefs heavy-duty/rig#112'
check "an issue named by both linkage paths appears exactly once" 0 "1" \
grep -cxF 5 <<<"$(open_pr_issues <<<"$open_records")"
check "unchecked criteria preserve their source lines verbatim" 0 \
$'- [ ] first criterion\n * [ ] indented criterion\n1. [ ] numbered criterion' \
unchecked_criteria <<< $'- [x] done\n- [ ] first criterion\r\n * [ ] indented criterion\n1. [ ] numbered criterion'
@ -731,6 +738,18 @@ check "...performs no release edit" 1 "" \
grep -qF -- 'issue edit 40 -R owner/repo --remove-assignee builder --remove-label claimed --add-label post-merge' \
"$ARRIVAL/fixtures/edits"
sed 's/"isDraft":false/"isDraft":true/' "$ARRIVAL/fixtures/graphql-open.json" \
>"$ARRIVAL/fixtures/graphql-open.json.tmp"
mv "$ARRIVAL/fixtures/graphql-open.json.tmp" "$ARRIVAL/fixtures/graphql-open.json"
: >"$ARRIVAL/fixtures/edits"
draft_transition_out="$(
env PATH="$ARRIVAL/stub:$PATH" GH_FIXTURES="$ARRIVAL/fixtures" \
REPO=owner/repo LABELS_CONF="$ARRIVAL/labels.conf" \
bash "$ROOT/actions/issueflow-reconcile/issueflow-reconcile.sh" 2>&1
)"
check "a draft Refs-bodied PR suppresses post-merge transition identically" 1 "" \
grep -qF '#40: merged Refs PR -> post-merge; claim released' <<<"$draft_transition_out"
# The same body linkage protects the reclaim clock even when no Refs-linked
# PR has merged. This is the derived half of crew#321's destructive shape.
printf '%s\n' \