Compare commits

...

4 commits

Author SHA1 Message Date
17a13685a7 Merge pull request 'fix: distinguish Forgejo mergeability states' (#242) from codex-bot-andresmgsl/ceremony:build/236-forgejo-mergeable into main
All checks were successful
CI / test (push) Successful in 3m50s
CI / release-exercise (push) Has been skipped
CI / self-guards (push) Successful in 19s
CI / action-exercise (push) Successful in 18s
CI / docs-sync-exercise (push) Successful in 18s
release / release (push) Successful in 19s
Reviewed-on: #242
Reviewed-by: kimi-bot-andresmgsl <andres+4@heavyduty.builders>
Reviewed-by: glm-bot-andresmgsl <andres+5@heavyduty.builders>
Reviewed-by: claude-bot-andresmgsl <andres+1@heavyduty.builders>
2026-08-23 22:52:09 +00:00
codex-bot-andresmgsl
8f9f7e560f docs: record Forgejo mergeability fix
Some checks failed
CI / test (pull_request) Successful in 3m38s
CI / release-exercise (pull_request) Successful in 24s
CI / self-guards (pull_request) Successful in 20s
CI / action-exercise (pull_request) Successful in 19s
CI / docs-sync-exercise (pull_request) Successful in 19s
labels / labels (pull_request) Failing after 21s
Refs guard / refs-not-closing (pull_request) Has been cancelled
2026-08-23 17:41:41 +00:00
codex-bot-andresmgsl
d3b7984a30 fix: distinguish Forgejo mergeability states
Some checks failed
labels / labels (pull_request) Failing after 20s
CI / test (pull_request) Has been cancelled
CI / release-exercise (pull_request) Has been cancelled
CI / self-guards (pull_request) Has been cancelled
CI / action-exercise (pull_request) Has been cancelled
CI / docs-sync-exercise (pull_request) Has been cancelled
Refs guard / refs-not-closing (pull_request) Has been cancelled
2026-08-23 17:41:10 +00:00
codex-bot-andresmgsl
2029c9f520 test: pin Forgejo mergeability distinctions
Some checks failed
labels / labels (pull_request) Failing after 21s
CI / test (pull_request) Has been cancelled
CI / release-exercise (pull_request) Has been cancelled
CI / self-guards (pull_request) Has been cancelled
CI / action-exercise (pull_request) Has been cancelled
CI / docs-sync-exercise (pull_request) Has been cancelled
Refs guard / refs-not-closing (pull_request) Has been cancelled
2026-08-23 17:40:06 +00:00
3 changed files with 36 additions and 4 deletions

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

@ -0,0 +1,3 @@
### Fixed
- Forgejo drafts and fast-forward conflict-check windows no longer surface as merge conflicts when the API has not distinguished one (#236).

View file

@ -429,9 +429,12 @@ forge_pr_view() {
status="$(forge_api "repos/$REPO/commits/$sha/status")" || return 1 status="$(forge_api "repos/$REPO/commits/$sha/status")" || return 1
jq -n --argjson pr "$pr" --argjson st "$status" ' jq -n --argjson pr "$pr" --argjson st "$status" '
{ {
mergeable: (if $pr.mergeable == true then "MERGEABLE" # Forgejo folds checking, conflict, check error, and WIP into false.
elif $pr.mergeable == false then "CONFLICTING" # Draft must win because WIP makes the boolean carry no merge result (#236).
else "UNKNOWN" end), mergeable: (if $pr.draft == true then "UNKNOWN"
elif $pr.mergeable == true then "MERGEABLE"
elif $pr.merge_base == $pr.base.sha then "UNKNOWN"
else "CONFLICTING" end),
statusCheckRollup: [ statusCheckRollup: [
$st.statuses[]? | { $st.statuses[]? | {
__typename: "StatusContext", __typename: "StatusContext",

View file

@ -599,7 +599,7 @@ pr_view_stub() {
printf 'HTTP/1.1 200 OK\r\nX-Total-Count: 1\r\n\r\n' >"$hdr" printf 'HTTP/1.1 200 OK\r\nX-Total-Count: 1\r\n\r\n' >"$hdr"
case "$url" in case "$url" in
*/status) printf '%s' "$FAKE_STATUS" >"$out" ;; */status) printf '%s' "$FAKE_STATUS" >"$out" ;;
*) printf '{"head":{"sha":"abc"},"mergeable":true}' >"$out" ;; *) printf '%s' "$FAKE_PR" >"$out" ;;
esac esac
return 0 return 0
} }
@ -608,6 +608,7 @@ pr_view_stub() {
FAKE_STATUS='{"state":"failure","statuses":[ FAKE_STATUS='{"state":"failure","statuses":[
{"context":"ci / check","status":"success","created_at":"2026-08-02T10:00:00Z","updated_at":"2026-08-02T10:00:00Z"}, {"context":"ci / check","status":"success","created_at":"2026-08-02T10:00:00Z","updated_at":"2026-08-02T10:00:00Z"},
{"context":"ci / check","status":"failure","created_at":"2026-08-02T09:00:00Z","updated_at":"2026-08-02T09:00:00Z"}]}' {"context":"ci / check","status":"failure","created_at":"2026-08-02T09:00:00Z","updated_at":"2026-08-02T09:00:00Z"}]}'
FAKE_PR='{"head":{"sha":"abc"},"base":{"sha":"base"},"merge_base":"ancestor","draft":false,"mergeable":true}'
pr_view_stub pr_view_stub
view_json="$(REPO=o/r forge_pr_view 5)" view_json="$(REPO=o/r forge_pr_view 5)"
check "pr_view maps createdAt" 0 "" \ check "pr_view maps createdAt" 0 "" \
@ -616,6 +617,31 @@ check "pr_view maps completedAt" 0 "" \
grep -q '"completedAt":' <<<"$view_json" grep -q '"completedAt":' <<<"$view_json"
check "pr_view maps mergeable to the UI string" 0 "" \ check "pr_view maps mergeable to the UI string" 0 "" \
grep -q '"mergeable": "MERGEABLE"' <<<"$view_json" grep -q '"mergeable": "MERGEABLE"' <<<"$view_json"
# Forgejo folds conflict-checking, conflict-check errors, real conflicts, and
# WIP into one false boolean. These fixtures pin the distinctions the API
# object still lets the backend report honestly (#236).
FAKE_PR='{"head":{"sha":"abc"},"base":{"sha":"base"},"merge_base":"ancestor","draft":true,"mergeable":false}'
view_json="$(REPO=o/r forge_pr_view 5)"
check "pr_view reports draft mergeability as unknown" 0 "" \
grep -q '"mergeable": "UNKNOWN"' <<<"$view_json"
FAKE_PR='{"head":{"sha":"abc"},"base":{"sha":"base"},"merge_base":"base","draft":false,"mergeable":false}'
view_json="$(REPO=o/r forge_pr_view 5)"
check "pr_view reports a fast-forward false mergeability as unknown" 0 "" \
grep -q '"mergeable": "UNKNOWN"' <<<"$view_json"
FAKE_PR='{"head":{"sha":"abc"},"base":{"sha":"base"},"merge_base":"ancestor","draft":false,"mergeable":false}'
view_json="$(REPO=o/r forge_pr_view 5)"
check "pr_view preserves a distinguishable real conflict" 0 "" \
grep -q '"mergeable": "CONFLICTING"' <<<"$view_json"
# Unreachable on Forgejo: Mergeable() includes !IsWorkInProgress(). This
# ordering fixture exists only to pin draft ahead of mergeable true (#236).
FAKE_PR='{"head":{"sha":"abc"},"base":{"sha":"base"},"merge_base":"ancestor","draft":true,"mergeable":true}'
view_json="$(REPO=o/r forge_pr_view 5)"
check "pr_view reads draft before the mergeable boolean" 0 "" \
grep -q '"mergeable": "UNKNOWN"' <<<"$view_json"
# The real proof: feed it to the production classifier and confirm the newer # The real proof: feed it to the production classifier and confirm the newer
# SUCCESS wins over the older FAILURE regardless of array order. # SUCCESS wins over the older FAILURE regardless of array order.
# shellcheck source=actions/labels-reconcile/labels-reconcile.sh # shellcheck source=actions/labels-reconcile/labels-reconcile.sh