What happened
mitchella was added to repos.json with "template_source": null, because
its working tree already existed locally and scaffolding from repo-template
would have produced a conflicting initial commit. The apply created the repo,
and the repo could not then receive its first commit.
The deadlock is structural, not a one-off:
ci/validate.py requires every public repo to have a required-checks.json
entry: "'mitchella' is public in repos.json but has no required-checks.json
entry — its ruleset would require nothing and auto-merge could not arm."
- The
main ruleset therefore requires status checks from the moment the repo
exists.
- A push to
main is rejected with GH013 ... 2 of 2 required status checks are expected, because no check has ever run: there is no pull request to run
one on, and no commit to open a pull request from.
- Branch protection on
main also blocks renaming a branch into place
("delete the branch protection rule for main and try again"), and the
Terraform token deliberately lacks delete_repo, so recreating is not
available to the automation either.
template_source is what normally prevents this. A template-seeded repo gets
its initial commit server-side at creation, before any rule can apply, which is
why every other entry in repos.json sets it.
Why it is worth closing
Both rails that would have caught this are documented, and neither is
enforced:
terraform/README.md § Adding a repo to the fleet shows template_source
pointing at repo-template in the example, but does not say it is load
bearing or what happens without it.
fleet-ops/README.md already warns that a required context which never
reports deadlocks a repo, and says to run the preflight before adding to
required-checks.json. On a repo with no pull request history there is
nothing for the preflight to check, so the warning is correct and the check
cannot help.
The next person adding a repo from an existing local tree will reach the same
place, and the way out is not obvious.
Where modern practice points
Make the invalid combination unrepresentable rather than documented. A rule in
ci/validate.py is the cheapest option and matches how the other fleet
invariants are held:
- Reject
visibility: public with template_source: null for an entry that
is not yet present live, with an error naming the consequence, in the style of
the existing public-repo-needs-checks message.
- Or, if a null
template_source should stay available for the
existing-local-tree case, document the escape hatch beside it in
terraform/README.md.
What worked, for the record
The repo was recovered without mutating any enforced surface. The main
ruleset targets ~DEFAULT_BRANCH, so: add push triggers to the repo's
workflows, push a non-default branch to make both contexts report on the
commit, push main while the default branch still pointed elsewhere, set the
default back to main, and delete the scaffolding branches. The end state is
identical to a normally seeded repo. Branch protection was never deleted and no
live setting was changed by hand.
Next step
Decide between the validator rule and the documented escape hatch, then add
whichever is chosen. Context: #174 and the initial commits of
lentago/mitchella.
What happened
mitchellawas added torepos.jsonwith"template_source": null, becauseits working tree already existed locally and scaffolding from
repo-templatewould have produced a conflicting initial commit. The apply created the repo,
and the repo could not then receive its first commit.
The deadlock is structural, not a one-off:
ci/validate.pyrequires every public repo to have arequired-checks.jsonentry: "'mitchella' is public in repos.json but has no required-checks.json
entry — its ruleset would require nothing and auto-merge could not arm."
mainruleset therefore requires status checks from the moment the repoexists.
mainis rejected withGH013 ... 2 of 2 required status checks are expected, because no check has ever run: there is no pull request to runone on, and no commit to open a pull request from.
mainalso blocks renaming a branch into place("delete the branch protection rule for main and try again"), and the
Terraform token deliberately lacks
delete_repo, so recreating is notavailable to the automation either.
template_sourceis what normally prevents this. A template-seeded repo getsits initial commit server-side at creation, before any rule can apply, which is
why every other entry in
repos.jsonsets it.Why it is worth closing
Both rails that would have caught this are documented, and neither is
enforced:
terraform/README.md§ Adding a repo to the fleet showstemplate_sourcepointing at
repo-templatein the example, but does not say it is loadbearing or what happens without it.
fleet-ops/README.mdalready warns that a required context which neverreports deadlocks a repo, and says to run the preflight before adding to
required-checks.json. On a repo with no pull request history there isnothing for the preflight to check, so the warning is correct and the check
cannot help.
The next person adding a repo from an existing local tree will reach the same
place, and the way out is not obvious.
Where modern practice points
Make the invalid combination unrepresentable rather than documented. A rule in
ci/validate.pyis the cheapest option and matches how the other fleetinvariants are held:
visibility: publicwithtemplate_source: nullfor an entry thatis not yet present live, with an error naming the consequence, in the style of
the existing public-repo-needs-checks message.
template_sourceshould stay available for theexisting-local-tree case, document the escape hatch beside it in
terraform/README.md.What worked, for the record
The repo was recovered without mutating any enforced surface. The
mainruleset targets
~DEFAULT_BRANCH, so: addpushtriggers to the repo'sworkflows, push a non-default branch to make both contexts report on the
commit, push
mainwhile the default branch still pointed elsewhere, set thedefault back to
main, and delete the scaffolding branches. The end state isidentical to a normally seeded repo. Branch protection was never deleted and no
live setting was changed by hand.
Next step
Decide between the validator rule and the documented escape hatch, then add
whichever is chosen. Context: #174 and the initial commits of
lentago/mitchella.