玩转飞书项目插件开发之三---同步飞书项目到Jira Issue

618 阅读4分钟

在前序中,我们介绍了同步Jira Issue信息到飞书项目,那么如果反过来,同步过来的缺陷数据在飞书项目中发生了变化,能不能把信息同步到Jira呢,答案是肯定的,那么接下来我们就一起来看看如何将信息从飞书项目同步到Jira。

我们还是拿前面同步过来的数据做例子,给大家讲解如何操作。

时序图

下图为调用的时序图,从图中可以大致了解整个操作过程的数据流向。插件会通过Webhook监听到工作项数据的变化,再根据工作项id获取该工作项的基本信息,然后通过Jira API更新Jira。 image.png

飞书项目Webhook

如果想要近实时的感知到数据的变化,并把变化的数据同步过去,我们就要依托于飞书项目的Webhook能力。 飞书项目提供了丰富的Webhook事件,可以参考以下的帮助文档: project.feishu.cn/b/helpcente…

自动化规则

飞书项目中的Webhook可以通过自动化规则进行配置,入口在“空间配置--->自动化”。

例如,当缺陷的名称经过评估发生更改时,需要同步更新Jira中的名称字段,我们配置的自动化规则如下: 当缺陷工作项的名称字段发生变化时,就会发送一个Webhook

image.png 上述截图示例中我们配置了一个自动化规则,当缺陷工作项的名称发生变化时触发Webhook,飞书项目就会向下一步配置的webhook地址,demo.com/sync_issue 发送http请求。我们在sync_issue接口后端接收到的事件信息如下所示:

Webhook数据

{

   "header": {

       "operator": "xxx", // string, 操作者的userkey

       "event_type": "WorkitemUpdateEvent", // string, webhook的event_type

       "token": "token-xxxx", // string,注册webhook填入的token,可用于校验

       "uuid": ""  // string,幂等串

   },

   "payload": {

       "id": 5018740550, // int,64位,工作项id

       "name": "Update Issue Name", // string,工作项名称

       "project_key": "xxxxx",   // string,空间ID

       "project_simple_name": "xxxxx", // string,空间域名

       "updated_at": 1639548775000, // int,64位,更新时间戳

       "updated_by": "xxxxx",    // string,更新人的userkey

       "work_item_type_key": "issue",  // string,工作项类型

       "changed_fields": [

           {

               "field_alias": "name",  // 字段对接标识

               "field_key": "name",    // 字段key

               "field_type_key": "_name",  // 字段类型

               "pre_field_value": "This is a issue demo, please confirm it.",  // 变更前的值

               "cur_field_value": "Update Issue Name"   // 变更后的值

           },

       ]

   }

}

在上述请求结构体中,我们可以看到发生变化的工作项id,工作项名称,空间key,空间名称,工作项类型以及变化的字段,变化字段参数中会将变化字段的字段key,类型,变更前后值都一一给出。

获取工作项详情

至此,我们在逻辑中可以对上述的报文信息进行解析,获得到变更后的名称是“Update Issue Name”。 在获得到更新后的缺陷名称后,我们还要进一步得到需要更新的是哪一条Jira Issue。此时需要根据工作项id来通过工作项详情接口来获得到当前实例的基本信息。

Postman获取实例详情

image.png

获取详情代码示例

func queryWorkItemDetail(ctx context.Context, projectKey string, workItemTypeKey string,
   workItemIDs []int64, filterFields []string, expand *workitem.Expand, userKey string) (Data []*workitem.WorkItemInfo, err error) {
   log.Println("start to query work item detail")
   cli := getCli()
   if expand == nil {
      expand = &workitem.Expand{}
   }
   req := workitem.NewQueryWorkItemDetailReqBuilder().ProjectKey(projectKey).WorkItemTypeKey(workItemTypeKey).WorkItemIDs(workItemIDs).Fields(filterFields).
      Expand(expand).Build()
   resp, err := cli.WorkItem.QueryWorkItemDetail(ctx, req, core.WithUserKey(userKey))
   if err != nil {
      log.Println("QueryWorkItem detail failed, err: ", err.Error())
      return nil, err
   }
   if !resp.Success() {
      msg := fmt.Sprintf("QueryWorkItemDetail failed,api err=%s,rpc err=%s,logid=%s", resp.Error(), resp.Err.Msg, resp.RequestId())
      log.Printf("QueryWorkItemDetail failed,api err=%s,rpc err=%s,logid=%s", resp.Error(), resp.Err.Msg, resp.RequestId())
      return nil, errors.New(msg)
   }
   log.Printf("QueryWorkItemDetail success,len=%d,logid=%s", len(resp.Data), resp.RequestId())
   return resp.Data, nil
}

例如上述逻辑中我们遍历该工作项的字段信息,通过事先在字段管理中配置的关联字段的对接标识sync_jira_id,获取到Jira的ID值.

image.png

获取Jira ID信息代码示例

func getJiraID(wii *workitem.WorkItemInfo) (string, error) {
   if wii == nil {
      return "", errors.New("work item is nil")
   }
   for _, field := range wii.Fields {
      if field.FieldAlias == "sync_jira_id" {
         return field.FieldValue.(string), nil
      }
   }
   return "", errors.New("sync_jira_id not found")
}

上述代码中是通过字段的对接标识来获取字段的,因为在创建自定义字段时,字段key(field_key)是系统生成的,这个无法控制,但是我们可以指定对接标识,这个就相当于是字段别名,这个是由我们自己控制的,通过字段别名,一样可以拿到字段信息。

更新Jira

如上述逻辑所示,假如我们获得到的Jira ID 为10000。 我们拿到了变更后的内容,以及当前缺陷关联的Jira Issue,就可以调用Jira的API做字段的更新,如下图所示:

image.png 我们去Jira中查看,发现名称已经更新了

image.png

以上就是我们通过Webhook监听到工作项字段的变化,然后去更新Jira Issue的详细过程,赶快来试试吧~