Skip to content

Commit

Permalink
Add "ignore transitions" rules
Browse files Browse the repository at this point in the history
  • Loading branch information
marko-bekhta committed Nov 13, 2024
1 parent e6cb05d commit 06d6732
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
19 changes: 19 additions & 0 deletions src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Base64;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import io.smallrye.config.ConfigMapping;
import io.smallrye.config.WithDefault;
Expand Down Expand Up @@ -293,6 +294,7 @@ interface IssueTypeValueMapping extends ValueMapping {
* epic-short-label in the upstream (source) Jira instance.
*/
Optional<String> epicLinkSourceLabelCustomFieldName();

/**
* @return The name of a custom field that represents the "epic name" i.e.
* epic-short-label in the downstream (destination) Jira instance.
Expand All @@ -312,6 +314,23 @@ interface StatusesValueMapping extends ValueMapping {
* closing the issue deleted upstream before archiving it.
*/
Optional<String> deletedTransition();

/**
* @return A map where the {@code key} is the upstream status name, and the
* corresponding {@code value} contains the names of the downstream
* status names. If the downstream issue is currently in one of the
* statuses present in the value set then the transition for status
* ({@code key}) should not be applied.
* <p>
* This allows both skipping unnecessary transitions
* {@code "status a" -> "status a" } as well as to keep the downstream
* issue in the status modified downstream if it is within the "group"
* of statuses "mapped" to the upstream one. This can be useful when
* e.g. downstream workflow has both {@code New} and {@code Ready}
* statuses, and users move new issues to the {@code Ready} status
* issues downstream, without an override from an upstream updates.
*/
Map<String, Set<String>> ignoreTransitionCondition();
}

interface UserValueMapping extends ValueMapping {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;

import org.hibernate.infra.replicate.jira.JiraConfig;
Expand All @@ -28,12 +30,27 @@ public JiraIssueAbstractEventHandler(ReportingConfig reportingConfig, HandlerPro
}

protected void applyTransition(JiraIssue sourceIssue, String destinationKey) {
JiraIssue destIssue = context.destinationJiraClient().getIssue(destinationKey);
applyTransition(sourceIssue, destIssue, destinationKey);
}

protected void applyTransition(JiraIssue sourceIssue, JiraIssue destIssue, String destinationKey) {
Set<String> statusesToIgnore = context.projectGroup().statuses().ignoreTransitionCondition()
.getOrDefault(sourceIssue.fields.status.name.toLowerCase(Locale.ROOT).replace(' ', '-'), Set.of());
if (statusesToIgnore.contains(destIssue.fields.status.name.toLowerCase(Locale.ROOT))) {
// no need to apply the transition :)
return;
}
prepareTransition(sourceIssue).ifPresent(
jiraTransition -> context.destinationJiraClient().transition(destinationKey, jiraTransition));
}

protected void updateIssueBody(JiraIssue sourceIssue, String destinationKey) {
JiraIssue destIssue = context.destinationJiraClient().getIssue(destinationKey);
updateIssueBody(sourceIssue, destIssue, destinationKey);
}

protected void updateIssueBody(JiraIssue sourceIssue, JiraIssue destIssue, String destinationKey) {
JiraIssue issue = issueToCreate(sourceIssue, destIssue);

updateIssue(destinationKey, issue, sourceIssue, context.notMappedAssignee());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ protected void doRun() {
context.createNextPlaceholderBatch(destinationKey);

try {
updateIssueBody(sourceIssue, destinationKey);
JiraIssue destIssue = context.destinationJiraClient().getIssue(destinationKey);

updateIssueBody(sourceIssue, destIssue, destinationKey);
// remote "aka web" links cannot be added in the same request and are also not
// returned as part of the issue API.
// We "upsert" the remote link pointing to the "original/source" issue that
// triggered the sync with an additional call:
context.destinationJiraClient().upsertRemoteLink(destinationKey, remoteSelfLink(sourceIssue));
// issue status can be updated only through transition:
applyTransition(sourceIssue, destinationKey);
applyTransition(sourceIssue, destIssue, destinationKey);
// and then we want to add a link to a parent, if the issue was actually a
// sub-task which we've created as a task:
prepareParentLink(destinationKey, sourceIssue).ifPresent(context.destinationJiraClient()::upsertIssueLink);
Expand Down

0 comments on commit 06d6732

Please sign in to comment.