3

After gitlab runner runs related tests or packages, we always want it to actively inform us of the results in real time. At this time, we need a DingTalk robot. I reported the idea of trying it out and searched on docker hub. Although I found several keywords with the same keywords, it is a pity that these authors are lazy and do not have any instructions for use. Just get one yourself.

foreword

If you don't want to know how I completed the build process from 0 to 1, but just need a DingTalk message that can be sent under itlab runner, please move to the docker official repository to quickly meet the current needs.

Choose a language

The DingTalk open document gives two examples of code push, namely JAVA and PHP. Since PHP is an unnecessary scripting language, we use PHP here.

 <?php  
function request_by_curl($remote_server, $post_string) {  
    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $remote_server);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Content-Type: application/json;charset=utf-8'));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);  
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    // 线下环境不用开启curl证书验证, 未调通情况可尝试添加该代码
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); 
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $data = curl_exec($ch);
    curl_close($ch);                
    return $data;  
}  

$webhook = "https://oapi.dingtalk.com/robot/send?access_token=xxxxxx";
$message="我就是我, 是不一样的烟火";
$data = array ('msgtype' => 'text','text' => array ('content' => $message));
$data_string = json_encode($data);

$result = request_by_curl($webhook, $data_string);  
echo $result;
?>

Although the most primitive curl command can also be used in bash to achieve this effect, but in terms of development efficiency, this is not the best choice.

image

After the language is determined to use php, I choose the more commonly used php:5.6 version, and we only need to use the scripting function of php here, so we can use the php:5.6-cli version. But after starting the docker service locally, execute: docker run php:5.6-cli /bin/bash , wait for a while, a php:5.6-cli environment is set up.

 panjie@panjies-iMac yunzhiclub % docker run -it php:5.6-cli /bin/bash
root@d46c5475b769:/# php -v
PHP 5.6.40 (cli) (built: Jan 23 2019 00:04:26) 
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
docker run -it php:5.6-cli /bin/bash indicates that after constructing the corresponding container, enter the container.

Finally, we use the exit command to exit the container, at which point the container is automatically terminated.

local debugging

Next, we debug the contanier container built on the php:5.6-cli image. The steps are as follows:

  1. Create a ding.php file locally
  2. Copy the official sample code to the ding.php file.
  3. Replace the token with your own DingTalk robot token
  4. Copy ding.php to the contanier container
  5. Execute on the container php ding.php to view the effect

The process is as follows:

Create a ding.php file locally, then we copy the official code and replace the part with access_token=xxx:

 <?php  
function request_by_curl($remote_server, $post_string) {  
    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $remote_server);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Content-Type: application/json;charset=utf-8'));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);  
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    // 线下环境不用开启curl证书验证, 未调通情况可尝试添加该代码
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); 
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $data = curl_exec($ch);
    curl_close($ch);                
    return $data;  
}  

$webhook = "https://oapi.dingtalk.com/robot/send?access_token=这里替换为你自己的自定义钉钉机器人token";
$message="我就是我, 是不一样的烟火";
$data = array ('msgtype' => 'text','text' => array ('content' => $message));
$data_string = json_encode($data);

$result = request_by_curl($webhook, $data_string);  
echo $result;
?>

image.png

Note: The robot type must be a custom machine

After saving the file, use the docker run -t -d --name=php php:5.6-cli command to start the container, and then continue to execute docker cp ./ding.php php:/root/ding.php to copy the local ding.php to the container.

Finally, we proceed to the container for testing:

 $ docker exec -it php /bin/bash
root@80adb7e221c3:/# cd /root
root@80adb7e221c3:~# php ding.php 
root@80adb7e221c3:~# exit

Then you can find the messages pushed by the tested robot in DingTalk:
image.png

mardown

But just pushing text messages is not enough. What we want is to push messages with PR addresses, so that when the construction is successful, we can directly open the PR addresses to complete the merge operation by clicking the link in DingTalk.

Next, we stop the original container, start a new container, and use the mount method to mount the current directory to the container, so that we can make code changes locally, and then execute the script in the container for testing .

 $ docker stop php
$ docker container rm php
$  docker run -it -v /Users/panjie/gitlab/yunzhiclub/process-evaluation/ding:/root --name=php php:5.6-cli /bin/bash 
root@488cfb9ae30a:/# cd /root
root@488cfb9ae30a:~# root@ddff97414a5c:~# ls
ding.php

