Skip to content

MWPW-194144: Add opt-in cascade publishing for references - #912

Merged
afmicka merged 94 commits into
mainfrom
MWPW-194144
Aug 12, 2026
Merged

MWPW-194144: Add opt-in cascade publishing for references#912
afmicka merged 94 commits into
mainfrom
MWPW-194144

Conversation

@seanchoi0

@seanchoi0 seanchoi0 commented May 28, 2026

Copy link
Copy Markdown
Contributor

Resolves https://jira.corp.adobe.com/browse/MWPW-194144

Add opt-in cascade publishing for fragment references (variations and cards/collections), with snapshot-based tracking for project bulk publish.

Changes

Single fragment publish

  • New `mas-publish-dialog` — lists publishable references (variations + cards) with individual checkboxes and Select All
  • `Fragment.getPublishableReferences()` — returns NEW/draft/unpublished variations and cards (includes NEW-status refs that have never been published)
  • `publishFragment(fragment, { selectedRefIds, allSelected })` — `allSelected` cascades DRAFT/MODIFIED/UNPUBLISHED then explicitly publishes any NEW refs by ID; partial selection publishes refs separately
  • Connected to `editor-panel`, `mas-fragment-editor`, `mas-selection-panel`

Bulk publish — snapshot-based targeting

  • `mas-bulk-publish-confirm-dialog` — two opt-in checkboxes: Include variations / Include sub-collections & cards
  • `createSnapshot` traverses the fragment tree based on `includeCards`/`includeVariations` flags and stores explicit paths per entry
  • Project mode always uses `filterReferencesByStatus = []` (cascade disabled); snapshot paths drive publish targets directly — eliminates cascade overshoot
  • Snapshot paths validated against `PATH_PREFIX` before use; `serializeEntries`/`deserializeEntries` now symmetric (both carry `path` field)

Resilience improvements

  • Stuck Publishing escape hatch — Revert button enabled during Publishing state when snapshots exist
  • Pending snapshot reuse — interrupted publish reuses existing snapshot (`publishComplete: false` marker + valid `path` fields)
  • ETag retry loop — `updateProjectFragment` retries up to 2× on 412/500; `fetchOdin` now attaches `.status` to thrown errors for reliable retry detection

Test coverage

  • `index.js`: 98.65% (was 88.92%)
  • `snapshot.js`: 100% (was 99.03%)
  • 245 passing tests (io/studio), 2326 passing (studio)

Test URLs

Checklist

  • Code follows project conventions
  • Tests pass locally
  • Linter runs without errors
  • Tested on Before/After URLs

seanchoi0 and others added 10 commits May 26, 2026 13:22
- bulk-snapshot: create pre-publish CF version snapshots with processBatchWithConcurrency
- bulk-revert: restore versions and unpublish via /adobe/sites/cf/workflows
- bulk-check-modifications: compare fragment modified timestamps against snapshot
- Register all three actions in app.config.yaml

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use /adobe/sites/cf/fragments/publish with scheduled_deactivation
  workflow instead of non-existent /adobe/sites/cf/workflows endpoint
- Fix STATUS_PUBLISHED/MODIFIED constants to use uppercase (PUBLISHED,
  MODIFIED) matching AEM CF API response values

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add includeVariations/includeCards checkboxes to bulk-publish confirm dialog
- Update publishBulk client to pass cascade options in request body
- IO action computes filterReferencesByStatus from includeVariations||includeCards
- publisher.js accepts filterReferencesByStatus param (default DRAFT,UNPUBLISHED)
- startPublishing and mas-bulk-publish-editor wire cascade options end-to-end
- Add tests for new IO action and publisher behavior

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch from sp-dialog-wrapper to sp-underlay+sp-dialog pattern (white background)
- Append dialog inside sp-theme for correct Spectrum token inheritance
- Add emphasized to Select All checkbox (blue), keep individual items standard
- Add ref-item card style (blue-100 background, border-radius)
- Fix intro text: "Check items to include" instead of "Uncheck to keep in draft"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@aem-code-sync

