一、场景

日常一般会通过jira bug面板筛选条件筛选出bug,如:经办人、状态、标签等,但这需要人为主动去筛选搜索,如果有一个定时每日钉钉群、飞书群提醒每个人截止当日bug情况就比较直观,对测试团队成员进度把控也有一定辅助左右。

二、方案设计

群消息,对应人员点击消息链接,跳转具体页面。

这边是通过jira issue 筛选器获取到URL

status = 已解决 AND assignee in (康丽婷) ORDER BY priority DESC, updated DESC

将jira issue页面筛选后的url进行解码,获得具体地址

UrlEncode编码/UrlDecode解码 - 站长工具

三、server RESTful API

(一)钉钉机器人 webhook 对接

1.封装

dingtalk-rebot.js

'use strict'
const assert = require('assert')
const exec = require( 'child_process' ).execclass DingTalkRobot {constructor (accessToken) {assert(accessToken, 'accessToken is necessary!')this.accessToken = accessToken}/*** text 类型* text String 必填 文本内容* isAtAll 选填 是否抄送所有人*/sendText(text = '', isAtAll = false) {this.send({msgtype: 'text',text: {content: text},at: {isAtAll: isAtAll}})}/*** link类型* text String 必填 文本内容* title String 必填 消息标题* picUrl String 必填 展示图片* messageUrl String 必填 点击消息跳转的URL*/sendLink(linkObject) {this.send({msgtype: 'link',link: linkObject})}/*** 发布markdown 消息* {*  "title":"杭州天气",*  "text": "#### 杭州天气\n"*  }* @param markdownContent*/sendMarkdown(markdownContent) {const { title = '无题', text = ''} = markdownContentthis.send({msgtype: 'markdown',markdown: {title,text}})}send(contentBody) {exec( `curl 'https://oapi.dingtalk.com/robot/send?access_token=${ this.accessToken }' \-H 'Content-Type: application/json' \-d '${ JSON.stringify(contentBody) }'`)}
}module.exports = DingTalkRobot

2.引入
dingtalk-rebot.js

var DingTalkRobot=require('../dingtalk-rebot')# 引入封装文件dingtalk-rebot.js
let robot = new DingTalkRobot('accesstoken')robot.sendText('jirabug hello world')
// robot.sendText('hello ding talk', true) // 抄送所有人robot.sendLink({text: 'jirabug hello dingtalk',title: 'hello wold',picUrl: 'https://placeholdit.imgix.net/~text?txtsize=14&txt=FreeGroup.org+Cool&w=800&h=600',messageUrl: 'http://baidu.com'})

accesstoken替换成钉钉机器人webhook url上面的accesstoken

(二)JIRA Client RESTful API

1.获取指定账号下jira bug数据

