Files
2026-06-01 13:43:09 +08:00

192 lines
5.8 KiB
JavaScript

#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')
const rootDir = path.resolve(__dirname, '..')
function readJson(relPath) {
return JSON.parse(fs.readFileSync(path.join(rootDir, relPath), 'utf8'))
}
function writeJson(relPath, data) {
fs.writeFileSync(path.join(rootDir, relPath), JSON.stringify(data, null, 2) + '\n')
}
function run(cmd, options = {}) {
execSync(cmd, { stdio: 'inherit', cwd: rootDir, ...options })
}
function runQuiet(cmd) {
return execSync(cmd, { encoding: 'utf8', cwd: rootDir }).trim()
}
const SEMVER_RE = /^\d+\.\d+\.\d+$/
const args = process.argv.slice(2)
let newVersion = null
for (const arg of args) {
if (arg === '--patch' || arg === '--minor' || arg === '--major') {
const rootPkg = readJson('package.json')
const parts = rootPkg.version.split('.').map(Number)
if (arg === '--patch') { parts[2]++; }
else if (arg === '--minor') { parts[1]++; parts[2] = 0; }
else if (arg === '--major') { parts[0]++; parts[1] = 0; parts[2] = 0; }
newVersion = parts.join('.')
} else if (SEMVER_RE.test(arg)) {
newVersion = arg
}
}
if (!newVersion) {
console.error('❌ 请指定版本号')
console.log('')
console.log('用法:')
console.log(' pnpm release <version> 指定版本号,如 pnpm release 1.3.0')
console.log(' pnpm release --patch 递增补丁版本 1.2.1 → 1.2.2')
console.log(' pnpm release --minor 递增次版本 1.2.1 → 1.3.0')
console.log(' pnpm release --major 递增主版本 1.2.1 → 2.0.0')
process.exit(1)
}
const tag = `v${newVersion}`
console.log('==========================================')
console.log(` XAGI Frontend Templates Release`)
console.log(` Target version: ${newVersion}`)
console.log(` Tag: ${tag}`)
console.log('==========================================')
console.log('')
// 1. Check working tree clean
try {
const status = runQuiet('git status --porcelain')
if (status) {
console.error('❌ 工作区有未提交的变更,请先 commit 或 stash')
console.log(status)
process.exit(1)
}
} catch {
console.error('❌ 无法检查 git 状态')
process.exit(1)
}
// 2. Check tag doesn't already exist
const existingTags = runQuiet('git tag -l').split('\n').filter(Boolean)
if (existingTags.includes(tag)) {
console.error(`❌ Tag ${tag} 已存在`)
process.exit(1)
}
// 3. Update all version numbers
console.log('📝 更新版本号...')
const templateSpecs = [
{ id: 'react-vite', packagePath: 'packages/react-vite/package.json', metaPath: 'packages/react-vite/meta.json' },
{ id: 'vue3-vite', packagePath: 'packages/vue3-vite/package.json', metaPath: 'packages/vue3-vite/meta.json' },
{ id: 'react-next', packagePath: 'packages/react-next/package.json', metaPath: 'packages/react-next/meta.json' },
]
// Update root package.json
const rootPkg = readJson('package.json')
rootPkg.version = newVersion
writeJson('package.json', rootPkg)
console.log(` ✓ root package.json → ${newVersion}`)
// Update templates.json
const templatesRegistry = readJson('templates.json')
templatesRegistry.version = newVersion
templatesRegistry.updatedAt = new Date().toISOString()
for (const spec of templateSpecs) {
const entry = templatesRegistry.templates.find(t => t.id === spec.id)
if (entry) {
entry.version = newVersion
console.log(` ✓ templates.json[${spec.id}] → ${newVersion}`)
}
}
writeJson('templates.json', templatesRegistry)
// Update each template package.json and meta.json
for (const spec of templateSpecs) {
const pkg = readJson(spec.packagePath)
pkg.version = newVersion
writeJson(spec.packagePath, pkg)
console.log(`${spec.packagePath}${newVersion}`)
const meta = readJson(spec.metaPath)
meta.version = newVersion
writeJson(spec.metaPath, meta)
console.log(`${spec.metaPath}${newVersion}`)
}
console.log('')
// 4. Run version consistency check
console.log('🔍 校验版本一致性...')
try {
run('node scripts/check-versions.js')
console.log('✅ 版本一致性校验通过')
} catch {
console.error('❌ 版本一致性校验失败')
process.exit(1)
}
console.log('')
// 5. Git commit
console.log('📦 创建 release commit...')
try {
run('git add package.json templates.json latest.json packages/*/package.json packages/*/meta.json')
run(`git commit -m "release: ${tag}"`)
console.log(` ✓ Committed: release: ${tag}`)
} catch {
console.error('❌ Git commit 失败')
process.exit(1)
}
console.log('')
// 6. Git tag
console.log(`🏷️ 创建 tag: ${tag}...`)
try {
run(`git tag -a ${tag} -m "Release ${tag}"`)
console.log(` ✓ Tag created: ${tag}`)
} catch {
console.error('❌ Git tag 创建失败')
process.exit(1)
}
console.log('')
// 7. Push
console.log('🚀 推送到远程...')
try {
run('git push')
run(`git push origin ${tag}`)
console.log(' ✓ Pushed commit and tag')
} catch {
console.error('❌ Push 失败')
console.log('')
console.log('你可以手动执行:')
console.log(` git push`)
console.log(` git push origin ${tag}`)
process.exit(1)
}
console.log('')
console.log('==========================================')
console.log(' ✅ Release 流程完成!')
console.log('==========================================')
console.log('')
console.log(` 版本: ${newVersion}`)
console.log(` Tag: ${tag}`)
console.log('')
console.log(' GitHub Actions 将自动:')
console.log(' 1. 打包所有模板')
console.log(' 2. 创建 GitHub Release')
console.log(' 3. 上传 zip 文件')
console.log(' 4. 更新 latest.json')
console.log('')
console.log(' 下载地址:')
console.log(` https://github.com/nuwax-ai/xagi-frontend-templates/releases/tag/${tag}`)
console.log(` https://raw.githubusercontent.com/nuwax-ai/xagi-frontend-templates/main/latest.json`)
console.log('')