fix(forge): term-5 GitHub pins for timeline/activity + keep activity stderr (#188)
Some checks failed
CI / test (pull_request) Successful in 1m25s
CI / release-exercise (pull_request) Successful in 9s
CI / self-guards (pull_request) Successful in 5s
CI / action-exercise (pull_request) Successful in 4s
CI / docs-sync-exercise (pull_request) Successful in 4s
labels / labels (pull_request) Failing after 6s

Codex 1566 held APPROVE: only Forgejo stubs covered forge_timeline and
forge_pr_activity. Pin the github twins as 1:1 extractions (timeline
paginate; issue comments + flat pulls comments + commits).

Cluade #4879: drop 2>/dev/null on the labels-reconcile activity call site
so a failed read still degrades last_activity but names the failure in the
job log (keep || true).
This commit is contained in:
grok-reviewer-andresmgsl 2026-08-03 15:26:08 +00:00
parent 5c8e4f5b84
commit ff17d1ea3f
2 changed files with 70 additions and 1 deletions

View file

@ -711,7 +711,10 @@ reconcile_pr() { # $1 = PR number; relies on the globals set from its fetch
{
jq -r '.created_at' <<<"$PR_JSON"
jq -r '.[].submitted_at // empty' <<<"$REVIEWS_JSON"
forge_pr_activity "$n" 2>/dev/null || true
# Non-fatal degrade (pre-#188 same edge), but do NOT swallow stderr —
# forge_api names failures loudly, and hiding them re-opens this issue's
# silent-green class (#4879 / #101 D5).
forge_pr_activity "$n" || true
} | sort | tail -n1
)"
last_activity_epoch="$(date -d "$last_activity" +%s)"

View file

@ -386,6 +386,72 @@ check "...and never routes through issue edit --add-label" 1 "" \
grep -q 'issue edit' "$gh_calls"
check "github request_reviewer posts the reviewer" 0 "" \
grep -q 'api repos/o/r/pulls/9/requested_reviewers -f reviewers\[\]=danmt' "$gh_calls"
# --- term-5 pins for the batch verbs (codex 1566) -------------------------
# The forgejo twins have hermetic coverage below; these pin that the github
# twins stay 1:1 extractions of the pre-port endpoints, not silent rewrites.
: >"$gh_calls"
# shellcheck disable=SC2317 # invoked indirectly, by the github verbs
gh() {
printf '%s\n' "$*" >>"$gh_calls"
if [ "$1" = api ]; then
shift
local jqexpr="" endpoint=""
while [ $# -gt 0 ]; do
case "$1" in
--jq) jqexpr="$2"; shift ;;
--paginate) ;;
-*) ;;
*) [ -n "$endpoint" ] || endpoint="$1" ;;
esac
shift
done
local body='[]'
case "$endpoint" in
*'/issues/'*'/timeline'*)
body='[{"event":"labeled","actor":{"login":"alice"},"label":{"name":"ready"},"created_at":"2026-08-01T09:00:00Z"}]'
;;
*'/issues/'*'/comments'*)
body='[{"created_at":"2026-08-01T10:00:00Z"}]'
;;
*'/pulls/'*'/comments'*)
body='[{"created_at":"2026-08-01T10:30:00Z"}]'
;;
*'/pulls/'*'/commits'*)
body='[{"commit":{"committer":{"date":"2026-08-01T11:00:00Z"}}}]'
;;
esac
if [ -n "$jqexpr" ]; then jq -r "$jqexpr" <<<"$body"; else printf '%s\n' "$body"; fi
return 0
fi
return 0
}
gh_tl="$(
forge_select github
# shellcheck disable=SC2030 # scoping REPO to this subshell is the point
REPO=o/r
forge_timeline 42
)"
check "github forge_timeline paginates the issue timeline endpoint" 0 "" \
grep -qE 'api --paginate repos/o/r/issues/42/timeline|api repos/o/r/issues/42/timeline' "$gh_calls"
check "github forge_timeline is a pass-through of the GitHub event shape" 0 "" \
jq -e '.[0].event == "labeled" and .[0].actor.login == "alice"' <<<"$gh_tl" >/dev/null
: >"$gh_calls"
gh_act="$(
forge_select github
# shellcheck disable=SC2030 # scoping REPO to this subshell is the point
REPO=o/r
forge_pr_activity 9 | sort
)"
check "github forge_pr_activity hits issue comments" 0 "" \
grep -q 'repos/o/r/issues/9/comments' "$gh_calls"
check "github forge_pr_activity hits the flat /pulls/{n}/comments endpoint" 0 "" \
grep -q 'repos/o/r/pulls/9/comments' "$gh_calls"
check "github forge_pr_activity hits commits" 0 "" \
grep -q 'repos/o/r/pulls/9/commits' "$gh_calls"
check "github forge_pr_activity emits all three timestamp sources" 0 "" \
test "$(printf '%s\n' "$gh_act")" = "$(printf '%s\n' '2026-08-01T10:00:00Z' '2026-08-01T10:30:00Z' '2026-08-01T11:00:00Z')"
unset -f gh
. "$ROOT/lib/forge-forgejo.sh"