Skip to content

feat(cron): add publish-due endpoint and rebuildHooks config#772

Open
michaelmcker wants to merge 2 commits intoemdash-cms:mainfrom
michaelmcker:feat/publish-due-cron
Open

feat(cron): add publish-due endpoint and rebuildHooks config#772
michaelmcker wants to merge 2 commits intoemdash-cms:mainfrom
michaelmcker:feat/publish-due-cron

Conversation

@michaelmcker
Copy link
Copy Markdown

What does this PR do?

Adds a POST /_emdash/api/cron/publish-due endpoint that publishes all content items whose scheduled_at has passed and fires configured rebuildHooks once per batch.

Also adds the rebuildHooks option to the integration config so users can point EmDash at a Vercel / Netlify / Cloudflare deploy hook URL to trigger a rebuild whenever scheduled content goes live.

Closes #

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 (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation and pnpm locale:extract has been run (if applicable)
  • I have added a changeset (if this PR changes a published package)
  • New features link to an approved Discussion: https://github.com/emdash-cms/emdash/discussions/...

AI-generated code disclosure

  • This PR includes AI-generated code

What's included

POST /_emdash/api/cron/publish-due

  • Iterates all collections, finds items where scheduled_at <= now and status = 'scheduled'
  • Publishes each due item in a transaction, fires content:afterPublish hooks per item
  • Fires rebuildHooks once for the whole batch (not per item)
  • Auth: Authorization: Bearer <EMDASH_CRON_SECRET> when the env var is set; localhost-only in dev; 503 if neither applies
  • Suitable for Vercel Cron, Cloudflare Workers cron triggers, or any HTTP scheduler

rebuildHooks config option

emdash({
  rebuildHooks: ["https://api.vercel.com/v1/integrations/deploy/..."],
})

Each URL receives a POST request after a publish batch. Requests are deferred past the response via after() so the isolate response isn't blocked. Failures are logged but never surfaced as errors.

Tests — 6 unit tests in tests/unit/api/publish-due.test.ts covering: empty (no-op), past-scheduled item published, future item skipped, multiple items across collections, idempotency (second call publishes 0), and items returned for hook dispatch.

Docs — new guides/scheduled-publishing.mdx and updated reference/configuration.mdx.

Screenshots / test output

✓ tests/unit/api/publish-due.test.ts (6 tests) 42ms
Test Files  157 passed (157)
     Tests  2593 passed (2593)

michaelmcker and others added 2 commits April 25, 2026 05:31
Adds POST /_emdash/api/cron/publish-due to publish all content items
whose scheduled_at has passed, then fire content:afterPublish hooks
per item and rebuild hooks once for the batch.

- New route secured by EMDASH_CRON_SECRET (or CRON_SECRET for Vercel)
- Constant-time token comparison via SHA-256 XOR
- rebuildHooks?: string[] config option fires POST to each URL after
  batch via after() so Workers doesn't cancel in-flight fetches
- Per-item publish failures are logged and skipped (batch continues)
- handleContentPublishDue exported from core package
- Integrates into runSystemCleanup via optional publishFn callback
- 6 unit tests covering all required scenarios

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…SH_CRON_SECRET

- New guide: guides/scheduled-publishing.mdx — covers setup steps for
  Vercel Cron, Cloudflare Workers scheduled events, and self-hosted cron,
  plus how to get deploy hook URLs from Vercel/Netlify/CF Pages
- configuration.mdx: document rebuildHooks option with example and
  fire-and-forget semantics note
- configuration.mdx: add EMDASH_CRON_SECRET to env vars table with
  CRON_SECRET fallback note for Vercel Cron compatibility
- Sidebar: add Scheduled Publishing entry in Guides

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

Scope check

This PR changes 628 lines across 15 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.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 26, 2026

🦋 Changeset detected

Latest commit: 24691af

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

This PR includes changesets to release 12 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash 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
Copy link
Copy Markdown
Contributor


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@github-actions
Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant