Skip to content

Updated @tryghost/url-utils to 5.4.0 and froze url getters - #31293

Merged
acburdine merged 2 commits into
mainfrom
claude/url-utils-freeze-option-b62240
Oct 2, 2026
Merged

acburdine merged 2 commits into
mainfrom
claude/url-utils-freeze-option-b62240

Conversation

@acburdine

Copy link
Copy Markdown
Member

no ref

Summary

  • Bumps @tryghost/url-utils to 5.4.0 (Improved url-utils performance for sitemap-scale workloads SDK#1095), which adds an opt-in freeze() / frozen option that snapshots getSiteUrl, getSubdir and getAdminUrl, plus faster transformReadyToAbsolute and replacePermalink.
  • The shared urlUtils instance in core/shared/url-utils.ts is now created with frozen: true. Ghost's getSubdir runs new URL(config.get('url')) on every call, and url config never changes after boot, so this removes that work from hot paths like the sitemap build.
  • Tests change url config at runtime (~29 files via configUtils.set), so both vitest setup files (vitest-setup.ts, vitest-setup-db.ts) call urlUtils.unfreeze() once after overrides load. Sinon stubs on the getters keep working either way.
  • 5.4.0 builds the asset base URL defaults once at construction, so the media-inliner CDN tests that mutated the private urlUtils._assetBaseUrls no longer took effect. They now use the existing stubUrlUtilsWithCdn helper.
  • Patch changeset for @tryghost/kg-default-cards, which picks up the catalog bump.

Testing

  • pnpm test:types passes
  • Core unit: 9288 passed
  • kg-default-cards: 250 passed
  • Integration: 483 passed
  • E2E: 2661/2662 passed; the one failure is the config snapshot expecting database: mysql8 against my local MySQL, unrelated to this change

🤖 Generated with Claude Code

no ref

url-utils 5.4.0 adds an opt-in freeze that snapshots the site, subdir
and admin URLs. Ghost's getSubdir parses the configured url on every call,
which showed up as a hot spot in sitemap builds on large sites. The url
config never changes after boot, so the shared instance now freezes at
construction.

Tests do swap url config at runtime, so both vitest setup files unfreeze
the shared instance. The media-inliner CDN tests mutated the private
_assetBaseUrls field, which 5.4.0 now reads once at construction; they
use the existing stubUrlUtilsWithCdn helper instead.
@nx-cloud

nx-cloud Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

🤖 Nx Cloud AI Fix

Ensure the fix-ci command is configured to always run in your CI pipeline to get automatic fixes in future runs. For more information, please see https://nx.dev/ci/features/self-healing-ci


View your CI Pipeline Execution ↗ for commit 8350577

Command Status Duration Result
nx run @tryghost/admin:test:acceptance --shard=2/2 ✅ Succeeded 11m 3s View ↗
nx run-many -t test:unit -p ghost,@tryghost/ada... ✅ Succeeded 10m 5s View ↗
nx run ghost:test:ci:integration ✅ Succeeded 5m 2s View ↗
nx run @tryghost/admin:test:acceptance --shard=1/2 ✅ Succeeded 9m 35s View ↗
nx run ghost:test:integration ✅ Succeeded 3m 33s View ↗
nx run ghost:test:ci:e2e ✅ Succeeded 4m 42s View ↗
nx run ghost-monorepo:lint:boundaries ✅ Succeeded 31s View ↗
nx run-many -t lint -p ghost-monorepo,ghost,@tr... ✅ Succeeded 4m 18s View ↗
Additional runs (13) ✅ Succeeded ... View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-10-02 17:28:40 UTC

@coderabbitai

coderabbitai Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (2)
docs/contributing/testing.md — configured
docs/codebase/monorepo-structure.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: TryGhost/Ghost/.coderabbit.yaml

Review profile: QUIET

Plan: Essentials

Run ID: b22f5249-44f0-4ec2-852b-68f5101b0787

📥 Commits

Reviewing files that changed from the base of the PR and between b921c96 and 8350577.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • .changeset/url-utils-5-4-0.md
  • ghost/core/core/shared/url-utils.ts
  • ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js
  • ghost/core/test/utils/vitest-setup-db.ts
  • ghost/core/test/utils/vitest-setup.ts
  • pnpm-workspace.yaml

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (12)
  • GitHub Check: E2E Tests (Main 8/10)
  • GitHub Check: E2E Tests (Main 6/10)
  • GitHub Check: E2E Tests (Main 4/10)
  • GitHub Check: E2E Tests (Main 9/10)
  • GitHub Check: E2E Tests (Main 5/10)
  • GitHub Check: E2E Tests (Main 2/10)
  • GitHub Check: E2E Tests (Main 1/10)
  • GitHub Check: App Playwright Acceptance Tests (@tryghost/admin 1/2)
  • GitHub Check: App Playwright Acceptance Tests (@tryghost/admin 2/2)
  • GitHub Check: Acceptance tests (Node 22.23.3, mysql8)
  • GitHub Check: Unit tests (Node 24.20.0)
  • GitHub Check: Unit tests (Node 22.23.3)
🧰 Additional context used
📓 Path-based instructions (6)
Review whether tests prove changed behaviour, meaningful error/edge paths, and externally observable contracts without coupling to implementation details.

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js
New source files must be TypeScript: flag new JS files as a required change unless exempt (DB migrations, apps/ember-admin/, tool/config files, scripts/, docker/, generated code).

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js
Review lens: "where does this data become trusted?" Boundary data (HTTP input, external API/SDK responses, env/config, DB/filesystem reads, queue/webhook/event payloads) is `unknown` until validated — Zod by default.

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/test/utils/vitest-setup-db.ts
  • ghost/core/test/utils/vitest-setup.ts
  • ghost/core/core/shared/url-utils.ts
Prioritise concrete correctness, security, data-integrity, compatibility, and regression risks.

⚙️ CodeRabbit configuration file

Files:

  • pnpm-workspace.yaml
  • ghost/core/test/utils/vitest-setup-db.ts
  • ghost/core/test/utils/vitest-setup.ts
  • ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js
  • ghost/core/core/shared/url-utils.ts
Source excerpt: Ghost has several test suites across the monorepo.

📄 CodeRabbit inference engine (docs/contributing/testing.md)

Files:

  • ghost/core/test/utils/vitest-setup-db.ts
  • ghost/core/test/utils/vitest-setup.ts
  • ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js
Source excerpt: Built Admin assets are copied into `ghost/core/core/built/admin/` for the Ghost release.

📄 CodeRabbit inference engine (docs/codebase/monorepo-structure.md)

Files:

  • pnpm-workspace.yaml
  • ghost/core/test/utils/vitest-setup-db.ts
  • ghost/core/test/utils/vitest-setup.ts
  • ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js
  • ghost/core/core/shared/url-utils.ts
🔇 Additional comments (6)
ghost/core/core/shared/url-utils.ts (1)

17-18: LGTM!

ghost/core/test/utils/vitest-setup.ts (1)

25-27: LGTM!

ghost/core/test/utils/vitest-setup-db.ts (1)

101-103: LGTM!

.changeset/url-utils-5-4-0.md (1)

1-5: LGTM!

pnpm-workspace.yaml (1)

98-98: 📐 Maintainability & Code Quality

The lockfile already records @tryghost/url-utils at 5.4.0, including the catalog specifier and package resolution. The frozen-lockfile failure described in this comment does not apply.

ghost/core/test/unit/server/services/media-inliner/test/external-media-inliner.test.js (1)

1403-1403: 📐 Maintainability & Code Quality

The concern is refuted. The enclosing suite's afterEach calls sinon.restore() for every test, including tests that fail. The CDN stubs are therefore restored; the nested teardown only restores configuration.


Walkthrough

URL-utils is configured as frozen by default. Both Vitest setup files unfreeze it after loading runtime overrides. The external media inliner test now uses a URL-utils helper to configure CDN base URLs. The workspace catalog and changeset record @tryghost/url-utils version 5.4.0.

Suggested reviewers: 9larsons

Priority: ➖ Normal

Change: Refactor

Merge Risk: ⚪ Minimal · up to 83505

The dependency update and test setup have no identified issue requiring a fix before merge.

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main changes: updating @tryghost/url-utils to 5.4.0 and freezing URL getters.
Description check ✅ Passed The description directly explains the dependency update, URL freezing, test adjustments, changeset, and reported test results.
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.
Type-Safe Boundaries ✅ Passed The PR adds only the literal frozen: true option in production code. Existing config reads and the existing as () => string assertion are unchanged. The other executable changes are in test file…
New Files Are Typescript ✅ Passed The pull request adds only .changeset/url-utils-5-4-0.md. It does not add any .js, .jsx, .cjs, or .mjs source file. The changed JavaScript test file is pre-existing and modified, which the c…
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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

@codecov

codecov Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 69.40%. Comparing base (b921c96) to head (8350577).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #31293      +/-   ##
==========================================
+ Coverage   69.29%   69.40%   +0.10%     
==========================================
  Files        1585     1585              
  Lines       58062    58062              
  Branches     9969     9969              
==========================================
+ Hits        40236    40297      +61     
+ Misses      15665    15608      -57     
+ Partials     2161     2157       -4     
Flag Coverage Δ
admin-tests 61.50% <ø> (ø)
e2e-tests 70.97% <ø> (+0.12%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@acburdine
acburdine merged commit 1fc5735 into main Oct 2, 2026
65 checks passed
@acburdine
acburdine deleted the claude/url-utils-freeze-option-b62240 branch October 2, 2026 17:34
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.

1 participant