Skip to content

Commit 06d6732

Browse files
committed
Add "ignore transitions" rules
1 parent e6cb05d commit 06d6732

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

src/main/java/org/hibernate/infra/replicate/jira/JiraConfig.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Base64;
55
import java.util.Map;
66
import java.util.Optional;
7+
import java.util.Set;
78

89
import io.smallrye.config.ConfigMapping;
910
import io.smallrye.config.WithDefault;
@@ -293,6 +294,7 @@ interface IssueTypeValueMapping extends ValueMapping {
293294
* epic-short-label in the upstream (source) Jira instance.
294295
*/
295296
Optional<String> epicLinkSourceLabelCustomFieldName();
297+
296298
/**
297299
* @return The name of a custom field that represents the "epic name" i.e.
298300
* epic-short-label in the downstream (destination) Jira instance.
@@ -312,6 +314,23 @@ interface StatusesValueMapping extends ValueMapping {
312314
* closing the issue deleted upstream before archiving it.
313315
*/
314316
Optional<String> deletedTransition();
317+
318+
/**
319+
* @return A map where the {@code key} is the upstream status name, and the
320+
* corresponding {@code value} contains the names of the downstream
321+
* status names. If the downstream issue is currently in one of the
322+
* statuses present in the value set then the transition for status
323+
* ({@code key}) should not be applied.
324+
* <p>
325+
* This allows both skipping unnecessary transitions
326+
* {@code "status a" -> "status a" } as well as to keep the downstream
327+
* issue in the status modified downstream if it is within the "group"
328+
* of statuses "mapped" to the upstream one. This can be useful when
329+
* e.g. downstream workflow has both {@code New} and {@code Ready}
330+
* statuses, and users move new issues to the {@code Ready} status
331+
* issues downstream, without an override from an upstream updates.
332+
*/
333+
Map<String, Set<String>> ignoreTransitionCondition();
315334
}
316335

317336
interface UserValueMapping extends ValueMapping {

src/main/java/org/hibernate/infra/replicate/jira/service/jira/handler/JiraIssueAbstractEventHandler.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
import java.net.URI;
44
import java.util.ArrayList;
55
import java.util.List;
6+
import java.util.Locale;
67
import java.util.Objects;
78
import java.util.Optional;
9+
import java.util.Set;
810
import java.util.regex.Pattern;
911

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

3032
protected void applyTransition(JiraIssue sourceIssue, String destinationKey) {
33+
JiraIssue destIssue = context.destinationJiraClient().getIssue(destinationKey);
34+
applyTransition(sourceIssue, destIssue, destinationKey);
35+
}
36+
37+
protected void applyTransition(JiraIssue sourceIssue, JiraIssue destIssue, String destinationKey) {
38+
Set<String> statusesToIgnore = context.projectGroup().statuses().ignoreTransitionCondition()
39+
.getOrDefault(sourceIssue.fields.status.name.toLowerCase(Locale.ROOT).replace(' ', '-'), Set.of());
40+
if (statusesToIgnore.contains(destIssue.fields.status.name.toLowerCase(Locale.ROOT))) {
41+
// no need to apply the transition :)
42+
return;
43+
}
3144
prepareTransition(sourceIssue).ifPresent(
3245
jiraTransition -> context.destinationJiraClient().transition(destinationKey, jiraTransition));
3346
}
3447

3548
protected void updateIssueBody(JiraIssue sourceIssue, String destinationKey) {
3649
JiraIssue destIssue = context.destinationJiraClient().getIssue(destinationKey);
50+
updateIssueBody(sourceIssue, destIssue, destinationKey);
51+
}
52+
53+
protected void updateIssueBody(JiraIssue sourceIssue, JiraIssue destIssue, String destinationKey) {
3754
JiraIssue issue = issueToCreate(sourceIssue, destIssue);
3855

3956
updateIssue(destinationKey, issue, sourceIssue, context.notMappedAssignee());

src/main/java/org/hibernate/infra/replicate/jira/service/jira/handler/JiraIssueUpsertEventHandler.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,16 @@ protected void doRun() {
2929
context.createNextPlaceholderBatch(destinationKey);
3030

3131
try {
32-
updateIssueBody(sourceIssue, destinationKey);
32+
JiraIssue destIssue = context.destinationJiraClient().getIssue(destinationKey);
33+
34+
updateIssueBody(sourceIssue, destIssue, destinationKey);
3335
// remote "aka web" links cannot be added in the same request and are also not
3436
// returned as part of the issue API.
3537
// We "upsert" the remote link pointing to the "original/source" issue that
3638
// triggered the sync with an additional call:
3739
context.destinationJiraClient().upsertRemoteLink(destinationKey, remoteSelfLink(sourceIssue));
3840
// issue status can be updated only through transition:
39-
applyTransition(sourceIssue, destinationKey);
41+
applyTransition(sourceIssue, destIssue, destinationKey);
4042
// and then we want to add a link to a parent, if the issue was actually a
4143
// sub-task which we've created as a task:
4244
prepareParentLink(destinationKey, sourceIssue).ifPresent(context.destinationJiraClient()::upsertIssueLink);

0 commit comments

Comments
 (0)