Repository navigation
Conversation
* feat(content-releases): add publishMode to releases Add a per-release publishMode enum (release_all_approved | wait_for_all), defaulting to wait_for_all so existing releases keep the current behavior. - schema attribute + shared contract types - afterSync backfill sets wait_for_all on releases without a mode - create/update validation rejects unknown values and null - publishMode changes are included in release.update audit changes Refs EE-217 * feat(content-releases): rename publishMode to releaseStrategy * feat(content-releases): rename releaseStrategy to releaseCondition
…l releases (#27983) * feat(content-releases): publish entries independently in allow_partial releases * fix(content-releases): publish webhook announces entries that a database error rolled back * feat(database): add savepoints to roll back part of a transaction * fix(content-releases): an entry failing at publish in a release run goes offline * chore(content-releases): share the blocked rule between publish and the release status * chore(content-releases): trim redundant comments * test(content-releases): cover release condition outcomes from the QA plan * fix(content-releases): edited unpublish entries block their release * test(content-releases): cover a rejected manual publish
…se run (#28030) * feat(content-releases): record what happened to each entry of a release run * chore(content-releases): write a release run's outcomes and status through one shared function * fix(content-releases): run outcomes are lost when an entry is deleted or recorded inaccurately * fix(content-releases): a failed release back to planned still shows its run's outcomes
…s failed (#28040) * feat(content-releases): freeze a release whose run released nothing as failed * feat(content-releases): ai review round 1 * feat(content-releases): fix throwaway api observation * feat(content-releases): fix comment and make use of helper
…d and skipped (#28077) Each run stores totalPublishedEntries, totalUnpublishedEntries and totalSkippedEntries on the release. The publish response, GET release, the releases list and the releases.publish webhook (failed runs included) return them.
…28048) * feat(content-releases): store why a planned entry isn't publishable * fix(content-releases): workflow changes * fix(content-releases): one failing planned action stops the startup reason backfill
…hanges and runs (#28093) * fix(content-releases): release statuses left inconsistent after a run or an entry change * fix(content-releases): release status overwritten or left stale by concurrent and background changes * fix(content-releases): review workflow changes deadlock with release runs
* feat(content-releases): freeze overdue releases as failed * fix(content-releases): lock a release while it's edited or deleted
…iled release skipped (#28160) * feat(content-releases): create a release from the entries a partial or failed release skipped * feat(content-releases): filter a release's entries by readiness or run outcome * fix(content-releases): never-validated entries missing from not-ready filter and count
…l release review (#28175) * enhancement(content-releases): close backend gaps found in the partial release review * fix(content-releases): empty overdue releases end failed and unchecked entries return a 500
…de panel (#28212) * feat(content-releases): create a release from skipped entries in a side panel * feat(content-releases): create and edit releases in a side panel * enhancement(content-releases): address review feedback on the release side panel * feat(content-releases): list, filter and sort releases in a table (#28254) * feat(content-releases): list releases in a table with their status The releases page lists pending and released releases in one paginated table (most recently updated first) with their status, schedule or run date, entries and release mode, instead of the Pending/Done tabs. Also fixes, from the review of the stack: - The release side panel no longer closes after picking a date in Firefox. - A check that throws is recorded as skipped_error whatever the error class; a blocked publish reports an entry's own error first. - A release update replaces the schedule as a whole; revalidation batches validity writes. - The skipped entries panel shows the server's error and no "0 entries" heading while loading. * feat(content-releases): filter and sort the releases list Admin: - The releases page gets a "Filters" button with Status, Release mode, Scheduled for and Released on, stored in the URL as `filters[$and]` and shown as removable tags, with "Clear all" and an empty state with "Clear filters". - Date filters take a date and an optional time: a date matches the whole day, a date and time the minute, in the viewer's timezone. `utils/scheduleFilters` turns them into `$gte`/`$lt` bounds, "is not" into an `$or` outside them. - A "Sort" menu: most recent updates (default), oldest updates, most recently created, name A to Z / Z to A. Changing it keeps the filters and goes back to the first page. Shared admin `Filters`: - `Filters.Filter` gets `formatValue` to format a tag's value. - `$null`/`$notNull` tags no longer format `true` as a date. - The field and operator selects no longer offer their placeholder. - A `filters[$and]` that isn't a list is ignored instead of crashing. - `formatValue`, `input` and `operators` aren't passed to value inputs (nor the DOM): `Filters.ValueInputProps` no longer includes them. * test(content-releases): paginated releases e2e exceeds the pending releases limit The e2e license caps pending releases at 3 and the seed already holds one, so creating 15 pending releases failed in CI. Each release is now published as soon as it's created. * chore(examples): enable the next design system in getstarted The release side panels are built with the next design system, which only gets its styles when the unstableNextDesignSystem future flag is on.
* feat(content-releases): create a release from skipped entries in a side panel * feat(content-releases): create and edit releases in a side panel * enhancement(content-releases): address review feedback on the release side panel * feat(content-releases): ui of the details page * fix(content-releases): refresh entry outcomes for e2e * feat(content-releases): fix stales * feat(content-releases): list, filter and sort releases in a table (#28254) * feat(content-releases): list releases in a table with their status The releases page lists pending and released releases in one paginated table (most recently updated first) with their status, schedule or run date, entries and release mode, instead of the Pending/Done tabs. Also fixes, from the review of the stack: - The release side panel no longer closes after picking a date in Firefox. - A check that throws is recorded as skipped_error whatever the error class; a blocked publish reports an entry's own error first. - A release update replaces the schedule as a whole; revalidation batches validity writes. - The skipped entries panel shows the server's error and no "0 entries" heading while loading. * feat(content-releases): filter and sort the releases list Admin: - The releases page gets a "Filters" button with Status, Release mode, Scheduled for and Released on, stored in the URL as `filters[$and]` and shown as removable tags, with "Clear all" and an empty state with "Clear filters". - Date filters take a date and an optional time: a date matches the whole day, a date and time the minute, in the viewer's timezone. `utils/scheduleFilters` turns them into `$gte`/`$lt` bounds, "is not" into an `$or` outside them. - A "Sort" menu: most recent updates (default), oldest updates, most recently created, name A to Z / Z to A. Changing it keeps the filters and goes back to the first page. Shared admin `Filters`: - `Filters.Filter` gets `formatValue` to format a tag's value. - `$null`/`$notNull` tags no longer format `true` as a date. - The field and operator selects no longer offer their placeholder. - A `filters[$and]` that isn't a list is ignored instead of crashing. - `formatValue`, `input` and `operators` aren't passed to value inputs (nor the DOM): `Filters.ValueInputProps` no longer includes them. * test(content-releases): paginated releases e2e exceeds the pending releases limit The e2e license caps pending releases at 3 and the seed already holds one, so creating 15 pending releases failed in CI. Each release is now published as soon as it's created. * chore(examples): enable the next design system in getstarted The release side panels are built with the next design system, which only gets its styles when the unstableNextDesignSystem future flag is on. * feat(content-releases): ui and ux upgrades * feat(content-releases): round of qa review * fix(content-releases): reason drawer can't reach entries past the first 500
…ial-release # Conflicts: # docs/docs/docs/01-core/content-releases/00-intro.md # packages/core/admin/admin/src/components/Filters.tsx # packages/core/admin/admin/src/components/tests/Filters.test.tsx # packages/core/content-releases/admin/src/pages/ReleasesPage.tsx # packages/core/content-releases/server/src/bootstrap.ts # packages/core/content-releases/server/src/middlewares/__tests__/documents.test.ts # packages/core/content-releases/server/src/middlewares/documents.ts # packages/core/content-releases/server/src/migrations/__tests__/revalidate.test.ts # packages/core/content-releases/server/src/migrations/index.ts # packages/core/content-releases/server/src/services/__tests__/release-action.test.ts # packages/core/content-releases/server/src/services/release-action.ts # packages/core/content-releases/server/src/utils/index.ts # packages/core/review-workflows/server/src/services/stages.ts # packages/core/review-workflows/server/src/services/workflows.ts # tests/api/plugins/content-releases/releases.test.api.ts
…ial releases spec - Publish is disabled while a release is blocked (running it would release nothing) - the release created from skipped entries starts without a date - a release that failed before the upgrade can't be carried over through the API either - deleted entries get a grey row in a release that ran - a manual run stopped by an unexpected error answers 400 naming the error, with the frozen release, instead of a bare 500 - the grace period that lets an overdue release still be published by hand is stated and tested
Publish is disabled on a blocked release since d26ae46; the e2e still clicked it. Also replace every '&' in the timezone label (CodeQL incomplete string escaping).
butcherZ
force-pushed
the
feature/ee-87-partial-release
branch
from
October 28, 2026 21:13
86f095e to
55e2b57
Compare
…ial releases test session Issues found by running the Partial releases blitz session against this branch: - Release side panels were cut off on small screens (fixed 50rem width). The panels now use Tailwind classes, are full width on phones and 50rem from sm up. - Escape inside an open date, time or timezone picker closed the whole panel and lost the input. - "This value is required." stayed under Time after picking a time, and a cleared time came back. - Arrow keys moved the focus between release modes without selecting one. - Typing in the release panel lagged once every change was validated: the timezone field is memoized and the form revalidates on change only after the first submit. - A duplicate release name (and edit, delete or action errors) showed "An error occurred" instead of the server message. - Relative dates counted 24-hour periods, so a release two calendar days away said "Tomorrow". - Missed and pre-upgrade releases showed the time they were frozen instead of their scheduled time. - Readiness didn't refresh after a review stage change in the Content Manager. - A partial run showed a success toast; a failed run showed only the raw error. Partial now warns with the counts, failed says nothing was released. - A release that ran still said "Scheduled for"; it now says "Released on". Header parts use one separator. - The disabled Publish button gave no reason; it now has a tooltip. - "Waiting on other entries" said "some were not ready" when another entry failed. - Skip reasons now keep the message of client-safe errors (ApplicationError); other errors stay name-only.
…, clearer schedule column (#28348)
* feat(content-releases): send the release mode, run status and skipped entries in release telemetry * feat(content-releases): list every reason of an entry in one box in the reason drawer * chore(content-releases): document and test the release telemetry events Lists willEditReleaseFromHome as the admin's only release event, notes that the server events replace didCreateRelease and didPublishRelease, and pins the telemetry a failed manual run and a frozen release send. * fix(content-manager): an entry opened from a release doesn't show its validation errors Content Releases opens an entry with forceValidation so its errors show straight away, but the edit view validated with draft rules, which skip required fields, and passed the yup result itself as the form's initial errors. It now checks the entry as Publish does and turns the errors into form errors, in the edit view and the preview. * fix(content-releases): the entry's Releases box says an entry that isn't ready will be published The Releases box in the Content Manager said "Will be published in" for an entry that fails validation or isn't at the required review stage, which the release will skip or be blocked by. It now says "Not ready to be published in" for a publish action whose entry isn't ready. * fix(content-releases): the upcoming releases widget hides scheduled releases behind undated ones The home widget listed undated releases first and kept four, so with four undated releases a release actually scheduled to run never showed. It now lists scheduled releases first, soonest first, then fills the remaining slots with undated ones. It also said "Not Scheduled" where the releases list says "Not scheduled". * fix(content-releases): release page and reason panel misreport empty runs, dates and issues * fix(content-manager): an entry opened from a release hides its errors once a locale is saved
…drawer Packages declared @strapi/design-system and @strapi/icons 2.2.4, which has no next entry. Only the root resolutions forced the experimental build, which apps installing the published packages never see.
Apps created from an experimental build get the unstableNextDesignSystem flag, so the content releases drawers are styled.
…api into feature/ee-87-partial-release
… off Apps opt in by adding unstableNextDesignSystem to config/features themselves.
@strapi/icons and @strapi/ui-primitives move with it: the design system pins ui-primitives and its icons peer range excludes the experimental build.
Conflict in the release publish flow: develop's release webhook deduplication (#27909) now runs in release-run.ts, around each entry the run publishes or unpublishes.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does it do?
Merges the partial release feature (EE-87) into
develop. A release can now publish the entries that are ready and skip the others, record what happened to each entry, and hand the skipped ones to a new release.Backend (
content-releases,@strapi/database):releaseConditionon releases,all_or_nothing(default, previous behaviour) orallow_partial. Inallow_partial, every entry is checked under the release lock (publish validation + required review stage); entries that aren't publishable are skipped, the others are published/unpublished each in its own savepoint (strapi.db.savepoint, new in@strapi/database).outcome+reasonon each release action (published,unpublished,skipped_invalid,skipped_not_approved,skipped_error, …). Planned releases also store why an entry isn't publishable, next toisEntryValid.totalPublishedEntries,totalUnpublishedEntries,totalSkippedEntrieson the release; returned by the publish route, the release routes and thereleases.publishwebhook.empty,ready,blocked) until a run, then frozen (done,partial,failed). A release that ran can't be edited, re-published or gain/lose entries. Status updates are saved with the entry change under one release lock. Overdue releases are frozen asfailed(failureReason:missed_schedule/failed_before_upgrade).POST /content-releases/:id/create-from-skipped-entriescreates a planned release from the entries apartial/failedrelease skipped.releaseConditionon existing releases; record outcomes and totals for releases that ran before this change.Admin:
Drawerfrom@strapi/design-system/nextbehindfuture.unstableNextDesignSystem(move to stable DS tracked in EE-283).Why is it needed?
Today one entry that can't be published cancels the whole release. Partial release lets editors ship what's ready, see exactly what was skipped and why, and retry the rest.
How to test it?
EE license required; i18n + Review Workflows for the stage cases. Admin side panel needs
future: { unstableNextDesignSystem: true }.yarn test:unit,yarn test:front,yarn test:front:ceinpackages/core/content-releasesyarn test:api tests/api/plugins/content-releases(SQLite, Postgres, MySQL)yarn test:e2e --domains content-releases(EE)Related issue(s)/PR(s)
EE-87
Sub-PRs merged into
feature/ee-87-partial-release: #27894, #27983, #28030, #28040, #28048, #28077, #28093, #28124, #28160, #28175, #28212, #28282