Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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
29 changes: 8 additions & 21 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,11 @@ name: Release Full
on:
workflow_dispatch:
inputs:
version:
type: choice
description: "Release Version Type"
required: true
default: "patch"
options:
- major
- premajor
- minor
- preminor
- patch
- prepatch
- prerelease

tag:
type: choice
description: "Release Npm Tag"
required: true
default: "latest"
default: "nightly"
options:
- canary
- nightly
Expand Down Expand Up @@ -71,9 +57,10 @@ jobs:
- name: Run Test
run: pnpm run test

- name: Try release to npm
run: pnpm run release
env:
DRY_RUN: ${{ inputs.dry_run }}
TAG: ${{ inputs.tag }}
VERSION: ${{ inputs.version }}
- name: Dry run release to npm
if: inputs.dry_run
run: node scripts/release.mjs --dry-run --tag ${{ inputs.tag }}

- name: Release to npm
if: ${{ !inputs.dry_run }}
run: node scripts/release.mjs --tag ${{ inputs.tag }}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@rspack/core": "1.4.11",
"@types/jest": "29.5.14",
"@types/node": "^22.17.0",
"cac": "^6.7.14",
"cross-env": "^10.0.0",
"execa": "9.6.0",
"fs-extra": "11.3.0",
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 38 additions & 32 deletions scripts/release.mjs
Original file line number Diff line number Diff line change
@@ -1,47 +1,64 @@
import path from 'path';
import * as url from 'url';
import cac from 'cac';
import { $ } from 'execa';
import fs from 'fs-extra';
import { inc } from 'semver';

const RELEASE_TAG = process.env.TAG || 'beta';
const RELEASE_DRY_RUN = process.env.DRY_RUN || 'true';
const RELEASE_VERSION_TYPE = process.env.VERSION || 'prerelease';
let cli = cac('release');
cli.option(
'--dry-run <run>',
'Perform a dry run without publishing or pushing tags',
{
default: 'false',
},
);
cli.option('--tag <tag>', 'The npm tag to publish under (default: canary)', {
default: 'canary',
});

const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
const PKG_PATH = path.resolve(__dirname, '../package.json');
const pkg = fs.readJsonSync(PKG_PATH);
const currentVersion = pkg.version;
const nextVersion = inc(currentVersion, RELEASE_VERSION_TYPE);
if (!nextVersion) {
const publishVersion = pkg.version;

const parsed = cli.parse();
const npmTag = parsed.options.tag;
const isDryRun = parsed.options.dryRun;

const allowedTags = ['latest', 'canary', 'alpha', 'beta', 'rc', 'nightly'];
if (!allowedTags.includes(npmTag)) {
throw new Error(
`Failed to generate next version from "${currentVersion}" with type "${RELEASE_VERSION_TYPE}"`,
`Invalid npm tag: ${npmTag}. Allowed tags: ${allowedTags.join(', ')}`,
);
}

console.info(`Release ${RELEASE_TAG} version ${nextVersion}`);

// Update pkg version
console.info(`Updating version from ${currentVersion} to ${nextVersion}`);
pkg.version = nextVersion;
fs.writeJsonSync(PKG_PATH, pkg, { spaces: 2 });
const prereleaseTags = ['alpha', 'beta', 'rc', 'canary', 'nightly'];
if (
npmTag === 'latest' &&
prereleaseTags.some((tag) => publishVersion.includes(tag))
) {
throw Error(`Can't release ${publishVersion} to latest tag`);
}

// Publish to npm
console.info(`Publishing to npm with tag ${RELEASE_TAG}`);
const dryRun = RELEASE_DRY_RUN === 'true' ? ['--dry-run'] : [];
console.info(
`Release ${npmTag} version ${publishVersion}${isDryRun ? '(dry-run)' : ''}`,
);

try {
await $`pnpm publish ${dryRun} --tag ${RELEASE_TAG} --no-git-checks`;
const flags = isDryRun
? ['--dry-run', `--tag`, npmTag, `--no-git-checks`]
: [`--tag`, npmTag, `--no-git-checks`];
await $`pnpm publish ${flags}`;
console.info(`Published successfully`);
} catch (e) {
console.error(`Publish failed: ${e.message}`);
process.exit(1);
}

// Push tag to github
if (RELEASE_DRY_RUN !== 'true') {
// Push tag to GitHub
if (!isDryRun) {
console.info(`Pushing tag to github`);
const tagName = `v${nextVersion}`;
const tagName = `v${publishVersion}`;
try {
await $`git config --global --add safe.directory /github/workspace`;
await $`git config --global user.name "github-actions[bot]"`;
Expand All @@ -54,17 +71,6 @@ if (RELEASE_DRY_RUN !== 'true') {
console.error(`Push tag failed: ${e.message}`);
process.exit(1);
}

try {
await $`git add --all`;
const commitMsg = `release ${tagName}`;
await $`git commit -m ${commitMsg}`;
await $`git push`;
console.info(`Pushed branch successfully`);
} catch (e) {
console.error(`Update branch failed: ${e.message}`);
process.exit(1);
}
}

console.info(`Release completed`);
46 changes: 46 additions & 0 deletions scripts/version.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { readFileSync, writeFileSync } from 'fs';
import { dirname, join } from 'path';
import { fileURLToPath } from 'url';
import { cac } from 'cac';
import semver from 'semver';

const cli = cac('version');
cli.option('--pre [prerelease]', 'Set the version to a pre-release version');
cli.command('version <bump_version>');
const parsed = cli.parse();

const __dirname = dirname(fileURLToPath(import.meta.url));
const pkgPath = join(__dirname, '../package.json');
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
const currentVersion = pkg.version;

const allowedVersion = ['major', 'minor', 'patch'];
const allowPretags = ['alpha', 'beta', 'rc'];

const version = parsed.args[0];

if (!allowedVersion.includes(version)) {
throw new Error(
`version must be one of ${allowedVersion}, but you passed ${version}`,
);
}

const hasPre = !!parsed.options.pre;
const pre = parsed.options.pre;

if (hasPre && !allowPretags.includes(pre)) {
throw new Error(
`pre tag must be one of ${allowPretags}, but you passed ${pre}`,
);
}

let newVersion;
if (hasPre) {
newVersion = semver.inc(currentVersion, `prerelease`, pre);
} else {
newVersion = semver.inc(currentVersion, version);
}

pkg.version = newVersion;
writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
console.log('package.json updated with new version.');