Skip to content

[pull] main from TryGhost:main - #1457

Merged
pull[bot] merged 19 commits into
code:mainfrom
TryGhost:main
Aug 31, 2026
Merged

[pull] main from TryGhost:main#1457
pull[bot] merged 19 commits into
code:mainfrom
TryGhost:main

Conversation

@pull

@pull pull Bot commented Aug 31, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

allouis and others added 19 commits August 31, 2026 14:21
no ref

The gifts jobs module uses the legacy jobs service for the reminders job
and the class-based jobs service for cleanup. The legacy binding held the
jobsService name, forcing the class-based parameter into the awkward
classBasedJobs name. jobManager matches the legacy service's own
vocabulary (addJob) and frees jobsService for the new service.
no ref

classBasedJobs described the service relative to the legacy one it
replaces, which only means something during the migration. Now that the
legacy binding is jobManager the injected class-based jobs service can
take the plain jobsService name.
…eter

no ref

The token and expired-comped scheduling functions reached into the jobs
service module with getInstance(), while the gift and update-check
equivalents already receive the service from boot. Injecting it makes
boot the single composition root for job scheduling and lets the tests
pass a plain stub instead of initialising the real service and stubbing
its backend adapter.
no ref

The handler read the gift service off the gifts module at execution time
with an uninitialised guard, unlike the media inliner which boot resolves
and injects at registration. Handler registration already runs after
initServices, and no job executes before jobsService.start(), so boot can
assert the service exists and inject the instance - the same pattern it
already uses for the gift delivery service. A boot-order regression now
fails at wire-up instead of at the first job delivery.
no ref

register-job-handlers assembled the db, models, events, logging and
sentry dependencies for the two member cleanup tasks, which made the
wiring file a second composition root. The members jobs module now owns
that composition behind an init() called from boot, the same shape
content-import uses, so every handler in the wiring file is a single
delegating line and the dependency interface shrinks to the jobs service
plus the service instances.
ref https://linear.app/ghost/issue/HKG-1977

Preparation for moving processWebmention onto the class-based jobs service:
the work the background job does is now a named controller method, so the job
body no longer has to be a closure over the request frame.

The destructure of frame.data moves from execution time to enqueue time. That
is behaviour-preserving because frame.data is not mutated in between, and it
leaves the method taking exactly the fields a serialized job payload will
carry. URL parsing stays inside the method: a malformed URL must keep failing
inside the job, after the request has already been answered with a 202.
… queue

ref https://linear.app/ghost/issue/HKG-1977

These tests waited for the mentions job manager to go idle, which ties them to
the queue that happens to run the work today. Ahead of moving processWebmention
to the jobs service, they now wait for the mentions API to report the webmention
processed, which is true of either transport, and the assertions are unchanged.

The signal is the API's own '[Webmention] Created/Updated/Deleted/Restored' log
line rather than the mention row appearing: three tests re-post the same source
to assert a new verification result, and polling the row would find the previous
test's row already in the asserted state and pass without the job ever running.
ref https://linear.app/ghost/issue/HKG-1977

The mentions controller is about to dispatch through the jobs service, and it
receives its dependencies during initServices, which ran before the jobs service
existed. Boot is the composition root, so it builds the instance first and can
then inject it rather than have services reach for a module singleton.

Handler registration and start() deliberately stay where they were: handlers
need the initialised services, and the backend queue is created paused, so a
dispatch that lands between construction and start() is buffered.
ref https://linear.app/ghost/issue/HKG-1977

Receiving a webmention queued a closure over the request frame on the mentions
job manager. It now dispatches a serializable ProcessWebmentionJob, and central
handler registration routes it back to the controller method that does the work,
so dispatch and execution are no longer tied together by a closure. The mentions
job manager stays for sendWebmentions, which is a separate migration.

Two things worth knowing. The dispatched payload keeps source and target as
strings and parses them in the executor, because a malformed URL has to keep
failing inside the job rather than turning the request's 202 into a 400. And the
executor still swallows every processing error: the job never fails from the
transport's point of view, exactly as it did before, so this change does not
start reporting webmention failures to Sentry.
no ref

Promotes the `tagDetailsReact` Labs flag to generally available, so every site serves `/tags/:slug` and `/tags/new` from the React tag detail screen.
no ref

Used the shared Shade timestamp formatter so older entries follow the
common date format.

<img width="1191" height="272" alt="Screenshot 2026-08-31 at 9 41 59 AM"
src="https://github.com/user-attachments/assets/fa8c71b0-2fd6-4dba-9d72-c2d3c92f6ef4"
/>
- only pass docker build secret to benchmark script on main push
- remove unused "member in org" check in setup
- removed release workflow branch input
- add npm-release env to other npm publishing steps
no ref

Keep generated outcome metadata together at the start of errors.csv so publishers can immediately see why each row failed before reviewing or correcting the original source values. Preserve collision-safe names and original source order so the file remains safe to edit and re-upload.
no ref

Publishers should not have to infer where row-level failures are explained. Point the failed count at errors.csv only when that actionable attachment exists, preserving honest copy for fatal runs and outcomes without source data.
no ref

Frontmatter is not part of the supported CSV migration contract and exposing it in the mapping UI implied support publishers should not rely on. Remove it at both Admin and Core boundaries while leaving legacy JSON imports and normal post APIs unchanged.
no ref

A post's coverImage, ogImage, and twitterImage frequently resolve to the same feature_image URL, and getImageDimensions() looks all three up concurrently via Promise.all. Since ImageSize.getImageSizeFromUrl() had no in-flight deduplication, a single cold pageview could fire off multiple simultaneous origin requests (HTTP probe or storage read) for the exact same image. This coalesces concurrent lookups for the same URL into one
underlying request, regardless of which cache adapter (or none) is configured, since the dedup lives below the caching layer.
no ref

Follow-up to #30349, which removed the SQLite acceptance and legacy jobs
from CI.
…ides (#30381)

no ref 

In the admin acceptance harness, the `labs` render option compiled into
full canned `browseSettings`/`browseConfig` boot overrides, and `boot`
was spread after it — so any test passing a `boot` override for either
of those entries silently lost its labs flags. Tests that needed both
had to hand-mutate the boot response object (build a
`configResponse({labs})`, tweak it, pass it as the override) instead of
just naming the flags.
no ref

The admin acceptance harness's `labs` render option used to be silently
ignored whenever a `boot` override supplied the config or settings
response, so any spec that needed both had to bake the flag into a
hand-built `configResponse({labs})`/`settingsResponse({labs})` as well
as (or instead of) the `labs` option. The harness now composes `labs`
flags into boot-provided responses, so each spec can state a flag
exactly once.
@pull pull Bot locked and limited conversation to collaborators Aug 31, 2026
@pull pull Bot added the ⤵️ pull label Aug 31, 2026
@pull
pull Bot merged commit b972c1a into code:main Aug 31, 2026
3 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants