Jira 当所有链接的故事和任务完成时,有没有办法自动将epic状态更改为done

Jira 当所有链接的故事和任务完成时,有没有办法自动将epic状态更改为done,jira,kanban,Jira,Kanban,我不熟悉JIRA和看板。当我创作一部史诗并将一些故事和任务链接到它时,我期待着它。当所有与史诗相关的故事和任务完成时,史诗的状态将自动更改(例如,完成)。但情况似乎并非如此。我可以将epic从Backlog移动到Done列,即使其链接的任务和故事仍在Backlog中。有没有办法让吉拉阻止这种事情发生 我一直在做类似的事情。我的意图是设置当状态更改为特定状态时,将另一个用户的所有链接问题分配给特定用户 我使用类型为“将字段值设置为常量或Groovy表达式”的工作流的postfunction实现了这

我不熟悉JIRA和看板。当我创作一部史诗并将一些故事和任务链接到它时,我期待着它。当所有与史诗相关的故事和任务完成时,史诗的状态将自动更改(例如,完成)。但情况似乎并非如此。我可以将epic从Backlog移动到Done列,即使其链接的任务和故事仍在Backlog中。有没有办法让吉拉阻止这种事情发生

我一直在做类似的事情。我的意图是设置当状态更改为特定状态时,将另一个用户的所有链接问题分配给特定用户

我使用类型为“将字段值设置为常量或Groovy表达式”的工作流的postfunction实现了这一点

在你的情况下,我会做以下工作:

  • 转到“关闭”转换,然后单击配置
  • 选择postfunctions,然后添加我告诉过你的类型
  • 标记表示仅在条件为真时执行的复选框
  • 设定你的条件。可能类似于issue.epic=您的epic
  • 然后添加脚本,在脚本中恢复链接到epic的所有问题,并检查它们的状态
  • 创建您的逻辑,这样,如果一切正常,您只需使用MutableIssue对象更改状态
  • 请记住,此脚本将修改一个字段,我猜您不能选择状态作为要设置的字段。如果发生这种情况,请选择summary,并存储当前值,然后使用它结束脚本,并设置summary值,与之前的值相同
  • 发布您的工作流程
对不起,如果不清楚,但很难解释。如果你还需要什么,请告诉我

PD:如果你只是想在某个特定的时刻这样做,而不是自动为每一部史诗,只需添加脚本运行插件,并在控制台中运行你的脚本。容易多了

关于

也许它能帮助你: 我使用jira时系统语言设置为“俄语”(我对groovy不太在行),这就是为什么下面的脚本包含语言依赖项(如果您使用的是与我的jira系统语言不同的语言,您应该编辑代码!至少要更改)

  • 使用Scrip Runner插件
  • 创建“自定义侦听器”并粘贴代码(代码不是很好,但可以正常工作):

    导入com.atlassian.jira.component.component访问器;
    导入com.atlassian.jira.issue.IssueManager;
    导入com.atlassian.jira.issue.issue;
    导入com.atlassian.jira.issue.link.IssueLinkManager;
    导入com.atlassian.jira.issue.link.IssueLink;
    导入com.atlassian.jira.issue.ModifiedValue;
    导入com.atlassian.jira.issue.util.DefaultIssueChangeHolder;
    导入com.atlassian.jira.issue.customfields.option.Options;
    导入com.atlassian.jira.issue.customfields.option.option;
    导入com.atlassian.jira.issue.fields.config.FieldConfig;
    导入com.atlassian.jira.issue.customfields.manager.OptionsManager;
    导入com.atlassian.jira.ComponentManager;
    ComponentManager ComponentManager=ComponentManager.getInstance();
    def groupMan=ComponentAccessor.getGroupManager()
    def authCon=ComponentAccessor.getJiraAuthenticationContext()
    def customFieldManager=ComponentAccessor.getCustomFieldManager()
    def changeHolder=新的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(问题)。查找{it.name=='EPICLINK'}
    如果(!epicLinkCf){log.warn“无Epic链接字段;返回}
    log.warn“现有Epic链接:${epicLinkCf.getValue(问题)}”
    字符串epicIssue=epicLinkCf.getValue(问题)
    Issue epic=issueManager.getIssueObject(epicIssue)//epicKey被传递到脚本中
    //检查Epic链接是否存在
    如果(!史诗)
    返回真值
    def newEpicState=“Сааааа”
    log.warn“Epic:+Epic
    List allOutIssueLink=issueLinkManager.getOutwardLinks(epic.getId());
    for(迭代器outIterator=allOutIssueLink.Iterator();outIterator.hasNext();){
    IssueLink IssueLink=(IssueLink)outIterator.next();
    log.warn“子链接类型:”+issueLink.GetIssueLink().getName()
    //检查epic中所有问题的状态
    如果(issueLink.GetIssueLink().getName()=“史诗故事链接”){
    Issue-chIssue=issueLink.getDestinationObject();
    log.warn“子状态:+chIssue.getStatusObject().getName()
    如果(chIssue.getStatusObject().getName()==“БППццС”){
    newEpicState=“СПццццц”
    }否则,如果(chIssue.getStatusObject().getName()!=“ааффф”和&newEpicState!=“аПффффффф1092{
    newEpicState=“Сааа”
    }
    }
    }
    def epicStatusCf=customFieldManager.getCustomFieldObjects(epic)。查找{it.name=='epic Status'}
    log.warn“当前epic状态:+epicStatusCf.getValue(epic)
    FieldConfig epicStatusFieldConfig=epicStatusCf.getRelevantConfig(epic);
    字符串oldStatus=epicStatusCf.getValue(epic)
    log.warn“新epic状态:”+newEpicState
    //如有必要,设置新状态
    如果(旧状态!=新状态){
    选项epicStatusOptions=optionsManager.getOptions(epicStatusFieldConfig);
    Option epicStatusDoneOption=epicStatusOptions.getOptionForValue(newEpicState,null);
    epicStatusCf.updateValue(null、epic、新修改值(epic.getCustomFieldValue(epicStatusCf)、epicStatusDoneOption)、changeHolder)
    log.warn“Epic状态已更新!”
    }
    

  • 我会试试你说的。我不知道我们可以用JIRAYes编写脚本,我使用groovy脚本。可能需要scriprunner插件。我不记得自动取款机了。让我们知道我在UI中找不到任何与“关闭”转换或后功能相关的部分。你能告诉我在哪里能找到吗,我
    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!"
    }