patch.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * @Author: liyxt
  3. * @Date: 2019-12-09 19:54:41
  4. * @LastEditors : liyxt
  5. * @LastEditTime : 2019-12-31 09:44:54
  6. * @Description: file content
  7. */
  8. const configJSON = require('../new-config.json');
  9. const fs = require('fs');
  10. const {resolve, join, sep} = require('path');
  11. const {spawn} = require('child_process');
  12. const yazl = require('yazl');
  13. const build = require('./nrb');
  14. const prompts = require('prompts');
  15. let zipfile = new yazl.ZipFile();
  16. let patchConfig = configJSON.patch || {};
  17. let args = [...process.argv];
  18. args.splice(0, 2);
  19. // 先删除dist目录
  20. delDir('./dist');
  21. delDir('./patch');
  22. // windows下npm执行名不同
  23. const ls = spawn(process.platform === 'win32' ? 'npm.cmd' : 'npm', [
  24. 'run',
  25. 'build',
  26. 'patch',
  27. ...args
  28. ]);
  29. ls.stdout.on('data', data => {
  30. if (data.includes('ERROR')) {
  31. throw new Error(data);
  32. } else {
  33. data && console.log(`${data}`);
  34. }
  35. });
  36. ls.stderr.on('data', data => {
  37. if (data.includes('ERROR')) {
  38. throw new Error(data);
  39. } else {
  40. data && console.log(`${data}`);
  41. }
  42. });
  43. ls.on('close', async code => {
  44. // 加入到zip入口
  45. addEntry(resolve(__dirname, '../dist'));
  46. // 动态修改xml
  47. let xmlconfig = {
  48. id: uuid(),
  49. provider: patchConfig.provider,
  50. department: patchConfig.department,
  51. needRecreatedLoginJar: false,
  52. needDeploy: false,
  53. time: dateFormat('YYYY-mm-dd HH:MM:SS', new Date())
  54. };
  55. let xml = fs.readFileSync(resolve(__dirname, './packmetadata.xml'), 'utf-8');
  56. Object.entries(xmlconfig).forEach(([key, value]) => {
  57. xml = xml.replace(`<!-- ${key} -->`, `<${key}>${value}</${key}>`);
  58. });
  59. fs.writeFileSync(resolve(__dirname, '../dist/packmetadata.xml'), xml, 'utf-8');
  60. zipfile.addFile('./dist/packmetadata.xml', 'packmetadata.xml');
  61. // await addReadMe(xmlconfig)
  62. zipfile.outputStream.pipe(fs.createWriteStream(`patch_${patchConfig['version']}_${patchConfig['name']}_${new Date().getTime()}.zip`)).on('close', function () {
  63. console.log('补丁已出!');
  64. });
  65. zipfile.end();
  66. });
  67. async function addReadMe(config) {
  68. let response;
  69. try {
  70. response = await prompts([{
  71. type: 'text',
  72. name: 'name',
  73. message: '请输入补丁名称:',
  74. }, {
  75. type: 'text',
  76. name: 'version',
  77. message: '请输入产品版本:',
  78. }, {
  79. type: 'text',
  80. name: 'module',
  81. message: '请输入补丁修改模块:',
  82. }], {
  83. onCancel: () => {
  84. throw new Error('Operation cancelled')
  85. }
  86. });
  87. } catch (cancelled) {
  88. console.log(cancelled.message)
  89. return;
  90. }
  91. patchConfig['name'] = response.name;
  92. patchConfig['version'] = response.version;
  93. let content = "\r\n==============================================================================\r\n" +
  94. "1)补丁基本信息\r\n" +
  95. "==============================================================================\r\n" +
  96. "\r\n 补丁名称 - " + (response.name || '修改补丁') + "\r\n" +
  97. " 补丁编号 - " + (config.id) + "\r\n" +
  98. " 产品版本 - " + (response.version || '2111') + "\r\n" +
  99. " 补丁修改模块 - " + (response.module || 'hrhi') + "\r\n" +
  100. " 补丁依赖信息 - 无\r\n" +
  101. " 适用的中间件平台 - Weblogic,Websphere 7.0,Yonyou Middleware V5,Yonyou Middleware V6\r\n" +
  102. " 适用的操作系统平台 - Linux,Windows,AIX,Solaris\r\n" +
  103. " 适用的数据库平台 - DB2 V9.7,SQL Server 2008 R2,Oracle 10,Oracle 11\r\n" +
  104. " 补丁创建时间 - " + (config.time) + "\r\n" +
  105. " 是否需要部署 - false\r\n" +
  106. " 是否需要重新生成客户端Applet Jar包 - false\r\n" +
  107. "\r\n==============================================================================\r\n" +
  108. "2)补丁安装步骤说明\r\n" +
  109. "==============================================================================\r\n" +
  110. "\r\n 补丁安装前置准备工作(比如数据备份)\r\n" +
  111. " ======================================================================\r\n" +
  112. " 无\r\n" +
  113. "\r\n 补丁安装\r\n" +
  114. " ======================================================================\r\n" +
  115. " 无\r\n" +
  116. "\r\n 补丁安装后置工作\r\n" +
  117. " ======================================================================\r\n" +
  118. " 清缓存\r\n" +
  119. "\r\n 补丁安装成功的验证工作\r\n" +
  120. " ======================================================================\r\n" +
  121. " 无\r\n" +
  122. "\r\n 其它信息\r\n" +
  123. " ======================================================================\r\n" +
  124. " 无\r\n" +
  125. "\r\n==============================================================================\r\n" +
  126. "3)补丁修复bug列表说明:" + (response.name || '修改补丁') + "\r\n" +
  127. "=============================================================================="
  128. fs.writeFileSync(resolve(__dirname, '../dist/readme.txt'), content, 'utf-8');
  129. zipfile.addFile('./dist/readme.txt', 'readme.txt');
  130. }
  131. function delDir(path) {
  132. let files = [];
  133. if (fs.existsSync(path)) {
  134. files = fs.readdirSync(path);
  135. files.forEach(file => {
  136. let curPath = path + '/' + file;
  137. if (fs.statSync(curPath).isDirectory()) {
  138. delDir(curPath); //递归删除文件夹
  139. } else {
  140. fs.unlinkSync(curPath); //删除文件
  141. }
  142. });
  143. fs.rmdirSync(path);
  144. }
  145. }
  146. function uuid() {
  147. var s = [];
  148. var hexDigits = '0123456789abcdef';
  149. for (var i = 0; i < 36; i++) {
  150. s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  151. }
  152. s[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010
  153. s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
  154. s[8] = s[13] = s[18] = s[23] = '-';
  155. var uuid = s.join('');
  156. return uuid;
  157. }
  158. function addEntry(prefix = './dist') {
  159. //读取目录
  160. var paths = fs.readdirSync(prefix);
  161. paths.forEach(function (path) {
  162. var from = join(prefix, path);
  163. var st = fs.statSync(from);
  164. if (st.isFile()) {
  165. zipfile.addFile(from, join('replacement/hotwebs/nccloud/resources/', from.split(`${sep}dist${sep}`)[1]));
  166. } else if (st.isDirectory()) {
  167. addEntry(from);
  168. }
  169. });
  170. }
  171. function dateFormat(fmt, date) {
  172. let ret;
  173. let opt = {
  174. 'Y+': date.getFullYear().toString(), // 年
  175. 'm+': (date.getMonth() + 1).toString(), // 月
  176. 'd+': date.getDate().toString(), // 日
  177. 'H+': date.getHours().toString(), // 时
  178. 'M+': date.getMinutes().toString(), // 分
  179. 'S+': date.getSeconds().toString() // 秒
  180. // 有其他格式化字符需求可以继续添加,必须转化成字符串
  181. };
  182. for (let k in opt) {
  183. ret = new RegExp('(' + k + ')').exec(fmt);
  184. if (ret) {
  185. fmt = fmt.replace(ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, '0'));
  186. }
  187. }
  188. return fmt;
  189. }