Kode-cli/scripts/publish-release.js
2025-08-31 02:16:59 +08:00

159 lines
5.3 KiB
JavaScript
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
const { execSync } = require('child_process');
const { readFileSync, writeFileSync } = require('fs');
const path = require('path');
const readline = require('readline');
/**
* 发布正式版本到 npm
* 使用 latest tag支持语义化版本升级
*/
async function publishRelease() {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const question = (query) => new Promise(resolve => rl.question(query, resolve));
try {
console.log('🚀 Starting production release process...\n');
// 1. 确保在主分支
const currentBranch = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
if (currentBranch !== 'main' && currentBranch !== 'master') {
console.log('⚠️ Not on main/master branch. Current branch:', currentBranch);
const proceed = await question('Continue anyway? (y/N): ');
if (proceed.toLowerCase() !== 'y') {
console.log('❌ Cancelled');
process.exit(0);
}
}
// 2. 检查工作区是否干净
try {
execSync('git diff --exit-code', { stdio: 'ignore' });
execSync('git diff --cached --exit-code', { stdio: 'ignore' });
console.log('✅ Working directory is clean');
} catch {
console.log('❌ Working directory has uncommitted changes');
console.log('Please commit or stash your changes before releasing');
process.exit(1);
}
// 3. 拉取最新代码
console.log('📡 Pulling latest changes...');
execSync('git pull origin ' + currentBranch, { stdio: 'inherit' });
// 4. 读取当前版本
const packagePath = path.join(process.cwd(), 'package.json');
const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
const currentVersion = packageJson.version;
console.log(`📦 Current version: ${currentVersion}`);
// 5. 选择版本升级类型
console.log('\n🔢 Version bump options:');
const versionParts = currentVersion.split('.');
const major = parseInt(versionParts[0]);
const minor = parseInt(versionParts[1]);
const patch = parseInt(versionParts[2]);
console.log(` 1. patch → ${major}.${minor}.${patch + 1} (bug fixes)`);
console.log(` 2. minor → ${major}.${minor + 1}.0 (new features)`);
console.log(` 3. major → ${major + 1}.0.0 (breaking changes)`);
console.log(` 4. custom → enter custom version`);
const choice = await question('\nSelect version bump (1-4): ');
let newVersion;
switch (choice) {
case '1':
newVersion = `${major}.${minor}.${patch + 1}`;
break;
case '2':
newVersion = `${major}.${minor + 1}.0`;
break;
case '3':
newVersion = `${major + 1}.0.0`;
break;
case '4':
newVersion = await question('Enter custom version: ');
break;
default:
console.log('❌ Invalid choice');
process.exit(1);
}
// 6. 确认发布
console.log(`\n📋 Release Summary:`);
console.log(` Current: ${currentVersion}`);
console.log(` New: ${newVersion}`);
console.log(` Branch: ${currentBranch}`);
console.log(` Tag: latest`);
const confirm = await question('\n🤔 Proceed with release? (y/N): ');
if (confirm.toLowerCase() !== 'y') {
console.log('❌ Cancelled');
process.exit(0);
}
// 7. 更新版本号
console.log('📝 Updating version...');
packageJson.version = newVersion;
writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
// 8. 运行测试
console.log('🧪 Running tests...');
try {
execSync('npm run typecheck', { stdio: 'inherit' });
execSync('npm test', { stdio: 'inherit' });
} catch (error) {
console.log('❌ Tests failed, rolling back version...');
packageJson.version = currentVersion;
writeFileSync(packagePath, JSON.stringify(packageJson, null, 2));
process.exit(1);
}
// 9. 构建项目
console.log('🔨 Building project...');
execSync('npm run build', { stdio: 'inherit' });
// 10. 运行预发布检查
console.log('🔍 Running pre-publish checks...');
execSync('node scripts/prepublish-check.js', { stdio: 'inherit' });
// 11. 提交版本更新
console.log('📝 Committing version update...');
execSync('git add package.json');
execSync(`git commit -m "chore: bump version to ${newVersion}"`);
// 12. 创建 git tag
console.log('🏷️ Creating git tag...');
execSync(`git tag -a v${newVersion} -m "Release ${newVersion}"`);
// 13. 发布到 npm
console.log('📤 Publishing to npm...');
execSync('npm publish --access public', { stdio: 'inherit' });
// 14. 推送到 git
console.log('📡 Pushing to git...');
execSync(`git push origin ${currentBranch}`);
execSync(`git push origin v${newVersion}`);
console.log('\n🎉 Production release published successfully!');
console.log(`📦 Version: ${newVersion}`);
console.log(`🔗 Install with: npm install -g @shareai-lab/kode`);
console.log(`🔗 Or: npm install -g @shareai-lab/kode@${newVersion}`);
console.log(`📊 View on npm: https://www.npmjs.com/package/@shareai-lab/kode`);
} catch (error) {
console.error('❌ Production release failed:', error.message);
process.exit(1);
} finally {
rl.close();
}
}
publishRelease();