Skip to content

Commit a997868

Browse files
Some changes to handle GitHub issue events which are now propagated by the gh-integration-service
Also, - Use long for issue ids - Use maven exec for the docker build
1 parent 01599b0 commit a997868

16 files changed

+410
-61
lines changed

pom.xml

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</parent>
1111
<groupId>edu.stanford.protege</groupId>
1212
<artifactId>webprotege-gh-issues-service</artifactId>
13-
<version>0.9.0</version>
13+
<version>0.9.1</version>
1414
<name>webprotege-gh-issues-service</name>
1515
<description>webprotege-gh-issues-service</description>
1616
<properties>
@@ -37,7 +37,7 @@
3737
<dependency>
3838
<groupId>edu.stanford.protege</groupId>
3939
<artifactId>webprotege-ipc</artifactId>
40-
<version>1.0.3</version>
40+
<version>2.0.2</version>
4141
</dependency>
4242
<dependency>
4343
<groupId>edu.stanford.protege</groupId>
@@ -155,24 +155,47 @@
155155
</plugin>
156156

157157
<plugin>
158-
<groupId>com.spotify</groupId>
159-
<artifactId>dockerfile-maven-plugin</artifactId>
160-
<version>1.4.13</version>
158+
<groupId>org.codehaus.mojo</groupId>
159+
<artifactId>exec-maven-plugin</artifactId>
160+
<version>3.3.0</version>
161161
<executions>
162162
<execution>
163-
<id>default</id>
163+
<id>docker-build</id>
164+
<phase>package</phase>
164165
<goals>
165-
<goal>build</goal>
166+
<goal>exec</goal>
166167
</goals>
168+
<configuration>
169+
<executable>docker</executable>
170+
<workingDirectory>${project.basedir}</workingDirectory>
171+
<arguments>
172+
<argument>build</argument>
173+
<argument>-f</argument>
174+
<argument>Dockerfile</argument>
175+
<argument>--build-arg</argument>
176+
<argument>JAR_FILE=${project.artifactId}-${project.version}.jar</argument>
177+
<argument>-t</argument>
178+
<argument>protegeproject/${project.artifactId}:${project.version}</argument>
179+
<argument>.</argument>
180+
</arguments>
181+
</configuration>
182+
</execution>
183+
<execution>
184+
<id>docker-push</id>
185+
<phase>install</phase>
186+
<goals>
187+
<goal>exec</goal>
188+
</goals>
189+
<configuration>
190+
<executable>docker</executable>
191+
<workingDirectory>${project.basedir}</workingDirectory>
192+
<arguments>
193+
<argument>push</argument>
194+
<argument>protegeproject/${project.artifactId}:${project.version}</argument>
195+
</arguments>
196+
</configuration>
167197
</execution>
168198
</executions>
169-
<configuration>
170-
<repository>protegeproject/${project.artifactId}</repository>
171-
<tag>${project.version}</tag>
172-
<buildArgs>
173-
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
174-
</buildArgs>
175-
</configuration>
176199
</plugin>
177200

