repomatic.lint_repo.roster module

The lint-repo check roster, in report order.

Each RepoCheck declares one check once: its name, the function that runs it, when it applies, and whether its failure fails the command. The lint-repo --help text and the lint-repo job docs render from the roster, so neither can list fewer checks than the command runs.

class repomatic.lint_repo.roster.RepoCheck(name, run, summary, description, applies=<function RepoCheck.<lambda>>, fatal=False)[source]

Bases: object

One entry of the lint-repo check sequence.

Declaring each check once makes the roster the thing tests and readers walk: the order, the gate and the severity of every check sit in one table.

name: str

Stable identity, for tests and for grepping the roster.

run: Callable[[LintContext], CheckResult | Iterable[CheckResult]]

Perform the check. May answer one result or a stream of them.

summary: str

What a passing repository looks like, as one clause for lint-repo --help.

Leave out the severity: help_entry derives it from fatal.

description: str

What the check reports and why, as its bullet in the lint-repo job docs.

Markdown, rendered on docs/workflows.md by repo_check_reference() in roster order, so a link is relative to that page. It opens on Fails for a fatal check and on Warns or Reports for any other, and carries no closing period, like every job bullet on that page.

applies()

Whether this repository has anything for the check to look at.

A check reading the GitHub API applies only when the context names a repository: it reads the slug through slug.

fatal: bool = False

Whether a failure fails the command.

A fatal check reports at ERROR and sets the non-zero exit code; every other check is advisory. A red run for an advisory finding teaches its readers to ignore red runs, and that hides the failures that count.

results(ctx)[source]

Run the check, normalizing one-or-many into a tuple.

Return type:

tuple[CheckResult, ...]

fails(result)[source]

Whether result fails the command, which only a fatal check can do.

Return type:

bool

property level: AnnotationLevel

The severity a failure reports at, which fatal selects.

property help_entry: str

This check’s item in the lint-repo --help list, wrapped for a terminal.

repomatic.lint_repo.roster.PAT_PERMISSION_NAMES = 'Administration, Contents, Issues, Pull requests, Dependabot alerts and Workflows'

The permissions the PAT probes cover, listed for the pat-permissions entry.

repomatic.lint_repo.roster.BOOTSTRAP_SECTIONS = '`[tool.ruff]`, `[tool.pytest]`, `[tool.coverage]`, `[tool.mypy]`, `[tool.mdformat]`'

The tool sections init seeds once, for the bootstrap-config-drift entry.

