天天看点

前端自动化部署的深度实践工作流番外结语

更新日志自动生成

之前我都是手动修改

CHANGELOG.md

,用来记录更新日志,感觉操作起来有点心累,也不是很规范。好在已有前人种树,于是我就考虑利用

conventional-changelog-cli

自动生成和更新

CHANGELOG.md

,真的好用!

什么是conventional-changelog

Generate a changelog from git metadata

根据

git

元数据生成更新日志,而

conventional-changelog-cli

则是相关的命令行工具。

安装conventional-changelog-cli

npm install -g conventional-changelog-cli
           

复制

初始化生成CHANGELOG.md

cd my-project
conventional-changelog -p angular -i CHANGELOG.md -s
           

复制

以上命令是基于最后一次的

Feature

,

Fix

,

Performance Improvement or Breaking Changes

等类型的

commit

记录生成或更新

CHANGELOG.md

。如果你希望根据之前所有的

commit

记录生成完整的

CHANGELOG.md

,那么可以试试下面这条命令:

conventional-changelog -p angular -i CHANGELOG.md -s -r 0
           

复制

工作流

代码添加到暂存区

这一步没有什么特殊,日常撸代码,然后将工作区的内容添加到暂存区。

git add .
           

复制

规范commit message

一个规范的commit message一般分为三个部分Header,Body 和 Footer。Header包含type, scope, subject等部分,分别用于描述commit类型,影响范围,commit简述。Body则是详细描述,可以分多行写。Footer主要用于描述不兼容改动(Breaking Change)或者关闭issue(Closes #issue)。

格式如下:

<type>(<scope>): <subject>

<body>

<footer>
           

复制

举个栗子:

feat(支持自动部署): 结合conventional-changelog,配合部署脚本完成部署任务

conventional-changelog是一个很好的工具,用于自动生成changelog,再配上自定义的部署脚本,整个部署流程就显得更规范了

Breaking Change: 比较大的更新
Closes #315
           

复制

其中,

Header

是必需的,

Body

Footer

可以省略。

大致了解规范后,就可以上工具了,这里我们用到的是

commitizen

npm install -g commitizen
           

复制

接着在项目根目录运行以下命令:

commitizen init cz-conventional-changelog --save --save-exact
           

复制

运行成功后,

package.json

会新增如下内容:

"devDependencies": {
  "cz-conventional-changelog": "^3.1.0"
},
"config": {
  "commitizen": {
    "path": "./node_modules/cz-conventional-changelog"
  }
}
           

复制

git commit

这一步用

git cz替代

cz

就是指

commitizen

,通过交互式命令行完成

commit

操作。

PS D:\robin\frontend\spa-blog-frontend> git cz
[email protected], [email protected]

? Select the type of change that you're committing: feat:     A new feature
? What is the scope of this change (e.g. component or file name): (press enter to skip) 支持自动部署
? Write a short, imperative tense description of the change (max 86 chars):
 (37) 结合conventional-changelog,配合部署脚本完成部署任务
? Provide a longer description of the change: (press enter to skip)

? Are there any breaking changes? No
? Does this change affect any open issues? No
[master ee41f35] feat(支持自动部署): 结合conventional-changelog,配合部署脚本完成部署任务
 3 files changed, 15 insertions(+), 3 deletions(-)
           

复制

处理版本号,更新CHANGELOG

接着我们要更新

npm

包的版本号,结合

npm version

conventional-changelog

使用,可以同时更新

CHANGELOG.md

好的,我们先准备好脚本:

"scripts": {
    "start": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "deploy": "node deploy",
    "version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
    "postversion": "npm run deploy"
}
           

复制

根据实际版本情况选择更新

patch/minor/major

版本。假设我们更新的是

minor

版本号,那么操作命令如下:

npm version minor -m '特性版本更新'
           

复制

执行这条命令会更新

package.json

中的

version

字段,

同时会执行

conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md

,更新

CHANGELOG.md

执行完这条命令后,可以看到

CHANGELOG.md

已经被修改了。

前端自动化部署的深度实践工作流番外结语

CHANGELOG自动更新

npm钩子触发部署脚本

通过

postversion

钩子触发部署脚本

node deploy

,开始进行部署工作。

deploy.js

文件内容如下:

const { execFile } = require('child_process');

const version = process.env.npm_package_version;

execFile('deploy.sh', [version], { shell: true }, (err, stdout, stderr) => {
    if (err) {
        throw err;
    }
    console.log(stdout);
});
           

复制

这里利用了

nodejs

child_process

模块执行子进程,调用了

execFile

执行了

deploy.sh

,并将

npm

包版本号作为参数传递给了

deploy.sh

deploy.sh

文件内容如下:

#!/bin/bash
npm run build
htmldir="/usr/share/nginx/html"
uploadbasedir="${htmldir}/upgrade_blog_vue_ts"
appenddir=$1
uploaddir="${uploadbasedir}/${appenddir}"
projectdir="/usr/share/nginx/html/blog_vue_ts"
scp -r ./dist/. txcloud:${uploaddir}
ssh txcloud > /dev/null 2>&1 << eeooff
ln -snf ${uploaddir} ${projectdir}
exit
eeooff
echo done
           

复制

以上命令主要做的事情是:

  • npm run build

    执行构建任务
  • 将构建得到的

    dist

    文件夹中的内容通过

    scp

    传输到服务器,通过版本号区分各个版本。
  • nginx

    配置的是监听

    80

    端口,指向

    /usr/share/nginx/html/blog_vue_ts

    ,而我通过软连接将

    blog_vue_ts

    再次指向到

    upgrade_blog_vue_ts

    下的版本目录,如

    upgrade_blog_vue_ts/0.5.4

    。每次发布版本时,以上脚本会修改软连接,指向目标版本,如

    upgrade_blog_vue_ts/0.6.0

    ,完成版本过渡。

我这里使用了软连接改进了之前的部署脚本,既可以在服务器保留各个历史版本文件夹,也不用考虑处理

index.html

与静态资源分离的问题。

lrwxrwxrwx 1 root root   47 Feb  3 21:35 blog_vue_ts -> /usr/share/nginx/html/upgrade_blog_vue_ts/0.6.0
           

复制

前端自动化部署的深度实践工作流番外结语

linux服务器项目版本文件夹

如果要回退版本,也可以通过修改软连接的方式实现,还是比较方便的。

推送到remote

最后别忘了把代码

push

到远程仓库。

git push
           

复制

更新日志

changelog

查看也变得很方便了,修改了什么内容一目了然,并且可以直接跳转到

commit

历史,

issue

等。

前端自动化部署的深度实践工作流番外结语

github上的changelog

番外

可以看到,我是通过

deploy.js

调用了

deploy.sh

。之前本想直接在

npm scripts

中调用

deploy.sh

并传入版本号参数的,但是试了几种写法都不行,这里也记录一下。

"deploy": "deploy.sh npm_package_version"
           

复制

"deploy": "deploy.sh $npm_package_version"
           

复制

看起来在

npm scripts

中调用

sh

脚本时,只能写字面量参数,传变量作为参数好像行不通。

下面这种字面量参数写法是可以的,但是就有点呆呆的感觉了,而且与自动化部署的主题不符。

"deploy": "deploy.sh 0.6.0"
           

复制

所以我目前还是选择通过

deploy.js

作为中间者来调用

deploy.sh

的。

结语

需要承认的是,我以上所述的部署流程是以我的个人项目为例说明,可能不是很规范,但是也算是通过自己的理解和摸索,完整地搞了一套部署流程,并没有借用

jenkins

等工具。有了这段自动化部署的学习经历后,相信学习和使用

jenkins

会变得更轻松。接下来我会继续优化和规范自己的部署流程,

jenkins

理所当然会出现在我的计划表中。