设为首页 收藏本站
开启辅助访问 快捷导航
菜单
猿人部落 主页 资讯 查看内容

Atlassian In Action-Jira之二次开发(五)

2019-8-1 05:13 发布者: lfgzh1979 评论 0 查看 1712
到如今已经写到了第五章节,现实上离Jira的官方体系已经越来越远,本章节的内容根本上已经完全离开了Jira这个体系自

到如今已经写到了第五章节,现实上离Jira的官方体系已经越来越远,本章节的内容根本上已经完全离开了Jira这个体系自己,而是依赖Jira的API接口和数据库举行开发了。紧张包罗如下几个功能:

  • 职员任务排期管理
  • 汗青职员任务排期查抄
  • BI报表

注意
由于我们的二次开发根本都是做成静态页面,但是大量利用了Jira的API接口,为了可以大概方便的利用。以是我们将这些页面放到Jira的容器当中,在此中创建了一个目次。如许就可以大概和Jira在同一个域名下,只要Jira体系有登录,访问接口都是不必要额外举行认证的。

职员任务排期管理

配景

这个页面的需求现实上是源自于BigGantt这个插件,我们前面讲过这是一个非常强盛的插件,对于迭代的任务管理有很大的资助。
但是在逐步的利用过程中产生了一个管理的场景:有一个重点项目占用了一部分的研发力气,必要相识这部分的任务安排环境。而且当任务有变更的时间,可以大概快速相识是否另有研发资源可以安排调解。
分析之后我们相识到,现实上这个需求有两个重点,一要有一个任务列表(通常是一个JQL语句筛选出的主任务列表),二要有涉及的人力资源和子任务清单。BigGantt是否满足呢?它可以根据JQL筛选出任务列表,但是这个列表只可以大概以任务为视角睁开。当我们必要评估某个职员排期怎样,是否可以大概插入大概调解时,没有太好的界面来清晰的展示。

实现

以是我们计划了如下的功能:
在这里插入图片形貌
可以看到这个界面分为三部分
第一部分是文本输入框,用于实行JQL语句。
第二部分是主任务列表。
第三部分是人力资源甘特图。
任务列表通过

https://jira.yourdomain.com/rest/api/2/search?jql=' + jqlstr + '&maxResults=9999

接口就可以获取任务的json数据。

