Skip to content

Commit 92f458e

Browse files
committed
minor improvements
1 parent d122995 commit 92f458e

File tree

6 files changed

+100
-19
lines changed

6 files changed

+100
-19
lines changed

src/main/java/com/openelements/issues/ApiEndpoint.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
import com.openelements.issues.services.GitHubCache;
66
import java.util.Objects;
77
import java.util.Set;
8+
import java.util.stream.Collectors;
89
import org.jspecify.annotations.NonNull;
910
import org.slf4j.Logger;
1011
import org.springframework.web.bind.annotation.CrossOrigin;
1112
import org.springframework.web.bind.annotation.GetMapping;
13+
import org.springframework.web.bind.annotation.PathVariable;
1214
import org.springframework.web.bind.annotation.RestController;
1315

1416
@RestController
@@ -53,4 +55,16 @@ public Set<Contributor> getContributors() {
5355
return issueCache.getContributors();
5456
}
5557

58+
@GetMapping("/api/issues")
59+
public Set<Issue> getGoodFirstIssues(@PathVariable(required = false) Boolean isAssigned, @PathVariable(required = false) Boolean isClosed, @PathVariable(required = false) Set<String> filteredLabels, @PathVariable(required = false) Set<String> excludedLabels, @PathVariable(required = false) Set<String> filteredLanguages) {
60+
log.info("Getting good first issues");
61+
return issueCache.getAllIssues().stream()
62+
.filter(issue -> isAssigned == null || issue.isAssigned() == isAssigned)
63+
.filter(issue -> isClosed == null || issue.isClosed() == isClosed)
64+
.filter(issue -> filteredLabels == null || issue.labels().containsAll(filteredLabels))
65+
.filter(issue -> excludedLabels == null || issue.labels().stream().noneMatch(excludedLabels::contains))
66+
.filter(issue -> filteredLanguages == null || issue.languageTags().containsAll(filteredLanguages))
67+
.collect(Collectors.toUnmodifiableSet());
68+
}
69+
5670
}

src/main/java/com/openelements/issues/config/RepositoryProperty.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,12 @@ public record RepositoryProperty(@NonNull String org, @NonNull String repo) {
88
public RepositoryProperty {
99
Objects.requireNonNull(org, "org must not be null");
1010
Objects.requireNonNull(repo, "repo must not be null");
11+
12+
if (org.isBlank()) {
13+
throw new IllegalArgumentException("org is required");
14+
}
15+
if (repo.isBlank()) {
16+
throw new IllegalArgumentException("repo is required");
17+
}
1118
}
1219
}

src/main/java/com/openelements/issues/data/Issue.java

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,34 @@
66

