赞
踩
首先看一下需要什么依赖?
- {
- "name": "zdpl",
- "version": "1.0.1",
- "description": "自动部署",
- "main": "./src/index.js",
- "bin": {
- "zc-deploy": "./src/index.js"
- },
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "keywords": [
- "deploy"
- ],
- "publicConfig": {
- "registry": "https://registry.npmjs.org/"
- },
- "author": "",
- "license": "ISC",
- "dependencies": {
- "chalk": "^4.1.0",
- "inquirer": "^8.0.0",
- "node-ssh": "^11.1.1",
- "ora": "^5.3.0",
- "shelljs": "^0.8.5",
- "zip-local": "^0.3.5"
- }
- }
脚本的目录结构如下:
1. chalk插件主要用于改变终端输出文字的样式
2. inquirer 用户交互命令行
3. node-ssh connect 用于用户连接服务器,exec 用于执行命令, putFIle用于推送文件到服务器指定位置。
4. ora 用于等待某个指令执行,类似loading效果
5. shelljs 是基于node.js的Unix shell命令的可移植实现。类似shell脚本可以写一下指令,然后执行。shelljs就是可以在js通过其中方法执行指令,在运行代码时依次执行。
6. zip-local用于压缩文件,用法查看npm官网
7. download-git-repo用于从github,gitlab等上拉取摸板。
8. commander 这里主要用来生成不同的指令,zc-deploy init 和 zc-deploy push
主要代码如下
需要在代码中配置deploy.config.ts 文件,使用zc-deploy init 初始化摸板。也可以自己配置,配置格式如下,需要知道公司项目发布的服务器ip,在此文件中声明即可。在执行yarn deploy时,会出现如下图选择部署的服务器。
- module.exports = Object.freeze({
- PRIVATE_KEY: 'C:/Us/.ssh/id_rsa', // 密钥地址
- SERVER: [
- {
- NAME: 'server-501',
- SERVER_PATH: '39.98.82.82',
- SSH_USER: 'root', // 服务器用户名
- SSH_KEY: ``, // 服务器密码
- PORT: 22, // 端口 默认为22
- DIST: './dist', // 需要部署的打包过后的文件夹 根据项目不同值不同 一般为 build static 或者dist
- SCRIPT: 'yarn build:prod', // 打包命令 可能项目由不同的构建命令 如打包指定环境的代码
- PATH: '/root/501', // 服务器存放静态文件目录
- },
- {
- NAME: 'server-506',
- SERVER_PATH: '192.168.117.133',
- SSH_USER: 'root', // 服务器用户名
- SSH_KEY: 'root', // 服务器密码
- PORT: 22, // 端口 默认为22
- DIST: './dist', // 需要部署的打包过后的文件夹 根据项目不同值不同 一般为 build static 或者dist
- SCRIPT: 'yarn build:prod', // 打包命令 可能项目由不同的构建命令 如打包指定环境的代码
- PATH: '/root/506', // 服务器存放静态文件目录
- },
- {
- NAME: 'server-603',
- SERVER_PATH: '192.168.117.133',
- SSH_USER: 'root', // 服务器用户名
- SSH_KEY: 'root', // 服务器密码
- PORT: 22, // 端口 默认为22
- DIST: './dist', // 需要部署的打包过后的文件夹 根据项目不同值不同 一般为 build static 或者dist
- SCRIPT: 'yarn build:prod', // 打包命令 可能项目由不同的构建命令 如打包指定环境的代码
- PATH: '/root/603', // 服务器存放静态文件目录
- },
- ],
- });
src/index.js:这是全局的入口。主要配置了两个命令:zc-deploy init 和zc-deploy push
- #!/usr/bin/env node
-
-
- program
- .version(packageJson.version, "-v, --version")
- .command("init")
- .description("初始化部署相关配置")
- .action(() => {
- require("../lib/init")();
- });
-
- program
- .version(packageJson.version)
- .command("push")
- .description("部署项目")
- .action(async () => {
- if (fs.existsSync(path.resolve(process.cwd(), "./deploy.config.ts"))) {
- const CONFIG = require(path.resolve(process.cwd(), "./deploy.config.ts"));
-
- const serverConfig = [...CONFIG.SERVER];
- const answers = await inquirer.prompt([
- {
- type: "confirm",
- name: "hasBuild",
- message: "是否需要打包",
- },
- ]);
- let hasBuild = answers.hasBuild ? true : !existsSync(distZipPath);
- const serverName = await inquirer.prompt([
- {
- type: "list",
- name: "server_name",
- message: "请选择部署的服务器",
- choices: serverConfig.map((item) => item.NAME),
- },
- ]);
- runTask(hasBuild, serverName, serverConfig, CONFIG);
- } else {
- defaultLog(`缺少部署相关的配置,请运行"zc-deploy init"下载部署配置`);
- }
- });
lib/deploy.js:这个文件是,项目的部署流程文件。
- #!/usr/bin/env node
-
- const distZipPath = resolve(process.cwd(), "./dist.zip");
-
- // 打包 npm run build 或yarn build
- const compileDist = async (CURCONFIG) => {
- // 进入本地文件夹
- cd(process.cwd(), "./");
- exec(CURCONFIG.SCRIPT || "yarn build:prod");
- success("打包完成");
- };
-
- // ******压缩dist文件******
-
- const zipDist = async (CURCONFIG) => {
- try {
- if (existsSync(distZipPath)) {
- defaultLog("dist.zip已经存在,即将删除压缩包");
- unlinkSync(distZipPath);
- } else {
- defaultLog("即将开始压缩zip文件");
- }
- let spinner = ora("文件开始压缩").start();
-
- sync
- .zip(path.resolve(process.cwd(), CURCONFIG.DIST || "./dist"))
- .compress()
- .save(distZipPath);
- spinner.succeed("文件压缩成功");
- } catch (error) {
- errorLog(error);
- errorLog("压缩dist文件失败");
- }
- };
-
- // ********执行清空线上文件夹指令**********
- const runCommond = async (commond, CONFIG) => {
- const result = await SSH.exec(commond, []);
- console.log(warning(result));
- };
- // ********* 执行清空线上文件夹指令 *********
- const runBeforeCommand = async (CONFIG) => {
- let spinner = ora("正在删除服务器文件").start();
- await runCommond(`rm -rf ${CONFIG.PATH}/dist.zip`);
- await runCommond(`rm -rf ${CONFIG.PATH}/dist`);
- spinner.succeed("删除服务器文件成功");
- };
-
- // 通过ssh上传文件服务器
- const uploadZipBySSH = async (CONFIG) => {
- // 上传文件
- let spinner = ora("准备上传文件").start();
- try {
- await SSH.putFile(distZipPath, CONFIG.PATH + "/dist.zip");
- // await SSH.putFile(distZipPath, '/root/dist.zip');
- spinner.succeed("文件上传服务器成功");
- let spinner1 = ora("完成上传,开始解压").start();
- await runCommond(`unzip ${CONFIG.PATH}"/dist.zip" -d ${CONFIG.PATH}/dist`);
- spinner1.succeed("文件解压成功");
- success(`${CONFIG.NAME}部署完成`);
- process.exit(0);
- } catch (err) {
- errorLog(err);
- errorLog("上传失败");
- }
- };
-
- const getServerConfig = (serverName, serverConfig) => {
- return serverConfig.find((item) => {
- return item.NAME == serverName;
- });
- };
-
- // 连接ssh
- const connectSSH = async (CURCONFIG, CONFIG) => {
- defaultLog(`尝试连接服务:${CURCONFIG.SERVER_PATH}`);
- defaultLog(`密钥路径${CONFIG.PRIVATE_KEY}`);
- let spinner = ora("正在连接").start();
- try {
- SSH.connect({
- host: CURCONFIG.SERVER_PATH,
- username: CURCONFIG.SSH_USER,
- password: CURCONFIG.SSH_KEY,
- privateKey: Buffer.from(CONFIG.PRIVATE_KEY).toString() ?? "",
- port: CURCONFIG.PORT || 22,
- }).then(async () => {
- // exec(`sh ${connect} ${CURCONFIG.SERVER_PATH} ${CURCONFIG.PATH}`);
- spinner.succeed("服务器连接成功");
- await runBeforeCommand(CURCONFIG);
- await uploadZipBySSH(CURCONFIG);
- });
- } catch (err) {
- errorLog(err);
- errorLog("ssh连接失败");
- }
- };
-
- async function runTask(hasBuild, serverName, serverConfig, CONFIG) {
- const CURCONFIG = getServerConfig(serverName.server_name, serverConfig);
- if (hasBuild) {
- await compileDist(CURCONFIG);
- }
- await zipDist(CURCONFIG);
- await connectSSH(CURCONFIG, CONFIG);
- }
-
- module.exports = runTask;
lib/init.js :这个文件是初始化配置文件,生成一系列配置信息(deploy.config.ts)
- const deployTem = "github:success-c/deploy-template";
- const checkDeployExists = () => {
- if (fs.existsSync(deployConfigPath)) {
- defaultLog("根目录下已经存在deploy.config.ts文件,请勿重新下载");
- process.exit(1);
- }
- downloadAndGenerate(deployTem);
- };
-
- const downloadAndGenerate = (templateURL) => {
- const spinner = ora("开始生成部署模板");
- spinner.start();
- download(templateURL, process.cwd(), { clone: false }, (err) => {
- if (err) {
- errorLog(err);
- process.exit(1);
- }
- spinner.stop();
- success("模板下载成功,模板位置:/deploy.config.js");
- defaultLog("请配置根目录下的deploy.config.js配置文件");
- console.log("注意:请删除不必要的环境配置");
- process.exit(0);
- });
- };
- module.exports = () => {
- checkDeployExists();
- };
lib/utils : 打印信息的方法
- const chalk = require("chalk");
- const { red, blue, green, yellow } = chalk;
- const errorLog = (error) => console.log(red(`=========>${error}`));
- const defaultLog = (log) => console.log(blue(`=========>${log}`));
- const success = (log) => console.log(green(`=========>${log}`));
- const warning = (log) => console.log(yellow(`${log}`));
-
- module.exports = {
- errorLog,
- defaultLog,
- success,
- warning,
- };
源码地址:
deploy: node脚本实现自动化部署https://gitee.com/liu--zicheng/deploy.git
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。