Skip to content

Comments

[pull] main from TryGhost:main#930

Merged
pull[bot] merged 14 commits intocode:mainfrom
TryGhost:main
Feb 19, 2026
Merged

[pull] main from TryGhost:main#930
pull[bot] merged 14 commits intocode:mainfrom
TryGhost:main

Conversation

@pull
Copy link

@pull pull bot commented Feb 19, 2026

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 : )

rob-ghost and others added 14 commits February 19, 2026 11:38
ref https://linear.app/ghost/issue/BER-3318/

knex-migrator silently skips migration folders that exceed the current
Ghost version (folder > ghostVersion.safe). If a developer adds a
migration folder without bumping package.json to an rc, those migrations
will never run. This test catches that by scanning all version folders
and failing when any exceed the safe version from package.json.
ref https://linear.app/ghost/issue/BER-3292/add-production-docker-image-build-to-ghost-ci

Ghost CI now builds two production Docker images on every commit:
- ghcr.io/tryghost/ghost-core (server + production deps, no admin)
- ghcr.io/tryghost/ghost (core + built admin assets)

Uses npm pack to create a standalone distribution via monobundle.js,
which bundles private workspace packages as local tarballs. The
Dockerfile mirrors Ghost-Moya's proven production setup (bookworm-slim,
jemalloc, ghost user uid 1000, sqlite3 native build).

Nothing consumes these images yet — this is purely additive. Ghost-Moya
continues building from source until we're ready to switch.
ref https://linear.app/ghost/issue/BER-3293/

E2E tests were running against the monorepo dev image — a different
artifact from what gets deployed. This switches the CI E2E job to
depend on job_docker_build_production and test the real production
image.

A thin Dockerfile.e2e layers pre-built UMD bundles onto the production
image so all 6 public apps are served from /ghost/assets/ paths. This
replaces the inconsistent setup where portal had a dedicated Vite
preview container while the other 4 apps fell back to CDN.

The migration command is unified to `node node_modules/.bin/knex-migrator
init` (MigratorConfig.js handles tsx gracefully via try/catch) and build
commands are reusable npm scripts (build:apps, build:docker). Dev mode
(yarn dev + DevEnvironmentManager) is completely unchanged.
The pretest script still called `yarn docker:build:ghost` which was
removed when E2E tests moved to production images. The fallback is no
longer needed — local dev uses `yarn dev` (auto-detected) and container
mode requires an explicit `GHOST_E2E_IMAGE`. Replaced with a helpful
hint instead of a hard failure.
closes https://linear.app/ghost/issue/BER-3229/

- Bookmark card descriptions containing pre-encoded HTML entities (e.g. `&`) were being double-escaped when rendering for email newsletters, showing `&` to readers
- Fixed the shared `escapeHtml` utility to decode existing entities before re-escaping, preventing double-encoding
- Removed redundant `escapeHtml` call on bookmark descriptions since `truncateHtml` already handles escaping
no issue

Previously with the Dockerised `yarn dev` command, in order to enable Stripe webhooks it was necessary to modify your local `.env` file to add the `COMPOSE_PROFILES=stripe` line, and either specify Stripe keys in the `.env` or export ENV variables in your shell file.

- added `docker/stripe/with-stripe.sh` command that adds `stripe` to `COMPOSE_PROFILES` and performs requirement checks to enable early exit with a useful log rather than needing to dig into container logs to find
the problem
- added `yarn dev:stripe` command to make Stripe availability easier to find than stumbling across the `.env.example` file
- updated `yarn dev:all` to use `with-stripe.sh` so Stripe webhook support is included alongside other services
ref
f1321fb

We no longer need the setup script to do the mysql container and config
setup, as the 'new' yarn dev handles this.
closes https://linear.app/ghost/issue/NY-1003

This change should have no user impact because the flag is on for
everyone.
fixes https://linear.app/ghost/issue/BER-3351/

Captured window.parent into a local variable at useEffect setup time
instead of reading it fresh in the hashchange handler and cleanup.
When the iframe is removed from the DOM (e.g. navigating away in Ghost
Admin), the browser nulls window.parent but the hashchange listener on
the host window survives — causing a TypeError on the next hash change.
The captured reference remains valid for both the handler and cleanup.
Resolves ADMIN-19WW, ADMIN-19X0, ADMIN-19WY, ADMIN-19X6 (~1,931 events
across Chrome, Safari, and Firefox).
closes https://linear.app/ghost/issue/BER-3344

- Added rounding for percent-off prices, so that the displayed price
matches the amount being billed by Stripe. Example: 20% off $5.99
renders $4.79 (not $4.792)
- Cleaned up duplicate code
closes https://linear.app/ghost/issue/BER-3349

This change ensures that only 1 retention offer per cadence is visible
in the offer select when filtering members by retention. This also
updates the retention modal to link the members list pre-filtered when
clicking on the redemption count
No ref

If the membersForward flag is enabled, route to /members-forward. If
not, route to members.
ref
2110267

- We introduced a regression of the sidebar banners with the above
change, that the banner would appear in the Editor.
- Made sense to restructure and make sidebar banners a bit more robust
closes #26125
closes https://linear.app/ghost/issue/BER-3271/

- Alerts rendered into `#ember-alerts-wormhole` (body grid row 1) did not push editor content down and appeared behind the editor header because `.gh-editor-fullscreen-container` used `position: fixed`, covering the entire viewport and ignoring the grid layout
- Changed the editor fullscreen container from `position: fixed` to `position: absolute` and established a flex height chain so `.gh-koenig-editor` remains the sole scroll container for editor content
- Simplified the layout so each page context has one scroll container: SidebarInset for non-editor pages, `.gh-koenig-editor` for editor content
- Fixed the post settings sidebar to use flex column layout with a pinned header and independently scrollable content area to resolve issues on mobile
- Moved Ember CSS overrides (`.gh-app` position, `.gh-main` overflow) from the React shell into Ember source styles directly, removing redundant overrides
- Fixed mobile editor layout to fill the full viewport when the mobile navbar is hidden
@pull pull bot locked and limited conversation to collaborators Feb 19, 2026
@pull pull bot added the ⤵️ pull label Feb 19, 2026
@pull pull bot merged commit d1b6408 into code:main Feb 19, 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.

9 participants