Skip to content

fix(admin): save editor state before publishing - #2860

Merged
ascorbic merged 1 commit into
mainfrom
fix/publish-autosave-race
Sep 2, 2026
Merged

fix(admin): save editor state before publishing#2860
ascorbic merged 1 commit into
mainfrom
fix/publish-autosave-race

Conversation

@ascorbic

@ascorbic ascorbic commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

What does this PR do?

Makes Publish save and await the editor's exact current payload before promoting a draft. Editor saves and autosaves share a serialized queue, so an in-flight autosave completes before the publish flush, and the pending debounce is cancelled so it cannot replay older state afterward.

This builds on the editor revision-token work merged in #2121 and the lifecycle preconditions merged in #2783. The route advances its current _rev after each save and publish response, so a validation error, failed save, or revision conflict stops the publish request, while repeated Publish clicks share the same in-flight operation.

Closes #2123

Type of change

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (complete @emdash-cms/admin suite: 1,805 tests)
  • pnpm format has been run (focused oxfmt formatting and check for changed files)
  • I have added/updated tests for my changes
  • User-visible strings in the admin UI are wrapped for translation (not applicable: no new strings)
  • I have added and reviewed the user-facing changeset
  • New features link to an approved Discussion (not applicable: bug fix)
  • I have included screenshots below if this PR changes the UI (not applicable: interaction ordering only, with no rendered UI change)

AI-generated code disclosure

  • This PR includes AI-generated code — model/tool: OpenAI Codex (GPT-5)

Screenshots / test output

Screenshots are not applicable because the rendered interface is unchanged.

  • pnpm --filter @emdash-cms/admin test: 142 files and 1,805 tests passed
  • pnpm --filter @emdash-cms/admin build: passed
  • pnpm typecheck: passed across 34 workspace projects
  • pnpm lint: passed with warnings denied
  • pnpm --silent lint:json | jq '.diagnostics | length': 0
  • Focused oxfmt check: passed
  • git diff --check: passed

@changeset-bot

changeset-bot Bot commented Sep 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1445e7c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
@emdash-cms/admin Patch
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/release-service Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Scope check

This PR changes 585 lines across 5 files. Large PRs are harder to review and more likely to be closed without review.

If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs.

See CONTRIBUTING.md for contribution guidelines.

@ascorbic
ascorbic force-pushed the fix/publish-autosave-race branch from 2d8e696 to a6afada Compare September 2, 2026 13:34
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 2, 2026

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://fix-publish-autosave-race.try.emdashcms.com, https://fix-publish-autosave-race-emdash-playground.emdash-cms.workers.dev (commit 1445e7c)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://b1e2a6b4.try.emdashcms.com, https://b1e2a6b4-emdash-playground.emdash-cms.workers.dev 1445e7c 2026-09-02T15:32:24.988Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://bffcb6f8.try.emdashcms.com, https://bffcb6f8-emdash-playground.emdash-cms.workers.dev a6afada 2026-09-02T13:38:21.768Z Visit the dashboard ↗

@pkg-pr-new

pkg-pr-new Bot commented Sep 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@2860

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@2860

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@2860

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@2860

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@2860

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@2860

emdash

npm i https://pkg.pr.new/emdash@2860

create-emdash

npm i https://pkg.pr.new/create-emdash@2860

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@2860

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@2860

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@2860

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@2860

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@2860

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@2860

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@2860

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@2860

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@2860

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@2860

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@2860

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@2860

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@2860

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@2860

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@2860

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@2860

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@2860

commit: 1445e7c

@ascorbic ascorbic added the bot:review Trigger an emdashbot code review on this PR label Sep 2, 2026

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach is sound. The PR fixes the publish/autosave race by serializing editor saves/autosaves through a single promise queue, making the publish handler first flush the current editor payload, and threading _rev tokens through save and publish so a failed/conflicting flush stops the publish. That builds cleanly on the revision-token work already in the server and router.

I checked the diff, the server publish handler (packages/core/src/api/handlers/content.ts), the publish route (packages/core/src/astro/routes/api/content/[collection]/[id]/publish.ts), existing ContentEditor and router tests, and the component call-sites for onPublish. The server already supports _rev in publish, the tests cover the serialization cases, and the ContentEditor/ContentSettingsPanel prop wiring is consistent.

Two issues keep this from being a clean sign-off:

  1. Optimistic lastSavedData update in ContentEditor.handlePublish can mark the wrong state as saved. The router coalesces repeated Publish clicks by returning the same in-flight promise. The editor captures a fresh savedState for each click and applies it when the promise resolves. The second click’s payload may be discarded by the router, but the editor still sets lastSavedData to the second click’s saved state, so the editor can briefly (or persistently, depending on render ordering) believe unsaved changes are saved.

  2. Form submission bypasses the disabled Save button during publish. handleSubmit does not check the same isContentSaveBlocked condition that disables SaveButton. That means pressing Enter in an input while a publish flush/publish is in flight can queue a second save, re-dirtying the form after the publish completes.

Both are small fixes in packages/admin/src/components/ContentEditor.tsx.

The changeset is accurate and user-facing.

Comment thread packages/admin/src/components/ContentEditor.tsx Outdated
Comment thread packages/admin/src/components/ContentEditor.tsx Outdated
@emdashbot emdashbot Bot removed the bot:review Trigger an emdashbot code review on this PR label Sep 2, 2026
@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels Sep 2, 2026
@ascorbic
ascorbic force-pushed the fix/publish-autosave-race branch from a6afada to 1445e7c Compare September 2, 2026 15:25
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/awaiting-author Reviewed; waiting on the author to respond labels Sep 2, 2026
@ascorbic
ascorbic merged commit afa81c5 into main Sep 2, 2026
59 of 60 checks passed
@ascorbic
ascorbic deleted the fix/publish-autosave-race branch September 2, 2026 16:23
@emdashbot emdashbot Bot mentioned this pull request Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/admin review/needs-rereview Author pushed changes since the last review size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Publish changes races the autosave debounce: unsaved edits silently dropped, and a stale pending draft can regress live content (0.29.0)

1 participant