Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,32 @@ admission remains enabled. Same-repository Dependabot updates to existing action
SHA pins can enter automatically after full immutable workflow blobs prove that
only pins and version comments changed. Runtime code, permissions, renamed or
new workflows, and other automation changes still require deliberate admission.
A package repository can opt in to dispatched source-PR result reporting with
`package-source-checks`, a JSON object mapping each configured workflow filename
to its required job names. Include every protected context exactly once and
include `dco.yml` with `DCO sign-off`. Keep this map aligned with branch protection.
The source adapter accepts only open, non-draft, same-repository PRs from the
GitHub Actions bot on `automation/package-updates-<package>` branches. It proves
one actual parent on protected default-branch history, changes limited to the
selected `pkgs/by-name/<prefix>/<package>/` directory and `docs/catalog.md`, and
workflow blobs identical to current protected main. It executes no PR code.

Source statuses link actual successful required jobs only after every configured
workflow and required job passes on the exact source SHA. A blocked approval run
can be ignored only when its jobs endpoint proves zero jobs. Failed, pending,
skipped, missing, stale and untrusted evidence never becomes success; newer
attempts invalidate older source adapter results. Actual failed required jobs
receive failure statuses linking the current failed job. Normal required checks and
expected-head merge-queue admission still apply. Unchanged completed runs reuse
only this bot's previously verified job attestations for the same run and attempt;
latest-run metadata remains live. Immutable Git objects and workflow identity are
cached only within one reconciliation. Opted-in callers should also reconcile
`workflow_run` requested and in-progress events to invalidate rerun results early.
These events inspect only their exact source head; initial events without prior
results do not poll validation, and unrelated scans skip already-admitted heads.
Keep hourly scheduled recovery for missed events. This opt-in adds no token
permissions and leaves existing synthetic queue result reporting unchanged.

Set `base-sha-workflows: '["ci.yml"]'` for a workflow that declares a `base_sha`
dispatch input. This supplies the queue commit's first parent for derivation
comparison without teaching the shared library repository names.
Expand Down
26 changes: 24 additions & 2 deletions actions/reconcile-queue/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ inputs:
automation-branch:
description: Optional same-repository github-actions bot branch eligible for admission.
default: ''
package-source-checks:
description: Opt-in JSON workflow-to-required-job map for same-repository package updater source PRs.
default: '{}'
base-sha-workflows:
description: JSON array of workflows accepting the base_sha dispatch input.
default: '[]'
Expand All @@ -19,10 +22,13 @@ runs:
- name: Validate queue inputs
shell: bash
env:
PACKAGE_SOURCE_CHECKS: ${{ inputs.package-source-checks }}
AUTOMATION_BRANCH: ${{ inputs.automation-branch }}
BASE_SHA_WORKFLOWS: ${{ inputs.base-sha-workflows }}
QUEUE_WORKFLOWS: ${{ inputs.workflows }}
SOURCE_RUN_ID: ${{ inputs.source-run-id }}
SOURCE_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
SOURCE_ACTIVITY: ${{ github.event.action }}
run: |
set -euo pipefail
if [[ -n "$SOURCE_RUN_ID" && ! "$SOURCE_RUN_ID" =~ ^[0-9]+$ ]]; then
Expand All @@ -33,19 +39,32 @@ runs:
printf 'Invalid automation-branch input: %s\n' "$AUTOMATION_BRANCH" >&2
exit 1
fi
python3 - "$QUEUE_WORKFLOWS" "$BASE_SHA_WORKFLOWS" <<'PY'
python3 - "$QUEUE_WORKFLOWS" "$BASE_SHA_WORKFLOWS" "$PACKAGE_SOURCE_CHECKS" <<'PY'
import json
import re
import sys

