Skip to content

Scope Dependabot to our beyond-template packages - #224

Open
alex-rawlings-yyc wants to merge 8 commits into
mainfrom
dependabot-security-updates
Open

Scope Dependabot to our beyond-template packages#224
alex-rawlings-yyc wants to merge 8 commits into
mainfrom
dependabot-security-updates

Conversation

@alex-rawlings-yyc

@alex-rawlings-yyc alex-rawlings-yyc commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Template-owned dependencies move only when we merge template changes, so the allow list covers just the packages this extension adds. Security updates stay inert until the repo's dependency graph is enabled.


This change is Reviewable

Summary by CodeRabbit

  • Chores
    • Added monthly automated checks for npm and GitHub Actions updates.
    • Limited dependency updates to extension-owned packages and excluded sibling file dependencies.
    • Grouped compatible test-tooling and workflow updates while keeping major updates separate.
    • Added dependency-scope validation to linting to detect unsupported or inconsistent dependencies.
  • Documentation
    • Documented dependency validation, update coverage, version exceptions, and template synchronization requirements.

@alex-rawlings-yyc alex-rawlings-yyc self-assigned this Aug 13, 2026
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review available on request

  • 🔍 Trigger review

Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment @coderabbitai review to review the latest changes. For a full review, comment @coderabbitai full review.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 185932cb-4ecf-4add-98f0-085378b2f4a0

📝 Walkthrough

Walkthrough

Added dependency-scope validation against a recorded merged template commit. The lint workflow now fetches full history, Dependabot manages monthly updates, and the README documents baseline and dependency-scope maintenance.

Changes

Dependency scope validation

Layer / File(s) Summary
Implement dependency-scope validation
scripts/check-dependency-scope.cjs
The script reads the template manifest and Dependabot configuration. It detects dependency-scope violations, stale version exceptions, unsupported file: dependencies, and unavailable or unmerged baselines.
Wire validation and dependency updates
package.json, .github/workflows/lint.yml, .github/dependabot.yml
The lint command runs dependency validation. The workflow fetches full Git history. Dependabot performs monthly npm and GitHub Actions updates with grouped minor and patch updates.
Document baseline maintenance
README.md
The README documents merged template commit updates, dependency-scope ownership, version exceptions, template comparison, and shallow-clone handling.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: 🟡 Moderate · up to a0bd2

Adding js-yaml without updating package-lock.json will cause the lint workflow's dependency installation to fail, so the change is not ready to merge until the lockfile is regenerated and committed.

Sequence Diagram(s)

sequenceDiagram
  participant Lint as npm lint
  participant Scope as check-dependency-scope.cjs
  participant Git as Git history
  participant Config as Dependabot config
  Lint->>Scope: Run dependency-scope validation
  Scope->>Git: Read merged template commit manifest
  Scope->>Config: Read npm allow and ignore lists
  Scope->>Scope: Compare manifests and validate scope
  Scope-->>Lint: Report violations and exit status
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: restricting Dependabot updates to packages introduced by the extension.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dependabot-security-updates

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@alex-rawlings-yyc alex-rawlings-yyc linked an issue Aug 13, 2026 that may be closed by this pull request
@alex-rawlings-yyc

alex-rawlings-yyc commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Why this config has an ignore block

Dependabot cannot run on this repo without it. platform-bible-utils, papi-dts, and
platform-bible-react are file: deps resolving against a sibling paranext-core checkout —
present on dev machines and in CI (test.yml clones both repos), absent inside Dependabot's
container. It aborts during file fetching before reaching any of our packages:

ERROR Error during file fetching; aborting: The following path based
dependencies could not be retrieved: platform-bible-utils

Naming the three in ignore makes the fetcher skip them. This is also why no repo in the
paranext org has a dependabot.yml — the template carries the same file: deps.

Verified before opening this PR

