This paper mainly solves the following problems:

  1. How can lint-staged code specification checks be performed when code is submitted?
  2. How do I use tools to generate messages that conform to the Angular Commit specification?
  3. How do I verify message compliance with the specification through gitHooks?
  4. How do I use the tool to automatically generate Changelog?

The github repository for this article is github.com/eyunhua/cod…

If you want to learn more about the process, read on; If you want a quick look at how to use it, see the summary directory.

preface

In a multi-person project, concise, clear and easy to understand code submission comments can be a great way to quickly locate problems. The Commit message should state the purpose of the commit.

Compare the following two code commit log diagrams:

The first page: message has no actual meaning, so you can’t see the scope of this change.

The second message is concise, clear and easy to understand. You can see the current new features, fixes, etc., and can see the scope of the impact of this submission.

The above two figures show how important it is that Message writes to the specification!

Therefore, in our daily work, we cannot completely guarantee the normalization of message submission only by manually entering message.

Here is a specification that is popular in the communityPresents the specificationAnd tools to generate messages that conform to this specification.

Presents the commit specification

introduce

An overview of canonical formats

<type>(<scope>): <subject> # header section// Empty line <body> // empty line <footer>Copy the code

The Header is required, and the Body and Footer can be omitted.

Specification format details

Header

The Header section is a single line with three fields: Type (required), scope (optional), and subject (required).

type

Indicates the type of the commit

Only the following seven identifiers are allowed

  • Feat: New Feature
  • Fix: Fixes bugs
  • -Jenny: There are some docs.
  • Style: format (changes that do not affect code execution)
  • Refactor: refactoring (i.e. code changes that are not new features or bug fixes)
  • Perf: Performance improvements (code changes that improve performance)
  • The test: testing
  • Build: Changes to the build process or ancillary tools (Webpack, etc.)
  • Ci: Changes the CI configuration file and script
  • Chore: does not modify SRC or other changes to the test file
  • Revert: Commit before retreat

If the type is feat, fix, perf, or Revert, the COMMIT will definitely appear in the Change log. For the other cases (Docs, chore, Style, test), it is up to you whether to add the Change log or not, and the recommendation is no.

scope

This parameter describes the scope of the commit, such as the home page and details page.

subject

A short description of the commit, of no more than 50 characters.

Body

The detailed description for this commit can be broken into multiple lines

Examples (actual application should indicate specific changes) :

more info... 

- first changes...
- second changes...
Copy the code

Footer

This is only used in the following two cases

Incompatible variation

If the current code is incompatible with the previous version, the Footer section begins with BREAKING CHANGE, followed by a description of the CHANGE, the reason for the CHANGE, and the migration method.

For example:

Vue – next changelog.md:github.com/vuejs/vue-n…

BREAKING CHANGE: `getTextMode` compiler option signature has changed from

  ``ts
  (tag: string, ns: string, parent: ElementNode | undefined) => TextModes
  ``

  to

  ``ts
  (node: ElementNode, parent: ElementNode | undefined) => TextModes
  ``
Copy the code

Close the Issue

If the current commit is for an issue, you can close the issue in the Footer section.

Closes # 123, # 234
Copy the code

Revert (can be ignored)

In a special case, if the current COMMIT is used to undo a previous COMMIT, you must start with REVERT:, followed by the headers of the revoked commit.

revert: feat(pencil): add 'graphiteWidth' option

This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
Copy the code

The format of the Body part is fixed, and it must be written as This reverts commit. The hash is the SHA identifier of the revoked commit.

If the current commit is in the same release as the revoked commit, neither of them will appear in the Change log. If the two are published at different times, the current commit appears under the Reverts subheading of the Change log.

Code specification check: Lint-staged

Tests the code of the staging area for compliance with the specification

introduce

Prior to code submission, code rule checking ensures that all code entering git repositories complies with code rules. However, lint can be slow to run on an entire project, and Lint-staged versions can be fast because they only detect files in staging.

Install

npx mrm@2 lint-staged
Copy the code

This command will install and configure Husky and Lint staged code quality tools from the package.json dependencies of your project, so be sure to install (NPM install – save dev) and configure all code quality tools, such as Prettier and ESLint, before you do this.

After running the above command, it will appear in package.json:

