Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

repo-config

Repository configuration as code - the parts of "operational" that live in GitHub settings rather than in workflow YAML: branch rulesets, repository settings, and the secrets the workflows read. This is the concrete form of WORKFLOW.md section 6 and guarantee D10, and the implementation of its 5D configuration audit.

This directory is intentionally not under .github/ - that path is GitHub's own (workflows, issue templates); repository administration config-as-code is the maintainer's, so it lives here.

Files

  • configure.sh - idempotent gh api script with two modes:
    • ./repo-config/configure.sh check - validate only, no writes; exits non-zero on drift (the 5D audit). Read-only, but it reads the rulesets and secrets endpoints, so it still needs a gh token with admin on the repo.
    • ./repo-config/configure.sh apply - create-or-update the rulesets and settings to match this directory (needs admin; writes).
  • ruleset-develop.json - the develop branch ruleset (squash-only, linear history, signed commits, the required status check, strict-status off).
  • ruleset-main.json - the main branch ruleset (merge-commit-only, signed commits, the same required check, strict off; no linear-history rule).
  • settings.json - repository settings (auto-merge on; squash and merge-commit allowed; rebase off; auto-delete-on-merge off). The repo-wide auto-delete setting is off so a develop -> main promotion does not delete develop (GitHub's auto-delete would remove the merged head branch). Per-merge deletion is explicit instead: the merge-bot deletes a merged bot branch with gh pr merge --delete-branch, and a feature branch is deleted the same way (or via the merge UI's delete button) - so main/develop survive while bot/feature branches are still cleaned up.

What it does not store

Secret values are never readable through the API, so the script only asserts the required secret names exist (NUGET_USERNAME and the App credentials CODEGEN_APP_CLIENT_ID / CODEGEN_APP_PRIVATE_KEY), and notes (best-effort) whether a GitHub App is installed - a precise check needs app-level auth, so the App-installation check does not fail the audit. Set the values in the repository (or organization) secret store directly. Publishing is keyless via OIDC trusted publishing (WORKFLOW.md D4.7), so there is no NUGET_API_KEY; the matching trusted-publishing policy lives on NuGet.org and is verified by hand, not by this script.

Applying, and the required-check rename lockstep

The live ruleset's required status check is matched by name to the aggregator job in test-pull-request.yml (Check pull request workflow status job). GitHub binds the check by that exact string, so the ruleset JSON here, the live ruleset, and the aggregator job name must move in lockstep (WORKFLOW.md D6.2). If they drift, a pull request runs CI but its required check never resolves and the PR cannot merge.

So whenever the ruleset JSON or that job name changes, run apply against the live repo in the same change that ships the workflow edit, then check:

REPO=ptr727/LanguageTags ./repo-config/configure.sh apply   # sync live rulesets + settings + security
REPO=ptr727/LanguageTags ./repo-config/configure.sh check   # confirm no drift

First-time adoption is the same step: the live ruleset predates the renamed aggregator, so the first apply is what lets a pull request against the new workflows go green. Both modes need a gh login with admin on the repo (the rulesets and secrets endpoints require it). apply writes, check only reads.

Why both a script and JSON

The JSON files are the unambiguous source of truth for the configuration; the script applies and audits them idempotently. An agent can also derive the same checks on the fly from WORKFLOW.md section 6, but the committed script and JSON codify the exact intended state so the configuration is reproducible and diffable rather than tribal knowledge.