diff --git a/actions/issueflow-reconcile/issueflow-reconcile.sh b/actions/issueflow-reconcile/issueflow-reconcile.sh index 672f197..d0b730b 100644 --- a/actions/issueflow-reconcile/issueflow-reconcile.sh +++ b/actions/issueflow-reconcile/issueflow-reconcile.sh @@ -78,9 +78,9 @@ author_decision() { # $1 = true when author is triage; labels on stdin claim_decision() { # $1 assignee count, $2 linked open PR, $3 age seconds local assignees="$1" open_pr="$2" age="$3" - if [ "$assignees" -eq 0 ]; then echo FLAG_UNASSIGNED - elif [ "$open_pr" = true ] || [ "$age" -le "$STALE_AFTER" ]; then echo KEEP - else echo RECLAIM + if [ "$open_pr" = false ] && [ "$age" -gt "$STALE_AFTER" ]; then echo RECLAIM + elif [ "$assignees" -eq 0 ]; then echo FLAG_UNASSIGNED + else echo KEEP fi } @@ -186,8 +186,12 @@ reconcile_issue() { ensure_comment "$n" claim-reclaimed \ 'This claim has no linked open PR and no activity for 48 hours. The sweep is reclaiming it for the ready queue.' owners="$(jq -r '[.assignees[].login] | join(",")' <<<"$ISSUE_JSON")" - run gh issue edit "$n" -R "$REPO" --remove-assignee "$owners" \ - --remove-label claimed --add-label ready >/dev/null + if [ -n "$owners" ]; then + run gh issue edit "$n" -R "$REPO" --remove-assignee "$owners" \ + --remove-label claimed --add-label ready >/dev/null + else + run gh issue edit "$n" -R "$REPO" --remove-label claimed --add-label ready >/dev/null + fi log "#$n: stale claim reclaimed -> ready" ;; esac elif has_issue_label blocked; then diff --git a/test/issueflow-reconcile.test.sh b/test/issueflow-reconcile.test.sh index 0806443..f78aa69 100644 --- a/test/issueflow-reconcile.test.sh +++ b/test/issueflow-reconcile.test.sh @@ -34,6 +34,7 @@ check "claim with open PR stays claimed" 0 "KEEP" claim_decision 1 true 999999 check "recent claim without PR stays claimed" 0 "KEEP" claim_decision 1 false 60 check "unassigned claim is flagged" 0 "FLAG_UNASSIGNED" claim_decision 0 false 60 check "quiet claim without PR is reclaimed" 0 "RECLAIM" claim_decision 1 false $((STALE_AFTER + 1)) +check "quiet unassigned claim is also reclaimed" 0 "RECLAIM" claim_decision 0 false $((STALE_AFTER + 1)) # Invariant 3: blocked declarations parse and release only when all close. refs="$(blocked_references <<< $'Context #99\nBlocked by #12 and #7')" diff --git a/test/labels.test.sh b/test/labels.test.sh index a042f41..af0d4de 100755 --- a/test/labels.test.sh +++ b/test/labels.test.sh @@ -12,6 +12,7 @@ trap 'rm -rf "$TMP"' EXIT printf '%s\n' \ 'panel=one two three' \ + 'triage-actors=triage-one' \ '' \ 'scope:one|C5DEF5|First scope' \ 'scope:two|C5DEF5|Second scope' >"$TMP/good.conf" @@ -25,6 +26,10 @@ check "panel is parsed" 0 "one two three" bash -c \ check "core and config rows merge" 0 "scope:two|C5DEF5|Second scope" bash -c \ 'source "$1"; core_label_rows; configured_label_rows "$2"' _ \ "$ROOT/actions/labels-reconcile/labels-reconcile.sh" "$TMP/good.conf" +# shellcheck disable=SC2016 # expansion belongs to the nested bash +check "triage config is not parsed as a label row" 1 "" bash -c \ + 'source "$1"; configured_label_rows "$2" | grep -F triage-actors' _ \ + "$ROOT/actions/labels-reconcile/labels-reconcile.sh" "$TMP/good.conf" check "missing scope config is an empty table" 0 "" configured_label_rows "$TMP/missing.conf" printf '%s\n' 'scope:bad|C5DEF5' >"$TMP/bad.conf"