钉钉机器人 自动化发版
钉钉机器人 自动化发版
#1 简介
- 开发机器人接收消息并调用构建接口, 实现自动化发版
- 发送指令 -> 机器人接收指令 -> 调用jenkins-job远程构建与部署
- jenkins配置,勾选job配置的
触发远程构建
并设置身份验证令牌
#测试 触发远程构建
curl -ks -u user:user_token -X POST \
jenkins_url/job/job_name/buildWithParameters?token=job_token
#2、创建机器人
#2.1 登录钉钉开放平台
- 登录用户需要有管理员权限
https://open-dev.dingtalk.com/fe/app
#2.2 创建机器人
- 应用开发 -> 机器人 -> 创建应用
- 继续使用旧版,名称如
cici
- 应用信息,复制
AppSecret
- 继续使用旧版,名称如
- 开发管理,修改,消息接收地址
- 创建test企业群, 添加机器人cici
- 复制群机器人token到default_token
#2.3 运行机器人服务
配置环境变量文件.env_lark
#vim .env_dingtalk
# 钉钉机器人密钥 AppSecret
ding_secret=Q-uG5AMlMgC_Tkn6qhz1601xMYfQgxzeQh3xxx
#默认 机器人token
ding_webhook_default_token=bf5ab6a77cbc1b7c21fcxxx
#jenkins
JenkinsBaseUrl=https://user:user_token@jenkins.elvin.vip/job/
使用docker启动机器人服务
docker rm -f robot-dingtalk &>/dev/null
docker run -dit --name robot-dingtalk \
--restart=always -h robot-dingtalk --net=host\
-v $Dir:/opt --env-file .env_dingtalk \
registry.aliyuncs.com/elvin/python:dingtalk-robot \
python3 /opt/dingtalk-robot.py
dingtalk-robot.py 实例在https://gitee.com/alivv/elvin-demo
nignx配置域名和lark反向代理
#dingtalk-cicd
location ~ ^/dingtalk-cicd {
proxy_pass http://127.0.0.1:8091;
proxy_set_header Host $host:$server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
#3 发送消息测试
#3 源码
python实例如下:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# By Elvin , blog.elvin.vip
import os
import time
import hmac
import hashlib
import base64
import json
from datetime import datetime
from flask import Flask, request
import requests
# 从环境变量加载配置
ding_secret = os.getenv("ding_secret")
ding_webhook_default_token = os.getenv("ding_webhook_default_token")
app = Flask(__name__)
#钉钉发送文本消息
def send_txt_msg(message, webhook_url):
data = { "msgtype": "text","text": {"content": message}}
#requests发送post请求
req = requests.post(webhook_url, json=data)
print(req)
#签名核对
def check_sign(timestamp=int(time.time() * 1000), app_secret=ding_secret):
#钉钉消息头部加密
app_secret_enc = app_secret.encode('utf-8')
string_to_sign = '{}\n{}'.format(timestamp, app_secret)
string_to_sign_enc = string_to_sign.encode('utf-8')
hmac_code = hmac.new(app_secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
sign = base64.b64encode(hmac_code).decode('utf-8')
return sign
# Default route, print user's IP
@app.route('/')
def remoteIP():
if 'X-Forwarded-For' in request.headers:
ip = request.headers['X-Forwarded-For'].split(',')[0]
else:
ip = request.remote_addr
return ip + "\n", 200, [("Server", "Go"), ("City", "Shanghai")]
# 接收@机器人的消息
@app.route('/dingtalk-cicd', methods=["POST"])
def index():
if request.method == "POST":
timestamp = request.headers.get('Timestamp')
sign = request.headers.get('Sign')
if check_sign(timestamp=timestamp) == sign:
req_data = json.loads(str(request.data, 'utf-8'))
sender = req_data.get('senderNick')
text = req_data.get('text').get('content', "").strip()
ddgroup = req_data.get('conversationTitle').strip()
#msg
msg_cicd(ddgroup,text,sender)
return "succeed"
else:
return "not found"
else:
return "method not found"
#筛选消息,执行指令
def msg_cicd(ddgroup,text,sender):
msg = text
sender = sender
ddGroup = ddgroup
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), " msg->: ", msg)
#check ddgroup
if ddGroup == "test" or ddGroup == "DevOps":
webhook = ding_webhook_test
appInfoMap = dict(appTest, **appProd)
myMenu = {"help", "test", "prod"}
if msg in appInfoMap:
app_env = appInfoMap[msg][0]
app_name = appInfoMap[msg][1]
app_url = appInfoMap[msg][2]
#app_url = appInfoMap[msg][2] + appInfoMap[msg][1]
app_url = app_url + app_env + "&app_list=" + app_name
if app_env != "":
#执行通知
msg = "By: %s\nenv: %s\napp: %s" % (sender, app_env, app_name)
send_txt_msg(msg,webhook)
head = { 'User-Agent': "webhook-dingtalk-robot" }
#向webhook发起post请求
res = requests.post(url=app_url, headers=head)
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "run", app_env, app_name, res.reason)
return "succeed"
else:
print(msg, "nothing")
return "succeed"
elif msg in myMenu:
#打印命令列表
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "print menu ", msg)
msgTitle = "#命令 名称\n"
if msg == "help":
msgTitle2 = "#命令 获取列表\n"
msg = msgTitle2 + "test app-test-list\nprod app-prod-list"
elif msg == "test":
msg = msgTitle
for i in appTest:
msg = msg + i + " " + appInfoMap[i][1] + "\n"
elif msg == "prod":
msg = msgTitle
for i in appProd:
msg = msg + i + " " + appInfoMap[i][1] + "\n"
msg = msg.rstrip('\n')
send_txt_msg(msg,webhook)
return "succeed"
else:
msg = f"已收到: {msg} \n发送 help@cici 查看支持指令"
send_txt_msg(msg,webhook)
return "succeed"
else:
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S')," no ddGroup config for ",ddGroup)
webhook = ding_webhook_default
msg = f"已收到: {msg} \n未发现组{ddGroup}支持指令"
send_txt_msg(msg,webhook)
return "succeed"
#webhook
ding_webhook_base_url = "https://oapi.dingtalk.com/robot/send?access_token="
ding_webhook_default = ding_webhook_base_url + ding_webhook_default_token
ding_webhook_test = ding_webhook_default
#webhook url for jenkins
JenkinsBaseUrl = os.getenv("JenkinsBaseUrl")
#job
appDeploy = "test-app-deploy/buildWithParameters?token=cicdTest&app_branch=master&app_build=true&docker_build=true&create_git_tag=false¬ice_msg=true&app_deploy=true&image_update=true&input_pass=true&deploy_tag=tag&deploy_env="
#ci url
appDeployUrl = JenkinsBaseUrl + appDeploy
#hybrid list
appTest = {
"#app-test-k8s-list:": ["","", ""],
"s201": ["test","app-web", appDeployUrl],
"s202": ["test","app-svc", appDeployUrl],
"s203": ["test","app-api", appDeployUrl],
"s204": ["test","app-event", appDeployUrl],
"s205": ["test","app-admin", appDeployUrl],
}
appProd = {
"#app-prod-k8s-list:": ["","", ""],
"s101": ["prod","app-web", appDeployUrl],
"s102": ["prod","app-svc", appDeployUrl],
"s103": ["prod","app-api", appDeployUrl],
"s104": ["prod","app-event", appDeployUrl],
"s105": ["prod","app-admin", appDeployUrl],
}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8091)
本文来自博客园,作者:blog-elvin-vip,转载请注明原文链接:https://www.cnblogs.com/elvi/p/18619018