Automatic deployment of front-end based on vue cli, automatic backup of index.html, version returnable

Expect:

  1. Hope to realize remote server deployment through npm command
  2. Deployment includes test environment and production environment
  3. Before packaging and deploying, you must ensure that the local code is up-to-date and synchronized with git server
  4. You need to keep the version management of vue cli, and back up index.html before uploading the code to facilitate version return

thinking

  1. Define configuration objects of test environment and production environment, including host, port, username, password, path (deployment path), outputDir (packaging folder)
  2. Pull the latest code of the branch to ensure that the local code is consistent with the GIT server (GIT fetch -- all & & & git reset -- hard origin / branchname & & & git pull, prompt the operation, and ensure that the local useful code has been submitted)
  3. Using env environment to print corresponding packages
  4. Through SSH 2, execute the linux stat command remotely to obtain the last modification time of the index.html file. The tool generates the version number at this time
  5. Through SSH 2, execute the cp command of linux, copy index.html on the server, rename it to index.201911081804.html (201911081804 is the last modification time of index. HTML)
  6. Upload the packed file to the server target directory with scp2 plug-in

Implementation (the code is rather sloppy and needs to be sorted out)

deploy.js

// /deploy.js
const scpClient = require("scp2");
const exec = require("child_process").exec;
const execSync = require("child_process").execSync;
const readline = require("readline");
/*
 *Define multiple server accounts
 */
const SERVER_LIST = {
  // testing environment
  test: {
    name: "testing environment",
    host: "", // ip
    port: 22, // port
    username: "root", // Account of login server
    password: "@", // Account of login server
    path: "/home/static/cnhpec", // Project path to publish to static server
    outputDir: "dist/" // The packed directory corresponds to the outputDir configuration of vue.config
  },
  // development environment
  prod: {
    name: "production environment",
    host: "",
    port: 22,
    username: "root",
    password: "@",
    path: "/home/static/cnhpec",
    outputDir: "dist/"
  }
};

const argv = process.argv.slice(2);
const env = argv[0] ? (argv[0] === "prod" ? "prod" : "test") : "test";
const indexFile = SERVER_LIST[env].path + "/index.html";

const Client = require("ssh2").Client;

const conn = new Client();
conn
  .on("ready", function() {
    init();
  })
  .on("error", function(err) {
    if (err) throw err;
  })
  .connect({
    host: SERVER_LIST[env].host,
    port: SERVER_LIST[env].port,
    username: SERVER_LIST[env].username,
    password: SERVER_LIST[env].password
  });

async function init() {
  await pull(); // Latest code of Latin
  await build(); // Pack
  await rename(); // Backup server code, build version
  await upload(); // Upload code
}

function pull() {
  return new Promise(function(resolve, reject) {
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    });
    select();
    function select() {
      rl.question(
        "This operation git Project force and remote synchronization!!! Do not operate easily if the local code is not submitted!!!\n\n This operation git Project force and remote synchronization!!! Do not operate easily if the local code is not submitted!!!\n\n This operation git Project force and remote synchronization!!! Do not operate easily if the local code is not submitted!!!(y/n)",
        function(answer) {
          answer = answer.trim().toLowerCase();
          if (answer === "y") {
            const branch = execSync("git symbolic-ref --short HEAD");
            exec(`git fetch --all && git reset --hard origin/${branch.toString()} && git pull`, function(err, stdout, stderr) {
              if (err) {
                console.error("Project force and remote synchronization failed!!!");
                reject();
                throw err;
              }
              console.info(stdout.toString());
              console.error(stderr);
              console.log("Project force and remote synchronization succeeded");
              resolve();
            });
            rl.close();
          } else if (answer === "n") {
            reject();
            rl.close();
            process.exit(0);
          } else {
            select();
          }
        }
      );
    }
  });
}

function build() {
  return new Promise(function(resolve, reject) {
    console.log(`Start packing ${env === "prod" ? "production" : "test"}Environmental Science......`);
    exec("npm run " + env, function(err, stdout, stderr) {
      if (err) {
        console.error("Package Failed!!!");
        reject();
        process.exit(1);
        throw err;
      }
      console.info(stdout.toString());
      console.error(stderr);
      console.log("Package success");
      resolve();
    });
  });
}

function rename() {
  return new Promise(function(resolve, reject) {
    console.log("Start backing up the server version......");
    conn.exec("stat " + indexFile, function(err, stream) {
      if (err) {
        console.error("Server version backup failed......");
        conn.end();
        reject();
        process.exit(1);
        throw err;
      }
      let mtime;
      stream
        .on("close", function(code) {
          if (code == 0) {
            copy(mtime, resolve, reject);
          } else {
            resolve();
          }
        })
        .on("data", function(data) {
          console.info(data.toString());
          mtime = data.toString().split("\n")[7];
          mtime = mtime.replace(/[\u4e00-\u9fa5]/g, "").replace(": ", "");
          mtime = formatDate(mtime);
        })
        .stderr.on("data", function(data) {
          console.warn(data.toString());
        });
    });
  });
}

function copy(mtime, resolve, reject) {
  conn.exec("/bin/cp " + indexFile + " " + SERVER_LIST[env].path + "/index." + mtime + ".html", function(err, stream) {
    if (err) {
      console.error("Server version backup failed......");
      conn.end();
      reject();
      process.exit(1);
      throw err;
    }
    stream
      .on("close", function(code) {
        if (code == 0) {
          console.log("Server version backup succeeded");
          resolve();
        } else {
          console.error("Server version backup failed......");
          conn.end();
          reject();
          process.exit(1);
        }
      })
      .on("data", function(data) {
        console.info(data.toString());
      })
      .stderr.on("data", function(data) {
        console.error(data.toString());
      });
  });
}

function upload() {
  return new Promise(function(resolve, reject) {
    scpClient.scp(
      SERVER_LIST[env].outputDir,
      {
        host: SERVER_LIST[env].host,
        port: SERVER_LIST[env].port,
        username: SERVER_LIST[env].username,
        password: SERVER_LIST[env].password,
        path: SERVER_LIST[env].path
      },
      function(err) {
        conn.end();
        if (err) {
          reject();
          process.exit(1);
          throw err;
        } else {
          console.log("Success! Successfully published to" + (env === "prod" ? "production" : "test") + "The server!");
          resolve();
          process.exit(0);
        }
      }
    );
  });
}

function formatDate(date) {
  const isZero = m => (m < 10 ? "0" + m : m),
    time = new Date(date),
    y = time.getFullYear(),
    m = time.getMonth() + 1,
    d = time.getDate(),
    h = time.getHours(),
    mm = time.getMinutes(),
    s = time.getSeconds();
  return y + "" + isZero(m) + "" + isZero(d) + "" + isZero(h) + "" + isZero(mm) + "" + isZero(s);
}

package.json add deployment command

{
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build --mode build",
    "test": "vue-cli-service build --mode test",
    "lint": "vue-cli-service lint",
    "i18n:report": "vue-cli-service i18n:report --src './src/**/*.?(js|vue)' --locales './src/locales/**/*.json'",
    "deploy:test": "node ./deploy test",
    "deploy:prod": "node ./deploy prod"
  },
  "devDependencies": {
     "scp2": "^0.5.0"
  }
}

summary

  1. Ensures that the code is up-to-date for packaging
  2. Ensure the version can be returned
  3. Not considering multi page development based on vue cli, version backup of html file
  4. No plug-in for vue cli
  5. It is still deployed locally, without realizing server-side deployment, just like jenkins (make a vue cli plug-in, start the vue ui on the deployment server, visit http://ip:8000/tasks, click deploy, and the deployment effect of type jenkins can be achieved)

Tags: Front-end git Vue npm ssh

Posted on Fri, 08 Nov 2019 05:56:09 -0500 by kaje