preface

The application scenarios in this article are mainly small programs, but other projects can be customized according to the ci/ CD configuration above.

First, why do small program automation?

1) There are two main purposes

  1. Remove development and test timeRepeat codeThis operation improves the development experience
  2. Avoid small programsArraignment and on-lineDue to human operation error, online accidents

2) What are the problems encountered before accessing CI/CD

  • Poor development experience. Each time after fixing the bug, you need to put the small program back to the experience version, will go through the following steps:
    • Merge your own code into the test branch and pull others’ code to merge
    • We are using uni-app, we need to run build and wait for dozens of seconds
    • Open another development tool, find the compiled directory, open, wait for more than ten seconds, fill in the small program upload when the relevant remarks, upload completed
    • Open the small program background management page, the small program experience version to switch to their own, and then notify to test
  • An accident caused by human error. For example, you forgot to pull someone else’s code and uploaded the experience version directly, or you got the development/production environment variables wrong, or you got the direct/distribution code mixed up
  • The dependencies on node_modules may not be consistent on everyone’s computer. NPM is currently used, and some toolkits are available
  • Whenever a new employee enters the company, the new employee needs to be trained on the repeated process of development/launch, so as to avoid online accidents when they are not familiar with the process
  • Our products are divided intoDirect selling/distribution and third partyA total of 8 small procedures, this set of combined punch down, directly take up my half a day’s time

3) What problems have been improved after access

  • Develop the experience. The code is submitted directly, automatically compiled for direct distribution and third party multiple versions. The average person saves five minutes at a time, which is half an hour over the course of the day
  • The line is safe. No more cumbersome review of the online process, one-click review, no longer worry about the test environment code submitted online

Create a simple CI/CD process

1) Basic workflow of GITLab CI/CD

  • Register a Runner machine, fill in the project address and token, and then associate with the corresponding repository
  • When you push code, it checks to see if it’s under the project.gitlab-ci.ymlfile
  • When there is.gitlab-ci.ymlFile, which triggers hooks in your current runner machine to execute the tasks described in the YML file

2) Register a Runner machine

Here separate Windows and Linux two versions, the actual business is placed on the Linux server, The Windows version can be used to familiarize yourself with some yML commands and CI code testing

