返回 blog
2021年10月11日
2 分钟阅读

代码推送前通过命令行设置版本号

目的

  1. 为了控制网站版本,老页面可通过判断网站版本来决定是否更新网站(即刷新网页)
  2. 为了避免开发者在一些重大更新后忘记设置版本号

可行性

既然可以在 pre-commit 阶段校验和格式化代码,那么就可以在 pre-push 阶段调用命令行执行设置版本号相关的命令

具体做法

效果广告是通过 ant-design-pro 搭建的,它自带了 yorkie ,可以类似 husky 的githook工具

  1. 修改 pre-push什么是gitHook),在 .git => hooks => pre-push ,添加一句 exec < /dev/tty。完整内容为:
#!/bin/sh
#yorkie 2.0.5

command_exists () {
  command -v "$1" >/dev/null 2>&1
}

has_hook_script () {
  if [ $1 == 'pre-commit' ];then
    return 0
  fi
  [ -f package.json ] && cat package.json | grep -q "\"$1\"[[:space:]]*:"
}

# OS X and Linux only
load_nvm () {
  # If nvm is not loaded, load it
  command_exists nvm || {
    export NVM_DIR="$1"
    [ -s "$1/nvm.sh" ] && . "$1/nvm.sh"
  }
}

# OS X and Linux only
run_nvm () {
  # If nvm has been loaded correctly, use project .nvmrc
  command_exists nvm && [ -f .nvmrc ] && nvm use
}

cd "."

# Check if pre-push is defined, skip if not
has_hook_script pre-push || exit 0

# Node standard installation
export PATH="$PATH:/c/Program Files/nodejs"

# Export Git hook params
export GIT_PARAMS="$*"

# allow interactive shell commands
exec < /dev/tty

# Run hook
node "./node_modules/@umijs/yorkie/src/runner.js" pre-push || {
  echo
  echo "pre-push hook failed (add --no-verify to bypass)"
  exit 1
}

  1. 修改 package.json 文件,添加 pre-push 脚本
"gitHooks": {
    "pre-push": "node publish.js"
 }
  1. 在项目根目录(或者其他你喜欢的任何地方,相应地,你需要修改步骤2中的脚本路径)。添加 publish.js 脚本
#!/usr/bin/env node

const commander = require('commander');
const inquirer = require('inquirer');
const semver = require('semver');
const chalk = require('chalk');
const shell = require('shelljs');

const program = new commander.Command();

const { version } = require('./package.json');

function isValidNewVersion(oldVersion, newVersion) {
  return !!(semver.valid(newVersion) || semver.inc(oldVersion, newVersion));
}

async function inputVersion() {
  // 弹出当前版本,并提示用户输入最新版本号
  const { newVersion } = await inquirer.prompt([
    {
      type: 'input',
      message: `请输入版本号(当前版本:${version})`,
      name: 'newVersion',
    },
  ]);

  if (isValidNewVersion(version, newVersion) && semver.lt(version, newVersion)) {
    console.log('更新版本中,请稍等...');
    try {
      // 更改package的version
      if (
        shell.exec(`npm version ${newVersion} --no-commit-hooks --no-git-tag-version`).code !== 0
      ) {
        console.log(chalk.red('更新失败'));
        shell.echo('Error: npm version error');
        shell.exit(1);
      } else {
        new Promise((resolve) => {
          const addCode = shell.exec(`git add .`).code;
          const commitCode = shell.exec(`git commit -m "v${newVersion}" --no-verify`).code;
          if (addCode === 0 && commitCode === 0) {
            console.log(chalk.green(`更新版本成功,最新版本:${newVersion}`));
            resolve();
          } else {
            shell.exit(1);
          }
        });
      }
    } catch (err) {
      console.log(err, chalk.grey('err~!'));
      shell.exit(1);
    }
  } else {
    // 提示输入不合法,重新输入
    console.error(
      chalk.red('输入不合法,请遵循npm语义化'),
      chalk.underline('https://semver.org/lang/zh-CN/'),
    );
    inputVersion();
  }
}

async function main() {
  if (!shell.which('git')) {
    shell.echo('Sorry, this script requires git');
    shell.exit(1);
  }

  // 只有在 master 或 develop 分支才会弹出
  const allowBranch = ['master', 'develop'];
  const gitBranchName = shell.exec(`git rev-parse --abbrev-ref HEAD`, { silent: true });

  if (allowBranch.includes(gitBranchName.stdout.trim())) {
    program.version(version).action(async () => {
      const { update } = await inquirer.prompt([
        {
          type: 'confirm',
          message: '是否更新网站版本?',
          name: 'update',
        },
      ]);

      if (update) {
        await inputVersion();
      }
    });
    await program.parseAsync(process.argv);
  } else {
    console.log(chalk.yellow(`当前分支为:${gitBranchName.stdout}不执行版本更新操作`));
  }
}

main();

实际效果

git push 的时候即可看到实际效果 image.png