feat(release): add beta and rc prerelease labels (#10806)

This commit is contained in:
shadcn
2026-05-29 15:13:21 +04:00
committed by GitHub
parent 2baa86081d
commit 5c849297d0
6 changed files with 124 additions and 39 deletions

View File

@@ -1,21 +0,0 @@
// ORIGINALLY FROM CLOUDFLARE WRANGLER:
// https://github.com/cloudflare/wrangler2/blob/main/.github/version-script.js
import { exec } from "child_process"
import fs from "fs"
const pkgJsonPath = "packages/shadcn/package.json"
try {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath))
exec("git rev-parse --short HEAD", (err, stdout) => {
if (err) {
console.log(err)
process.exit(1)
}
pkg.version = "0.0.0-beta." + stdout.trim()
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, "\t") + "\n")
})
} catch (error) {
console.error(error)
process.exit(1)
}

37
.github/version-script-prerelease.js vendored Normal file
View File

@@ -0,0 +1,37 @@
import fs from "fs"
const pkgJsonPath = "packages/shadcn/package.json"
const channel = process.argv[2]
const headSha = process.argv[3]
if (!["beta", "rc"].includes(channel)) {
console.error(
`Expected prerelease channel to be "beta" or "rc", got "${channel}".`
)
process.exit(1)
}
if (!headSha) {
console.error("Expected pull request head SHA.")
process.exit(1)
}
try {
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"))
const shortSha = headSha.trim().slice(0, 7)
const baseVersion = channel === "beta" ? "0.0.0" : pkg.version
if (channel === "rc" && baseVersion.includes("-")) {
console.error(
`Expected a stable planned version for rc, got "${baseVersion}".`
)
process.exit(1)
}
pkg.version = `${baseVersion}-${channel}.${shortSha}`
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, "\t") + "\n")
console.log(`Prepared shadcn@${pkg.version}`)
} catch (error) {
console.error(error)
process.exit(1)
}

View File

@@ -1,5 +1,5 @@
# Adapted from create-t3-app.
name: Write Beta Release comment
name: Write Prerelease comment
on:
workflow_run:
@@ -32,9 +32,13 @@ jobs:
const match = /^npm-package-shadcn@(.*?)-pr-(\d+)/.exec(artifact.name);
if (match) {
const version = match[1];
const channel = version.includes("-rc.") ? "rc" : "beta";
require("fs").appendFileSync(
process.env.GITHUB_ENV,
`\nBETA_PACKAGE_VERSION=${match[1]}` +
`\nPRERELEASE_PACKAGE_VERSION=${version}` +
`\nPRERELEASE_CHANNEL=${channel}` +
`\nPRERELEASE_LABEL=release: ${channel}` +
`\nWORKFLOW_RUN_PR=${match[2]}` +
`\nWORKFLOW_RUN_ID=${context.payload.workflow_run.id}`
);
@@ -47,20 +51,30 @@ jobs:
with:
number: ${{ env.WORKFLOW_RUN_PR }}
message: |
A new prerelease is available for testing:
A new ${{ env.PRERELEASE_CHANNEL }} prerelease is available for testing:
```sh
pnpm dlx shadcn@${{ env.BETA_PACKAGE_VERSION }}
pnpm dlx shadcn@${{ env.PRERELEASE_PACKAGE_VERSION }}
```
- name: "Remove the autorelease label once published"
View on npm: https://www.npmjs.com/package/shadcn/v/${{ env.PRERELEASE_PACKAGE_VERSION }}
- name: "Remove the prerelease label once published"
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: '${{ env.WORKFLOW_RUN_PR }}',
name: '🚀 autorelease',
});
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: '${{ env.WORKFLOW_RUN_PR }}',
name: '${{ env.PRERELEASE_LABEL }}',
});
} catch (error) {
if (error.status !== 404) {
throw error;
}
core.info("The prerelease label was already removed.");
}

View File

@@ -2,7 +2,7 @@
name: Release
run-name: ${{ github.event_name == 'pull_request' && format('Release Beta - PR {0}', github.event.number) || 'Release Stable' }}
run-name: ${{ github.event_name == 'pull_request' && format('Release Prerelease - PR {0}', github.event.number) || 'Release Stable' }}
on:
pull_request:
@@ -15,8 +15,8 @@ on:
jobs:
prerelease:
if: ${{ github.event_name == 'pull_request' && github.repository_owner == 'shadcn-ui' && contains(github.event.pull_request.labels.*.name, '🚀 autorelease') }}
name: Publish Beta to NPM
if: "${{ github.event_name == 'pull_request' && github.repository_owner == 'shadcn-ui' && (contains(github.event.pull_request.labels.*.name, 'release: beta') || contains(github.event.pull_request.labels.*.name, 'release: rc')) }}"
name: Publish Prerelease to NPM
runs-on: ubuntu-latest
environment: Preview
permissions:
@@ -24,10 +24,49 @@ jobs:
contents: read
steps:
- name: Select prerelease channel
id: prerelease
uses: actions/github-script@v7
with:
script: |
const prereleaseLabels = [
{ name: "release: beta", channel: "beta" },
{ name: "release: rc", channel: "rc" },
];
const labels = context.payload.pull_request.labels.map((label) => label.name);
const selectedLabels = prereleaseLabels.filter((label) =>
labels.includes(label.name)
);
if (selectedLabels.length !== 1) {
throw new Error(
`Expected exactly one prerelease label, found: ${
selectedLabels.map((label) => label.name).join(", ") || "none"
}.`
);
}
const selected = selectedLabels[0];
const pullRequest = context.payload.pull_request;
if (
selected.channel === "rc" &&
(pullRequest.head.ref !== "changeset-release/main" ||
pullRequest.title !== "chore(release): version packages")
) {
throw new Error(
"The release: rc label can only be used on the Changesets version PR from changeset-release/main."
);
}
core.setOutput("channel", selected.channel);
core.setOutput("label", selected.name);
- name: Checkout Repo
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Use PNPM
uses: pnpm/action-setup@v4
@@ -48,10 +87,7 @@ jobs:
run: pnpm install
- name: Modify package.json version
run: node .github/version-script-beta.js
- name: Publish Beta to NPM
run: pnpm pub:beta
run: node .github/version-script-prerelease.js ${{ steps.prerelease.outputs.channel }} ${{ github.event.pull_request.head.sha }}
- name: get-npm-version
id: package-version
@@ -59,6 +95,23 @@ jobs:
with:
path: packages/shadcn
- name: Check package version on NPM
id: package-exists
run: |
if npm view "shadcn@${{ steps.package-version.outputs.current-version }}" version >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
else
echo "exists=false" >> "$GITHUB_OUTPUT"
fi
- name: Publish Prerelease to NPM
if: ${{ steps.package-exists.outputs.exists == 'false' }}
run: pnpm pub:${{ steps.prerelease.outputs.channel }}
- name: Build packaged artifact
if: ${{ steps.package-exists.outputs.exists == 'true' }}
run: pnpm shadcn:build
- name: Upload packaged artifact
uses: actions/upload-artifact@v4
with:

View File

@@ -35,6 +35,7 @@
"check": "turbo lint typecheck format:check",
"release": "changeset version",
"pub:beta": "cd packages/shadcn && pnpm pub:beta",
"pub:rc": "cd packages/shadcn && pnpm pub:rc",
"pub:release": "cd packages/shadcn && pnpm pub:release",
"test:dev": "turbo run test --filter=!shadcn-ui --force",
"test": "pnpm --filter=v4 registry:build && start-server-and-test v4:dev http://localhost:4000 test:dev",

View File

@@ -73,6 +73,7 @@
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
"release": "changeset version",
"pub:beta": "pnpm build && pnpm publish --no-git-checks --access public --tag beta",
"pub:rc": "pnpm build && pnpm publish --no-git-checks --access public --tag rc",
"pub:next": "pnpm build && pnpm publish --no-git-checks --access public --tag next",
"pub:release": "pnpm build && pnpm publish --access public",
"test": "vitest run",