CaaS auto-publish: extract payload builder into leaf module + standalone bundle#6227
Open
shkhan91 wants to merge 5 commits into
Open
CaaS auto-publish: extract payload builder into leaf module + standalone bundle#6227shkhan91 wants to merge 5 commits into
shkhan91 wants to merge 5 commits into
Conversation
Introduces tools/send-to-caas/auto-publish.js, a new library that hosts
(da-live editor, milo bulk-publish-v2) call after a successful Helix
preview/publish to push the page into CaaS via the existing milo-caas
gateway. Replaces an earlier approach that polled Helix logs externally
and managed its own auth — that design was operationally fragile.
Hooking next to the publish primitive keeps the user's IMS token in
scope, removes a separate auth path, and surfaces failures immediately
in the host's UI.
Design
- Data-driven config at /.milo/caas/config.json per site, fetched via
the existing getCustomConfig helper. Mirrors the URL-pattern shape
of /.milo/publish-permissions-config.json: '**' suffix matches
descendants, exact match otherwise; longest pattern wins.
- Reuses send-utils.js unchanged for HTML -> XDM transformation. No
changes to the existing CaaS publishing logic.
- Per-page controls: pages without a .card-metadata block are skipped
silently; an explicit "auto-publish | false" row in card-metadata
opts a single page out without touching site config.
- Default routing: preview -> [prod+draft, stage+live]; publish ->
[prod+live]. A rule's `targets` array overrides defaults.
- Never throws. Returns { skipped, reason } or { skipped:false,
results } or { skipped:false, error }. CaaS publishing is best-
effort and must not block the underlying Helix publish.
- Per-target failures are isolated; one CaaS env failing does not
affect the others.
Scope
Pure additive change — no existing files modified. Integration into
bulk-publish-v2/services.js and da-live's saveToAem() will land in
follow-up PRs once this library is reviewed.
Testing
35 tests in test/tools/send-to-caas/auto-publish.test.js cover:
- matchesUrl, resolveRule, resolveTargets, isDisabledOnPage as
pure functions
- every gating skip reason (unsupported action, missing args,
no config, no matching rule, rule disabled, page fetch error,
no card-metadata, page-level disable override)
- posting paths: 1 call on publish, 2 parallel calls on preview,
rule.targets overriding defaults, per-target failure isolation
- never-throws contract: getCustomConfig rejection, getAuthToken
throwing, both surface as structured errors
All 45 tests in test/tools/send-to-caas/ pass; 25/25 bulk-publish-v2
tests pass; no regressions.
Wires the new caasAutoPublish library into bulk-publish-v2 so that bulk
preview/publish jobs automatically index successful URLs into CaaS.
Mirrors how the same library will be invoked from da-live's single-page
publish path: hook next to the existing Helix admin call, reuse the
user's IMS token, never block the underlying publish.
What was added
- libs/blocks/bulk-publish-v2/auto-publish-hook.js
A small orchestrator (runAutoPublishForJob) that consumes a Helix
job result, filters to successful resources on supported topics
(preview/publish only), checks site opt-in, fetches the IMS token
once, then invokes caasAutoPublish for each path in parallel. All
side-effects are isolated through dependency injection (publish,
getToken, optedIn) which makes the hook fully unit-testable
without touching the real IMS or network.
- libs/blocks/bulk-publish-v2/components/job-process.js
A 10-line addition in updated(): once per job (guarded by a
caasAutoPublishFired boolean against Lit re-renders), fire the
hook and swallow any error. The bulk-publish UI never waits on,
observes, or surfaces CaaS results — failure cannot affect
existing functionality.
Failure isolation (three layers)
- Per-target inside caasAutoPublish (postDataToCaaS rejection
becomes ok: false on that target, others still post).
- Per-resource inside runAutoPublishForJob (one path throwing is
captured as an entry in the result array).
- Top-level .catch(() => {}) in job-process.js (any unexpected
error is silently dropped).
Lazy IMS load
The hook short-circuits before fetching IMS by checking
/.milo/caas/config.json via the existing cached getCustomConfig
helper. Sites that have not opted in never load the IMS library;
this also keeps existing bulk-publish-v2 tests free of the
"external script in tests" warning.
Mock fetch hardening (independent improvement)
test/blocks/bulk-publish-v2/mocks/fetch.js previously threw a
TypeError when a request URL was not in the fixture list (it
destructured an undefined response). Replaced with a graceful 404
response. Necessary for the new background fetches the auto-publish
hook makes, and a defensive improvement on its own — additions to
existing components no longer require updating the mock fixture
just to keep tests passing.
Scope discipline
- send-utils.js intentionally untouched. The library imports
setConfig/getCardMetadata/getCaasProps/postDataToCaaS/
loadCaasTags as-is; modifying that file would be churn.
- bulk-publish-v2/services.js intentionally untouched. The hook
lives one level up, in the consumer (job-process.js), so the
services layer keeps a single responsibility.
- Only preview/publish topics fire the hook. unpublish/delete
CaaS removal is a future PR.
Testing
13 new tests in test/blocks/bulk-publish-v2/auto-publish-hook.test.js
cover: collectSuccessfulPaths variants (missing/malformed jobStatus,
mixed status codes, webPath/path fallback), all gating skip paths
(missing origin/topic, unsupported topic, no successful paths,
not opted in, missing token, throwing token), happy paths
(per-resource fanout with correct args for preview and publish),
per-resource error isolation, defensive parsing of malformed
origins, and verification that getToken is not invoked when the
site is not opted in.
All 85 tests pass: 45 in test/tools/send-to-caas/ (existing 10 plus
35 from the auto-publish library), and 38 in test/blocks/
bulk-publish-v2/ (existing 25 plus 13 from the new hook). No
regression in existing bulk-publish-v2 tests.
- Add buildCaasXdmPayload() + hasCardMetadata/isDisabledOnPage in a new self-contained leaf (tools/send-to-caas/caas-payload-core.js) that does not import utils.js/caas-utils.js, so it can be bundled standalone. - send-utils.js re-exports the payload surface and keeps the browser-only postDataToCaaS/isPagePublished; injects the lazy 706KB caas-tags fallback so the leaf stays free of it. - Refactor caasAutoPublish() to use buildCaasXdmPayload(). - Add build/caas-payload-builder.js entry + build:caas-payload-builder microbundle script producing a single ~20KB UMD bundle for milo-caas to fetch and run. 271 CaaS unit tests pass.
The bundle is a minified build artifact (like libs/deps/*); add it to eslint ignorePatterns so lint-changed-files does not flag it.
- Only pages carrying a caas:content-type tag auto-publish (matches the original AEM behavior); core pages without one are a clean skip, not an error. Adds hasContentTypeTag() and applies it in caasAutoPublish(). - Add getCaasIds(prodUrl, floodgatecolor) to derive a card's entityId/ contentId from the prodUrl alone (no DOM) for milo-caas removal. - Export both from the leaf, send-utils, and the bundle entry; rebuild the standalone bundle. Milo CaaS unit tests: 272 passing (adds a no-content-type-tag gate test).
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 & why
Milo is static-only (AEM Edge Delivery) and cannot host a backend endpoint, but the CaaS card→XDM business logic must be reusable from a backend service (
milo-caas) that auto-publishes pages to CaaS on a schedule. This PR extracts that logic into a self-contained leaf module and produces a small standalone bundle thatmilo-caasfetches (pinned by SHA-256) and runs in avmsandbox — keeping a single source of truth here in Milo.This PR is library/tooling only — it does not change any page rendering and is behavior-preserving for the existing browser "Send to CaaS" / bulk-publish paths.
buildCaasXdmPayload()(plushasCardMetadata/isDisabledOnPage) in a new self-contained leaftools/send-to-caas/caas-payload-core.jsthat does not importlibs/utils/utils.jsorlibs/blocks/caas/utils.js(those transitively drag in Milo's bootstrap, a 706KB tag taxonomy, and lazy chunks — which makes the module impossible to bundle standalone). The onlylibs/import is the leaf-safegetUuid.js.send-utils.jsnow re-exports the payload surface from the leaf and keeps only the browser-only pieces (postDataToCaaS,isPagePublished). It injects the 706KBcaas-tagsfallback lazily viasetConfig({ getCaasTagsFallback }), so the leaf stays free of it and the browser never eagerly downloads it when the network tag fetch succeeds.caasAutoPublish()to callbuildCaasXdmPayload()(removes the duplicated inlinesetConfig → loadCaasTags → getCardMetadata → getCaasPropssequence). No behavior change.build/caas-payload-builder.jsentry +build:caas-payload-buildernpm script (microbundle UMD,--external none, mirroring the existingbuild:gnav-profilepattern) producing a single ~20KB committed bundle attools/send-to-caas/caas-payload-builder.js, served frommilo.adobe.com.Companion PR
This is Part 1 of 2. The backend service that consumes the bundle lives in
milo-caas:Together:
milo-caaspolls the DA/Franklin admin log per tenant → fetches the page HTML → runs this bundle to build the XDM payload → posts to Chimera (preview → CaaS stage, publish → CaaS prod).Design notes for reviewers
send-utils.jsdirectly? A standalone import ofsend-utils.jspulls inutils.js(2850 lines, top-levelwindow/documentside effects) and its lazy graph (e.g.preflight-notification~170KB). The leaf isolates the pure payload logic so the bundle is ~20KB andvm-safe.caas-tagsfallback injected rather than imported? microbundle UMD cannot code-split, so a dynamic import breaks the single-file build, while a static import would bloat the bundle to ~404KB and eager-load 706KB in the browser. Injecting it keeps the bundle tiny and the browser lazy. The leaf reaches the fallback only when the network tag fetch fails.contentId/entityId/urlderive from theprodUrlstring — unchanged here, but this is why the consuming service applies per-tenant.htmlrules.Testing
tools/send-to-caas+blocks/caasunit tests: 271 passing (auto-publish,bulk-publish-to-caas,send-to-caas,caas/utils). No regressions.milo-caasvm+linkedomloader against the real bundle (tags resolve,caasPropscorrect,.htmldrivescontentId/url).Resolves: MWPW-117684
Test URLs: