Skip to content

ci: retrigger release workflow after suppression token in #175 body - #176

Merged
JonasJesus42 merged 1 commit into
mainfrom
ci/retrigger-release-after-175
May 13, 2026
Merged

ci: retrigger release workflow after suppression token in #175 body#176
JonasJesus42 merged 1 commit into
mainfrom
ci/retrigger-release-after-175

Conversation

@JonasJesus42

@JonasJesus42 JonasJesus42 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Problem

PR #175 (which fixed the release CI by dropping @semantic-release/git) was merged, but the release workflow did not run on the merge commit.

Root cause: the PR #175 body quoted the canonical semantic-release suppression token verbatim while documenting what the dropped plugin used to emit:

The semantic-release release commit emits that token by design (so its own commit doesn't loop a release back through CI).

The squash-merge commit message inherited that quote, GitHub Actions saw the token anywhere in the message, and the workflow was silently skipped. The release.yml header comment warns about this exact pitfall.

Result: the fix from #175 is on main but no release was published, so @decocms/start@5.1.1 remains on npm.

Fix

This PR is a no-op commit whose title and body do not contain the literal suppression token, so the merge push triggers the release workflow normally. Same recovery pattern used after PR #171.

The only file change is a one-line addition to the release.yml header comment noting #175 as a second occurrence of this gotcha, so the breadcrumb is up to date for the next person.

Test plan

Follow-up

Once published, two storefront PRs that depend on #174's new options can fast-follow:

Both currently use a createTanStackRouter direct workaround that I will revert to createDecoRouter after the npm publish.

Generated with Claude Code.


Summary by cubic

Retriggers the Release workflow skipped after #175 because the squash-merge message quoted the semantic-release skip token. Pushes a no-op commit that omits the token to trigger Release CI and updates .github/workflows/release.yml comments to note #171 and #175, unblocking @decocms/start@5.2.0.

Written for commit 674b0d3. Summary will update on new commits.

PR #175 body referenced the semantic-release suppression token
verbatim while documenting what the dropped @semantic-release/git
plugin used to emit. The squash-merge commit message inherited that
verbatim quote and the release workflow was silently skipped, so the
fix from #175 itself never reached npm.

This is a no-op commit whose title and body do not contain the
literal suppression token, so the next push event triggers the
release workflow normally. Same recovery pattern used after PR #171.

Also expanded the workflow header comment to note that #175 hit the
same gotcha — small breadcrumb for the next person.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@JonasJesus42
JonasJesus42 requested a review from a team May 13, 2026 15:42
@JonasJesus42
JonasJesus42 requested a review from vibe-dex as a code owner May 13, 2026 15:42
@JonasJesus42
JonasJesus42 merged commit 5d4621a into main May 13, 2026
2 checks passed
vibe-dex pushed a commit that referenced this pull request May 14, 2026
…#178)

* feat(router): expose preload options + add pdp-fast-navigation skill (#174)

createDecoRouter only exposed defaultPreload, omitting all the TanStack
Router options that control how long a prefetch is reused. Result: even
with `<Link preload="intent">`, hover prefetch was refetched on click
because the default staleTime is short — wasted work, slow perceived
navigation on commerce storefronts.

Expose the missing options:
- defaultPreloadStaleTime
- defaultPreloadGcTime
- defaultPreloadDelay
- defaultStaleTime
- defaultPendingMs
- defaultPendingMinMs

All optional, all forwarded to createTanStackRouter as-is. No default
changes — sites must opt in (commerce sweet spot is staleTime: 60_000).

Also add `.cursor/skills/deco-pdp-fast-navigation/SKILL.md` documenting
the full pattern (5 levers: intent preload + eager sections + staleTime
+ createCachedLoader + reserved-height fallback) discovered while
optimizing a commerce PDP from multi-second click delay to sub-second
perceived navigation.

The skill explicitly recommends `createCachedLoader` over hand-rolled
LRU maps for heavy loaders (thumbnail format detection, Vimeo oEmbed).

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* ci: retrigger release workflow after suppression token in #175 body (#176)

PR #175 body referenced the semantic-release suppression token
verbatim while documenting what the dropped @semantic-release/git
plugin used to emit. The squash-merge commit message inherited that
verbatim quote and the release workflow was silently skipped, so the
fix from #175 itself never reached npm.

This is a no-op commit whose title and body do not contain the
literal suppression token, so the next push event triggers the
release workflow normally. Same recovery pattern used after PR #171.

Also expanded the workflow header comment to note that #175 hit the
same gotcha — small breadcrumb for the next person.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* fix(release): default to latest tag when nextRelease.channel is empty (#177)

semantic-release sets nextRelease.channel from the branches config.
For the main branch (no prerelease flag), channel is null, so
'npm publish --access public --tag ${nextRelease.channel}' interpolates
to 'npm publish --access public --tag ' (trailing empty argument), and
npm rejects with:

  npm error Tag name must not be a valid SemVer range:

Default to 'latest' when channel is falsy. main still publishes under
the default npm dist-tag, next branch (which has prerelease: true and
channel='next') keeps its own tag.

This regressed silently because the previous prepare step
@semantic-release/git always failed on the branch protection rule
before publish was reached, so the publishCmd path was never exercised
on main. After dropping that plugin in the previous release fix, the
publish step finally ran and surfaced this issue.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>

* docs(spec): next adapter admin coverage + shared daemon refactor design

Captures the brainstorming session for closing three gaps in the Next.js
adapter: hosting probes (/_healthcheck, /_ready), broken route-mounting
docs, and missing /watch + /fs/* coverage. Lands a shared Web-standard
daemon core in src/node/daemon/ consumed by both adapters; the
Connect-style wrapping stays as a thin Vite-specific shim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(plan): next adapter admin coverage + shared daemon implementation plan

17-task TDD-discipline plan derived from the matching spec. Phases: core
foundation (version + readiness), node/daemon tier (jwt → auth → handlers →
adapter → dispatcher), TanStack refactor onto shared core, Next adapter
exports + handlers, docs rewrite, final verification.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(core/admin): add ADMIN_COMPAT_VERSION pinned to deco-cx/deco 1.177.x

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(core/admin): add handleDecoReadiness backed by getRevision()

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(daemon): move JWT primitives to src/node/daemon/jwt

Pure Web-Crypto verifyAdminJwt + tokenIsValid relocate to a framework-neutral
tier so the new Web-standard auth wrapper can consume them without crossing
the next/ → tanstack/ boundary. tanstack/daemon/auth.ts keeps its Connect-style
middleware and re-exports the JWT symbols for back-compat.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): add requireAdminJwt Web-standard guard

Returns Response (401/403) to short-circuit or null to continue. Mirrors
createAuthMiddleware's semantics including the DANGEROUSLY_ALLOW_PUBLIC_ACCESS
bypass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): add handleDecoHealthcheck Web-standard handler

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(daemon): move broadcast channel + .deco scanner to src/node/daemon

src/tanstack/daemon/watch.ts becomes a thin Connect-style shim over the
new shared scanner + channel; the chokidar wrapper for Next-side use lives
in src/node/daemon/watcher.ts (lazy singleton, never instantiated from
TanStack).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): Web-standard handleWatchSse SSE handler

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): Web-standard handleFsRequest

GET/PATCH/DELETE on /fs/file/<path> plus the /fs/grep stub the admin search
UI hits. Refuses path traversal. Broadcasts fs-sync events on mutate paths
so the existing SSE channel stays in sync.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): toNodeMiddleware Web↔Connect adapter

Lets the new Web-standard route handlers plug into Vite's middleware stack
without duplicating any dispatch logic. Honors backpressure and treats a
null return as fall-through.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): createDecoAdminRoute dispatcher

Single Web-standard entry point composing all daemon handlers behind
configurable route-group flags. Defaults dev tooling (watch, fs) to off
in production; throws at construction if an auth-gated group is enabled
without a site name.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(pkg): export @decocms/start/node/daemon

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(tanstack/daemon): compose shared Web-standard route handler

createDaemonMiddleware delegates probes, fs, watch, and admin-protocol
dispatch to createDecoAdminRoute via toNodeMiddleware. Volumes WebSocket
binding stays in-place because it requires raw httpServer access. Public
signature unchanged; new optional routes field forwards group toggles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(next): handleDecoAdminRoute composes shared dispatcher

Brings probes, watch, fs, and the corrected route-mounting JSDoc into the
Next adapter without duplicating logic. handleDecoAdminRoute is now a
pre-instantiated createDecoAdminRoute that reads DECO_SITE.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(next): createDecoAdminRouteHandlers convenience factory

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(next): expose new admin coverage surface from the barrel

Adds createDecoAdminRoute, createDecoAdminRouteHandlers, decoAdminRouteHandlers,
handleDecoHealthcheck, handleDecoReadiness, ADMIN_COMPAT_VERSION, and the
related types.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(next): rewrite App Router integration guide with correct route layout

Removes the broken single-catchall recipe and replaces it with the
escaped-folder layout that survives Next App Router's _folder privacy rule
and Turbopack's %2E behaviour. Documents the createDecoAdminRouteHandlers
config pattern and the per-group toggles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* build(tsup): include src/node/daemon entries

Without this glob the new src/node/daemon/* sources only had .d.ts emitted
by tsc; tsup's bundle pipeline never saw them, so dist/node/daemon/index.js
and friends were missing and the @decocms/start/node/daemon subpath would
fail at runtime.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(core/admin): re-export ADMIN_COMPAT_VERSION + handleDecoReadiness from barrel

Without these the tsup externalizer routes cross-bundle imports of
src/core/admin/version + readiness to the @decocms/start/admin subpath
(per DIR_OWNERS in tsup.config.ts) and resolves the named imports to
undefined at runtime. Symptoms: /_healthcheck returned 200 with an empty
body, /_ready threw TypeError: handleDecoReadiness is not a function.

The bug was invisible to vitest because it runs against TypeScript source
and bypasses the bundle externalizer. Caught by the final whole-branch
review's dist-level smoke test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): canonical DAEMON_IGNORED_DIRS with .next/.turbo/dist filters

Three call sites (watch.ts shouldIgnore, volumes.ts walkFiles, volumes.ts
broadcastChange) each carried their own copy of the ignore list. Consumer
testing against Next 16 / Turbopack reported the SSE channel flooded with
.next/dev/server/* fs-sync events on every rebuild because the list didn't
cover framework artefact dirs.

Consolidates the list into src/node/daemon/ignored.ts and extends it with
.next, .turbo, dist, build, .cache, coverage. Both watch.ts and volumes.ts
delegate to the new isIgnoredPath. shouldIgnorePath is preserved as a
deprecated re-export to keep watcher.ts and any external imports working.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(next): expose PATCH and DELETE from createDecoAdminRouteHandlers

The previous {GET, POST} pair broke the documented one-line route file
pattern for /fs/file/*: PATCH (JSON-Patch apply) and DELETE (rm) requests
fell through to 405 because Next App Router only forwards exported method
handlers. Consumers had to fall back to calling createDecoAdminRoute
directly, defeating the purpose of the helper.

Widens DecoAdminRouteHandlers to {GET, POST, PATCH, DELETE} (single handler
reference; the dispatcher already branches on method internally). Updates
the JSDoc example in adminRoute.ts and the layout in docs/using-from-nextjs.md
to re-export all four. Default-instance proxy gains the same two methods.
Smoke test asserts reference equality across all four methods.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: CONTRIBUTING.md + scripts/dev-link-into.sh for consumer testing

Documents the Turbopack-vs-symlinks gotcha (subpath exports fail to resolve
through bun link / npm link with Next 16 + Turbopack — confirmed against
16.2.6) and the dist-overlay workaround. Helper script bundles the rebuild
+ overlay into one command.

Keeps bun link documented as the path-of-first-resort for Vite/Webpack
consumers where it still works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(node/daemon): JSON-patch against non-JSON file returns 200 conflict, not 500

A Next consumer hit PATCH /fs/file/README.md with a type:'json' patch. The
on-disk plaintext content tripped JSON.parse inside applyPatch with a
SyntaxError that escaped the JsonPatchError catch and bubbled all the way
to a 500 with a stack trace. Server is healthy; the file's shape just
doesn't match the patch's expectations — that's exactly the soft-conflict
case the existing TEST_OPERATION_FAILED branch already handles.

Splits the inner JSON.parse into its own try/catch (returns conflict),
applies the same symmetry to the text-patch branch. Test asserts 200
{conflict:true} on a plaintext target.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(node/daemon): add onRequest per-request hook to DecoAdminRouteOptions

Real consumers commonly need to run something before every dispatched admin
request — the canonical case being 'await ensureSetup()' so the block
registry is hydrated before handleMeta / handleDecofileRead /
handleDecoReadiness read it. Wrapping the helper's returned methods by hand
requires re-introducing the four-method dance the helper was supposed to
remove and quietly depends on the all-methods-share-one-handler internal.

onRequest runs after the master enabled check, before pathname dispatch.
Returning undefined continues; returning a Response short-circuits — useful
for custom auth gates and maintenance-mode early-outs without overriding
the whole helper. Four new tests cover: called-once-per-request, Response
short-circuit, undefined continues, and disabled-route skips the hook.
Documented in createDecoAdminRouteHandlers' JSDoc and the App Router guide.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jonas Jesus <jonasdasilvajesus@outlook.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
vibe-dex added a commit that referenced this pull request May 19, 2026
Reverts the full chain of commits introduced in PRs #164, #165, #166,
#167, #170, #174, #175, #176, #177 plus the two semantic-release auto
commits (5.1.0, 5.1.1).

Root cause:
PR #164 (Framework-agnostic entrypoints: /core, /tanstack, /next,
/node) repointed package.json exports from src/ to dist/ and split
the framework into multiple bundle chunks via tsup. This is correct
in principle, but the tsup output produces a separate copy of every
module per entry tier. Files with module-level mutable state
(let foo = ..., new Map(), new Set() at top level) end up with one
copy per dist entry, so writes through one export resolve a
different copy than reads through another export.

Symptoms observed on @decocms/start@5.1.0+ and 5.3.0-rc.0/rc.1:

  - GET/POST /deco/invoke/site/loaders/<any-site-loader>
    → 404 "Unknown handler: site/loaders/<name>"
    despite the loader being correctly emitted into
    site/server/cms/loaders.gen.ts and registered via
    setInvokeLoaders() in setup.ts. The site's setup.ts mutates
    the getRegisteredLoaders closure inside dist/core/admin/index.js,
    while handleInvoke (mounted on the catch-all route) reads
    getRegisteredLoaders from a different copy of invoke.ts bundled
    into dist/tanstack/routes/index.js — which still holds the
    default () => ({}).

  - OTel direct-POST channels silently dropped (metrics + error
    logs) — same pattern in src/core/sdk/observability.ts and
    src/core/sdk/logger.ts. Partially fixed on the
    fix/o11y-shared-state-singleton branch (the rc.1 work) but the
    fix never covered invoke.ts handler registry.

PR #167 patched two other #164 regressions (CLI scripts dropped from
the tsup entries, ESM bundle wrapping require() in a broken __require
shim) and PR #166 finalized the publish surface — both strictly
downstream of #164. #174 (router preload options) and #170/#175/
#176/#177 (CI / release machinery) build on the same foundation.

Path forward:
A future re-attempt at framework-agnostic entrypoints must (a) emit a
single shared bundle for the admin/invoke handler registry, the
observability state, and any other module-level mutable state, or
(b) hoist that state onto a globalThis-keyed singleton from the
start, with a CI guard that fails any new module-level mutable state
inside src/core/. This revert intentionally takes us back to the
single-bundle src/-exports world where the bug is latent but inert.

Verification:
  - npm run build      → succeeds against the pre-#164 source layout
  - On a casaevideo build pinned to a snapshot from this revert,
    POST /deco/invoke/site/loaders/adressByCep returns 500 ("Cannot
    read properties of undefined (reading 'replace')" from the loader
    body, not a 404) — i.e. the registry contains the handler again,
    matching v5.0.0 behaviour.

This is the working-baseline state. Re-landing #174's preload options
on top of the restored src/ layout is a follow-up.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant