Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
f3e720c
feat: add Linux musl target support for NAPI bindings
fengmk2 Mar 17, 2026
f127d39
refactor: consolidate Linux build steps and add fail-fast default case
fengmk2 Mar 18, 2026
6917731
feat(ci): add musl CLI E2E test
fengmk2 Mar 18, 2026
dbaf6f8
fix(ci): keep rolldown download keyed to runner OS, not Rust target
fengmk2 Mar 18, 2026
77a0aa6
fix(ci): use alpine:3.21 instead of node:22-alpine3.21 for musl test
fengmk2 Mar 22, 2026
9de8809
revert: use node:22-alpine3.21 for musl test (needs Node.js for NAPI)
fengmk2 Mar 22, 2026
0c22b39
fix(ci): add cmake and fix HOME mismatch in Alpine musl test container
fengmk2 Mar 22, 2026
093d7fe
fix(ci): use cargo-zigbuild for musl NAPI builds instead of napi-cross
fengmk2 Mar 22, 2026
8736e96
fix(ci): add rustup target for musl in build-upstream action
fengmk2 Mar 22, 2026
cfed7b3
fix(ci): remove musl from cli-e2e-test matrix
fengmk2 Mar 22, 2026
1ad3f6b
fix(ci): set NAPI_RS_NATIVE_LIBRARY_PATH for musl CLI E2E test
fengmk2 Mar 22, 2026
b44b3d9
fix(ci): run musl CLI E2E test in Alpine Docker container
fengmk2 Mar 22, 2026
1357bf2
fix(ci): copy vp binary directly into Alpine container for musl E2E
fengmk2 Mar 22, 2026
39ae5de
fix(ci): run pnpm bootstrap-cli:ci inside Alpine container for musl E2E
fengmk2 Mar 22, 2026
687f259
fix(ci): run pnpm install inside Alpine to resolve musl optional deps
fengmk2 Mar 22, 2026
6a3ea09
fix(ci): use pnpm install --force to re-resolve musl optional deps
fengmk2 Mar 23, 2026
898537b
feat(ci): add snap tests to musl CLI E2E test in Alpine container
fengmk2 Mar 23, 2026
e2ee7dc
fix(ci): align musl snap test logic with cli-e2e-test
fengmk2 Mar 23, 2026
f6dee18
fix(ci): use system Node.js in Alpine musl E2E with vp env off
fengmk2 Mar 23, 2026
192c120
feat: download musl Node.js from unofficial-builds on musl targets
fengmk2 Mar 23, 2026
0f96012
fix(ci): download musl rolldown binding inside Alpine container
fengmk2 Mar 23, 2026
a87bda6
fix(ci): copy musl rolldown binding to packages/core/dist/rolldown
fengmk2 Mar 23, 2026
b43fb40
fix(ci): only copy musl rolldown binding to packages/core/dist/rolldown
fengmk2 Mar 23, 2026
7619560
fix(ci): copy musl rolldown binding to correct shared/ subdirectory
fengmk2 Mar 23, 2026
9eeb6ea
fix(ci): add safe.directory for git in Alpine Docker container
fengmk2 Mar 23, 2026
28ff57e
fix(ci): remove unnecessary Playwright install from musl E2E
fengmk2 Mar 23, 2026
3140345
fix: use cfg-gated DEFAULT_NODE_DIST_URL to avoid unused constant on …
fengmk2 Mar 23, 2026
2497abe
fix: update Node.js provider tests for musl platform string and URL
fengmk2 Mar 23, 2026
e6fa000
debug(ci): run command-pack-exe manually in musl E2E to capture output
fengmk2 Mar 23, 2026
989d4b3
debug(ci): also run migration-auto-create-vite-config manually in mus…
fengmk2 Mar 23, 2026
94a36dc
feat: support libc filter in snap test ignoredPlatforms
fengmk2 Mar 23, 2026
41b3236
refactor: use process.report API for musl detection instead of readin…
fengmk2 Mar 23, 2026
a6ef708
fix(ci): copy musl rolldown binding to rolldown/packages/rolldown/dis…
fengmk2 Mar 23, 2026
c14f8da
fix: skip command-upgrade-check snap test on musl
fengmk2 Mar 23, 2026
6c94d01
fix(ci): add TARGET_CFLAGS for aarch64 musl builds
fengmk2 Mar 23, 2026
51a4b30
debug(ci): verify rolldown musl binding files exist after copy
fengmk2 Mar 23, 2026
1e0d0d5
debug(ci): isolate migration-auto-create-vite-config snap test in mus…
fengmk2 Mar 23, 2026
5870384
debug(ci): run migration-auto-create-vite-config commands directly in…
fengmk2 Mar 23, 2026
7084d5f
fix(ci): skip snap tests that install vite-plus from npm on musl
fengmk2 Mar 23, 2026
7986818
fix(ci): pass CI=true to Alpine Docker container for musl E2E
fengmk2 Mar 23, 2026
4160a8e
fix: use test -f instead of cat for file existence checks in snap tests
fengmk2 Mar 23, 2026
e9b86fc
fix(ci): rename Test (musl) to Test (Linux x64 musl)
fengmk2 Mar 23, 2026
ddb38dc
fix: use test -f in command-init-inline-config snap test
fengmk2 Mar 23, 2026
871dce8
fix: replace cat with test -f and skip command-dlx-npm10 on musl
fengmk2 Mar 23, 2026
69b6e0d
fix(ci): use git diff --quiet to avoid duplicate diff output in musl E2E
fengmk2 Mar 23, 2026
8b52410
fix: skip create-missing-typecheck snap test on musl
fengmk2 Mar 23, 2026
6cdc468
fix(ci): remove dangling run job reference from done gate
fengmk2 Mar 24, 2026
686e778
fix(ci): remove redundant cargo check from test-musl job to save CI time
fengmk2 Mar 24, 2026
600704d
ci: allow retry the failed native package publishing
Brooooooklyn Mar 24, 2026
31a82b5
simplify publish native addons script
Brooooooklyn Mar 24, 2026
af835cc
fix: print install log directly in CI instead of pointing to file
fengmk2 Mar 24, 2026
56feff9
debug(ci): add bash -x and CI=true to musl standalone install tests
fengmk2 Mar 24, 2026
7e91b2e
fix: avoid error() function exit before printing install log in CI
fengmk2 Mar 24, 2026
1068d3c
fix(ci): disable musl standalone install tests until musl support is …
fengmk2 Mar 24, 2026
a085027
fix(ci): re-enable musl install tests with libstdc++ dependency
fengmk2 Mar 24, 2026
69234de
fix(ci): use direct PATH export in musl install tests instead of source
fengmk2 Mar 24, 2026
fa90e0e
feat(ci): add create and build test to musl x64 standalone install
fengmk2 Mar 24, 2026
b8cc217
feat(ci): add create and build test to musl arm64 standalone install
fengmk2 Mar 24, 2026
56f0dee
docs: add libstdc++ requirement for Alpine/musl platforms
fengmk2 Mar 24, 2026
75ecabb
fix(docs): remove --no-cache flag from apk add example
fengmk2 Mar 24, 2026
79c4653
fix(ci): comment out create test in ARM64 musl QEMU job
fengmk2 Mar 24, 2026
76dbdd5
fix(ci): skip flaky test_verify_file_hash_sha1 in musl test job
fengmk2 Mar 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 32 additions & 12 deletions .github/actions/build-upstream/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,44 @@ runs:
pnpm --filter "@voidzero-dev/*" build
pnpm --filter vite-plus build-ts
# Install zig + cargo-zigbuild for musl cross-compilation (napi-cross only supports gnu)
- name: Add musl Rust target
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl')
shell: bash
run: rustup target add ${{ inputs.target }}

