33 * Automated release script for prettier-vscode
44 *
55 * Usage:
6- * pnpm release major - Bump major version (11.0.0 -> 12.0.0)
7- * pnpm release minor - Bump minor version (11.0.0 -> 11.1.0)
8- * pnpm release patch - Bump patch version (11.0.0 -> 11.0.1)
9- * pnpm release preview - Create preview release (11.0.0 -> 11.0.0-preview.1)
10- * pnpm release preview 12.0.0-preview.1 - Create preview with specific version
6+ * pnpm release major - Bump major version (11.0.0 -> 12.0.0)
7+ * pnpm release minor - Bump minor version (11.0.0 -> 11.1.0)
8+ * pnpm release patch - Bump patch version (11.0.0 -> 11.0.1)
9+ * pnpm release patch --pre - Patch as prerelease (tag: v11.0.1-pre)
10+ * pnpm release minor 12.1.0 - Use specific version
11+ * pnpm release patch 12.0.1 --pre - Specific version as prerelease
1112 */
1213import fs from "fs/promises" ;
1314import { execSync } from "child_process" ;
1415
15- const RELEASE_TYPES = [ "major" , "minor" , "patch" , "preview" ] ;
16+ const RELEASE_TYPES = [ "major" , "minor" , "patch" ] ;
1617
1718function exec ( cmd , options = { } ) {
1819 console . log ( `$ ${ cmd } ` ) ;
@@ -24,34 +25,26 @@ function execQuiet(cmd) {
2425}
2526
2627function parseVersion ( version ) {
27- // Handle prerelease versions like "11.1.0-preview.1"
28- const match = version . match ( / ^ ( \d + ) \. ( \d + ) \. ( \d + ) (?: - ( [ a - z ] + ) \. ( \d + ) ) ? $ / i) ;
28+ const match = version . match ( / ^ ( \d + ) \. ( \d + ) \. ( \d + ) $ / ) ;
2929 if ( ! match ) {
3030 throw new Error ( `Invalid version format: ${ version } ` ) ;
3131 }
3232 return {
3333 major : parseInt ( match [ 1 ] , 10 ) ,
3434 minor : parseInt ( match [ 2 ] , 10 ) ,
3535 patch : parseInt ( match [ 3 ] , 10 ) ,
36- prerelease : match [ 4 ] || null ,
37- prereleaseNum : match [ 5 ] ? parseInt ( match [ 5 ] , 10 ) : null ,
3836 } ;
3937}
4038
41- function formatVersion ( { major, minor, patch, prerelease, prereleaseNum } ) {
42- let version = `${ major } .${ minor } .${ patch } ` ;
43- if ( prerelease ) {
44- version += `-${ prerelease } .${ prereleaseNum } ` ;
45- }
46- return version ;
39+ function formatVersion ( { major, minor, patch } ) {
40+ return `${ major } .${ minor } .${ patch } ` ;
4741}
4842
49- async function updateChangelog ( version , releaseType ) {
43+ async function updateChangelog ( version , isPrerelease ) {
5044 const CHANGELOG = "CHANGELOG.md" ;
51- const isPrerelease = releaseType === "preview" || version . includes ( "-" ) ;
5245
5346 if ( isPrerelease ) {
54- console . log ( `Skipping changelog update for prerelease version ${ version } ` ) ;
47+ console . log ( `Skipping changelog update for prerelease` ) ;
5548 return ;
5649 }
5750
@@ -71,110 +64,73 @@ async function updateChangelog(version, releaseType) {
7164
7265function calculateNewVersion ( currentVersion , releaseType ) {
7366 const v = parseVersion ( currentVersion ) ;
74- const isCurrentPrerelease = v . prerelease !== null ;
7567
7668 switch ( releaseType ) {
7769 case "major" :
78- // If current is prerelease of this major, just drop prerelease suffix
79- // e.g., 12.0.0-preview.1 -> 12.0.0
80- if ( isCurrentPrerelease && v . minor === 0 && v . patch === 0 ) {
81- return formatVersion ( { ...v , prerelease : null , prereleaseNum : null } ) ;
82- }
83- // Otherwise bump major
8470 return formatVersion ( {
8571 major : v . major + 1 ,
8672 minor : 0 ,
8773 patch : 0 ,
88- prerelease : null ,
89- prereleaseNum : null ,
9074 } ) ;
9175
9276 case "minor" :
93- // If current is prerelease of this minor, just drop prerelease suffix
94- // e.g., 11.1.0-preview.1 -> 11.1.0
95- if ( isCurrentPrerelease && v . patch === 0 ) {
96- return formatVersion ( { ...v , prerelease : null , prereleaseNum : null } ) ;
97- }
98- // Otherwise bump minor
9977 return formatVersion ( {
10078 major : v . major ,
10179 minor : v . minor + 1 ,
10280 patch : 0 ,
103- prerelease : null ,
104- prereleaseNum : null ,
10581 } ) ;
10682
10783 case "patch" :
108- // If current is prerelease of this patch, just drop prerelease suffix
109- // e.g., 11.0.1-preview.1 -> 11.0.1
110- if ( isCurrentPrerelease ) {
111- return formatVersion ( { ...v , prerelease : null , prereleaseNum : null } ) ;
112- }
113- // Otherwise bump patch
11484 return formatVersion ( {
11585 major : v . major ,
11686 minor : v . minor ,
11787 patch : v . patch + 1 ,
118- prerelease : null ,
119- prereleaseNum : null ,
120- } ) ;
121-
122- case "preview" :
123- // If already a preview, increment the preview number
124- if ( isCurrentPrerelease && v . prerelease === "preview" ) {
125- return formatVersion ( {
126- ...v ,
127- prereleaseNum : v . prereleaseNum + 1 ,
128- } ) ;
129- }
130- // Otherwise, keep the same version and add preview.1
131- return formatVersion ( {
132- major : v . major ,
133- minor : v . minor ,
134- patch : v . patch ,
135- prerelease : "preview" ,
136- prereleaseNum : 1 ,
13788 } ) ;
13889
13990 default :
14091 throw new Error ( `Unknown release type: ${ releaseType } ` ) ;
14192 }
14293}
14394
95+ function parseArgs ( argv ) {
96+ const args = argv . slice ( 2 ) ;
97+ const isPrerelease = args . includes ( "--pre" ) ;
98+ const positional = args . filter ( ( arg ) => ! arg . startsWith ( "--" ) ) ;
99+
100+ return {
101+ releaseType : positional [ 0 ] ,
102+ manualVersion : positional [ 1 ] ,
103+ isPrerelease,
104+ } ;
105+ }
106+
144107async function main ( ) {
145- const releaseType = process . argv [ 2 ] ;
146- const manualVersion = process . argv [ 3 ] ;
108+ const { releaseType, manualVersion, isPrerelease } = parseArgs ( process . argv ) ;
147109
148110 if ( ! releaseType || ! RELEASE_TYPES . includes ( releaseType ) ) {
149- console . error ( "Usage: pnpm release <major|minor|patch|preview > [version]" ) ;
111+ console . error ( "Usage: pnpm release <major|minor|patch> [version] [--pre ]" ) ;
150112 console . error ( "" ) ;
151113 console . error ( "Examples:" ) ;
152- console . error ( " pnpm release major - 11.0.0 -> 12.0.0" ) ;
153- console . error ( " pnpm release minor - 11.0.0 -> 11.1.0" ) ;
154- console . error ( " pnpm release patch - 11.0.0 -> 11.0.1" ) ;
155- console . error ( " pnpm release preview - 11.0.0 -> 11.0.0-preview.1" ) ;
114+ console . error ( " pnpm release major - 11.0.0 -> 12.0.0" ) ;
115+ console . error ( " pnpm release minor - 11.0.0 -> 11.1.0" ) ;
116+ console . error ( " pnpm release patch - 11.0.0 -> 11.0.1" ) ;
117+ console . error (
118+ " pnpm release patch --pre - 11.0.0 -> 11.0.1 (tag: v11.0.1-pre)" ,
119+ ) ;
120+ console . error ( " pnpm release minor 12.1.0 - Use specific version" ) ;
156121 console . error (
157- " pnpm release preview 12.0.0-preview. 1 - Use specific version" ,
122+ " pnpm release patch 12.0.1 --pre - Specific version as prerelease " ,
158123 ) ;
159124 process . exit ( 1 ) ;
160125 }
161126
162127 // Validate manual version if provided
163128 if ( manualVersion ) {
164- if ( releaseType !== "preview" ) {
165- console . error (
166- "Error: Manual version can only be specified with 'preview' release type." ,
167- ) ;
168- process . exit ( 1 ) ;
169- }
170- // Validate format
171129 try {
172130 parseVersion ( manualVersion ) ;
173131 } catch {
174132 console . error ( `Error: Invalid version format: ${ manualVersion } ` ) ;
175- console . error (
176- "Expected format: X.Y.Z or X.Y.Z-prerelease.N (e.g., 12.0.0-preview.1)" ,
177- ) ;
133+ console . error ( "Expected format: X.Y.Z (e.g., 12.0.1)" ) ;
178134 process . exit ( 1 ) ;
179135 }
180136 }
@@ -189,13 +145,11 @@ async function main() {
189145
190146 // Stable releases must be on main branch
191147 const currentBranch = execQuiet ( "git rev-parse --abbrev-ref HEAD" ) ;
192- if ( releaseType !== "preview" && currentBranch !== "main" ) {
193- console . error (
194- `Error: ${ releaseType } releases must be run from the main branch.` ,
195- ) ;
148+ if ( ! isPrerelease && currentBranch !== "main" ) {
149+ console . error ( `Error: Stable releases must be run from the main branch.` ) ;
196150 console . error ( `Current branch: ${ currentBranch } ` ) ;
197- console . error ( "\nTo release a preview from this branch, use:" ) ;
198- console . error ( " pnpm release preview " ) ;
151+ console . error ( "\nTo release a prerelease from this branch, use:" ) ;
152+ console . error ( " pnpm release <major|minor|patch> --pre " ) ;
199153 process . exit ( 1 ) ;
200154 }
201155
@@ -205,9 +159,14 @@ async function main() {
205159 const newVersion =
206160 manualVersion || calculateNewVersion ( currentVersion , releaseType ) ;
207161
208- console . log ( `\nRelease: ${ releaseType } ` ) ;
162+ const tagName = isPrerelease ? `v${ newVersion } -pre` : `v${ newVersion } ` ;
163+
164+ console . log (
165+ `\nRelease: ${ releaseType } ${ isPrerelease ? " (prerelease)" : "" } ` ,
166+ ) ;
209167 console . log ( `Current version: ${ currentVersion } ` ) ;
210- console . log ( `New version: ${ newVersion } \n` ) ;
168+ console . log ( `New version: ${ newVersion } ` ) ;
169+ console . log ( `Tag: ${ tagName } \n` ) ;
211170
212171 // Update package.json
213172 packageJson . version = newVersion ;
@@ -218,13 +177,12 @@ async function main() {
218177 console . log ( "Updated package.json" ) ;
219178
220179 // Update changelog (skip for prereleases)
221- await updateChangelog ( newVersion , releaseType ) ;
180+ await updateChangelog ( newVersion , isPrerelease ) ;
222181
223182 // Stage changes
224183 exec ( "git add package.json CHANGELOG.md" ) ;
225184
226185 // Create commit and tag
227- const tagName = `v${ newVersion } ` ;
228186 exec ( `git commit -m "${ tagName } "` ) ;
229187 exec ( `git tag ${ tagName } ` ) ;
230188
0 commit comments