Skip to content
Merged
2 changes: 1 addition & 1 deletion .github/workflows/reconcile-merge-queue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
github.event_name != 'workflow_run' ||
contains(fromJSON('["pull_request", "merge_group"]'), github.event.workflow_run.event)
runs-on: ubuntu-24.04
timeout-minutes: 5
timeout-minutes: 15
permissions:
checks: read # Read validation evidence for the queued commit.
actions: write # Dispatch trusted queue validation.
Expand Down
6 changes: 3 additions & 3 deletions actions/queue-completion/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ runs:
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
SOURCE_ACTIVITY: ${{ inputs.source-activity }}
run: |
args=(-f source_run_id="$GITHUB_RUN_ID")
args=(-f ref="$DEFAULT_BRANCH" -f "inputs[source_run_id]=$GITHUB_RUN_ID")
case "$SOURCE_ACTIVITY" in
'') ;;
in_progress|completed)
args+=(-f source_run_attempt="$GITHUB_RUN_ATTEMPT" -f source_activity="$SOURCE_ACTIVITY") ;;
args+=(-f "inputs[source_run_attempt]=$GITHUB_RUN_ATTEMPT" -f "inputs[source_activity]=$SOURCE_ACTIVITY") ;;
*) echo '::error::Invalid package-source notification phase'; exit 1 ;;
esac
for attempt in 1 2 3; do
if gh workflow run reconcile-merge-queue.yml --ref "$DEFAULT_BRANCH" "${args[@]}"; then
if gh api "repos/$GH_REPO/actions/workflows/reconcile-merge-queue.yml/dispatches" --method POST "${args[@]}"; then
exit 0
fi
echo "::warning::Queue completion notification attempt $attempt failed"
Expand Down
53 changes: 53 additions & 0 deletions docs/releases/v2.13.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Nix Forge CI v2.13.0

## Changelog

- Reconcile all eligible package-source heads on a completion notification.
This recovers ready heads when workflow concurrency replaces a pending callback.
- Read current PR identity, source refs and latest statuses in a GraphQL batch.
Use a bounded native check-suite projection to defer healthy partial producers
and recognize unchanged already-admitted results without writes.
- Preserve full immutable source, workflow, current-run and actual-job proofs
for every new result or admission. Real failures retain their actual job URLs
when another producer is running or absent. Changed attempts invalidate old
source results. Truncated, missing and approval-only projections take the
complete validation path.
- Replace callback workflow-name lookup with one direct dispatch request.
Preserve legacy queue callback inputs and bounded visible notification retries.
- Pace opted-in package reconciliation content writes four seconds apart,
including status, enqueue and validation dispatch requests. Package-source
callers must allow 15 minutes in their own reconciler jobs for a paced
six-head sweep.

A finite six-package fixture executes the actual reconciler for source
notifications and all 30 queue completion callbacks. It preserves all 19 queue
results and includes notification and candidate-dispatch requests. That fixture
uses 831 REST requests. A separate 99-request source-inspection allowance brings
the normal automation-layer accounting model to 930 requests. Live read-only
GraphQL queries for the PR snapshot and six distinct native source heads each
cost one point.

GitHub's standard repository token allows
[1,000 REST requests per hour](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api).
Updater publication, native validation tools, repeated reruns and delayed
producer completion consume additional requests. Completion callbacks retain
their bounded wait when the producer is still running. The six native queue
candidates execute serially, so these measured calls need not share one hour.
These counts do not guarantee capacity for arbitrary bursts. The production
rollout must verify the current single-package update through native validation
and the protected queue.

Existing source start notifications remain asynchronous. They do not acknowledge
that the reconciler has completed its status writes. Source completion
notifications remain blocking after all actual validation jobs.

No token permissions or required native job gates change. The independently
reviewed release-builder and repository-checks pins remain separate. Consumers
without package-source reconciliation retain their existing callback contract.

The 192 repository regression tests passed locally. Required hosted validation
and the protected normal merge queue must pass before publication. The signed
tag and verified release manifest identify the protected source commit.
Publication verifies the archive checksum and all release provenance subjects
against the separately pinned SLSA builder. Restore the previous reviewed v2.x
pin to roll back. Compatible v2.x consumers have no scheduled support end date.
Loading
Loading