workflow_pattern = re.compile(r"^[A-Za-z0-9._/-]+\.yml$")
for label, value in zip(("workflows", "base-sha-workflows"), sys.argv[1:]):
for label, value in zip(("workflows", "base-sha-workflows"), sys.argv[1:3]):
entries = json.loads(value)
if not isinstance(entries, list) or not all(
isinstance(entry, str) and workflow_pattern.fullmatch(entry)
for entry in entries
):
raise SystemExit(f"Invalid {label} input")
source = json.loads(sys.argv[3])
if not isinstance(source, dict) or any(
not workflow_pattern.fullmatch(key) or not isinstance(jobs, list) or not jobs
or any(not isinstance(job, str) or not job or len(job) > 256 for job in jobs)
or len(jobs) != len(set(jobs))
for key, jobs in source.items()
):
raise SystemExit("Invalid package-source-checks input")
contexts = [job for jobs in source.values() for job in jobs]
if len(contexts) != len(set(contexts)):
raise SystemExit("Source required job names must be unique")
if source and (set(source) != set(json.loads(sys.argv[1])) or "DCO sign-off" not in source.get("dco.yml", [])):
raise SystemExit("Source checks must cover every workflow, including actual source DCO")
PY
- name: Set up queue validation Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7
Expand All @@ -66,8 +85,11 @@ runs:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
PACKAGE_SOURCE_CHECKS: ${{ inputs.package-source-checks }}
AUTOMATION_BRANCH: ${{ inputs.automation-branch }}
BASE_SHA_WORKFLOWS: ${{ inputs.base-sha-workflows }}
QUEUE_WORKFLOWS: ${{ inputs.workflows }}
SOURCE_RUN_ID: ${{ inputs.source-run-id }}
SOURCE_HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
SOURCE_ACTIVITY: ${{ github.event.action }}
run: python3 "$ACTION_PATH/../../scripts/reconcile-queue.py"
41 changes: 41 additions & 0 deletions docs/releases/v2.11.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Nix Forge CI v2.11.0

## Changelog

- Add opt-in reporting and normal queue admission for verified package source PRs
whose explicitly dispatched validation is missing from GitHub's PR rollup.
- Prove the exact GitHub Actions bot identity, same-repository package branch,
actual parent ancestry, selected package/catalog paths, and current protected
workflow blobs before trusting source validation. The reconciler executes no PR code.
- Report actual failed required jobs with their exact job URLs. Missing, running,
skipped, stale, or untrusted evidence never becomes success. Producer changes
during collection or publication invalidate old results and refuse admission.
- Reuse verified unchanged-run attestations and cache only immutable Git data and
stable workflow identity within one reconciliation. Latest-run state remains
live; exact-head events avoid polling unrelated source PRs.

Existing callers keep source reporting disabled and retain their current queue
behavior. Update general shared references coherently to the v2.11.0 release
commit. Repository checks and SLSA builders retain separately reviewed pins.
The package caller opts in through `package-source-checks`, mapping every
configured workflow to all of its protected required job names, including actual
source `DCO sign-off`. Add `requested`, `in_progress`, and `completed` workflow-run
notifications and retain hourly scheduled recovery. Regenerate existing source
branches from reviewed protected main so their workflow blobs match the caller.

The change adds no token permissions and passes no privileged token to PR builds.
Expected-head queue admission and full merge-group validation remain required.
Regression coverage includes source identity and ownership, workflow drift,
approval runs with zero jobs, actual job run/attempt provenance, failure URLs,
producer races, stale-result invalidation, and six-PR request budgets. All 133
repository tests and offline workflow/security checks passed locally; required
hosted PR and merge-group validation and representative caller checks must pass
before the release tag is published.

The functional source was reviewed at
`dc803bb28ea7ae9f2c576d2d03bb78a7f497e72b`. The signed tag and release manifest identify
the final reviewed source commit including these notes. Publication uses
`nix-forge/ci/.github/workflows/release.yml`, which verifies the archive checksum,
all provenance subjects, exact pinned builder identity, and protected-main tag
ancestry. Restore the v2.10.0 pin and remove the source opt-in for rollback.
No support end date is scheduled for compatible v2.x consumers.
Loading
Loading