repomatic.setup_guide module¶
Build and manage the setup guide issue.
Backs the setup-guide command: composes the repository-settings checks from
repomatic.lint_repo and the PAT permission probes from
repomatic.github.token with the setup-guide-* templates into a single
issue body, then drives the issue lifecycle. Each setup step renders as a
collapsible section whose open/closed state and emoji reflect the check
outcome, and the issue closes only once every verifiable step passes.
- repomatic.setup_guide.CANNOT_VERIFY = '\n\n> [!NOTE]\n> This setting could not be verified: `REPOMATIC_PAT` is missing the **Administration: Read-only** permission. Update the token with the pre-filled link in the first step. The setting may well be correct already, but nothing here can confirm it.'¶
Note appended to a step whose probe could not run.
Both settings it covers are read through Administration-scoped endpoints, so a PAT issued without that permission answers
403and the check lands onNone. Saying so in the step beats dropping it: dropping also hid the token gap itself, since the missing permission had no other symptom.
- class repomatic.setup_guide.GuideContext(config, repo, has_pat, has_notifications_pat, has_virustotal_key, has_cloudflare_api_token)[source]¶
Bases:
objectEverything the steps read, resolved once per run.
The expensive lookups (PAT permission probes,
pyproject.toml) are cached properties, so a step that never asks never pays and two steps asking the same question share one answer.- property pypi_package_name: str | None[source]¶
The PyPI name to register a Trusted Publisher for, if any.
Gated on
is_python_packagerather than onpackage_namebeing set: a uv virtual project declares[project] namepurely to carry dependencies, so the name alone says nothing about whether anything is ever published. Asking those projects to register a publisher points them at a PyPI name they do not own, for a workflow file they do not have.
- property pat_results: PatPermissionResults | None[source]¶
The PAT permission probe results, or
Nonewhen unrunnable.
- property missing_permissions_section: str[source]¶
Warning table naming the permissions the configured PAT lacks.
- property cloudflare_secrets_ok: bool¶
Whether the Cloudflare Pages deploy can authenticate.
The token alone settles it: the account it belongs to is derived from it at run time, even when it is scoped to nothing but
Cloudflare Pages: Edit, so there is no second identifier to configure and nothing else to ask for here.
- property cloudflare_token_name: str¶
Suggested name for the deploy token, carrying the month it was made.
Cloudflare’s token list shows what a token can do and never how old it is, while the rotation procedure turns entirely on telling the incumbent from its replacement. Stamping the month into the name is what makes a token approaching its one-year expiry obvious at a glance, and what lets the two coexist unambiguously during a handover.
Recomputed per run, so the name the guide suggests stays current while the step is still open. It stops moving once the issue closes, which is the point at which the body is no longer rewritten.
- deploys_to(target)[source]¶
Whether this repository publishes its site to target.
One host’s setup step is the other’s noise, and the guide asks about exactly the one
site.deploynames: a Cloudflare-hosted project has no GitHub Pages source to set, and the probe for it answers404forever. Routes throughrepomatic.config.deploys_to(), the same predicate thelint-repoaudit reads.- Return type:
- property dependabot_ok: bool¶
Whether vulnerability alerts are confirmed enabled.
Piggybacks the Dependabot alerts permission probe, which only answers
200when the alerts themselves are on.
- class repomatic.setup_guide.SetupStep(placeholder, title, template, probe=<function SetupStep.<lambda>>, applies=<function SetupStep.<lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False)[source]¶
Bases:
objectOne step of the setup guide, declared once and read by every phase.
The guide used to spell each step out four times: a probe, a render, a template keyword and a clause of the close gate. Keeping the four in sync was manual, and the applicability guards were duplicated between the probe and the render. One entry per step now drives all four.
- probe()¶
Read the step’s completion state. Tri-state, per
CheckResult.
- applies()¶
Whether this repository needs the step at all.
A step that does not apply renders nothing and satisfies its gate, so a non-Sphinx project is never asked about Pages.
- args()¶
Template variables, defaulting to the pair almost every step wants.
- gates_closure: bool = True¶
Whether this step’s outcome can hold the issue open.
Falsefor the two steps with nothing to probe (immutable releases, the final verification), which would otherwise wedge the issue open forever.
- tolerates_unknown: bool = False¶
Whether an indeterminate probe (
None) satisfies the gate.Truefor the settings read through Administration-scoped endpoints: a PAT without that permission answers403, and a reader has no way to satisfy a check that cannot run, so it must not block the issue closing. Everywhere elseNoneis treated as incomplete, keeping the step prompting.
- explains_unverifiable: bool = False¶
Append
CANNOT_VERIFYto the body when the probe answeredNone.The reader is looking at a setting they were told to configure, so the difference between “verified” and “nobody could look” belongs on screen.
- outcome(ctx)[source]¶
The step’s state as the section renders it.
Nonesurvives only wheretolerates_unknownsays an unreadable probe is not the reader’s fault; elsewhere it collapses to incomplete so the section stays open.
- repomatic.setup_guide.SETUP_STEPS: tuple[SetupStep, ...] = (SetupStep(placeholder='step_token', title='Create and configure the token', template='setup-guide-token', probe=<function <lambda>>, applies=<function SetupStep.<lambda>>, args=<function <lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_dependabot', title='Configure Dependabot settings', template='setup-guide-dependabot', probe=<function <lambda>>, applies=<function SetupStep.<lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='immutable_releases_step', title='Enable immutable releases', template='immutable-releases', probe=<function <lambda>>, applies=<function <lambda>>, args=<function <lambda>>, gates_closure=False, tolerates_unknown=True, explains_unverifiable=False), SetupStep(placeholder='step_branch_ruleset', title='Protect the main branch', template='setup-guide-branch-ruleset', probe=<function <lambda>>, applies=<function SetupStep.<lambda>>, args=<function <lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_fork_pr_approval', title='Require approval for fork PR workflows', template='setup-guide-fork-pr-approval', probe=<function <lambda>>, applies=<function SetupStep.<lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=True, explains_unverifiable=True), SetupStep(placeholder='step_sha_pinning_required', title='Require SHA pinning for GitHub Actions', template='setup-guide-sha-pinning-required', probe=<function <lambda>>, applies=<function SetupStep.<lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=True, explains_unverifiable=True), SetupStep(placeholder='step_pypi_trusted_publisher', title='Register the PyPI Trusted Publisher entry', template='setup-guide-pypi-trusted-publisher', probe=<function <lambda>>, applies=<function <lambda>>, args=<function <lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_pages_source', title='Set GitHub Pages deployment source to GitHub Actions', template='setup-guide-pages-source', probe=<function <lambda>>, applies=<function <lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_cloudflare_pages', title='Configure the Cloudflare Pages credentials', template='setup-guide-cloudflare-pages', probe=<function <lambda>>, applies=<function <lambda>>, args=<function <lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_virustotal', title='Configure VirusTotal scanning (optional)', template='setup-guide-virustotal', probe=<function <lambda>>, applies=<function <lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_notifications_pat', title='Create and configure the notifications token', template='setup-guide-notifications-pat', probe=<function <lambda>>, applies=<function <lambda>>, args=<function SetupStep.<lambda>>, gates_closure=True, tolerates_unknown=False, explains_unverifiable=False), SetupStep(placeholder='step_verify', title='Verify the setup', template='setup-guide-verify', probe=<function SetupStep.<lambda>>, applies=<function SetupStep.<lambda>>, args=<function SetupStep.<lambda>>, gates_closure=False, tolerates_unknown=False, explains_unverifiable=False))¶
Every step of the setup guide, in the order the issue body lists them.
- repomatic.setup_guide.manage_setup_guide(config, *, has_pat, has_notifications_pat, has_virustotal_key, has_cloudflare_api_token=False, repo)[source]¶
Render the setup guide issue body and drive the issue lifecycle.
Walks
SETUP_STEPS: each step probes its own state, renders its collapsible section, and reports whether it lets the issue close. The issue closes only when every applicable gating step passes.- Parameters:
config (
Config) – The resolved[tool.repomatic]configuration.has_pat (
bool) – WhetherREPOMATIC_PATis configured.has_notifications_pat (
bool) – WhetherREPOMATIC_NOTIFICATIONS_PATis configured.has_virustotal_key (
bool) – WhetherVIRUSTOTAL_API_KEYis configured.has_cloudflare_api_token (
bool) – WhetherCLOUDFLARE_API_TOKENis configured.repo (
str|None) – Repository inowner/repoformat; permission and settings checks are skipped whenNone.
- Return type: