Skip to content

fix(release): restore build before publish and the alpha dist-tag - #650

Merged
kirtesh-cstk merged 3 commits into
mainfrom
hotfix/restore-build-before-publish
Sep 16, 2026
Merged

kirtesh-cstk merged 3 commits into
mainfrom
hotfix/restore-build-before-publish

Conversation

@kirtesh-cstk

@kirtesh-cstk kirtesh-cstk commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Two fixes for the npm publish path, both regressions from the workflow rewrite on 15 Sept.

1. dist/ is missing from the published package

4.5.1 on npm contains only package.json, README.md and LICENSE. There is no JS in it, even though main, module, types and exports all point into dist/. Anyone who upgrades gets a build failure on import, in any project type. It is not limited to one hosting platform.

4.4.5 4.5.0 4.5.1
files in tarball 1895 1907 3
unpacked 7.8 MB 7.8 MB 12.3 kB
published with node 18.20.8 / npm 10.8.2 node 18.20.8 / npm 10.8.2 node 24.20.0 / npm 12.0.2

The publish workflow lost its npm run build step when it was rewritten:

-            - run: npm ci
-            - run: npm run build
-            - run: npm publish --provenance --access public
+      - run: npm ci
+      - name: Update npm
+        run: npm install -g npm@latest
+      - name: Release
+        run: npm publish --provenance --access public

Nothing else covers the gap. There is no prepack or prepublishOnly script, so npm publish never builds on its own. package.json declares "files": ["dist"], so with no dist/ on disk that pattern matches nothing and the tarball is left with only the three files npm always includes regardless. No build means an empty package.

The node and npm versions above are the fingerprint: the new workflow pins node 24 and adds npm install -g npm@latest, the old one pinned node 18. 4.5.1 was published 12 minutes after that workflow commit, from the same commit that is main today.

Fix: one script in package.json.

"prepack": "npm run build"

Rather than restoring the workflow step, because prepack covers every publish path including a local npm publish or npm pack, a later workflow edit cannot silently drop it, and a failing build now fails the publish instead of quietly shipping nothing. It also covers the alpha job below. Restoring the step in the workflow as well would just build twice.

2. Alpha releases would overwrite the latest dist-tag

When npm-alpha-publish.yml was deleted and folded into this workflow, the publish-alpha job came out byte-identical to publish. It lost the --tag alpha the standalone workflow had:

# npm-alpha-publish.yml, before deletion
- run: npm ci
- run: npm run build
# Publish package to npm under the "alpha" tag
- run: npm publish --tag alpha --provenance

So a prerelease would move latest and be handed to every consumer on a caret range. Fix: --tag alpha back on the alpha job.

This also restores the alpha channel as a rehearsal for a real publish: cut a prerelease, install it, confirm it resolves, then cut the release, without latest ever moving.

Verification

Clean npm ci on this branch, then npm pack --dry-run:

with prepack:              total files: 1931   unpacked size: 7.8 MB
without (what shipped):    total files: 3      unpacked size: 12.3 kB

The second figure reproduces the published 4.5.1 exactly (3 files, 12263 bytes), which confirms the diagnosis and not only the fix. The first matches 4.5.0, and dist/legacy/index.cjs, index.js and index.d.ts are all present.

The build itself was confirmed on node 24, which no release has used before (4.5.0 built on node 18, and the current workflow builds not at all). tsup.config.js:3 uses import packageJson from './package.json' assert { type: "json" }, which node 24 rejects on its own (SyntaxError: Unexpected identifier 'assert'), but tsup bundles its config through esbuild before evaluating it, so the clause never reaches node's parser. npx tsup on node 24 finishes with Build success and writes dist/modern/index.js and dist/legacy/index.cjs.

Also exercised in a node:24 container with npm install -g npm@latest (npm 12.0.2, the same npm that published 4.5.1) and a clean npm ci from the lockfile: prepack fires and the build runs. npm 12 gates install scripts by default, which does not affect esbuild here because its platform binary ships as its own package. The declaration step was OOM-killed in that container at 8 GB, which is the container limit and not CI. The build asks for a 16 GB heap and ubuntu-latest has 16 GB, which is how 4.5.0 built. The native run completed the full build including declarations.