Note: The -d parameter is missing from the above parameters, and the -t parameter and the ending /bin/bash e912d4598bfca9c08fd162e1a18a8282--- parameter are added. The function is to enter the container after the container is created.

Among them: /Users/panjie/gitlab/yunzhiclub/process-evaluation/ding is the local directory where ding.php is located, which must be an absolute path, and /root is the container directory.

Modify ding.php

According to the official documentation of DingTalk , we will change the push robot message format to markdown.

 <?php  
function request_by_curl($remote_server, $post_string) {  
    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $remote_server);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Content-Type: application/json;charset=utf-8'));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);  
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); 
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $data = curl_exec($ch);
    curl_close($ch);                
    return $data;  
}  

$webhook = "https://oapi.dingtalk.com/robot/send?access_token=你自定义机器人的token";
$message = ["title" => "这是标题", "text" => "## 执行成功 \n 我就是我,不一样的烟火[这里是地址](https://www.baidu.com)"];

$data = array ('msgtype' => 'markdown','markdown' => $message);
$data_string = json_encode($data);

$result = request_by_curl($webhook, $data_string);  
echo $result;
echo PHP_EOL;
?>

Execute the php /root/ding.php test in the container:

image.png

environment variable

Execute in the script in gitlab runner env to view the environment variables, and then we find out the required items:

 CI_MERGE_REQUEST_PROJECT_URL=https://xxx.xxx.com:xxx/yunzhiclub/process-evaluation
CI_MERGE_REQUEST_TITLE=用户管理 重置密码 和 编辑
CI_MERGE_REQUEST_IID=32
GITLAB_USER_LOGIN=weiweiyi189

Used to splice [PR标题](PR地址)构建成功,运行者:weiweiyi189 this markdown message.

PHP get environment variable

In order to use PHP in combination with environment variables in gitlab runner, we make the following modifications to ding.php.

 <?php  
$projectUrl = getenv("CI_MERGE_REQUEST_PROJECT_URL");
$prId = getenv("CI_MERGE_REQUEST_IID");
if (!$prId) {
    echo "当前脚本仅适用于PR" . PHP_EOL;
    exit(1);
}
$prUrl = $projectUrl . "/-/merge_requests/" . $prId;
$title = getenv("CI_MERGE_REQUEST_TITLE");
$author = getenv("GITLAB_USER_LOGIN");
$text = "## 😀 😃 😄 😁 😆 \n [$title]($prUrl)运行成功,提交者: $author";

function request_by_curl($remote_server, $post_string) {  
    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $remote_server);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Content-Type: application/json;charset=utf-8'));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);  
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); 
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $data = curl_exec($ch);
    curl_close($ch);                
    return $data;  
}  

$webhook = "https://oapi.dingtalk.com/robot/send?access_token=你自定义机器的token";
$markdown = ["title" => "这是标题", "text" => $text];

$data = array ('msgtype' => 'markdown','markdown' => $markdown);
$data_string = json_encode($data);

$result = request_by_curl($webhook, $data_string);  
echo $result;
echo PHP_EOL;
?>

Then design several environment variables in the container:

 $ export CI_MERGE_REQUEST_PROJECT_URL=https://xxx.xxx.com:xxx/yunzhiclub/process-evaluation
$ export CI_MERGE_REQUEST_TITLE="title test"
$ export CI_MERGE_REQUEST_IID=32
$ export GITLAB_USER_LOGIN=weiweiyi189

Finally execute again php ding.php (Note: you may need to change the DingTalk robot keyword)

 root@ddff97414a5c:~# php ding.php
{"errcode":0,"errmsg":"ok"}

image.png

strip the token

Since the DingTalk machine is only the token is different, so we turn token into the value from the environment variable, and finally complete the version ding.php

 <?php  
$token = getenv("YZ_DING_TOKEN");
if (!$token) {
    echo "未检测到环境变量'YZ_DING_TOKEN'" . PHP_EOL;
    exit(1);
}
$projectUrl = getenv("CI_MERGE_REQUEST_PROJECT_URL");
$prId = getenv("CI_MERGE_REQUEST_IID");
if (!$prId) {
    echo "当前脚本仅适用于PR" . PHP_EOL;
    exit(1);
}
$prUrl = $projectUrl . "/-/merge_requests/" . $prId;
$title = getenv("CI_MERGE_REQUEST_TITLE");
$author = getenv("GITLAB_USER_LOGIN");
$text = "## 😀 😃 😄 😁 😆 \n [$title]($prUrl)运行成功,提交者: $author";

function request_by_curl($remote_server, $post_string) {  
    $ch = curl_init();  
    curl_setopt($ch, CURLOPT_URL, $remote_server);
    curl_setopt($ch, CURLOPT_POST, 1); 
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); 
    curl_setopt($ch, CURLOPT_HTTPHEADER, array ('Content-Type: application/json;charset=utf-8'));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);  
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0); 
    // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
    $data = curl_exec($ch);
    curl_close($ch);                
    return $data;  
}  

$webhook = "https://oapi.dingtalk.com/robot/send?access_token=$token";
$markdown = ["title" => "这是标题", "text" => $text];

$data = array ('msgtype' => 'markdown','markdown' => $markdown);
$data_string = json_encode($data);

$result = request_by_curl($webhook, $data_string);  
echo $result;
echo PHP_EOL;
?>

Before using, we first set the environment variable YZ_DING_TOKEN :

 $ export YZ_DING_TOKEN=65adbb5f6d99955b86e0eff562e1d562exxxx
$ php ding.php

At this point, we have completed the local testing part, and then we can build it into a public image and upload it to a specific repository. For how to automatically build with the help of Alibaba Cloud's container service, please refer to the section How to create a docker container that runs angular unit tests -- DOCKER

The process of using Alibaba Cloud to build an image is omitted. The image address of the construction meeting is: registry.cn-beijing.aliyuncs.com/mengyunzhi/dingding:1.0.0

use

So far, we can use this image for DingTalk message push in gitlab runner .

 dingding-success:
  stage: notify
  tags:
    - docker
  image: registry.cn-beijing.aliyuncs.com/mengyunzhi/dingding:1.0.0
  variables:
    YZ_DING_TOKEN: "65adbb5f6d99955b86e0eff562e1d562e85086cc18740e5c07b2xxxx"
  script:
    - php /root/ding.php

Note: The keyword of your custom machine needs to be a substring of 运行成功,提交者 .

image.png

At this point, the current image can send a successful message to DingTalk when the build is successful.

image.png

Of course, you can also rewrite the content in ding.php yourself to meet the needs of more personalized definition of the content sent by the robot.

BUILD OFFICIAL DOCKER IMAGE

After docker is officially registered, public images can be pushed without restrictions. After we register docker, install docker desktop locally.

Next, use the image built by Alibaba Cloud to build locally:

 $ docker run --name="dingding" registry.cn-beijing.aliyuncs.com/mengyunzhi/dingding:1.0.0
$ docker image ls
REPOSITORY                                             TAG                     IMAGE ID       CREATED          SIZE
registry.cn-beijing.aliyuncs.com/mengyunzhi/dingding   1.0.0                   3b817aa5b98b   19 minutes ago   344MB

Since the official docker repository only supports image push prefixed with its username, we need to rename it before pushing to the official repository:

 $ docker tag registry.cn-beijing.aliyuncs.com/mengyunzhi/dingding:1.0.0 teacherpan/gitlab-dingtalk:1.0.0
$ docker image ls
registry.cn-beijing.aliyuncs.com/mengyunzhi/dingding   1.0.0                   3b817aa5b98b   19 minutes ago   344MB
teacherpan/gitlab-dingtalk                             1.0.0                   3b817aa5b98b   19 minutes ago   344MB

Finally, open docker desktop, find the image prefixed with the docker username, and click push to hub in the menu

image.png

Depending on the network speed, the upload time will definitely be different:

image.png

Finally, we can find it in the official docker library and successfully share it with other docker partners.

At this point, we can happily use the official repository.

 dingding-success:
  stage: notify
  tags:
    - docker
  image: teacherpan/gitlab-dingtalk
  variables:
    YZ_DING_TOKEN: "65adbb5f6d99955b86e0eff562e1d562e85086cc18740e5c07b2xxxx"
  script:
    - php /root/ding.php

The most important thing is that when others have a demand for the DingTalk push of gitlab runner, they can also quickly find us in the docker hub.


潘杰
3.1k 声望238 粉丝