Pewarta Proxy

📋 Server Request & Proxy Logs

Loading active proxy settings...
Developed by Khairul Adha (adhexa.id)
Mengambil log server...

⚙️ Pengaturan Proxy Target

Skip to content

feat(content-releases): partial releases - #28339

Draft
butcherZ wants to merge 26 commits into
developfrom
feature/ee-87-partial-release
Draft

butcherZ wants to merge 26 commits into
developfrom
feature/ee-87-partial-release

Conversation

@butcherZ

Copy link
Copy Markdown
Member

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

Admin:

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:ce in packages/core/content-releases
  • yarn test:api tests/api/plugins/content-releases (SQLite, Postgres, MySQL)
  • yarn test:e2e --domains content-releases (EE)
  • Manual scenarios: see each sub-PR's "How to test it?" section.

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

butcherZ and others added 13 commits October 6, 2026 11:09
* 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
butcherZ force-pushed the feature/ee-87-partial-release branch from 86f095e to 55e2b57 Compare October 28, 2026 21:13
Re-added by 87f5d9f after #28282 removed it; the deleted entry keeps its grey italic name.
…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.
butcherZ and others added 8 commits October 30, 2026 09:57
* 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.
… 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.
@butcherZ butcherZ added the publish-experimental Trigger the Experimental publish on npm (publish-prerelease.yml) label Oct 30, 2026
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

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants