diff --git a/package.json b/package.json index 222cff1..f31d1a9 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "export": "next build && next export", "eslint": "eslint src/ --ext .ts,.tsx,.js,.jsx --fix --cache", "stylelint": "stylelint 'src/**/*.less' 'src/**/*.css' --fix --cache", - "pre-commit": "pretty-quick --staged && npm run eslint && npm run stylelint" + "pre-commit": "pretty-quick --staged && npm run eslint && npm run stylelint", + "deploy": "node scripts/merge-to-production.js" }, "dependencies": { "@antv/data-set": "^0.11.8", diff --git a/scripts/merge-to-production.js b/scripts/merge-to-production.js new file mode 100644 index 0000000..d3583b0 --- /dev/null +++ b/scripts/merge-to-production.js @@ -0,0 +1,119 @@ +#!/usr/bin/env node + +const { execSync } = require('child_process'); + +const COLORS = { + red: '\x1b[31m', + green: '\x1b[32m', + yellow: '\x1b[33m', + cyan: '\x1b[36m', + reset: '\x1b[0m' +}; + +function log(message, color = 'reset') { + console.log(`${COLORS[color]}${message}${COLORS.reset}`); +} + +function exec(command, options = {}) { + try { + return execSync(command, { encoding: 'utf-8', stdio: options.silent ? 'pipe' : 'inherit', ...options }); + } catch (error) { + if (options.ignoreError) { + return error.stdout || ''; + } + throw error; + } +} + +function run() { + log('\n========================================', 'cyan'); + log(' 合并 master 到 production 分支', 'cyan'); + log('========================================\n', 'cyan'); + + // 1. 检查是否有未提交的更改 + log('>>> 检查工作区状态...', 'yellow'); + const status = exec('git status --porcelain', { silent: true }); + if (status.trim()) { + log('\n错误: 工作区有未提交的更改,请先提交或暂存', 'red'); + log('运行 git status 查看详情\n', 'red'); + process.exit(1); + } + log('工作区干净\n', 'green'); + + // 2. 获取当前分支名 + const currentBranch = exec('git branch --show-current', { silent: true }).trim(); + log(`当前分支: ${currentBranch}\n`, 'cyan'); + + // 3. 拉取最新代码 + log('>>> 拉取远程最新代码...', 'yellow'); + try { + exec('git fetch origin'); + } catch (error) { + log('\n错误: 拉取远程代码失败', 'red'); + process.exit(1); + } + log('拉取完成\n', 'green'); + + // 4. 切换到 master 并更新 + log('>>> 切换到 master 分支并更新...', 'yellow'); + try { + exec('git checkout master'); + exec('git pull origin master'); + } catch (error) { + log('\n错误: 更新 master 分支失败', 'red'); + process.exit(1); + } + log('master 分支已更新\n', 'green'); + + // 5. 切换到 production 并更新 + log('>>> 切换到 production 分支并更新...', 'yellow'); + try { + exec('git checkout production'); + exec('git pull origin production'); + } catch (error) { + log('\n错误: 更新 production 分支失败,分支可能不存在', 'red'); + log('请先创建 production 分支: git checkout -b production\n', 'yellow'); + exec(`git checkout ${currentBranch}`, { ignoreError: true }); + process.exit(1); + } + log('production 分支已更新\n', 'green'); + + // 6. 合并 master 到 production + log('>>> 合并 master 到 production...', 'yellow'); + try { + exec('git merge master --no-edit'); + } catch (error) { + log('\n错误: 合并过程中发生冲突!', 'red'); + log('请手动解决冲突后再提交', 'red'); + log('\n冲突文件:', 'yellow'); + exec('git diff --name-only --diff-filter=U', { ignoreError: true }); + log('\n解决冲突后运行:', 'yellow'); + log(' git add .', 'cyan'); + log(' git commit', 'cyan'); + log(' git push origin production\n', 'cyan'); + log('或放弃合并:', 'yellow'); + log(' git merge --abort\n', 'cyan'); + process.exit(1); + } + log('合并成功\n', 'green'); + + // 7. 推送到远程 + log('>>> 推送到远程 production 分支...', 'yellow'); + try { + exec('git push origin production'); + } catch (error) { + log('\n错误: 推送失败', 'red'); + process.exit(1); + } + log('推送成功\n', 'green'); + + // 8. 切换回原分支 + log(`>>> 切换回原分支 ${currentBranch}...`, 'yellow'); + exec(`git checkout ${currentBranch}`, { ignoreError: true }); + + log('\n========================================', 'green'); + log(' master 已成功合并到 production!', 'green'); + log('========================================\n', 'green'); +} + +run();