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. |
… (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.
…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" }
…#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" }
…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>
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