- name: Setup zig (musl)
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl')
uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
with:
version: 0.15.2

- name: Install cargo-zigbuild (musl)
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl')
uses: taiki-e/install-action@f916cfac5d8efd040e250d0cd6b967616504b3a4 # v2.68.32
with:
tool: cargo-zigbuild

# NAPI builds - only run on cache miss (slow, especially on Windows)
# Must run before vite-plus TypeScript builds which depend on the bindings
- name: Build NAPI bindings (x86_64-linux)
- name: Build NAPI bindings (Linux gnu)
shell: bash
if: steps.cache-restore.outputs.cache-hit != 'true' && inputs.target == 'x86_64-unknown-linux-gnu'
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'linux') && !contains(inputs.target, 'musl')
run: |
pnpm --filter=vite-plus build-native --target ${{ inputs.target }} --use-napi-cross
env:
TARGET_CC: clang
TARGET_CFLAGS: ${{ contains(inputs.target, 'aarch64') && '-D_BSD_SOURCE' || '' }}
DEBUG: napi:*

- name: Build NAPI bindings (aarch64-linux)
- name: Build NAPI bindings (Linux musl)
shell: bash
if: steps.cache-restore.outputs.cache-hit != 'true' && inputs.target == 'aarch64-unknown-linux-gnu'
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl')
run: |
pnpm --filter=vite-plus build-native --target ${{ inputs.target }} --use-napi-cross
pnpm --filter=vite-plus build-native --target ${{ inputs.target }} -x
env:
TARGET_CC: clang
TARGET_CFLAGS: '-D_BSD_SOURCE'
TARGET_CFLAGS: ${{ contains(inputs.target, 'aarch64') && '-D_BSD_SOURCE' || '' }}
DEBUG: napi:*