repomatic.lint_repo.roster.REPO_CHECKS: tuple[RepoCheck, ...] = (RepoCheck(name='package-name-vs-repo', run=<function check_package_name_vs_repo>, summary='Package name matches the repository name', description='Warns when the package name differs from the repository name', applies=<function <lambda>>, fatal=False), RepoCheck(name='website-for-sphinx', run=<function check_website_for_sphinx>, summary="A Sphinx project's website field names the documentation URL declared in [project.urls]", description='Warns when a Sphinx project\'s GitHub website field does not name the documentation URL it declares in `[project.urls]` (`Documentation`, then `Docs`). A trailing slash and the case of the scheme and host are ignored, since GitHub stores the website field with the slash a browser appends. Moving a documentation site to a new domain is what this catches: Sphinx renders `<link rel="canonical">` from `html_baseurl`, so every published page names the new origin while the repository sidebar keeps sending visitors to the old one. A project declaring no documentation URL keeps the presence-only check', applies=<function <lambda>>, fatal=False), RepoCheck(name='pages-deployment-source', run=<function check_pages_deployment_source>, summary='GitHub Pages publishes from GitHub Actions, when site.deploy targets GitHub Pages', description='Warns when a Sphinx project deploying to GitHub Pages (the `site.deploy` default) has the Pages source set to `Deploy from a branch`. The `docs.yaml` deploy job publishes with `actions/deploy-pages`, which needs the Pages source set to `GitHub Actions`', applies=<function <lambda>>, fatal=False), RepoCheck(name='cloudflare-pages-secrets', run=<function check_cloudflare_secrets>, summary='CLOUDFLARE_API_TOKEN secret set, when site.deploy targets Cloudflare Pages', description='Warns about a missing `CLOUDFLARE_API_TOKEN` when `site.deploy` targets Cloudflare Pages. The token is the whole of the credential: the account is derived from it at run time', applies=<function <lambda>>, fatal=False), RepoCheck(name='cloudflare-r2-secrets', run=<function check_cloudflare_r2_secrets>, summary='CLOUDFLARE_R2_ACCESS_KEY_ID and CLOUDFLARE_R2_SECRET_ACCESS_KEY secrets set, when site.cloudflare-r2-bucket is declared', description='Warns about a missing `CLOUDFLARE_R2_ACCESS_KEY_ID` or `CLOUDFLARE_R2_SECRET_ACCESS_KEY` when `site.deploy` targets Cloudflare Pages and `site.cloudflare-r2-bucket` is declared', applies=<function <lambda>>, fatal=False), RepoCheck(name='pages-redirect-preserved', run=<function check_pages_redirect_preserved>, summary='Legacy github.io URLs still redirect, for a site moved to Cloudflare Pages', description='Warns when a site that moved to Cloudflare Pages no longer keeps its old `github.io` URLs redirecting: `[project.urls]` still naming the `github.io` host, GitHub Pages disabled, or its custom domain unset or naming another host ([details](cloudflare.md#leaving-github-pages-behind-urls-intact))', applies=<function <lambda>>, fatal=False), RepoCheck(name='pages-redirects', run=<function check_pages_redirects>, summary='Committed _redirects files survive the Cloudflare Pages engine: no dropped rules, no silent budget abort', description="Fails when a committed `_redirects` file would lose rules to the Cloudflare Pages engine's undocumented budget accounting, or holds a rule that can never apply as written, since such a rule is silently dead in production ([details](cloudflare.md#the-redirects-engine-as-it-actually-is))", applies=<function <lambda>>, fatal=True), RepoCheck(name='wrangler-toml', run=<function check_wrangler_config>, summary='wrangler.toml agrees with the declared Cloudflare project name and compatibility date', description='Warns when a committed `wrangler.toml` contradicts the declared Cloudflare project name or compatibility date', applies=<function <lambda>>, fatal=False), RepoCheck(name='oversized-site-files', run=<function check_oversized_site_files>, summary='No tracked file over the 25 MiB Cloudflare Pages limit, unless an R2 bucket is declared to serve it', description='Warns about a tracked file over the 25 MiB Cloudflare Pages limit when `site.deploy` targets Cloudflare Pages and no R2 bucket is declared', applies=<function <lambda>>, fatal=False), RepoCheck(name='stale-gh-pages-branch', run=<function check_stale_gh_pages_branch>, summary='No leftover gh-pages branch in a Sphinx project', description='Warns when a Sphinx project still has a `gh-pages` branch. Pages deploys through GitHub Actions, so the branch is no longer needed', applies=<function <lambda>>, fatal=False), RepoCheck(name='description-matches', run=<function check_description_matches>, summary='Repository description matches the project description', description='Fails when the repository description differs from the project description', applies=<function <lambda>>, fatal=True), RepoCheck(name='topics-subset-of-keywords', run=<function check_topics_subset_of_keywords>, summary='GitHub topics are a subset of the pyproject.toml keywords', description='Warns when a GitHub topic matches no `[project] keywords` entry. A keyword matches the topic GitHub would store for it: lowercased, with each run of whitespace replaced by a hyphen, so `CLI` declares the `cli` topic and `Weather forecast` declares `weather-forecast`', applies=<function <lambda>>, fatal=False), RepoCheck(name='funding-file', run=<function check_funding_file>, summary='Funding file present when the owner has GitHub Sponsors', description='Warns when the repository owner has a GitHub Sponsors listing but `.github/funding.yml` is missing, so the repository shows no Sponsor button. Forks are skipped', applies=<function <lambda>>, fatal=False), RepoCheck(name='stale-draft-releases', run=<function check_stale_draft_releases>, summary='No stale draft release, whose tag is not a .dev0', description='Warns about draft releases whose tag does not end in `.dev0`. Those are leftovers from an abandoned or failed release: the only expected drafts are the rolling dev pre-releases that `sync-dev-release` manages', applies=<function <lambda>>, fatal=False), RepoCheck(name='undeclared-labels', run=<function check_undeclared_labels>, summary='Every repository label is declared by a configured label source', description="Warns when the repository carries a label that no configured source (the labeller's bundled `labels.toml` profiles, a hand-written or downloaded `extra-labels/` file, the inline `labels.extra` block) declares. `sync-labels` runs `labelmaker apply`, which creates, updates and renames labels but never deletes one, so a label dropped from a source keeps existing on GitHub with nothing left to mention it again. Advisory only: deleting a label detaches every issue and pull request carrying it, and only the count of what each orphan holds tells a hand-made label from one still in active use. Extra label files are read in every format `labelmaker` accepts (JSON, TOML, YAML, and JSON5 as far as its plain-JSON subset), and a file that cannot be fetched or read skips the check rather than reporting its labels as orphans", applies=<function <lambda>>, fatal=False), RepoCheck(name='install-guide-downloads', run=<function check_install_guide_downloads>, summary='Install guide download URLs resolve to real release assets', description='Warns when a release download URL in `docs/install.md` names a file its release does not carry. The release freeze pins those URLs before the binaries exist, so a failed build lane leaves the guide advertising 404s until the next release moves past it: this is the check that surfaces the gap instead of leaving it for a user to hit. Versionless `releases/latest/download` URLs are checked against the latest published release too, and rot longer: nothing rewrites them at release time, so a renamed asset leaves one pointing at a 404 indefinitely', applies=<function <lambda>>, fatal=False), RepoCheck(name='tag-protection-rules', run=<function check_tag_protection_rules>, summary='No active tag ruleset that can block a release tag push', description='Warns when an active ruleset targets tags, including one inherited from a parent level. Such a ruleset can stop the `create-tag` job from pushing release tags unless `REPOMATIC_PAT` is in its bypass list', applies=<function <lambda>>, fatal=False), RepoCheck(name='branch-ruleset-on-default', run=<function check_branch_ruleset_on_default>, summary='At least one active branch ruleset', description='Warns when the repository has no active branch ruleset, which the check reads as a default branch open to deletion and force pushes. It does not verify that a ruleset targets the default branch itself ([details](security.md#supply-chain-security))', applies=<function <lambda>>, fatal=False), RepoCheck(name='classic-branch-protection', run=<function check_classic_branch_protection>, summary='No classic branch protection rule beside the rulesets', description='Warns when a classic branch protection rule survives beside the rulesets. GitHub applies both together, so the branch policy splits across two settings pages ([details](security.md#supply-chain-security))', applies=<function <lambda>>, fatal=False), RepoCheck(name='immutable-releases', run=<function check_immutable_releases>, summary='Immutable releases enabled, for a repository publishing releases', description='Warns when a repository that publishes GitHub releases, which means one holding a changelog, has immutable releases disabled. That setting locks the tag and assets of a published release (see [§ Immutable releases](#immutable-releases))', applies=<function <lambda>>, fatal=False), RepoCheck(name='fork-pr-approval-policy', run=<function check_fork_pr_approval_policy>, summary='Fork PR workflow approval policy strict enough', description='Warns when the fork PR workflow approval policy is weaker than `first_time_contributors`', applies=<function <lambda>>, fatal=False), RepoCheck(name='sha-pinning-required', run=<function check_sha_pinning_required>, summary='Actions required to be pinned to a full-length commit SHA', description='Warns when the repository does not require actions to be pinned to a full-length commit SHA (`sha_pinning_required`). With the setting on, GitHub itself refuses to run a workflow that names an action by a mutable tag or branch. This backs up `zizmor`, whose findings can be silenced inline ([details](security.md#supply-chain-security))', applies=<function <lambda>>, fatal=False), RepoCheck(name='pypi-trusted-publisher', run=<function check_pypi_trusted_publisher>, summary="The latest PyPI release's provenance names this repository's release.yaml", description="Warns when the latest PyPI release of a package carries PEP 740 provenance naming a repository or workflow other than this repository's `release.yaml`, which means the Trusted Publisher entry is registered wrongly. A package with no release yet, or no provenance, is reported as skipped ([details](security.md#supply-chain-security))", applies=<function <lambda>>, fatal=False), RepoCheck(name='workflow-permissions', run=<function check_workflow_permissions>, summary='Workflows and reusable-workflow callers declare their permissions', description='Warns when a workflow with steps of its own has no top-level `permissions` key. Also warns when a job calling a reusable workflow under `permissions: {}` declares no `permissions:` of its own: GitHub then aborts the run at startup once a nested job requests a scope the caller never granted', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='workflow-dispatch', run=<function check_workflow_dispatch>, summary='Every standalone workflow can be started by hand', description='Warns when a workflow that neither calls an upstream reusable workflow nor is reusable itself has no `workflow_dispatch` trigger, so a maintainer cannot rerun it without a push', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='thin-caller-pins', run=<function check_thin_caller_pins>, summary='Thin callers pin the upstream workflows to a release, not to @main', description='Warns when a job calling an upstream reusable workflow references it at `@main`, which runs whatever the upstream default branch holds when the job starts instead of a release', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='thin-caller-triggers', run=<function check_thin_caller_triggers>, summary='Thin callers carry the triggers of the workflow they call', description='Warns when a thin caller lacks a trigger the upstream workflow it calls declares, or adds one it does not. An upstream workflow callable only through `workflow_call` leaves its caller free to pick its own', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='thin-caller-secrets', run=<function check_thin_caller_secrets>, summary='Thin callers pass every secret the workflow they call declares', description='Warns when the job of a thin caller that calls its upstream workflow forwards neither `secrets: inherit` nor every secret that workflow declares. The secrets are read off that job alone, so another job of the same file, like the build lane of a downstream `release.yaml`, cannot vouch for it', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='test-matrix-excludes', run=<function check_test_matrix_excludes>, summary='Every test-matrix exclude entry names a value on some matrix axis', description='Warns when a `[tool.repomatic.test-matrix] exclude` entry names a value found on no matrix axis, like a renamed runner. Such an entry never matches a combination, so the matrix drops it without a message ([details](test-matrix.md#guard-the-matrix-with-a-test))', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='python-version-consistency', run=<function check_python_version_consistency>, summary='Python classifiers, requires-python and the workflow test matrices agree', description='Warns when the lowest `Programming Language :: Python :: X.Y` classifier differs from the `requires-python` floor. Also warns when a workflow test matrix listing `python-version` values literally omits either end of the advertised range, or tests a released version the classifiers do not advertise', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='runner-images', run=<function check_runner_images>, summary='No job runs on a -latest alias or on an image outside the test matrices', description='Warns when a job runs on a `-latest` alias, which GitHub repoints without a commit to review, or on an image outside the test matrix axes. A `runs-on:` built from an expression is left alone ([details](test-matrix.md#github-hosted-runner-inventory))', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='release-path', run=<function check_release_path>, summary='Each release-only step tests the capability it needs, and runs on a release commit', description="Reports which release-only steps a release commit would run or skip for a Python project, so a missing capability shows on an ordinary push instead of on release day. Where the reusable workflows live, warns when a step's `if:` never tests the capability it needs", applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='manpages-toolchain', run=<function check_manpages_toolchain>, summary='The manpages.script lockfile pins a click-extra able to render man pages', description='Warns when a project setting `[tool.repomatic] manpages.script` locks a `click-extra` older than `9`. The `manpages` release job renders with `click-extra wrap --help-format man`, an invocation `9.0.0` introduced, and the job first runs on the commit that tags and publishes. Since a published release locks its asset list, a failure there costs that version its man pages for good rather than being repairable afterwards. The subject is `uv.lock`, which is what `uv sync --frozen` installs; a project with no lockfile, or one whose lockfile never mentions `click-extra`, is reported as skipped', applies=<function <lambda>>, fatal=False), RepoCheck(name='bootstrap-config-drift', run=<function check_bootstrap_config_drift>, summary='Seeded tool configs carry every bundled template entry, or decline it with a reason', description='Warns when a tool config seeded once (`[tool.ruff]`, `[tool.pytest]`, `[tool.coverage]`, `[tool.mypy]`, `[tool.mdformat]`) lacks an entry its bundled template carries. `init` writes those sections on the first run and hands them over, so a rule the template gains later reaches no repository and nothing names the gap. Only absence is reported, keys and list members alike: a value the repository tuned, a key it added and a comment it rewrote are all its own. A pytest section that keeps its keys under `[tool.pytest.ini_options]` is measured there, since pytest refuses a file holding both that table and the native keys. Advisory, since a template rule dropped on purpose looks identical to one never received, and only the maintainer can tell them apart. An entry named under `[tool.repomatic] lint-repo.declined` is reported with its reason in place of the warning, and an entry there that declines nothing is warned about in its turn', applies=<function <lambda>>, fatal=False), RepoCheck(name='superseded-local-excludes', run=<function check_superseded_local_excludes>, summary='No bare [tool.lychee] exclude entry the bundled template now anchors', description='Warns when a `[tool.lychee] exclude` entry is the bare form of one the bundled template has since anchored. An ongoing sync grafts a local-only array item back on and retires nothing, so a pattern the template *replaced* rather than added survives beside its own replacement: lychee matches these as substrings, and a bare `x\\.com` kept beside `^https://(www\\.)?x\\.com(/.*)?$` goes on excluding every domain ending in `x.com`, which is what the anchoring was written to stop. A section no sync reaches holds the bare form alone, so there the warning names the anchored form to write in its place rather than advising a drop. Advisory, since only the maintainer can tell a superseded entry from one the repository narrowed on purpose', applies=<function <lambda>>, fatal=False), RepoCheck(name='inline-pins-match-upstream', run=<function check_inline_pins_match_upstream>, summary='Inline upstream pins match the version the uses: refs name', description="Fails when a workflow's inline upstream pin (like `uvx 'repomatic==X.Y.Z'`) names a different version than its `uses:` refs. A stale pin can lack a symbol the newer refs rely on: the `metadata` job then fails, and a release can reach PyPI without a tag", applies=<function RepoCheck.<lambda>>, fatal=True), RepoCheck(name='self-pin-cooldown-exemption', run=<function check_self_pin_cooldown_exemption>, summary='Inline upstream pins resolving under a cooldown carry their --exclude-newer-package exemption', description="Fails when a workflow's inline upstream pin (like `uvx 'repomatic==X.Y.Z'`) resolves under a cooldown but carries no `--exclude-newer-package` exemption beside it, checked only in a workflow that sets `UV_EXCLUDE_NEWER` at all. `uvx` reads no project configuration, so the flag on the command line is the only place the bypass can live: without it, a pin naming a release younger than the window cannot resolve, and since the pin usually sits in the `metadata` job with every other job `needs: metadata`, the whole workflow fails at its first job while executing nothing. `sync-workflow-pins` backfills the flag on its next run, but a repository already pinned at the newest release never triggers that backfill on its own, which is what this check catches. The sharper of the two fatal pin checks, since the pin it guards takes every `needs: metadata` job down with it", applies=<function RepoCheck.<lambda>>, fatal=True), RepoCheck(name='setup-uv-version-pin', run=<function check_setup_uv_version_pin>, summary='Every astral-sh/setup-uv step pins one uv version', description='Warns when an `astral-sh/setup-uv` step declares no `version:` input, or when steps across the repository pin more than one uv version. `[tool.uv] required-version` is only a floor; left unpinned, `setup-uv` installs whatever uv release is newest the moment the job runs, seconds after publication, making the one tool that enforces every cooldown the one tool carrying none of its own', applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='setup-uv-checksum-coverage', run=<function check_setup_uv_checksum_coverage>, summary='The pinned uv carries a checksum in the pinned astral-sh/setup-uv', description="Warns when the pinned uv is absent from the checksum table bundled into the pinned `astral-sh/setup-uv` release. That table holds the only pinned hashes `setup-uv` verifies a download against, and a version missing from it is not refused. Before `v10.1.0` it installs unverified, on a debug line no CI log shows by default. From `v10.1.0` on it is checked against a hash the action fetches at run time, which no pin fixes. Since uv ships weekly against the action's monthly cadence, and `sync-action-pins` and `sync-workflow-pins` walk the two pins independently, a repository drifts into holding two perfectly good pins that together pin no hash. `sync-workflow-pins` repairs it by stepping the uv pin back onto the table, and a `sync-action-pins` bump lets the pin move forward again. Reported as skipped rather than failed when the table cannot be read", applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='registry-pin-cooldown', run=<function check_registry_pin_cooldown>, summary='Every repomatic run tool pin is past the cooldown, or an exclude-newer-package entry admits it', description="Warns when a `repomatic run` tool is pinned at a release younger than [`minimum-release-age`](configuration.md#minimum-release-age), which `sync-tool-versions` never adopts but a hand bump can. A virtualenv tool like `nuitka` installs through uv commands that read the project's `[tool.uv] exclude-newer-package`, so the warning names the dated entry to add when none admits the release. A downstream repository that adopts such a pin before it clears the window needs the same entry. A `uvx` or npm tool reads no such entry, so the warning gives the date its install starts to work. Binary tools are not checked: their download applies no cooldown, so nothing holds a young pin back. A pin whose release date cannot be read is reported as skipped", applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='metadata-keys', run=<function check_metadata_keys>, summary='Workflows only ask repomatic show-metadata for keys it still emits', description="Fails when a workflow's `run:` line asks `repomatic show-metadata` for a key that no longer exists, reading the invocation the way Click does so an option's value is never mistaken for a positional key. `repomatic init` syncs a header-only workflow's header and its `uses:` pins and leaves the job bodies to the repository, so a key retired upstream stays in a `run:` line nothing sweeps. The command answers an unknown key with a `UsageError`, and every job reaching the metadata job through `needs:` dies with it, which turns a retired key into a whole workflow failing at its first job on the next push. Fatal, like the inline-pin checks above: all three describe a workflow that is already broken rather than one that might age badly", applies=<function RepoCheck.<lambda>>, fatal=True), RepoCheck(name='pr-templates', run=<function check_pr_templates>, summary='Repository-local PR body templates sit in .github/pr-templates/ and carry valid frontmatter', description="Warns when a repository-local `pr-body --template-file` template sits outside `.github/pr-templates/`, does not exist, or has frontmatter without a `title` or that keeps the attribution footer. Both `footer: false` and the quoted `footer: 'false'` opt out. A template that keeps the footer renders it twice ([details](operation-contracts.md#repository-local-templates))", applies=<function RepoCheck.<lambda>>, fatal=False), RepoCheck(name='virustotal-secret', run=<function check_virustotal_secret>, summary='VIRUSTOTAL_API_KEY secret set, when Nuitka is active', description='Warns about a missing `VIRUSTOTAL_API_KEY` when Nuitka binary compilation is active', applies=<function <lambda>>, fatal=False), RepoCheck(name='notifications-pat-secret', run=<function check_notifications_secret>, summary='REPOMATIC_NOTIFICATIONS_PAT secret set, when the unsubscribe workflow is enabled', description='Warns about a missing `REPOMATIC_NOTIFICATIONS_PAT` when the unsubscribe workflow is enabled', applies=<function <lambda>>, fatal=False), RepoCheck(name='pat-permissions', run=<function check_pat_permissions>, summary='With a PAT, the Administration, Contents, Issues, Pull requests, Dependabot alerts and Workflows permissions of REPOMATIC_PAT', description='Fails when a configured `REPOMATIC_PAT` lacks one of the permissions the automation needs: Administration, Contents, Issues, Pull requests, Dependabot alerts and Workflows', applies=<function RepoCheck.<lambda>>, fatal=True), RepoCheck(name='pat-repository-scope', run=<function check_pat_scope>, summary='With a PAT, a REPOMATIC_PAT limited to this repository', description="Warns when a configured `REPOMATIC_PAT` also has access to another repository of the same owner. The check asks the owner's most recently pushed repositories for their Actions settings, which only a token covering them can read. The setup guide issue stays open on the same finding", applies=<function <lambda>>, fatal=False))

