Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sync of resolution #91

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 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 @@ -58,6 +58,12 @@ interface JiraProjectGroup {
*/
StatusesValueMapping statuses();

/**
* Mapping of upstream resolutions to downstream ones. Please make sure to
* review your project scheme to see which resolutions can be used.
*/
ResolutionValueMapping resolutions();

/**
* Mapping of upstream issue types to downstream ones. Please make sure to
* review your project scheme to see which issue types are available.
Expand Down Expand Up @@ -347,6 +353,15 @@ interface StatusesValueMapping extends ValueMapping {
Map<String, Set<String>> ignoreTransitionCondition();
}

interface ResolutionValueMapping extends ValueMapping {
/**
* @return The name of the resolution to apply for the transition applied to the
* upstream issue, caused by an update of a downstream issue, when
* there's no compatible backwards mapping.
*/
Optional<String> defaultUpstreamResolution();
}

interface UserValueMapping extends ValueMapping {
/**
* @return the name of the property to apply the assignee value to. With Jira
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,6 @@ private static boolean versionNeedsUpdate(JiraVersion upstreamVersion, JiraVersi
|| !Objects.equals(upstreamVersion.releaseDate, downstreamVersion.releaseDate);
}

public String upstreamUser(String mappedValue) {
return projectGroupContext.upstreamUser(mappedValue);
}

public String upstreamStatus(String mappedValue) {
return projectGroupContext.upstreamStatus(mappedValue);
}

public String toDestinationKey(String key) {
if (keyToUpdatePattern.matcher(key).matches()) {
return "%s-%d".formatted(project().projectKey(), JiraIssue.keyToLong(key));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public final class HandlerProjectGroupContext implements AutoCloseable {
private final JiraConfig.JiraProjectGroup projectGroup;
private final Map<String, String> invertedUsers;
private final Map<String, String> invertedStatuses;
private final Map<String, String> invertedResolutions;
private final Map<String, HandlerProjectContext> projectContexts;
private final Pattern sourceLabelPattern;
private final JiraUser notMappedAssignee;
Expand Down Expand Up @@ -73,6 +74,7 @@ public HandlerProjectGroupContext(String projectGroupName, JiraConfig.JiraProjec

this.invertedUsers = invert(projectGroup.users().mapping());
this.invertedStatuses = invert(projectGroup.statuses().mapping());
this.invertedResolutions = invert(projectGroup.resolutions().mapping());
this.sourceJiraClient = source;
this.destinationJiraClient = destination;

Expand Down Expand Up @@ -209,6 +211,10 @@ public String upstreamStatus(String mappedValue) {
return invertedStatuses.get(mappedValue);
}

public String upstreamResolution(String mappedValue) {
return invertedResolutions.get(mappedValue);
}

public boolean isUserIgnored(String triggeredByUser) {
return projectGroup().users().ignoredUpstreamUsers().contains(triggeredByUser);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraRemoteLink;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraSimpleObject;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTransition;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTransitionFields;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTransitions;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraUser;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraVersion;
Expand All @@ -44,7 +45,7 @@ protected void applyTransition(JiraIssue sourceIssue, JiraIssue destIssue, Strin
// no need to apply the transition :)
return;
}
prepareTransition(sourceIssue.fields.status, destIssue).ifPresent(
prepareTransition(sourceIssue.fields.status, sourceIssue.fields.resolution, destIssue).ifPresent(
jiraTransition -> context.destinationJiraClient().transition(destinationKey, jiraTransition));
}

Expand Down Expand Up @@ -229,10 +230,20 @@ private JiraUser toUser(String value) {
return new JiraUser(context.projectGroup().users().mappedPropertyName(), value);
}

protected Optional<JiraTransition> prepareTransition(JiraSimpleObject sourceStatus, JiraIssue destIssue) {
protected Optional<JiraTransition> prepareTransition(JiraSimpleObject sourceStatus, JiraSimpleObject resolution,
JiraIssue destIssue) {
String downstreamStatus = context.projectGroup().statuses().mapping()
.get(sourceStatus.name.toLowerCase(Locale.ROOT));
return prepareTransition(downstreamStatus, destIssue);
Optional<JiraTransition> transition = prepareTransition(downstreamStatus, destIssue);
if (resolution != null) {
String downstreamResolution = context.projectGroup().resolutions().mapping()
.get(resolution.name.toLowerCase(Locale.ROOT));
return transition.map(t -> {
t.fields = JiraTransitionFields.forResolution(downstreamResolution);
return t;
});
}
return transition;
}

protected Optional<JiraTransition> prepareTransition(String downstreamStatus, JiraIssue destIssue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import org.hibernate.infra.replicate.jira.service.jira.HandlerProjectGroupContext;
import org.hibernate.infra.replicate.jira.service.jira.client.JiraRestException;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraFields;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssue;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssueTransition;
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraTransition;
import org.hibernate.infra.replicate.jira.service.reporting.ReportingConfig;

Expand Down Expand Up @@ -84,12 +82,9 @@ private Optional<JiraTransition> prepareTransition(JiraIssue issue) {
Optional<String> deletedStatus = context.projectGroup().statuses().deletedStatus();
if (deletedStatus.isPresent()) {
prepareTransition(deletedStatus.get(), issue);
JiraTransition transition = new JiraTransition();
transition.transition = new JiraIssueTransition(deletedStatus.get());

Optional<String> deletedResolution = context.projectGroup().statuses().deletedResolution();
deletedResolution.ifPresent(
name -> transition.properties().put("fields", Map.of("resolution", Map.of("name", name))));
JiraTransition transition = new JiraTransition(deletedStatus.get(), deletedResolution.orElse(null));

return Optional.of(transition);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,26 @@ protected void doRun() {

String statusDownstream = issue.fields.status.name.toLowerCase(Locale.ROOT);
String statusCurrent = sourceIssue.fields.status.name.toLowerCase(Locale.ROOT);
String resolutionDownstream = issue.fields.resolution != null
? issue.fields.resolution.name.toLowerCase(Locale.ROOT)
: null;

if (context.projectGroup().statuses().ignoreTransitionCondition().getOrDefault(statusCurrent, Set.of())
.contains(statusDownstream)) {
return;
}

String statusNew = context.upstreamStatus(statusDownstream);
String resolution = context.upstreamResolution(resolutionDownstream);

prepareTransition(statusNew, sourceIssue)
prepareTransition(statusNew, resolution, sourceIssue)
.ifPresent(jiraTransition -> context.sourceJiraClient().transition(sourceKey, jiraTransition));
}

protected Optional<JiraTransition> prepareTransition(String upstreamStatus, JiraIssue issue) {
protected Optional<JiraTransition> prepareTransition(String upstreamStatus, String resolution, JiraIssue issue) {
return statusToTransition(issue.fields.status.name, upstreamStatus, () -> JiraTransitions
.findRequiredTransitionId(context.sourceJiraClient(), failureCollector, upstreamStatus, issue))
.map(JiraTransition::new);
.map(id -> new JiraTransition(id, resolution));
}

protected Optional<String> statusToTransition(String from, String to, Supplier<Optional<String>> transitionFinder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class JiraFields extends JiraBaseObject {
public JiraIssue parent;
public ZonedDateTime created;
public ZonedDateTime updated;
public JiraSimpleObject resolution;

public static JiraFields empty() {
JiraFields fields = new JiraFields();
Expand All @@ -42,8 +43,8 @@ public static JiraFields empty() {
@Override
public String toString() {
return "JiraFields{" + "summary='" + summary + '\'' + ", description=" + description + ", priority=" + priority
+ ", issuetype=" + issuetype + ", project=" + project + ", labels=" + labels + "otherProperties="
+ properties() + '}';
+ ", issuetype=" + issuetype + ", project=" + project + ", resolution=" + resolution + ", labels="
+ labels + "otherProperties=" + properties() + '}';
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,24 @@
public class JiraTransition extends JiraBaseObject {
public JiraIssueTransition transition;
public JiraUpdate update;
public JiraTransitionFields fields;

public JiraTransition() {
}

public JiraTransition(String transitionId) {
this(transitionId, null);
this(transitionId, null, null);
}

public JiraTransition(String transitionId, String comment) {
public JiraTransition(String transitionId, String resolution) {
this(transitionId, resolution, null);
}

public JiraTransition(String transitionId, String resolution, String comment) {
transition = new JiraIssueTransition(transitionId);
if (resolution != null) {
fields = JiraTransitionFields.forResolution(resolution);
}
if (comment != null && !comment.isBlank()) {
update = new JiraUpdate();
JiraBaseObject c = new JiraBaseObject();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.hibernate.infra.replicate.jira.service.jira.model.rest;

import org.hibernate.infra.replicate.jira.service.jira.model.JiraBaseObject;

public class JiraTransitionFields extends JiraBaseObject {

public JiraSimpleObject resolution;

public static JiraTransitionFields forResolution(String resolution) {
if (resolution == null) {
return null;
}
JiraTransitionFields fields = new JiraTransitionFields();
fields.resolution = new JiraSimpleObject();
fields.resolution.name = resolution;
return fields;

}

@Override
public String toString() {
return "JiraTransitionFields{" + "resolution=" + resolution + "otherProperties=" + properties() + '}';
}

}
1 change: 1 addition & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ jira.project-group."hibernate".priorities.default-value=3
jira.project-group."hibernate".statuses.default-value=1
jira.project-group."hibernate".issue-link-types.parent-link-type=10011
jira.project-group."hibernate".users.default-value=-1
jira.project-group."hibernate".resolutions.default-value=Done

jira.project-group."hibernate".scheduled.cron=off

Expand Down
Loading