Skip to content

ci: fail a PR that leaves an orphaned image under src/content - #12771

Open
jd wants to merge 2 commits into
mainfrom
devs/jd/jd/orphaned-images/fail-pr-leaves-orphaned-image-under-src-content--7a8544e1
Open

ci: fail a PR that leaves an orphaned image under src/content#12771
jd wants to merge 2 commits into
mainfrom
devs/jd/jd/orphaned-images/fail-pr-leaves-orphaned-image-under-src-content--7a8544e1

Conversation

@jd

@jd jd commented Sep 10, 2026

Copy link
Copy Markdown
Member

Prose moves and an asset does not, and a one-off deletion pass alone
just recurs on the next page rewrite or removal. Adds
scripts/check-orphaned-images.mjs, matching the internal-leaks check's
shape (plain-Node scanner, its own vitest suite, pnpm script, CI job):
for every image file under any images/ directory within src/content/,
it checks whether any source file (src/, integrations/, plugins/)
spells out /images/<path from the nearest such directory> — the
substring every relative import carries, anchored on the leading
slash, regardless of how many ../ it climbs.

Matches on that anchored path, not on basename alone. A basename-only
sweep of the whole tree is what missed
workflow/writing-your-first-rule/config-editor.png in the previous
commit on the first pass: a same-named config-editor.png under
configuration/ is genuinely imported, so the orphan read as
referenced. It also does not assume every image lives under
src/content/images/ — src/content/docs/images/merge-queue-hero.jpg is
real and referenced, sitting next to the page that imports it instead
of in the shared tree, so the scan walks for any images/ directory
under src/content/ rather than that one path.

Also covers .avif (a supported documentation image format the first
pass omitted), and fails closed when two images share the same
/images/<...> needle across different roots: rather than let one
import clear both, it reports every image in a colliding group so a
human resolves the ambiguity.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

docs#12728 dropped the real-invoice billing example from billing.mdx —
both <Image> uses and both import lines — and left
invoice-previous-period.png and invoice-next-period.png behind with
nothing pointing at them.

A repo-wide sweep for the same pattern (path-relative-to-images/, not
basename — see the next commit) turned up five more:
merge-protections/freeze-main.png and stacked-gh-pr.png /
stacked-mergify-pr.png were never wired into the pages they were added
for, and workflow/writing-your-first-rule/{summary,config-editor}.png
belonged to a page removed wholesale in 068ac36.

Deleting first, before the check that follows, so that check is never
red on main.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Change-Id: I770291bedc49acb609264a58b7032c9fad738c58
@jd

jd commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

This pull request is part of a Mergify stack:

# Pull Request Link
1 docs: delete images nothing references #12770
2 ci: fail a PR that leaves an orphaned image under src/content #12771 👈

@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 10, 2026 19:34 Failure
@jd
jd added this pull request to stack #12772 September 10, 2026 19:34
@mergify

mergify Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 2 of 6 protections blocking · waiting on 👀 reviews

Protection Waiting on
🔴 👀 Review Requirements 👀 reviews
🔴 🔎 Reviews 👀 reviews
🟢 🤖 Continuous Integration
🟢 Enforce conventional commit
🟢 📕 PR description
🟢 🚦 Auto-queue

🔴 👀 Review Requirements

Waiting for

  • #approved-reviews-by >= 1
This rule is failing.
  • any of:
    • #approved-reviews-by >= 1
    • author = dependabot[bot]
    • author = renovate[bot]
    • all of:
      • author = mergify-ci-bot
      • -head ~= ^docs-agent/

🔴 🔎 Reviews

Waiting for

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

Show 4 satisfied protections

🟢 🤖 Continuous Integration

  • all of:
    • check-success = build
    • check-success = diagram-tokens
    • check-success = lint
    • check-success = test
    • any of:
      • check-success = test-broken-links
      • label = ignore-broken-links
    • any of:
      • check-success=Cloudflare Pages
      • -head-repo-full-name~=^Mergifyio/

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:

🟢 📕 PR description

  • body ~= (?ms:.{48,})

🟢 🚦 Auto-queue

When all merge protections are satisfied, this pull request will be queued automatically.

@mergify
mergify Bot requested a review from a team September 10, 2026 19:37

@jd jd left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

missing entry in mergify config to make this ci mandatory

@jd
jd force-pushed the devs/jd/jd/orphaned-images/fail-pr-leaves-orphaned-image-under-src-content--7a8544e1 branch from 9c3f2e2 to e913075 Compare September 11, 2026 07:38
Copilot AI lite review requested due to automatic review settings September 11, 2026 07:38
@jd