人力资源甘特图是写了一个python脚本启动了一个web容器,从jira的底层数据库读取数据,构造返回json。获取的就是全部研发中央职员未完成的子任务。为什么要用python?由于Jira这台服务器上没有其他容器,如果要安装tomcat之类的太贫苦,还要做一个mvc框架之类的东西大概直接写jsp,太贫苦了。
下面给出获取数据的sql:

         select concat(a.id) as pissueId,
                ifnull(concat("EXEPD-", k.issuenum),"无父任务") as pikey,
                k.SUMMARY as pisummary,
                concat("EXEPD-", a.issuenum) as ikey,
                '子任务' as itype,
                a.SUMMARY,
                b.pname,
                ifnull(ifnull(i.vname, e.customvalue), '版本为空') as vname,
                ac.last_name,
                ad.lower_parent_name,
                (case ad.lower_parent_name
                   when 'org-pd-qa' then '测试'
                   when 'org-pd-frontside-h5' then '前端h5'
                   when 'org-pd-frontside-native' then '原生'
                   when 'org-pd-serverside-b' then '业务'
                   when 'org-pd-serverside-a' then '架构'
                   when 'org-pd-product' then '产物UI'
                   else '' end) as deptname,
                DATE_FORMAT(a.CREATED,'%Y-%m-%d') as creatdate,
                DATE_FORMAT(a.DUEDATE,'%m/%d/%Y') as enddate,
                DATE_FORMAT(cd.DATEVALUE,'%m/%d/%Y') as startdate,
                concat(ab.ID) as asid,
                concat(ad.parent_id) as dpid,
                concat(ROUND(ifnull(a.TIMESPENT,0) / 3600, 1)) as timespent,
                ab.lower_user_name asname,
                1 as nums
         from jiraissue a
                join app_user ab on ab.user_key = a.ASSIGNEE
                join cwd_user ac on ac.lower_user_name = ab.lower_user_name
                join cwd_membership ad on ad.lower_child_name = ab.lower_user_name and ad.lower_parent_name in
                                                                                       ('org-pd-frontside-h5',
                                                                                        'org-pd-frontside-native',
                                                                                        'org-pd-serverside-a',
                                                                                        'org-pd-serverside-b',
                                                                                        'org-pd-qa',
                                                                                        'org-pd-product')
                join issuestatus b on b.ID = a.issuestatus
                left join nodeassociation f on f.SOURCE_NODE_ID = a.ID and f.ASSOCIATION_TYPE = 'IssueFixVersion'
                left join projectversion i on i.ID = f.SINK_NODE_ID
                left join customfield c on c.cfname = '修正状态'
                left join customfieldvalue d on d.CUSTOMFIELD = c.id and d.ISSUE = a.ID
                left join customfieldoption e on e.CUSTOMFIELD = c.ID and e.id = d.STRINGVALUE
                left join customfieldvalue dd on dd.CUSTOMFIELD = 10400 and dd.ISSUE = a.ID
                left join customfieldoption de on de.CUSTOMFIELD = 10400 and de.id = dd.STRINGVALUE
                left join customfield cc on cc.cfname = '开始日'
                left join customfieldvalue cd on cd.CUSTOMFIELD = cc.id and cd.ISSUE = a.ID
                left join issuelink j on j.DESTINATION = a.ID
                left join jiraissue k on k.ID = j.SOURCE
         where a.issuetype = 10003
           and a.PROJECT = 10000
           and a.issuestatus != 10001
            and a.PRIORITY<=5
          order by ad.lower_parent_name,ac.last_name,cd.DATEVALUE

这内里就涉及到对于Jira数据库的相识了,jiraissue 是issue的库,app_user 是职员库,cwd_membership是分组库,customfield 、customfieldoption 、customfieldvalue 是自界说字段的三件套。这个语句并不能直接在任何Jira体系上利用,由于内里有较多的自界说设置规则。
比如我们增长了开始日、修正状态两个自界说字段,而且界说了一种优先级是在当前的管理面板忽略的(以是才有 PRIORITY<=5 这个条件)。

有了任务列表和人力资源列表,我们就要把两者团结起来了。
起首我们利用的Gantt插件是JSGantt,这个插件还是很简单的。我们的甘特图是三层的,第一层是部分,第二层是职员,第三层是任务。为了在甘特图可以大概清晰的展示和任务的关系,我们循环全部职员的子任务,当父任务在第二部分的任务列表中时,在第一层的标题打一个星号,第二层打两个星号,第三次打三个星号,而且任务的甘特图体现为赤色。除了无法拖拽修改任务排期,根本可以大概满足我们上述的需求了。这个图也变成现在我用于查抄迭代和职员排期的最紧张的工具。

汗青职员任务排期查抄

配景

全部人的任务都是在不停滚动的,每个人天天都面临至少四种任务:

  • 操持性任务(长期)
  • 插入性任务(长期或短期,告急)
  • 线上标题(紧张告急短期)
  • Bug标题(紧张不告急)

以是作为管理职员要管理好研发资源就要妥善的调和任务安排,而且时间还要针对任务变更环境举行分析,对内部职员大概外部需求单元提出改进需求。

实现

这是一个管理需求,基于职员视角,观察一段时间区间内某个职员的任务厘革环境并举行分析。
由于观察的区间并不确定,以是我们要将每个人天天的未完成子任务缓存,而且根据页面必要获取指定时间区间的子任务聚合。
先给出终极结果:
在这里插入图片形貌
我们要做的事变:

  1. 定时任务用于天天定时生存未完成子任务
  2. 背景服务根据前端传入条件查询而且聚合任务信息
  3. 前端展示