- name: Build NAPI bindings (non-Linux targets)
Expand All @@ -88,23 +107,24 @@ runs:
env:
DEBUG: napi:*

- name: Build Rust CLI binary (x86_64-linux)
if: steps.cache-restore.outputs.cache-hit != 'true' && inputs.target == 'x86_64-unknown-linux-gnu'
- name: Build Rust CLI binary (Linux gnu)
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'linux') && !contains(inputs.target, 'musl')
shell: bash
run: |
pnpm exec napi build --use-napi-cross --target ${{ inputs.target }} --release -p vite_global_cli
env:
TARGET_CC: clang
TARGET_CFLAGS: ${{ contains(inputs.target, 'aarch64') && '-D_BSD_SOURCE' || '' }}
DEBUG: napi:*

- name: Build Rust CLI binary (aarch64-linux)
if: steps.cache-restore.outputs.cache-hit != 'true' && inputs.target == 'aarch64-unknown-linux-gnu'
- name: Build Rust CLI binary (Linux musl)
if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl')
shell: bash
run: |
pnpm exec napi build --use-napi-cross --target ${{ inputs.target }} --release -p vite_global_cli
pnpm exec napi build -x --target ${{ inputs.target }} --release -p vite_global_cli
env:
TARGET_CC: clang
TARGET_CFLAGS: '-D_BSD_SOURCE'
TARGET_CFLAGS: ${{ contains(inputs.target, 'aarch64') && '-D_BSD_SOURCE' || '' }}
DEBUG: napi:*

- name: Build Rust CLI binary (non-Linux targets)
Expand Down
3 changes: 3 additions & 0 deletions .github/actions/download-rolldown-binaries/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ runs:
- name: Install previous release
shell: bash
run: |
# Always download the binding that matches the runner OS (not the
# Rust cross-compilation target). The rolldown binding is loaded by
# Node.js on the host to run JS build steps, not cross-compiled.
if ${{ runner.os == 'Windows' }}; then
export TARGET="win32-x64-msvc"
elif ${{ runner.os == 'Linux' }}; then
Expand Down
177 changes: 127 additions & 50 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,6 @@
cache-key: test
target-dir: ${{ runner.os == 'Windows' && format('{0}/target', env.DEV_DRIVE) || '' }}

- run: rustup target add x86_64-unknown-linux-musl
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}

- run: cargo check --all-targets --all-features
env:
RUSTFLAGS: '-D warnings --cfg tokio_unstable' # also update .cargo/config.toml
Expand All @@ -112,6 +109,43 @@
env:
RUST_MIN_STACK: 8388608

