vitejs/vite
12 workflows · maturity 67% · 7 patterns · GitHub ↗
Practices
✓ Matrix✓ Permissions○ Security scan○ AI review✓ Cache✓ Concurrency○ Reusable workflows
Detected patterns
Security dimensions
Workflows (12)
ci matrix perms .github/workflows/ci.yml
View raw YAML
name: CI
env:
# 7 GiB by default on GitHub, setting to 6 GiB
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
NODE_OPTIONS: --max-old-space-size=6144
# install playwright binary manually (because pnpm only runs install script once)
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
# Vitest auto retry on flaky segfault
VITEST_SEGFAULT_RETRY: 3
# Remove default permissions of GITHUB_TOKEN for security
# https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs
permissions: {}
on:
push:
branches:
- main
- release/*
- feat/*
- fix/*
- perf/*
- "v[0-9]+" # v1, v2, ...
- "v[0-9]+.[0-9]+" # v4.0, v4.1, ...
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: true
jobs:
changed:
name: Get changed files
runs-on: ubuntu-slim
outputs:
should_skip: ${{ steps.changed-files.outputs.only_changed == 'true' }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
# Assume PRs are less than 50 commits
fetch-depth: 50
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v47.0.5
with:
files: |
docs/**
.github/**
!.github/workflows/ci.yml
packages/create-vite/template**
**.md
test:
needs: changed
if: needs.changed.outputs.should_skip != 'true'
timeout-minutes: 20
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node_version: [20, 22, 24]
include:
# Active LTS + other OS
- os: macos-latest
node_version: 24
- os: windows-latest
node_version: 24
fail-fast: false
name: "Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}"
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Set node version to ${{ matrix.node_version }}
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node_version }}
cache: "pnpm"
- name: Install deps
run: pnpm install
# Install playwright's binary under custom directory to cache
- name: (non-windows) Set Playwright path and Get playwright version
if: runner.os != 'Windows'
run: |
echo "PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin" >> $GITHUB_ENV
PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies["playwright-chromium"].version')"
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
- name: (windows) Set Playwright path and Get playwright version
if: runner.os == 'Windows'
run: |
echo "PLAYWRIGHT_BROWSERS_PATH=$HOME\.cache\playwright-bin" >> $env:GITHUB_ENV
$env:PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies["playwright-chromium"].version')"
echo "PLAYWRIGHT_VERSION=$env:PLAYWRIGHT_VERSION" >> $env:GITHUB_ENV
- name: Cache Playwright's binary
uses: actions/cache@v5
with:
key: ${{ runner.os }}-playwright-bin-v1-${{ env.PLAYWRIGHT_VERSION }}
path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}
restore-keys: |
${{ runner.os }}-playwright-bin-v1-
- name: Install Playwright
# does not need to explicitly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved
run: pnpm playwright install chromium
- name: Build
run: pnpm run build
- name: Test unit
run: pnpm run test-unit
- name: Test serve
run: pnpm run test-serve
- name: Test build
run: pnpm run test-build
test-passed:
if: (!cancelled() && !failure())
needs: test
runs-on: ubuntu-slim
name: Build & Test Passed or Skipped
steps:
- run: echo "Build & Test Passed or Skipped"
test-failed:
if: (!cancelled() && failure())
needs: test
runs-on: ubuntu-slim
name: Build & Test Failed
steps:
- run: echo "Build & Test Failed"
lint:
timeout-minutes: 10
runs-on: ubuntu-latest
name: "Lint: node-24, ubuntu-latest"
steps:
- uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Set node version to 24
uses: actions/setup-node@v6
with:
node-version: 24
cache: "pnpm"
- name: Install deps
run: pnpm install
- name: Build
run: pnpm run build
- name: Lint
run: pnpm run lint
- name: Check formatting
run: pnpm prettier --write --log-level=warn . && git diff --exit-code
- name: Typecheck
run: pnpm run typecheck
- name: Test docs
run: pnpm run test-docs
# From https://github.com/rhysd/actionlint/blob/main/docs/usage.md#use-actionlint-on-github-actions
- name: Check workflow files
run: |
bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
./actionlint -color -shellcheck=""
copilot-setup-steps .github/workflows/copilot-setup-steps.yml
View raw YAML
on:
workflow_dispatch:
push:
paths:
- .github/workflows/copilot-setup-steps.yml
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml
jobs:
copilot-setup-steps:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Set node version to 24
uses: actions/setup-node@v6
with:
node-version: 24
cache: "pnpm"
- name: Install deps
run: pnpm install
# Install playwright's binary under custom directory to cache
- name: (non-windows) Set Playwright path and Get playwright version
if: runner.os != 'Windows'
run: |
echo "PLAYWRIGHT_BROWSERS_PATH=$HOME/.cache/playwright-bin" >> $GITHUB_ENV
PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies["playwright-chromium"].version')"
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
- name: (windows) Set Playwright path and Get playwright version
if: runner.os == 'Windows'
run: |
echo "PLAYWRIGHT_BROWSERS_PATH=$HOME\.cache\playwright-bin" >> $env:GITHUB_ENV
$env:PLAYWRIGHT_VERSION="$(pnpm ls --depth 0 --json -w playwright-chromium | jq --raw-output '.[0].devDependencies["playwright-chromium"].version')"
echo "PLAYWRIGHT_VERSION=$env:PLAYWRIGHT_VERSION" >> $env:GITHUB_ENV
- name: Install Playwright
# does not need to explicitly set chromium after https://github.com/microsoft/playwright/issues/14862 is solved
run: pnpm playwright install chromium
ecosystem-ci-trigger .github/workflows/ecosystem-ci-trigger.yml
View raw YAML
name: ecosystem-ci trigger
on:
issue_comment:
types: [created]
jobs:
trigger:
runs-on: ubuntu-slim
if: github.repository == 'vitejs/vite' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')
permissions:
issues: write # to add / delete reactions, post comments
pull-requests: write # to read PR data, and to add labels
actions: read # to check workflow status
steps:
- name: Check User Permissions
uses: actions/github-script@v8
id: check-permissions
with:
script: |
const user = context.payload.sender.login
console.log(`Validate user: ${user}`)
const additionalAllowedUsers = ['lukastaegert']
let hasTriagePermission = false
try {
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: user,
});
hasTriagePermission = data.user.permissions.triage
} catch (e) {
console.warn(e)
}
if (hasTriagePermission || additionalAllowedUsers.includes(user)) {
console.log('User is allowed. Adding +1 reaction.')
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: '+1',
})
} else {
console.log('User is not allowed. Adding -1 reaction.')
await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: '-1',
})
throw new Error('User does not have the necessary permissions.')
}
- name: Get PR Data
uses: actions/github-script@v8
id: get-pr-data
with:
script: |
console.log(`Get PR info: ${context.repo.owner}/${context.repo.repo}#${context.issue.number}`)
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number
})
const commentCreatedAt = new Date(context.payload.comment.created_at)
const commitPushedAt = new Date(pr.head.repo.pushed_at)
console.log(`Comment created at: ${commentCreatedAt.toISOString()}`)
console.log(`PR last pushed at: ${commitPushedAt.toISOString()}`)
// Check if any commits were pushed after the comment was created
if (commitPushedAt > commentCreatedAt) {
const errorMsg = [
'⚠️ Security warning: PR was updated after the trigger command was posted.',
'',
`Comment posted at: ${commentCreatedAt.toISOString()}`,
`PR last pushed at: ${commitPushedAt.toISOString()}`,
'',
'This could indicate an attempt to inject code after approval.',
'Please review the latest changes and re-run /ecosystem-ci run if they are acceptable.'
].join('\n')
core.setFailed(errorMsg)
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: errorMsg
})
throw new Error('PR was pushed to after comment was created')
}
core.setOutput('head_sha', pr.head.sha)
return {
num: context.issue.number,
branchName: pr.head.ref,
commit: pr.head.sha,
repo: pr.head.repo.full_name
}
- name: Check Package Existence
uses: actions/github-script@v8
id: check-package
with:
script: |
const prData = ${{ steps.get-pr-data.outputs.result }}
const url = `https://pkg.pr.new/vite@${prData.commit}`
const response = await fetch(url)
console.log(`Package check URL: ${url}, Status: ${response.status}`)
// Add 'rocket' reaction to the issue comment
if (response.status === 404) {
const { data: reaction } = await github.rest.reactions.createForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
content: 'rocket',
})
return { exists: false, reaction: reaction.id }
}
return { exists: true, reaction: null }
- name: Generate Token
id: generate-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }}
private-key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }}
repositories: |
vite
vite-ecosystem-ci
- name: Trigger Preview Release (if Package Not Found)
if: fromJSON(steps.check-package.outputs.result).exists == false
uses: actions/github-script@v8
id: trigger-preview-release
env:
PR_DATA: ${{ steps.get-pr-data.outputs.result }}
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const prData = JSON.parse(process.env.PR_DATA)
console.log('Package not found, triggering preview release...')
// Add label "trigger: preview" to the PR
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prData.num,
labels: ['trigger: preview']
})
console.log('Added "trigger: preview" label.')
- name: Wait for Preview Release Completion (if Package Not Found)
if: fromJSON(steps.check-package.outputs.result).exists == false
uses: actions/github-script@v8
id: wait-preview-release
env:
PR_DATA: ${{ steps.get-pr-data.outputs.result }}
REACTION: ${{ fromJSON(steps.check-package.outputs.result).reaction }}
with:
script: |
const prData = JSON.parse(process.env.PR_DATA)
const reaction = +process.env.REACTION
const workflowFileName = 'preview-release.yml'
const workflow = await github.rest.actions.getWorkflow({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: workflowFileName,
})
const workflowId = workflow.data.id
console.log(`Waiting for workflow ID ${workflowId} to complete...`)
const maxRetries = 60 // Wait up to 10 minutes
const delay = 10000 // 10 seconds
let completed = false
for (let i = 0; i < maxRetries; i++) {
const runsData = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: workflowId,
head_sha: prData.commit,
per_page: 100,
page: 1,
})
const runs = runsData.data.workflow_runs
if (runs.length > 0) {
const latestRun = runs[0]
console.log(`Latest run status: ${latestRun.status}, conclusion: ${latestRun.conclusion}`)
if (latestRun.status === 'completed') {
if (latestRun.conclusion === 'success') {
console.log('Preview release workflow completed successfully.')
completed = true
break
} else if (latestRun.conclusion === 'skipped') {
// noop
} else {
throw new Error('Preview Release workflow failed.')
}
}
}
console.log(`Retrying... (${i + 1}/${maxRetries})`)
await new Promise(resolve => setTimeout(resolve, delay))
}
if (!completed) {
throw new Error('Preview Release workflow did not complete in time.')
}
// Remove the 'rocket' reaction
if (reaction) {
await github.rest.reactions.deleteForIssueComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: context.payload.comment.id,
reaction_id: reaction,
})
console.log('Removed "rocket" reaction.')
}
- name: Trigger Downstream Workflow
uses: actions/github-script@v8
id: trigger
env:
COMMENT: ${{ github.event.comment.body }}
PR_DATA: ${{ steps.get-pr-data.outputs.result }}
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const comment = process.env.COMMENT.trim()
const prData = JSON.parse(process.env.PR_DATA)
const suite = comment.split('\n')[0].replace(/^\/ecosystem-ci run/, '').trim()
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: 'vite-ecosystem-ci',
workflow_id: 'ecosystem-ci-from-pr.yml',
ref: 'main',
inputs: {
prNumber: '' + prData.num,
branchName: prData.branchName,
repo: prData.repo,
commit: prData.commit,
suite: suite === '' ? '-' : suite
}
})
issue-close-require .github/workflows/issue-close-require.yml
View raw YAML
name: Issue Close Require
on:
schedule:
- cron: "0 0 * * *"
jobs:
close-issues:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-slim
permissions:
issues: write # for actions-cool/issues-helper to update issues
pull-requests: write # for actions-cool/issues-helper to update PRs
steps:
- name: needs reproduction
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3
with:
actions: "close-issues"
token: ${{ secrets.GITHUB_TOKEN }}
labels: "needs reproduction"
inactive-day: 3
issue-labeled .github/workflows/issue-labeled.yml
View raw YAML
name: Issue Labeled
on:
issues:
types: [labeled]
jobs:
reply-labeled:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-slim
permissions:
issues: write # for actions-cool/issues-helper to update issues
pull-requests: write # for actions-cool/issues-helper to update PRs
steps:
- name: contribution welcome
if: github.event.label.name == 'contribution welcome' || github.event.label.name == 'help wanted'
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3
with:
actions: "remove-labels"
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: "pending triage, needs reproduction"
- name: remove pending
if: (github.event.label.name == 'enhancement' || contains(github.event.label.description, '(priority)')) && contains(github.event.issue.labels.*.name, 'pending triage')
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3
with:
actions: "remove-labels"
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
labels: "pending triage"
- name: needs reproduction
if: github.event.label.name == 'needs reproduction'
uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3
with:
actions: "create-comment, remove-labels"
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}. Please provide a [minimal reproduction](https://stackoverflow.com/help/minimal-reproducible-example) using a GitHub repository or [StackBlitz](https://vite.new). Issues marked with `needs reproduction` will be closed if they have no activity within 3 days.
labels: "pending triage"
issue-template-check .github/workflows/issue-template-check.yml
View raw YAML
name: Issue Template Check
on:
issues:
types: [opened]
jobs:
evaluate-issue:
if: "!github.event.issue.pull_request"
runs-on: ubuntu-latest
permissions:
contents: read
issues: read
pull-requests: read
outputs:
agent_output: ${{ steps.agent.outputs.agent_output }}
template_type: ${{ steps.detect.outputs.template_type }}
skip: ${{ steps.detect.outputs.skip }}
steps:
- uses: actions/checkout@v6
- name: Detect issue type
id: detect
uses: actions/github-script@v8
with:
script: |
const labels = context.payload.issue.labels.map(l => l.name);
const issueType = context.payload.issue.type?.name;
if (issueType === 'Bug') {
core.setOutput('template_type', 'bug_report');
core.setOutput('skip', 'false');
} else if (issueType === 'Feature') {
core.setOutput('template_type', 'feature_request');
core.setOutput('skip', 'false');
} else if (labels.includes('documentation')) {
core.setOutput('template_type', 'docs');
core.setOutput('skip', 'false');
} else {
core.info('Issue was not created from a recognized template. Skipping.');
core.setOutput('template_type', 'unknown');
core.setOutput('skip', 'true');
}
- uses: warpdotdev/oz-agent-action@1c023d0799f42be182644ced823d372a5ddddb40 # v1
if: steps.detect.outputs.skip == 'false'
id: agent
with:
prompt: |
You are an issue reviewer for the Vite project.
The issue template type detected is: ${{ steps.detect.outputs.template_type }}
Read the matching issue template from the checked-out repository at:
.github/ISSUE_TEMPLATE/${{ steps.detect.outputs.template_type }}.yml
Then evaluate the following issue to determine if it faithfully follows that template.
Issue title: ${{ github.event.issue.title }}
Issue body:
${{ github.event.issue.body }}
Here is a summary of the required fields per template type:
**bug_report** required fields:
1. Describe the bug (required) - A clear and concise description, not vague or just a generic error message
2. Reproduction (required) - A valid link to a reproduction (vite.new or GitHub repo URL), not empty or plain text
3. Steps to reproduce - Steps needed to reproduce (optional)
4. System Info (required) - Output of the envinfo command, must look like actual system/envinfo output
5. Used Package Manager (required) - One of: npm, yarn, pnpm, bun
6. Logs - Optional error logs
7. Validations (required) - All checkboxes must be checked
**feature_request** required fields:
1. Description (required) - Clear and concise description of the problem and use cases
2. Suggested solution (required) - A proposed implementation or approach. If it suggests a new option, check against "Think Before Adding Yet Another Option" in the CONTRIBUTING.md
3. Alternative - Alternative solutions considered (optional)
4. Additional context - Any other context (optional)
5. Validations (required) - All checkboxes must be checked
**docs** required fields:
1. Documentation is - Checkboxes indicating the issue type: Missing, Outdated, Confusing, Not sure (optional but at least one should be checked)
2. Explain in Detail (required) - A clear description of the documentation issue
3. Your Suggestion for Changes (required) - What should be changed
4. Reproduction - Optional link via vite.new or GitHub repo
5. Steps to reproduce - Optional reproduction steps
Evaluate the issue against the criteria for its detected template type. Focus on whether the required fields are present and substantive (not empty placeholders or placeholder text).
Respond with ONLY a JSON object (no markdown fencing) with these fields:
- "template": the template type that was checked
- "compliant": true/false
- "missing": an array of strings describing what is missing or inadequate (empty array if compliant)
- "comment": a polite, helpful comment to post if non-compliant, formatted in GitHub markdown. Address the user by their username @${{ github.event.issue.user.login }}. Ask them to update the issue with the missing information. Reference the specific template they should follow. Be concise.
output_format: json
warp_api_key: ${{ secrets.WARP_API_KEY }}
profile: ${{ vars.WARP_AGENT_PROFILE || '' }}
post-results:
needs: evaluate-issue
if: needs.evaluate-issue.outputs.skip == 'false' && needs.evaluate-issue.outputs.agent_output
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- name: Write result to summary
uses: actions/github-script@v8
env:
TEMPLATE_TYPE: ${{ needs.evaluate-issue.outputs.template_type }}
AGENT_OUTPUT: ${{ needs.evaluate-issue.outputs.agent_output }}
with:
script: |
const output = process.env.AGENT_OUTPUT;
const templateType = process.env.TEMPLATE_TYPE;
try {
// The agent outputs streaming JSON format with multiple lines
// We need to extract the last line with type:"agent" and parse its text field
const lines = output.trim().split('\n');
let agentText = null;
for (const line of lines) {
try {
const parsed = JSON.parse(line);
if (parsed.type === 'agent' && parsed.text) {
agentText = parsed.text;
}
} catch (e) {}
}
if (agentText) {
await core.summary
.addHeading(`Issue Template Check (${templateType})`)
.addCodeBlock(agentText, 'json')
.write();
} else {
core.setFailed('No agent output found in response');
}
} catch (e) {
core.setFailed(`Failed to write summary: ${e.message}`);
}
lock-closed-issues perms .github/workflows/lock-closed-issues.yml
View raw YAML
name: Lock Closed Issues
on:
schedule:
- cron: "0 0 * * *"
permissions:
issues: write
jobs:
action:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-slim
steps:
- uses: actions-cool/issues-helper@200c78641dbf33838311e5a1e0c31bbdb92d7cf0 # v3
with:
actions: "lock-issues"
token: ${{ secrets.GITHUB_TOKEN }}
#body: |
# This issue has been locked since it has been closed for more than 14 days.
#
# If you have found a concrete bug or regression related to it, please open a new [bug report](https://github.com/vitejs/vite/issues/new/choose) with a reproduction against the latest Vite version. If you have any other comments you should join the chat at [Vite Land](https://chat.vite.dev) or create a new [discussion](https://github.com/vitejs/vite/discussions).
issue-state: closed
inactive-day: 14
preview-release perms .github/workflows/preview-release.yml
View raw YAML
name: Preview release
env:
# install playwright binary manually (because pnpm only runs install script once)
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
permissions:
pull-requests: write
on:
push:
branches:
- main
pull_request:
types: [opened, synchronize, labeled]
jobs:
preview:
if: >
github.repository == 'vitejs/vite' &&
(github.event_name == 'push' ||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'trigger: preview')))
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Set node version to 24
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: https://registry.npmjs.org/
# disable cache, to avoid cache poisoning (https://docs.zizmor.sh/audits/#cache-poisoning)
package-manager-cache: false
- name: Disallow installation scripts
run: yq '.onlyBuiltDependencies = []' -i pnpm-workspace.yaml
- name: Install deps
run: pnpm install
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
- name: Build Vite core
working-directory: ./packages/vite
run: pnpm build
- name: Build plugin-legacy
working-directory: ./packages/plugin-legacy
run: pnpm build
- run: pnpm dlx pkg-pr-new@0.0 publish --pnpm './packages/vite' './packages/plugin-legacy' --packageManager=pnpm,npm,yarn --commentWithDev
publish .github/workflows/publish.yml
View raw YAML
name: Publish Package
on:
push:
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
- "plugin-*" # Push events to matching plugin-*, i.e. plugin-(vue|vue-jsx|react|legacy)@1.0.0
- "create-vite*" # # Push events to matching create-vite*, i.e. create-vite@1.0.0
jobs:
publish:
# prevents this action from running on forks
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
environment: Release
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install pnpm
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Set node version to 24
uses: actions/setup-node@v6
with:
node-version: 24
registry-url: https://registry.npmjs.org/
# disable cache, to avoid cache poisoning (https://docs.zizmor.sh/audits/#cache-poisoning)
package-manager-cache: false
- name: Disallow installation scripts
run: yq '.onlyBuiltDependencies = []' -i pnpm-workspace.yaml
- name: Install deps
run: pnpm install
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: "1"
- name: Publish package
run: npm i -g npm@^11.5.2 && pnpm run ci-publish "$REF_NAME"
env:
REF_NAME: ${{ github.ref_name }}
pull-request-template-check .github/workflows/pull-request-template-check.yml
View raw YAML
name: Pull Request Template Check
# SAFETY: pull_request_target is used here because:
# - The workflow does NOT check out PR code (actions/checkout checks out the base branch)
# - Only PR metadata (title, body) from the event payload is read
# - No PR-supplied code is executed
on:
pull_request_target:
types: [opened]
jobs:
evaluate-pr:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-latest
permissions:
contents: read
issues: read
pull-requests: read
outputs:
agent_output: ${{ steps.agent.outputs.agent_output }}
steps:
- uses: actions/checkout@v6
- uses: warpdotdev/oz-agent-action@827a9ad5438c195eb9d1d9a7acece3a8000be512 # v1
id: agent
with:
prompt: |
You are a pull request reviewer for the Vite project.
Read the PR template from the checked-out repository at:
.github/PULL_REQUEST_TEMPLATE.md
Then evaluate the following pull request to determine if it faithfully follows that template's guidelines.
PR title: ${{ github.event.pull_request.title }}
PR body:
${{ github.event.pull_request.body }}
Based on the PR template, check for the following:
1. **Description** (required) - A clear and concise description of what the PR solves
2. **Issue reference** (required) - References to related issues (e.g. `fixes #123`)
3. **Alternatives explored** (optional but encouraged) - Mention of other approaches considered
4. **Acknowledgments** (required) - Evidence that the author has:
- Read the Contributing Guidelines
- Checked for duplicate PRs
- Considered documentation updates
- Included relevant tests (or explained why not)
Evaluate the PR against these criteria. Focus on whether the required information is present and substantive (not empty placeholders or placeholder text).
Respond with ONLY a JSON object (no markdown fencing) with these fields:
- "compliant": true/false
- "missing": an array of strings describing what is missing or inadequate (empty array if compliant)
- "comment": a polite, helpful comment to post if non-compliant, formatted in GitHub markdown. Address the user by their username @${{ github.event.pull_request.user.login }}. Ask them to update the PR with the missing information. Reference the PR template they should follow. Be concise.
output_format: json
warp_api_key: ${{ secrets.WARP_API_KEY }}
profile: ${{ vars.WARP_AGENT_PROFILE || '' }}
post-results:
needs: evaluate-pr
if: needs.evaluate-pr.outputs.agent_output
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- name: Write result to summary
uses: actions/github-script@v8
env:
AGENT_OUTPUT: ${{ needs.evaluate-pr.outputs.agent_output }}
with:
script: |
const output = process.env.AGENT_OUTPUT;
try {
// The agent outputs streaming JSON format with multiple lines
// We need to extract the last line with type:"agent" and parse its text field
const lines = output.trim().split('\n');
let agentText = null;
for (const line of lines) {
try {
const parsed = JSON.parse(line);
if (parsed.type === 'agent' && parsed.text) {
agentText = parsed.text;
}
} catch (e) {}
}
if (agentText) {
await core.summary
.addHeading('Pull Request Template Check')
.addCodeBlock(agentText, 'json')
.write();
} else {
core.setFailed('No agent output found in response');
}
} catch (e) {
core.setFailed(`Failed to write summary: ${e.message}`);
}
release-tag .github/workflows/release-tag.yml
View raw YAML
name: Add GitHub Release Tag
on:
push:
tags:
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
- "plugin-*" # Push events to matching plugin-*, i.e. plugin-(vue|vue-jsx|react|legacy)@1.0.0
- "create-vite*" # # Push events to matching create-vite*, i.e. create-vite@1.0.0
# $GITHUB_REF_NAME - https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables
jobs:
release:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-slim
permissions:
contents: write # for yyx990803/release-tag to create a release tag
steps:
- uses: actions/checkout@v6
- name: Get pkgName for tag
id: tag
run: |
# skip if alpha
if [[ $GITHUB_REF_NAME =~ alpha ]]; then
exit 0
fi
# matching v2.0.0 / v2.0.0-beta.8 etc
if [[ $GITHUB_REF_NAME =~ ^v.+ ]]; then
pkgName="vite"
else
# `%@*` truncates @ and version number from the right side.
# https://stackoverflow.com/questions/9532654/expression-after-last-specific-character
pkgName=${GITHUB_REF_NAME%@*}
fi
echo "pkgName=$pkgName" >> $GITHUB_OUTPUT
- name: Create Release for Tag
# only run if tag is not alpha
if: steps.tag.outputs.pkgName
id: release_tag
uses: yyx990803/release-tag@8cccf7c5aa332d71d222df46677f70f77a8d2dc0 # v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
body: |
Please refer to [CHANGELOG.md](https://github.com/vitejs/vite/blob/${{ github.ref_name }}/packages/${{ steps.tag.outputs.pkgName }}/CHANGELOG.md) for details.
semantic-pull-request .github/workflows/semantic-pull-request.yml
View raw YAML
name: Semantic Pull Request
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
main:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-slim
name: Semantic Pull Request
permissions:
pull-requests: read
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6
with:
subjectPattern: ^(?![A-Z]).+$
subjectPatternError: |
The subject "{subject}" found in the pull request title "{title}"
didn't match the configured pattern. Please ensure that the subject
doesn't start with an uppercase character.
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}