Skip to content

[pull] main from TryGhost:main - #1493

Merged
pull[bot] merged 11 commits into
code:mainfrom
TryGhost:main
Sep 15, 2026
Merged

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

Conversation

@pull

@pull pull Bot commented Sep 15, 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 : )

louisghost and others added 11 commits September 15, 2026 13:13
)

## Summary
- Adds nullable `posts.auto_excerpt` and `posts.reading_time` columns
(DDL only, `{ algorithm: 'auto' }`) so automatic excerpt and reading
time can later be stored instead of recomputed on every Posts API
response.
- Updates `schema.js` and the schema integrity hash to match.
- Strips `auto_excerpt` from post serializers so it stays internal;
`reading_time` remains the existing public API field and is still
computed at read time in this PR.
- Also strips the new columns from member activity-feed attribution and
avoids leaking null `reading_time` into webhook payloads before
population exists.
- Migration lives in `6.64/` (after `v6.63.0`); bumps Core + ember-admin
to `6.64.0-rc.0`.

No write-path population, backfill, or stored read path yet — those land
in follow-up PRs.

## Test plan
- [x] Confirm migration adds both columns on MySQL (`pnpm knex-migrator
migrate` for 6.64) and rolls back cleanly
- [x] `pnpm test:single test/unit/server/data/schema/integrity.test.js`
- [x] Spot-check Content/Admin post responses: no `auto_excerpt` key;
`reading_time` / `excerpt` unchanged from today
- [x] Migration review checklist on the PR

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
ref https://linear.app/ghost/issue/BER-3911

The opened-events lag warning measured the age of the last processed event, which only moves when events arrive, so quiet sites warned for days.

The `job.completed` log for the opened and delivery pipelines now carries `lag_seconds`:  the time between now and the last point up to which all events have been fetched and processed. It is omitted until a fetch has succeeded in the current process. The warning and its threshold are removed and the missing-events sweep has no lag entry because its window trails the delivery pipeline by design.

Also fixes the email debug screen's status poll stopping on a failed request.

Co-authored-by: Ricardo Pinto <hessian_loom_0u@icloud.com>
Migrated the global and per-member Activity screens to React behind the
private `membersActivityReact` experiment. The existing
`/members-activity` URL, member selection, event filters, permissions,
and navigation remain compatible with Ember. Default enablement and
Ember removal are separate rollout steps.

The screen uses Shade and the existing member event parser, with
full-page financial details and cleaned click URLs. Historical email
previews prefer stored HTML/subject and use a post preview only when a
valid post identity is available. The editor preview and existing
five-event member detail feed retain their behavior.

Pagination uses bounded requests to finish each timestamp boundary per
event type before moving backward. It works with the existing API and
avoids dropping same-timestamp events. Loading, empty, failure, and
retry states include accessible announcements. The Ember handoff
preserves React filters across reloads without briefly rewriting the
URL.

Related:
[PLA-285](https://linear.app/ghost/issue/PLA-285/migrate-members-activity-to-react).

### Validation

- Full Admin and admin-x-framework unit suites passed; Admin typecheck
passed.
- 17 Activity browser acceptance tests passed; 15 route-access/fallback
acceptance tests passed.
- Existing Ember Activity tests passed (13); Core Labs/config/settings
tests passed.
- Real-browser tests verified actual React/Ember ownership,
member/profile navigation, and filtered reloads. A real API fixture
verified all 75 same-timestamp signups plus one older signup appear
exactly once. URL override persistence and clearing back to Ember after
reload also passed.
- Independent slice reviews and final Standards/Spec reviews completed;
findings addressed.
- `pnpm check` passed formatting and repository lint. Its Core test
phase failed in unchanged cron/date and gift-image/email-renderer tests.
The two date assertions pass with `TZ=UTC`; isolated gift-image tests
still time out, with a local Fontconfig configuration error. Admin and
framework tests passed within the full check.

### Manual testing

1. Open `/ghost/#/members-activity?labs=membersActivityReact`, or enable
**React member activity** in Labs' private features.
2. Search/select a member, open their profile, then use **View all
member activity**. Toggle filters, reload, and use Back/Forward.
3. Scroll a long feed and check subscription/donation/gift values and
post links. Open an email preview, switch desktop/mobile, and close with
Escape.
4. Disable the persisted flag if enabled, visit
`/ghost/#/members-activity?labs=`, and reload to verify the Ember
fallback.

See [the Activity
README](https://github.com/TryGhost/Ghost/blob/codex/pla-285-member-activity-react/apps/admin/src/members/activity/README.md)
for behavior and pagination details.

- [x] Read and followed the Contributor Guide
- [x] Explained the change
- [x] Added automated regression tests

---------

Co-authored-by: Steve Larson <9larsons@gmail.com>
ref https://linear.app/ghost/issue/GVA-988

The billing overview no longer opens the card-update form automatically. Point the existing overdue alert at `/pro/update-card` so customers can reach payment directly before the new dunning warnings roll out. The payment page returns to the billing overview and does not require the dunning feature flag or return-to-Admin handler.
ref https://linear.app/ghost/issue/GVA-988

Billing can ship its payment page before Ghost's dunning return handler.
Advertise whether that return flow is enabled through the existing
forceUpgradeInfo response. A missing or disabled dunningWarnings accessor
reports false, keeping payment completion on the Billing overview until
the later dunning UI and handler are available and enabled.
ref
https://forum.ghost.org/t/working-locally-on-navigation-and-cant-save-icons/63703

Navigation icon URLs are validated with `validator.isURL`, which defaults to
`require_tld: true`. Admin uploads an icon and sends back the absolute site URL,
so on a local install that is `http://localhost:2368/content/images/...`.
`localhost` has no TLD, the icon regex only covers `/...` and `__GHOST_URL__/...`,
and input validation runs before the URL transform in the serializer — so every
save was rejected with a 422 "Please enter a valid navigation item".

The navigation `url` field never hit this because its regex accepts any scheme
prefix. Rather than dropping `require_tld` altogether, which would also accept
arbitrary single-label hosts such as `http://intranet/icon.svg` on production
sites, the TLD requirement is kept and an exception is made for a parsed hostname
of exactly `localhost`. The protocol allowlist still applies, so
`ftp://localhost:2368/icon.svg` stays invalid.

The existing test passed because the test config URL is an IP address, which
`isURL` accepts — the same reason `127.0.0.1:2368` was the forum workaround. The
new tests use a literal localhost icon URL and lock down the scope of the
exception from both sides.
ref https://linear.app/ghost/issue/DES-1209/analytics-breaks-layout-on-mobile-devices

Analytics scrolled sideways on a phone with nothing visible to explain it. Each
metric in a Top posts row carries an absolutely positioned tooltip at least 160px
wide, centred on a 66px parent, so it overhung its row by ~50px each side; below md
the metrics stack flush right, which put that overhang past the page edge. It sits at
opacity-0 but is still laid out. Anchoring it right in the component covers every
instance and removes the per-call-site overrides.

Also fixed: a single unbroken word wider than its column pushed the Latest post and
Top posts cards off-screen. wrap-anywhere rather than break-words, because only
overflow-wrap: anywhere reduces the intrinsic width the layout reserves.

Two tidy-ups in the same code: Latest post applied wide-layout margin and padding at
every width, and Top newsletters bounded itself with 100vw arithmetic that included
the scrollbar.
no ref

Useful for debugging.
@pull pull Bot locked and limited conversation to collaborators Sep 15, 2026
@pull pull Bot added the ⤵️ pull label Sep 15, 2026
@pull
pull Bot merged commit f0f0de5 into code:main Sep 15, 2026
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.

7 participants