1. The Windows version (Docs.gitlab.com/runner/inst…
  • From the interface point you just set up to the installation of Windows
  • There are a few things to note, which I will briefly mention (in fact, they are all described in the document, so I won’t repeat them here).
    • Once you’ve downloaded it, rename the.exe file to,gitlab-runner.exeEasy to follow the steps
    • You have to register to use it after you have downloaded it

  • Began to register
    • Here are some of the configuration for CICD in the GitLab project, mainly tokens and urls, which need to be copied later for registration

    • Registration Process (Docs.gitlab.com/runner/regi…
      • Run the./gitlab-runner. Exe register command
      • Fill in the copied URL and token
      • Fill in the description (just note what the machine is used for)
      • Fill in the runner’s tags, and subsequent CI operations will be performed according to this match
      • Select the language in which the script is executed. In this case, select shell
      • Complete registration. There will be another config.toml file in the directory. Refresh the GitLab background to see a new registered machine

  • Start the runner
    • .\gitlab-runner.exe runAfter the execution, refresh the background of GitLab and you can see that the dot of the machine turns green, representing that the machine is running.
    • As long as the yML file is configured correctly, the ci will be triggered when the code is pushed
2. The Linux version (Docs.gitlab.com/runner/regi…
  • If it’s Ubuntudpkg -i gitlab-runner_<arch>.debIf CentOS is usedrpm -i gitlab-runner_<arch>.rpm
  • Start registration,sudo gitlab-runner register
  • The following steps for filling in information are the same as those for Windows

3) Create a.gitlab-ci.yml file

1. The Windows version

Some steps are written directly in comments to the code. If you want to run the simple example, simply remove the business branch name and script involved

Ci configuration of small program. If there is any change in the online process, pay attention to re-check the process here
image: node:latest
# Here is the step flow, you can customize the order
stages:
  - build
  - test
  
cache:
  paths:
    - node_modules/
Execute the task of installing the dependency
install_job:
  # Here is the first process build, currently there is only one parallel task
  stage: build
  script:
    - npm --registry https://registry.npm.taobao.org install
  This corresponds to the name of the runner you just registered. This is very important in determining whether you can enable a runner machine
  tags:
    - test_ci
  # Here is the limit triggered
  only:
    This is the branch of the limit, which means cicD will only be triggered when these three branches push
    refs:
      - master
      - pre-production
      - production
    The default gitlab variable can be found in the gitlab-cicd documentation
    variables:
      This is only triggered when cicd exists in the remarks for COMMIT
      - $CI_COMMIT_TITLE = ~ /cicd/
# master branch
# Perform compile and upload tasks
master_no_oem_job:
  # Here is the second process build, the same process can be executed in parallel. The number of concurrent tasks needs to be set
  stage: test
  The command for compiling and uploading the code for the program is now automatically implemented in the script
  script:
    Compile the direct/distribution environment
    - npm run copy_diffModule_d    
    # Compile and package small program code
    - npm run build:directsale
    Upload the packaged code to the corresponding direct selling/distribution applet, where you can access the API provided by the applet official documentation
    - npm run upload:devd
    Change the environment variables to the same code and upload a copy to the corresponding third-party applet
    - cross-env NODE_ENV=development isOem=false isThird=true node ./script/ci/uploadCode.js
  tags:
    - test_ci
  only:
    refs:
      - master
    variables:
      - $CI_COMMIT_TITLE = ~ /cicd/
# Execute compile and upload tasks, and the previous task is basically the same, but the small program is different
master_oem_job:
  stage: test
  script:
    - npm run copy_diffModule_nd    
    - npm run build:no-directsale
    - npm run upload:devnd
    - cross-env NODE_ENV=development isOem=true isThird=true node ./script/ci/uploadCode.js
  tags:
    - test_ci
  only:
    refs:
      - master
    variables:
      - $CI_COMMIT_TITLE = ~ /cicd/
Copy the code
2. Linux version

It’s basically the same as the Windows version, with some caveats

  • If the project is connected by a soft link, the dependent installation may need to be replaced
  • System variables may not be available in the soft link, and need to be output in the directory in advance
Ci configuration of small program. If there is any change in the online process, pay attention to re-check the process here
# Currently, only master, Pre and Pro branches are processed
image: node:latest

stages:
  - build
  - test
before_script:
  # Here because of business reasons need to link to another server, no need can be removed
  - ssh -p 10086 faier@**.**.cc << ssh
  - node -v
  - pwd
  - ls
  - echo $CI_COMMIT_REF_NAME
  - echo $CI_COMMIT_BRANCH
after_script:
  # Here because of business reasons need to link to another server, no need can be removed
  - ssh
# Define some generic variables that can be referenced later
variables:
  LIB_DIR: "~/gitlab-cicd/ts-app/libs/yx-miniapp/node_modules/"
  MATER_NO_OEM_DIR: "~/gitlab-cicd/ts-app/master/no_oem/yx-miniapp"
  MATER_OEM_DIR: "~/gitlab-cicd/ts-app/master/oem/yx-miniapp"
  PRE_NO_OEM_DIR: "~/gitlab-cicd/ts-app/pre-production/no_oem/yx-miniapp"
  PRE_OEM_DIR: "~/gitlab-cicd/ts-app/pre-production/oem/yx-miniapp"
  PRO_NO_OEM_DIR: "~/gitlab-cicd/ts-app/production/no_oem/yx-miniapp"
  PRO_OEM_DIR: "~/gitlab-cicd/ts-app/production/oem/yx-miniapp"
# When there is a package that needs to be updated
If this is not a soft link, you can follow the normal NPM install process
install_job:
  stage: build
  script:
    - rm -rf $MATER_NO_OEM_DIR/node_modules/ $MATER_OEM_DIR/node_modules/ $PRE_NO_OEM_DIR/node_modules/ $PRE_OEM_DIR/node_modules/ $PRO_NO_OEM_DIR/node_modules/ $PRO_OEM_DIR/node_modules/
    - cp -r $LIB_DIR $MATER_NO_OEM_DIR
  tags:
    - test_ci
  only:
    refs:
      - master
      - pre-production
      - production
      - waldon_ci_feat
    If you wish to submit a note containing a 'git' keyword, you may wish to reInstall the dependency
    variables:
      - $CI_COMMIT_TITLE = ~ /reInstall/

# Pro branch, including third party direct distribution
pro_no_oem_job:
  stage: test
  script:
    - cd ~/gitlab-cicd/ts-app/production/no_oem/yx-miniapp
    Because the link to another server, can not get the system default variable, need to manually output and then reference
    - echo "CI_COMMIT_TITLE"=$CI_COMMIT_TITLE >> ".env.ci"
    - pwd
    The code is automatically updated by default. This is the reason for the soft link
    - git pull origin production
    - npm run copy_diffModule_d
    - npm run build:directsale-pro
    - npm run upload:prod
    - cross-env NODE_ENV=production isOem=false isThird=true node ./script/ci/uploadCode.js
    - cp -r $PRO_NO_OEM_DIR/dist/build/mp-weixin/ ~/gitlab-cicd/ts-app_build/production/no_oem/
  tags:
    - test_ci
  only:
    refs:
      - production
    variables:
      - $CI_COMMIT_TITLE = ~ /cicd/

Copy the code

4) The effect after ci is triggered

  • The pipe will run the corresponding task

  • The corresponding file is generated in the directory where the machine is located

  • If the execution fails, you can click in the corresponding task to see the error message.

Three, in the small program to realize CI automatic upload/preview code

1) Configure the key and IP whitelist