定时任务利用python作为脚本,利用crontab破晓实行,每次都以日期作为表名新生存一个表,脚本现实上利用职员任务排期管理中的sql,用 create table z_subtask_%date () 包起来就OK了。
服务端还是利用上面的python启动的web服务,增长一个接口。
终极界面紧张视角为职员,字段包罗:

  • 主任务和子任务的信息
  • 何时创建(确认何时吸取到任务)
  • 开始日期和竣事日期,如果日期从未厘革过则是一个日期,如果有调解则是日期区间
  • 连续天数,是指这个任务有缓存在多少天的库中,即新建之后连续了多少天
  • 终极状态,是指到查询克制日期这天,这个任务是否完成

如许我们可以大概基原来分析某个职员他的任务操持性和耽误性,沟通相识缘故原由而且订定相应的优化方案。

BI

配景

每个构造肯定会有分析需求,无论是内部改进大概团体陈诉,可以大概有图表和数据表的完备出现是最根本的要求。这个需求最早是实验在Jira的插件中来探求的,但是实验了不少插件发现都达不到预期的结果,终极只能转入了利用第三方BI框架,底层数据源自己构造。

实现

选定的就是阿里云的QuickBI。
展示一部分结果图:
工时维度BI报表
在这里插入图片形貌
迭代任务分析
在这里插入图片形貌
有了BI工具,现实上报表制作成什么样就没有太大束缚了。根本紧张还是针对工时、迭代任务两部分的分析。
我提供给各人两份sql参考Jira的底层数据库构造数据的示例:
迭代任务构造:

select concat('C_', a.id) as pissueId,
       concat("EXEPD-", a.issuenum) as ikey,
       k.pname as itype,
       a.SUMMARY,
       sum((ifnull(a.TIMESPENT, 0) + ifnull(j.TIMESPENT, 0)) / 3600) as allTimeSpent,
       sum(ifnull(ll.timeworked, 0)) / 3600 as cuMonthTimeSpent,
       b.pname,
       ifnull(ifnull((case when i.vname='hotfix' then null else i.vname end) , e.customvalue), '版本为空') as vname,
       1 as nums
from jiraissue a
       join issuestatus b on b.ID = a.issuestatus
       left join nodeassociation f on f.SOURCE_NODE_ID = a.ID and f.ASSOCIATION_TYPE = 'IssueFixVersion'
       left join projectversion i on i.ID = f.SINK_NODE_ID
       left join customfield c on c.cfname = '修正状态'
       left join customfieldvalue d on d.CUSTOMFIELD = c.id and d.ISSUE = a.ID
       left join customfieldoption e on e.CUSTOMFIELD = c.ID and e.id = d.STRINGVALUE
       left join issuelink g on g.SOURCE = a.ID and g.LINKTYPE = 10100
       left join jiraissue j on j.ID = g.DESTINATION
       join issuetype k on k.id = a.issuetype
       left join (select l.issueid, sum(ifnull(l.timeworked, 0)) as timeworked
                  from worklog l
                  where date_format(l.STARTDATE, '%Y-%m') = '2019-06'
                  group by l.issueid) ll on ll.issueid = j.ID
where a.issuenum in (1,2,3,4)
  and a.PROJECT = 10000
group by a.ID

工时分析:

select a.id,
       a.issueid,
       concat('C_', ifnull(n.SOURCE, a.id)) as pissueId,
       a.worklogbody,
       (a.timeworked / 3600) as wmin,
       (a.timeworked / 3600 / (case d.lower_parent_name
                                 when 'org-pd-qa' then 10
                                 when 'org-pd-frontside-h5' then 9
                                 when 'org-pd-frontside-native' then 5
                                 when 'org-pd-serverside-b' then 12
                                 when 'org-pd-serverside-a' then 7
                                 when 'org-pd-product' then 9
                                 else '' end)) as wminperm,
       date_format(a.STARTDATE, '%Y-%m-%d') as sdate,
       date_format(a.STARTDATE, '%Y-%m') as sdm,
       c.last_name,
       (case d.lower_parent_name
          when 'org-pd-qa' then '测试'
          when 'org-pd-frontside-h5' then '前端h5'
          when 'org-pd-frontside-native' then '原生'
          when 'org-pd-serverside-b' then '业务'
          when 'org-pd-serverside-a' then '架构'
          when 'org-pd-product' then '产物UI'
          else '' end) as deptname,
       k.pname,
       concat(h.pkey, '-', e.issuenum) as issuekey,
       concat('https://jira.exexm.com/browse/', h.pkey, '-', e.issuenum) as issueurl,
       (case j.pname when 'Sub-task' then '任务与子任务' when 'Task' then '任务与子任务' else j.pname end) as issuetypename,
       -- (case j.pname when 'Sub-task' then '子任务' when 'Task' then '任务' else j.pname end) as issuetypename,
       e.SUMMARY,
       -- ifnull(ifnull(i.vname, ifnull(m.customvalue,mm.customvalue)), '版本为空') as vname,
       i.vname,
       (case
          when
            (i.vname is null and (l.STRINGVALUE is not null or ll.STRINGVALUE is not null))
            then 'hotfix'
          when
            (i.vname is null or i.vname='')
            then '版本为空'
          when
            a.issueid = 10752
            then '一样平常事件'
          when
            a.issueid = 18019
            then '规划外事件'
          else i.vname end) as cord
from worklog a
       join app_user b on b.user_key = a.AUTHOR
       join cwd_user c on c.lower_user_name = b.lower_user_name
       join cwd_membership d on d.lower_child_name = b.lower_user_name and d.lower_parent_name in
                                                                           ('org-pd-frontside-h5',
                                                                            'org-pd-frontside-native',
                                                                            'org-pd-serverside-a',
                                                                            'org-pd-serverside-b',
                                                                            'org-pd-qa',
                                                                            'org-pd-product')
       join jiraissue e on e.ID = a.issueid
       left join nodeassociation f on f.SOURCE_NODE_ID = e.ID and f.ASSOCIATION_TYPE = 'IssueFixVersion'
       left join projectversion i on i.ID = f.SINK_NODE_ID
       join issuetype j on j.id = e.issuetype
       join project h on h.ID = e.PROJECT
       left join issuelink n on n.DESTINATION = e.ID and n.LINKTYPE = 10100
       join issuestatus k on k.ID = e.issuestatus
       left join customfieldvalue l on l.CUSTOMFIELD = 10025 and l.ISSUE = n.SOURCE
       left join customfieldoption m on m.CUSTOMFIELD = 10025 and m.id = l.STRINGVALUE
       left join customfieldvalue ll on ll.CUSTOMFIELD = 10025 and ll.ISSUE = e.ID
       left join customfieldoption mm on mm.CUSTOMFIELD = 10025 and mm.id = ll.STRINGVALUE
where a.STARTDATE >= '2019-1-1'
order by a.STARTDATE asc

总结

写到这里,全部关于Jira的利用的整理现在告一段落了。但是这应该还只是一个阶段性里程碑而已,我们的构造架构在进步,过程管理方法在进步,Atlassian也在进步,以是我们也不能停下自己的脚步。Jira还只是完备生态当中的一个环节,我们要更好的构造我们的研发团队,反面另有一些同伴给各人先容。一个企业、研发团队要能恒久的生存和进步,就必要积聚,但是不能口口相传,还要能举行阶段性的梳理和进步。下一章就是企业怎样利用Confluence举行知识积聚。



路过

雷人

握手

鲜花

鸡蛋
收藏 邀请
上一篇:什么是正向代理?下一篇:【2019最新版】性能测试入门-Jmeter工具与监控全方位打造

相关阅读

一周热门

头条攻略!

日排行榜

相关分类