Skip to content

Commit 098ad21

Browse files
committed
fix beta versioning to find latest stable release and wait for code checks
1 parent 70d2c38 commit 098ad21

File tree

2 files changed

+104
-36
lines changed

2 files changed

+104
-36
lines changed

.github/scripts/before-beta-release.cjs

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
/* eslint-disable no-console */
21
const { execSync } = require('node:child_process');
32
const fs = require('node:fs');
43
const path = require('node:path');
@@ -12,7 +11,6 @@ function execCommand(command, options = {}) {
1211
console.error(`Command failed: ${command}`);
1312
console.error(error.message);
1413
process.exit(1);
15-
return null; // Ensure a return value for all code paths
1614
}
1715
}
1816

@@ -21,7 +19,7 @@ function getPackageInfo() {
2119
return {
2220
name: pkgJson.name,
2321
version: pkgJson.version,
24-
pkgJson,
22+
pkgJson
2523
};
2624
}
2725

@@ -38,93 +36,127 @@ function getBaseVersionFromGit() {
3836
}
3937
}
4038

39+
function incrementVersion(version, type = 'patch') {
40+
const [major, minor, patch] = version.split('.').map(Number);
41+
42+
switch (type) {
43+
case 'major':
44+
return `${major + 1}.0.0`;
45+
case 'minor':
46+
return `${major}.${minor + 1}.0`;
47+
case 'patch':
48+
default:
49+
return `${major}.${minor}.${patch + 1}`;
50+
}
51+
}
52+
53+
function findNextAvailableVersion(packageName, baseVersion) {
54+
console.log(`Finding next available version starting from: ${baseVersion}`);
55+
56+
try {
57+
const versionString = execCommand(`npm show ${packageName} versions --json`);
58+
const versions = JSON.parse(versionString);
59+
60+
let currentVersion = baseVersion;
61+
62+
// Keep incrementing patch version until we find one that doesn't exist
63+
while (versions.includes(currentVersion)) {
64+
console.log(`Version ${currentVersion} already exists as stable, incrementing...`);
65+
currentVersion = incrementVersion(currentVersion, 'patch');
66+
}
67+
68+
console.log(`Next available base version: ${currentVersion}`);
69+
return currentVersion;
70+
} catch (error) {
71+
console.log('Could not check NPM versions, using provided base version');
72+
return baseVersion;
73+
}
74+
}
75+
4176
function getNextBetaVersion(packageName, baseVersion) {
4277
console.log(`Calculating next beta version for base: ${baseVersion}`);
43-
78+
4479
// Validate base version format
4580
if (!/^\d+\.\d+\.\d+$/.test(baseVersion)) {
4681
console.error(`Invalid base version format: ${baseVersion}`);
4782
process.exit(1);
4883
}
4984

85+
// Find the next available base version if current one exists as stable
86+
const availableBaseVersion = findNextAvailableVersion(packageName, baseVersion);
87+
5088
let npmBetaNumber = 0;
5189
let gitBetaNumber = 0;
5290

53-
// Check NPM for existing beta versions
91+
// Check NPM for existing beta versions of the available base version
5492
try {
5593
const versionString = execCommand(`npm show ${packageName} versions --json`);
5694
const versions = JSON.parse(versionString);
5795

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.`;
96+
const versionPrefix = `${availableBaseVersion}-beta.`;
6597
const npmBetas = versions
66-
.filter((v) => v.startsWith(versionPrefix))
67-
.map((v) => {
98+
.filter(v => v.startsWith(versionPrefix))
99+
.map(v => {
68100
const match = v.match(/^.+-beta\.(\d+)$/);
69101
return match ? parseInt(match[1], 10) : 0;
70102
});
71-
103+
72104
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');
105+
console.log(`Latest beta on NPM for ${availableBaseVersion}: ${npmBetaNumber}`);
106+
} catch (error) {
107+
console.log('No existing beta versions found on NPM');
76108
}
77109

78-
// Check Git tags for existing beta versions
110+
// Check Git tags for existing beta versions of the available base version
79111
try {
80-
const tagPattern = `v${baseVersion}-beta.*`;
112+
const tagPattern = `v${availableBaseVersion}-beta.*`;
81113
const tags = execCommand(`git tag -l "${tagPattern}" --sort=-version:refname`);
82-
114+
83115
if (tags) {
84-
const tagList = tags.split('\n').filter((tag) => tag.trim());
116+
const tagList = tags.split('\n').filter(tag => tag.trim());
85117
if (tagList.length > 0) {
86118
const latestTag = tagList[0];
87119
const match = latestTag.match(/v\d+\.\d+\.\d+-beta\.(\d+)$/);
88120
if (match) {
89121
gitBetaNumber = parseInt(match[1], 10);
90-
console.log(`Latest beta in Git: ${gitBetaNumber}`);
122+
console.log(`Latest beta in Git for ${availableBaseVersion}: ${gitBetaNumber}`);
91123
}
92124
}
93125
}
94-
} catch {
126+
} catch (error) {
95127
console.log('No existing beta tags found in Git');
96128
}
97129

98130
// Use the higher number to avoid conflicts
99131
const nextBetaNumber = Math.max(npmBetaNumber, gitBetaNumber) + 1;
100-
const nextVersion = `${baseVersion}-beta.${nextBetaNumber}`;
101-
132+
const nextVersion = `${availableBaseVersion}-beta.${nextBetaNumber}`;
133+
102134
console.log(`Next beta version: ${nextVersion}`);
103135
return nextVersion;
104136
}
105137

106138
function updatePackageVersion(newVersion) {
107139
const { pkgJson } = getPackageInfo();
108140
pkgJson.version = newVersion;
109-
fs.writeFileSync(PKG_JSON_PATH, `${JSON.stringify(pkgJson, null, 2)}\n`);
141+
fs.writeFileSync(PKG_JSON_PATH, JSON.stringify(pkgJson, null, 2) + '\n');
110142
console.log(`Updated package.json to ${newVersion}`);
111143
}
112144

113145
function main() {
114146
console.log('🚀 Starting beta version calculation...');
115-
147+
116148
const { name: packageName } = getPackageInfo();
117-
149+
118150
// Get the base version from Git (what was committed by release_metadata)
119151
const baseVersion = getBaseVersionFromGit();
120152
console.log(`Base version from Git: ${baseVersion}`);
121-
122-
// Calculate next beta version
153+
154+
// Calculate next beta version (will auto-increment if base version exists as stable)
123155
const nextBetaVersion = getNextBetaVersion(packageName, baseVersion);
124-
156+
125157
// Update package.json with the beta version
126158
updatePackageVersion(nextBetaVersion);
127-
159+
128160
console.log('✅ Beta version preparation completed!');
129161
console.log(`Package will be published as: ${nextBetaVersion}`);
130162
}

.github/workflows/pre_release.yaml

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,48 @@ jobs:
3030
name: Wait for code checks to pass
3131
runs-on: ubuntu-latest
3232
steps:
33-
- uses: lewagon/[email protected]
33+
- name: Wait for existing checks or skip if none
34+
uses: lewagon/[email protected]
3435
with:
35-
ref: ${{ github.ref }}
36+
ref: ${{ github.event.pull_request.head.sha }}
3637
repo-token: ${{ secrets.GITHUB_TOKEN }}
3738
check-regexp: (Code checks)
38-
wait-interval: 5
39+
wait-interval: 10
40+
running-workflow-name: 'Wait for code checks to pass'
41+
allowed-conclusions: success,neutral,skipped
42+
continue-on-error: true
43+
44+
- name: Run checks if none were found
45+
if: failure()
46+
uses: actions/checkout@v4
47+
48+
- name: Use Node.js 22
49+
if: failure()
50+
uses: actions/setup-node@v4
51+
with:
52+
node-version: 22
53+
cache: 'npm'
54+
cache-dependency-path: 'package-lock.json'
55+
56+
- name: Install Dependencies
57+
if: failure()
58+
run: npm ci
59+
60+
- name: Lint
61+
if: failure()
62+
run: npm run lint
63+
64+
- name: Build
65+
if: failure()
66+
run: npm run build
67+
68+
- name: Test
69+
if: failure()
70+
run: npm run test
71+
72+
- name: Type checks
73+
if: failure()
74+
run: npm run type-check
3975

4076
update_changelog_and_version:
4177
needs: [ release_metadata, wait_for_checks ]

0 commit comments

Comments
 (0)