jira是有bug的hook订阅的,但是权限得是管理员,所以只能用笨方法,轮询自己的bug,遇到新的bug,向企业微信发送消息。
jira的bug查询接口
http://companyName/rest/api/2/search
企业微信机器人hook地址
https://qyapi.weixin.qq.com/*******
jira 查询自己bug的jql查询语法
project = *** AND issuetype = 故障 AND status in (Open, 'In Progress', Reopened) AND affectedVersion in *** AND assignee = ***
具体语法需要自己查询。直接上代码:
package main
import (
"net/http"
"time"
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
)
// 思路:
// 使用定时器,每5分钟查询jira中bug,如果bug不在内存中,加入内存并通知企业微信机器人。
// 限制,晚上7点后到早上8点略过不执行。
type issue_request struct {
jql string
key []string
}
type issues struct {
Expend string `json:"expend"`
Id string `json:"id"`
Self string `json:"self"`
Key string `json:"key"`
Fields field `json:"fields"`
}
type field struct {
Summary string `json:"summary"`
Status interface{} `json:"status"`
}
type issueRes struct {
Expand string `json:"expend"`
StartAt int `json:"startAt"`
MaxResults int `json:"maxResults"`
Total int `json:"total"`
Issues []issues `json:"issues"`
}
type WeChatRoboatMessage struct {
Msgtype string `json:"msgtype"`
Text WeChatRoboatMessageText `json:"text"`
}
type WeChatRoboatMessageText struct {
Content string `json:"content"`
}
var bugs = map[string]string{}
func getIssues() {
/*
请求jira并将新的bug发送到企业微信
*/
url := "http://***/rest/api/2/search"
jql := "project = ***"
issueRes, err := GetAllIssue(url, jql)
if err != nil {
fmt.Print(err)
}
if issueRes.Total > 0 {
for _, value := range issueRes.Issues {
if _, ok := bugs[value.Key]; !ok {
urlKey := "http://******/browse/" + value.Key
bugs[urlKey] = value.Fields.Summary
var WeChatRoboatMessageDemo WeChatRoboatMessage
WeChatRoboatMessageDemo.Msgtype = "text"
WeChatRoboatMessageDemo.Text.Content = urlKey + " " + value.Fields.Summary
messageDemo, err := json.Marshal(WeChatRoboatMessageDemo)
if err != nil {
fmt.Println(err.Error())
return
}
// print(messageDemo)
err = WeChatRobot(messageDemo)
if err != nil {
fmt.Println("企业微信机器人信息发送失败" + err.Error())
return
}
} else {
println(value.Key + "已经存在")
}
}
}
}
func WeChatRobot(message []byte) error {
/* 向企业微信机器人发送消息 */
wechatBusinessRobot:= "https://***"
res, err := http.Post(wechatBusinessRobot,
"application/json;charset=utf-8", bytes.NewBuffer(message))
if err != nil {
fmt.Println("Fatal error ", err.Error())
}
defer res.Body.Close()
return nil
}
func GetAllIssue(url string, jql string) (issueRes, error) {
/*
向jira请求,获取用户的所有bug,并返回反序列化的结构体
url:请求的地址
jql:查询语句
*/
var issueResStr issueRes
info := make(map[string]interface{})
// info["jql"] = "project = VDI AND issuetype = 故障 AND status in (Open, 'In Progress', Reopened) AND affectedVersion = ArcherDT_V1.7 AND assignee = sundedong"
info["jql"] = jql
// fields := ["keys","summary"]
var fields []string
fields = append(fields, "keys")
fields = append(fields, "summary")
info["fields"] = fields
bytesData, err := json.Marshal(info)
if err != nil {
fmt.Println(err.Error())
return issueResStr, err
}
//fmt.Println(bytesData)
reader := bytes.NewReader(bytesData)
// url := "http:///rest/api/2/search" //要访问的Url地址
request, err := http.NewRequest("POST", url, reader)
defer request.Body.Close() //程序在使用完回复后必须关闭回复的主体
if err != nil {
fmt.Println(err.Error())
return issueResStr, err
}
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
request.Header.Set("Authorization", "Basic ***")
//必须设定该参数,POST参数才能正常提交,意思是以json串提交数据
client := http.Client{}
resp, err := client.Do(request) //Do 方法发送请求,返回 HTTP 回复
if err != nil {
fmt.Println(err.Error())
return issueResStr, err
}
respBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println(err.Error())
return issueResStr, err
}
err = json.Unmarshal(respBytes, &issueResStr)
if err != nil {
fmt.Println("json unmarshal fail: ", err)
}
return issueResStr, err
}
func main() {
ticker := time.NewTicker(time.Minute * 5) //创建一个周期性定时器
defer ticker.Stop()
for {
// fmt.Println(i, "====>", <-ticker.C)
current_time := time.Now()
hour := current_time.Hour()
// 粗略的仅当早8点到晚上7点发送消息
if hour >= 8 && hour <= 19 {
getIssues()
}
}
}
这是很简单的版本,jql,企业微信地址也是写死的,重启后数据也会丢失,后续可以把jql,查询语句放到配置文件,bug也可以放到本地缓存文件。甚至把gin装上,配置这些东西。
附上大致的流程图。