77
public record Issue(@NonNull String title, @NonNull String link, @NonNull String org, @NonNull String repo, @NonNull String imageUrl, @NonNull String identifier, boolean isAssigned, boolean isClosed, @NonNull List<String> labels, @NonNull List<String> languageTags) {
88

9-
public Issue {
10-
Objects.requireNonNull(title, "title must not be null");
11-
Objects.requireNonNull(link, "link must not be null");
12-
Objects.requireNonNull(org, "org must not be null");
13-
Objects.requireNonNull(repo, "repo must not be null");
14-
Objects.requireNonNull(imageUrl, "imageUrl must not be null");
15-
Objects.requireNonNull(identifier, "identifier must not be null");
9+
public Issue(@NonNull String title, @NonNull String link, @NonNull String org, @NonNull String repo, @NonNull String imageUrl, @NonNull String identifier, boolean isAssigned, boolean isClosed, @NonNull List<String> labels, @NonNull List<String> languageTags) {
10+
this.title = Objects.requireNonNull(title, "title must not be null");
11+
this.link = Objects.requireNonNull(link, "link must not be null");
12+
this.org = Objects.requireNonNull(org, "org must not be null");
13+
this.repo = Objects.requireNonNull(repo, "repo must not be null");
14+
this.imageUrl = Objects.requireNonNull(imageUrl, "imageUrl must not be null");
15+
this.identifier = Objects.requireNonNull(identifier, "identifier must not be null");
16+
this.isAssigned = isAssigned;
17+
this.isClosed = isClosed;
1618
Objects.requireNonNull(labels, "labels must not be null");
19+
this.labels = List.copyOf(labels);
1720
Objects.requireNonNull(languageTags, "languageTags must not be null");
21+
this.languageTags = List.copyOf(languageTags);
22+
23+
if (title.isBlank()) {
24+
throw new IllegalArgumentException("title is required");
25+
}
26+
if (link.isBlank()) {
27+
throw new IllegalArgumentException("link is required");
28+
}
29+
if (org.isBlank()) {
30+
throw new IllegalArgumentException("org is required");
31+
}
32+
if (repo.isBlank()) {
33+
throw new IllegalArgumentException("repo is required");
34+
}
35+
if (identifier.isBlank()) {
36+
throw new IllegalArgumentException("identifier is required");
37+
}
1838
}
1939
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
11
package com.openelements.issues.data;
22

33
import java.util.List;
4+
import java.util.Objects;
45
import org.jspecify.annotations.NonNull;
56

67
public record Repository(@NonNull String org, @NonNull String name, @NonNull String imageUrl, @NonNull List<String> languages) {
8+
9+
10+
11+
public Repository(@NonNull String org, @NonNull String name, @NonNull String imageUrl, @NonNull List<String> languages) {
12+
this.org = Objects.requireNonNull(org, "org must not be null");
13+
this.name = Objects.requireNonNull(name, "name must not be null");
14+
this.imageUrl = Objects.requireNonNull(imageUrl, "imageUrl must not be null");
15+
Objects.requireNonNull(languages, "languages must not be null");
16+
this.languages = List.copyOf(languages);
17+
18+
if (org.isBlank()) {
19+
throw new IllegalArgumentException("org is required");
20+
}
21+
if (name.isBlank()) {
22+
throw new IllegalArgumentException("name is required");
23+
}
24+
}
725
}

src/main/java/com/openelements/issues/services/GitHubCache.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
package com.openelements.issues.services;
22

3-
import com.openelements.issues.LabelConstants;
3+
import static com.openelements.issues.LabelConstants.GOOD_FIRST_ISSUE_CANDIDATE_LABEL;
4+
import static com.openelements.issues.LabelConstants.GOOD_FIRST_ISSUE_LABEL;
5+
import static com.openelements.issues.LabelConstants.HACKTOBERFEST_LABEL;
6+
import static com.openelements.issues.LabelConstants.HELP_WANTED_LABEL;
7+
48
import com.openelements.issues.config.IssueServiceProperties;
9+
import com.openelements.issues.config.RepositoryProperty;
510
import com.openelements.issues.data.Contributor;
611
import com.openelements.issues.data.Issue;
712
import com.openelements.issues.data.Repository;
@@ -36,13 +41,20 @@ public GitHubCache(@NonNull final IssueServiceProperties properties, final GitHu
3641
this.gitHubClient = Objects.requireNonNull(gitHubClient, "gitHubClient must not be null");
3742
this.issuesCache = new ConcurrentHashMap<>();
3843
this.contributorsCache = new ConcurrentHashMap<>();
44+
log.info("Cache will be updated all {} seconds", CACHE_DURATION.getSeconds());
3945
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
40-
properties.getRepositories().forEach(repository -> updateContributors(repository.org(), repository.repo()));
41-
42-
properties.getRepositories().forEach(repository -> updateIssues(repository.org(), repository.repo(), LabelConstants.GOOD_FIRST_ISSUE_LABEL));
43-
properties.getRepositories().forEach(repository -> updateIssues(repository.org(), repository.repo(), LabelConstants.GOOD_FIRST_ISSUE_CANDIDATE_LABEL));
44-
properties.getRepositories().forEach(repository -> updateIssues(repository.org(), repository.repo(), LabelConstants.HACKTOBERFEST_LABEL));
45-
properties.getRepositories().forEach(repository -> updateIssues(repository.org(), repository.repo(), LabelConstants.HELP_WANTED_LABEL));
46+
try {
47+
log.info("Updating cache");
48+
final List<RepositoryProperty> repos = properties.getRepositories();
49+
repos.forEach(repo -> updateContributors(repo.org(), repo.repo()));
50+
repos.forEach(repo -> updateIssues(repo.org(), repo.repo(), GOOD_FIRST_ISSUE_LABEL));
51+
repos.forEach(repo -> updateIssues(repo.org(), repo.repo(), GOOD_FIRST_ISSUE_CANDIDATE_LABEL));
52+
repos.forEach(repo -> updateIssues(repo.org(), repo.repo(), HACKTOBERFEST_LABEL));
53+
repos.forEach(repo -> updateIssues(repo.org(), repo.repo(), HELP_WANTED_LABEL));
54+
log.info("Cache updated. Found {} contributors and {} issues", getContributors().size(), getAllIssues().size());
55+
} catch (final Exception e) {
56+
log.error("Failed to update cache", e);
57+
}
4658
}, 0, CACHE_DURATION.getSeconds(), TimeUnit.SECONDS);
4759
}
4860

@@ -70,6 +82,12 @@ private void updateIssues(@NonNull final String org, @NonNull final String repo,
7082
}
7183
}
7284

85+
public Set<Issue> getAllIssues() {
86+
return issuesCache.keySet().stream()
87+
.flatMap(key -> issuesCache.get(key).stream())
88+
.collect(Collectors.toUnmodifiableSet());
89+
}
90+
7391
public Set<Issue> getIssues(@NonNull final String label) {
7492
Objects.requireNonNull(label, "label must not be null");
7593
return issuesCache.keySet().stream()

src/main/java/com/openelements/issues/services/GitHubClient.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,25 @@
2121
public class GitHubClient {
2222

2323
private final static Logger log = LoggerFactory.getLogger(GitHubClient.class);
24+
public static final String GITHUB_TOKEN = "GITHUB_TOKEN";
25+
public static final String GITHUB_API_URL = "https://api.github.com";
26+
public static final String HTTP_ACCEPT = "Accept";
27+
public static final String GITHUB_V_3_JSON = "application/vnd.github.v3+json";
2428

2529
private final RestClient restClient;
2630

2731
private final ObjectMapper objectMapper;
2832

2933
public GitHubClient() {
3034
Builder builder = RestClient.builder()
31-
.baseUrl("https://api.github.com")
32-
.defaultHeader("Accept", "application/vnd.github.v3+json");
33-
final String githubToken = System.getenv("GITHUB_TOKEN");
35+
.baseUrl(GITHUB_API_URL)
36+
.defaultHeader(HTTP_ACCEPT, GITHUB_V_3_JSON);
37+
final String githubToken = System.getenv(GITHUB_TOKEN);
3438
if(githubToken != null) {
35-
log.info("Using GITHUB_TOKEN environment variable for GitHub API authentication");
39+
log.info("Using {} environment variable for GitHub API authentication", GITHUB_TOKEN);
3640
builder = builder.defaultHeader("Authorization", "token " + githubToken);
3741
} else {
38-
log.warn("No GITHUB_TOKEN environment variable found, GitHub API rate limits will apply");
42+
log.warn("{} environment variable found, GitHub API rate limits will apply", GITHUB_TOKEN);
3943
}
4044
restClient = builder.build();
4145
objectMapper = new ObjectMapper();

0 commit comments

Comments
 (0)