Before using miniProgram-CI, you should access “wechat public Platform – development – development Settings”, download the code and upload the key, and configure the IP whitelist. Developers can choose to open the IP whitelist. After opening, only the IP in the whitelist can call the relevant interface

2) Install the dependency package of mini program CI,npm install miniprogram-ci --save

3) Put the downloaded key in a secure directory

4) Write the script of small program CI

Here directly posted our project inside the implementation, for reference only. If third-party applets are involved, the extEnable field should be set to false, which is not mentioned in the official documentation

const ci = require("miniprogram-ci");
const fs = require("fs-extra");
const path = require("path");
const dotenv = require("dotenv");

const isOem = process.env.isOem === "true";
const isThird = process.env.isThird === "true";
const isPreview = process.env.isPreview === "true";
const mode = process.env.NODE_ENV;

const filePath = `.. /.. /.env.${mode}`;
const filePath_ci = `.. /.. /.env.ci`; // Handle the upload parameters
const devInfoPath = path.resolve(__dirname, ".. /.. /src/devInfo.json");

let ciPreviewNumb = 18; // Preview the robot serial number

const readFileInfo = filePath= > {
  let fileName = path.resolve(__dirname, filePath);
  let data = fs.readFileSync(fileName, { encoding: "utf8" });
  const obj = dotenv.parse(data);
  return obj;
};
let desc = "";
const fileInfo = readFileInfo(filePath);
if (isPreview) {
  try {
    const devInfo = fs.readJsonSync(devInfoPath);
    const { ci_number, ci_desc } = devInfo;
    desc = ci_desc;
    ciPreviewNumb = ci_number;
  } catch (error) {
    console.info('Failed to read the user information file., error); }}else {
  const fileInfo_ci = readFileInfo(filePath_ci);
  desc = `${fileInfo.VUE_APP_ENV}${isOem ? "Distribution" : "Direct"}The ${!!!!! isThird ?"Third party" : ""
  }.${fileInfo_ci.CI_COMMIT_TITLE}.The ${new Date().toLocaleString()}`;
}
const projectPath = path.resolve(__dirname, ".. /.. /dist/build/mp-weixin");
let appid = "";

if(!!!!! isThird) {// The third party will only submit the Pro branch for now
  appid = isOem
    ? fileInfo.VUE_APP_NO_DIRECTSALE_THIRD_APPID
    : fileInfo.VUE_APP_DIRECTSALE_THIRD_APPID;
  const extPath = path.resolve(
    __dirname,
    ".. /.. /dist/build/mp-weixin/ext.json",);let extData = fs.readJSONSync(extPath);
  // There is no explanation in the documentation or the community that extEnable can affect ci
  extData.extEnable = false;
  extData.extAppid = appid;
  extData.ext.extAppid = appid;
  fs.writeJSONSync(extPath, extData);
} else {
  appid = isOem
    ? fileInfo.VUE_APP_NO_DIRECTSALE_APPID
    : fileInfo.VUE_APP_DIRECTSALE_APPID;
}
const privateKey = `./privateKey/private.${appid}.key`; // Get the corresponding key for different environments
const privateKeyPath = path.resolve(__dirname, privateKey);
(async() = > {const project = new ci.Project({
    appid,
    type: "miniProgram",
    projectPath,
    privateKeyPath,
    ignores: ["node_modules/**/*"]});if (isPreview) {
    const previewResult = await ci.preview({
      project,
      desc, // This remark will be displayed in the "Applet Assistant" development version list
      setting: {
        autoPrefixWXSS: true.// Style completion
      },
      robot: ciPreviewNumb,
      pagePath: "pages/loading/main".// Preview the page
      onProgressUpdate: () = >{}});console.info(`previewResult`, previewResult);
  } else {
    const uploadResult = await ci.upload({
      project,
      version: "2.2.12".// Release online or resubmit, change the version here
      desc,
      setting: {
        autoPrefixWXSS: true.// Style completion
      },
      onProgressUpdate: () = >{}});console.info(` uploadResult: `, uploadResult);
  }
})();

Copy the code

5) Define the script entry in package.json

Here is the corresponding script defined earlier in gitlab-cicd.yml

"upload:devd": "cross-env NODE_ENV=development isOem=false node ./script/ci/uploadCode.js",
"upload:devnd": "cross-env NODE_ENV=development isOem=true node ./script/ci/uploadCode.js",
Copy the code

reference

  • docs.gitlab.com/ee/ Official documentation for Gitlab
  • Developers.weixin.qq.com/miniprogram… Official documentation for mini program CI