diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a50e07f6416..9ac4e60e2c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -447,8 +447,8 @@ jobs: bearings_output=$(/bin/bash tests/fm-bearings-snapshot.test.sh) printf '%s\n' "$bearings_output" bearings_count=$(printf '%s\n' "$bearings_output" | grep -c '^ok - ') - [ "$bearings_count" -eq 71 ] || { - echo "::error::expected 71 Bearings tests, got $bearings_count" + [ "$bearings_count" -eq 72 ] || { + echo "::error::expected 72 Bearings tests, got $bearings_count" exit 1 } diff --git a/bin/fm-fleet-snapshot.sh b/bin/fm-fleet-snapshot.sh index 1f0c6f0000d..1f7d6e113f1 100755 --- a/bin/fm-fleet-snapshot.sh +++ b/bin/fm-fleet-snapshot.sh @@ -1983,7 +1983,8 @@ contribution_tasks_json() { if [ "$OUTPUT_MODE" = contribution-input ]; then # Reuse the canonical backlog parser, without observing workers or other homes. contribution_tasks=$(contribution_tasks_json) || { echo "fm-fleet-snapshot: contribution task read failed" >&2; exit 1; } - jq -n --argjson backlog "$BACKLOG_JSON" --argjson tasks "$contribution_tasks" '{backlog:$backlog,tasks:$tasks}' + printf '%s\n' "$BACKLOG_JSON" "$contribution_tasks" | jq -n \ + '[inputs] as [$backlog, $tasks] | {backlog:$backlog,tasks:$tasks}' exit 0 fi prefetch_task_current_states || { echo "fm-fleet-snapshot: task observation failed" >&2; exit 1; } diff --git a/tests/fm-bearings-snapshot.test.sh b/tests/fm-bearings-snapshot.test.sh index 40b991b9d40..febb6811a39 100755 --- a/tests/fm-bearings-snapshot.test.sh +++ b/tests/fm-bearings-snapshot.test.sh @@ -3862,6 +3862,29 @@ test_a_remote_home_without_any_ledger_is_explicitly_unreadable_without_remote_co pass "a missing remote ledger stays explicitly unreadable without remote summary computation" } +test_contribution_input_with_large_backlog() { + local home out + home=$(make_home contribution-large-backlog) + { + printf '## Queued\n' + awk 'BEGIN { for (i = 1; i <= 500; i++) printf "- [ ] queued-%d - Queued contribution %d (repo: sample) (kind: ship)\n", i, i }' + } > "$home/data/backlog.md" + fm_write_meta "$home/state/contribution.meta" "kind=ship" + out=$(FM_HOME="$home" "$ROOT/bin/fm-fleet-snapshot.sh" --contribution-input) \ + || fail 'contribution input failed with a backlog exceeding the exec argument limit' + printf '%s\n' "$out" | jq -e --arg path "$home/data/backlog.md" ' + keys == ["backlog", "tasks"] + and (.backlog | tojson | length) > 131072 + and .backlog.path == $path and .backlog.present == true + and (.backlog.records | length) == 500 + and [.backlog.records[].id] == [range(1;501) | "queued-\(.)"] + and all(.backlog.records[]; .state == "queued" and .kind == "ship") + and .tasks == [{id:"contribution",kind:"ship",pr:{url:"",head:""},merge_authority:"attended"}] + ' >/dev/null || fail 'large contribution input lost backlog records or changed the ownership pair shape' + pass 'contribution input preserves backlog larger than 128 KiB and task ownership' +} + +test_contribution_input_with_large_backlog test_task_teardown_during_metadata_capture_does_not_abort_snapshot test_current_state_uses_captured_status_observation test_relaunched_task_does_not_inherit_reused_endpoint_state