Within the company to use a library recently published to the Intranet of NPM private servers, just release it is relatively simple, but the library is maintained, with more people and NPM private servers only a set, so the production environment and development environment, use the same, so we demand: how to design the NPM package development process and the automatic release process. What we want to achieve with this process is the following
- Support for team collaboration, there is development to submit code, others can be timely synchronized to the latest code
- Supports regular iteration and hotfix rollout
- The version numbers of reference packages in the same development, test, and production environments are the same
- Automatic publishing reduces manual operation
Let’s talk about how to set up NPM private server and how to distribute packages, but this is not the focus of this article, so we will briefly introduce
NPM private server setup
At present, nexus and Verdaccio are relatively mainstream. Because Verdaccio is lighter and also meets our needs, we choose it. Verdaccio setup is very simple, just use the default configuration
npm install -g verdaccio
or
yarn global add verdaccio
verdaccio
Copy the code
In this way, private service on the completion of the construction.
NPM package release
With the private server, we first register in the local NPM NPM set registry http://localhost:4873 and then add users. If this is the first time, Create user NPM adduser –registry http://localhost:4873 and publish NPM publish
There are two ways to set the version number. One is to manually change the version in package.json
// package.json
{
"name": "project"."version": "1.0.0",}Copy the code
The other option is to change the version number through NPM Version, which provides the following parameters
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]
Copy the code
Detailed explanation is as follows:
Newversion: specifies a customized version number. Write whatever you want except for the released version number. Major: Specifies the major version number. Upgrade patch 1.0.0 -> 1.0.1 PreMajor: pre-major version Preminor: pre-release version prerelease: pre-release version prerelease: pre-release version prerelease: pre-release versionCopy the code
NPM version 2.0.0: commit message 2.0.0: commit message 2.0.0: commit message 2.0.0: commit message 2.0.0 This is very simple, because the NPM version command actually changes the version in package.json, changes it and commits it, so there is a new commit record. NPM version 2.0.0 -m “Upgrade to %s for reasons” where %s is the updated version number.
gitlab CI
We intend to use GitLab CI for automated publishing, and we will briefly cover some of the steps and configuration items for GitLab CI.
- The project starts CI, selects a public runner, and if it doesn’t have one, it has to start its own.
- The project root directory is created
.gitlab-ci.yml
, write configuration, detailed configuration can be viewedGtilab website
# define stages
stages:
- build
define job
job1:
stage: build
script:
- echo 'xxx'
Copy the code
- Configuration is complete
The design phase
We want to say the key point, through the way of drawing to introduce our design ideas. Let’s set some conventions
Branching convention
The branch planning of the project, set three branches
feature
Branching: General functional iterationsmaster
Branch: Stable branchhotfix
Branch: When there are urgent changes, this branch is created as a temporary fix branch, so that the development of regular functionality is not affected
Conventions for version numbers
We adopt the method of major version: Minor version: minor version, and each submission on the feature branch will trigger the upgrade of the version number. For example, the version number of the current feature branch is 1.1.5, then the next submission will be upgraded to 1.1.6 and NPM will be released. The minor version will be upgraded according to the general requirements iteration. For example, if the current version is 1.1.8, and the periodic requirements come online tomorrow, then the version number will be upgraded to 1.2.0 and the NPM will be released. Everyone finds that 1.1.8 and 1.2.0 are the same code. Yes, the reason for this is that the minor version number corresponds to the regular changes of the cycle. Then upgrade 1.2.0 is as the version number of the next regulatory requirements, as a result, the version number corresponding to each submission, small version number corresponding to the current development phase, the two we can be triggered by CI change, do not need artificial participation, left a big version number, the only in the case of a major revision by the artificial modification, Generally speaking, the frequency of upgrading a large version number is relatively low, and manual modification is completely OK.
You may find that NPM version patch & NPM publish is triggered too often on every commit, but a small concession is required to allow for team collaboration. So this version number is not used to distinguish the version, the small version number is really used to distinguish the version, then reference this NPM to control the version number, for example
"my-package": "~ 1.2.0"
Copy the code
Lock the large and small version numbers so that our references are up to date no matter how many times we commit them during development.
Sequence diagram
The sequence diagram of development and release is drawn as follows.
Development process sequence diagram
The development sequence diagram is shown below
Publish the process sequence diagram
coded
The coding of CI is as follows
# .gitlab-ci.yml
# define stages
stages:
- publish
# define job
job2:
stage: publish
before_script:
- cd /home/node/MY Go to the project directory
- git checkout .
- git checkout $CI_COMMIT_REF_NAME || git checkout -b $CI_COMMIT_REF_NAME
- git pull -f -X theirs origin $CI_COMMIT_REF_NAME
- yarn
script:
- node publish.js
Copy the code
// publish.js
var shell = require('shelljs');
var git = require('git-last-commit');
var featureBranchName = 'feature-npm';
// Check whether the text is in version number format
function checkCommitMessage(subject) {
return /^\d+.\d+.\d+$/g.test(subject)
}
// Get the last commit, determine if it is a version number format, if not, publish,
git.getLastCommit(function(err, commit) {
console.log(commit);
const { subject, sanitizedSubject } = commit;
shell.exec('echo $CI_COMMIT_REF_NAME');
if(! checkCommitMessage(subject)) {if (sanitizedSubject.indexOf(`Merge-branch-${featureBranchName}-into-master`) > - 1) {
shell.exec('git checkout .');
shell.exec(`git checkout ${featureBranchName} || git checkout -b ${featureBranchName}`);
shell.exec(`git pull -f -X theirs origin ${featureBranchName}`);
shell.exec('npm version minor');
shell.exec('npm publish');
shell.exec(`git push origin ${featureBranchName}`);
} else {
shell.exec('npm version patch');
shell.exec('npm publish');
shell.exec('git push origin $CI_COMMIT_REF_NAME'); }}});Copy the code
// package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepublish": "build script"
},
Copy the code
In the release script, there is a function checkCommitMessage that checks whether the latest commit message is in the version number format. Since there will be a push operation at the end, the PUSH operation will trigger CI again, so to prevent the endless loop, We use the submitted message as the basis for whether to trigger CI, so we need to standardize the format of message. My suggestion is to follow this format U ${modify the specific content}.
summary
This scheme is not a universal scheme, after all, each team’s development process is different, the current scheme is suitable for our current scene. If there is a friend whose scene is the same as ours, you can try it. If the friend has a better plan, welcome to communicate with us