生成压缩包并上传指定分支自动化脚本
- 2019 年 10 月 5 日
- 筆記
生成压缩包并上传指定分支自动化脚本
业务需求
- 项目测试或部署上线时,需要从主分支拉取打包后的压缩包
- 当前存在开发分支
dev
, 主分支marster
, 当处于开发分支时,执行脚本命令zip
自动完成 ,压缩包生成, 分支切换, 文件更新及提交
执行流程
graph TD 生成压缩包 --> 保存压缩包到缓存目录 保存压缩包到缓存目录 --> 切换到主分支 切换到主分支 --> 将缓存拷贝到主分支目录 将缓存拷贝到主分支目录 --> 提交 提交 --> 切回开发分支 切回开发分支 --> 删除缓存 删除缓存 --> 保存新版本信息
脚本目录
- 当前以vue 项目为例
- root - script - index.js // 入口 - createZip.js // 生成压缩包 - cmmds.js // 执行git命令 - utils.js // 工具包 - version.js // 版本更新 - color.js // 信息输出 - config.json // 配置文件
源码
- /createZip.js
/** * 创建压缩包 */ const fs = require('fs') const archiver = require('archiver') const events = { warning(err){ console.log(`warning: ${err}`) }, error(err){ console.log(`error: ${err}`) } } /** * 新建zip压缩包 * @param { string } entryPath 被打包文件地址 * @param { string } outPath 打包输出地址 */ function createZip(entryPath, outPath){ const outBuff = fs.createWriteStream(outPath) const archive = archiver('zip', { zlib: { level: 9 } }) Object.entries(events).map(({key, fn}) => archive[key] = fn ) archive.pipe(outBuff); archive.directory(entryPath, false) archive.finalize() } module.exports = { createZip }
- /cmmds.js
const util = require('util') const exec = util.promisify(require('child_process').exec); function splitLineFeed(str){ return str.split('n') } function loopPrint(str){ splitLineFeed(str).map(item => console.log(item)) } /** * 命令仓库 */ class Commds{ constructor(){ this.commds = [] } /** * 注册命令 * 参数参考 node child_process/exec */ register(cmmd, options, callback){ // 调整参数 if(typeof options === 'function'){ callback = options options = null } if(Array.isArray(cmmd)){ this.cmmds.concat(cmmd) }else{ this.commds.push({ cmmd, options, callback }) } return this } /** * 按顺序调用命令 */ run(){ return this.commds.reduce((acc, next) => acc.then(() => exec(next['cmmd'], next['options']).then(next['callback']) ), Promise.resolve() ) } /** * 清空命令 */ clear(){ this.commds = [] } /** * 非 new 新建对象 */ static of(){ return new Commds() } } module.exports = { splitLineFeed, loopPrint, Commds }
- /utils.js
const fs = require('fs') const util = require('util') const path = require('path') const { printSuccess } = require('./color') /** * 拷贝文件 * @param { string } source 原文件路径 * @param { string } target 目标文件路径 */ function copyFile(source, target){ source = path.resolve(__dirname, source) target = path.resolve(__dirname, target) return () => util.promisify(fs.copyFile)(source,target).then(() => printSuccess(`copy success from ${source} to ${target}`) ) } /** * 删除文件 * @param { string } filePath 文件路径 */ function delFile(filePath){ return () => util.promisify(fs.unlink)(filePath) } /** * 写入配置 * @param { string } path 保存路径 * @param { json } data 保存数据 */ function updateConfig(path, data){ return util.promisify(fs.writeFile)(path, JSON.stringify(data,null, 2), {flag:'w',encoding:'utf-8',mode:'0666'}).then(() => printSuccess('save config')) } module.exports = { copyFile, delFile, updateConfig }
- /version.js
/** * 版本更新 * @param { string } version 版本号 0.0.1 */ function updateVersion(version, separator='.'){ const nums = String.prototype.split.apply(version, [separator]) nums.push(parseInt(nums.pop()) + 1) return nums.join(separator) } module.exports = { updateVersion }
- /color.js
const chalk = require('chalk') /** * 彩色提示 */ function print(msg, type='green'){ console.log('>>>', chalk[type](msg)) } function printError(error){ print(error, 'res') } function printSuccess(msg){ print(msg, 'green') } function printWarning(warning){ print(warning, 'yellow') } module.exports = { print, printError, printSuccess, printWarning }
- /index.js
const path = require('path') const config = require('./config.json') const { printError, printSuccess } = require('./color') const { createZip } = require('./createZip') const { zip } = config const { Commds } = require('./cmmds') const { updateVersion } = require('./version') const { copyFile, delFile, updateConfig } = require('./utils') const newVersion = updateVersion(config.varsion) const checkoutToMarster = Commds.of().register(`git checkout ${zip.masterBranch}`, () =>printSuccess(`checkout to ${zip.masterBranch}`)) const updateMarster = Commds.of().register(`git add *`).register(`git commit -m "${newVersion}"`).register(`git push`, () => printSuccess('push success')) const checkoutToDev = Commds.of().register(`git checkout ${zip.devBranch}`, () => printSuccess(`checkout to ${zip.devBranch}`)) const newConfig = Object.assign({}, config, { varsion: newVersion, lastTime: new Date() }) createZip(zip.entry, zip.catch) checkoutToMarster.run() .then(copyFile(zip.catch, zip.out)) // 将打包文件拷贝到主分支目录 .then(() => updateMarster.run()) // 提交文件 .then(() => checkoutToDev.run()) // 切回开发分支 .then(delFile(zip.catch)) // 删除打包文件 .then(() => printSuccess(`remove catch from ${zip.catch}`)) .then(() => updateConfig(path.resolve(__dirname, './config.json'), newConfig)) // 保存版本信息 .catch(printError)
- package.json 配置执行命令
{ ... "scripts":{ "zip": "node ./script" } }
总结
最初的想法,希望在开发分支生成压缩包后,通过checkout [branch] [file]
合并文件,但切换分支时,因为生成了新文件,需要保存更新。所以改用将压缩包生成到项目目录外的方式。后期应该会改用临时文件的方式。当前脚本只是对 vue 打包后的文件做压缩上传, 通过 webpack hook 可以将打包压缩继承到一起。