We briefly introduced the installation and configuration operation based on GitLab CI/CD in the front. In detail, we are no longer unfamiliar with the use of GitLab Runner. However, looking at the configuration, it is not easy to find out a complete set of deployment scheme, so Floret gave our team’s common combat scheme for your reference

Project analysis

In this article, flower will give four kinds of project deployment implementation scheme, respectively is Vue project, Node project, Taro wechat small program project, Uniapp project before this, let us first familiar with the internal use of the Git branch management scheme, management scheme is similar, suitable for it, we can learn from it

Based on the branch

Git management schemes are mostly branch based, and we are no exception. For all projects we create, we default master to the production branch, Develop to the development branch, and release branch

The develop branch has multiple functional branches that are cut out from develop and merged back into Develop

The version history of multiple environments exists under the version branch, which is divided into multiple sub-branches with strict version control

The master is alone, and only when there is an urgent Bug will the Hotfix branch be cut in and merged back into Master and Develop

See the following figure for details

So for us, we only need to pay special attention to beta/*, release/* and Master. These three branches are related to our test, grey test and production environment deployment, which are also the key points that CI Jobs cuts into

Project analysis

As mentioned above, in this article we will cover the CI/CD deployment methods of the four projects, and after we fully understand how the Git branch is managed, we will examine the differences between the four projects

Vue project

The Vue project is relatively simple, and the tasks we can expect to perform are

  • Server download items (git cloneThis step is done automatically by GitLab Runner and requires no additional operations.)
  • Project dependent installation (npm install)
  • Project compilation (npm run build)
  • Static file deployment

The Node project

Node projects are a little more complex than Vue projects, using the Typescript + egg.js project as an example. Koa and Express projects are similar, with the following task instructions

  • Server download project (same as above)
  • Project dependent Installation (ditto)
  • Typescript compilation (egg.js provides a convenient way to compilenpm run ci)
  • Running projects (npm run start)
  • Project deployment

Taro wechat mini program project

We can only rely on wechat’s own CI scaffolding to compile and upload wechat applets, so it is the same for other application frameworks, such as uni-App’S wechat applets, MPvue and Kbone

  • Server download project (same as above)
  • Project dependent Installation (ditto)
  • Project compilation (npm run build)
  • Upload the project with wechat CI tool (write cli script by myself)

Uni – app project

Uni-app is a bit more difficult because most of the projects are based on the HBuilder tool of DCloud, which makes compiling and publishing more complicated. Fortunately, uni-App also provides vuE-CLI installation

There are two cases here. First, if your project is created in VUE-CLI mode based on uni-App, then congratulations, you can directly use the vUE project form as above and wechat CLI to publish directly

The second is that your project is based entirely on HBuilderX, which requires the following tasks

  • Create a build framework project (vue-cliMode creation, convenient for us after automatic conversion)
  • The server deploys the build framework
  • Download HBuilderX created projects to the server (GitLab RunnerComplete)
  • Execute the migration script (migrate the HBuilderX project tovue-cliProject)
  • Project dependent installation (npm install)
  • Project compilation (npm run build:mp-weixin)
  • Upload projects with the help of wechat CI tool

The preparatory work

We also need to configure the set of environments that automation depends on before we can actually begin project deployment

Server environment

The above analysis of the relevant tasks required by our project, so the environmental dependence of the corresponding link is essential, and it has been clear that the environment to be installed is

  • Node.js
  • Github Runner
  • Taro CLI(Can also be installed separately in the project)
  • Git
  • miniprogram-ci(wechat CI tool can also be installed separately in the project)
  • Uni-app compilation framework(More on this later)
  • Nginx(or other deployment class framework)
  • If your project has multiple environments deployed on different machines or servers, you may need to install themrsyncFor a rainy day
  • DockerIf your GitLab Runner runs on Docker, you will need to install the Docker environment

Docker or Shell is the mechanism of choice for GitLab Runner when registering. You can check it out when running the Github-Runner register command. This tutorial runs on the Shell version

GitLab Runner environment

You need to confirm whether GitLab Runner is successfully bound to your pre-compiled project or project Group. The advantage of binding to the Group is that as long as all projects under this Group, we can use the Runner instead of separate binding

For example, the front end team of Xiaohuais named G-FE, so I created a group named @G-FE, and divided several sub-groups to distinguish projects at each end. In this way, my Runner program should be mounted under the general group @G-fe, and other sub-groups and sub-projects can use Runner configuration without any problem

GitLab offers a variety of mount schemes and can even mount the same Runner across the entire site

To make sure that your Runner is mounted correctly, see The Environment section of The Automated Deployment Solution for front-end teams

Run the script

GitLab and GitLab Runner run on the.gitlab-ci.yml file. To start, you must create the file in your project

First of all, we need to confirm the order and purpose of CI tasks. We can first set up construction stages, as shown below. Add the following code to your fresh document

stages:
  - test
  - build
  - deploy
Copy the code

If you’ve forgotten the meaning of keywords, let’s go over the past and get to the bottom of it. Automated deployment solutions for front-end teams – Configuration

Vue project

To complete this CI/CD operation, I created an initial project using vue-CLI. You can also use a new project to follow the flower, or you can work in your preparatory project

In Vue projects, we usually use ESLint or prettier to optimize the code for the project. For CI, there is usually an prettier version used for the project. Just run the NPM run Lint that the code detects, so the first step

Code quality inspection

stages:
  - test
  - build
  - deploy
  
test:
  stage: test
  tags:
    - shell-g-fe-runner
  script:
    - npm install --no-optional --registry=https://registry.npm.taobao.org/
    - npm run lint
Copy the code

Tags are used to declare Runners available for the task, and you have a Tag moment for your runner when you perform the Gitlab-Runner register

As shown above, we declared a test task, and the task command will execute two, one for installing dependencies and one for code detection

Compile the project

stages:
  - test
  - build
  - deploy
  
test:
  stage: test
  tags:
    - shell-g-fe-runner
  script:
    - npm install --no-optional --registry=https://registry.npm.taobao.org/
    - npm run lint
    
build:
  stage: build
  tags:
    - shell-g-fe-runner
  script:
    - sudo npm rebuild node-sass
    - sudo npm run build
  only:
    - master
    - /^beta\/.*$/
    - /^release\/.*$/
Copy the code

Above, we declare the build task, which will first help us rebuild Node-sass and then execute the standard build statement

Remember the three branches we talked about earlier, we only do compilation in them. Of course, there may be multiple branch versions below beta/\* and release/\*. Fortunately, the only parameter supports regular expression configuration

GitLab’s CI program also includes a caching mechanism, so if you want to cache your build, it’s a good time to do it after compile time, as shown below

build:
  stage: build
  tags:
    - shell-g-fe-runner
  script:
    - sudo npm rebuild node-sass
    - sudo npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 60 mins
Copy the code

Artifacts keywords will help you cache artifacts that can be downloaded from the GitLab visualization screen after the task is completed. You can also set the artifacts cache expiration time, as shown in expire_IN, which defaults to 4 weeks. Go to the GitLab CI/CD documentation to learn more

Project deployment

In the previous step, we completed the code review and project compilation, and now we have the dist folder. Smart people already know the next step, we just put the dist folder in the nginx setting location to complete the deployment, and then we regenerate into a task, However, considering that we are multi-environment configuration, we will create a separate task for each corresponding environment

deploy_test:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - /^beta\/.*$/
  environment:
    name: Test
    url: http://test.vue.com/
  script:
    - cp -R dist/* /data/html/vue-com/test/
    
deploy_uat:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - /^release\/.*$/
  environment:
    name: Uat
    url: https://uat.vue.com/
  script:
    - cp -R dist/* /data/html/vue-com/uat/

deploy_prod:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://vue.com/
  script:
    - cp -R dist/* /data/html/vue-com/prod/
Copy the code

We just compile the corresponding branch and publish it to different services. In the configuration, we see a new keyword environment, which is our environment identifier. It can not only effectively distinguish the corresponding environment, but also provide convenient environment management and rollback for us

The examples above are only working on the same machine, so if your environment is differentiated by different servers, be aware of multi-server deployments

You will find that every time you enter a task period, you will enter a period of waiting and possibly reportingnode_modulesIf the file cannot be found, it is because our task mechanisms are isolated from each other and enjoy different files. In this case, we need to supplement the global cache strategy

cache:
  paths:
    - node_modules/
Copy the code

Add it to your profile and give it a try

The Node project

From the Vue project release strategy above, we should know some general practices about GitLab CI/CD, and the Node project certainly comes in handy

Note that the Node project will have fewer compile operations than the normal Vue project, so for us, we can write one less task, no more nonsense to say, directly on the overall, I believe that for everyone, understand the configuration is easy

stages:
  - test
  - build
  - deploy

cache:
  paths:
    - node_modules/

test:
  stage: test
  tags:
    - shell-g-fe-runner
  script:
    - npm install --no-optional --registry=https://registry.npm.taobao.org/
    - npm run lint

deploy_test:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - /^beta\/.*$/
  environment:
    name: Test
    url: http://test.node-api.com
  script:
    - npm run ci
    - npm run restart:test

deploy_uat:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - /^release\/.*$/
  environment:
    name: Uat
    url: https://uat.node-api.com
  script:
    - npm run ci
    - npm run restart:uat

deploy_prod:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://node-api.com
  script:
    - npm run ci
    - npm run restart
Copy the code

Taro wechat mini program project

Taro project upload is not complicated, but we first need to write a CI program using a small program to upload files, as follows, is a simple upload script file

Applets upload scripts

// build/ci-upload.js

const ci = require('miniprogram-ci')
const path = require('path')

const project = new ci.Project({
  appid: 'wxappid'.type: 'miniProgram'.projectPath: path.resolve(__dirname, '.. /dist'),
  // Wechat upload Key
  privateKeyPath: path.resolve(__dirname, 'upload-key.key'),
})

ci.upload({
  project,
  version: '1.0.0'.desc: 'Upload by CI'.onProgressUpdate: (p) = > {
    console.log(p._msg, p._status)
  },
}).then(() = > {
  console.log('upload success')})Copy the code

The Key of wechat upload comes from the wechat public platform and the development Settings under the development module

Project deployment

Unlike other projects, our applet does not require multi-environment configuration. Of course, if you are interested, you can integrate preview and upload Source Map into the policy. This is also a good practice, but for everyone, it just takes a little more time

stages:
  - test
  - build
  - deploy
  
cache:
  paths:
    - node_modules/
  
test:
  stage: test
  tags:
    - shell-g-fe-runner
  script:
    - npm install --no-optional --registry=https://registry.npm.taobao.org/
    - npm run lint
    
build:
  stage: build
  tags:
    - shell-g-fe-runner
  script:
    - npm run build:weapp
  artifacts:
    paths:
      - dist/
    expire_in: 60 mins
  only:
    - master
    
deploy:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://weixin.qq.com
  script:
    - node build/ci-upload.js
Copy the code

The server stores the Private Key

Under normal circumstances, files involving sensitive content are stored on the server. At this time, you can also choose to execute operations directly through the command line instead of uploading files

deploy:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://weixin.qq.com
  script:
    - miniprogram-ci upload --pp dist/ --pkp /data/private-key/mini-key.key --appid weixinappid --uv 1.0. 0 --ud "Upload By CI"
Copy the code

Please refer to wechat CI tool for details

Uniapp project

The Uni-App project is a bit more difficult. We will deploy the project created by HBuilderX. The first step is to set up a common build framework

Generate build framework

We can generate a project by default using the VUe-CLI template provided with UNI-app

vue create -p dcloudio/uni-preset-vue ci-uploader
Copy the code

In the generated project, we also need to create a.gitlab-ci.yml file, because the build framework is also updated and deployed. Secondly, we need to delete the SRC folder and all its files, so that we have a simple build framework

Given the NPM libraries that may be commonly used in uni-app, we need to install these libraries in the build framework and keep the versions consistent

npm i vue vuex -S
npm i node-sass sass-loader -D
Copy the code

If you have common libraries in your project that need to be installed into the build framework, the next step is to configure the CI file for the build framework

stages:
  - deploy

cache:
  paths:
    - node_modules/

deploy:
  stage: deploy
  tags:
    - shell-g-fe-runner
  script:
    - sudo npm install --no-optional --registry=https://registry.npm.taobao.org/
    - sudo npm rebuild node-sass
    - rm -rf /data/mp/ci-uploader
    - mkdir -p /data/mp/ci-uploader
    - cp -R . / * /data/mp/ci-uploader
  only:
    - master
Copy the code

As shown in the configuration, we put the build framework in the /data/mp/ci-uploader location that we will use to perform the release

Project deployment

Converting an HBuilderX project to a VUe-cli project is pretty easy, just move all the files from the original project to the SRC folder in vue-cli project and compile it. That’s why we just removed the SRC folder. Now look at our configuration files. The current configuration file is in the applets to be distributed, not in the compilation framework

stages:
  - deploy

deploy:
  stage: deploy
  tags:
    - shell-g-fe-runner
  script:
  	- MPNAME=my-mp-app
    - rm -rf /data/mp/$MPNAME
    - mkdir -p /data/mp/$MPNAME
    - cp -R /data/mp/ci-uploader/* /data/mp/$MPNAME/
    - mkdir -p /data/mp/$MPNAME/src
    - cp -R . / * /data/mp/$MPNAME/src
    - npm run build:mp-weixin
    - miniprogram-ci upload --pp dist/ --pkp /data/private-key/mini-key.key --appid weixinappid --uv 1.0. 0 --ud "Upload By CI"
  only:
    - master
Copy the code

Believe this code a cinch for everybody, but you may wonder why does not directly copy the project to compile the framework, and to copy out a alone, because more than one small programs, if only rely on compile framework of a folder, the task cannot be executed simultaneously, and we obviously don’t want to see this kind of situation, it is also a small team of best practices

Environment Management and Rollback

In many of the above task declarations, we have seen a parameter environment. For a single task, it can be said to be an environment identification, but the most important thing is that setting this parameter enables us to easily complete environment management and rollback operations in GitLab. I believe that for everyone, This is also an extremely important step, and there is no guarantee that every step of our release strategy will not go wrong

In GitLab project panel, click Operation -> Environment panel, you can see our environment management

You can also manually create a new environment here, but the environment will not be synchronized to the.gitlab-ci.yml file, so you need to manually synchronize the environment, so it is not recommended to create a new environment here, click on any environment, we can see rollback, redeploy, suspend service and many other environment operations

Click the rollback operation and GitLab will target the Commit record you currently selected to redeploy the environment

Multi-server Deployment

We have analyzed the deployment modes of four projects above, Vue project and Node project, which undoubtedly require multi-environment deployment. Even in most companies, multi-environment is differentiated by multiple machines or multiple servers. How can CI be used to deploy different services in different environments

Remember when project environment analysis, floret said, if you are a multi-server deployment, then you need to install this tool rsync, believe ops colleagues are no stranger to this, yes, remote synchronization, as long as we have installed the tool, remote deployment is relatively simple, the use of rsync multifarious online, Let’s skip the florets and jump right into the deployment strategy

Vue project

The Vue project is simple, we just need to remotely send the compiled artifacts to the machine where the server is located

deploy_prod:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://vue.com/
  script:
    - rsync -ravtz --delete --password-file=/data/auth/rsync.pwd dist/* 192.1681.1.::vue-com-prod/
Copy the code

The rsync authorization file needs to be stored on the server, and after specifying the address and mapping of the remote machine, we can complete the automatic deployment

The Node project

The solution is to compile the Node service, package it into a tar file, remotely synchronize it to the server, and then restart it via remote SSH. Isn’t that complicated? It’s fine. Let’s look at the script

#! /bin/sh
#SSH [email protected]" cd /data/api/node tar -xf release.tar.gz npm run restart "
Copy the code

This is a very simple remote command, you can put it anywhere, we temporarily /data/bin/up_node_api, then execute the authorization operation chmod 755 /data/bin/up_node_api, then our distribution file can be written like this

deploy_prod:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://node-api.com/
  script:
  	- npm run ci
    - rm -f /data/api/temp-files/release.tar.gz
    - tar -zcf /data/api/temp-files/release.tar.gz .
    - rsync -ravtz --delete --password-file=/data/auth/rsync.pwd /data/api/temp-files/release.tar.gz 192.1681.1.::/data/api/node/
    - /data/bin/up_node_api
Copy the code

If your Node service also needs to cache, it can be written that the artifacts must be copied to the original project to perform caching, since GitLab Runner does not support caching outside of the working directory

deploy_prod:
  stage: deploy
  tags:
    - shell-g-fe-runner
  only:
    - master
  environment:
    name: Production
    url: https://node-api.com/
  artifacts:
    paths:
      - release.tar.gz
  script:
  	- npm run ci
    - rm -f /data/api/temp-files/release.tar.gz
    - tar -zcf /data/api/temp-files/release.tar.gz .
    - rsync -ravtz --delete --password-file=/data/auth/rsync.pwd /data/api/temp-files/release.tar.gz 192.1681.1.::/data/api/node/
    - /data/bin/up_node_api
    - cp /data/api/temp-files/release.tar.gz .
Copy the code

conclusion

Well, the above plan is small current teams use automated deployment, not too many gaudy, are dry, our solution is not universal, of course, is not very perfect, if you have a better suggestion, welcome to leave a message to floret, floret will respond positively, if there are not understand of place, floret also look forward to everyone

Look forward to your attention, floret will grow with you, come on!!