Jira Automation 与飞书 IM 打通

Jira Automation 与飞书 IM 打通

作者简介:YY哥,10年+软件研发行业经验,4年研发经验,6年项目管理与过程改进经验。 曾服务于保险、金融、电商和智慧旅游行业,目前就职于国内一家互联网医疗科技公司,主导PMO体系建设与效能改进工作。

三个月前发布了一篇打通Jira与钉钉和企业微信不再难实践文章,朋友圈有个飞书同学说他家IM也可以打通,5月份研究了一把,基本完成了Jira与飞书IM打通目标。总体感受是,相对于与钉钉与企业微信的打通方式,与飞书打通显得复杂一些

由于需要根据JQL动态查询Jira列表后输出到飞书IM,必须使用smart values语法来做遍历,输出符合飞书要求的markdown格式webhook消息体。第一个挑战就是markdown,钉钉与企业微信的markdown格式大同小异,切换起来非常容易。但是,飞书格式完全是另外的套路,而且格式似乎没法排版,都在content里。

{ "msg_type": "interactive", "card": { "config": { "wide_screen_mode": true }, "header": { "title": { "tag": "plain_text", "content": "【小蜜提醒】-项目逾期任务" }, "template":"red" }, "elements": [{ "tag": "markdown", "content": "截至当前,本项目有 **{{issues.size}}** 个任务已逾期,请相关同学尽快处理!{{#issues}}\n --------------\n**项目名称:**{{project.name}} - {{sprint.name}}\n**问题概述:**[{{key}}]({{url}}) {{summary}}\n**结束日期:**{{customField_10307}}\n**经办人:**{{assignee.displayName}}\n{{/}}" }] }}

 

在官网文档中,发现飞书群自定义机器人支持通过邮箱等@到具体的人,当时对这个功能点很兴奋,因为jira账号是企业邮箱前缀,那么,在jira账号后拼接@company.com,放在webhook消息体内可以完美实现@Jira经办人、报告人、工作日志登记人等。这点在钉钉和企业微信群自定义机器人中是不支持通过邮箱@人的。折腾了几把,总@空人,后来咨询了飞书售前、客服等人都不知道什么原因。最后,来了一个高级技术支持,告诉我只有自建应用才支持通过邮箱来@人。出于安全考虑, 群自定义机器人只能通过open_id来@人。当时心情很复杂,在群聊中也表达了当时的心情,不支持就在官网文档中写明,而不是让用户折腾好久后,被告之此路不通!飞书同学也坦言,涉及到跨团队共同完善用户手册,内部存在一点协同问题。

 

众所周知,Jira支持Issue层级的自定义字段扩展,但是好像不支持基于User层级的自定义字段扩展(至少一周前是这么认为)。后来再次研究smart values官网手册发现有个Entity Properties概念,可以用来设置User层级的属性,比如:用户手机号、邮箱、家庭住址等等。那么,它也支持在user层级扩展一个飞书open_id字段。通过Jira配置->用户管理->点击用户名->编辑用户属性->添加key/value为openid及其值,来实现为该用户添加一个自定义属性openid,使用<at id = {{assignee.legacyProperties."jira.meta.openid"}}><at>实现@人,完整代码如下:

{ "msg_type": "interactive", "card": { "config": { "wide_screen_mode": true }, "header": { "title": { "tag": "plain_text", "content": "【小蜜提醒】-项目逾期任务" }, "template":"red" }, "elements": [{ "tag": "markdown", "content": "截至当前,本项目有 **{{issues.size}}** 个任务已逾期,请相关同学尽快处理!{{#issues}}\n --------------\n**项目名称:**{{project.name}} - {{sprint.name}}\n**问题概述:**[{{key}}]({{url}}) {{summary}}\n**结束日期:**{{customField_10307}}\n**经办人:**{{assignee.displayName}} <at id = {{assignee.legacyProperties."jira.meta.openid"}}><at>\n{{/}}" }] }}

 

接下来面临的问题是,如何批量获取飞书open_id?又如何批量更新到Jira系统呢?前者有官网文档说明(不做赘述),后者需要研究下相关Jira数据库表。最终选择的解决方案如下:

CREATE PROCEDURE AddUserPropertywithFeishuOpenID ( userName VARCHAR ( 100 ), openID VARCHAR ( 100 ) ) BEGIN DECLARE userID INTEGER; DECLARE propertyID INTEGER; SET userID = ( SELECT ID FROM app_user WHERE lower_user_name = userName ); -- 仅针对未添加用户属性,才执行下面语句 IF userID is not NULL AND NOT EXISTS(SELECT * FROM propertyentry WHERE ENTITY_NAME = "ApplicationUser" AND ENTITY_ID = userID AND PROPERTY_KEY = "jira.meta.openid") THEN BEGIN SET propertyID = ( SELECT MAX( ID ) + 1 FROM propertyentry ); INSERT INTO propertyentry ( ID, ENTITY_NAME, ENTITY_ID, PROPERTY_KEY, propertytype ) VALUES ( propertyID, "ApplicationUser", userID, "jira.meta.openid", 5 ); INSERT INTO propertystring ( ID, propertyvalue ) VALUES ( propertyID, openID ); END; ELSE SELECT userName + "已经存在"; END IF; END -- 调用存储过程添加用户属性:飞书OpenID CALL AddUserPropertywithFeishuOpenID('yyge','ou_xxxxxxxxxx'); -- 检查脚本 SELECT e.user_key, e.lower_user_name, t.property_key, s.propertyvalue as FieldValue FROM app_user e JOIN propertyentry t ON e.ID = t.entity_id JOIN propertystring s ON t.ID = s.ID WHERE t.property_key = "jira.meta.openid" -- 删除脚本 DELETE FROM propertystring WHERE ID IN (SELECT ID FROM propertyentry WHERE property_key = "jira.meta.openid"); DELETE FROM propertyentry WHERE property_key = "jira.meta.openid"; -- 注意必须将sequence_value_item中的SEQ_ID更新到较大的值,否则上面脚本可能导致无法通过Jira配置后台手工添加user property select * from sequence_value_item where seq_name = 'OSPropertyEntry';

作者简介

文章来源YY哥的小屋公众号:https://mp.weixin.qq.com/s/e63QrC4Z98TnOFW81VE-jA