Skip to content

[pull] main from TryGhost:main - #1403

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

pull[bot] merged 24 commits into
code:mainfrom
TryGhost:main

Conversation

@pull

@pull pull Bot commented Aug 10, 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 : )

ErisDS and others added 24 commits August 10, 2026 17:29
## Summary

- Fixes the IndexNow development guard test on `main`.
- Updates the assertion to use the current direct URL-service dependency
rather than the removed `facade` shape.
- Contains no runtime behavior changes.

## Context

The stale assertion was introduced when #29781 merged after #29792
changed the URL-service dependency shape. The `main` CI run for #29781
was cancelled by the following merge, so the interaction surfaced in
[the next `main`
run](https://github.com/TryGhost/Ghost/actions/runs/31405973089/job/93513219875).

## Testing

- [x] `pnpm test:single
test/unit/server/services/indexnow-ping/indexnow-ping-service.test.js` —
28 passed
- [x] ESLint pre-commit check
#29860)

no ref

Two packages fail their `test:types` target on a fresh local `pnpm test`
run. CI only runs the `test:unit` target for workspace packages, so
these type-check failures never surfaced there — but every local full
test run hits them.
fixes https://linear.app/ghost/issue/ONC-1936/

Editing a default theme (Source/Casper) in the built-in theme editor
forces a "save as new theme" flow because default themes can't be
overwritten. Custom theme settings are stored against the theme name, so
the newly-named copy starts with the theme's default settings — the
moment it was activated, all customised design settings (fonts, colours,
header styles, etc.) silently reverted to defaults and unexpectedly
broke the site's appearance.

Fixed it so the editor asks the API to carry the settings over:

- `POST /themes/upload` now accepts an optional `copy_settings_from`
query option. After the theme is stored, the custom theme settings
service duplicates the source theme's stored settings under the new
theme name, so activating the copy keeps the site's design.
- Copied values are reconciled by the existing activation sync (unknown
keys pruned, invalid select values reset), which handles the case where
the edit also changed the theme's settings definition.
- Copying no-ops when the destination theme already has stored settings,
so saving over an existing theme never clobbers its customisations.
- The theme editor sends `copy_settings_from` whenever a save results in
a new theme name — the forced save-as for default themes, and any rename
of a custom theme.
ref https://linear.app/ghost/issue/BER-3851/

- the specificity of the `gift-reminders` controller naming made it
harder to expand gift subscriptions with additional endpoints, renaming
to just `gifts` matches the service naming and provides a single file to
house upcoming gift delivery work
no ref

Three focused cleanups that remove expected noise from the legacy Ember
Admin development server without hiding the same diagnostics from
production builds or tests.
closes #29805 

Currently, switching between tiers does not cause a webhook to fire.
This makes it hard for an integration to detect plan changes without
doing a full scan of members.

This PR makes sure that tiers are emitted, and provides a test for the
corrected behavior.
no ref

`_generateCompleteRange` in `members-stats-service.js` builds a `Map` of events by date and then never reads it.
no ref
- ensure session verification is bound to user id

Co-authored-by: Steve Larson <9larsons@gmail.com>
Co-authored-by: UserExistsError <23325451+UserExistsError@users.noreply.github.com>
closes #22883

Adds a regression test proving that custom adapters placed in the
documented `content/adapters/<type>/<name>` location (per
https://ghost.org/docs/config/#location) are correctly detected, and
that a genuine missing-dependency error inside the adapter's own code is
surfaced as such rather than misreported as "adapter not found."
…29867)

fixes https://linear.app/ghost/issue/SC-41/
- this limits which staff users can view member data in feedback.

Co-authored-by: UserExistsError <23325451+UserExistsError@users.noreply.github.com>
ref https://linear.app/ghost/issue/SC-20/
- prevents a logged-in member from unwittingly submitting feedback.

Co-authored-by: UserExistsError <23325451+UserExistsError@users.noreply.github.com>
no ref
- github actions native runners can have wildly different performance
characteristics depending on CPU/load, making benchmarks difficult to
evaluate over time
- switching benchmarks to run on Blacksmith should in theory provide a
more stable set of measurements
Activating the admin toolbar on a subdirectory site (e.g.
`https://ghost.org/changelog/?admin=1`) can redirect-loop when a reverse
proxy strips the subdirectory before forwarding the request. Ghost then
cleaned the query and redirected to `/`, which bounced back to the
public URL with `admin=1` still attached.

## Summary
- Build the clean redirect with `urlUtils.createUrl()` so the configured
subdirectory is restored when missing (and left alone when already
present)
- Add unit coverage for stripped paths, already-prefixed paths, retained
query params, and the activation redirect

## Test plan
- [x] `pnpm test:single
test/unit/frontend/web/middleware/admin-toolbar.test.js`
- [ ] Manually open `/?admin=1` on a subdirectory install and confirm it
redirects once to the public subdirectory path without looping
…nt of paid plans (#29814)

closes #29806 

Currently, if a user clicks 'cancel subscription' or while in
cancel_at_period_end: true state clicks 'resume', Ghost does not fire a
webhook, which makes it hard for integrations to run retention flows.

This PR causes the member.edited webhook to fire, and causes the webhook
to include the subscription field in current and previous.

---------

Co-authored-by: Steve Larson <9larsons@gmail.com>
…ight backgrounds (#29834)

Fixes #27797

Fixes `{{contrast_text_color}}` and every other Ghost consumer of
`textColorForBackgroundColor` returning white for light colors such as
`#dacafe`, `#ffa5b1`, and `#a3e6ff`.

## Root cause

`@tryghost/color-utils@0.2.19` used `.b()` in its YIQ calculation. That
accessor is the Lab b-channel, not the RGB blue channel, so many colors
were classified incorrectly.

---------

Co-authored-by: Steve Larson <9larsons@gmail.com>
no ref

- Retire the abandoned, proposed-only E2E ADR experiment so the
repository does not imply that it has a second engineering decision
system.
- Consolidate the useful Arrange–Act–Assert and Page Object guidance
into the canonical E2E documentation and agent instructions.
- Reconcile selector guidance with current suite practice: prefer
semantic locators, then stable test IDs, while allowing stable
structural selectors where semantic locators are unavailable.

This is the precursor change for a broader contributor-documentation
consolidation. It does not introduce a replacement ADR process or begin
the wider `/docs` restructuring.
)

closes #25059

The video card's web-rendering `poster` attribute pointed at a third-party service
(`https://img.spacergif.org/v1/{w}x{h}/0a/spacer.png`) to produce an
aspect-ratio-shaped placeholder image. Every visitor viewing a post with
a video card triggered a request to that external host, leaking
IP/referrer/UA data with no consent. This replaces the web-path poster
with a local, inline transparent 1x1 GIF `data:` URI — zero third-party
network requests, no visual change.

---------

Co-authored-by: Steve Larson <9larsons@gmail.com>
no ref
- if a commit is merged into main while the release script is running/waiting for CI to pass, it will cause the release to fail
- update the release script to switch the commit it's checking if a commit is merged on top of main
no ref
- Wait for the tag name input to be visible before passing its element
to `userEvent.type`.

The `/tags/new` title renders before the form is ready because the form
also waits for asynchronous site data. The test used the title as its
readiness signal and then synchronously dereferenced the name input,
which could fail when the form had not mounted yet.
no ref
- makes the core build consistent with admin/e2e builds
@pull pull Bot locked and limited conversation to collaborators Aug 10, 2026
@pull pull Bot added the ⤵️ pull label Aug 10, 2026
@pull
pull Bot merged commit c8be291 into code:main Aug 10, 2026
1 check 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.

10 participants