Angular combined with Git Commit version handling

version.png测试环境/开发环境The image above is the version information displayed on the page .

introduced later

version-txt.pngThe above picture shows the Git Commitinformation of each submission, of course, here I record each submission, you can record it every time you build.

So, we next use Angularto achieve the next effect, Reactand the Vuesame is true.

build environment

Because the focus here is not to build the environment, we can directly generate a project with angular-cliscaffolding .

Step 1: Install Scaffolding Tools

npm install -g @angular/cli
复制代码

Step 2: Create a project

# ng new PROJECT_NAME
ng new ng-commit
复制代码

Step 3: Run the project

npm run start
复制代码

When the project is running, the default listening 4200port is opened directly in the browser http://localhost:4200/.

Under the premise that port 4200 is not occupied

At this point, theng-commit composition of the project key folder is as follows:src

src
├── app                                               // 应用主体
│   ├── app-routing.module.ts                         // 路由模块
│   .
│   └── app.module.ts                                 // 应用模块
├── assets                                            // 静态资源
├── main.ts                                           // 入口文件
.
└── style.less                                        // 全局样式
复制代码

In the above directory structure, we appwill add the servicesservice assetsdirectory the version.jsonfiles in the directory later.

Record information for each submission

Create a file in the root directory version.txtto store the submitted information; create a file in the root directory commit.jsto manipulate the submitted information.

The point is commit.js, we go straight to the topic:

const execSync = require('child_process').execSync;
const fs = require('fs')
const versionPath = 'version.txt'
const buildPath = 'dist'
const autoPush = true;
const commit = execSync('git show -s --format=%H').toString().trim(); // 当前的版本号

let versionStr = ''; // 版本字符串

if(fs.existsSync(versionPath)) {
  versionStr = fs.readFileSync(versionPath).toString() + '\n';
}

if(versionStr.indexOf(commit) != -1) {
  console.warn('\x1B[33m%s\x1b[0m', 'warming: 当前的git版本数据已经存在了!\n')
} else {
  let name = execSync('git show -s --format=%cn').toString().trim(); // 姓名
  let email = execSync('git show -s --format=%ce').toString().trim(); // 邮箱
  let date = new Date(execSync('git show -s --format=%cd').toString()); // 日期
  let message = execSync('git show -s --format=%s').toString().trim(); // 说明
  versionStr = `git:${commit}\n作者:${name}<${email}>\n日期:${date.getFullYear()+'-'+(date.getMonth()+1)+'-'+date.getDate()+' '+date.getHours()+':'+date.getMinutes()}\n说明:${message}\n${new Array(80).join('*')}\n${versionStr}`;
  fs.writeFileSync(versionPath, versionStr);
  // 写入版本信息之后,自动将版本信息提交到当前分支的git上
  if(autoPush) { // 这一步可以按照实际的需求来编写
    execSync(`git add ${ versionPath }`);
    execSync(`git commit ${ versionPath } -m 自动提交版本信息`);
    execSync(`git push origin ${ execSync('git rev-parse --abbrev-ref HEAD').toString().trim() }`)
  }
}

if(fs.existsSync(buildPath)) {
  fs.writeFileSync(`${ buildPath }/${ versionPath }`, fs.readFileSync(versionPath))
}
复制代码

The above file can be accessed directly node commit.jsvia . To facilitate management, package.jsonwe add the command line to :

"scripts": {
  "commit": "node commit.js"
}
复制代码

That way, npm run commituse node commit.jsthe same effect.

Generate version information

With the above foreshadowing, we can generate version information in the specified format through committhe information version.jsonof .

在根目录中新建文件version.js用来生成版本的数据。

const execSync = require('child_process').execSync;
const fs = require('fs')
const targetFile = 'src/assets/version.json'; // 存储到的目标文件

const commit = execSync('git show -s --format=%h').toString().trim(); //当前提交的版本号,hash 值的前7位
let date = new Date(execSync('git show -s --format=%cd').toString()); // 日期
let message = execSync('git show -s --format=%s').toString().trim(); // 说明

let versionObj = {
  "commit": commit,
  "date": date,
  "message": message
};

const data = JSON.stringify(versionObj);

fs.writeFile(targetFile, data, (err) => {
  if(err) {
    throw err
  }
  console.log('Stringify Json data is saved.')
})
复制代码

我们在 package.json 上加上命令行方便管理:

"scripts": {
  "version": "node version.js"
}
复制代码

根据环境生成版本信息

针对不同的环境生成不同的版本信息,假设我们这里有开发环境 development,生产环境 production 和车测试环境 test

  • 生产环境版本信息是 major.minor.patch,如:1.1.0
  • 开发环境版本信息是 major.minor.patch:beta,如:1.1.0:beta
  • 测试环境版本信息是 major.minor.path-data:hash,如:1.1.0-2022.01.01:4rtr5rg