aem-code-sync Bot commented May 28, 2026

Copy link
Copy Markdown

Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch.
In case there are problems, just click the checkbox below to rerun the respective action.

  • Re-sync branch
Commits

- Adopt project-based architecture: publishBulk now uses projectId
- Preserve cascade options (includeVariations/includeCards) through new architecture
- Add filterReferencesByStatus logic to runWithProject in IO action
- Add MODIFIED status to all filterReferencesByStatus arrays
- Fix handleConfirmPublish to use optional chaining on e?.detail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…cards, and variations

- snapshot.js: rewrite createSnapshot with recursive BFS — when includeCards is
  true, follows cards and collections fields at every level of the tree; when
  includeVariations is true, also includes variations of all in-scope fragments.
  Visited Set prevents cycles and deduplication. Parameter renamed from
  includeRefs to includeCards + includeVariations.
- index.js: pass includeCards and includeVariations separately to createSnapshot.
- confirm-dialog: update labels — CB1 "Include sub-collections & cards",
  CB2 "Include variations (incl. nested items)"; cascade note simplified.
- editor: fix handleConfirmPublish optional chaining for programmatic calls.
- tests: update snapshot tests for new params; add recursive, collections-field,
  and sub-item variation test cases.

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

codecov Bot commented Jun 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 87.43883% with 77 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.36%. Comparing base (45fd185) to head (4e79453).

Files with missing lines Patch % Lines
studio/src/bulk-publish/mas-bulk-publish-editor.js 58.44% 32 Missing ⚠️
studio/src/mas-selection-panel.js 56.75% 16 Missing ⚠️
studio/src/mas-fragment-editor.js 0.00% 12 Missing ⚠️
studio/src/mas-repository.js 86.36% 6 Missing ⚠️
studio/src/publish/mas-publish-dialog.js 96.52% 5 Missing ⚠️
io/studio/src/bulk-publish/snapshot.js 93.93% 4 Missing ⚠️
...rc/bulk-publish/mas-bulk-publish-confirm-dialog.js 95.23% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #912      +/-   ##
==========================================
+ Coverage   90.25%   90.36%   +0.10%     
==========================================
  Files         303      305       +2     
  Lines       96845    97382     +537     
==========================================
+ Hits        87409    87997     +588     
+ Misses       9436     9385      -51     
Files with missing lines Coverage Δ
io/studio/src/bulk-publish/bulk-publish-worker.js 100.00% <100.00%> (+0.68%) ⬆️
io/studio/src/bulk-publish/index.js 100.00% <100.00%> (ø)
io/studio/src/bulk-publish/project.js 100.00% <100.00%> (ø)
io/studio/src/bulk-publish/publisher.js 93.81% <100.00%> (ø)
studio/src/aem/aem.js 52.19% <100.00%> (+0.06%) ⬆️
studio/src/aem/fragment.js 96.02% <100.00%> (+0.16%) ⬆️
studio/src/bulk-publish/bulk-publish-client.js 97.18% <100.00%> (+0.46%) ⬆️
studio/src/bulk-publish/bulk-publish-store.js 100.00% <100.00%> (ø)
studio/src/editor-panel.js 60.15% <100.00%> (+0.77%) ⬆️
...io/src/placeholders/mas-placeholders-repository.js 89.54% <100.00%> (ø)
... and 8 more

... and 7 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 45fd185...4e79453. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

  Add 'NEW' to filterReferencesByStatus so Odin cascade-publishes
  freshly created fragments (status NEW) when includeCards or
  includeVariations is enabled. Previously only DRAFT/MODIFIED/UNPUBLISHED
  fragments were cascade-published, causing newly seeded cards and locale
  variations to be skipped.

  Also adds seed-test-data.mjs and cleanup-test-data.mjs scripts for
  manual testing of the bulk-publish snapshot/revert flow.

  Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use snapshot paths as explicit publish targets instead of cascade to
  include NEW-status fragments that cascade status filter would skip
