From 5a72df0c4247f4d6e6fb42cdb16b37a24520dfc3 Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 19 May 2026 21:21:48 +0800 Subject: [PATCH 1/2] ci: address zizmor findings in actions and release workflow Apply zizmor auto-fixes: route untrusted ${{ inputs.* }} through env vars in build-upstream, clone, and set-snapshot-version actions to prevent template injection, and set persist-credentials: false on the upstream checkouts. Drop pnpm caching from the release workflow to remove the cache-poisoning vector before npm publish. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/actions/build-upstream/action.yml | 35 +++++++++++++------ .github/actions/clone/action.yml | 14 +++++--- .../actions/set-snapshot-version/action.yml | 4 ++- .github/workflows/release.yml | 1 - 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.github/actions/build-upstream/action.yml b/.github/actions/build-upstream/action.yml index 0ffb71f8fa..68171a9cb3 100644 --- a/.github/actions/build-upstream/action.yml +++ b/.github/actions/build-upstream/action.yml @@ -25,7 +25,9 @@ runs: id: cache-key shell: bash run: | - echo "key=napi-binding-v3-${{ inputs.target }}-${{ env.RELEASE_BUILD }}-${{ env.DEBUG }}-${{ env.VERSION }}-${{ env.NPM_TAG }}-${{ hashFiles('packages/tools/.upstream-versions.json', 'Cargo.lock', 'crates/**/*.rs', 'crates/*/Cargo.toml', 'packages/cli/binding/**/*.rs', 'packages/cli/binding/Cargo.toml', 'Cargo.toml', '.cargo/config.toml', 'packages/cli/package.json', 'packages/cli/build.ts', 'packages/cli/tsdown.config.ts') }}" >> $GITHUB_OUTPUT + echo "key=napi-binding-v3-${INPUTS_TARGET}-${RELEASE_BUILD}-${DEBUG}-${VERSION}-${NPM_TAG}-${{ hashFiles('packages/tools/.upstream-versions.json', 'Cargo.lock', 'crates/**/*.rs', 'crates/*/Cargo.toml', 'packages/cli/binding/**/*.rs', 'packages/cli/binding/Cargo.toml', 'Cargo.toml', '.cargo/config.toml', 'packages/cli/package.json', 'packages/cli/build.ts', 'packages/cli/tsdown.config.ts') }}" >> $GITHUB_OUTPUT + env: + INPUTS_TARGET: ${{ inputs.target }} # Resolve the Rust target directory (CARGO_TARGET_DIR from setup-rust, or default "target") - name: Resolve Rust target directory @@ -70,7 +72,9 @@ runs: - 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 }} + run: rustup target add ${INPUTS_TARGET} + env: + INPUTS_TARGET: ${{ inputs.target }} - name: Setup zig (musl) if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl') @@ -90,64 +94,75 @@ runs: shell: bash 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 + 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:* + INPUTS_TARGET: ${{ inputs.target }} - name: Build NAPI bindings (Linux musl) shell: bash if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'musl') run: | - pnpm --filter=vite-plus build-native --target ${{ inputs.target }} -x + pnpm --filter=vite-plus build-native --target ${INPUTS_TARGET} -x env: TARGET_CC: clang TARGET_CFLAGS: ${{ contains(inputs.target, 'aarch64') && '-D_BSD_SOURCE' || '' }} DEBUG: napi:* + INPUTS_TARGET: ${{ inputs.target }} - name: Build NAPI bindings (non-Linux targets) shell: bash if: steps.cache-restore.outputs.cache-hit != 'true' && !contains(inputs.target, 'linux') run: | - pnpm --filter=vite-plus build-native --target ${{ inputs.target }} + pnpm --filter=vite-plus build-native --target ${INPUTS_TARGET} env: DEBUG: napi:* + INPUTS_TARGET: ${{ inputs.target }} - 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 + 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:* + INPUTS_TARGET: ${{ inputs.target }} - 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 -x --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: ${{ contains(inputs.target, 'aarch64') && '-D_BSD_SOURCE' || '' }} DEBUG: napi:* + INPUTS_TARGET: ${{ inputs.target }} - name: Build Rust CLI binary (non-Linux targets) if: steps.cache-restore.outputs.cache-hit != 'true' && !contains(inputs.target, 'linux') shell: bash - run: cargo build --release --target ${{ inputs.target }} -p vite_global_cli + run: cargo build --release --target ${INPUTS_TARGET} -p vite_global_cli + env: + INPUTS_TARGET: ${{ inputs.target }} - name: Build trampoline shim binary (Windows only) if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'windows') shell: bash - run: cargo build --release --target ${{ inputs.target }} -p vite_trampoline + run: cargo build --release --target ${INPUTS_TARGET} -p vite_trampoline + env: + INPUTS_TARGET: ${{ inputs.target }} - name: Build installer binary (Windows only) if: steps.cache-restore.outputs.cache-hit != 'true' && contains(inputs.target, 'windows') shell: bash - run: cargo build --release --target ${{ inputs.target }} -p vite_installer + run: cargo build --release --target ${INPUTS_TARGET} -p vite_installer + env: + INPUTS_TARGET: ${{ inputs.target }} - name: Save NAPI binding cache if: steps.cache-restore.outputs.cache-hit != 'true' diff --git a/.github/actions/clone/action.yml b/.github/actions/clone/action.yml index c10333217d..d0db52936f 100644 --- a/.github/actions/clone/action.yml +++ b/.github/actions/clone/action.yml @@ -27,21 +27,25 @@ runs: id: ecosystem-ci-project-hash if: ${{ inputs.ecosystem-ci-project != '' }} run: | - node -e "console.log('ECOSYSTEM_CI_PROJECT_HASH=' + require('./ecosystem-ci/repo.json')['${{ inputs.ecosystem-ci-project }}'].hash)" >> $GITHUB_OUTPUT - node -e "console.log('ECOSYSTEM_CI_PROJECT_REPOSITORY=' + require('./ecosystem-ci/repo.json')['${{ inputs.ecosystem-ci-project }}'].repository.replace('https://github.com/', '').replace('.git', ''))" >> $GITHUB_OUTPUT - echo "ECOSYSTEM_CI_PROJECT_PATH=${{ runner.temp }}/vite-plus-ecosystem-ci/${{ inputs.ecosystem-ci-project }}" >> $GITHUB_OUTPUT + node -e "console.log('ECOSYSTEM_CI_PROJECT_HASH=' + require('./ecosystem-ci/repo.json')['${INPUTS_ECOSYSTEM_CI_PROJECT}'].hash)" >> $GITHUB_OUTPUT + node -e "console.log('ECOSYSTEM_CI_PROJECT_REPOSITORY=' + require('./ecosystem-ci/repo.json')['${INPUTS_ECOSYSTEM_CI_PROJECT}'].repository.replace('https://github.com/', '').replace('.git', ''))" >> $GITHUB_OUTPUT + echo "ECOSYSTEM_CI_PROJECT_PATH=${{ runner.temp }}/vite-plus-ecosystem-ci/${INPUTS_ECOSYSTEM_CI_PROJECT}" >> $GITHUB_OUTPUT + env: + INPUTS_ECOSYSTEM_CI_PROJECT: ${{ inputs.ecosystem-ci-project }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: rolldown/rolldown path: rolldown ref: ${{ steps.upstream-versions.outputs.ROLLDOWN_HASH }} + persist-credentials: false - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: repository: vitejs/vite path: vite ref: ${{ steps.upstream-versions.outputs.ROLLDOWN_VITE_HASH }} + persist-credentials: false # Disable autocrlf to preserve LF line endings on Windows # This prevents prettier/eslint from failing with "Delete ␍" errors @@ -53,4 +57,6 @@ runs: - name: Clone ecosystem ci project if: ${{ inputs.ecosystem-ci-project != '' }} shell: bash - run: npx tsx ecosystem-ci/clone.ts ${{ inputs.ecosystem-ci-project }} + run: npx tsx ecosystem-ci/clone.ts ${INPUTS_ECOSYSTEM_CI_PROJECT} + env: + INPUTS_ECOSYSTEM_CI_PROJECT: ${{ inputs.ecosystem-ci-project }} diff --git a/.github/actions/set-snapshot-version/action.yml b/.github/actions/set-snapshot-version/action.yml index f53ddb18ad..86a9d70113 100644 --- a/.github/actions/set-snapshot-version/action.yml +++ b/.github/actions/set-snapshot-version/action.yml @@ -21,6 +21,8 @@ runs: run: | git fetch --tags --quiet npm install --prefix ${{ github.action_path }} semver > /dev/null 2>&1 - VERSION_OUTPUT=$(node ${{ github.action_path }}/compute-version.mjs "${{ inputs.npm_tag }}") + VERSION_OUTPUT=$(node ${{ github.action_path }}/compute-version.mjs "${INPUTS_NPM_TAG}") echo "$VERSION_OUTPUT" echo "$VERSION_OUTPUT" | tail -n 1 >> $GITHUB_OUTPUT + env: + INPUTS_NPM_TAG: ${{ inputs.npm_tag }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d389453c25..8c350b326a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -76,7 +76,6 @@ jobs: node-version-file: .node-version package-manager-cache: false registry-url: 'https://registry.npmjs.org' - cache: 'pnpm' - name: Install dependencies run: pnpm install From 52994b459d54b2e9fa2660890d7d6d8fb3c92298 Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 19 May 2026 21:45:54 +0800 Subject: [PATCH 2/2] ci: replace disabled actions-cool/issues-helper with gh CLI The actions-cool/issues-helper repository was disabled, which broke the zizmor impostor-commit audit (3rd-party SHA can no longer be verified). Rewrite both issue automation workflows using the gh CLI shipped on the runners, removing the third-party dependency entirely. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/issue-close-require.yml | 29 ++++++++---- .github/workflows/issue-labeled.yml | 58 ++++++++++++----------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/.github/workflows/issue-close-require.yml b/.github/workflows/issue-close-require.yml index 0a42f56f43..66e667010b 100644 --- a/.github/workflows/issue-close-require.yml +++ b/.github/workflows/issue-close-require.yml @@ -7,15 +7,24 @@ on: jobs: close-issues: if: github.repository == 'voidzero-dev/vite-plus' - runs-on: ubuntu-slim + runs-on: ubuntu-latest permissions: - issues: write # for actions-cool/issues-helper to update issues - pull-requests: write # for actions-cool/issues-helper to update PRs + issues: write steps: - - name: needs reproduction - uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0 - with: - actions: 'close-issues' - token: ${{ secrets.GITHUB_TOKEN }} - labels: 'needs reproduction' - inactive-day: 3 + - name: Close inactive "needs reproduction" issues + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + shell: bash + run: | + cutoff=$(date -u -d '3 days ago' +%Y-%m-%dT%H:%M:%SZ) + gh issue list \ + --state open \ + --label "needs reproduction" \ + --limit 200 \ + --json number,updatedAt \ + --jq ".[] | select(.updatedAt < \"$cutoff\") | .number" | + while read -r number; do + [ -z "$number" ] && continue + gh issue close "$number" + done diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml index e9d4029cd2..fd8745c279 100644 --- a/.github/workflows/issue-labeled.yml +++ b/.github/workflows/issue-labeled.yml @@ -7,38 +7,42 @@ on: jobs: reply-labeled: if: github.repository == 'voidzero-dev/vite-plus' - runs-on: ubuntu-slim + runs-on: ubuntu-latest permissions: - issues: write # for actions-cool/issues-helper to update issues - pull-requests: write # for actions-cool/issues-helper to update PRs + issues: write steps: - - name: contribution welcome + - name: Remove triage labels (contribution welcome / help wanted) if: github.event.label.name == 'contribution welcome' || github.event.label.name == 'help wanted' - uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0 - with: - actions: 'remove-labels' - token: ${{ secrets.GITHUB_TOKEN }} - issue-number: ${{ github.event.issue.number }} - labels: 'pending triage, needs reproduction' - - - name: needs reproduction + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + shell: bash + run: | + gh issue edit "$ISSUE_NUMBER" \ + --remove-label "pending triage" \ + --remove-label "needs reproduction" || true + + - name: Comment and remove triage on "needs reproduction" if: github.event.label.name == 'needs reproduction' - uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3.8.0 - with: - actions: 'create-comment, remove-labels' - token: ${{ secrets.GITHUB_TOKEN }} - issue-number: ${{ github.event.issue.number }} - labels: 'pending triage' - body: | - Hello @${{ github.event.issue.user.login }} 👋 + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_USER: ${{ github.event.issue.user.login }} + shell: bash + run: | + gh issue comment "$ISSUE_NUMBER" --body "Hello @${ISSUE_USER} 👋 + + Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository. This helps us understand and resolve your issue much faster. - Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository. This helps us understand and resolve your issue much faster. + **A good reproduction should be:** + - **Minimal** – include only the code necessary to demonstrate the issue + - **Complete** – contain everything needed to run and observe the problem + - **Reproducible** – consistently show the issue with clear steps - **A good reproduction should be:** - - **Minimal** – include only the code necessary to demonstrate the issue - - **Complete** – contain everything needed to run and observe the problem - - **Reproducible** – consistently show the issue with clear steps + If no reproduction is provided, issues labeled \`needs reproduction\` will be closed after 3 days of inactivity. - If no reproduction is provided, issues labeled `needs reproduction` will be closed after 3 days of inactivity. + For more context on why this is required, please read: https://antfu.me/posts/why-reproductions-are-required" - For more context on why this is required, please read: https://antfu.me/posts/why-reproductions-are-required + gh issue edit "$ISSUE_NUMBER" --remove-label "pending triage" || true