Follow-ups, not in this PR

  • Cut 4.5.2-alpha.0 first as a rehearsal of the real workflow, then 4.5.2. 4.5.1 cannot be republished.
  • Deprecate 4.5.1 on npm pointing at 4.5.2, so nobody else lands on it. latest currently resolves to the broken version.
  • Anyone blocked meanwhile should pin the exact version 4.5.0. A caret range still resolves to 4.5.1. Nothing is lost by doing so: the only change in 4.5.1 was a dompurify bump, and 4.5.0 already depends on ^3.4.12, which installs the patched release.

develop_v4 and stage_v4 are both strictly behind main, so they pick both fixes up on their next sync and need no separate change.


🤖 Generated with Claude Code

v4.5.1 was published with only package.json, README.md and LICENSE. The
package has no JS in it, so every consumer build fails on import while
main, module, types and exports all point into dist/.

The publish workflow dropped its `npm run build` step when it was
rewritten on 15 Sept. Nothing else builds before publish: there is no
prepack or prepublishOnly script, and with no `files` field npm falls
back to .gitignore, which excludes dist. No build means an empty package.

Hooking the build to prepack fixes it for every publish path rather than
just the one workflow, so a later workflow edit cannot silently drop it
again. A failing build now fails the publish instead of shipping nothing.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 16, 2026 05:18
@kirtesh-cstk
kirtesh-cstk requested a review from a team as a code owner September 16, 2026 05:18
@snyk-io

snyk-io Bot commented Sep 16, 2026

Copy link
Copy Markdown

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 0 0 25 ✅ Passed
🟡 Medium Severity 0 0 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

✅ BUILD PASSED - All security checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The only review comment is a non-blocking documentation nit.

Pull request overview

Adds an npm prepack hook to build dist before packaging or publishing.

Changes:

  • Runs npm run build during npm pack and npm publish.
File summaries
File Description
package.json Adds the prepack lifecycle script.
Review details

Suppressed comments (1)

package.json:34

  • The PR description says there is no files field and that npm therefore falls back to .gitignore, but this package already declares "files": ["dist"] at package.json:22-24. The empty tarball is explained by dist not being built; please correct the rationale so the diagnosis remains accurate.
        "prepack": "npm run build",
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Sep 16, 2026

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 67.43% 2530 / 3752
🔵 Statements 66.28% 2570 / 3877
🔵 Functions 64.71% 453 / 700
🔵 Branches 61.98% 1531 / 2470
File CoverageNo changed files found.
Generated in workflow #910 for commit fd8e6af by the Vitest Coverage Report Action

@hitesh-shetty-cstk hitesh-shetty-cstk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review

Critical journey at risk: publishing the SDK to npm. The failure a consumer sees is npm install succeeding and the import failing, because the package contains no JavaScript.

What this changes: Adds a prepack script so npm run build runs before the tarball is packed. The publish workflow no longer runs a build step, so npm publish packed whatever was on disk, and nothing was.

Business impact: This is the published SDK, so the blast radius is every project that installs it. The public registry currently reports 4.5.1 at 3 files and 12,263 bytes, against 1,907 files and 7.8 MB for 4.5.0, and latest still resolves to 4.5.1. Anyone installing or upgrading fails at import, because main, module, types and exports all resolve into dist/. This change fixes the publish path for the next version. It does nothing for the version already on the registry, which the follow-up list in the description covers.

Security: nothing beyond what the scanners cover. One observation about the surrounding publish job, which this PR does not introduce or change: it runs npm install -g npm@latest at release time in a job holding id-token: write, so an unpinned tool version sits in the provenance path. Worth pinning in its own change.

Flow

flowchart TD
    A["Release published"] --> B["checkout at tag"]
    B --> C["npm ci"]
    C --> D["npm publish --provenance"]
    D --> E["prepack: npm run build"]:::changed
    E --> F["tsup writes dist/modern and dist/legacy"]
    F --> G["pack: files field selects dist"]
    G --> H["tarball, about 1900 files"]
    D -.->|"before this change"| I["no prepack, dist absent"]
    I -.-> J["tarball, 3 files, 12.3 kB"]
    classDef changed fill:#fff3cd,stroke:#d39e00