- Add 412/500 retry logic to updateProjectFragment to recover from
  AEM CDN cache serving stale ETags after a preceding PUT
- Serialize fragment paths into snapshot entries so they survive
  across publish retries
- Guard pending snapshot reuse: only reuse if entries contain path
  field (new format); fall back to fresh snapshot for old-format entries
- Enable REVERT during Publishing state when snapshots exist, giving
  users an escape hatch when a project gets stuck

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

When only CB2 (Include variations) was checked without CB1 (Include
sub-collections & cards), Odin's cascade was following the collection's
`cards` and `collections` references and publishing fragments that were
never added to the snapshot. On revert, those extra fragments remained
published because they weren't tracked.

Root cause: filterReferencesByStatus was enabled whenever includeVariations
OR includeCards was true, triggering Odin cascade. But in project mode the
snapshot already performs explicit traversal based on the checked flags —
cascade must be disabled so the publish scope stays exactly what the
snapshot captured.

Fix: always use filterReferencesByStatus=[] in runWithProject.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@seanchoi0
seanchoi0 marked this pull request as ready for review June 2, 2026 20:48
…t.js

- Add 10 new tests in index.test.js covering project-read error, empty paths,
  pending snapshot reuse, resolve edge cases, paths/locales validation, and
  filterReferencesByStatus passthrough in direct mode
- Add snapshot.test.js coverage for sub-fragment skip when versionId=null
- Apply prettier formatting to long function signatures in snapshot.js,
  publisher.js, bulk-publish-client.js, bulk-publish-store.js

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

afmicka commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

@seanchoi0 could you please resolve the conflicts on this? Will try to find time to validate it tomorrow my time.

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

afmicka commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

@seanchoi0

  1. in the Bulk publish, when i click to publish without checking any variations or collections (i want only the fragment to be published), it gets stuck in the infinite loop. Could you please check?
    https://mwpw-194144--mas--adobecom.aem.live/studio.html?io.studio.env=seanchoi#bulkPublishProjectId=8dd50b51-6fbd-4a10-b90c-4befef047a24&page=bulkPublishEditor&path=sandbox
Screenshot 2026-08-05 at 15 08 34
  1. When user is asked to select variations to select for publishing, it shows Odin names and paths. We should be displaying Fragment Title and Fragment Paths that are in studio and user are used to them for recognizing the fragments
Screenshot 2026-08-05 at 15 20 01 Screenshot 2026-08-05 at 15 19 55 Screenshot 2026-08-05 at 15 25 19
  1. When i do select one fragment for publishing with the default, it did not get published. Please verify it is really getting published after some time ( i will wait a bit, just in case please test it yourself)
Screenshot 2026-08-05 at 15 25 25

- Fix indefinite bulk publish polling: worker was getting 404 on project
  fragment because masAccessToken (sessionStorage) must be used instead
  of the plain IMS token; forward aemOdinEndpoint through the dispatch
  chain so the worker hits the correct AEM environment
- Prevent double-dispatch: move publishing store flag before first await
  in startPublishing so it acts as a synchronous mutex; add early-return
  guard when project is already in-flight
- Skip hydrated references during status polls (skipReferences:true) to
  avoid repeated ?references=direct-hydrated requests while polling
- Fail fast in worker when project has no fragment paths: set FAILED
  status immediately instead of silently returning published with 0 items
- Selection panel: restore opt-in cascade publish dialog for multi-select
  and resolve fragment refs from field values instead of hydrated refs
- Publish dialog: show fragment title and studio path instead of DAM path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@afmicka afmicka removed the run nala label Aug 10, 2026
@afmicka

afmicka commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

