This repository has been archived on 2026-11-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
qqq-orb/docs/consumer-enrollment.md
2026-10-21 20:27:54 -05:00

8.5 KiB

Batch consumer enrollment

Use one target file for canonical consumers of every supported Circle profile and legacy QBits whose jobs and publication filters the shared converter recognizes:

[
  {"checkout": "/work/qbit-example", "default_branch": "main"},
  {"checkout": "/work/qqq", "default_branch": "develop"}
]

The branch values must come from repository inventory. Run on clean isolated checkouts of the branches being migrated.

python tools/enroll_consumers.py targets.json --orb-version 0.8
python tools/enroll_consumers.py targets.json --orb-version 0.8 --write

The command validates the entire batch before writing. Existing manifests keep all publication and profile options; only the managed orb version changes. Recognized legacy QBits receive the canonical caller and inferred publication policy. An unknown job, filter, profile option, duplicate target, symlink, or concurrent declaration edit rejects the batch. Repeating a completed enrollment makes no changes. Filesystem errors during the write phase can leave a partial batch; rerun after correcting the error. This is not a filesystem transaction.

Only .circleci/config.yml and .qqq-ci.yml are changed. The tool does not delete other workflows, infer publication from repository names, or enroll unknown custom pipelines. Their behavior must first be represented by a central profile. After committing and qualifying the exact source, apply the shared branch enforcement tool to supported gate profiles.

This command provides batch source conversion. Use the coordinator below for remote signed submissions. Local conversion alone does not prove fleet deployment or release success.

Remote signed submissions

Supply observed current branches, without cloning each repository yourself:

[
  {"repository": "QRun-IO/qbit-example", "branch": "main"},
  {"repository": "QRun-IO/qqq", "branch": "develop"}
]
python tools/reconcile_enrollment.py --targets remote-targets.json --orb-version 0.8 --output plan.json
python tools/reconcile_enrollment.py --targets remote-targets.json --orb-version 0.8 --output result.json --apply

Use existing gh authentication with repository write access. The coordinator never installs credentials or changes authentication. Every target is inspected at an immutable head and validated before any remote mutation. No repository clone, SSH key or local signing key is required. A moved target stops submission; refresh the plan instead of overwriting it.

An automation branch derives from the source commit and proposed declarations. The coordinator creates the branch at the observed base and uses GitHub's createCommitOnBranch API with expectedHeadOid for an atomic append. GitHub signs the commit when supported by the authenticated identity; the coordinator requires remote signature verification, exact parent, changed paths and declaration bytes before opening a PR. It never force-updates a branch. An interrupted branch creation, commit or PR creation can be resumed: an existing branch still at the planned base receives the missing commit; matching signed branches and PRs are reused. A mismatched branch is rejected. Closed existing PRs are reported as existing; they are not silently reopened. Reports include repository, branch, immutable head and submission URL, without embedding declaration contents or credentials. Keep the report if a later target fails; earlier valid submissions remain intact.

API permission, signature or commit-conflict failures stop the run. A timeout can occur after GitHub accepted a mutation, so inspect remote state or repeat the same invocation; do not create a different automation branch to retry. See GitHub commit API documentation.

This handles remote target lists and signed submissions. Organization discovery is described below. Qualification-aware merging and classic branch enforcement are described below; scheduling and ruleset reconciliation remain separate work. A submitted PR is not a completed migration. Unknown profiles and native workflows require their own central conversion, not deletion by this tool.

Organization discovery

The coordinator can select observed current branches directly from GitHub:

python tools/reconcile_enrollment.py --organization QRun-IO --orb-version 0.8 --output organization-plan.json
python tools/reconcile_enrollment.py --organization QRun-IO --orb-version 0.8 --output organization-result.json --apply

Repository and branch inventories are paginated. Only existing main/develop branches are considered; historical release branches are excluded. Archived repositories and the orb's own bootstrap repository are reported separately. Each supported branch receives the same immutable preflight as explicit targets. Unknown workflows, missing entrypoints, unsupported branch layouts and unavailable APIs stay unresolved in the output. They are never counted as conforming or silently converted. No-CI and native-only repositories may therefore appear as unresolved here; use the estate auditor for their separate policy classification.

Discovery finishes before any submission. --apply processes qualified plans and retains unresolved entries for follow-up; one unsupported repository does not prevent independent valid submissions. An explicit --targets batch keeps its stricter behavior: any preflight failure stops the whole batch. By default neither mode merges PRs or changes branch protections. Use the explicit completion flags below.

Qualification and enforcement

python tools/reconcile_enrollment.py --targets remote-targets.json --orb-version 0.8 --output result.json --apply --merge-ready --enforce

Both flags require --apply and are optional. --merge-ready revalidates the signed submission, exact parent/files/content and current base, requires successful CircleCI-app setup and verify checks and every advertised latest check/status, then requests a normal exact-head squash merge. It never uses admin override or force pushes. The resulting signed merge must have the qualified source tree. Pending/failed checks and changed bases are reported without merging. Repeated runs can advance the same PR once checks complete; there is no polling loop that holds a CI executor open.

--enforce independently checks the actual current target branch, which must pass its own orb gates before shared classic protection enforcement. Existing protections and other required checks are preserved. Supported gate profiles are QBit, Core, frontend-core, frontend-material and repository-policy. Other profiles remain explicitly unsupported for completion even when source enrollment works. Existing active repository rulesets with app-bound gates and no bypass actors are verified without writes. Unsupported or incomplete rulesets remain unresolved; none are rewritten or layered with classic protection. API/plan restrictions remain visible.

A merged source update and an enforced branch are separate reported outcomes. Neither proves artifact publication or deployment. Scheduling and ruleset reconciliation remain outstanding.

Central hosted pass

The orb owner's CircleCI config accepts run_enrollment_reconcile: true on main. This selects one small Python container instead of the normal orb build/publication workflow. It uses the existing qqq-maven-registry-credentials context's GitHub token through gh. No consumer-specific runner configuration or local signing key is needed.

tools/run_enrollment.py verifies the owner repository and main branch, runs organization discovery, signed enrollment, qualified merging and enforcement, then exits. The pass has a 20-minute execution limit. Pending checks are reported for the next pass rather than polled while a paid executor waits. Incremental results and execution status are retained under artifacts/enrollment, including when execution fails or times out. A completed pass does not mean every repository conforms: unresolved and waiting entries remain explicit follow-up work.

Create a single daily CircleCI schedule for the owner project only after a manual main-branch pass verifies its hosted credentials and results. Set branch: main and run_enrollment_reconcile: true in the schedule parameters. Scheduling is an external project setting; merging this config does not itself enable a schedule. Keep the existing RC-finalization parameter false for these runs. A timed-out GitHub request may already have succeeded remotely; the next pass resumes from the deterministic branch and verified source rather than forcing updates.