ci(spoke): tinyland.repo.json + lanes.json + spoke-ci.yml@v3.1.0 wiring (TIN-3914) — DO NOT MERGE before the jesssullivan-blog-nix ARS is applied - #267
Draft
Jesssullivan wants to merge 2 commits into
Conversation
…TIN-3914) Adopts the org spoke CI contract this repo has had zero adoption of: no tinyland.repo.json, no lanes.json, and not one `uses: tinyland-inc/*` reference across the ten workflow files. Additive only. `.github/workflows/ci.yml` is untouched, so substrate-boundary, bazel-remote-gates, and build-and-test remain the required checks and the exact-source proofs that production and rollback consume are unchanged. - tinyland.repo.json: schema_version 1 (v1 is what spoke-ci@v3.1.0's repo-manifest-validate gate validates against), modeled on gftb-site's manifest. `contracts.nix: none` because this repo has no flake.nix, matching the account-controller precedent rather than claiming a file that is absent. `scaffold_tag` is omitted: this repo was not spawned from site.scaffold. Validated against ci-templates@v3.1.0 schemas/tinyland-repo-manifest.schema.json with that repo's own scripts/manifest-schema-validate.py. - .github/lanes.json: three lanes named for the check/test/e2e authority this repo already has, each recording the npm script it stands for under `extra` (spoke-ci does not read `extra`; the lane schema has no command field, so this is the reviewable mapping, not a dispatch). `defaults.runner_class` is jesssullivan-nix, which satisfies the vendored runnerClass pattern. Validated against ci-templates@v3.1.0 schemas/lanes.schema.json. - .github/workflows/spoke-ci.yml: calls the reusable workflow pinned at the v3.1.0 tag's commit d8d178c, not the tag name, because scripts/test-workflow-authority.mjs requires every non-local `uses:` in this directory to resolve to a 40-hex commit and applies that rule to reusable workflows too. That test needed no change: the new file passes its generic loop as written. heavy_runner_class and cache_backed_targets override template defaults that name a runner pool and two Bazel targets which do not exist here. No `secrets: inherit`, diverging from the gftb-site exemplar, because this lane carries a pull_request trigger. DO NOT MERGE before Jesssullivan/jesssullivan-infra applies a jesssullivan-blog-nix ARC scale set serving the jesssullivan-nix label. Until then every job in the new workflow queues with nowhere to run.
…s); honest nix contract The jesssullivan-blog-nix scale set registers runs-on label tinyland-nix -- the overlay runner-taxonomy validator rejects owner-namespaced labels, and the k8s ARS name is a separate field from the label. Pointing spoke-ci at a label no listener serves would queue forever. Also stop declaring contracts.nix none while the wired workflow runs nix develop.
Owner
Author
|
Blocker from the convergence synthesis fixed at HEAD: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DO NOT MERGE before
Jesssullivan/jesssullivan-infraapplies ajesssullivan-blog-nixARC scale set serving thejesssullivan-nixlabel (tofu/stacks/arc-runners/jesssullivan.tfvars). Until that apply lands, every job in the new workflow queues with nowhere to run. This is wiring, not adoption.This repo had zero ci-templates adoption: no
tinyland.repo.json, no.github/lanes.json, and not oneuses: tinyland-inc/*across the ten workflow files. It is outside every ci-templates oracle's reach by non-adoption, not by failure.Additive by construction
.github/workflows/ci.ymlis untouched.substrate-boundary,bazel-remote-gates, andbuild-and-testremain exactly where they are, so required checks and the exact-source proofs thatcloudflare-pages-production-v2.ymlandgithub-pages-rollback-v2.ymlconsume (for (const requiredName of ["build-and-test", "bazel-remote-gates"])) are unchanged. The new workflow is namedSpoke CI (TIN-3914), deliberately notCI, so it does not enter the production workflow'sworkflow_run: workflows: ['CI']lane.scripts/test-workflow-authority.mjs— not edited, and here is whyThe generic loop (lines 292-310) applies three rules to every file in
.github/workflows/. The new file passes all three as written, so the test needed no extension:hasPrTrigger && /secrets\.|github\.token|GITHUB_TOKEN/hasManualCarrier && hasAuthorityworkflow_dispatch:statuses: writeis not in the authority set anyway.)./uses:must end in 40 hexuses:spoke-ci.yml@v3.1.0would fail it. Pinned instead at@d8d178c022a0f84853d53a2c8fe0fc90115f0949 # v3.1.0— the capture group is[^\s#]+, so it stops before the comment and the SHA validates.Verified by porting the loop to stdlib Python and running it over all 11 workflow files: 0 failures.
ruby ci-templates/scripts/lint-runs-on.rb --root .goes 19 -> 20 runs-on checked with FAIL unchanged at 17, which is the positive proof thatjesssullivan-nixis an accepted capability label.no-hosted-runners.rbstays at 23 labels; this PR adds none.Deliberate deviations from the gftb-site exemplar
secrets: inherit. gftb-site inherits. This lane carries apull_requesttrigger, and this repo's standing contract is that a PR-triggered lane reaches no credential.spoke-cideclares one optional secret (ATTIC_TOKEN), and the cache-backed path reads the shared Bazel cache without uploading, so it does not need one. Note the authority test's credential rule keys on the literalsecrets., whichsecrets: inheritwould slip past — this follows the rule's intent, not its letter. Revisit only behind a same-repo-only guard.heavy_runner_class: jesssullivan-nix. The template default sendsbazel-graphtotinyland-nix-heavy, which serves no repo in this forge scope. Same org-tenancy rationale gftb-site uses.cache_backed_targetsoverridden. The template default names//:sveltekit_typesand//:svelte_check_test. Neither target exists in this repo. Replaced with//:node_modules //:sveltekit_check //:sveltekit_vite_build_smokefromBUILD.bazel.playwright_enabledleft at false. Thekvm_runner_classjob would need a KVM-capable class that is not anchored here.Manifest and lanes
schema_version: 1. Not a style choice:spoke-ci@v3.1.0routes throughrepo-manifest-validate@v3, and thev3tag still points atd8d178c(2026-08-19), which predates ci-templatesd321dbd's v2 schema dispatch. A v2 manifest would fail the gate that this PR is wiring up.Both files were validated against the vendored ci-templates copies at
v3.1.0(schemas/tinyland-repo-manifest.schema.json,schemas/lanes.schema.json) using that repo's ownscripts/manifest-schema-validate.py— the same stdlib validator the composite action falls back to. Both pass. The validator was negative-tested first (hostedrunner_class, unknown lane key, bad target class, bad spoke-name case, bad trigger — all correctly rejected), so the greens are not vacuous.Two honesty notes on the manifest:
contracts.nix: "none"— this repo has noflake.nix.tinyland-inc/account-controllersets the same precedent rather than naming a file that is absent.scaffold_tagis omitted. This repo was not spawned fromsite.scaffold, and the field is optional.lanes.jsoncarries three lanes named for the check/test/e2e authority this repo already has. The lane schema hasadditionalProperties: falseand no command field, so the mapping toremote:check/remote:test/remote:e2elives in each lane's free-formextraobject.spoke-cidoes not readextra; it is the reviewable record of what each lane stands for, not a dispatch.defaults.runner_class: jesssullivan-nixsatisfies the vendoredrunnerClasspattern^[a-z0-9][a-z0-9-]*-(nix|nix-heavy|nix-kvm|nix-gpu|docker|dind)$. (site.scaffold'sdocs/copy of that schema still carries an older hard enum that would reject it — a third fork of the org schema, noted, not touched here.)Blockers this PR does not fix
Beyond the ARS,
spoke-ci@v3.1.0runsnix develop --command just setup/just build/just checkandnix develop --command bazelisk mod graph. Thejustrecipes all exist.flake.nixdoes not. Everynix developstep will fail once runners exist.lanes-loadalso falls back tonix developwhen the host python lacksjsonschema, and hard-exits 2 when there is noflake.nixeither. Aflake.nixis a prerequisite for this lane going green and is not in scope here.Merge order with #264
Written to merge cleanly with #264, which also edits this register. Proven with
git merge-tree --write-treeagainstrefs/pull/264/head: conflict-free. #264 inserts a table row after theCI proofrow and a bullet at the end of Build, Test, And Deploy; this PR appends a row at the end of the table and a bullet inside the Cross-Repo Delivery Ownership list, so no hunk contexts overlap. Whichever lands second should trim the overlap: #264's paragraph says adoption "first needs ...tinyland.repo.json, and.github/lanes.json", which this PR supplies.Not run (host rule: this seat is teletype-only)
npm/node/bazelwere not run.//:workflow_authority_testsis reasoned about by reading, and by the stdlib port of its generic loop described above — deferred: needs CI-capable seat for the real run. Same for anything requiringnix.