// With ES5
var JiraApi = require('jira-client');
var jira = '';
var fs = require('fs');
describe('JIRA API', async () => {beforeEach('Initialize', async () => {// Initializejira = new JiraApi({protocol: 'https',host: 'jira.homeking365.com', // jira域名username: 'jira账号',password: 'jira密码',apiVersion: '2',strictSSL: true});});/*** ES6* @description 获取指定账号提交的issue (获取某个账号所提交的所有bug)* @param username: string* @param open: boolean issue状态是否打开* @method getUsersIssues(username: string, open: boolean): ** @returns object {"startAt":0,"maxResults":50,"total":0,"issues":[]}*/it('getUsersIssues', async () => {try {var result = await jira.getUsersIssues('liyc', false);// await console.log(`getUsersIssues: ${JSON.stringify(result.issues)}`);// 筛选bugvar bugListOpen = []; // 激活var bugListClose = []; // 已关闭var bugListResolve = []; // 已解决var bugListReopen = []; // 重新打开// bug分类统计for (const iterator of result.issues) {switch (iterator.fields.status.name) {case '激活':bugListOpen.push(iterator);break;case '已关闭':bugListClose.push(iterator);break;case '已解决':bugListResolve.push(iterator);break;default:bugListReopen.push(iterator);break;}}// 激活 数量console.log('激活 bug数量:', bugListOpen.length);// 已解决 数量console.log('已解决 bug数量:', bugListResolve.length);// 已关闭 数量console.log('已关闭 bug数量:', bugListClose.length);// bugListReopen 数量console.log('bugListReopen bug数量:', bugListReopen.length);} catch (error) {await console.log(`getUsersIssues error:${error}`);}});});

四、应用配置

(一)钉钉

1.钉钉机器人配置

(1)使用Webhook

(2)选择关键字,输入关键字

(3)获得WebHook

(二)飞书机器人 webhook 对接

 1.新建自定义机器人

飞书群设置>添加机器人>自定义机器人>

2.安全设置

自定义关键词,当发送内容含有自定义关键词,才能成功发送钉钉机器人消息到群里!

3.lib库

(1)crypto.js

const crypto = require('crypto');
/*** 签名* @param {string} timestamp - 10位时间戳* @param {string} secret - 密钥* @returns {string} - 签名*/
exports.genSign = function (timestamp, secret) {const key = `${timestamp}\n${secret}`;const sign = crypto.createHmac('sha256', key).update('').digest('base64');return sign;
}

(2)index.js

const Robot = require('./robot');
const utils = require('./utils');
module.exports = function (option) {checkInput(option);const { webhook, secret } = option;return new Robot(webhook, secret);
};/*** 参数检查* @param {string} option.webhook* @param {string?} option.secret*/
function checkInput(option) {const { webhook, secret } = option;if(!utils.exist(webhook) || !utils.isString(webhook)) {throw new TypeError('webhook is required and expect string');}try {new URL(webhook);} catch (err) {throw new TypeError('webhook expect URL');}if (utils.exist(secret) && !utils.isString(secret)) {throw new TypeError('secret expect string');}
}

(3)robot.js

const crypto = require('./crypto');
const utils = require('./utils');
const simpleClient = require('simple-client');/*** 飞书群聊机器人* @param {string} webhook - webhook地址* @param {string} secret - 密钥* @return {Robot}*/
function Robot(webhook, secret) {this.webhook = webhook;this.secret = secret;
}/*** 发送文本消息* @param {string} text 文本* @return {Promise} - resolve({ statusCode, statusMessage, data }), reject(err);*/
Robot.prototype.sendText = function (text) {const data = {msg_type: 'text',content: {text: text}};return this.send(data);
}/*** 发送富文本消息* @param {string} title 标题* @param {array[]} texts 富文本消息按照飞书格式数组中每个元素是数字,代表一行数据 element: [{ tag, text, ... }]* @param {string} language - 语言默认中文zh_cn* @return {Promise} - resolve({ statusCode, statusMessage, data }), reject(err);*/
Robot.prototype.sendRickText = function (title, texts, language) {const defaultLanguage = 'zh_cn';language = utils.exist(language) ? language : defaultLanguage;const data = {msg_type: 'post',content: {post: {[language]: {title: title,content: texts}}}};return this.send(data);
}/*** 发送消息* @param {object} data - 对应飞书消息格式* @returns {Promise} - resolve({ statusCode, data }), reject(err);*/
Robot.prototype.send = function(data) {if (utils.exist(this.secret)) {const timestamp = utils.genTimeStamp();const sign = crypto.genSign(timestamp, this.secret);data.timestamp = timestamp;data.sign = sign;}return simpleClient.post(this.webhook, { body: data });
}module.exports = Robot;

(4)utils.js

/*** @method 生成10位时间戳* @returns string 时间戳*/function genTimeStamp() {let timestamp = Date.now();return String(timestamp).slice(0, 10);
}function exist(value) {return null != value;
}function isString(value) {return typeof value === 'string';
}module.exports = {genTimeStamp,exist,isString,
}

(5)test-feishu-robot.js

// 飞书群机器人webhook
var webhook;
// 引入飞书机器人
var robot;// setup
before("setup", () => {// 飞书群机器人webhookwebhook = 'https://open.feishu.cn/open-apis/bot/v2/hook/xxx';// 引入飞书机器人robot = require('../../src/feishu/lib/index.js')({webhook});
});// teardown
after("teardown",()=>{console.log("done")
})describe('发送消息', async () => {it('普通文本', async () => {try {var data = await robot.sendText('JIRA bug');console.log(data);} catch (error) {console.log(error);}});it('富文本', async () => {var message = {title: 'JIRA bug 日常提醒',texts: [[{ tag: 'text', text: '张三:其余标签请' },{tag: 'a',text: '点击链接',href: 'https://open.feishu.cn/document/ukTMukTMukTM/uMDMxEjLzATMx4yMwETM'}]]};try {var data = robot.sendRickText(message.title, message.texts, 'en_us');console.log(data);} catch (error) {console.log(error);}});
});// 富文本
/**
(async () => {try {var data = robot.sendRickText(message.title, message.texts, 'en_us');console.log(data);} catch (error) {console.log(error);}
})()**/

4.相关文档

(1)旧版

发送消息卡片

发送文本

发送图片

发送富文本

查询消息已读状态

(2)新版

飞书开放平台

(三)其他应用配置方式

【语雀】

https://jingyan.baidu.com/article/c1a3101ebcc3d19f656deb8c.html

【gitee】

https://gitee.com/help/articles/4135

【github】

https://blog.csdn.net/Q563573095/article/details/79580249

【gitlab】

https://blog.csdn.net/keep_learn/article/details/105136144

【测试团队管理】Node版钉钉飞书机器人提醒团队成员每日缺陷状态相关推荐

  1. 钉钉、飞书、企业微信,还没学会赚钱

    深燃(shenrancaijing)原创 作者 | 金玙璠 编辑 | 魏佳 2022年,是国内移动办公"三巨头"取消"免费午餐"的一年. 先是阿里旗下的钉钉对企 ...

  2. 干货|Webhook配置钉钉/飞书机器人告警

    马嘉炜 | Zabbix开源社区签约专家 SRE运维工程师,六年Zabbix监控系统使用经验.在Zabbix架构设计及性能优化领域有丰富的经验,擅长监控模板制作及Zabbix API的二次开发. 官方 ...

  3. 五分钟实现Zabbix电话、短信、邮件、钉钉、飞书、企业微信等机器人报警

    Zabbix是现在企业用的比较多的开源监控系统,Zabbix电话短信报警更是运维不可缺少的报警渠道,假如半夜正在睡觉服务器异常了,这时候电话报警就非常必要. Spug推送助手针对常见的报警系统,内置好 ...

  4. 在内网也想使用微信、钉钉和飞书,怎么办?

    一上班就失联,这个情况形容在内网办公的打工人,再合适不过了. 在内网隔离的网络环境下能有效隔绝大部分的网络攻击,但同时也牺牲了效率,特别是沟通交流和文件共享. 首先是沟通. 单位内网无法登录微信,更别 ...

  5. 将钉钉、飞书、企业微信账号同步到Synology群晖NAS,并开启LDAP双因子认证

    用户使用钉钉.飞书.企业微信账号即可登录群晖 Synology NAS 等LDAP协议应用,账号的创建.删除.变更都会自动同步给下游LDAP应用,这意味着账号管理流程缩短了一倍.而流程如此高效,秘密就 ...

  6. 飞书接入ChatGPT - 将ChatGPT集成到飞书机器人,直接拉满效率

    文章目录 前言 环境列表 视频教程 1.飞书设置 2.克隆feishu-chatgpt项目 3.配置config.yaml文件 4.运行feishu-chatgpt项目 5.安装cpolar内网穿透 ...

  7. Jenkins+Allure测试报告+飞书机器人发送通知

    Python微信订餐小程序课程视频 https://blog.csdn.net/m0_56069948/article/details/122285951 Python实战量化交易理财系统 https ...

  8. python+selenium+docker+飞书机器人部署自动预约程序

    python+selenium+docker+飞书机器人部署自动预约程序 项目介绍 python+selenium 滑块验证 selenium提示元素无法操作 无法定位到元素 接口+服务器部署 本地测 ...

  9. 飞书接入ChatGPT - 将ChatGPT集成到飞书机器人,直接拉满效率 【飞书ChatGPT机器人】

    文章目录 前言 环境列表 视频教程 1.飞书设置 2.克隆feishu-chatgpt项目 3.配置config.yaml文件 4.运行feishu-chatgpt项目 5.安装cpolar内网穿透 ...

最新文章

  1. CSDN蒋涛提出技术社区三倍速定律,称下一个20年全球开发者数量将过亿
  2. 自己录制的Oracle 相关视频(陆续更新)
  3. bash: 无法为立即文档创建临时文件: 权限不够_世界顶级Linux大牛耗时三年总结出3000页Linux文档...
  4. elasticsearch 通过curl的操作
  5. bootstrap form表单提交_[Selenium]28. 处理表单元素
  6. Linux下Kill函数用法
  7. 终于记住回车和换行cr lf的来由和含义了 -参考: http://www.cnblogs.com/me115/archive/2011/04/27/2030762.html...
  8. 代码的抽象三原则【转载】
  9. 江苏省计算机学业水平测试时间,江苏2018年高中学业水平考试时间公布
  10. css无效 https_【CSS非全解02】CSS基础-文档流
  11. [转]Linux内核基础与常用命令总结
  12. 提升机器学习数学基础,这7本书一定要读-附pdf资源
  13. 【ArcGIS风暴】中国756个气象台站分布Shapefile数据下载
  14. 如何实现页面广告随时上下线、过期自动下线及到时自动上线
  15. 7. 【containerd】连接远程containerd问题
  16. 宝塔面板IP域名绑定
  17. CookieSession
  18. 在线图书销售系统顺序图_良心好用的在线学习工具,你知道和不知道的,这里都有~...
  19. 曾颖明的博客关于作者
  20. 从事人工智能行业,推荐的几本书籍

热门文章

  1. 一加9RT评测:以速度之名,为速度重新命名
  2. 微软实现Win8设备销售量4亿的5个机密
  3. HTML+CSS鲜花静态网页设计
  4. 三星玄龙骑士电竞显示器Neo G9国内首秀,闪耀登陆2021ChinaJoy与UDE展
  5. JS获取中文拼音首字母,并通过拼音首字母快速查找页面内的中文内容
  6. 机械键盘和机械手感键盘的区别 机械键盘和机械手感键盘哪个好用
  7. 新年首日涨姿势不能停:召回→排序→重排技术演进趋势深度总结
  8. 入职新手必知的劳动法
  9. 中国式家长计算机科学家攻略,中国式家长九代内攻略6个妹子方法详解
  10. 解决:Field xxClient in XXX required a bean of type 'XXX' that could not be found