jd commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Revision history

# Type Changes Reason Date
1 initial 9c3f2e2 2026-09-11 07:38 UTC
2 content 9c3f2e2 → e913075 review: make orphaned-images check-run mandatory by adding it to the CheckRuns anchor in .mergify.yml 2026-09-11 07:38 UTC
3 content e913075 → 2fa2c6e review: copilot flagged .avif support and a duplicate-needle ambiguity across images/ roots — both fixed, with regression tests 2026-09-11 11:32 UTC

@jd

jd commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Added check-success = orphaned-images to the CheckRuns anchor in .mergify.yml, so this check is now mandatory for merge — addresses the review comment above.

9c3f2e2e913075

@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 11, 2026 07:40 Failure

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

The scanner omits supported .avif assets, allowing orphaned AVIF files to pass undetected.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds automated detection of orphaned images under src/content, with tests and CI/merge protections.

Changes:

  • Adds a path-aware orphaned-image scanner.
  • Adds Vitest coverage, a package script, and documentation.
  • Integrates the check into CI and Mergify protections.
File summaries
File Summary
scripts/check-orphaned-images.test.mjs Adds scanner and repository tests.
scripts/check-orphaned-images.mjs Implements orphan detection; moderate issue: supported .avif files are excluded.
package.json Adds the check script.
AGENTS.md Documents the command.
.mergify.yml Requires the check for merging.
.github/workflows/ci.yaml Adds the CI validation job.
Review details

Suppressed comments (1)

scripts/check-orphaned-images.mjs:100

  • These needles discard the path above the selected images/ directory. If src/content/images/hero.png and src/content/docs/images/hero.png both exist (both layouts are supported by findImages), a single import of either produces /images/hero.png, so findOrphans marks both files as referenced and lets the other orphan pass. Please either resolve imports per source file or detect duplicate needles and fail as ambiguous.
  const idx = parts.lastIndexOf(IMAGES_DIRNAME);
  return `/${parts.slice(idx).join('/')}`;
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/check-orphaned-images.mjs Outdated
Prose moves and an asset does not, and a one-off deletion pass alone
just recurs on the next page rewrite or removal. Adds
scripts/check-orphaned-images.mjs, matching the internal-leaks check's
shape (plain-Node scanner, its own vitest suite, pnpm script, CI job):
for every image file under any images/ directory within src/content/,
it checks whether any source file (src/, integrations/, plugins/)
spells out `/images/<path from the nearest such directory>` — the
substring every relative import carries, anchored on the leading
slash, regardless of how many `../` it climbs.

Matches on that anchored path, not on basename alone. A basename-only
sweep of the whole tree is what missed
workflow/writing-your-first-rule/config-editor.png in the previous
commit on the first pass: a same-named config-editor.png under
configuration/ is genuinely imported, so the orphan read as
referenced. It also does not assume every image lives under
src/content/images/ — src/content/docs/images/merge-queue-hero.jpg is
real and referenced, sitting next to the page that imports it instead
of in the shared tree, so the scan walks for any images/ directory
under src/content/ rather than that one path.

Also covers .avif (a supported documentation image format the first
pass omitted), and fails closed when two images share the same
`/images/<...>` needle across different roots: rather than let one
import clear both, it reports every image in a colliding group so a
human resolves the ambiguity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Change-Id: I7a8544e1209554c67202175985a75db65b0ac00f
@jd
jd force-pushed the devs/jd/jd/orphaned-images/fail-pr-leaves-orphaned-image-under-src-content--7a8544e1 branch from e913075 to 2fa2c6e Compare September 11, 2026 11:32
@jd

jd commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Pushed a fix for both things Copilot's review flagged:

  • IMAGE_EXTENSIONS now includes .avif (was silently excluding it), with a regression test.
  • findOrphans now fails closed when two images under different images/ roots share the same /images/<...> needle — previously a single import would have cleared both regardless of which one it actually referenced. Also covered by a regression test. No such collision exists in the repo today (verified against the live tree), so this doesn't change current output — it just stops the checker from silently guessing if one shows up later.

e9130752fa2c6e

@mergify
mergify Bot had a problem deploying to Mergify Merge Protections September 11, 2026 11:35 Failure
Base automatically changed from devs/jd/jd/orphaned-images/delete-images-nothing-refs--770291be to main September 11, 2026 12:40
@jd
jd marked this pull request as ready for review September 11, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants