1+
2+ /**
3+ * @fileoverview Version consistency checker for Socket CLI release process.
4+ *
5+ * Ensures all @socketbin packages and the main socket package have the same version.
6+ * This is CRITICAL for the release process to work correctly.
7+ */
8+
9+ import { existsSync , promises as fs } from 'node:fs'
10+ import path from 'node:path'
11+ import { fileURLToPath } from 'node:url'
12+
13+ import colors from 'yoctocolors-cjs'
14+
15+ const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) )
16+ const ROOT_DIR = path . join ( __dirname , '..' )
17+
18+ /**
19+ * Platform configurations for @socketbin packages.
20+ */
21+ const PLATFORMS = [
22+ { platform : 'darwin' , arch : 'arm64' } ,
23+ { platform : 'darwin' , arch : 'x64' } ,
24+ { platform : 'linux' , arch : 'arm64' } ,
25+ { platform : 'linux' , arch : 'x64' } ,
26+ { platform : 'win32' , arch : 'arm64' } ,
27+ { platform : 'win32' , arch : 'x64' } ,
28+ ]
29+
30+ /**
31+ * Read and parse a package.json file.
32+ */
33+ async function readPackageJson ( packagePath ) {
34+ try {
35+ const content = await fs . readFile ( packagePath , 'utf8' )
36+ return JSON . parse ( content )
37+ } catch ( error ) {
38+ if ( error . code === 'ENOENT' ) {
39+ return null
40+ }
41+ throw error
42+ }
43+ }
44+
45+ /**
46+ * Check version consistency across all packages.
47+ */
48+ async function checkVersionConsistency ( targetVersion = null ) {
49+ const errors = [ ]
50+ const warnings = [ ]
51+ const versions = new Map ( )
52+
53+ console . log ( '🔍 Checking version consistency...\n' )
54+
55+ // Check main package.json version.
56+ const mainPackagePath = path . join ( ROOT_DIR , 'package.json' )
57+ const mainPackage = await readPackageJson ( mainPackagePath )
58+ const mainVersion = mainPackage . version
59+
60+ console . log ( `📦 Main package version: ${ colors . cyan ( mainVersion ) } ` )
61+ versions . set ( 'socket (main)' , mainVersion )
62+
63+ // If target version specified, check it matches.
64+ if ( targetVersion && targetVersion !== mainVersion ) {
65+ errors . push (
66+ `Main package version (${ mainVersion } ) does not match target version (${ targetVersion } )`
67+ )
68+ }
69+
70+ // Check socket npm package (the published one).
71+ const npmPackagePath = path . join ( ROOT_DIR , 'src' , 'sea' , 'npm-package' , 'package.json' )
72+ if ( existsSync ( npmPackagePath ) ) {
73+ const npmPackage = await readPackageJson ( npmPackagePath )
74+ if ( npmPackage ) {
75+ const npmVersion = npmPackage . version
76+ console . log ( `📦 Socket npm package version: ${ colors . cyan ( npmVersion ) } ` )
77+ versions . set ( 'socket (npm)' , npmVersion )
78+
79+ if ( npmVersion !== mainVersion ) {
80+ errors . push (
81+ `Socket npm package version (${ npmVersion } ) does not match main version (${ mainVersion } )`
82+ )
83+ }
84+
85+ // Check optionalDependencies versions.
86+ if ( npmPackage . optionalDependencies ) {
87+ console . log ( '\n📦 Checking optionalDependencies versions:' )
88+ for ( const [ dep , version ] of Object . entries ( npmPackage . optionalDependencies ) ) {
89+ if ( dep . startsWith ( '@socketbin/' ) ) {
90+ console . log ( ` ${ dep } : ${ colors . cyan ( version ) } ` )
91+ versions . set ( dep , version )
92+
93+ if ( version !== mainVersion && version !== targetVersion ) {
94+ warnings . push (
95+ `${ dep } version in optionalDependencies (${ version } ) does not match expected version`
96+ )
97+ }
98+ }
99+ }
100+ }
101+ }
102+ } else {
103+ warnings . push ( 'Socket npm package not found at src/sea/npm-package/package.json' )
104+ }
105+
106+ // Check @socketbin binary packages.
107+ console . log ( '\n📦 Checking @socketbin package versions:' )
108+ const platformChecks = await Promise . all (
109+ PLATFORMS . map ( async ( { arch, platform } ) => {
110+ const packageName = `@socketbin/cli-${ platform } -${ arch } `
111+ const packagePath = path . join (
112+ ROOT_DIR ,
113+ 'packages' ,
114+ 'binaries' ,
115+ `cli-${ platform } -${ arch } ` ,
116+ 'package.json'
117+ )
118+
119+ if ( existsSync ( packagePath ) ) {
120+ const pkg = await readPackageJson ( packagePath )
121+ if ( pkg ) {
122+ const pkgVersion = pkg . version
123+ return {
124+ packageName,
125+ pkgVersion,
126+ exists : true ,
127+ error : pkgVersion !== mainVersion
128+ ? `${ packageName } version (${ pkgVersion } ) does not match main version (${ mainVersion } )`
129+ : null
130+ }
131+ }
132+ }
133+ return {
134+ packageName,
135+ exists : false
136+ }
137+ } )
138+ )
139+
140+ // Process results in order.
141+ for ( const result of platformChecks ) {
142+ if ( result . exists ) {
143+ console . log ( ` ${ result . packageName } : ${ colors . cyan ( result . pkgVersion ) } ` )
144+ versions . set ( result . packageName , result . pkgVersion )
145+ if ( result . error ) {
146+ errors . push ( result . error )
147+ }
148+ } else {
149+ // Package doesn't exist yet (expected before first publish).
150+ console . log ( ` ${ result . packageName } : ${ colors . gray ( '(not created yet)' ) } ` )
151+ }
152+ }
153+
154+ // Check for version mismatches.
155+ const uniqueVersions = new Set ( versions . values ( ) )
156+ if ( uniqueVersions . size > 1 && versions . size > 2 ) {
157+ console . log ( `\n⚠️ Multiple versions detected: ${ Array . from ( uniqueVersions ) . join ( ', ' ) } ` )
158+ }
159+
160+ // Print results.
161+ console . log ( )
162+ if ( errors . length > 0 ) {
163+ console . log ( colors . red ( '❌ Version consistency check failed!\n' ) )
164+ errors . forEach ( error => console . log ( ` ${ colors . red ( '✗' ) } ${ error } ` ) )
165+
166+ console . log ( '\n' + colors . yellow ( 'To fix version mismatches:' ) )
167+ console . log ( ' 1. Update version in main package.json' )
168+ console . log ( ' 2. Run: npm version <version> --no-git-tag-version in src/sea/npm-package' )
169+ console . log ( ' 3. Ensure all @socketbin packages are regenerated with correct version' )
170+ return false
171+ }
172+
173+ if ( warnings . length > 0 ) {
174+ console . log ( colors . yellow ( '⚠️ Warnings:\n' ) )
175+ warnings . forEach ( warning => console . log ( ` ${ colors . yellow ( '⚠' ) } ${ warning } ` ) )
176+ }
177+
178+ console . log ( colors . green ( '✅ All package versions are consistent!' ) )
179+ return true
180+ }
181+
182+ /**
183+ * Main entry point.
184+ */
185+ async function main ( ) {
186+ // Check if a target version was provided.
187+ const targetVersion = process . argv [ 2 ]
188+
189+ if ( targetVersion ) {
190+ console . log ( `Target version: ${ colors . cyan ( targetVersion ) } \n` )
191+ }
192+
193+ const isConsistent = await checkVersionConsistency ( targetVersion )
194+ process . exitCode = isConsistent ? 0 : 1
195+ }
196+
197+ // Run if executed directly.
198+ if ( process . argv [ 1 ] === fileURLToPath ( import . meta. url ) ) {
199+ main ( ) . catch ( error => {
200+ console . error ( colors . red ( 'Error:' ) , error . message )
201+ process . exitCode = 1
202+ } )
203+ }
204+
205+ export { checkVersionConsistency }
0 commit comments