方便管理不同环境,我们在项目的根目录中新建文件如下:

config
├── default.json          // 项目调用的配置文件
├── development.json      // 开发环境配置文件
├── production.json       // 生产环境配置文件
└── test.json             // 测试环境配置文件
复制代码

相关的文件内容如下:

// development.json
{
  "env": "development",
  "version": "1.3.0"
}
复制代码
// production.json
{
  "env": "production",
  "version": "1.3.0"
}
复制代码
// test.json
{
  "env": "test",
  "version": "1.3.0"
}
复制代码

default.json 根据命令行拷贝不同环境的配置信息,在 package.json 中配置下:

"scripts": {
  "copyConfigProduction": "cp ./config/production.json ./config/default.json",
  "copyConfigDevelopment": "cp ./config/development.json ./config/default.json",
  "copyConfigTest": "cp ./config/test.json ./config/default.json",
}
复制代码

Is easy Bro, right?

整合生成版本信息的内容,得到根据不同环境生成不同的版本信息,具体代码如下:

const execSync = require('child_process').execSync;
const fs = require('fs')
const targetFile = 'src/assets/version.json'; // 存储到的目标文件
const config = require('./config/default.json');

const commit = execSync('git show -s --format=%h').toString().trim(); //当前提交的版本号
let date = new Date(execSync('git show -s --format=%cd').toString()); // 日期
let message = execSync('git show -s --format=%s').toString().trim(); // 说明

let versionObj = {
  "env": config.env,
  "version": "",
  "commit": commit,
  "date": date,
  "message": message
};

// 格式化日期
const formatDay = (date) => {
  let formatted_date = date.getFullYear() + "." + (date.getMonth()+1) + "." +date.getDate()
    return formatted_date;
}

if(config.env === 'production') {
  versionObj.version = config.version
}

if(config.env === 'development') {
  versionObj.version = `${ config.version }:beta`
}

if(config.env === 'test') {
  versionObj.version = `${ config.version }-${ formatDay(date) }:${ commit }`
}

const data = JSON.stringify(versionObj);

fs.writeFile(targetFile, data, (err) => {
  if(err) {
    throw err
  }
  console.log('Stringify Json data is saved.')
})
复制代码

package.json 中添加不同环境的命令行:

"scripts": {
  "build:production": "npm run copyConfigProduction && npm run version",
  "build:development": "npm run copyConfigDevelopment && npm run version",
  "build:test": "npm run copyConfigTest && npm run version",
}
复制代码

生成的版本信息会直接存放在 assets 中,具体路径为 src/assets/version.json

结合 Angular 在页面中展示版本信息

最后一步,在页面中展示版本信息,这里是跟 angular 结合。

使用 ng generate service versionapp/services 目录中生成 version 服务。在生成的 version.service.ts 文件中添加请求信息,如下:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class VersionService {

  constructor(
    private http: HttpClient
  ) { }

  public getVersion():Observable<any> {
    return this.http.get('assets/version.json')
  }
}
复制代码

要使用请求之前,要在 app.module.ts 文件挂载 HttpClientModule 模块:

import { HttpClientModule } from '@angular/common/http';

// ...

imports: [
  HttpClientModule
],
复制代码

之后在组件中调用即可,这里是 app.component.ts 文件:

import { Component } from '@angular/core';
import { VersionService } from './services/version.service'; // 引入版本服务

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent {

  public version: string = '1.0.0'

  constructor(
    private readonly versionService: VersionService
  ) {}

  ngOnInit() {
    this.versionService.getVersion().subscribe({
      next: (data: any) => {
        this.version = data.version // 更改版本信息
      },
      error: (error: any) => {
        console.error(error)
      }
    })
  }
}
复制代码

So far, we have completed the version information. Let's finally adjust package.jsonthe command below:

"scripts": {
  "start": "ng serve",
  "version": "node version.js",
  "commit": "node commit.js",
  "build": "ng build",
  "build:production": "npm run copyConfigProduction && npm run version && npm run build",
  "build:development": "npm run copyConfigDevelopment && npm run version && npm run build",
  "build:test": "npm run copyConfigTest && npm run version && npm run build",
  "copyConfigProduction": "cp ./config/production.json ./config/default.json",
  "copyConfigDevelopment": "cp ./config/development.json ./config/default.json",
  "copyConfigTest": "cp ./config/test.json ./config/default.json"
}
复制代码

Use scriptsOne is to facilitate management, but to facilitate jenkinsconstruction and convenient invocation. For the jenkinspart , those who are interested can try it by themselves.

References & Afterwords

Guess you like

Origin juejin.im/post/7079925900531204126