Every check lint-repo runs, in report order.

repomatic.lint_repo.roster.REPO_CHECK_HELP_LIST: str = "  - Package name matches the repository name (warning).\n  - A Sphinx project's website field names the documentation URL declared in\n    [project.urls] (warning).\n  - GitHub Pages publishes from GitHub Actions, when site.deploy targets\n    GitHub Pages (warning).\n  - CLOUDFLARE_API_TOKEN secret set, when site.deploy targets Cloudflare\n    Pages (warning).\n  - CLOUDFLARE_R2_ACCESS_KEY_ID and CLOUDFLARE_R2_SECRET_ACCESS_KEY secrets\n    set, when site.cloudflare-r2-bucket is declared (warning).\n  - Legacy github.io URLs still redirect, for a site moved to Cloudflare\n    Pages (warning).\n  - Committed _redirects files survive the Cloudflare Pages engine: no\n    dropped rules, no silent budget abort (error).\n  - wrangler.toml agrees with the declared Cloudflare project name and\n    compatibility date (warning).\n  - No tracked file over the 25 MiB Cloudflare Pages limit, unless an R2\n    bucket is declared to serve it (warning).\n  - No leftover gh-pages branch in a Sphinx project (warning).\n  - Repository description matches the project description (error).\n  - GitHub topics are a subset of the pyproject.toml keywords (warning).\n  - Funding file present when the owner has GitHub Sponsors (warning).\n  - No stale draft release, whose tag is not a .dev0 (warning).\n  - Every repository label is declared by a configured label source\n    (warning).\n  - Install guide download URLs resolve to real release assets (warning).\n  - No active tag ruleset that can block a release tag push (warning).\n  - At least one active branch ruleset (warning).\n  - No classic branch protection rule beside the rulesets (warning).\n  - Immutable releases enabled, for a repository publishing releases\n    (warning).\n  - Fork PR workflow approval policy strict enough (warning).\n  - Actions required to be pinned to a full-length commit SHA (warning).\n  - The latest PyPI release's provenance names this repository's\n    release.yaml (warning).\n  - Workflows and reusable-workflow callers declare their permissions\n    (warning).\n  - Every standalone workflow can be started by hand (warning).\n  - Thin callers pin the upstream workflows to a release, not to @main\n    (warning).\n  - Thin callers carry the triggers of the workflow they call (warning).\n  - Thin callers pass every secret the workflow they call declares\n    (warning).\n  - Every test-matrix exclude entry names a value on some matrix axis\n    (warning).\n  - Python classifiers, requires-python and the workflow test matrices agree\n    (warning).\n  - No job runs on a -latest alias or on an image outside the test matrices\n    (warning).\n  - Each release-only step tests the capability it needs, and runs on a\n    release commit (warning).\n  - The manpages.script lockfile pins a click-extra able to render man pages\n    (warning).\n  - Seeded tool configs carry every bundled template entry, or decline it\n    with a reason (warning).\n  - No bare [tool.lychee] exclude entry the bundled template now anchors\n    (warning).\n  - Inline upstream pins match the version the uses: refs name (error).\n  - Inline upstream pins resolving under a cooldown carry their\n    --exclude-newer-package exemption (error).\n  - Every astral-sh/setup-uv step pins one uv version (warning).\n  - The pinned uv carries a checksum in the pinned astral-sh/setup-uv\n    (warning).\n  - Every repomatic run tool pin is past the cooldown, or an\n    exclude-newer-package entry admits it (warning).\n  - Workflows only ask repomatic show-metadata for keys it still emits\n    (error).\n  - Repository-local PR body templates sit in .github/pr-templates/ and\n    carry valid frontmatter (warning).\n  - VIRUSTOTAL_API_KEY secret set, when Nuitka is active (warning).\n  - REPOMATIC_NOTIFICATIONS_PAT secret set, when the unsubscribe workflow is\n    enabled (warning).\n  - With a PAT, the Administration, Contents, Issues, Pull requests,\n    Dependabot alerts and Workflows permissions of REPOMATIC_PAT (error).\n  - With a PAT, a REPOMATIC_PAT limited to this repository (warning)."

The lint-repo --help check list, one item per REPO_CHECKS entry.

Rendered from the roster, so the help cannot name fewer checks than the command runs.

repomatic.lint_repo.roster.repo_check_reference()[source]

The lint-repo job’s check list for docs/workflows.md, as Markdown.

One bullet per REPO_CHECKS entry, from its description, in report order. Rendered from the roster for the same reason as REPO_CHECK_HELP_LIST: the page cannot describe fewer checks than the command runs.

Return type:

str

repomatic.lint_repo.roster.run_repo_lint(ctx)[source]

Run every check of REPO_CHECKS that applies to the repository.

Reports nothing itself: the caller renders each result at the level of its check, and fails when fails() says so. Only a fatal check can fail the command; everything else is advisory, so a scheduled run stays green on findings a maintainer merely needs to see.

Parameters:

ctx (LintContext) – Everything the checks read. Build it with from_project() to derive the project facts the way the CLI does, or directly for a hand-assembled probe.

Return type:

Iterator[tuple[RepoCheck, CheckResult]]

Returns:

Each result, with the check that produced it, in report order.