"lint-staged": {
    "*.{js,vue}"[// Run different check commands for different postfix files"vue-cli-service lint"."git add"]."*.{ts}"[// Run different check commands for different postfix files"xxx"]}Copy the code

Husky is used in

Add the following script to the pre-commit hook script in the. Husky directory:

npx lint-staged
Copy the code

Used in the yorkie

In package.json, add the following script:

{
    "gitHooks": {
        "pre-commit": "lint-staged"}}Copy the code

After configuring the script, execute it in usgit commit -m 'xxx'When the code is submitted, it is automatically triggeredpre-commitHooks for code specification checking.

Commit-msg Check method 1: script

Package. Json file:

"gitHooks": {
    "commit-msg": "node build/verify-commit-msg.js"
}
Copy the code

Build/verify – commit – MSG. Js file:

Returns a non-zero value and exits

/* eslint-disable */
const chalk = require("chalk");
const msgPath = process.env.GIT_PARAMS;
const msg = require("fs")
    .readFileSync(msgPath, "utf-8")
    .trim();
// ([A-Za-z0-9]+-[A-Za-z0-9]+)+ 
const commitRE = /^(build|chore|ci|docs|feat|fix|wip|perf|refactor|revert|style|test|temp|)(\(.+\))? : {1, 50} /;
if(! (commitRE.test(msg) || msg.indexOf("Merge") = = =0)) {
    console.error(
        `  ${chalk.bgRed.white(" ERROR ")}
  [${chalk.red(msg)}] is the${chalk.red("Invalid submit message format")}
  ${chalk.red("Automatically generating update logs requires correct submission message formats such as :")}

  ${chalk.green("Issue-1 feat(module): Add A module for pre-release environment")}
  ${chalk.green("Issue-2 fix: Fix bad copy")}`
    );
    process.exit(1);  // Return a non-zero value to exit
}
/* eslint-enable */

Copy the code

Commit-msg Check mode 2: Commitlint

Git commit -m ‘XXX’ message

Install

@commitlint/ CLI, @commitlint/ config-Conventional:

npm install --save-dev @commitlint/cli @commitlint/config-conventional
Copy the code

Configure

The configuration can be defined in the Commitlint.config.js,.commitlintrc.js,.commitlintrc.json, or.commitlintrc.yml file or the CommitLint field in package.json.

Commitlint.config.js is used as an example:

echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
Copy the code

Used in husky

Add. Husky /commit-msg hook NPX –no-install commitlint –edit $1:

npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'
Copy the code

Used in Yorkie

Package. Json:

"gitHooks": {
    "commit-msg": "commitlint --edit"
 }
Copy the code

Test

After installing the CommitLint, commitlint.config.js configuration items and configuring them in hooks, you can verify message compliance at commit time.

If you enter an invalid message, the following error message will appear:

Simply typing messages manually is obviously not reliable, commitlint provides a tool to generate messages @commitlint/prompt-cli.

Message generation method 1: CommitLint

commitlintforcomitizenTwo ways are provided:

A:@commitlint/prompt-cli

Install

npm install --save-dev @commitlint/prompt-cli
Copy the code

Usage

Add an NPM run script to package.json

"scripts": {
    "commit": "commit"
}
Copy the code

perform

git add .
npm run commit
Copy the code

Running NPM run commit will produce the following image:

Enter commit Message step by step as prompted

Method 2:@commitlint/cz-commitlint

Introduce NPM

Install

npm install --save-dev @commitlint/cz-commitlint commitizen
Copy the code

Usage

package.json

{
  "scripts": {
    "commit": "git-cz"
  },
  "config": {
    "commitizen": {
      "path": "@commitlint/cz-commitlint"}}}Copy the code

perform

git add .
npm run commit
Copy the code

Running NPM run commit will produce the following image:

Enter commit Message step by step as prompted

prompt

You can do rules and prompt related rules in the commitlint.config.js configuration file, see the official documentation here for details.

Check the history commit message

npx commitlint -- --from HEAD~1 --to HEAD --verbose
Copy the code

Message generation method 2: Commitizen

Commitizen is a tool for writing qualified Commit messages.

Install Commitizen globally

npm install -g commitizen
Copy the code

The project initializes Commitizen

In the project directory, run the following command to support Angular’s Commit Message format

Commitizen init Z-xconventional -changelog --save --save-exact Commitizen init Z-conventional -changelog --save --save-exactCopy the code

Cz – but – changelog is introduced

After the preceding command is executed, the cz-Xconventional – Changelog package is added to devDependencies in the package.json file and the config item is automatically added as follows:

"devDependencies": {
    "cz-conventional-changelog": "^ 3.3.0"
},
"config": {
   "commitizen": {
       "path": "./node_modules/cz-conventional-changelog"}}Copy the code

Git cz: git cz: git cz: git cz: git cz: git cz Options appear to generate a commit Message that matches the format.

We can also configure commands in script in package.json:

"scripts": {..."commit": "git cz"
},
Copy the code

Git commit: NPM run commit

The full version generates the Message sample

To generate Breaking changes, enter Are there any Breaking changes? And that’s choice y

Generate the changelog

introduce

If all your Commits comply with the Angular Commit specification, the script will automatically generate Changelog when you release a new version.

Example: VUe-next v3.1.0 Changelog

The generated Changelog document consists of the following parts:

  • Features (Corresponding type: feat)
  • Bug Fixes (corresponding type: fix)
  • Code refactor (type: refactor and breaking changes is Y)
  • Performance Improvements (Corresponding type: perf)
  • Reverts (corresponding to Type: Revert)
  • BREAKING CHANGES (show body for BREAKING CHANGES)

Each section lists the associated Commits and has links to them. Of course, the resulting document allows manual modification, so you can add additional content before Posting.

conventional-changelog-cli

A tool used to generate Changelog

But – changelog – cli is introduced

The installation

npm install -g conventional-changelog-cli
Copy the code

Generate the changelog

Run the following command to generate Changelog:

conventional-changelog -p angular -i CHANGELOG.md -s
Copy the code

The above command does not overwrite the previous Change log, but only adds changes since the last release to the changelog.md header.

If you want to generate all published Change logs, run the following command:

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

For ease of use, you can write it to the scripts field of package.json.

{
  "scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"}}Copy the code

In the future, simply run the following command.

npm run changelog
Copy the code

Changelog generation basis

There may be such a question, how to generate a version of the corresponding Changelog?

That involves the Version field in package.json, and creating a tag on the COMMIT where this version is developed.

In this way, when NPM Run Changelog is run, the corresponding version log is generated based on the version and tag.

The sample

1. Commit log as shown below:

2. The generated Changelog is shown as follows:

conclusion

Code review

/ / installation
npx mrm@2 lint-staged
// Configure the following script checks in package.json
"lint-staged": {
    "*.{js,vue}": [ // Run different check commands for different postfix files
      "vue-cli-service lint"."git add"]."*.{ts}": [ // Run different check commands for different postfix files
      "xxx"]}// In husky, '. Husky /pre-commit ', add the following script:
npx lint-staged
// in 'package.json', add the following script:
"gitHooks": {
    "pre-commit": "lint-staged"
}
Copy the code

Verifying message specification

The script

package.json

"gitHooks": {
    "commit-msg": "node build/verify-commit-msg.js"
}
Copy the code

build/verify-commit-msg.js

const chalk = require("chalk");
const msgPath = process.env.GIT_PARAMS;
const msg = require("fs")
    .readFileSync(msgPath, "utf-8")
    .trim();
const commitRE = /^(build|chore|ci|docs|feat|fix|wip|perf|refactor|revert|style|test|temp|)(\(.+\))? : {1, 50} /;
// Verify that the submitted message conforms to the team specification against the regular expression
if(! (commitRE.test(msg) || msg.indexOf("Merge") = = =0)) {
    console.error(
        `  ${chalk.bgRed.white(" ERROR ")}
  [${chalk.red(msg)}] is the${chalk.red("Invalid submit message format")}
  ${chalk.red("Automatically generating update logs requires correct submission message formats such as :")}

  ${chalk.green("Issue-1 feat(module): Add A module for pre-release environment")}
  ${chalk.green("Issue-2 fix: Fix bad copy")}`
    );
    // Exit with a non-zero value, abandoning the commit
    process.exit(1);
}
Copy the code

commitlint

/ / installation
npm install --save-dev @commitlint/cli @commitlint/config-conventional
/ / configuration
echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
// Used in husky
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit $1'
// Used in yorkie
"gitHooks": {
    "commit-msg": "commitlint --edit"
}
Copy the code

Generated message

@commitlint/prompt-cli

/ / installation
npm install --save-dev @commitlint/prompt-cli
Copy the code

Package. json configuration script:

"scripts": {
    "commit": "commit"
}
// To commit, run NPM run commit
Copy the code

@commitlint/cz-commitlint

/ / installation
npm install --save-dev @commitlint/cz-commitlint commitizen
Copy the code

Package. Json:

{
    "scripts": {
        "commit":"git-cz"
    },
    "config": {
        "commitizen": {
            "path": "@commitlint/cz-commitlint"}}}// To commit, run NPM run commit
Copy the code

commitizen

NPM install -g commitizen // Switch to the project directory commitizen init Z-xconventional -changelog --save --save-exact // Run the git command Git cz // or package.json config 'scripts'Copy the code

Generate the changelog

NPM install -g xconventional -Changelog // Generate all Changelog xconventional -Changelog -p angular-i changelog. md-s -r 0 // Generate changelog Conventional -Changelog -p angular-i Changelog.md-s since the last version changeCopy the code

Q&A

1. For gitHooks hook authentication, only one of the following methods can be reserved:

  • .git/hoos/In the directory, delete it.sampleSuffix after effective hook, e.g

  • package.jsonThrough thegitHoosCustom hooks that can be checked by NPM package or JS file

2. Modify the version in package.json every time the version is released. Changelog needs to be generated based on the version number

Reference code base

  • Webpack:github.com/webpack/web…
  • Vue:github.com/vuejs/vue-n…

Reference documentation

  1. www.jianshu.com/p/c7e40dab5…
  2. www.ruanyifeng.com/blog/2016/0…
  3. Git hooks
  4. www.jianshu.com/p/62b5c6471…
  5. Vue code base
  6. commitlint