Run against an identical package.json + package-lock.json in a scratch repo
(alex-rawlings-yyc/dependabot-pathdep-test), so nothing unproven landed on main:

  • Job completed successfully — the path-dependency abort is gone, and npm regenerated the
    lockfile without the sibling checkout.
  • Three PRs, as designed: one grouped test-tooling PR (@playwright/test,
    @testing-library/user-event, ws — all patch), plus eslint-plugin-jest 28→29 and
    @testing-library/jest-dom 6→7 as separate majors.
  • Scope confirmed: the only version changes were our packages and Playwright's own
    transitives. No template-owned package was bumped.

One thing reviewers will see: the grouped PR also adds six
@tailwindcss/oxide-wasm32-wasi/node_modules/* lockfile entries. Those are optional wasm platform
deps npm materializes on any lockfile regeneration — nothing is bumped or removed. It is not the
allow list leaking.

Known limitation

allow is name-based, and npm doesn't support dependency-type: indirect, so there is no way to
express "these packages plus everything they pull in." Advisories against transitive deps of the 14
won't raise a PR — both vulnerabilities currently reachable only through our packages are in Jest's
istanbul chain (test-exclude → brace-expansion, @istanbuljs/load-nyc-config → js-yaml). They
clear when Dependabot bumps jest, not via a security PR. Left unpinned deliberately: they're
dev-only, nothing ships them, and hand-pinning transitives in package.json is exactly what this
policy avoids.

Separately

Dependabot alerts and security updates still can't fire — this repo's dependency graph has
zero manifests, so alerts have been silently empty since January (npm audit reports 5). That
needs Settings → Advanced Security, independent of this PR. Version updates need only this file.

@alex-rawlings-yyc
alex-rawlings-yyc marked this pull request as ready for review August 13, 2026 20:52

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@imnasnainaec reviewed all commit messages and made 1 comment.
Reviewable status: 0 of 1 files reviewed, 1 unresolved discussion (waiting on alex-rawlings-yyc).


.github/dependabot.yml line 15 at r1 (raw file):

    directory: /
    schedule:
      interval: weekly

Weekly can be pretty annoying. I'd opt for monthly.

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ Might we want a script that compares our package-lock.json to the template's, to prevent drift?

@imnasnainaec made 3 comments.
Reviewable status: 0 of 1 files reviewed, 3 unresolved discussions (waiting on alex-rawlings-yyc).


.github/dependabot.yml line 12 at r1 (raw file):

version: 2
updates:
  - package-ecosystem: npm

⛏️ from Devin that I agree with:

Only npm is covered; GitHub Actions workflows get no updates

The repo has six workflows under .github/workflows/ plus composite actions in .github/actions/, and no github-actions ecosystem entry is configured. Action pins therefore receive neither version nor security updates. This is consistent with the PR's npm-only scoping, but the template rationale (lockfile conflicts on template merges) does not apply to action pins, so a separate github-actions entry may be worth adding later.


.github/dependabot.yml line 19 at r1 (raw file):

    # checkout, which exists on developer machines and in CI but not inside
    # Dependabot's container. Without these entries Dependabot aborts the whole
    # job during file fetching and never reaches the allow list below.

❓ from Devin:

Ignore entries may not actually prevent the abort on file: dependencies
The comment claims Dependabot "aborts the whole job during file fetching" for the three file:../paranext-core/... dependencies and that these ignore entries prevent it. ignore rules are applied when Dependabot filters the parsed dependency list, which happens after the file fetcher/parser stage; if the failure genuinely occurs during file fetching or lockfile parsing, ignore would not suppress it. Since these three packages are also absent from allow, the entries are otherwise redundant. Worth confirming against an actual Dependabot run log rather than relying on the stated rationale.

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might the comparing the lockfiles be too noisy? Though, if we're only updating it on Template merge, it may not actually be

@alex-rawlings-yyc made 4 comments.
Reviewable status: 0 of 1 files reviewed, 3 unresolved discussions (waiting on alex-rawlings-yyc and imnasnainaec).


.github/dependabot.yml line 12 at r1 (raw file):

Previously, imnasnainaec (D. Ror.) wrote…

⛏️ from Devin that I agree with:

Only npm is covered; GitHub Actions workflows get no updates

The repo has six workflows under .github/workflows/ plus composite actions in .github/actions/, and no github-actions ecosystem entry is configured. Action pins therefore receive neither version nor security updates. This is consistent with the PR's npm-only scoping, but the template rationale (lockfile conflicts on template merges) does not apply to action pins, so a separate github-actions entry may be worth adding later.

Do we want to add an issue to address this later or do it right now?


.github/dependabot.yml line 15 at r1 (raw file):

Previously, imnasnainaec (D. Ror.) wrote…

Weekly can be pretty annoying. I'd opt for monthly.

Agreed


.github/dependabot.yml line 19 at r1 (raw file):

Previously, imnasnainaec (D. Ror.) wrote…

❓ from Devin:

Ignore entries may not actually prevent the abort on file: dependencies
The comment claims Dependabot "aborts the whole job during file fetching" for the three file:../paranext-core/... dependencies and that these ignore entries prevent it. ignore rules are applied when Dependabot filters the parsed dependency list, which happens after the file fetcher/parser stage; if the failure genuinely occurs during file fetching or lockfile parsing, ignore would not suppress it. Since these three packages are also absent from allow, the entries are otherwise redundant. Worth confirming against an actual Dependabot run log rather than relying on the stated rationale.

I'm looking into this now; I'll come back with some sort of answer

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude's thoughts:

Worth doing, and I went and measured it — the drift is real, but it's the manifest that's checkable, not the lockfile.

package.json vs template/main:

shared deps: 57  |  version-range mismatches: 2
  @tailwindcss/postcss: tmpl ^4.0.0 vs ours ^4.3.0
  tailwindcss:          tmpl ^4.0.0 vs ours ^4.3.0
ours-only: 14   ← exactly the allow list in this PR, no more, no less
template-only: 0

package-lock.json vs template/main:

ours 1266 packages, template 1012
only in ours: 390   only in template: 136
shared package, different version: 278   (mostly @babel/*, all ours-newer)

~670 differences today, with no Dependabot PR ever merged — a lockfile comparison would need ~670 baselined exceptions before it could report anything new. It isn't the template running ahead of us either; template/main is only 3 commits past our last update-from-template, and none of them touch dependencies.

The cause is known: 5f44a9d (the React 19 / Tailwind 4 baseline) is a commit shared with the template, so at that point our lockfile was the template's and described none of our own dependencies. 791ffd6 the next day regenerated it (+343 packages, −89, 219 version changes) — 219 of the 278 in one commit. The rest came from running core:reinstall before committing on a handful of feature PRs. Our policy is that the lockfile moves only on template merges and, once this lands, Dependabot PRs.

One wrinkle worth naming: there's a third legitimate case. Our lockfile snapshots the full dependency manifests of the three file:-linked core libs, and two of those feature-PR lockfile diffs carried real changes to them (#131 platform-bible-react; #180 platform-bible-react + platform-bible-utils). Since CI installs the extension with npm ci, if core's manifest changes never land we'd be testing against a tree that doesn't match the core we cloned. So core-lib syncs have to be allowed through.

Which suggests two checks, neither of them a lockfile diff:

  1. Lockfile changed, package.json didn't, and no ../paranext-core/lib/* entry changed — that's incidental drift with nothing legitimate in it. Checked against history it catches the five accidental ones and passes #131 and #180. Exempt Dependabot and update-from-template PRs.
  2. Manifest comparison — shared deps must have identical ranges; every ours-only dep must be in allow; every allow entry must be in our package.json and absent from the template's. That mechanizes the "keep the allow list in sync" instruction in the header comment, which is the part most likely to rot. Fires today on the two Tailwind entries — deliberate, from the React 19 / Tailwind 4 work, but recorded nowhere.

Happy to write both. Probably a separate PR from this one — want me to open an issue?

(Resetting the existing 278 back onto the template's pins is possible but I'd skip it: it downgrades 278 transitives for cosmetic gain, and check 1 stops the bleeding either way.)

@alex-rawlings-yyc made 3 comments.
Reviewable status: 0 of 1 files reviewed, 3 unresolved discussions (waiting on alex-rawlings-yyc and imnasnainaec).


.github/dependabot.yml line 12 at r1 (raw file):

Previously, alex-rawlings-yyc (Alex Rawlings) wrote…

Do we want to add an issue to address this later or do it right now?

Claude's opinion:

Agreed this is a gap, though I'd argue the template rationale doesn't apply here at all — I checked, and none of our action pins match the template's. It floats major tags (actions/checkout@v4, github/codeql-action@v3, ncipollo/release-action@v1); we SHA-pinned every one of them back in #82. All four template-owned workflows are already locally modified too (lint.yml +19/-5, publish.yml +68/-10, codeql.yml +5/-3, bump-versions.yml +4/-4), and update-from-template lands as a hand-curated squash — #204 was one file — so there's no mechanical merge for a pin bump to conflict with.

The more pressing part is that SHA-pinning opts us out of updates and we never added the thing that puts them back. The pins are frozen where #82 left them:

actions/checkout      pinned v6.0.2 (2026-01-09)  ->  latest v7.0.1 (2026-07-20)   major behind
actions/setup-node    pinned v6.4.0 (2026-04-20)  ->  latest v7.0.0 (2026-07-14)   major behind
github/codeql-action  pinned       (2026-05-22)  ->  latest bundle (2026-08-12)   ~3 months

CodeQL three months stale is the one I'd least like to leave sitting. Since our pins already carry # v6.0.2-style comments, Dependabot maintains the SHA and the comment together — no extra setup:

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly
    groups:
      actions:
        patterns: ['*']

Happy to add that here rather than defer it — it's six lines and the npm half of this config is already doing the harder job. Shout if you'd rather it went in its own PR.


.github/dependabot.yml line 19 at r1 (raw file):

Previously, alex-rawlings-yyc (Alex Rawlings) wrote…

I'm looking into this now; I'll come back with some sort of answer

Good check to insist on — I'd only verified that the config works, not that ignore was the reason it works. Turns out it is, and the finding's premise doesn't hold for npm.

The claim is that ignore is applied when filtering the parsed dependency list, downstream of the file fetcher. npm's fetcher actually consults the ignore list itself, in two places in npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb. In path_dependencies, before it ever tries to fetch:

if dependency_ignored?(name)
  Dependabot.logger.info(
    "Ignored local path dependency '#{cleaned_name}' for package '#{name}' as it matches the ignore list."
  )
  next
end

begin
  file = fetch_file_from_host(filename, fetch_submodules: true)

and again in build_unfetchable_deps, which is the path that actually bites us:

filtered_deps = unfetchable_deps.reject do |name, _path|
  if dependency_ignored?(name)
    Dependabot.logger.info("Ignored unfetchable path dependency '#{name}' as it matches the ignore list.")
    true

Our three don't trip either hard raise PathDependenciesNotReachable guard — those fire only on /-absolute paths or traversal past the repo root, and ../paranext-core/... is neither. So without ignore they fall through to fetch_file_from_hostDependencyFileNotFoundunfetchable_depsPathDependencyBuilder, which is where the abort originates.

That also answers the "otherwise redundant" half: the fetcher calls dependency_ignored? and never looks at allow, so leaving the three out of allow cannot substitute for listing them in ignore. The two keys aren't interchangeable here.

The comment was misleading about the mechanism ("never reaches the allow list" implied allow was the relevant knob), so I've rewritten it to name ignore specifically and say why allow can't cover it.

Worth noting the related bug reports where ignore genuinely doesn't suppress this are other ecosystems — dependabot/dependabot-core#14425 is Bundler, and it's closed with a fix.

@alex-rawlings-yyc
alex-rawlings-yyc force-pushed the dependabot-security-updates branch from 020c0e5 to e7a4469 Compare August 17, 2026 16:39

@imnasnainaec imnasnainaec left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I meant just comparing package.json with the template's. We don't worry about lockfile drift; rather we update package-lock.json after syncing from the template (and we could do the same atop a dependabot update for the non-template packages).

@imnasnainaec reviewed all commit messages, made 2 comments, and resolved 2 discussions.
Reviewable status: 0 of 1 files reviewed, 1 unresolved discussion (waiting on alex-rawlings-yyc).


.github/dependabot.yml line 12 at r1 (raw file):

Previously, alex-rawlings-yyc (Alex Rawlings) wrote…

Claude's opinion:

Agreed this is a gap, though I'd argue the template rationale doesn't apply here at all — I checked, and none of our action pins match the template's. It floats major tags (actions/checkout@v4, github/codeql-action@v3, ncipollo/release-action@v1); we SHA-pinned every one of them back in #82. All four template-owned workflows are already locally modified too (lint.yml +19/-5, publish.yml +68/-10, codeql.yml +5/-3, bump-versions.yml +4/-4), and update-from-template lands as a hand-curated squash — #204 was one file — so there's no mechanical merge for a pin bump to conflict with.

The more pressing part is that SHA-pinning opts us out of updates and we never added the thing that puts them back. The pins are frozen where #82 left them:

actions/checkout      pinned v6.0.2 (2026-01-09)  ->  latest v7.0.1 (2026-07-20)   major behind
actions/setup-node    pinned v6.4.0 (2026-04-20)  ->  latest v7.0.0 (2026-07-14)   major behind
github/codeql-action  pinned       (2026-05-22)  ->  latest bundle (2026-08-12)   ~3 months

CodeQL three months stale is the one I'd least like to leave sitting. Since our pins already carry # v6.0.2-style comments, Dependabot maintains the SHA and the comment together — no extra setup:

  - package-ecosystem: github-actions
    directory: /
    schedule:
      interval: monthly
    groups:
      actions:
        patterns: ['*']

Happy to add that here rather than defer it — it's six lines and the npm half of this config is already doing the harder job. Shout if you'd rather it went in its own PR.

I'm inclined toward here over its own pr.

@alex-rawlings-yyc alex-rawlings-yyc left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a script that does the comparison and added it to npm run lint

@alex-rawlings-yyc made 2 comments.
Reviewable status: 0 of 6 files reviewed, 1 unresolved discussion (waiting on imnasnainaec).


.github/dependabot.yml line 12 at r1 (raw file):

Previously, imnasnainaec (D. Ror.) wrote…

I'm inclined toward here over its own pr.

Added

Template-owned dependencies move only when we merge template changes, so
the allow list covers just the packages this extension adds. Security
updates stay inert until the repo's dependency graph is enabled.
npm's file fetcher consults `ignore` and never `allow`, so the comment
claiming the job "never reaches the allow list" named the wrong key.
SHA-pinned actions receive no updates without an ecosystem entry, and
nothing enforced the allow list's "absent from the template" rule.
Comparing against the template's moving head turned lint red on every PR
whenever the template bumped a shared range; reading the baseline out of
this repo's own history also lets CI drop the template checkout.
Failures
name a stale baseline as a possible cause, since it inverts their
advice.
@alex-rawlings-yyc
alex-rawlings-yyc force-pushed the dependabot-security-updates branch from d991f0b to a0bd260 Compare August 17, 2026 20:07
coderabbitai[bot]

This comment was marked as outdated.

A squashed template update leaves the pinned commit unreachable, which
would
fail every build; the copy also drops lint's git dependency and CI-only
skip.
Add npm run template:baseline and document when the refresh is needed.
merged-template-package.json from the template
commit that merge brought in, rather than acting on the lines above. Run
npm run template:baseline
while template/main still points at that commit.
The recorded id still named the state merged by #65. That template
commit's manifest is byte-identical to #204's, so only the id lagged —
the checked-in baseline copy needs no change.
Refreshing it runs a script rather than a shell redirect, which
truncated the file before git could fail. The check also compares
peerDependencies and names the file it could not parse.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add dependabot for security updates

2 participants