Skip to content

Commit 39bf41a

Browse files
committed
Use project group context for handling events
instead of a project context. and remove dependency on project key in the requests
1 parent ddd0d3d commit 39bf41a

File tree

41 files changed

+516
-397
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+516
-397
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ interface JiraProjectGroup {
9898
* Allows customizing formatting options.
9999
*/
100100
Formatting formatting();
101+
102+
/**
103+
* Allows enabling signature verification.
104+
*/
105+
WebHookSecurity security();
101106
}
102107

103108
interface Formatting {
@@ -188,11 +193,6 @@ interface JiraProject {
188193
*/
189194
String originalProjectKey();
190195

191-
/**
192-
* Allows enabling signature verification.
193-
*/
194-
WebHookSecurity security();
195-
196196
/**
197197
* Allows enabling signature verification of downstream events.
198198
*/

src/main/java/org/hibernate/infra/replicate/jira/resource/JiraWebHookListenerResource.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import org.hibernate.infra.replicate.jira.service.jira.model.action.JiraActionEvent;
55
import org.hibernate.infra.replicate.jira.service.jira.model.hook.JiraWebHookEvent;
66
import org.hibernate.infra.replicate.jira.service.validation.ConfiguredProject;
7+
import org.hibernate.infra.replicate.jira.service.validation.ConfiguredProjectGroup;
78

89
import org.jboss.resteasy.reactive.RestPath;
910

@@ -23,22 +24,22 @@ public class JiraWebHookListenerResource {
2324
JiraService jiraService;
2425

2526
@POST
26-
@Path("/{project}")
27+
@Path("/source/{projectGroup}")
2728
@Consumes(MediaType.APPLICATION_JSON)
28-
public String somethingHappenedUpstream(@RestPath @NotNull @ConfiguredProject String project,
29+
public String somethingHappenedUpstream(@RestPath @NotNull @ConfiguredProjectGroup String projectGroup,
2930
@QueryParam("triggeredByUser") String triggeredByUser, JiraWebHookEvent event) {
30-
Log.tracef("Received a notification about %s project: %.200s...", project, event);
31-
jiraService.acknowledge(project, event, triggeredByUser);
31+
Log.tracef("Received a notification about %s project group: %.200s...", projectGroup, event);
32+
jiraService.acknowledge(projectGroup, event, triggeredByUser);
3233
return "ack";
3334
}
3435

3536
@POST
36-
@Path("/mirror/{project}")
37+
@Path("/mirror/{projectGroup}/{project}")
3738
@Consumes(MediaType.APPLICATION_JSON)
38-
public String somethingHappenedDownstream(@RestPath @NotNull @ConfiguredProject String project,
39-
JiraActionEvent data) {
39+
public String somethingHappenedDownstream(@RestPath @NotNull @ConfiguredProjectGroup String projectGroup,
40+
@RestPath @NotNull @ConfiguredProject String project, JiraActionEvent data) {
4041
Log.tracef("Received a downstream notification about %s project: %s...", project, data);
41-
jiraService.downstreamAcknowledge(project, data);
42+
jiraService.downstreamAcknowledge(projectGroup, data);
4243
return "ack";
4344
}
4445
}

src/main/java/org/hibernate/infra/replicate/jira/service/jira/HandlerProjectContext.java

Lines changed: 33 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package org.hibernate.infra.replicate.jira.service.jira;
22

3-
import java.time.ZonedDateTime;
4-
import java.time.format.DateTimeFormatter;
53
import java.util.HashMap;
64
import java.util.List;
75
import java.util.Map;
@@ -19,7 +17,6 @@
1917
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssueBulk;
2018
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssueBulkResponse;
2119
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraIssues;
22-
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraUser;
2320
import org.hibernate.infra.replicate.jira.service.jira.model.rest.JiraVersion;
2421

2522
import io.quarkus.logging.Log;
@@ -34,46 +31,26 @@ public final class HandlerProjectContext implements AutoCloseable {
3431
private final ReentrantLock versionLock = new ReentrantLock();
3532

3633
private final String projectName;
37-
private final String projectGroupName;
38-
private final JiraRestClient sourceJiraClient;
39-
private final JiraRestClient destinationJiraClient;
4034
private final HandlerProjectGroupContext projectGroupContext;
4135
private final JiraConfig.JiraProject project;
4236
private final AtomicLong currentIssueKeyNumber;
4337
private final JiraIssueBulk bulk;
4438

4539
private final String projectKeyWithDash;
46-
private final JiraUser notMappedAssignee;
47-
48-
private final Map<String, HandlerProjectContext> allProjectsContextMap;
49-
private final Pattern sourceLabelPattern;
50-
private final DateTimeFormatter formatter;
51-
5240
private final Map<String, JiraVersion> destFixVersions;
41+
private final Pattern keyToUpdatePattern;
5342

54-
public HandlerProjectContext(String projectName, String projectGroupName, JiraRestClient sourceJiraClient,
55-
JiraRestClient destinationJiraClient, HandlerProjectGroupContext projectGroupContext,
56-
Map<String, HandlerProjectContext> allProjectsContextMap) {
43+
public HandlerProjectContext(String projectName, HandlerProjectGroupContext projectGroupContext) {
5744
this.projectName = projectName;
58-
this.projectGroupName = projectGroupName;
59-
this.sourceJiraClient = sourceJiraClient;
60-
this.destinationJiraClient = destinationJiraClient;
6145
this.projectGroupContext = projectGroupContext;
6246
this.project = projectGroup().projects().get(projectName());
6347
this.currentIssueKeyNumber = new AtomicLong(getCurrentLatestJiraIssueKeyNumber());
6448
this.bulk = new JiraIssueBulk(createIssuePlaceholder(), ISSUES_PER_REQUEST);
6549
this.projectKeyWithDash = "%s-".formatted(project.projectKey());
6650

67-
this.notMappedAssignee = projectGroup().users().notMappedAssignee()
68-
.map(v -> new JiraUser(projectGroup().users().mappedPropertyName(), v)).orElse(null);
69-
70-
this.allProjectsContextMap = allProjectsContextMap;
71-
this.sourceLabelPattern = Pattern
72-
.compile(projectGroupContext.projectGroup().formatting().labelTemplate().formatted(".+"));
73-
this.formatter = DateTimeFormatter.ofPattern(projectGroupContext.projectGroup().formatting().timestampFormat());
74-
75-
this.destFixVersions = getAndCreateMissingCurrentFixVersions(project, projectGroupContext, sourceJiraClient,
76-
destinationJiraClient);
51+
this.destFixVersions = getAndCreateMissingCurrentFixVersions(project, projectGroupContext,
52+
projectGroupContext.sourceJiraClient(), projectGroupContext.destinationJiraClient());
53+
this.keyToUpdatePattern = Pattern.compile("^%s-\\d+".formatted(project.originalProjectKey()));
7754
}
7855

7956
public JiraConfig.JiraProject project() {
@@ -84,18 +61,6 @@ public String projectName() {
8461
return projectName;
8562
}
8663

87-
public String projectGroupName() {
88-
return projectGroupName;
89-
}
90-
91-
public JiraRestClient sourceJiraClient() {
92-
return sourceJiraClient;
93-
}
94-
95-
public JiraRestClient destinationJiraClient() {
96-
return destinationJiraClient;
97-
}
98-
9964
public JiraConfig.JiraProjectGroup projectGroup() {
10065
return projectGroupContext.projectGroup();
10166
}
@@ -105,8 +70,9 @@ public AtomicLong currentIssueKeyNumber() {
10570
}
10671

10772
public Long getLargestSyncedJiraIssueKeyNumber() {
108-
JiraIssues issues = destinationJiraClient.find("project = %s and summary !~\"%s\" ORDER BY key DESC"
109-
.formatted(project.projectId(), SYNC_ISSUE_PLACEHOLDER_SUMMARY), 0, 1);
73+
JiraIssues issues = projectGroupContext.destinationJiraClient()
74+
.find("project = %s and summary !~\"%s\" ORDER BY key DESC".formatted(project.projectId(),
75+
SYNC_ISSUE_PLACEHOLDER_SUMMARY), 0, 1);
11076
if (issues.issues.isEmpty()) {
11177
return 0L;
11278
} else {
@@ -123,7 +89,7 @@ public Optional<JiraIssue> getNextIssueToSync(Long latestSyncedJiraIssueKeyNumbe
12389
query = "project = %s ORDER BY key ASC".formatted(project.originalProjectKey(),
12490
project.originalProjectKey());
12591
}
126-
JiraIssues issues = sourceJiraClient.find(query, 0, 1);
92+
JiraIssues issues = projectGroupContext.sourceJiraClient().find(query, 0, 1);
12793
if (issues.issues.isEmpty()) {
12894
return Optional.empty();
12995
} else {
@@ -133,7 +99,7 @@ public Optional<JiraIssue> getNextIssueToSync(Long latestSyncedJiraIssueKeyNumbe
13399

134100
private Long getCurrentLatestJiraIssueKeyNumber() {
135101
try {
136-
JiraIssues issues = destinationJiraClient
102+
JiraIssues issues = projectGroupContext.destinationJiraClient()
137103
.find("project = %s ORDER BY created DESC".formatted(project.projectId()), 0, 1);
138104
if (issues.issues.isEmpty()) {
139105
return 0L;
@@ -165,7 +131,7 @@ public void createNextPlaceholderBatch(Long upToKeyNumber) {
165131
}
166132
try {
167133
do {
168-
JiraIssueBulkResponse response = destinationJiraClient.create(bulk);
134+
JiraIssueBulkResponse response = projectGroupContext.destinationJiraClient().create(bulk);
169135
response.issues.stream().mapToLong(i -> JiraIssue.keyToLong(i.key)).max()
170136
.ifPresent(currentIssueKeyNumber::set);
171137
Log.infof(
@@ -185,10 +151,6 @@ public void startProcessingDownstreamEvent() throws InterruptedException {
185151
projectGroupContext.startProcessingDownstreamEvent();
186152
}
187153

188-
public JiraUser notMappedAssignee() {
189-
return notMappedAssignee;
190-
}
191-
192154
private boolean requiredIssueKeyNumberShouldBeAvailable(Long key) {
193155
return currentIssueKeyNumber.get() >= key;
194156
}
@@ -214,15 +176,13 @@ private JiraIssue createIssuePlaceholder() {
214176

215177
@Override
216178
public String toString() {
217-
return "HandlerProjectContext[" + "projectName=" + projectName + ", " + "projectGroupName=" + projectGroupName
218-
+ ", " + "sourceJiraClient=" + sourceJiraClient + ", " + "destinationJiraClient="
219-
+ destinationJiraClient + ", " + "projectGroup=" + projectGroupContext.projectGroup() + ", "
220-
+ "currentIssueKeyNumber=" + currentIssueKeyNumber + ']';
179+
return "HandlerProjectContext[" + "projectName=" + projectName + ", " + "projectGroup="
180+
+ projectGroupContext.projectGroup() + ", " + "currentIssueKeyNumber=" + currentIssueKeyNumber + ']';
221181
}
222182

223183
@Override
224184
public void close() {
225-
projectGroupContext.close();
185+
// do nothing
226186
}
227187

228188
public int pendingEventsInCurrentContext() {
@@ -241,22 +201,6 @@ public void submitDownstreamTask(Runnable runnable) {
241201
projectGroupContext.submitDownstreamTask(runnable);
242202
}
243203

244-
public Optional<HandlerProjectContext> contextForProjectInSameGroup(String project) {
245-
if (!projectGroup().projects().containsKey(project)) {
246-
// different project group, don't bother
247-
return Optional.empty();
248-
}
249-
return Optional.ofNullable(allProjectsContextMap.get(project));
250-
}
251-
252-
public boolean isSourceLabel(String label) {
253-
return sourceLabelPattern.matcher(label).matches();
254-
}
255-
256-
public String formatTimestamp(ZonedDateTime time) {
257-
return time != null ? time.format(formatter) : "";
258-
}
259-
260204
public JiraVersion fixVersion(JiraVersion version) {
261205
return fixVersion(version, false);
262206
}
@@ -271,11 +215,13 @@ public JiraVersion fixVersion(JiraVersion version, boolean force) {
271215
versionLock.lock();
272216
try {
273217
if (force) {
274-
return destFixVersions.compute(version.name, (name, current) -> upsert(project, projectGroupContext,
275-
destinationJiraClient, version, destinationJiraClient().versions(project.projectKey())));
218+
return destFixVersions.compute(version.name,
219+
(name, current) -> upsert(project, projectGroupContext,
220+
projectGroupContext.destinationJiraClient(), version,
221+
projectGroupContext.destinationJiraClient().versions(project.projectKey())));
276222
} else {
277-
return destFixVersions.computeIfAbsent(version.name,
278-
name -> upsert(project, projectGroupContext, destinationJiraClient, version, List.of()));
223+
return destFixVersions.computeIfAbsent(version.name, name -> upsert(project, projectGroupContext,
224+
projectGroupContext.destinationJiraClient(), version, List.of()));
279225
}
280226
} catch (Exception e) {
281227
Log.errorf(e,
@@ -291,8 +237,8 @@ public void refreshFixVersions() {
291237
versionLock.lock();
292238
try {
293239
destFixVersions.clear();
294-
destFixVersions.putAll(getAndCreateMissingCurrentFixVersions(project, projectGroupContext, sourceJiraClient,
295-
destinationJiraClient));
240+
destFixVersions.putAll(getAndCreateMissingCurrentFixVersions(project, projectGroupContext,
241+
projectGroupContext.sourceJiraClient(), projectGroupContext.destinationJiraClient()));
296242
} finally {
297243
versionLock.unlock();
298244
}
@@ -360,19 +306,22 @@ private static boolean versionNeedsUpdate(JiraVersion upstreamVersion, JiraVersi
360306
|| !Objects.equals(upstreamVersion.releaseDate, downstreamVersion.releaseDate);
361307
}
362308

363-
public boolean isUserIgnored(String triggeredByUser) {
364-
return projectGroupContext.projectGroup().users().ignoredUpstreamUsers().contains(triggeredByUser);
365-
}
366-
367-
public boolean isDownstreamUserIgnored(String triggeredByUser) {
368-
return projectGroupContext.projectGroup().users().ignoredDownstreamUsers().contains(triggeredByUser);
369-
}
370-
371309
public String upstreamUser(String mappedValue) {
372310
return projectGroupContext.upstreamUser(mappedValue);
373311
}
374312

375313
public String upstreamStatus(String mappedValue) {
376314
return projectGroupContext.upstreamStatus(mappedValue);
377315
}
316+
317+
public String toDestinationKey(String key) {
318+
if (keyToUpdatePattern.matcher(key).matches()) {
319+
return "%s-%d".formatted(project().projectKey(), JiraIssue.keyToLong(key));
320+
}
321+
return key;
322+
}
323+
324+
public String toSourceKey(String key) {
325+
return "%s-%d".formatted(project().originalProjectKey(), JiraIssue.keyToLong(key));
326+
}
378327
}

0 commit comments

Comments
 (0)