JIRA Agile 脚本注解参考
1. 批量修改Summary为需求标题
import com.atlassian.jira.component.ComponentAccessorimport org.apache.log4j.Levellog.setLevel(Level.DEBUG)def user = ComponentAccessor.jiraAuthenticationContext.loggedInUserdef projectManager = ComponentAccessor.projectManagerdef issueManager = ComponentAccessor.issueManagerdef cfManager = ComponentAccessor.customFieldManagerdef cfReqTitle = cfManager.getCustomFieldObjectsByName("需求标题").first()def vpProjects = projectManager.projects.findAll { it.projectCategory?.name == "VP传统项目"}def issueList = vpProjects.collect { project -> issueManager.getIssueIdsForProject(project.id).findAll { def issue = issueManager.getIssueObject(it) def summary = issue.summary def reqTitle = issue.getCustomFieldValue(cfReqTitle) reqTitle != null && summary != reqTitle }}.flatten()issueList.each { def issue = issueManager.getIssueObject(it as Long) def reqTitle = issue.getCustomFieldValue(cfReqTitle) // issue.summary = reqTitle log.info "${issue.key}: summary: ${issue.summary} => 需求标题: ${reqTitle}"} |
2. 查找VPID重复的Issue
import com.atlassian.jira.component.ComponentAccessorimport com.atlassian.jira.issue.Issueimport org.apache.log4j.Levelimport com.atlassian.activeobjects.external.ActiveObjectsimport com.onresolve.scriptrunner.runner.ScriptRunnerImpldef ao = ScriptRunnerImpl.getOsgiService(ActiveObjects)log.setLevel(Level.DEBUG)def projectManager = ComponentAccessor.projectManagerdef issueManager = ComponentAccessor.issueManagerdef changeHistoryManager = ComponentAccessor.changeHistoryManagerdef cfManager = ComponentAccessor.customFieldManagerdef cfVPID = cfManager.getCustomFieldObjectsByName("VPID").first()def getVPIssues = { projectManager.projects.findAll { it.projectCategory?.name == "VP传统项目" }.collect { project -> def ids = issueManager.getIssueIdsForProject(project.id) issueManager.getIssueObjects(ids) }.flatten()}def getVPIDIssueMap = { getVPIssues().findAll { def issue = it as Issue issue.getCustomFieldValue(cfVPID) != null }.groupBy { def issue = it as Issue issue.getCustomFieldValue(cfVPID) }}def vpidIssueMap = getVPIDIssueMap() |
3. 查找关联需求
import com.atlassian.jira.component.ComponentAccessorimport com.atlassian.jira.issue.Issueimport org.apache.log4j.Levellog.setLevel(Level.DEBUG)def projectManager = ComponentAccessor.projectManagerdef issueManager = ComponentAccessor.issueManagerdef cfManager = ComponentAccessor.customFieldManagerdef cfRelatedReqNo = cfManager.getCustomFieldObjectsByName("关联需求编号").first()def cfReqNo = cfManager.getCustomFieldObjectsByName("VP需求编号").first()def vpIssues = projectManager.projects.findAll { it.projectCategory?.name == "VP传统项目"}.collectMany { project -> def ids = issueManager.getIssueIdsForProject(project.id) issueManager.getIssueObjects(ids)}def reqIssueMap = vpIssues.collectMany{ def issue = it as Issue def reqNo = issue.getCustomFieldValue(cfReqNo) as String reqNo ? [[reqNo, issue]] : []}.collectEntries()vpIssues.each { def issue = it as Issue def relatedReqNo = issue.getCustomFieldValue(cfRelatedReqNo) as String if (relatedReqNo) { def reqNoList = relatedReqNo.split(";") reqNoList.each { Issue target = reqIssueMap[it] if (target) { log.info("${issue.key} => ${target.key}") } } }} |
4. 在【发布预告】issue created listener 中自动创建 2 个 Sprint(确认上线清单、待上线清单),并将该 issue 加入到第一个 Sprint 中
import com.atlassian.jira.issue.Issueimport com.atlassian.greenhopper.service.rapid.view.RapidViewServiceimport com.atlassian.greenhopper.service.sprint.Sprintimport com.atlassian.greenhopper.service.sprint.SprintServiceimport com.atlassian.greenhopper.service.sprint.SprintIssueServiceimport com.atlassian.greenhopper.model.rapid.RapidViewimport com.atlassian.jira.component.ComponentAccessorimport com.onresolve.scriptrunner.runner.customisers.JiraAgileBeanimport com.onresolve.scriptrunner.runner.customisers.WithPluginimport org.apache.log4j.Level log.setLevel(Level.DEBUG)@WithPlugin("com.pyxis.greenhopper.jira") @JiraAgileBeanRapidViewService rapidViewService @JiraAgileBeanSprintService sprintService@JiraAgileBeanSprintIssueService sprintIssueService // 脚本功能介绍: 在【发布预告】issue created listener 中自动创建 2 个 Sprint(确认上线清单、待上线清单),并将该 issue 加入到第一个 Sprint 中def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser def createSprint = { String sprintName, RapidView rapidView -> Sprint sprint = Sprint.builder().with { name(sprintName) rapidViewId(rapidView.id) }.build() def result = sprintService.createSprint(currentUser, sprint) def s = result.value log.info("sprint 自动创建成功。sprint:" + s) return s} if (issue.issueType.name == '发布预告') { def project = issue.projectObject def rapidViewName = "${project.key}发布面板" RapidView rapidView = rapidViewService.findRapidViewsByName(currentUser, rapidViewName).value.first() if (rapidView == null){ log.error("sprint 自动创建失败。${project.key}发布面板 不存在。") } else { // 注意:sprint 创建有先后顺序。先建 确认上线清单,再建 待上线清单 Sprint s = createSprint("确认上线清单 ${issue.key}", rapidView) createSprint("待上线清单 ${issue.key}", rapidView) // 把刚刚创建的【发布预告】issue 加入其中的 确认上线清单 if(s != null){ log.info("把刚刚创建的【发布预告】issue ( ${issue.key} ) 加入确认上线清单。sprint:"+ s) Collection<Issue> issueList = new ArrayList<Issue>() issueList.add(issue) sprintIssueService.moveIssuesToSprint(currentUser, s, issueList) } } } |
5. 监听所有 “确认上线清单”、“待上线清单” sprint,一旦有 sprint Active 了,就发邮件通知这个 sprint 中所有 issue 的 reporter(此脚本已经不用了)
import com.atlassian.jira.issue.Issueimport com.atlassian.jira.user.ApplicationUserimport com.atlassian.mail.Emailimport com.atlassian.mail.server.SMTPMailServerimport com.atlassian.jira.component.ComponentAccessorimport com.atlassian.greenhopper.service.sprint.Sprintimport com.atlassian.greenhopper.service.sprint.Sprint.Stateimport com.atlassian.greenhopper.service.sprint.SprintIssueServiceimport com.onresolve.scriptrunner.runner.customisers.JiraAgileBeanimport com.onresolve.scriptrunner.runner.customisers.WithPluginimport org.apache.log4j.Level log.setLevel(Level.DEBUG) @WithPlugin("com.pyxis.greenhopper.jira")@JiraAgileBeanSprintIssueService sprintIssueService// 功能描述: 监听所有 “确认上线清单”、“待上线清单” sprint,一旦有 sprint Active 了,就发邮件通知这个 sprint 中所有 issue 的 reporterdef currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUserSMTPMailServer mailServer = ComponentAccessor.getMailServerManager().getDefaultSMTPMailServer()def sprint = event.sprint as Sprintif (sprint.state == Sprint.State.ACTIVE) { if (sprint.getName().contains("确认上线清单") || sprint.getName().contains("待上线清单")) { def emailSubject = "本周上线清单已更新,请留意上线预告仪表板" def emailBody = "您提交的需求/生产缺陷已加入“${sprint.getName()}”,请确认或查看。" def outcome = sprintIssueService.getIssuesForSprint(currentUser, sprint) Iterable<Issue> issues = outcome.getValue() LinkedHashSet<String> emails = new LinkedHashSet<String>() issues.each { def issue = it as Issue //def projectCategory = issue.getProjectObject().projectCategory //if (projectCategory != null){ // if (projectCategory.name == "VP传统项目" || projectCategory.name == "自研项目") { ApplicationUser reporter = issue.getReporter() if (reporter != null) { def emailAddress = reporter.getEmailAddress() if (emailAddress != null) { emails.add(emailAddress) } } //} //} } emails.each { def emailAddress = it as String Email email = new Email(emailAddress) email.setSubject(emailSubject) email.setBody(emailBody) mailServer.send(email) } } } |
6. VP 【需求】已有 issue:申请人 → 申请人员 处理(本脚本只执行一次)
import com.atlassian.jira.component.ComponentAccessorimport com.atlassian.jira.issue.MutableIssueimport org.apache.log4j.Level import com.atlassian.activeobjects.external.ActiveObjectsimport com.onresolve.scriptrunner.runner.ScriptRunnerImplimport com.atlassian.jira.bc.JiraServiceContextImpl;import com.atlassian.jira.bc.JiraServiceContext;import com.atlassian.jira.bc.issue.search.SearchService;import com.atlassian.jira.bc.user.search.UserSearchParams;import com.atlassian.jira.bc.user.search.UserSearchService;import com.atlassian.jira.user.ApplicationUser;import com.atlassian.jira.security.JiraAuthenticationContext;import com.atlassian.jira.event.type.EventDispatchOption; // 脚本功能说明:VP传统项目 【需求】已有 issue:申请人 → 申请人员 处理(本脚本只执行一次)def ao = ScriptRunnerImpl.getOsgiService(ActiveObjects) log.setLevel(Level.DEBUG) def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUserdef projectManager = ComponentAccessor.projectManagerdef issueManager = ComponentAccessor.issueManagerdef userManager = ComponentAccessor.userManagerdef userSearchService = ComponentAccessor.userSearchServicedef changeHistoryManager = ComponentAccessor.changeHistoryManagerdef cfManager = ComponentAccessor.customFieldManagerdef cf_SQR = cfManager.getCustomFieldObjectsByName("申请人").first()def cf_SQRY = cfManager.getCustomFieldObjectsByName("申请人员").first() def getVPIssues = { projectManager.projects.findAll { it.projectCategory?.name == "VP传统项目" }.collect { project -> def ids = issueManager.getIssueIdsForProject(project.id) issueManager.getIssueObjects(ids) }.flatten()} getVPIssues().findAll { def issue = it as MutableIssue if (issue.issueType.name == "需求") { log.info("开始处理 VP传统项目 【需求】已有 issue(" + issue.key + "):“申请人”-->“申请人员”..." ) def sqrValue = issue.getCustomFieldValue(cf_SQR) if (sqrValue != null && !"".equals(sqrValue)) { def s = sqrValue.toString(); /** * “申请人员” 匹配规则: * * 0. 若“申请人”为空,则将“申请人员”设置为 IT_Service * 1. “申请人”里面,如果包含 中英文逗号、中英文分号、中文顿号 写了多个人名,那么只处理标点之前的第一个 * 2. 根据人名,在 JIRA 里面找用户,如果能够找到唯一一个,那么就用这个用户 * 3. 如果没有找到,则用 IT_Service * 4. 如果有多个,优先选择邮箱是 @tpl.cntaiping.com 的。若邮箱均不包含 @tpl.cntaiping.com,则用 IT_Service。 * 5. 如果还有多个,判断部门(这条下一版本做) * 6. 还有多个,用 IT_Service(这条下一版本做) */ // 只处理第一个人名 if (s.contains(",")) { s = s.substring(0, s.indexOf(",")); } else if (s.contains(";")) { s = s.substring(0, s.indexOf(";")); } else if (s.contains(",")) { s = s.substring(0, s.indexOf(",")); } else if (s.contains(";")) { s = s.substring(0, s.indexOf(";")); } else if (s.contains("、")) { s = s.substring(0, s.indexOf("、")); } s = s.trim(); JiraServiceContext jsc = new JiraServiceContextImpl(loggedInUser); UserSearchParams userSearchParams = new UserSearchParams(false, true, true); List<ApplicationUser> userList0 = userSearchService.findUsers(jsc, s, userSearchParams); // 上一行只是模糊搜索。接下来对姓名进行精准匹配: ArrayList<ApplicationUser> userList2 = new ArrayList<>(); for (ApplicationUser u : userList0) { if (s.equals(u.getUsername()) || s.equals(u.getDisplayName())) { userList2.add(u); } } ApplicationUser user = null; if (userList2.size() == 1) { // 只找到一个用户 user = userList2.get(0); } else if (userList2.size() > 1) { // 找到多个用户,优先选择邮箱是 @tpl.cntaiping.com 的。若邮箱均不包含 @tpl.cntaiping.com,则用 IT_Service。 boolean foundByTPL = false; for (ApplicationUser u : userList2) { if (u.getEmailAddress().contains("@tpl.cntaiping.com")) { foundByTPL = true; user = u; break; } } if (!foundByTPL) { user = userManager.getUserByName("IT_Service"); } } else { // 找到 0 个用户 user = userManager.getUserByName("IT_Service"); } if (user != null) { issue.setCustomFieldValue(cf_SQRY, user); issueManager.updateIssue(loggedInUser,issue, EventDispatchOption.DO_NOT_DISPATCH, false) } } else { issue.setCustomFieldValue(cf_SQRY, userManager.getUserByName("IT_Service")); issueManager.updateIssue(loggedInUser,issue, EventDispatchOption.DO_NOT_DISPATCH, false) } } } |
7. 【发布预告】流转到需求管理人时,在点击 issue 界面中的 “已标记确认” 按钮后,状态变更时触发:post function 脚本中让【发布预告】所在 sprint 中的需求及生产缺陷的 “标签” 字段值变为 “确认上线”,并将该 sprint acitve
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
import com.atlassian.jira.issue.Issueimport com.atlassian.jira.issue.MutableIssueimport com.atlassian.jira.issue.label.Labelimport com.atlassian.jira.issue.label.LabelManagerimport com.atlassian.jira.user.ApplicationUserimport com.atlassian.jira.component.ComponentAccessorimport com.atlassian.greenhopper.service.sprint.Sprintimport com.atlassian.greenhopper.service.sprint.Sprint.Stateimport com.atlassian.greenhopper.service.sprint.SprintServiceimport com.atlassian.greenhopper.service.sprint.SprintIssueServiceimport com.onresolve.scriptrunner.runner.customisers.JiraAgileBeanimport com.onresolve.scriptrunner.runner.customisers.WithPluginimport com.atlassian.jira.event.type.EventDispatchOptionimport org.apache.log4j.Levelimport java.util.* log.setLevel(Level.DEBUG) @WithPlugin("com.pyxis.greenhopper.jira") @JiraAgileBeanSprintIssueService sprintIssueService@JiraAgileBeanSprintService sprintServicedef issueManager = ComponentAccessor.issueManagerdef labelManager = ComponentAccessor.getComponent(LabelManager)def loggedInUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser// 功能描述:让【发布预告】所在 sprint 中的需求及生产缺陷的 “标签” 字段值变为 “确认上线”,并将该 sprint acitve。log.info("------ 【发布预告】" + issue.getKey() + "“已标记确认”。开始查询该 issue 所属 sprint 中的 需求、生产缺陷:")def sprints_outcome = sprintIssueService.getSprintsForIssue(loggedInUser, issue)Iterable<Sprint> sprints = sprints_outcome.getValue()sprints.each { def sprint = it as Sprint log.info("所属 sprint:" + sprint.getName()) def issues_outcome = sprintIssueService.getIssuesForSprint(loggedInUser, sprint) Iterable<Issue> issues = issues_outcome.getValue() issues.each { def issue2 = it as Issue def mutableIssue = issueManager.getIssueObject(issue2.getId()) def mutableIssue_issueTypeName = mutableIssue.getIssueType().getName() if ("需求".equals(mutableIssue_issueTypeName) || "生产缺陷".equals(mutableIssue_issueTypeName)) { log.info("找到符合要求的 issue:" + mutableIssue.getKey() + ",开始修改其 “标签” 字段值为 “确认上线”...") // 先清空原有 label mutableIssue.setLabels(new HashSet<Label>()) issueManager.updateIssue(loggedInUser, mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false) // 再设置 label labelManager.addLabel(loggedInUser, mutableIssue.getId(), "确认上线", false) } } if (sprint.isFuture()) { log.info("开始 active 当前 sprint...") Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.set(Calendar.HOUR_OF_DAY, 24); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); // active sprint 之前,必须先设置开始时间和结束时间 // 将 sprint 的开始时间设置为现在,结束时间设置为今晚 24 点 Sprint sprint2 = Sprint.builder(sprint).startDate(new Date().getTime()).endDate(calendar.getTimeInMillis()).state(Sprint.State.ACTIVE).build(); sprintService.updateSprint(loggedInUser, sprint2) } } |
8. VP传统项目 >> 【需求】工作流 >> “已发布” 的 post function:若 sprint 不为空且“用户确认发布”为空,则设置“用户确认发布”为发布,“确认上线操作用户”取“申请人员”。
import com.atlassian.jira.issue.Issueimport com.atlassian.jira.issue.MutableIssueimport com.atlassian.jira.component.ComponentAccessorimport com.atlassian.greenhopper.service.sprint.Sprintimport com.atlassian.greenhopper.service.sprint.Sprint.Stateimport com.atlassian.greenhopper.service.sprint.SprintServiceimport com.atlassian.greenhopper.service.sprint.SprintIssueServiceimport com.onresolve.scriptrunner.runner.customisers.JiraAgileBeanimport com.onresolve.scriptrunner.runner.customisers.WithPluginimport com.atlassian.jira.event.type.EventDispatchOptionimport com.atlassian.jira.user.ApplicationUserimport com.atlassian.jira.user.util.UserManagerimport org.apache.log4j.Levellog.setLevel(Level.DEBUG)// 功能描述:若 sprint 不为空且“用户确认发布”为空,则设置“用户确认发布”为发布,“确认上线操作用户”取“申请人员”。// 部署位置:VP传统项目 >> 【需求】工作流 >> “已发布” 的 post function。@WithPlugin("com.pyxis.greenhopper.jira")@JiraAgileBeanSprintIssueService sprintIssueService@JiraAgileBeanSprintService sprintServicedef issueManager = ComponentAccessor.issueManagerdef customFieldManager = ComponentAccessor.getCustomFieldManager()def userManager = ComponentAccessor.getUserManager()def optionsManager = ComponentAccessor.getOptionsManager()log.info("------ See if Sprint field is empty --------")def sprints_outcome_iterator = sprintIssueService.getSprintsForIssue(userManager.getUserByName("IT_Service"), issue).getValue().iterator()def confirm_field = customFieldManager.getCustomFieldObjectsByName("用户确认发布").iterator();if (!confirm_field.hasNext()) { log.error("找不到 '用户确认发布' 自定义字段!!!") return}MutableIssue mutableIssue = issueManager.getIssueObject(issue.getId())def cf = confirm_field.next()def confirm = cf.getValue(issue)log.info('sprints_outcome_iterator.hasNext() : ' + sprints_outcome_iterator.hasNext())log.info('confirm : '+ confirm)if (sprints_outcome_iterator.hasNext() && confirm == null) { log.info("------ sprint 不为空,但'用户确认发布'为空。需要自动修复 --------") def operator = customFieldManager.getCustomFieldObjectsByName("确认上线操作用户").iterator(); def applier = customFieldManager.getCustomFieldObjectsByName("申请人员").iterator(); if (!operator.hasNext() || !applier.hasNext()) { log.error("找不到 '确认上线操作用户' 自定义字段 或 '申请人员' 自定义字段!!!") return } // 设置 “用户确认发布” 为发布 def optionVal = optionsManager.getOptions(cf.getRelevantConfig(issue)).getOptionForValue("发布", null) log.info("optionVal:" + optionVal) mutableIssue.setCustomFieldValue(cf, optionVal) // 设置 “确认上线操作用户” 取 “申请人员” def user_field = applier.next() if (user_field != null) { def user = issue.getCustomFieldValue(user_field) as ApplicationUser mutableIssue.setCustomFieldValue(operator.next(), user) } issueManager.updateIssue(userManager.getUserByName("IT_Service"), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)} |
posted on 2021-02-09 18:45 Sunshine-jcy 阅读(255) 评论(1) 收藏 举报

浙公网安备 33010602011771号