For a period of time, the focus of work was focused on the development of the official account. Although the team had automatic deployment like Jenkins, it sometimes needed repeated release tests to solve compatibility problems, and deployment tools like warehouse would cause a lot of unnecessary submission information, hence this article.
The capabilities of the ideal deployment tool
- Based on the current team’s development, the deployment tool usually requires the release of a packaged Webpack and an entire library upload of the Class Express
- Automatically compress the files that need to be published
- Add, delete, and check server accounts
- Encrypts key server information stored locally
The use of plug-in
- SSH: Used to process login
- Commander: Specifies a command
- Compressing: pack and compress
- Inquirer: Terminal interaction
- Fs: reads files
- Path: indicates the storage path
- Crypto-js: password encryption
Server address store
The plug-in needs to add, delete and check the server, so the server needs to be stored. Therefore, data.json is created locally for data storage. Data format:
{
"data": [
{
"name": "test",
"config": {
"ip": "*****",
"pw": "*****.",
"dir": "*****",
"user": "*****"
}
}
]
}
Copy the code
Add, delete, and query servers
Use commander to schedule the command, -a to add, -l to list, and -rm to delete.
program
.option('-a, --add', 'add service')
.option('-rm, --remove', 'remove service')
.option('-l, --list', 'list service');
program.parse(process.argv);
switch (true) {
case program.add:
add()
break
case program.remove:
remove()
break
case program.list:
list()
break
default:
push()
}
Copy the code
Fs will add or delete data.json by retrieving parameters from the inquirer. Note: Nodejs write files only recognize strings or binary numbers, so convert json objects to strings and write them to JSON files.
File compression
By default, the dist folder in the current directory is published. When uploading the full library is selected, the copy2dist function needs to be called to package the files in the current directory into the dist compressed package. Note: Ignore the Node module folder.
var fs = require('fs'); var path = require("path"); function writeFile(p, text) { fs.writeFile(p, text, function (err) { if (! Err) console.log(" Write succeeded!" Function mkdirsSync(dirname) {if (fs.existssync (dirname)) {return true; } else { if (mkdirsSync(path.dirname(dirname))) { console.log("mkdirsSync = " + dirname); fs.mkdirSync(dirname); return true; } } } function _copy(src, dist) { var paths = fs.readdirSync(src) paths.forEach(function (p) { var _src = src + '/' + p; var _dist = dist + '/' + p; Var stat = fs.statsync (_src) if (stat.isfile ()) {fs.writefilesync (_dist, fs.readfilesync (_src)); } else if (stat.isDirectory() && p ! = 'node_modules' && p ! = 'dist') {copyDir(_src, _dist) /* * copy directory, subdirectory, * @param dist {String} */ function copyDir(SRC, param dist {String}) dist) { var b = fs.existsSync(dist) if (! b) { mkdirsSync(dist); } _copy(SRC, dist); } function createDocs(src, dist, callback) { console.log("createDocs..." ) copyDir(src, dist); console.log("copyDir finish exec callback") if (callback) { callback(); } } module.exports = createDocsCopy the code
encryption
The data that stores the server information is stored locally, so the password for the server information should be encrypted as necessary. Crypto - JS, the reversible symmetric encryption scheme, is chosen here.Copy the code
const CryptoJS = require('crypto-js'); Function getAesString(data, key, iv) {var key = cryptojs.enc.utf8.parse (key); var iv = CryptoJS.enc.Utf8.parse(iv); var encrypted = CryptoJS.AES.encrypt(data, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return encrypted.toString(); } function getDAesString(encrypted, key, iv) {var key = cryptojs.enc.utf8.parse (key); var iv = CryptoJS.enc.Utf8.parse(iv); var decrypted = CryptoJS.AES.decrypt(encrypted, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return decrypted.toString(CryptoJS.enc.Utf8); {} function getAES (data)/var/encryption key = '* * * * * * * * * * * * * * * *'; Var iv = 'ABCDEF1234123412'; var encrypted = getAesString(data, key, iv); // Var encrypted1 = cryptojs.enc.utf8.parse (encrypted); return encrypted; } function getDAes (data) {/ / decryption var key = '* * * * * * * * * * * * * * * *'; Var iv = 'ABCDEF1234123412'; var decryptedStr = getDAesString(data, key, iv); return decryptedStr; } module.exports = { getAES, getDAes }Copy the code
Note: The key must be 16 bits.
release
Establish a connection to publish the DIST zip to the specified path on the server and execute the set of comment instructions.
Function conFun() {console.log(' Start connection... '); connection = new ssh2(); connection.connect({ "host": ip, "username": user, "password": getDAes(password) }); Connection. on('error', function (err) {connection.end() console.log(' failed to connect '); }); Connection. on('ready', function () {console.log(' start uploading '); upLoadFile(connection, params) }); Function upLoadFile(conn, params) {const file = params.file const target = params.target if (! conn) { return } conn.sftp(function (err, sftp) { if (err) { throw err } console.log(file, target); sftp.fastPut(file, target, {}, function (err, Result) {if (err) {throw err} Shell(conn)})} function Shell(conn) {conn. Shell(function (err, stream) { if (err) throw err; Stream. on('close', function () {console.log(' Publish complete!! '); Fs.unlinksync ('./dist. Zip ') conn.end(); }).on('data', function (data) { console.log('STDOUT: ' + data) }); stream.end(comment.join('\n')); }); } comment = [ `cd ${servicePath}`, 'unzip -o dist.zip', 'rm -f dist.zip', 'exit', 'close' ]Copy the code
summary
The original intention of writing this deployment plug-in is due to the need for frequent release of the real machine debugging public end, generally not recommended for the release of the official version.