Description
Follow-up to #36587/PR #36633 (date-lockstep SDK versioning), which removed the standalone @next prerelease channel entirely — SDK packages are now only published to the latest npm dist-tag, and only when a real dotCMS release is cut (cicd_release-sdk.yml, triggered by release: created). Nothing publishes to npm on a plain merge to main anymore.
This created a gap for internal QA: the team runs a post-merge QA phase against "real" environments, not local code (npm pack + .tgz install isn't usable there). Without a next channel, there's no installable, non-production SDK version to point those environments at between merges and the next real release cut.
This issue reintroduces a next npm dist-tag, published automatically on merge to main when SDK files change — but explicitly as an internal dev/QA-only channel, not a customer-facing one, and without reopening the "second door for an off-version SDK publish" concern ADR-0019 originally removed next to close. The latest/date-lockstep mechanism (real releases, MinSdkVersion, the compatibility handshake) is not touched at all by this change.
Naming scheme
The next version is computed at publish time — no local VERSION file is reintroduced:
- Query the currently-published
latest version live from npm (e.g. npm view @dotcms/client version).
- Append
-next.<github.run_number> (unique, monotonically increasing per workflow run).
Example: if latest is currently 26.3.17-1, a trunk run publishes 26.3.17-1-next.87. Verified with Node's semver package that this format is valid strict and loose semver — safe for npm publish.
Because this string always carries an explicit -next. prerelease suffix, it can never be mistaken for a real date-lockstep release version — and it's never something we tell customers to install.
Proposed changes
deploy-javascript-sdk/action.yml — add a new optional input npm-tag (default 'latest'); use it in place of the currently hardcoded --tag latest in the publish step. Everything else in the action (build, per-package version rewrite, idempotency check) is reused unchanged for both tags.
cicd_3-trunk.yml — re-add SDK-changed detection and a next-publish step:
Explicitly not touched
cicd_comp_deployment-phase.yml, cicd_release-sdk.yml, cicd_6-release.yml, cicd_comp_release-prepare-phase.yml, MinSdkVersion.java, SdkVersionWebInterceptor.java, and all SDK-compatibility-check TypeScript code (sdk-compatibility.ts and friends) — the real-release, date-lockstep, and version-handshake mechanisms are unaffected.
Why this doesn't reopen the ADR-0019 "second door" concern
next versions are never date-lockstep-shaped, so they can never satisfy or interfere with the one-dotCMS-version⇄one-SDK-version invariant, which only concerns latest.
- The SDK's own compatibility check (
sdk-compatibility.ts's parseVersionSegments/compareVersions) already fails open (returns null, no warning logged) on a version string like 26.3.17-1-next.87, since the next/run-number segments aren't plain integers — verified against the existing, unmodified parsing logic. No code change needed there for this safety property to hold.
next is purely an internal dev/QA convenience; it must never be documented or recommended to customers as an installable channel.
Acceptance Criteria
Priority
Medium
Additional Context
Testing plan: mirror how #36587/PR #36633 was validated — implement and test first in the core-workflow-test fork (dry-run trigger, then a real trunk-style push with SDK changes) before applying the same changes to dotcms/core.
Out of scope:
References:
Description
Follow-up to #36587/PR #36633 (date-lockstep SDK versioning), which removed the standalone
@nextprerelease channel entirely — SDK packages are now only published to thelatestnpm dist-tag, and only when a real dotCMS release is cut (cicd_release-sdk.yml, triggered byrelease: created). Nothing publishes to npm on a plain merge tomainanymore.This created a gap for internal QA: the team runs a post-merge QA phase against "real" environments, not local code (
npm pack+.tgzinstall isn't usable there). Without anextchannel, there's no installable, non-production SDK version to point those environments at between merges and the next real release cut.This issue reintroduces a
nextnpm dist-tag, published automatically on merge tomainwhen SDK files change — but explicitly as an internal dev/QA-only channel, not a customer-facing one, and without reopening the "second door for an off-version SDK publish" concern ADR-0019 originally removednextto close. Thelatest/date-lockstep mechanism (real releases,MinSdkVersion, the compatibility handshake) is not touched at all by this change.Naming scheme
The
nextversion is computed at publish time — no localVERSIONfile is reintroduced:latestversion live from npm (e.g.npm view @dotcms/client version).-next.<github.run_number>(unique, monotonically increasing per workflow run).Example: if
latestis currently26.3.17-1, a trunk run publishes26.3.17-1-next.87. Verified with Node'ssemverpackage that this format is valid strict and loose semver — safe fornpm publish.Because this string always carries an explicit
-next.prerelease suffix, it can never be mistaken for a real date-lockstep release version — and it's never something we tell customers to install.Proposed changes
deploy-javascript-sdk/action.yml— add a new optional inputnpm-tag(default'latest'); use it in place of the currently hardcoded--tag latestin the publish step. Everything else in the action (build, per-package version rewrite, idempotency check) is reused unchanged for both tags.cicd_3-trunk.yml— re-add SDK-changed detection and anext-publish step:sdk_libschange-detection filter (defined in.github/filters.yaml, computed bycicd_comp_initialize-phase.yml) — this filter was never deleted in Align SDK publish pipeline with dotCMS date-lockstep versioning #36587/refactor(deployment): update SDK publishing workflow to align with dotCMS release strategy #36633, only the wiring in trunk that consumed it for publishing was removed.nextversion as described above and callsdeploy-javascript-sdkwithnpm-tag: next, gated on thesdk_libsfilter matching andgithub.event_name != 'workflow_dispatch'(mirroring the exact condition the pre-Align SDK publish pipeline with dotCMS date-lockstep versioning #36587 mechanism used).Explicitly not touched
cicd_comp_deployment-phase.yml,cicd_release-sdk.yml,cicd_6-release.yml,cicd_comp_release-prepare-phase.yml,MinSdkVersion.java,SdkVersionWebInterceptor.java, and all SDK-compatibility-check TypeScript code (sdk-compatibility.tsand friends) — the real-release, date-lockstep, and version-handshake mechanisms are unaffected.Why this doesn't reopen the ADR-0019 "second door" concern
nextversions are never date-lockstep-shaped, so they can never satisfy or interfere with the one-dotCMS-version⇄one-SDK-version invariant, which only concernslatest.sdk-compatibility.ts'sparseVersionSegments/compareVersions) already fails open (returnsnull, no warning logged) on a version string like26.3.17-1-next.87, since thenext/run-number segments aren't plain integers — verified against the existing, unmodified parsing logic. No code change needed there for this safety property to hold.nextis purely an internal dev/QA convenience; it must never be documented or recommended to customers as an installable channel.Acceptance Criteria
deploy-javascript-sdk/action.ymlhas a new optionalnpm-taginput (defaultlatest), used in the publish step instead of the hardcoded valuecicd_3-trunk.ymlcomputes anextversion from the currently-publishedlatestnpm version +-next.<run_number>suffix, with no localVERSIONfile reintroducedcicd_3-trunk.ymlonly publishes tonextwhen SDK files changed (reusing the existingsdk_libsfilter) and the run is not a manualworkflow_dispatchmainwith SDK changes results in a new@dotcms/client@<version>-next.<n>published under thenextdist-tag, installable vianpm install @dotcms/client@nextcicd_release-sdk.yml/cicd_6-release.yml/MinSdkVersion/SdkVersionWebInterceptor— the real-release/date-lockstep/compatibility-handshake mechanism remains fully untouchednextSDK build does not trigger any false-positive/false-negative in the SDK compatibility check (fails open due to the unparsable version string)Priority
Medium
Additional Context
Testing plan: mirror how #36587/PR #36633 was validated — implement and test first in the
core-workflow-testfork (dry-run trigger, then a real trunk-style push with SDK changes) before applying the same changes todotcms/core.Out of scope:
latestis published or versioned (date-lockstep stays exactly as-is).MinSdkVersionor the SDK compatibility handshake (SDK compatibility handshake: server advertises version + minimum supported SDK, SDKs warn on mismatch #36609/Automate MIN_SDK_VERSION bump via release pipeline + AI-based SDK-breaking-change detection #36698).nextchannel for@dotcms/dotcli— scope is limited to the SDK libs (core-web/libs/sdk/*) only.References:
@nextchannel as part of date-lockstep versioning (ADR-0019)MIN_SDK_VERSIONrelease-pipeline automation (separate, unaffected concern)