Every check: why it exists, the API it uses, what apply does, how to undo it.
{o}/{r} = owner/repo, {b} = default branch. All endpoints are GitHub REST
(https://docs.github.com/en/rest) unless noted. Status legend: ✅ OK, ⚠️ recommended, ❌ action needed, ➖ not applicable.
Default apply items are the ones that are invisible to visitors and easy to revert. Opt-in items
need --only <id>.
GET /repos/{o}/{r}/vulnerability-alerts (204 = on, 404 = off).PUT /repos/{o}/{r}/vulnerability-alerts.DELETE the same path, or Settings → Advanced Security.GET / PUT /repos/{o}/{r}/automated-security-fixes.DELETE the same path.security_and_analysis in GET /repos/{o}/{r} (only visible to admins).PATCH /repos/{o}/{r} with {"security_and_analysis":{"secret_scanning":{"status":"enabled"}}}
(and secret_scanning_push_protection)."disabled".SECURITY.md points to it.GET / PUT /repos/{o}/{r}/private-vulnerability-reporting.DELETE the same path.GET /repos/{o}/{r}/languages: C/C++ → c-cpp, C# → csharp, Go → go,
Java/Kotlin → java-kotlin, JavaScript/TypeScript → javascript-typescript, Python → python, Ruby → ruby,
Swift → swift. No match → ➖ “no CodeQL-supported language”.github/codeql-action counts as ✅ (advanced setup); default setup is not added on top.GET /repos/{o}/{r}/code-scanning/default-setup (state: configured / not-configured).PATCH the same path with {"state":"configured"} (languages auto-detected; GitHub answers 202 and runs a validation).PATCH with {"state":"not-configured"}.schedule.interval: monthly
and a single groups entry (patterns: ["*"]) per ecosystem → at most one PR per ecosystem per month.package.json → npm, requirements*.txt / pyproject.toml / setup.py / Pipfile → pip,
uv.lock → uv, Cargo.toml → cargo, go.mod → gomod, composer.json → composer, Gemfile → bundler,
Dockerfile* → docker, docker-compose*.yml / compose.yml → docker-compose, *.csproj/*.fsproj/*.vbproj/packages.config → nuget,
pom.xml → maven, build.gradle(.kts) → gradle, *.tf → terraform, Package.swift → swift, pubspec.yaml → pub,
mix.exs → mix, elm.json → elm, Chart.yaml → helm, .gitmodules → gitsubmodule, .pre-commit-config.yaml → pre-commit,
and github-actions whenever .github/workflows/*.yml exists. The ecosystem names are the package-ecosystem values listed in
Dependabot’s options reference; the manifest file names for the less common ones are the conventional names (see the note in ROADMAP.md).third_party/, vendor/, external/, deps/, node_modules/… are ignored on purpose (the audit says so):
Dependabot does not update copied-in source..github/dependabot.yml: never modified. Missing ecosystems, and manifests in directories the existing entry does not cover
(directory / directories, globs such as /* understood), are printed as a proposal to paste. github-actions is not checked per directory.--commit-files commits through
PUT /repos/{o}/{r}/contents/{path}. See the release-on-push warning below.uses: owner/action@v4 can be re-pointed by whoever controls the tag; a commit SHA cannot. Local (./) and docker:// refs are ignored.github-actions) then updates both.GITHUB_TOKEN limits the damage of a compromised workflow step.GET / PUT /repos/{o}/{r}/actions/permissions/workflow with {"default_workflow_permissions":"read"}.permissions: will start failing.
Add permissions: contents: write (etc.) to those jobs first.PUT with "write". May answer 409 if an organization policy owns the setting.peter-evans/create-pull-request, gh pr create or pulls.create in a workflow fail with GitHub Actions is not permitted to create or approve pull requests when the repo setting
Settings -> Actions -> General -> Workflow permissions -> Allow GitHub Actions to create and approve pull requests is off (this exact failure was hit by this project’s own release-please workflow).can_approve_pull_request_reviews from GET /repos/{o}/{r}/actions/permissions/workflow. ✅ when no workflow needs it or it is on.PUT the same path with {"default_workflow_permissions": <current value>, "can_approve_pull_request_reviews": true}. Opt-in because it also lets a workflow approve PRs. Undo: the same call with false (restore does it).permissions: block anywhere (the repo default token permission applies); pull_request_target together with a checkout of the pull request’s code;
and a value an outsider controls (PR / issue title or body, head_ref, branch name, commit message) expanded with $ inside a run: script.env: variable instead of expanding them in the script, and says workflows triggered by
pull_request_target must not check out untrusted code (https://docs.github.com/en/actions/reference/security/secure-use). The list of risky context fields here is a pragmatic subset, not the full list.GET /repos/{o}/{r}/dependabot/alerts?state=open: ⚠️ with the count by severity and the Security-tab URL; ➖ when the token cannot read alerts or alerts are off (the exact status the API uses for “off” was not confirmed).GET /repos/{o}/{r}/branches/{b}/protection →
required_pull_request_reviews) or a ruleset (GET /repos/{o}/{r}/rules/branches/{b} → pull_request rule), andGET /repos/{o}/{r}/collaborators → permissions.push).gh api -X DELETE repos/{o}/{r}/branches/{b}/protection/required_pull_request_reviews,
gh api -X DELETE repos/{o}/{r}/branches/{b}/protection/enforce_admins (when on), settings URL
https://github.com/{o}/{r}/settings/branches; for a ruleset: gh api -X PUT repos/{o}/{r}/rulesets/<id> -f enforcement=disabled
or edit it at https://github.com/{o}/{r}/settings/rules/<id>.git push --force or git push origin :main should not be able to destroy the default branch.{b} include both deletion and non_fast_forward; or classic protection with
force-pushes and deletions disallowed.POST /repos/{o}/{r}/rulesets:
{"name":"solo-guard","target":"branch","enforcement":"active",
"conditions":{"ref_name":{"include":["~DEFAULT_BRANCH"],"exclude":[]}},
"rules":[{"type":"deletion"},{"type":"non_fast_forward"}]}
No pull-request rule, no required checks, no bypass list: you can still push and merge directly.
gh api -X PUT repos/{o}/{r}/rulesets/<id> -f enforcement=disabled, do the work,
then -f enforcement=active. <id> is printed after creation, or gh api repos/{o}/{r}/rulesets. Or Settings → Rules → Rulesets → solo-guard → Disable.solo-guard ruleset exists but is not active, it is reported and left alone.POST /repos/{o}/{r}/rulesets with {"name":"solo-tag-guard","target":"tag","enforcement":"active","conditions":{"ref_name":{"include":["refs/tags/v*"],"exclude":[]}},"rules":[{"type":"deletion"},{"type":"non_fast_forward"}]}.solo-guard (set enforcement to disabled).refs/tags/v* pattern was applied and reverted against the live API (see ROADMAP).delete_branch_on_merge in GET / PATCH /repos/{o}/{r}. Undo: set false.has_discussions in GET / PATCH /repos/{o}/{r}. Public-facing, so opt-in. Undo: set false.https_enforced is false is reported ⚠️ (turn on Enforce HTTPS in Settings -> Pages).GET /repos/{o}/{r}/pages (404 = not set up).docs/index.html → /docs; else root index.html → /; else / (GitHub then renders the README as the top page).
Override with --pages-path / | /docs.POST /repos/{o}/{r}/pages with {"build_type":"legacy","source":{"branch":"{b}","path":"/docs"}}.
If homepage is empty it is then set to the Pages URL (PATCH /repos/{o}/{r}). Pages sites are public even for private repos on paid plans.DELETE /repos/{o}/{r}/pages; clear the homepage by hand.--profile library); or only pre-releases (GET /repos/{o}/{r}/releases/latest ignores pre-releases and drafts → 404);
or every asset name contains a version (so /releases/latest/download/<asset> changes name each release).solo.py links and references/release-latest.md.my-package-v0.2.0 (what release-please produces by default, because it adds the package name) looks odd in release links and breaks tooling that expects vX.Y.Z.v1.2.3, 1.2.3, v1.2.3-rc.1); ⚠️ when it carries a prefix or is not a version; ➖ when there is no release yet (and for --profile site / docs)."include-component-in-tag": false in release-please-config.json and, before the next release, create a vX.Y.Z tag on the same commit as the old one so release-please still finds the last release
(the option changes the tag pattern it searches for; see the release-please manifest docs).GET /repos/{o}/{r}/actions/runs?branch={b}&status=completed: the newest completed run of each workflow file on the default branch; ⚠️ if it failed / timed out. Dependabot’s own update runs (not workflow files) are ignored. ➖ when there are no runs or Actions cannot be read.on: push incl. branches/branches-ignore/tags
filters) AND contains gh release create, softprops/action-gh-release, release-please, actions/create-release,
ncipollo/release-action, semantic-release, changesets/action (strong) or only contents: write (weak).release-please is on the strong list because merging its release PR (a push) publishes a release. Ordinary pushes only update the PR,
so for a release-please-only repo the warning is conservative.apply prints a warning before it writes/commits files, and --commit-files is refused unless --accept-release-risk is given.
It is a heuristic. Called reusable workflows (uses: ./.github/workflows/x.yml) are followed one level; an if: mentioning refs/tags/
downgrades the finding to weak. Other conditions, matrix tricks and cross-repo workflows are not followed..github/release.yml makes “Generate release notes” group PRs by label and drop Dependabot’s PRs
(changelog.exclude.authors, changelog.categories; see “Automatically generated release notes” in the GitHub docs).description and topics come from GET /repos/{o}/{r}. topics can be set with --only topics --topics a,b
(PUT /repos/{o}/{r}/topics, replaces all topics; lowercase, digits, hyphens, ≤50 chars, ≤20 topics).license is never generated: choosing one is your decision (https://choosealicense.com/)..github/release.yml groups PRs by the labels breaking-change, enhancement and bug; without them every PR lands in “Other Changes”.GET /repos/{o}/{r}/labels. Apply: POST /repos/{o}/{r}/labels for each missing one (name, color, description). Existing labels are never touched.DELETE /repos/{o}/{r}/labels/{name} (restore does this for the labels it created)..github/pull_request_template.md, .github/ISSUE_TEMPLATE/bug_report.md, .github/ISSUE_TEMPLATE/feature_request.md, CONTRIBUTING.md (same file handling as the other generated files). CODE_OF_CONDUCT is not generated: pick a text you endorse (for example the Contributor Covenant).has_issues from GET /repos/{o}/{r}: ⚠️ when Issues are off, because people then cannot report problems or ask questions (vulnerabilities go through SECURITY.md). Switch it back on in Settings -> General -> Features.SECURITY.md (root, .github/ or docs/) present → ✅. Otherwise a template pointing at
https://github.com/{o}/{r}/security/advisories/new is generated (same file handling as above). Undo: delete the file.repository { usesCustomOpenGraphImage }. The image cannot be set through the API; upload it at
https://github.com/{o}/{r}/settings → Social preview.apply --yes makes no writes: every item is derived from the current state, and files that exist (locally or in the repo) are never touched.apply makes no deletions and never overwrites. The only PUT that replaces data is topics, which is opt-in and requires --topics.