我是JIRA和看板的新手。当我制作一部史诗并将一些故事和任务链接到它时,我期待着它。当完成与其相关的所有故事和任务时,史诗的状态将自动改变(例如完成)。但似乎事实并非如此。我可以将史诗从Backlog移动到Done列,即使其链接的任务和故事仍在积压中。有没有办法让JIRA防止这种情况发生?
答案 0 :(得分:1)
我一直在做类似的事情。我的目的是在状态变为特定状态时,将特定用户的所有相关问题设置为特定用户。
我使用类型工作流的后期功能执行此操作:“将字段值设置为常量或Groovy表达式”
在你的情况下,我会做以下事情:
对不起,如果不清楚,但很难解释。如果你需要其他的话,请告诉我。
PD:如果您只是想在某个特定时刻而不是每个史诗自动执行此操作,只需添加Script Runner插件,然后在控制台中运行您的脚本。更容易。
此致
答案 1 :(得分:1)
也许它会帮助你: 我使用系统语言设置为“俄语”的jira(并且我不熟悉groovy),这就是为什么下面的脚本包含语言依赖性(如果你使用与我的jira系统语言不同,你应该编辑代码!至少改变)
创建“自定义侦听器”并粘贴代码(代码不是很好,但它正在工作):
import com.atlassian.jira.component.ComponentAccessor;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.link.IssueLinkManager;
import com.atlassian.jira.issue.link.IssueLink;
import com.atlassian.jira.issue.ModifiedValue;
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
import com.atlassian.jira.issue.customfields.option.Options;
import com.atlassian.jira.issue.customfields.option.Option;
import com.atlassian.jira.issue.fields.config.FieldConfig;
import com.atlassian.jira.issue.customfields.manager.OptionsManager;
import com.atlassian.jira.ComponentManager;
ComponentManager componentManager = ComponentManager.getInstance();
def groupMan = ComponentAccessor.getGroupManager()
def authCon = ComponentAccessor.getJiraAuthenticationContext()
def customFieldManager = ComponentAccessor.getCustomFieldManager()
def changeHolder = new DefaultIssueChangeHolder();
IssueManager issueManager = ComponentAccessor.getIssueManager();
OptionsManager optionsManager = componentManager.getComponentInstanceOfType(OptionsManager.class);
IssueLinkManager issueLinkManager = ComponentAccessor.getIssueLinkManager()
def curUser = authCon.getUser()
def issue = event.issue
def epicLinkCf = customFieldManager.getCustomFieldObjects(issue).find {it.name == 'Epic Link'}
if(!epicLinkCf) {log.warn "No Epic Link field"; return}
log.warn "Existing Epic Link: ${epicLinkCf.getValue(issue)}"
String epicIssue = epicLinkCf.getValue(issue)
Issue epic = issueManager.getIssueObject(epicIssue) // epicKey is passed into your script
// Check if Epic link is exist
if(!epic)
return true
def newEpicState = "Сделано"
log.warn "Epic: " + epic
List<IssueLink> allOutIssueLink = issueLinkManager.getOutwardLinks(epic.getId());
for (Iterator<IssueLink> outIterator = allOutIssueLink.iterator(); outIterator.hasNext();) {
IssueLink issueLink = (IssueLink) outIterator.next();
log.warn "child link type: " + issueLink.getIssueLinkType().getName()
// Check status of all issues from epic
if (issueLink.getIssueLinkType().getName() == "Epic-Story Link") {
Issue chIssue = issueLink.getDestinationObject();
log.warn "child state: " + chIssue.getStatusObject().getName()
if(chIssue.getStatusObject().getName() == "В процессе") {
newEpicState = "В процессе"
} else if (chIssue.getStatusObject().getName() != "Закрыто" && newEpicState != "В процессе") {
newEpicState = "Сделать"
}
}
}
def epicStatusCf = customFieldManager.getCustomFieldObjects(epic).find {it.name == 'Epic Status'}
log.warn "Current epic status: " + epicStatusCf.getValue(epic)
FieldConfig epicStatusFieldConfig = epicStatusCf.getRelevantConfig(epic);
String oldStatus = epicStatusCf.getValue(epic)
log.warn "New epic status: " + newEpicState
// Set new status if it necessary
if (oldStatus != newEpicState) {
Options epicStatusOptions = optionsManager.getOptions(epicStatusFieldConfig);
Option epicStatusDoneOption = epicStatusOptions.getOptionForValue(newEpicState, null);
epicStatusCf.updateValue(null, epic, new ModifiedValue(epic.getCustomFieldValue(epicStatusCf),epicStatusDoneOption),changeHolder)
log.warn "Epic status is updated!"
}