178201
</plugins>
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package edu.stanford.protege.issues.service;
2+
3+
4+
import com.fasterxml.jackson.annotation.JsonCreator;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
7+
/**
8+
* Represents the type of action performed on a GitHub issue.
9+
*/
10+
public enum GitHubIssueAction {
11+
12+
/** The issue was opened. */
13+
@JsonProperty("opened")
14+
OPENED,
15+
16+
/** The issue was edited. */
17+
@JsonProperty("edited")
18+
EDITED,
19+
20+
/** The issue was deleted. */
21+
@JsonProperty("deleted")
22+
DELETED,
23+
24+
/** The issue was closed. */
25+
@JsonProperty("closed")
26+
CLOSED,
27+
28+
/** The issue was reopened. */
29+
@JsonProperty("reopened")
30+
REOPENED,
31+
32+
/** A user was assigned to the issue. */
33+
@JsonProperty("assigned")
34+
ASSIGNED,
35+
36+
/** A user was unassigned from the issue. */
37+
@JsonProperty("unassigned")
38+
UNASSIGNED,
39+
40+
/** A label was added to the issue. */
41+
@JsonProperty("labeled")
42+
LABELED,
43+
44+
/** A label was removed from the issue. */
45+
@JsonProperty("unlabeled")
46+
UNLABELED,
47+
48+
/** The issue was locked. */
49+
@JsonProperty("locked")
50+
LOCKED,
51+
52+
/** The issue was unlocked. */
53+
@JsonProperty("unlocked")
54+
UNLOCKED,
55+
56+
/** The issue was transferred to another repository. */
57+
@JsonProperty("transferred")
58+
TRANSFERRED,
59+
60+
/** The issue was pinned. */
61+
@JsonProperty("pinned")
62+
PINNED,
63+
64+
/** The issue was unpinned. */
65+
@JsonProperty("unpinned")
66+
UNPINNED,
67+
68+
/** A milestone was added to the issue. */
69+
@JsonProperty("milestoned")
70+
MILESTONED,
71+
72+
/** A milestone was removed from the issue. */
73+
@JsonProperty("demilestoned")
74+
DEMILESTONED;
75+
76+
/**
77+
* Fallback creator to deserialize a GitHub issue action value into an enum constant.
78+
*
79+
* @param value the string from the webhook payload
80+
* @return the matching enum value
81+
* @throws IllegalArgumentException if no match is found
82+
*/
83+
@JsonCreator
84+
public static GitHubIssueAction fromString(String value) {
85+
for (GitHubIssueAction action : GitHubIssueAction.values()) {
86+
JsonProperty annotation = null;
87+
try {
88+
annotation = GitHubIssueAction.class
89+
.getField(action.name())
90+
.getAnnotation(JsonProperty.class);
91+
} catch (NoSuchFieldException ignored) {}
92+
93+
if (annotation != null && annotation.value().equals(value)) {
94+
return action;
95+
}
96+
}
97+
throw new IllegalArgumentException("Unknown GitHub issue action: " + value);
98+
}
99+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package edu.stanford.protege.issues.service;
2+
3+
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
import edu.stanford.protege.github.GitHubRepository;
7+
import edu.stanford.protege.github.issues.GitHubIssue;
8+
9+
/**
10+
* Payload for an {@code issues} event sent by GitHub webhooks.
11+
*
12+
* @param action the action performed on the issue (e.g., {@code opened}, {@code closed}, {@code edited})
13+
* @param issue the issue object associated with the event
14+
* @param repository the repository where the issue resides
15+
* @param sender the GitHub user who triggered the event
16+
*/
17+
@JsonIgnoreProperties(ignoreUnknown = true)
18+
public record GitHubIssuesEvent(
19+
@JsonProperty("action") GitHubIssueAction action,
20+
@JsonProperty("issue") GitHubIssue issue,
21+
@JsonProperty("repository") GitHubRepository repository,
22+
@JsonProperty("sender") GitHubSender sender
23+
) {
24+
/**
25+
* The GitHub event type identifier for issues.
26+
*/
27+
public static final String TYPE = "issues";
28+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package edu.stanford.protege.issues.service;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import com.fasterxml.jackson.annotation.JsonTypeName;
5+
import edu.stanford.protege.webprotege.common.Event;
6+
import edu.stanford.protege.webprotege.common.EventId;
7+
8+
import static edu.stanford.protege.issues.service.GitHubIssuesWebProtegeEvent.CHANNEL;
9+
10+
@JsonTypeName(CHANNEL)
11+
public record GitHubIssuesWebProtegeEvent(@JsonProperty("eventId") EventId eventId,
12+
@JsonProperty("issuesEvent") GitHubIssuesEvent issuesEvent) implements Event {
13+
14+
public static final String CHANNEL = "webprotege.github.events.IssuesEvent";
15+
16+
@Override
17+
public String getChannel() {
18+
return CHANNEL;
19+
}
20+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package edu.stanford.protege.issues.service;
2+
3+
import edu.stanford.protege.webprotege.ipc.EventHandler;
4+
import edu.stanford.protege.webprotege.ipc.WebProtegeHandler;
5+
import org.jetbrains.annotations.NotNull;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
9+
import java.util.List;
10+
11+
@WebProtegeHandler
12+
public class GitHubIssuesWebProtegeEventHandler implements EventHandler<GitHubIssuesWebProtegeEvent> {
13+
14+
private final GitHubRepositoryLinkRecordStore store;
15+
16+
private final LocalIssueStoreUpdater updater;
17+
18+
private final Logger logger = LoggerFactory.getLogger(GitHubIssuesWebProtegeEventHandler.class);
19+
20+
public GitHubIssuesWebProtegeEventHandler(GitHubRepositoryLinkRecordStore store, LocalIssueStoreUpdater updater) {
21+
this.store = store;
22+
this.updater = updater;
23+
}
24+
25+
@NotNull
26+
@Override
27+
public String getChannelName() {
28+
return GitHubIssuesWebProtegeEvent.CHANNEL;
29+
}
30+
31+
@NotNull
32+
@Override
33+
public String getHandlerName() {
34+
return "GitHubIssuesEventHandler";
35+
}
36+
37+
@Override
38+
public Class<GitHubIssuesWebProtegeEvent> getEventClass() {
39+
return GitHubIssuesWebProtegeEvent.class;
40+
}
41+
42+
@Override
43+
public void handleEvent(GitHubIssuesWebProtegeEvent event) {
44+
var issueEvent = event.issuesEvent();
45+
logger.info("Handling GitHubIssuesWebProtegeEvent: {} on issue {} in repo {}. Issue: {}",
46+
issueEvent.action(),
47+
issueEvent.issue().id(),
48+
issueEvent.repository().getCoordinates(),
49+
issueEvent.issue());
50+
var repoCoords = issueEvent.repository().getCoordinates();
51+
updater.updateIssues(repoCoords, List.of(issueEvent.issue()));
52+
}
53+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package edu.stanford.protege.issues.service;
2+
3+
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
7+
/**
8+
* The GitHub user who triggered the event.
9+
*/
10+
@JsonIgnoreProperties(ignoreUnknown = true)
11+
public record GitHubSender(
12+
/**
13+
* GitHub login name.
14+
*/
15+
@JsonProperty("login" ) String login,
16+
17+
/**
18+
* GitHub user ID.
19+
*/
20+
@JsonProperty("id" ) long id,
21+
22+
/**
23+
* URL to the user's avatar image.
24+
*/
25+
@JsonProperty("avatar_url" ) String avatar_url,
26+
27+
/**
28+
* URL to the user's GitHub profile.
29+
*/
30+
@JsonProperty("html_url" ) String html_url
31+
) {
32+
33+
}

src/main/java/edu/stanford/protege/issues/service/IssueRecord.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import edu.stanford.protege.github.issues.GitHubIssue;
55
import edu.stanford.protege.github.GitHubRepositoryCoordinates;
66
import org.springframework.data.annotation.Id;
7+
import org.springframework.data.mongodb.core.mapping.Document;
78

89
import javax.annotation.Nonnull;
910
import java.util.Objects;
@@ -14,25 +15,26 @@
1415
* Stanford Center for Biomedical Informatics Research
1516
* 2023-09-21
1617
*/
18+
@Document(collection = "GitHubIssueRecords")
1719
@JsonIgnoreProperties(ignoreUnknown = true)
18-
public record IssueRecord(@JsonProperty("_id") @Id String nodeId,
20+
public record IssueRecord(@JsonProperty("_id") @Id Long id,
1921
@JsonProperty("repoCoords") GitHubRepositoryCoordinates repoCoords,
2022
@JsonProperty("issue") @Nonnull GitHubIssue issue,
2123
@JsonProperty("oboIds") @Nonnull Set<OboId> oboIds,
2224
@JsonProperty("iris") @Nonnull Set<Iri> iris) {
2325

24-
public IssueRecord(@JsonProperty("_id") String nodeId,
26+
public IssueRecord(@JsonProperty("_id") Long id,
2527
@JsonProperty("repoCoords") GitHubRepositoryCoordinates repoCoords,
2628
@JsonProperty("issue") @Nonnull GitHubIssue issue,
2729
@JsonProperty("oboIds") @Nonnull Set<OboId> oboIds,
2830
@JsonProperty("iris") @Nonnull Set<Iri> iris) {
29-
this.nodeId = Objects.requireNonNull(nodeId);
31+
this.id = Objects.requireNonNull(id);
3032
this.repoCoords = Objects.requireNonNull(repoCoords);
3133
this.issue = Objects.requireNonNull(issue);
3234
this.oboIds = Objects.requireNonNull(oboIds);
3335
this.iris = Objects.requireNonNull(iris);
34-
if(!nodeId.equals(issue.nodeId())) {
35-
throw new IllegalArgumentException("nodeId and issue.nodeId must be equal");
36+
if(!id.equals(issue.id())) {
37+
throw new IllegalArgumentException("_id and issue.id must be equal");
3638
}
3739
}
3840

@@ -41,7 +43,7 @@ public static IssueRecord of(@JsonProperty("issue") @Nonnull GitHubIssue issue,
4143
@JsonProperty("repoCoords") GitHubRepositoryCoordinates repoCoords,
4244
@JsonProperty("oboIds") @Nonnull Set<OboId> oboIds,
4345
@JsonProperty("iris") @Nonnull Set<Iri> iris) {
44-
return new IssueRecord(issue.nodeId(), repoCoords, issue, oboIds, iris);
46+
return new IssueRecord(issue.id(), repoCoords, issue, oboIds, iris);
4547
}
4648

4749
@JsonCreator
@@ -51,6 +53,6 @@ static IssueRecord fromJson(@JsonProperty("_id") String issueNodeId,
5153
@JsonProperty("issue") @Nonnull GitHubIssue issue,
5254
@JsonProperty("oboIds") @Nonnull Set<OboId> oboIds,
5355
@JsonProperty("iris") @Nonnull Set<Iri> iris) {
54-
return new IssueRecord(issueNodeId, repoCoords, issue, oboIds, iris);
56+
return new IssueRecord(issue.id(), repoCoords, issue, oboIds, iris);
5557
}
5658
}

0 commit comments

Comments
 (0)