Skip to content

fix(build): copy assets from tsdown so the build works on Windows - #1253

Open
anhtahaylove wants to merge 2 commits into
rohitg00:mainfrom
anhtahaylove:fix/windows-build-asset-copy
Open

fix(build): copy assets from tsdown so the build works on Windows#1253
anhtahaylove wants to merge 2 commits into
rohitg00:mainfrom
anhtahaylove:fix/windows-build-asset-copy

Conversation

@anhtahaylove

@anhtahaylove anhtahaylove commented Aug 26, 2026

Copy link
Copy Markdown

npm run build exits 1 on Windows, and dist/viewer/ never gets created — so the viewer assets are silently missing from the built package.

The script chains POSIX file utilities after tsdown:

"build": "tsdown && (cp iii-config.yaml dist/ 2>/dev/null || true) && ... && mkdir -p dist/viewer && cp src/viewer/index.html dist/viewer/ && cp src/viewer/favicon.svg dist/viewer/"

npm runs scripts through cmd.exe on Windows, which has neither cp nor mkdir -p:

$ npm run build
...
✔ Build complete in 4245ms
The system cannot find the path specified.
The system cannot find the path specified.
The system cannot find the path specified.
The system cannot find the path specified.
The syntax of the command is incorrect.

$ echo $?
1
$ ls dist/viewer
ls: cannot access 'dist/viewer/': No such file or directory

The four leading copies survive because of their || true guards, so iii-config.yaml and friends do land. mkdir -p dist/viewer and the two copies after it have no guard, so the chain dies there and takes the exit code with it.

Easy to miss two ways: ✔ Build complete is printed before the failure, and piping the build through tail/grep reports the pipeline's last exit status rather than npm's.

What this does

Moves the copies into tsdown's own copy option, which runs in Node and needs no shell. No new dependency — tsdown 0.21.10 already supports it.

The copy rides on the last hook entry rather than every mapped block. Setting it on all of them runs the copies once per entry, and the parallel copies race:

ERROR  Error: EBUSY: resource busy or locked, unlink 'dist\iii-config.yaml'
    at async mayCopyFile (node:internal/fs/cp/cp:247:5)
    at async copy (tsdown/dist/watch-D6EGzM6P.mjs:19:2)

clean: true only runs on the first config block, so assets copied from the last one are not wiped.

Verification

Windows 11, Node v24.19.0, starting from an empty dist/:

$ rm -rf dist && npm run build >/dev/null 2>&1; echo $?
0

$ for each of the six assets: sha256 dist/... == sha256 source
  MATCH  dist/iii-config.yaml
  MATCH  dist/iii-config.docker.yaml
  MATCH  dist/docker-compose.yml
  MATCH  dist/.env.example
  MATCH  dist/viewer/index.html
  MATCH  dist/viewer/favicon.svg

Byte-identical to source, not merely present. Three consecutive builds without cleaning also stay at exit 0, and the outputs are unchanged: 12 bundles in dist/, 14 in dist/hooks/, 15 in plugin/scripts/. package.json files already ships dist/, so packaging is unaffected.

Test suite is 30 failed | 1665 passed, identical to main at e04ba88 on this machine — the pre-existing failures are unrelated and unaffected.

This should be a no-op on Linux and macOS, where the old chain already worked. Worth a CI check on a Windows runner if you want it guarded, though I did not want to add a workflow uninvited.

Found while working on #1249; unrelated to it, so it is a separate PR.

Summary by CodeRabbit

  • Bug Fixes

    • Improved build reliability by preventing duplicate asset-copy operations.
    • Ensured runtime, Docker, environment, and viewer assets are included in the build output.
    • Verified viewer files are placed in the expected location and packaged assets are available.
  • Chores

    • Simplified the build process and centralized asset handling.
    • Added automated validation for build asset packaging and output structure.

The build script chained POSIX file utilities after tsdown. npm runs
scripts through cmd.exe on Windows, which has no cp or mkdir -p, so the
tail failed with "The system cannot find the path specified." and
"The syntax of the command is incorrect." The four leading copies were
guarded with || true, but mkdir -p dist/viewer and the two copies after
it were not, so npm run build exited 1 and dist/viewer/ was never
created — the viewer assets silently went missing from the package.

Move the copies into tsdown's own copy option, which runs in Node and
needs no shell. The copy rides on the last hook entry rather than every
mapped block: setting it on all of them runs the copies once per entry,
and the parallel copies race each other (EBUSY unlinking dist/
iii-config.yaml on Windows).

Verified on Windows 11 with an empty dist/: exit 0, all six assets
present, and each byte-identical to its source. Three consecutive builds
stay at exit 0, and dist/ still carries 12 bundles, 14 hooks, and 15
plugin scripts. Test suite is unchanged at 30 failed | 1665 passed,
matching main on the same machine.

Signed-off-by: anhtahaylove <everest.kill1@gmail.com>
@vercel

vercel Bot commented Aug 26, 2026

Copy link
Copy Markdown

@anhtahaylove is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2ecf9ac9-97ab-4d64-ba1c-f73e8e8ee685

📥 Commits

Reviewing files that changed from the base of the PR and between d8631c6 and 2f7973d.

📒 Files selected for processing (1)
  • test/build-asset-copy.test.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The build script now runs tsdown only. The final hook entry copies required runtime, Docker, environment, and viewer assets through tsdown. Tests validate the configuration.

Changes

Build asset handling

Layer / File(s) Summary
Configure final hook asset copying
package.json, tsdown.config.ts, test/build-asset-copy.test.ts
The build script delegates execution to tsdown. The final hook entry copies configuration, Docker, environment, and viewer assets. Earlier hook entries do not copy these assets. Tests validate asset coverage, source paths, viewer output, build-script portability, and cleanup behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 2f797

The build now copies required assets through the existing build tool instead of shell-specific commands, addressing Windows build failures while preserving the existing package outputs. No actionable merge-blocking risk remains beyond normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely identifies the main change: moving asset copying to tsdown to make Windows builds work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@anhtahaylove

Copy link
Copy Markdown
Author

@rohitg00 — small one, ready when you are.

npm run build fails on Windows: the build script chains POSIX cp/mkdir -p, so it exits 1 with "The system cannot find the path specified." and dist/ ends up missing its six runtime assets.

This moves the asset copying into tsdown's own copy option — it runs through Node, so no shell dependency and no new devDependency. package.json drops to "build": "tsdown".

Worth flagging one non-obvious detail: copy has to sit on a single config block. The config maps over hookEntries, so putting it in the mapped block duplicates it 14x and the parallel copies race into EBUSY: resource busy or locked.

Verified: builds clean three times in a row (exit 0, stable 12 bundles / 14 hooks / 15 plugin scripts), all six assets sha256-identical to source, files in package.json already covers dist/ so packaging is unchanged, and the test suite matches the baseline on main. CodeRabbit had no actionable comments.

The build failure this fixes is silent in CI on Linux: the POSIX tail
worked there, so nothing caught that cmd.exe could not run it. These
assert the shape the fix depends on — copies on exactly one block, no
cp/mkdir left in the script, and every packaged asset actually copied.

Restoring the old script and dropping the copy block fails four of six.

Signed-off-by: anhtahaylove <everest.kill1@gmail.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