|
| 1 | +/* eslint-disable no-console */ |
1 | 2 | const { execSync } = require('node:child_process'); |
2 | 3 | const fs = require('node:fs'); |
3 | 4 | const path = require('node:path'); |
4 | 5 |
|
5 | 6 | const PKG_JSON_PATH = path.join(__dirname, '..', '..', 'package.json'); |
6 | 7 |
|
7 | | -const pkgJson = require(PKG_JSON_PATH); // eslint-disable-line import/no-dynamic-require |
8 | | - |
9 | | -const PACKAGE_NAME = pkgJson.name; |
10 | | -const VERSION = pkgJson.version; |
11 | | -console.log(`before-deploy: Current version is ${VERSION}`); // eslint-disable-line no-console |
| 8 | +function execCommand(command, options = {}) { |
| 9 | + try { |
| 10 | + return execSync(command, { encoding: 'utf8', ...options }).trim(); |
| 11 | + } catch (error) { |
| 12 | + console.error(`Command failed: ${command}`); |
| 13 | + console.error(error.message); |
| 14 | + process.exit(1); |
| 15 | + return null; // Ensure a return value for all code paths |
| 16 | + } |
| 17 | +} |
12 | 18 |
|
13 | | -const nextVersion = getNextVersion(VERSION); |
14 | | -console.log(`before-deploy: Setting version to ${nextVersion}`); // eslint-disable-line no-console |
15 | | -pkgJson.version = nextVersion; |
| 19 | +function getPackageInfo() { |
| 20 | + const pkgJson = JSON.parse(fs.readFileSync(PKG_JSON_PATH, 'utf8')); |
| 21 | + return { |
| 22 | + name: pkgJson.name, |
| 23 | + version: pkgJson.version, |
| 24 | + pkgJson, |
| 25 | + }; |
| 26 | +} |
16 | 27 |
|
17 | | -fs.writeFileSync(PKG_JSON_PATH, `${JSON.stringify(pkgJson, null, 2)}\n`); |
| 28 | +function getBaseVersionFromGit() { |
| 29 | + try { |
| 30 | + // Get the base version from the latest commit that updated package.json |
| 31 | + // This ensures we use the version that was set by the release_metadata step |
| 32 | + const gitShow = execCommand('git show HEAD:package.json'); |
| 33 | + const gitPackageJson = JSON.parse(gitShow); |
| 34 | + return gitPackageJson.version; |
| 35 | + } catch (error) { |
| 36 | + console.error('Could not get base version from git'); |
| 37 | + throw error; |
| 38 | + } |
| 39 | +} |
18 | 40 |
|
19 | | -function getNextVersion(version) { |
20 | | - const versionString = execSync(`npm show ${PACKAGE_NAME} versions --json`, { encoding: 'utf8' }); |
21 | | - const versions = JSON.parse(versionString); |
| 41 | +function getNextBetaVersion(packageName, baseVersion) { |
| 42 | + console.log(`Calculating next beta version for base: ${baseVersion}`); |
22 | 43 |
|
23 | | - if (versions.some((v) => v === VERSION)) { |
24 | | - console.error(`before-deploy: A release with version ${VERSION} already exists. Please increment version accordingly.`); // eslint-disable-line no-console |
| 44 | + // Validate base version format |
| 45 | + if (!/^\d+\.\d+\.\d+$/.test(baseVersion)) { |
| 46 | + console.error(`Invalid base version format: ${baseVersion}`); |
25 | 47 | process.exit(1); |
26 | 48 | } |
27 | 49 |
|
28 | | - const prereleaseNumbers = versions |
29 | | - .filter((v) => (v.startsWith(VERSION) && v.includes('-'))) |
30 | | - .map((v) => Number(v.match(/\.(\d+)$/)[1])); |
31 | | - const lastPrereleaseNumber = Math.max(-1, ...prereleaseNumbers); |
32 | | - return `${version}-beta.${lastPrereleaseNumber + 1}`; |
| 50 | + let npmBetaNumber = 0; |
| 51 | + let gitBetaNumber = 0; |
| 52 | + |
| 53 | + // Check NPM for existing beta versions |
| 54 | + try { |
| 55 | + const versionString = execCommand(`npm show ${packageName} versions --json`); |
| 56 | + const versions = JSON.parse(versionString); |
| 57 | + |
| 58 | + // Check if base version already exists as stable |
| 59 | + if (versions.includes(baseVersion)) { |
| 60 | + console.error(`Base version ${baseVersion} already exists as stable on NPM!`); |
| 61 | + process.exit(1); |
| 62 | + } |
| 63 | + |
| 64 | + const versionPrefix = `${baseVersion}-beta.`; |
| 65 | + const npmBetas = versions |
| 66 | + .filter((v) => v.startsWith(versionPrefix)) |
| 67 | + .map((v) => { |
| 68 | + const match = v.match(/^.+-beta\.(\d+)$/); |
| 69 | + return match ? parseInt(match[1], 10) : 0; |
| 70 | + }); |
| 71 | + |
| 72 | + npmBetaNumber = npmBetas.length > 0 ? Math.max(...npmBetas) : 0; |
| 73 | + console.log(`Latest beta on NPM: ${npmBetaNumber}`); |
| 74 | + } catch { |
| 75 | + console.log('No existing versions found on NPM'); |
| 76 | + } |
| 77 | + |
| 78 | + // Check Git tags for existing beta versions |
| 79 | + try { |
| 80 | + const tagPattern = `v${baseVersion}-beta.*`; |
| 81 | + const tags = execCommand(`git tag -l "${tagPattern}" --sort=-version:refname`); |
| 82 | + |
| 83 | + if (tags) { |
| 84 | + const tagList = tags.split('\n').filter((tag) => tag.trim()); |
| 85 | + if (tagList.length > 0) { |
| 86 | + const latestTag = tagList[0]; |
| 87 | + const match = latestTag.match(/v\d+\.\d+\.\d+-beta\.(\d+)$/); |
| 88 | + if (match) { |
| 89 | + gitBetaNumber = parseInt(match[1], 10); |
| 90 | + console.log(`Latest beta in Git: ${gitBetaNumber}`); |
| 91 | + } |
| 92 | + } |
| 93 | + } |
| 94 | + } catch { |
| 95 | + console.log('No existing beta tags found in Git'); |
| 96 | + } |
| 97 | + |
| 98 | + // Use the higher number to avoid conflicts |
| 99 | + const nextBetaNumber = Math.max(npmBetaNumber, gitBetaNumber) + 1; |
| 100 | + const nextVersion = `${baseVersion}-beta.${nextBetaNumber}`; |
| 101 | + |
| 102 | + console.log(`Next beta version: ${nextVersion}`); |
| 103 | + return nextVersion; |
33 | 104 | } |
| 105 | + |
| 106 | +function updatePackageVersion(newVersion) { |
| 107 | + const { pkgJson } = getPackageInfo(); |
| 108 | + pkgJson.version = newVersion; |
| 109 | + fs.writeFileSync(PKG_JSON_PATH, `${JSON.stringify(pkgJson, null, 2)}\n`); |
| 110 | + console.log(`Updated package.json to ${newVersion}`); |
| 111 | +} |
| 112 | + |
| 113 | +function main() { |
| 114 | + console.log('🚀 Starting beta version calculation...'); |
| 115 | + |
| 116 | + const { name: packageName } = getPackageInfo(); |
| 117 | + |
| 118 | + // Get the base version from Git (what was committed by release_metadata) |
| 119 | + const baseVersion = getBaseVersionFromGit(); |
| 120 | + console.log(`Base version from Git: ${baseVersion}`); |
| 121 | + |
| 122 | + // Calculate next beta version |
| 123 | + const nextBetaVersion = getNextBetaVersion(packageName, baseVersion); |
| 124 | + |
| 125 | + // Update package.json with the beta version |
| 126 | + updatePackageVersion(nextBetaVersion); |
| 127 | + |
| 128 | + console.log('✅ Beta version preparation completed!'); |
| 129 | + console.log(`Package will be published as: ${nextBetaVersion}`); |
| 130 | +} |
| 131 | + |
| 132 | +main(); |
0 commit comments