From 53d052c94eb0cfe4764f35866e6a2bcdc2079f9d Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 7 May 2026 16:31:45 +0800 Subject: [PATCH 1/7] ci: publish preview packages to pkg.pr.new Adds a labeled-PR workflow that publishes preview packages to pkg.pr.new, and extracts the release build matrix into a reusable workflow shared with the existing npm release flow. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-to-pkg.pr.new.yml | 172 +++++++++++++++++++ .github/workflows/release.yml | 131 +------------- .github/workflows/reusable-release-build.yml | 150 ++++++++++++++++ packages/cli/publish-native-addons.ts | 56 +++--- 4 files changed, 362 insertions(+), 147 deletions(-) create mode 100644 .github/workflows/publish-to-pkg.pr.new.yml create mode 100644 .github/workflows/reusable-release-build.yml diff --git a/.github/workflows/publish-to-pkg.pr.new.yml b/.github/workflows/publish-to-pkg.pr.new.yml new file mode 100644 index 0000000000..4233f0bce5 --- /dev/null +++ b/.github/workflows/publish-to-pkg.pr.new.yml @@ -0,0 +1,172 @@ +name: Publish to pkg.pr.new + +# https://pkg.pr.new/~/voidzero-dev/vite-plus + +permissions: {} + +on: + workflow_dispatch: + pull_request: + types: [labeled] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-rust: + name: Build bindings and binaries + if: >- + github.repository == 'voidzero-dev/vite-plus' && + (github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) + needs: prepare + permissions: + contents: read + uses: ./.github/workflows/reusable-release-build.yml + with: + version: ${{ needs.prepare.outputs.version }} + cache-key: pkg-pr-new + + prepare: + if: >- + github.repository == 'voidzero-dev/vite-plus' && + (github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) + name: Compute snapshot version + runs-on: ubuntu-latest + permissions: + contents: read + outputs: + version: ${{ steps.version.outputs.version }} + steps: + - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 + + # pkg-pr-new rewrites the published version anyway, but we still need a + # unique snapshot version so `napi pre-publish` writes consistent + # optionalDependencies entries across the platform packages. + - name: Compute version + id: version + run: | + short_sha=$(git rev-parse --short=7 HEAD) + echo "version=0.0.0-pkg-pr-new.${short_sha}" >> "$GITHUB_OUTPUT" + + publish: + if: >- + github.repository == 'voidzero-dev/vite-plus' && + (github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) + name: Pkg Preview + runs-on: ubuntu-latest + needs: + - prepare + - build-rust + permissions: + # pkg-pr-new comments on PRs and posts run statuses with this token. + contents: read + pull-requests: write + env: + VERSION: ${{ needs.prepare.outputs.version }} + steps: + - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 + - uses: ./.github/actions/clone + + - uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0 + + - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 + with: + node-version-file: .node-version + package-manager-cache: false + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Download cli dist + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: packages/cli/dist + pattern: cli + merge-multiple: true + + - name: Download cli docs + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: packages/cli/docs + pattern: cli-docs + merge-multiple: true + + - name: Download cli binding + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: packages/cli/artifacts + pattern: vite-plus-native-* + + - name: Download core dist + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: packages/core/dist + pattern: core + merge-multiple: true + + - uses: ./.github/actions/download-rolldown-binaries + with: + github-token: ${{ github.token }} + target: x86_64-unknown-linux-gnu + upload: 'false' + + - name: Download Rust CLI binaries + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: rust-cli-artifacts + pattern: vite-global-cli-* + + - name: Move Rust CLI binaries to target directories + run: | + for artifact_dir in rust-cli-artifacts/vite-global-cli-*/; do + if [ -d "$artifact_dir" ]; then + dir_name=$(basename "$artifact_dir") + target_name=${dir_name#vite-global-cli-} + mkdir -p "target/${target_name}/release" + cp -r "$artifact_dir"* "target/${target_name}/release/" + fi + done + vp_files=$(find target -name "vp*" -type f 2>/dev/null || echo "") + if [ -z "$vp_files" ]; then + echo "Error: No vp binaries found in target directory" + find rust-cli-artifacts -type f || true + exit 1 + fi + echo "Found binaries:" + echo "$vp_files" + + - name: Set npm packages version + run: | + sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" packages/core/package.json + sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" packages/test/package.json + sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" packages/cli/package.json + + - name: Build test package + run: pnpm --filter=@voidzero-dev/vite-plus-test build + + # Reuses the release script with SKIP_NPM_PUBLISH=true so it stops short + # of `npm publish` and leaves packages/cli/{npm,cli-npm}/* on disk for + # pkg-pr-new to upload. + - name: Prepare native addon and CLI binary packages + run: node ./packages/cli/publish-native-addons.ts + env: + SKIP_NPM_PUBLISH: 'true' + + - name: List prepared packages + run: | + ls -R ./packages/cli/npm + ls -R ./packages/cli/cli-npm + + - name: Publish to pkg.pr.new + run: | + pnpm dlx pkg-pr-new publish --compact --pnpm \ + './packages/cli/npm/*' \ + './packages/cli/cli-npm/*' \ + './packages/cli' \ + './packages/core' \ + './packages/test' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 40b044c331..aa7a53e9aa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,135 +47,14 @@ jobs: run: echo "version=${{ inputs.version || steps.computed.outputs.version }}" >> $GITHUB_OUTPUT build-rust: - runs-on: ${{ matrix.settings.os }} + name: Build bindings and binaries needs: prepare permissions: contents: read - env: - VERSION: ${{ needs.prepare.outputs.version }} - strategy: - fail-fast: false - matrix: - settings: - - target: aarch64-apple-darwin - os: macos-latest - - target: x86_64-apple-darwin - 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 - os: windows-latest - steps: - - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 - - uses: ./.github/actions/clone - - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16 - with: - save-cache: ${{ github.ref_name == 'main' }} - cache-key: release - - - name: Rustup Adds Target - run: rustup target add ${{ matrix.settings.target }} - - - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0 - - - name: Set binding version - shell: bash - run: | - pnpm exec tool replace-file-content packages/cli/binding/Cargo.toml 'version = "0.0.0"' 'version = "${{ env.VERSION }}"' - pnpm exec tool replace-file-content crates/vite_global_cli/Cargo.toml 'version = "0.0.0"' 'version = "${{ env.VERSION }}"' - cat crates/vite_global_cli/Cargo.toml - - - name: Verify version replacement - shell: bash - run: | - if grep -q 'version = "0.0.0"' crates/vite_global_cli/Cargo.toml; then - echo "ERROR: Version replacement failed for crates/vite_global_cli/Cargo.toml" - head -5 crates/vite_global_cli/Cargo.toml - exit 1 - fi - if grep -q 'version = "0.0.0"' packages/cli/binding/Cargo.toml; then - echo "ERROR: Version replacement failed for packages/cli/binding/Cargo.toml" - head -5 packages/cli/binding/Cargo.toml - exit 1 - fi - echo "Version replacement verified successfully" - - - name: Build - uses: ./.github/actions/build-upstream - with: - target: ${{ matrix.settings.target }} - - - name: Upload Vite+ native artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: vite-plus-native-${{ matrix.settings.target }} - path: ./packages/cli/binding/*.node - if-no-files-found: error - - - name: Upload Rust CLI binary artifact - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: vite-global-cli-${{ matrix.settings.target }} - path: | - ./target/${{ matrix.settings.target }}/release/vp - ./target/${{ matrix.settings.target }}/release/vp.exe - ./target/${{ matrix.settings.target }}/release/vp-shim.exe - if-no-files-found: error - - - name: Upload installer binary artifact (Windows only) - if: contains(matrix.settings.target, 'windows') - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - with: - name: vp-setup-${{ matrix.settings.target }} - path: ./target/${{ matrix.settings.target }}/release/vp-setup.exe - if-no-files-found: error - - - name: Remove .node files before upload dist - if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - run: | - rm ./packages/core/dist/**/*.node - - - name: Upload core dist - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - with: - name: core - path: ./packages/core/dist - if-no-files-found: error - - - name: Upload cli dist - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - with: - name: cli - path: ./packages/cli/dist - if-no-files-found: error - - - name: Upload cli docs - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - with: - name: cli-docs - path: ./packages/cli/docs - if-no-files-found: error - - - name: Upload LICENSE files - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 - if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} - with: - name: licenses - path: | - ./packages/core/LICENSE - ./packages/cli/LICENSE - if-no-files-found: error + uses: ./.github/workflows/reusable-release-build.yml + with: + version: ${{ needs.prepare.outputs.version }} + cache-key: release Release: runs-on: ubuntu-latest diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml new file mode 100644 index 0000000000..51b0e539d8 --- /dev/null +++ b/.github/workflows/reusable-release-build.yml @@ -0,0 +1,150 @@ +name: Reusable Release Build + +permissions: {} + +on: + workflow_call: + inputs: + version: + description: 'Version to stamp into Cargo.toml and produced binaries.' + type: string + required: true + cache-key: + description: 'setup-rust cache-key prefix; pass a distinct value per caller (e.g. "release", "pkg-pr-new") to avoid cross-workflow cache pollution.' + type: string + required: false + default: 'release' + +jobs: + build-rust: + name: Build (${{ matrix.settings.target }}) + runs-on: ${{ matrix.settings.os }} + permissions: + contents: read + env: + RELEASE_BUILD: 'true' + DEBUG: 'napi:*' + VERSION: ${{ inputs.version }} + strategy: + fail-fast: false + matrix: + settings: + - target: aarch64-apple-darwin + os: macos-latest + - target: x86_64-apple-darwin + 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 + os: windows-latest + steps: + - uses: taiki-e/checkout-action@7d1e50e93dc4fb3bba58f85018fadf77898aee8b # v1.4.2 + - uses: ./.github/actions/clone + - uses: oxc-project/setup-rust@23f38cfb0c04af97a055f76acee94d5be71c7c82 # v1.0.16 + with: + save-cache: ${{ github.ref_name == 'main' }} + cache-key: ${{ inputs.cache-key }} + + - name: Rustup Adds Target + run: rustup target add ${{ matrix.settings.target }} + + - uses: oxc-project/setup-node@4c26e7cb3605b6bdef5450dacd02c434b10fd8ba # v1.2.0 + + - name: Set binding version + shell: bash + run: | + pnpm exec tool replace-file-content packages/cli/binding/Cargo.toml 'version = "0.0.0"' "version = \"${VERSION}\"" + pnpm exec tool replace-file-content crates/vite_global_cli/Cargo.toml 'version = "0.0.0"' "version = \"${VERSION}\"" + cat crates/vite_global_cli/Cargo.toml + + - name: Verify version replacement + shell: bash + run: | + if grep -q 'version = "0.0.0"' crates/vite_global_cli/Cargo.toml; then + echo "ERROR: Version replacement failed for crates/vite_global_cli/Cargo.toml" + head -5 crates/vite_global_cli/Cargo.toml + exit 1 + fi + if grep -q 'version = "0.0.0"' packages/cli/binding/Cargo.toml; then + echo "ERROR: Version replacement failed for packages/cli/binding/Cargo.toml" + head -5 packages/cli/binding/Cargo.toml + exit 1 + fi + echo "Version replacement verified successfully" + + - name: Build + uses: ./.github/actions/build-upstream + with: + target: ${{ matrix.settings.target }} + + - name: Upload Vite+ native artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: vite-plus-native-${{ matrix.settings.target }} + path: ./packages/cli/binding/*.node + if-no-files-found: error + + - name: Upload Rust CLI binary artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: vite-global-cli-${{ matrix.settings.target }} + path: | + ./target/${{ matrix.settings.target }}/release/vp + ./target/${{ matrix.settings.target }}/release/vp.exe + ./target/${{ matrix.settings.target }}/release/vp-shim.exe + if-no-files-found: error + + - name: Upload installer binary artifact (Windows only) + if: contains(matrix.settings.target, 'windows') + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: vp-setup-${{ matrix.settings.target }} + path: ./target/${{ matrix.settings.target }}/release/vp-setup.exe + if-no-files-found: error + + - name: Remove .node files before upload dist + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + run: | + rm ./packages/core/dist/**/*.node + + - name: Upload core dist + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + with: + name: core + path: ./packages/core/dist + if-no-files-found: error + + - name: Upload cli dist + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + with: + name: cli + path: ./packages/cli/dist + if-no-files-found: error + + - name: Upload cli docs + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + with: + name: cli-docs + path: ./packages/cli/docs + if-no-files-found: error + + - name: Upload LICENSE files + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + with: + name: licenses + path: | + ./packages/core/LICENSE + ./packages/cli/LICENSE + if-no-files-found: error diff --git a/packages/cli/publish-native-addons.ts b/packages/cli/publish-native-addons.ts index e58509c2d7..5cb7e7c8bb 100644 --- a/packages/cli/publish-native-addons.ts +++ b/packages/cli/publish-native-addons.ts @@ -45,27 +45,33 @@ await cli.prePublish({ const npmDir = join(currentDir, 'npm'); const platformDirs = await readdir(npmDir); +// Skip the actual `npm publish` calls (and the cli-npm cleanup below) so a +// caller like the pkg.pr.new workflow can pick up the prepared directories. +const skipNpmPublish = process.env.SKIP_NPM_PUBLISH === 'true'; + // Publish each NAPI platform package (without vp binary) const npmTag = process.env.NPM_TAG || 'latest'; -for (const file of platformDirs) { - try { - const output = execSync(`npm publish --tag ${npmTag} --access public`, { - cwd: join(currentDir, 'npm', file), - env: process.env, - stdio: 'pipe', - }); - process.stdout.write(output); - } catch (e) { - if ( - e instanceof Error && - e.message.includes('You cannot publish over the previously published versions') - ) { - // eslint-disable-next-line no-console - console.info(e.message); - // eslint-disable-next-line no-console - console.warn(`${file} has been published, skipping`); - } else { - throw e; +if (!skipNpmPublish) { + for (const file of platformDirs) { + try { + const output = execSync(`npm publish --tag ${npmTag} --access public`, { + cwd: join(currentDir, 'npm', file), + env: process.env, + stdio: 'pipe', + }); + process.stdout.write(output); + } catch (e) { + if ( + e instanceof Error && + e.message.includes('You cannot publish over the previously published versions') + ) { + // eslint-disable-next-line no-console + console.info(e.message); + // eslint-disable-next-line no-console + console.warn(`${file} has been published, skipping`); + } else { + throw e; + } } } } @@ -130,6 +136,12 @@ for (const napiTarget of pkg.napi.targets) { }; writeFileSync(join(platformCliDir, 'package.json'), JSON.stringify(cliPackage, null, 2) + '\n'); + if (skipNpmPublish) { + // eslint-disable-next-line no-console + console.log(`Prepared CLI package: @voidzero-dev/vite-plus-cli-${platformArchABI}@${cliVersion}`); + continue; + } + // Publish CLI package execSync(`npm publish --tag ${npmTag} --access public`, { cwd: platformCliDir, @@ -141,5 +153,7 @@ for (const napiTarget of pkg.napi.targets) { console.log(`Published CLI package: @voidzero-dev/vite-plus-cli-${platform}@${cliVersion}`); } -// Clean up cli-npm directory -rmSync(cliNpmDir, { recursive: true, force: true }); +// Clean up cli-npm directory (skipped when caller still needs the prepared dirs). +if (!skipNpmPublish) { + rmSync(cliNpmDir, { recursive: true, force: true }); +} From 996dec82960b343ba069b88469874fee879611a1 Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 7 May 2026 16:43:10 +0800 Subject: [PATCH 2/7] ci: move prep steps into publish-native-addons script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pulls the move-binaries / version-stamp / build-test logic out of inline YAML and into the existing publish-native-addons.ts. Replaces the SKIP_NPM_PUBLISH env hack with a --mode {npm,pkg-pr-new} flag. Each publish workflow is now: download artifacts → run script → publish. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-to-pkg.pr.new.yml | 42 ++---------------- .github/workflows/release.yml | 41 ++---------------- packages/cli/publish-native-addons.ts | 48 +++++++++++++++++++-- 3 files changed, 50 insertions(+), 81 deletions(-) diff --git a/.github/workflows/publish-to-pkg.pr.new.yml b/.github/workflows/publish-to-pkg.pr.new.yml index 4233f0bce5..4ea0b6b51d 100644 --- a/.github/workflows/publish-to-pkg.pr.new.yml +++ b/.github/workflows/publish-to-pkg.pr.new.yml @@ -121,46 +121,10 @@ jobs: path: rust-cli-artifacts pattern: vite-global-cli-* - - name: Move Rust CLI binaries to target directories - run: | - for artifact_dir in rust-cli-artifacts/vite-global-cli-*/; do - if [ -d "$artifact_dir" ]; then - dir_name=$(basename "$artifact_dir") - target_name=${dir_name#vite-global-cli-} - mkdir -p "target/${target_name}/release" - cp -r "$artifact_dir"* "target/${target_name}/release/" - fi - done - vp_files=$(find target -name "vp*" -type f 2>/dev/null || echo "") - if [ -z "$vp_files" ]; then - echo "Error: No vp binaries found in target directory" - find rust-cli-artifacts -type f || true - exit 1 - fi - echo "Found binaries:" - echo "$vp_files" - - - name: Set npm packages version - run: | - sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" packages/core/package.json - sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" packages/test/package.json - sed -i "s/\"version\": \"0.0.0\"/\"version\": \"${VERSION}\"/" packages/cli/package.json - - - name: Build test package - run: pnpm --filter=@voidzero-dev/vite-plus-test build - - # Reuses the release script with SKIP_NPM_PUBLISH=true so it stops short - # of `npm publish` and leaves packages/cli/{npm,cli-npm}/* on disk for - # pkg-pr-new to upload. + # Stops short of `npm publish` and leaves packages/cli/{npm,cli-npm}/* + # on disk for pkg-pr-new to upload. - name: Prepare native addon and CLI binary packages - run: node ./packages/cli/publish-native-addons.ts - env: - SKIP_NPM_PUBLISH: 'true' - - - name: List prepared packages - run: | - ls -R ./packages/cli/npm - ls -R ./packages/cli/cli-npm + run: node ./packages/cli/publish-native-addons.ts --mode pkg-pr-new - name: Publish to pkg.pr.new run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aa7a53e9aa..74ac18395c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -133,30 +133,6 @@ jobs: path: installer-artifacts pattern: vp-setup-* - - name: Move Rust CLI binaries to target directories - run: | - # Move each artifact's binary to the correct target directory - for artifact_dir in rust-cli-artifacts/vite-global-cli-*/; do - if [ -d "$artifact_dir" ]; then - # Extract target name from directory (e.g., vite-global-cli-x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu) - dir_name=$(basename "$artifact_dir") - target_name=${dir_name#vite-global-cli-} - # Create target directory and copy binary - mkdir -p "target/${target_name}/release" - cp -r "$artifact_dir"* "target/${target_name}/release/" - fi - done - # Show what we have (fail if no binaries found) - vp_files=$(find target -name "vp*" -type f 2>/dev/null || echo "") - if [ -z "$vp_files" ]; then - echo "Error: No vp binaries found in target directory" - echo "Artifact contents:" - find rust-cli-artifacts -type f || true - exit 1 - fi - echo "Found binaries:" - echo "$vp_files" - - name: Prepare installer binaries for release run: | mkdir -p installer-release @@ -170,22 +146,11 @@ jobs: echo "Installer binaries:" ls -la installer-release/ || echo "No installer binaries found" - - name: Set npm packages version - run: | - sed -i 's/"version": "0.0.0"/"version": "${{ env.VERSION }}"/' packages/core/package.json - sed -i 's/"version": "0.0.0"/"version": "${{ env.VERSION }}"/' packages/test/package.json - sed -i 's/"version": "0.0.0"/"version": "${{ env.VERSION }}"/' packages/cli/package.json - - - name: Build test - run: pnpm --filter=@voidzero-dev/vite-plus-test build - - name: 'Setup npm' - run: | - npm install -g npm@latest + run: npm install -g npm@latest - - name: Publish native addons - run: | - node ./packages/cli/publish-native-addons.ts + - name: Prepare and publish native addons + run: node ./packages/cli/publish-native-addons.ts --mode npm - name: Publish run: | diff --git a/packages/cli/publish-native-addons.ts b/packages/cli/publish-native-addons.ts index 5cb7e7c8bb..765ef89cb8 100644 --- a/packages/cli/publish-native-addons.ts +++ b/packages/cli/publish-native-addons.ts @@ -21,6 +21,50 @@ const cli = new NapiCli(); const currentDir = dirname(fileURLToPath(import.meta.url)); const repoRoot = join(currentDir, '..', '..'); +const args = process.argv.slice(2); +const modeIdx = args.indexOf('--mode'); +const mode = modeIdx >= 0 ? args[modeIdx + 1] : null; +if (mode !== 'npm' && mode !== 'pkg-pr-new') { + console.error(`Usage: publish-native-addons.ts --mode `); + process.exit(1); +} +const skipNpmPublish = mode === 'pkg-pr-new'; + +const VERSION = process.env.VERSION; +if (!VERSION) { + console.error('VERSION env var must be set'); + process.exit(1); +} + +// Move downloaded Rust CLI binaries into target//release/ where the +// rest of this script (and napi-cli) expects them. +const rustCliArtifactsDir = join(repoRoot, 'rust-cli-artifacts'); +if (existsSync(rustCliArtifactsDir)) { + for (const dir of await readdir(rustCliArtifactsDir)) { + if (!dir.startsWith('vite-global-cli-')) continue; + const target = dir.slice('vite-global-cli-'.length); + const releaseDir = join(repoRoot, 'target', target, 'release'); + mkdirSync(releaseDir, { recursive: true }); + for (const file of await readdir(join(rustCliArtifactsDir, dir))) { + copyFileSync(join(rustCliArtifactsDir, dir, file), join(releaseDir, file)); + } + } +} + +// Stamp VERSION into the publishable package.json files. napi prePublish and +// the cli-binary packages below both read packages/cli/package.json#version. +for (const p of ['core', 'test', 'cli']) { + const pkgPath = join(repoRoot, 'packages', p, 'package.json'); + const content = readFileSync(pkgPath, 'utf-8'); + writeFileSync(pkgPath, content.replace('"version": "0.0.0"', `"version": "${VERSION}"`)); +} + +// Build test package against the just-stamped versions. +execSync('pnpm --filter=@voidzero-dev/vite-plus-test build', { + cwd: repoRoot, + stdio: 'inherit', +}); + // Create npm directories for NAPI bindings await cli.createNpmDirs({ cwd: currentDir, @@ -45,10 +89,6 @@ await cli.prePublish({ const npmDir = join(currentDir, 'npm'); const platformDirs = await readdir(npmDir); -// Skip the actual `npm publish` calls (and the cli-npm cleanup below) so a -// caller like the pkg.pr.new workflow can pick up the prepared directories. -const skipNpmPublish = process.env.SKIP_NPM_PUBLISH === 'true'; - // Publish each NAPI platform package (without vp binary) const npmTag = process.env.NPM_TAG || 'latest'; if (!skipNpmPublish) { From a18c27c52df502383e0d16f0e0733b34e4b43da8 Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 7 May 2026 16:55:22 +0800 Subject: [PATCH 3/7] =?UTF-8?q?ci:=20order=20pkg.pr.new=20jobs=20by=20exec?= =?UTF-8?q?ution=20(prepare=20=E2=86=92=20build=20=E2=86=92=20publish)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-to-pkg.pr.new.yml | 28 ++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish-to-pkg.pr.new.yml b/.github/workflows/publish-to-pkg.pr.new.yml index 4ea0b6b51d..b6094e8cad 100644 --- a/.github/workflows/publish-to-pkg.pr.new.yml +++ b/.github/workflows/publish-to-pkg.pr.new.yml @@ -14,20 +14,6 @@ concurrency: cancel-in-progress: true jobs: - build-rust: - name: Build bindings and binaries - if: >- - github.repository == 'voidzero-dev/vite-plus' && - (github.event_name == 'workflow_dispatch' || - (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) - needs: prepare - permissions: - contents: read - uses: ./.github/workflows/reusable-release-build.yml - with: - version: ${{ needs.prepare.outputs.version }} - cache-key: pkg-pr-new - prepare: if: >- github.repository == 'voidzero-dev/vite-plus' && @@ -51,6 +37,20 @@ jobs: short_sha=$(git rev-parse --short=7 HEAD) echo "version=0.0.0-pkg-pr-new.${short_sha}" >> "$GITHUB_OUTPUT" + build-rust: + name: Build bindings and binaries + if: >- + github.repository == 'voidzero-dev/vite-plus' && + (github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) + needs: prepare + permissions: + contents: read + uses: ./.github/workflows/reusable-release-build.yml + with: + version: ${{ needs.prepare.outputs.version }} + cache-key: pkg-pr-new + publish: if: >- github.repository == 'voidzero-dev/vite-plus' && From e86df3d33b304b2af90d1fce44e50a0e517b6c01 Mon Sep 17 00:00:00 2001 From: Boshen Date: Thu, 7 May 2026 19:36:42 +0800 Subject: [PATCH 4/7] ci: harden release.yml against zizmor findings - Add persist-credentials: false to the prepare-job checkout (artipacked). - Replace ${{ inputs.* }} / ${{ env.* }} interpolation in run blocks with shell env-var expansion to avoid template-injection. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 31 ++++++++++++++++----------- packages/cli/publish-native-addons.ts | 4 +++- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 74ac18395c..b533f42c4f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,6 +36,7 @@ jobs: with: fetch-depth: 0 fetch-tags: true + persist-credentials: false - uses: ./.github/actions/set-snapshot-version if: ${{ inputs.version == '' }} id: computed @@ -44,7 +45,10 @@ jobs: - name: Set final version id: version - run: echo "version=${{ inputs.version || steps.computed.outputs.version }}" >> $GITHUB_OUTPUT + env: + INPUT_VERSION: ${{ inputs.version }} + COMPUTED_VERSION: ${{ steps.computed.outputs.version }} + run: echo "version=${INPUT_VERSION:-$COMPUTED_VERSION}" >> "$GITHUB_OUTPUT" build-rust: name: Build bindings and binaries @@ -154,27 +158,30 @@ jobs: - name: Publish run: | - pnpm publish --filter=./packages/core --tag ${{ inputs.npm_tag }} --access public --no-git-checks - pnpm publish --filter=./packages/test --tag ${{ inputs.npm_tag }} --access public --no-git-checks - pnpm publish --filter=./packages/cli --tag ${{ inputs.npm_tag }} --access public --no-git-checks + pnpm publish --filter=./packages/core --tag "${NPM_TAG}" --access public --no-git-checks + pnpm publish --filter=./packages/test --tag "${NPM_TAG}" --access public --no-git-checks + pnpm publish --filter=./packages/cli --tag "${NPM_TAG}" --access public --no-git-checks - name: Create release body + env: + REPOSITORY: ${{ github.repository }} + COMMIT_SHA: ${{ github.sha }} run: | - if [[ "${{ inputs.npm_tag }}" == "latest" ]]; then + if [[ "${NPM_TAG}" == "latest" ]]; then INSTALL_BASH="curl -fsSL https://vite.plus | bash" INSTALL_PS1="irm https://vite.plus/ps1 | iex" else - INSTALL_BASH="curl -fsSL https://vite.plus | VP_VERSION=${{ env.VERSION }} bash" - INSTALL_PS1="\\\$env:VP_VERSION=\\\"${{ env.VERSION }}\\\"; irm https://vite.plus/ps1 | iex" + INSTALL_BASH="curl -fsSL https://vite.plus | VP_VERSION=${VERSION} bash" + INSTALL_PS1="\\\$env:VP_VERSION=\\\"${VERSION}\\\"; irm https://vite.plus/ps1 | iex" fi cat > ./RELEASE_BODY.md < Date: Fri, 8 May 2026 11:53:52 +0800 Subject: [PATCH 5/7] ci: trigger pkg.pr.new workflow on ci/pkg-pr-new branch pushes Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-to-pkg.pr.new.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/publish-to-pkg.pr.new.yml b/.github/workflows/publish-to-pkg.pr.new.yml index b6094e8cad..a770aa54b9 100644 --- a/.github/workflows/publish-to-pkg.pr.new.yml +++ b/.github/workflows/publish-to-pkg.pr.new.yml @@ -6,6 +6,9 @@ permissions: {} on: workflow_dispatch: + push: + branches: + - ci/pkg-pr-new pull_request: types: [labeled] @@ -18,6 +21,7 @@ jobs: if: >- github.repository == 'voidzero-dev/vite-plus' && (github.event_name == 'workflow_dispatch' || + github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) name: Compute snapshot version runs-on: ubuntu-latest @@ -42,6 +46,7 @@ jobs: if: >- github.repository == 'voidzero-dev/vite-plus' && (github.event_name == 'workflow_dispatch' || + github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) needs: prepare permissions: @@ -55,6 +60,7 @@ jobs: if: >- github.repository == 'voidzero-dev/vite-plus' && (github.event_name == 'workflow_dispatch' || + github.event_name == 'push' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'pkg.pr.new'))) name: Pkg Preview runs-on: ubuntu-latest From 66d3f357ad1833bcb85a1e4621af82062c866c3a Mon Sep 17 00:00:00 2001 From: Boshen Date: Fri, 8 May 2026 15:45:29 +0800 Subject: [PATCH 6/7] ci: include prompts in pkg.pr.new publish Adds @voidzero-dev/vite-plus-prompts to the pkg.pr.new upload list so preview installs can resolve workspace:* references to it. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-to-pkg.pr.new.yml | 8 ++++++++ .github/workflows/reusable-release-build.yml | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/.github/workflows/publish-to-pkg.pr.new.yml b/.github/workflows/publish-to-pkg.pr.new.yml index a770aa54b9..46e23a7d80 100644 --- a/.github/workflows/publish-to-pkg.pr.new.yml +++ b/.github/workflows/publish-to-pkg.pr.new.yml @@ -115,6 +115,13 @@ jobs: pattern: core merge-multiple: true + - name: Download prompts dist + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + path: packages/prompts/dist + pattern: prompts + merge-multiple: true + - uses: ./.github/actions/download-rolldown-binaries with: github-token: ${{ github.token }} @@ -139,4 +146,5 @@ jobs: './packages/cli/cli-npm/*' \ './packages/cli' \ './packages/core' \ + './packages/prompts' \ './packages/test' diff --git a/.github/workflows/reusable-release-build.yml b/.github/workflows/reusable-release-build.yml index 51b0e539d8..5ba0575282 100644 --- a/.github/workflows/reusable-release-build.yml +++ b/.github/workflows/reusable-release-build.yml @@ -123,6 +123,14 @@ jobs: path: ./packages/core/dist if-no-files-found: error + - name: Upload prompts dist + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} + with: + name: prompts + path: ./packages/prompts/dist + if-no-files-found: error + - name: Upload cli dist uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: ${{ matrix.settings.target == 'x86_64-unknown-linux-gnu' }} From 277bda21fc656d964adc8c36d309d125cb9293bd Mon Sep 17 00:00:00 2001 From: Boshen Date: Fri, 8 May 2026 16:04:52 +0800 Subject: [PATCH 7/7] fix(cli): satisfy oxlint(curly) in publish-native-addons.ts Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/cli/publish-native-addons.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/cli/publish-native-addons.ts b/packages/cli/publish-native-addons.ts index cba45128ed..4ccb6c9996 100644 --- a/packages/cli/publish-native-addons.ts +++ b/packages/cli/publish-native-addons.ts @@ -41,7 +41,9 @@ if (!VERSION) { const rustCliArtifactsDir = join(repoRoot, 'rust-cli-artifacts'); if (existsSync(rustCliArtifactsDir)) { for (const dir of await readdir(rustCliArtifactsDir)) { - if (!dir.startsWith('vite-global-cli-')) continue; + if (!dir.startsWith('vite-global-cli-')) { + continue; + } const target = dir.slice('vite-global-cli-'.length); const releaseDir = join(repoRoot, 'target', target, 'release'); mkdirSync(releaseDir, { recursive: true });