test-musl:
needs: detect-changes
if: needs.detect-changes.outputs.code-changed == 'true'
name: Test (Linux x64 musl)
runs-on: namespace-profile-linux-x64-default
container:
image: node:22-alpine3.21
env:
# GitHub Actions sets HOME=/github/home in containers, but the euid home is /root.
# Pin Rust tooling paths to avoid $HOME mismatch issues.
CARGO_HOME: /root/.cargo
RUSTUP_HOME: /root/.rustup
steps:
- name: Install Alpine dependencies
shell: sh {0}

Check notice

Code scanning / zizmor

credential persistence through GitHub Actions artifacts Note

credential persistence through GitHub Actions artifacts
run: apk add --no-cache bash curl git musl-dev gcc g++ python3 cmake make

- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/clone

- name: Install rustup
run: |
# GitHub Actions sets HOME=/github/home in containers, but rustup expects euid home (/root)
export HOME=/root
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
echo "/root/.cargo/bin" >> "$GITHUB_PATH"

- name: Install Rust toolchain
run: rustup show

# Test all crates/* packages. New crates are automatically included.
# Also test vite-plus-cli (lives outside crates/) to catch type sync issues.
# Skip separate cargo check — cargo test already compiles everything.
- run: cargo test $(for d in crates/*/; do echo -n "-p $(basename $d) "; done) -p vite-plus-cli
env:
RUST_MIN_STACK: 8388608

lint:
needs: detect-changes
if: needs.detect-changes.outputs.code-changed == 'true'
Expand Down Expand Up @@ -146,48 +180,6 @@
- name: Deduplicate dependencies
run: pnpm dedupe --check

run:
name: Run task
runs-on: namespace-profile-linux-x64-default
needs:
- download-previous-rolldown-binaries
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/clone

- uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0
with:
save-cache: ${{ github.ref_name == 'main' }}
cache-key: run

- uses: oxc-project/setup-node@fdbf0dfd334c4e6d56ceeb77d91c76339c2a0885 # v1.0.4

- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: rolldown-binaries
path: ./rolldown/packages/rolldown/src
merge-multiple: true

- name: Build with upstream
uses: ./.github/actions/build-upstream
with:
target: x86_64-unknown-linux-gnu

- name: Install Global CLI vp
run: |
pnpm bootstrap-cli:ci
echo "$HOME/.vite-plus/bin" >> $GITHUB_PATH

- name: Print help for built-in commands
run: |
which vp
vp -h
vp run -h
vp lint -h
vp test -h
vp build -h
vp fmt -h

cli-e2e-test:
name: CLI E2E test
needs:
Expand All @@ -197,8 +189,11 @@
matrix:
include:
- os: namespace-profile-linux-x64-default
target: x86_64-unknown-linux-gnu
- os: namespace-profile-mac-default
target: aarch64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
Expand All @@ -217,9 +212,9 @@
- uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0
with:
save-cache: ${{ github.ref_name == 'main' }}
cache-key: cli-e2e-test
cache-key: cli-e2e-test-${{ matrix.target }}
target-dir: ${{ runner.os == 'Windows' && format('{0}/target', env.DEV_DRIVE) || '' }}

Check warning

Code scanning / zizmor

detects commit SHAs that don't match their version comment tags Warning

detects commit SHAs that don't match their version comment tags
- uses: oxc-project/setup-node@fdbf0dfd334c4e6d56ceeb77d91c76339c2a0885 # v1.0.4

- name: Install docs dependencies
Expand All @@ -234,10 +229,10 @@
- name: Build with upstream
uses: ./.github/actions/build-upstream
with:
target: ${{ matrix.os == 'namespace-profile-linux-x64-default' && 'x86_64-unknown-linux-gnu' || matrix.os == 'windows-latest' && 'x86_64-pc-windows-msvc' || 'aarch64-apple-darwin' }}
target: ${{ matrix.target }}

- name: Check TypeScript types
if: ${{ matrix.os == 'namespace-profile-linux-x64-default' }}
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
run: pnpm tsgo

- name: Install Global CLI vp
Expand Down Expand Up @@ -395,7 +390,7 @@
- name: Run CLI snapshot tests
run: |
RUST_BACKTRACE=1 pnpm test
if ! git diff --exit-code; then
if ! git diff --quiet; then
echo "::error::Snapshot diff detected. Run 'pnpm -F vite-plus snap-test' locally and commit the updated snap.txt files."
git diff --stat
git diff
Expand Down Expand Up @@ -577,6 +572,87 @@
pnpm bootstrap-cli:ci
vp --version

cli-e2e-test-musl:
name: CLI E2E test (Linux x64 musl)
needs:
- download-previous-rolldown-binaries
runs-on: namespace-profile-linux-x64-default
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/clone

- uses: oxc-project/setup-rust@d286d43bc1f606abbd98096666ff8be68c8d5f57 # v1.0.0
with:
save-cache: ${{ github.ref_name == 'main' }}
cache-key: cli-e2e-test-musl

Check notice

Code scanning / zizmor

credential persistence through GitHub Actions artifacts Note

credential persistence through GitHub Actions artifacts
- uses: oxc-project/setup-node@fdbf0dfd334c4e6d56ceeb77d91c76339c2a0885 # v1.0.4

- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: rolldown-binaries
path: ./rolldown/packages/rolldown/src
merge-multiple: true

# Cross-compile for musl on the glibc host
- name: Build with upstream (musl)
uses: ./.github/actions/build-upstream
with:
target: x86_64-unknown-linux-musl

# Run bootstrap-cli:ci and E2E tests inside an Alpine container where musl is native.
# Can't run on the glibc host because NAPI .node files are musl-linked.
- name: Run E2E in Alpine container
run: |
docker run --rm \
-e CI=true \
-v "${{ github.workspace }}:/workspace" \
-w /workspace \
node:22-alpine3.21 sh -c "
apk add --no-cache bash curl ca-certificates git

# Install pnpm and re-resolve optional dependencies for musl.
# The host node_modules has glibc bindings; pnpm store holds both
# but we need to re-link the musl variants.
corepack enable
pnpm install --frozen-lockfile --force

# Download musl rolldown binding (host downloaded glibc variant)
ROLLDOWN_VERSION=\$(node -p \"require('./rolldown/packages/rolldown/package.json').version\")
npm pack \"@rolldown/binding-linux-x64-musl@\${ROLLDOWN_VERSION}\"
tar -xzf \"rolldown-binding-linux-x64-musl-\${ROLLDOWN_VERSION}.tgz\"
cp ./package/rolldown-binding.linux-x64-musl.node ./packages/core/dist/rolldown/shared/
cp ./package/rolldown-binding.linux-x64-musl.node ./rolldown/packages/rolldown/dist/shared/
rm -rf package *.tgz

pnpm bootstrap-cli:ci
export PATH=\"/root/.vite-plus/bin:\$PATH\"

vp --version
vp -h
vp env doctor

# Verify shims work
which node
which npm
node --version

# Test global package install
vp install -g typescript
tsc --version
vp uninstall -g typescript

# Run snap tests
git config --global --add safe.directory /workspace
RUST_BACKTRACE=1 pnpm test
if ! git diff --quiet; then
echo '::error::Snapshot diff detected. Run pnpm -F vite-plus snap-test locally and commit the updated snap.txt files.'
git diff --stat
git diff
exit 1
fi
"

install-e2e-test:
name: Local CLI `vp install` E2E test
needs:
Expand Down Expand Up @@ -651,9 +727,10 @@
if: always()
needs:
- test
- test-musl
- lint
- run
- cli-e2e-test
- cli-e2e-test-musl
steps:
- run: exit 1
# Thank you, next https://github.com/vercel/next.js/blob/canary/.github/workflows/build_and_test.yml#L379
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ jobs:
os: macos-latest
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
- target: aarch64-unknown-linux-musl
os: ubuntu-latest
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
- target: x86_64-pc-windows-msvc
os: windows-latest
- target: aarch64-pc-windows-msvc
Expand Down
Loading
Loading