Я новичок в JIRA и Kanban. Я ожидал этого, когда создам эпопею и свяжу с ней какие-то истории и задания. Статус эпоса автоматически изменится (например, на выполненное), когда все истории и задачи, связанные с ним, будут выполнены. Но, похоже, это не так. Я могу переместить эпос из журнала невыполненных работ в столбец «Готово», даже если связанные с ним задачи и истории все еще находятся в очереди. Есть ли способ заставить JIRA предотвратить это?
Есть ли способ автоматически изменить эпическое состояние на выполненное, когда все связанные истории и задачи выполнены?
Ответы (2)
Я работал над чем-то подобным. Мое намерение состояло в том, чтобы назначить все связанные задачи другого конкретного пользователя, когда статус меняется на определенное состояние.
Я сделал это с помощью постфункции рабочего процесса типа: «Установить значение поля на константу или выражение Groovy».
В вашей ситуации я бы сделал следующее:
- перейдите к переходу «Закрыть» и нажмите кнопку «Настроить».
- выберите постфункции и добавьте тип, который я вам сказал.
- отметьте чекбокс, который говорит выполнять, только если условие истинно
- установите свое условие. Наверное, что-то вроде issue.epic = your epic.
- Затем вы добавляете свой сценарий, в котором вы восстанавливаете все проблемы, связанные с эпосом, и проверяете их статус.
- Создайте свою логику так, чтобы, если все было так, как должно быть, вы просто меняли статус, используя объект MutableIssue.
- помните, что поле будет изменено этим скриптом, и я предполагаю, что вы не можете выбрать статус в качестве поля для установки. Если это произойдет, выберите «Сводка» и сохраните текущее значение, используйте его для завершения сценария и установите итоговое значение, такое же, как и у вас.
- Опубликуйте свой рабочий процесс.
Извините, если непонятно, но сложно объяснить. Дайте мне знать, если вам понадобится что-нибудь еще.
PD: Если вы просто хотите сделать это в определенный момент, а не для каждого эпика автоматически, просто добавьте плагин Script Runner и запустите свой скрипт в консоли. Намного легче.
С Уважением
Может быть, это вам поможет: я использовал jira с системным языком, установленным на "Русский" (и я плохо разбираюсь в Groovy), поэтому приведенный ниже сценарий содержит языковые зависимости (вам следует отредактировать код, если вы используете язык, отличный от моего языка системы jira! На минимум изменений)
- Используйте плагин Scrip Runner
Создайте «Пользовательский слушатель» и вставьте код (код не так хорош, как может быть, но он работает):
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!" }