Skip to content

Commit 34f4f2e

Browse files
committed
Set up post-merge hook to stablize version and fix tests
1 parent b61e6d8 commit 34f4f2e

File tree

9 files changed

+262
-18
lines changed

9 files changed

+262
-18
lines changed

.gitattributes

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +0,0 @@
1-
*.js text eol=lf
2-
*.svg text eol=lf
3-
lessc text eol=lf
4-
*.less text eol=lf
5-
*.css text eol=lf
6-
*.htm text eol=lf
7-
*.html text eol=lf
8-
*.jpg binary
9-
*.png binary
10-
*.jpeg binary
11-
12-
# From https://github.com/alexkaratarakis/gitattributes/blob/master/Web.gitattributes
13-
*.lock text -diff
14-
package-lock.json text -diff

.husky/post-merge

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env sh
2+
. "$(dirname -- "$0")/_/husky.sh"
3+
4+
# Post-merge hook to preserve alpha versions when merging master into alpha
5+
node scripts/post-merge-version-fix.js

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pnpm test

CONTRIBUTING.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,23 @@ The publishing workflow (`.github/workflows/publish.yml`) handles both release t
123123
- Alpha branch must be up-to-date with master before publishing
124124
- Alpha base version must be >= master version (semver)
125125

126+
### Merging Master into Alpha
127+
128+
When merging `master` into `alpha`, the version in `package.json` might be overwritten. We have two layers of protection:
129+
130+
1. **Post-merge git hook** (automatic): Automatically restores alpha versions after merges
131+
- Installed automatically via husky when you run `pnpm install`
132+
- Runs automatically after `git merge`
133+
- Restores and increments the alpha version if it was overwritten
134+
- Prompts you to commit the restored version
135+
136+
2. **Publishing script detection** (safety net): The publishing script also detects overwritten versions
137+
- Searches git history for the last alpha version
138+
- Restores and increments it (e.g., if it was `5.0.0-alpha.3`, it becomes `5.0.0-alpha.4`)
139+
- Updates all package.json files accordingly
140+
141+
**Note**: The git hook is managed by husky and installs automatically. The publishing script protection works as a backup even if the hook isn't installed.
142+
126143
---
127144

128145
Thank you for contributing to Less.js!

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"scripts": {
88
"publish": "node scripts/bump-and-publish.js",
99
"publish:dry-run": "DRY_RUN=true node scripts/bump-and-publish.js",
10+
"prepare": "husky",
1011
"changelog": "github-changes -o less -r less.js -a --only-pulls --use-commit-body -m \"(YYYY-MM-DD)\"",
1112
"test": "cd packages/less && npm test",
1213
"postinstall": "npx only-allow pnpm"
@@ -26,6 +27,7 @@
2627
"devDependencies": {
2728
"all-contributors-cli": "~6.26.1",
2829
"github-changes": "^1.1.2",
30+
"husky": "~9.1.7",
2931
"npm-run-all": "^4.1.5",
3032
"semver": "^6.3.1"
3133
},

packages/test-data/tests-unit/import/import-remote.less

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// https://github.com/less/less.js/issues/3541
2-
@import (reference) url(https://cdn.jsdelivr.net/npm/@less/test-data/less/_main/selectors.less);
3-
@import (reference) url("https://cdn.jsdelivr.net/npm/@less/test-data/less/_main/media.less");
4-
@import (reference) url("https://cdn.jsdelivr.net/npm/@less/test-data/less/_main/empty.less?arg");
2+
@import (reference) url(https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/selectors/selectors.less);
3+
@import (reference) url("https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/media/media.less");
4+
@import (reference) url("https://cdn.jsdelivr.net/npm/@less/test-data/tests-unit/empty/empty.less?arg");
55

66
.test {
77
color: @var;

pnpm-lock.yaml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/bump-and-publish.js

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,79 @@ function main() {
159159
console.log(`🚀 Starting publish process for branch: ${branch}`);
160160

161161
// Get current version
162-
const currentVersion = getCurrentVersion();
162+
let currentVersion = getCurrentVersion();
163163
console.log(`📦 Current version: ${currentVersion}`);
164164

165+
// Protection: If on alpha branch and version was overwritten by a merge from master
166+
if (isAlpha && !currentVersion.includes('-alpha.')) {
167+
console.log(`\n⚠️ WARNING: Alpha branch version (${currentVersion}) doesn't contain '-alpha.'`);
168+
console.log(` This likely happened due to merging master into alpha.`);
169+
console.log(` Attempting to restore alpha version...`);
170+
171+
// Try to find the last alpha version from alpha branch history
172+
let restoredVersion = null;
173+
try {
174+
// Get recent commits on alpha that modified package.json
175+
const commits = execSync(
176+
'git log alpha --oneline -20 -- packages/less/package.json',
177+
{ cwd: ROOT_DIR, encoding: 'utf8' }
178+
).trim().split('\n');
179+
180+
// Search through commits to find the last alpha version
181+
for (const commitLine of commits) {
182+
const commitHash = commitLine.split(' ')[0];
183+
try {
184+
const pkgContent = execSync(
185+
`git show ${commitHash}:packages/less/package.json 2>/dev/null`,
186+
{ cwd: ROOT_DIR, encoding: 'utf8' }
187+
);
188+
const pkg = JSON.parse(pkgContent);
189+
if (pkg.version && pkg.version.includes('-alpha.')) {
190+
restoredVersion = pkg.version;
191+
console.log(` Found previous alpha version in commit ${commitHash}: ${restoredVersion}`);
192+
break;
193+
}
194+
} catch (e) {
195+
// Continue to next commit
196+
}
197+
}
198+
199+
if (restoredVersion) {
200+
// Increment the alpha number from the restored version
201+
const alphaMatch = restoredVersion.match(/^(\d+\.\d+\.\d+)-alpha\.(\d+)$/);
202+
if (alphaMatch) {
203+
const alphaNum = parseInt(alphaMatch[2], 10);
204+
const newAlphaVersion = `${alphaMatch[1]}-alpha.${alphaNum + 1}`;
205+
console.log(` Restoring and incrementing to: ${newAlphaVersion}`);
206+
currentVersion = newAlphaVersion;
207+
updateAllVersions(newAlphaVersion);
208+
} else {
209+
console.log(` Restoring to: ${restoredVersion}`);
210+
currentVersion = restoredVersion;
211+
updateAllVersions(restoredVersion);
212+
}
213+
} else {
214+
// No previous alpha version found, create one from current version
215+
const parsed = parseVersion(currentVersion);
216+
const nextMajor = parsed.major + 1;
217+
const newAlphaVersion = `${nextMajor}.0.0-alpha.1`;
218+
console.log(` No previous alpha version found. Creating new: ${newAlphaVersion}`);
219+
currentVersion = newAlphaVersion;
220+
updateAllVersions(newAlphaVersion);
221+
}
222+
} catch (e) {
223+
// If we can't find previous version, create a new alpha version
224+
const parsed = parseVersion(currentVersion);
225+
const nextMajor = parsed.major + 1;
226+
const newAlphaVersion = `${nextMajor}.0.0-alpha.1`;
227+
console.log(` Could not find previous alpha version. Creating: ${newAlphaVersion}`);
228+
currentVersion = newAlphaVersion;
229+
updateAllVersions(newAlphaVersion);
230+
}
231+
232+
console.log(`✅ Restored/created alpha version: ${currentVersion}\n`);
233+
}
234+
165235
// Determine next version
166236
const explicitVersion = getExplicitVersion();
167237
let nextVersion;

scripts/post-merge-version-fix.js

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Post-merge hook to preserve alpha versions when merging master into alpha branch
5+
*
6+
* This script runs after a merge and checks if:
7+
* 1. We're on the alpha branch
8+
* 2. The version in package.json doesn't contain '-alpha.' (was overwritten)
9+
* 3. If so, restores the previous alpha version from git history
10+
*/
11+
12+
const fs = require('fs');
13+
const path = require('path');
14+
const { execSync } = require('child_process');
15+
16+
const ROOT_DIR = path.resolve(__dirname, '..');
17+
const LESS_PKG_PATH = path.join(ROOT_DIR, 'packages', 'less', 'package.json');
18+
19+
// Get current branch
20+
function getCurrentBranch() {
21+
try {
22+
return execSync('git rev-parse --abbrev-ref HEAD', {
23+
cwd: ROOT_DIR,
24+
encoding: 'utf8'
25+
}).trim();
26+
} catch (e) {
27+
return null;
28+
}
29+
}
30+
31+
// Read package.json version
32+
function getVersion(pkgPath) {
33+
try {
34+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
35+
return pkg.version;
36+
} catch (e) {
37+
return null;
38+
}
39+
}
40+
41+
// Update version in package.json
42+
function updateVersion(pkgPath, newVersion) {
43+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
44+
pkg.version = newVersion;
45+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, '\t') + '\n', 'utf8');
46+
}
47+
48+
// Find last alpha version from git history
49+
function findLastAlphaVersion() {
50+
try {
51+
// Get recent commits on alpha that modified package.json
52+
const commits = execSync(
53+
'git log alpha --oneline -20 -- packages/less/package.json',
54+
{ cwd: ROOT_DIR, encoding: 'utf8' }
55+
).trim().split('\n');
56+
57+
// Search through commits to find the last alpha version
58+
for (const commitLine of commits) {
59+
const commitHash = commitLine.split(' ')[0];
60+
try {
61+
const pkgContent = execSync(
62+
`git show ${commitHash}:packages/less/package.json 2>/dev/null`,
63+
{ cwd: ROOT_DIR, encoding: 'utf8' }
64+
);
65+
const pkg = JSON.parse(pkgContent);
66+
if (pkg.version && pkg.version.includes('-alpha.')) {
67+
return pkg.version;
68+
}
69+
} catch (e) {
70+
// Continue to next commit
71+
}
72+
}
73+
} catch (e) {
74+
// Ignore errors
75+
}
76+
return null;
77+
}
78+
79+
// Update all package.json files with new version
80+
function updateAllVersions(newVersion) {
81+
const packageFiles = [
82+
path.join(ROOT_DIR, 'package.json'),
83+
path.join(ROOT_DIR, 'packages', 'less', 'package.json'),
84+
path.join(ROOT_DIR, 'packages', 'test-data', 'package.json')
85+
];
86+
87+
for (const pkgPath of packageFiles) {
88+
if (fs.existsSync(pkgPath)) {
89+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
90+
if (pkg.version) {
91+
pkg.version = newVersion;
92+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, '\t') + '\n', 'utf8');
93+
}
94+
}
95+
}
96+
}
97+
98+
// Main function
99+
function main() {
100+
const branch = getCurrentBranch();
101+
102+
// Only run on alpha branch
103+
if (branch !== 'alpha') {
104+
return;
105+
}
106+
107+
const currentVersion = getVersion(LESS_PKG_PATH);
108+
109+
if (!currentVersion) {
110+
return;
111+
}
112+
113+
// Check if version was overwritten (doesn't contain -alpha.)
114+
if (!currentVersion.includes('-alpha.')) {
115+
console.log(`\n⚠️ Post-merge: Alpha version was overwritten (${currentVersion})`);
116+
console.log(` Attempting to restore alpha version...`);
117+
118+
const lastAlphaVersion = findLastAlphaVersion();
119+
120+
if (lastAlphaVersion) {
121+
// Increment the alpha number
122+
const alphaMatch = lastAlphaVersion.match(/^(\d+\.\d+\.\d+)-alpha\.(\d+)$/);
123+
if (alphaMatch) {
124+
const alphaNum = parseInt(alphaMatch[2], 10);
125+
const newAlphaVersion = `${alphaMatch[1]}-alpha.${alphaNum + 1}`;
126+
console.log(` Restoring and incrementing: ${lastAlphaVersion}${newAlphaVersion}`);
127+
updateAllVersions(newAlphaVersion);
128+
console.log(`✅ Restored alpha version: ${newAlphaVersion}`);
129+
console.log(` Please commit this change: git add package.json packages/*/package.json && git commit -m "chore: restore alpha version after merge"`);
130+
} else {
131+
console.log(` Restoring to: ${lastAlphaVersion}`);
132+
updateAllVersions(lastAlphaVersion);
133+
console.log(`✅ Restored alpha version: ${lastAlphaVersion}`);
134+
console.log(` Please commit this change: git add package.json packages/*/package.json && git commit -m "chore: restore alpha version after merge"`);
135+
}
136+
} else {
137+
// No previous alpha version found, create one
138+
const parts = currentVersion.split('.');
139+
const nextMajor = parseInt(parts[0], 10) + 1;
140+
const newAlphaVersion = `${nextMajor}.0.0-alpha.1`;
141+
console.log(` No previous alpha version found. Creating: ${newAlphaVersion}`);
142+
updateAllVersions(newAlphaVersion);
143+
console.log(`✅ Created new alpha version: ${newAlphaVersion}`);
144+
console.log(` Please commit this change: git add package.json packages/*/package.json && git commit -m "chore: restore alpha version after merge"`);
145+
}
146+
}
147+
}
148+
149+
if (require.main === module) {
150+
main();
151+
}
152+
153+
module.exports = { main };

0 commit comments

Comments
 (0)