This article was written in the context of the company in 2020. Most companies now have Devops performance platforms using Docker or OSS deployment

preface

This is a continuation of Gitlab CI/CD for Automated Build, Automated Deployment. We know that after the Job in Gitlab Pipeline is successfully executed or fails, the corresponding Job state will change to PassedorFailed. When the Job state changes, We need to check the Job status under the PAGE of Gitlab CI/CD again to see if the package is completed. Practice shows that sometimes our GITLab execution Job often needs to wait for a long time and is unstable. This causes us to repeatedly go to the CI/CD page to see if the Job has been executed. Therefore, we need a more friendly and efficient feedback scheme for Job execution completion status. Which brings me to the Spike notification robot.

Introduce the nailing robot

The idea is to introduce webhooks into a group of pegs, give you tokens and secret, and make HTTP requests in the format specified

See: ding-doc.dingtalk.com/doc#/server…

Official document analysis is clear, need to pay attention to the need to sign this step:

/* Timestamp +"\n"+ key as signature string, using HmacSHA256 algorithm to calculate the signature, then Base64 encode, \n finally put signature parameters again urlEncode, get the final signature (utF-8 character set is required). - Here with node crypto encryption module implementation, roughly implemented as follows */
const encryptSign = (secret, content) = > {
  const str = crypto
    .createHmac("sha256", secret)
    .update(content)
    .digest()
    .toString("base64");
  return encodeURIComponent(str);
};
const sign = encryptSign(this.secret, timestamp + "\n" + this.secret);
Copy the code

Custom nailing robot

The nail robot supports various types of messages, what we need is a text and card type message, the picture is as follows.



In conjunction with the pin document, we packaged our own robot dingtalkBot class that supports fast text and card messages. The script is as follows:

dingtalkBot.js

/* eslint-disable @typescript-eslint/no-var-requires */
const crypto = require("crypto");
const axios = require("axios");
const encryptSign = (secret, content) = > {
  const str = crypto
    .createHmac("sha256", secret)
    .update(content)
    .digest()
    .toString("base64");
  return encodeURIComponent(str);
};

/** * WebHook: Used to support the message sending of the nail robot ** Official documentation: https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq */
class DingtalkBot {
  /** * Robot factory, all push items will call this. Webhook interface to send **@param {String} Options. webhook complete interface address *@param {String} Options. baseUrl Interface address *@param {String} options.accessToken accessToken
   * @param {String} options.secret secret
   */
  constructor(options) {
    options = options || {};
    if(! options.webhook && ! (options.accessToken && options.baseUrl)) {throw new Error("Lack for arguments!");
    }
    Options. webhook is preferred
    // The options. BaseUrl and options.accessToken are combined to form a webhook address
    this.webhook =
      options.webhook ||
      `${options.baseUrl}? access_token=${options.accessToken}`;
    this.secret = options.secret;
  }

  /** * Sends a pin message **@param {Object} Content Launches the message object *@return {Promise}* /
  send(content) {
    let singStr = "";
    if (this.secret) {
      const timestamp = Date.now();
      singStr =
        "&timestamp=" +
        timestamp +
        "&sign=" +
        encryptSign(this.secret, timestamp + "\n" + this.secret);
    }
    return axios.request(this.webhook + singStr, {
      method: "POST".headers: {
        "Content-Type": "application/json",},data: JSON.stringify(content),
    });
  }

  /** * Send plain text message, support @ group member **@param {String} Content Message content *@param {Object} At group @ Mobile phone number * of a member@return {Promise}* /
  text(content, at) {
    at = at || {};
    return this.send({
      msgtype: "text".text: {
        content,
      },
      at,
    });
  }

  /** * Send actionCard * Ps: support multiple buttons, support Markdown **@param {String} Card. The title title *@param {String} Card. text Message content *@param {String} Card.btnorientation The orientation of the buttons (0 vertical, 1 horizontal, default to 0) *@param {String} Card.btn. title Specifies the title of a button *@param {String} Card.btn. actionURL A button link *@return {Promise}* /
  actionCard(card) {
    return this.send({
      msgtype: "actionCard".actionCard: {
        title: card.title,
        text: card.text,
        btnOrientation: card.btnOrientation || 0.btns: card.btns || [], }, }); }}module.exports = DingtalkBot;
Copy the code

Custom message templates

As we know from the message type above, we need some build information (project, branch, environment, etc.) and the submitter that @ specifies. After some work, we know that when gitlab Runner executes the Node script, the process.env variable contains all the variables we need, as shown in the figure

The screenshot above is only part of it


From this we define the following Markdown format template



In addition to the card message. We need @ to notify the named submitter. According to the API provided by Dingding, we need the phone number information of the submitter. How about when we expose the submitter’s phone number information while Node executes JS. After the same process, we can set environment variables for the project. When GitLab Runner executes Job, it will be exposed to the execution environment. See details:Docs.gitlab.com/help/ci/var…

Such as:



The variable name of Luxuemin is set here, and the variable value is my number: XXXXX.

Note: There is a mapping. The variable name is luxuemin, which is my gitLab platform user name and probably git user name, as shown in the figure

With the mapping configured, we can @ the submitter specified.

const gitlabUserName = process.env.GITLAB_USER_NAME;
const phoneNumber = process.env[gitlabUserName]; // Configure the GITLAB_USER_NAME mapping phone number on gitlab CI/CD

await robot.text("Please check your build information", {
  atMobiles: [phoneNumber],
  isAtAll: false});Copy the code

Send the message script file notify.js

The script file above also adds a Github Today Trending egg (randomly recommending a Github Trending item Today) and a random eye pleasing picture.

As shown in figure:

Used in the previous script

According to the result of simulated Jenkins request, node carries the status of success and failure before executing the above script, which is represented by status. At the same time, the js script is launched, and process.exit(status) is used to exit, which can be refer to the following script

RES=$( curl -X POST \
       --user tao-tao:1169ee9c0493b27d915632c0577fdd66fd \
       --data 'json={"parameter":[{"name":"PJ","value":"crm-finance-static"},{"name":"MYENV", "value":"'$env'"},{"name":"TAG","value":"'$branch'"}]}' \
       --compressed \
       'http://xxxx/job/tao.tao/build? delay=0sec'\] #if [ "$RES" ]; then { echo 'failed! '; exit 1;  } fi
if [ "$RES" ]; then
  node scripts/notify.js $env $branch --status=1 || { echo 'failed! '; exit 1; }else
  node scripts/notify.js $env $branch --status=0 && { echo 'succused! '; exit 0; } fiCopy the code

The last

Currently crM-finance is configured to introduce this robot. Follow-up needs of partners can be introduced in their own projects, if partners want to enter Gitlab&Dingtalk notification robot test group, you can scan code to join. A warm welcome!

Original address: github.com/jackluson/l…