Loading

Findings: 0 blocker, 1 should fix, 1 nit. Both are inline on package.json:34. The fix itself is the right shape: prepack covers the publish and publish-alpha jobs and a local npm pack, and neither job currently builds.

Reviewer candidates:

  • @csAyushDubey authored 9 of the last 30 commits touching package.json, though all of them are dependency-upgrade merges from December 2025.
  • @hitesh-shetty-cstk authored 8 of the last 30, including the 4.4.5, 4.4.2, 4.4.1 and 4.2.0 release commits.
  • @Aravind-Kumar-cstk is not requested here, but wrote both 15 September commits to .github/workflows/npm-publish.yml, which is the other half of this publish path. Worth a walkthrough before merge, given what is at risk.

Not covered: I did not run the build, the tests, or a publish. I checked the tarball figures against the public npm registry (4.4.5 at 1,895 files, 4.5.0 at 1,907, 4.5.1 at 3 files and 12,263 bytes), and confirmed from repository history that develop_v4 and stage_v4 are both ancestors of main, so the branch note at the end of the description holds. What I could not check is whether npm run build succeeds on node 24, which is the nit above.

Automated review by Claude Code. A human review is still required.


Generated by Claude Code

Comment thread package.json
Comment thread package.json
When npm-alpha-publish.yml was folded into this workflow the publish-alpha
job came out identical to publish, losing the `--tag alpha` the old
workflow had. An alpha release would move the `latest` dist-tag to the
prerelease and hand it to every consumer on a caret range.

This also restores the alpha channel as a rehearsal for a real publish:
cut a prerelease, install it, confirm it resolves, then cut the release,
all without touching `latest`.

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings September 16, 2026 05:32
@kirtesh-cstk
kirtesh-cstk requested a review from a team as a code owner September 16, 2026 05:32
@kirtesh-cstk kirtesh-cstk changed the title fix(release): build on prepack so dist ships in the published package fix(release): restore build before publish and the alpha dist-tag Sep 16, 2026
@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 0 0 25 ✅ Passed
🟡 Medium Severity 0 0 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

✅ BUILD PASSED - All security checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Copilot was unable to run its full agentic suite in this review.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/npm-publish.yml
karancs06
karancs06 previously approved these changes Sep 16, 2026

@karancs06 karancs06 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!

A version tag is mutable, so the action owner or anyone who compromises
that account can change what runs in CI without the ref changing here.
Pinning to the commit sha behind v2.13.0 keeps the same code and removes
that path.

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🔒 Security Scan Results

ℹ️ Note: Only vulnerabilities with available fixes (upgrades or patches) are counted toward thresholds.

Check Type Count (with fixes) Without fixes Threshold Result
🔴 Critical Severity 0 0 10 ✅ Passed
🟠 High Severity 0 0 25 ✅ Passed
🟡 Medium Severity 0 0 500 ✅ Passed
🔵 Low Severity 0 0 1000 ✅ Passed

⏱️ SLA Breach Summary

✅ No SLA breaches detected. All vulnerabilities are within acceptable time thresholds.

Severity Breaches (with fixes) Breaches (no fixes) SLA Threshold (with/no fixes) Status
🔴 Critical 0 0 15 / 30 days ✅ Passed
🟠 High 0 0 30 / 120 days ✅ Passed
🟡 Medium 0 0 90 / 365 days ✅ Passed
🔵 Low 0 0 180 / 365 days ✅ Passed

✅ BUILD PASSED - All security checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The reviewed changes address the release regressions with no blocking issues.

Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@kirtesh-cstk
kirtesh-cstk merged commit 859918e into main Sep 16, 2026
11 checks passed
@kirtesh-cstk
kirtesh-cstk deleted the hotfix/restore-build-before-publish branch September 16, 2026 06:25
@hitesh-shetty-cstk hitesh-shetty-cstk mentioned this pull request Sep 16, 2026
6 tasks
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.

5 participants