@seanchoi0 Regarding issue No.2 - We should not display AEM paths at any time. We should use the exact same information a user uses to find a variation in the fragments view. Therefore, these paths either need to be removed and leave only Fragment title or the path should be in the format of the fragment path like "merch-card: SANDBOX / Plans v2 / Individual / com / Creative Cloud Individual" or instead of the path just have a link to the fragment that opens in new tab/window.

If there is no clear requirement right now, remove the paths, leave only the Fragment title and create a separate follow-up jira to discuss what information beside Title should be shown in this dialog
cc: @3ch023 @npeltier

Screenshot 2026-08-11 at 12 36 46

@afmicka afmicka removed the run nala label Aug 11, 2026
…cale for PZN variations

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

seanchoi0 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Addressed @afmicka's feedback on the publish dialog:

  • Removed AEM paths from the reference list
  • Locale variations now show title as the primary label with the locale code (e.g. `fr_FR`) as a subtitle — consistent with the variations panel
  • Grouped (PZN) variations show title only, since locale from the path is not their identifier

Redeployed to: https://mwpw-194144--mas--adobecom.aem.live/studio.html?io.studio.env=seanchoi


Side note — promotions not included in the dialog: `getPublishableReferences()` sources refs from the `variations` field only. Promo variations can also live directly in `references` (without a `variations` field entry), so they're silently skipped. That said, promo variations have their own publish lifecycle managed through the promotions workflow, so excluding them here seems intentional — flagging in case it needs a follow-up.

@afmicka

afmicka commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Addressed @afmicka's feedback on the publish dialog:

  • Removed AEM paths from the reference list
  • Locale variations now show title as the primary label with the locale code (e.g. fr_FR) as a subtitle — consistent with the variations panel
  • Grouped (PZN) variations show title only, since locale from the path is not their identifier

Redeployed to: https://mwpw-194144--mas--adobecom.aem.live/studio.html?io.studio.env=seanchoi

Side note — promotions not included in the dialog: getPublishableReferences() sources refs from the variations field only. Promo variations can also live directly in references (without a variations field entry), so they're silently skipped. That said, promo variations have their own publish lifecycle managed through the promotions workflow, so excluding them here seems intentional — flagging in case it needs a follow-up.

@npeltier @3ch023 could you please confirm comment for the promo variations?

@afmicka

afmicka commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@seanchoi0 i am still seeing the issue #1. When i add one fragment to bulk publish and choose to publish only that one fragment, it gets stuck in the infinite loop. Please check what is causing this. On main it works
https://mwpw-194144--mas--adobecom.aem.live/studio.html?io.studio.env=seanchoi#bulkPublishProjectId=516cdc2b-6266-4416-b1cb-d790ef59a9ff&page=bulkPublishEditor&path=sandbox

@seanchoi0

Copy link
Copy Markdown
Contributor Author

@seanchoi0 i am still seeing the issue #1. When i add one fragment to bulk publish and choose to publish only that one fragment, it gets stuck in the infinite loop. Please check what is causing this. On main it works https://mwpw-194144--mas--adobecom.aem.live/studio.html?io.studio.env=seanchoi#bulkPublishProjectId=516cdc2b-6266-4416-b1cb-d790ef59a9ff&page=bulkPublishEditor&path=sandbox

I re-deployed AIO and it seems working now.

image

@afmicka

afmicka commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

@seanchoi0 Cancel button does not work for me in the publish dialog. Could you try?
https://mwpw-194144--mas--adobecom.aem.live/studio.html?io.studio.env=seanchoi#fragmentId=a7b0af6d-cf72-4894-8400-5408e47393d8&page=fragment-editor&path=sandbox

click to publish and then try to cancel it
Screenshot 2026-08-12 at 17 30 37

@afmicka
afmicka merged commit 1ba8caa into main Aug 12, 2026
23 of 25 checks passed
@afmicka
afmicka deleted the MWPW-194144 branch August 12, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants