186 lines
5.1 KiB
TypeScript
186 lines
5.1 KiB
TypeScript
import { execSync } from 'child_process';
|
|
import { readFileSync, writeFileSync } from 'fs';
|
|
import { join } from 'path';
|
|
|
|
interface Version {
|
|
major: number;
|
|
minor: number;
|
|
patch: number;
|
|
}
|
|
|
|
function parseVersion(version: string): Version {
|
|
const [major, minor, patch] = version.split('.').map(Number);
|
|
return { major, minor, patch };
|
|
}
|
|
|
|
function formatVersion(v: Version): string {
|
|
return `${v.major}.${v.minor}.${v.patch}`;
|
|
}
|
|
|
|
function getLastVersionTag(): string | null {
|
|
try {
|
|
const tag = execSync('git describe --tags --abbrev=0', {
|
|
encoding: 'utf-8',
|
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
}).trim();
|
|
return tag;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function getCommitsSinceTag(tag: string | null): string[] {
|
|
try {
|
|
const range = tag ? `${tag}..HEAD` : 'HEAD';
|
|
const commits = execSync(`git log ${range} --pretty=format:"%s"`, {
|
|
encoding: 'utf-8',
|
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
})
|
|
.trim()
|
|
.split('\n')
|
|
.filter(Boolean);
|
|
return commits;
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
function determineVersionBump(commits: string[]): 'major' | 'minor' | 'patch' {
|
|
let hasBreaking = false;
|
|
let hasFeature = false;
|
|
let hasPatch = false;
|
|
|
|
for (const commit of commits) {
|
|
const lowerCommit = commit.toLowerCase();
|
|
|
|
// Breaking changes (major bump)
|
|
if (
|
|
lowerCommit.includes('breaking change') ||
|
|
lowerCommit.includes('breaking:') ||
|
|
lowerCommit.match(/^[a-z]+!:/) || // feat!:, refactor!:, etc.
|
|
lowerCommit.includes('!')
|
|
) {
|
|
hasBreaking = true;
|
|
}
|
|
|
|
// Features (minor bump)
|
|
if (lowerCommit.startsWith('feat:')) {
|
|
hasFeature = true;
|
|
}
|
|
|
|
// Patch bumps: fixes, performance improvements, security fixes, refactorings
|
|
if (
|
|
lowerCommit.startsWith('fix:') ||
|
|
lowerCommit.startsWith('perf:') ||
|
|
lowerCommit.startsWith('security:') ||
|
|
lowerCommit.startsWith('patch:') ||
|
|
lowerCommit.startsWith('refactor:')
|
|
) {
|
|
hasPatch = true;
|
|
}
|
|
}
|
|
|
|
if (hasBreaking) return 'major';
|
|
if (hasFeature) return 'minor';
|
|
if (hasPatch) return 'patch';
|
|
|
|
// Par défaut, patch si on a des commits mais aucun type spécifique
|
|
return commits.length > 0 ? 'patch' : 'patch';
|
|
}
|
|
|
|
function incrementVersion(
|
|
current: Version,
|
|
type: 'major' | 'minor' | 'patch'
|
|
): Version {
|
|
switch (type) {
|
|
case 'major':
|
|
return { major: current.major + 1, minor: 0, patch: 0 };
|
|
case 'minor':
|
|
return { major: current.major, minor: current.minor + 1, patch: 0 };
|
|
case 'patch':
|
|
return {
|
|
major: current.major,
|
|
minor: current.minor,
|
|
patch: current.patch + 1,
|
|
};
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const silent = process.argv.includes('--silent');
|
|
const hookMode = process.argv.includes('--hook');
|
|
|
|
try {
|
|
const packagePath = join(process.cwd(), 'package.json');
|
|
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
|
const currentVersion = parseVersion(packageJson.version);
|
|
|
|
const lastTag = getLastVersionTag();
|
|
const commits = getCommitsSinceTag(lastTag);
|
|
|
|
if (commits.length === 0) {
|
|
if (!silent) {
|
|
console.log('✅ Aucun nouveau commit depuis la dernière version');
|
|
console.log(`Version actuelle: ${packageJson.version}`);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const bumpType = determineVersionBump(commits);
|
|
const newVersion = incrementVersion(currentVersion, bumpType);
|
|
const newVersionString = formatVersion(newVersion);
|
|
|
|
// Si la version n'a pas changé, ne rien faire
|
|
if (newVersionString === packageJson.version) {
|
|
return;
|
|
}
|
|
|
|
if (!silent) {
|
|
console.log(`📊 Analyse des commits depuis ${lastTag || 'le début'}:`);
|
|
console.log(` - ${commits.length} commit(s) trouvé(s)`);
|
|
console.log(` - Type de bump détecté: ${bumpType}`);
|
|
console.log(` - Version actuelle: ${packageJson.version}`);
|
|
console.log(` - Nouvelle version: ${newVersionString}`);
|
|
|
|
// Afficher les commits pertinents
|
|
console.log('\n📝 Commits analysés:');
|
|
commits.slice(0, 10).forEach((commit) => {
|
|
console.log(` - ${commit}`);
|
|
});
|
|
if (commits.length > 10) {
|
|
console.log(` ... et ${commits.length - 10} autre(s) commit(s)`);
|
|
}
|
|
}
|
|
|
|
// Mettre à jour package.json
|
|
packageJson.version = newVersionString;
|
|
writeFileSync(packagePath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
|
|
if (!silent) {
|
|
console.log(`\n✅ Version mise à jour dans package.json`);
|
|
console.log(
|
|
`\n💡 Prochaines étapes:` +
|
|
`\n 1. git add package.json` +
|
|
`\n 2. git commit -m "chore: bump version to ${newVersionString}"` +
|
|
`\n 3. git tag v${newVersionString}`
|
|
);
|
|
} else if (hookMode) {
|
|
// En mode hook, ajouter package.json au staging
|
|
try {
|
|
execSync('git add package.json', { stdio: 'ignore' });
|
|
} catch {
|
|
// Ignorer les erreurs en mode hook
|
|
}
|
|
}
|
|
} catch (error) {
|
|
if (!silent) {
|
|
console.error('❌ Erreur lors de la mise à jour de version:', error);
|
|
}
|
|
if (!hookMode) {
|
|
process.exit(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
main();
|