upload.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. const simpleGit = require('simple-git');
  2. // const path = require('path');
  3. const axios = require('axios');
  4. const DINGTALK_WEBHOOK = 'https://oapi.dingtalk.com/robot/send?access_token=54b7c152d185a3b6220b444d366490ecf45876c7fa64e3bf4ab55fc9d1d5190e'
  5. const SECRET = 'SEC058cffe27061581bde3d42b4a610179c04cdc296f4e7dee1af510803c49af5a0'
  6. // 钉钉消息格式
  7. // const message = {
  8. // msgtype: 'markdown',
  9. // markdown: {
  10. // title: '前端项目构建通知',
  11. // text: `### 前端项目构建完成\n` +
  12. // `- 项目: ${process.env.npm_package_name}\n` +
  13. // `- 版本: ${process.env.npm_package_version}\n` +
  14. // `- 环境: ${process.env.NODE_ENV || 'production'}\n` +
  15. // `- 时间: ${new Date().toLocaleString()}\n` +
  16. // `- 状态: 成功 ✅\n\n`
  17. // }
  18. // };
  19. const message2 = {
  20. 'at': {
  21. 'atMobiles': [
  22. '13717881619'
  23. ],
  24. 'atUserIds': [
  25. ],
  26. 'isAtAll': false
  27. },
  28. 'text': {
  29. 'content': '大数据平台前端页面打包上传完成,请发版!\n'
  30. },
  31. 'msgtype': 'text'
  32. }
  33. function send(webhook, data) {
  34. axios.post(webhook, data)
  35. .then(response => {
  36. if (response.data.errcode !== 0) {
  37. console.error('发送钉钉通知失败', response.data);
  38. process.exit(1);
  39. } else {
  40. console.log('钉钉通知发送成功');
  41. }
  42. })
  43. .catch(error => {
  44. console.error('发送钉钉通知时出错', error.message);
  45. process.exit(1);
  46. });
  47. }
  48. function sendDingTalk() {
  49. if (SECRET) {
  50. const timestamp = Date.now();
  51. const sign = generateSign(SECRET, timestamp);
  52. send(`${DINGTALK_WEBHOOK}&timestamp=${timestamp}&sign=${sign}`, message2);
  53. } else {
  54. send(DINGTALK_WEBHOOK, message2);
  55. }
  56. }
  57. // 生成加签
  58. function generateSign(secret, timestamp) {
  59. const crypto = require('crypto');
  60. const str = timestamp + '\n' + secret;
  61. const hmac = crypto.createHmac('sha256', secret);
  62. hmac.update(str);
  63. return encodeURIComponent(hmac.digest('base64'));
  64. }
  65. // ==================== 配置参数 ====================
  66. const CONFIG = {
  67. // 仓库2的本地路径(即项目A的 dist 目录,必填)
  68. repo2LocalPath: 'F:\\project\\bigdata_vue_frond', // 假设 dist 是项目A的输出目录
  69. // 仓库2的远程地址(必填,如 GitHub 私有仓库用 HTTPS 或 SSH)
  70. repo2Remote: 'http://code.nyzhwlw.com:10202/bd_vue_org/bigdata_vue_frond.git',
  71. // 仓库2的目标分支(必填,如 main、gh-pages)
  72. targetBranch: 'master',
  73. // 提交信息(可选,默认动态生成)
  74. commitMsg: `Auto commit: ${new Date().toLocaleString()}`
  75. };
  76. // ==================================================
  77. // 初始化 Git 实例(指向仓库2的本地路径)
  78. const git = simpleGit({
  79. baseDir: CONFIG.repo2LocalPath,
  80. maxConcurrentProcesses: 1
  81. });
  82. /**
  83. * 主函数:执行全流程
  84. */
  85. async function main() {
  86. try {
  87. // 步骤 1:检查仓库2的本地路径是否存在且是 Git 仓库
  88. if (!await isGitRepository(CONFIG.repo2LocalPath)) {
  89. throw new Error(`❌ 仓库2的本地路径不存在或不是 Git 仓库:${CONFIG.repo2LocalPath}`);
  90. }
  91. // 步骤 2:切换到仓库2目录并拉取最新代码
  92. await pullLatestCode();
  93. // 步骤 3:检测仓库2中是否有新变更(由项目A打包生成)
  94. const hasChanges = await checkForChanges();
  95. if (!hasChanges) {
  96. console.log('\x1b[33mℹ️ 无变更需要提交,跳过操作。\x1b[0m');
  97. return;
  98. }
  99. // 步骤 4:提交并推送至仓库2
  100. await commitAndPush();
  101. console.log('\x1b[32m✅ 操作成功!\x1b[0m');
  102. console.log(`仓库2的 ${CONFIG.targetBranch} 分支已更新。`);
  103. // 发送到钉钉
  104. sendDingTalk()
  105. } catch (error) {
  106. console.error('\x1b[31m❌ 操作失败!\x1b[0m');
  107. console.error(error.message);
  108. process.exit(1);
  109. }
  110. }
  111. /**
  112. * 检查路径是否是 Git 仓库(通过 .git 目录判断)
  113. */
  114. async function isGitRepository(dirPath) {
  115. try {
  116. await simpleGit(dirPath).checkIsRepo();
  117. return true;
  118. } catch (e) {
  119. return false;
  120. }
  121. }
  122. /**
  123. * 拉取仓库2的远程最新代码
  124. */
  125. async function pullLatestCode() {
  126. console.log('🔄 正在拉取仓库2的远程最新代码...');
  127. await git.pull('origin', CONFIG.targetBranch);
  128. }
  129. /**
  130. * 检测仓库2中是否有新变更(由项目A打包生成)
  131. */
  132. async function checkForChanges() {
  133. console.log('🔍 检测仓库2中是否有新变更...');
  134. const status = await git.status();
  135. return status.files.length > 0; // 有文件变更则返回 true
  136. }
  137. /**
  138. * 提交并推送至仓库2的远程
  139. */
  140. async function commitAndPush() {
  141. console.log('🔄 提交并推送变更到仓库2...');
  142. // 添加所有变更文件
  143. await git.add('./*');
  144. // 提交(确保有变更)
  145. const status = await git.status();
  146. if (!status.files.length) {
  147. throw new Error('❌ 无变更需要提交(可能仓库2内容与远程一致)');
  148. }
  149. await git.commit(CONFIG.commitMsg);
  150. // 推送至远程分支(-u 关联本地与远程分支)
  151. await git.push('-u', 'origin', CONFIG.targetBranch);
  152. }
  153. // 执行主函数
  154. main();