audit.py: check Dependabot ecosystem coverage against the repo tree (#346) - #347
Conversation
…346) The audit checked Dependabot secret stores but never that a repo's .github/dependabot.yml declares the ecosystems its tree implies, so ESPHome-Config shipping workflows with SHA-pinned actions but tracking only devcontainers passed the standup audit clean - its action pins get no bump PRs and the merge-bot it just stood up has nothing to merge. New crossCutting check setup.dependabot.ecosystems (repo-setup): for each implied ecosystem, dependabot.yml must declare it (dual-target main+develop per the fleet norm) - github-actions when .github/workflows/ ships actions, devcontainers when a .devcontainer is present. A missing implied ecosystem is a DRIFT finding. dependabot.yml is YAML (no stdlib parser) so the declared ecosystems are scanned by regex; the check only runs when the file exists (its absence is already a file-presence letter). Language ecosystems (nuget/uv/npm) are directory-scoped and left to inspection for now. Codified in AUDIT.md section 6 and spec/project-types.json. Verified live: ESPHome-Config flags github-actions (devcontainers correctly not flagged); Vantage-Config, HomeAutomation-Config, PlexCleaner, Utilities, aiopurpleair all clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new audit check to ensure repos’ Dependabot configuration covers ecosystems implied by the repo tree (notably github-actions when workflows exist, and devcontainers when a .devcontainer/ exists), so action SHA pins receive update PRs and the merge-bot has relevant PRs to auto-merge.
Changes:
- Extend
spec/audit.pywith a new DRIFT check that compares implied ecosystems (from repo contents) vs declaredpackage-ecosystemvalues in.github/dependabot.yml. - Document the new audit step in
AUDIT.mdand add a supporting reference link. - Register the new check as
setup.dependabot.ecosystemsinspec/project-types.json.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| spec/project-types.json | Adds the new cross-cutting repo-setup check definition for Dependabot ecosystem coverage. |
| spec/audit.py | Implements the new live audit logic to detect missing implied Dependabot ecosystems. |
| AUDIT.md | Documents the new manual audit step and provides a CLI snippet for verification. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
… (Copilot #347) The regex check asserts an implied ecosystem's presence only; it cannot pair an ecosystem with its target-branch, so the finding text no longer claims dual-target is enforced (it states the remedy: add it for both branches). AUDIT.md now separates the mechanical presence assertion from the by-inspection dual-target confirmation, and its snippet covers both github-actions and devcontainers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
AUDIT.md:92
- This section states
github-actionsis implied when workflows "ship SHA-pinned actions", but the mechanical check (and the snippet below) only test for the presence of.github/workflows/and workflow YAML files. To avoid inconsistent guidance, align this wording with what is mechanically asserted (or update both the snippet and spec/audit.py to actually detect action usage/pins in workflow contents).
- **Dependabot ecosystem coverage** - for each ecosystem the repo's tree implies, `.github/dependabot.yml` must declare it: `github-actions` when `.github/workflows/` ships SHA-pinned actions - otherwise the pins go stale and a stood-up merge-bot has no action-update PRs to auto-merge - and `devcontainers` when a `.devcontainer` is present. The mechanical check (`spec/audit.py`) asserts each implied ecosystem's **presence**; a tree-implied ecosystem declared nowhere is a **drift finding** (the file exists; its absence would instead be a file-presence letter). Then confirm **by inspection** that each declared ecosystem **dual-targets `main` + `develop`** per the [Branching Model][agents-branching-model] - the regex below cannot pair an ecosystem with its `target-branch`. Language ecosystems (`nuget`/`uv`/`npm`) are directory-scoped and audited by inspection too.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…ed claim (Copilot #347) - The package-ecosystem scan is line-anchored (^[ \t]*-?[ \t]*), so a commented-out '# package-ecosystem: ...' no longer reads as declared (which would false-negative the check). Verified against the dash-led and indented real forms and a commented sample. - The github-actions ecosystem is implied by .github/workflows/ *using* actions, not by SHA-pinning (which the code does not and need not verify); the rationale text drops the 'SHA-pinned' qualifier in audit.py, AUDIT.md, and project-types.json. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
spec/audit.py:198
- The audit currently implies the github-actions ecosystem based only on the presence of workflow YAML files (directory listing), but the rationale string says ".github/workflows/ uses actions". That is not what is being checked and can make the DRIFT message misleading. Either scan workflow contents for non-local
uses:entries, or adjust the reason text to match the actual heuristic (workflows present).
workflows = gh(f"repos/{slug}/contents/.github/workflows?ref={ground}", ok404=True)
if isinstance(workflows, list) and any(e["name"].endswith((".yml", ".yaml")) for e in workflows):
implied["github-actions"] = ".github/workflows/ uses actions"
if gh(f"repos/{slug}/contents/.devcontainer?ref={ground}", ok404=True) is not None:
spec/project-types.json:127
- This intent text says the github-actions ecosystem is implied when
.github/workflows/"uses actions", but the mechanical check in spec/audit.py only keys off the presence of workflow YAML files. To keep the spec aligned with the implemented audit, adjust this wording (or strengthen the audit to actually detectuses:entries).
{ "id": "setup.dependabot.ecosystems", "verdict": "intent", "assert": "For each ecosystem the repo's tree implies, .github/dependabot.yml declares it (dual-target main+develop per the fleet norm): github-actions when .github/workflows/ uses actions (else their versions go stale and a stood-up merge-bot has no PRs to auto-merge), devcontainers when a .devcontainer is present. A missing implied ecosystem is a drift finding. Language ecosystems (nuget/uv/npm) are directory-scoped, audited by inspection.", "intentRef": "AGENTS.md#branching-model" }
Uh oh!
There was an error while loading. Please reload this page.
…#347) The manual-audit snippet's grep now anchors package-ecosystem to the line start (optional list dash), matching the audit.py regex, so a commented-out entry is not counted as declared. Verified on a mixed active/commented sample. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (2)
spec/audit.py:197
- The implied-reason string says ".github/workflows/ uses actions", but this check only verifies that workflow YAML exists (it does not scan for
uses:). This can make the DRIFT message misleading. Reword the reason to match what is actually checked (workflow YAML presence), or strengthen the check to detectuses:entries.
implied["github-actions"] = ".github/workflows/ uses actions"
spec/project-types.json:127
- This assertion says the ecosystem is implied when workflows "use actions", but the mechanical audit (spec/audit.py) currently only checks for workflow YAML presence. Either align this text to the implemented check (workflow YAML present) or update the audit to actually detect
uses:lines.
{ "id": "setup.dependabot.ecosystems", "verdict": "intent", "assert": "For each ecosystem the repo's tree implies, .github/dependabot.yml declares it (dual-target main+develop per the fleet norm): github-actions when .github/workflows/ uses actions (else their versions go stale and a stood-up merge-bot has no PRs to auto-merge), devcontainers when a .devcontainer is present. A missing implied ecosystem is a drift finding. Language ecosystems (nuget/uv/npm) are directory-scoped, audited by inspection.", "intentRef": "AGENTS.md#branching-model" }
Uh oh!
There was an error while loading. Please reload this page.
…pilot #347) The check keys off the presence of .github/workflows/, so the rationale now reads "workflows/ is present (its workflows reference actions)" across audit.py, AUDIT.md, and project-types.json - no longer implying the check parses whether each workflow uses an action. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The prior commit's scripted edit flattened the file to LF; it follows the .editorconfig [*] end_of_line = crlf default (editorconfig-checker flagged it). Content unchanged; endings restored to CRLF. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Fixes the audit-coverage half of #346. (The concrete ESPHome-Config drift is filed as a separate downstream issue for that repo to fix.)
The gap
spec/audit.pychecked Dependabot secret stores but never that a repo's.github/dependabot.ymldeclares the ecosystems its tree implies. So ESPHome-Config - which shipstest-pull-request.yml/publish-release.yml/merge-bot-pull-request.ymlwith SHA-pinned actions but tracks onlydevcontainers- passed the standup audit clean, even though its action pins get no bump PRs and the merge-bot it just stood up has no action-update PRs to act on.The check
New crossCutting check
setup.dependabot.ecosystems(repo-setup dimension): for each ecosystem the tree implies,dependabot.ymlmust declare it (dual-targetmain+developper the fleet norm):github-actionswhen.github/workflows/ships actions,devcontainerswhen a.devcontaineris present.A missing implied ecosystem is a DRIFT finding.
dependabot.ymlis YAML (audit.py is stdlib-only, no parser), so the declaredpackage-ecosystemvalues are scanned by regex - enough to assert presence. The check only runs when the file exists (its absence is already a file-presence LETTER). Language ecosystems (nuget/uv/npm) are directory-scoped and left to inspection for now (noted in AUDIT.md).Codified in
AUDIT.mdsection 6 (with a shell snippet) andspec/project-types.json.Verification (live, read-only)
The
devcontainersecosystem ESPHome-Config does declare is correctly not flagged.spec/validate.pypasses; markdownlint + editorconfig-checker clean.🤖 Generated with Claude Code