Skip to content
Open
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
35 changes: 34 additions & 1 deletion src/main/java/com/openelements/issues/ApiEndpoint.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import com.openelements.issues.data.Contributor;
import com.openelements.issues.data.Issue;
import com.openelements.issues.services.GitHubCache;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
Expand All @@ -13,6 +17,7 @@
import org.springframework.web.bind.annotation.RestController;

@RestController
@Tag(name = "Good First Issue API", description = "Endpoints for querying good first issues, contributors, and repository statistics")
public class ApiEndpoint {

private final static Logger log = org.slf4j.LoggerFactory.getLogger(ApiEndpoint.class);
Expand All @@ -23,25 +28,39 @@ public ApiEndpoint(@NonNull final GitHubCache issueCache) {
this.issueCache = Objects.requireNonNull(issueCache, "issueCache must not be null");
}


@Operation(summary = "Get all contributors",
description = "Returns a set of all contributors across the configured repositories")
@ApiResponse(responseCode = "200", description = "Successfully retrieved the list of contributors")
@GetMapping("/api/v2/contributors")
public Set<Contributor> getContributors() {
log.info("Getting contributors");
return issueCache.getContributors();
}

@Operation(summary = "Get contributor count",
description = "Returns the total number of contributors across all configured repositories")
@ApiResponse(responseCode = "200", description = "Successfully retrieved the contributor count")
@GetMapping("/api/v2/contributors/count")
public long getContributorCount() {
log.info("Getting contributors count");
return issueCache.getContributors().size();
}

@Operation(summary = "Get issues",
description = "Returns a filtered set of issues from configured repositories. "
+ "Supports filtering by assignment status, closed status, labels, and programming languages.")
@ApiResponse(responseCode = "200", description = "Successfully retrieved the list of issues")
@GetMapping("/api/v2/issues")
public Set<Issue> getIssues(
@Parameter(description = "Filter by assignment status (true = assigned, false = unassigned)")
@RequestParam(name = "isAssigned", required = false) Boolean isAssigned,
@Parameter(description = "Filter by closed status (true = closed, false = open)")
@RequestParam(name = "isClosed", required = false) Boolean isClosed,
@Parameter(description = "Filter issues that contain all of the specified labels")
@RequestParam(name = "filteredLabels", required = false) Set<String> filteredLabels,
@Parameter(description = "Exclude issues that contain any of the specified labels")
@RequestParam(name = "excludedLabels", required = false) Set<String> excludedLabels,
@Parameter(description = "Filter issues by repository programming languages")
@RequestParam(name = "filteredLanguages", required = false) Set<String> filteredLanguages) {
log.info(
"Getting issues with filters - isAssigned: {}, isClosed: {}, filteredLabels: {}, excludedLabels: {}, filteredLanguages: {}",
Expand All @@ -58,21 +77,35 @@ public Set<Issue> getIssues(
.collect(Collectors.toUnmodifiableSet());
}

@Operation(summary = "Get issue count",
description = "Returns the total count of issues matching the specified filters")
@ApiResponse(responseCode = "200", description = "Successfully retrieved the issue count")
@GetMapping("/api/v2/issues/count")
public long getIssuesCount(
@Parameter(description = "Filter by assignment status (true = assigned, false = unassigned)")
@RequestParam(name = "isAssigned", required = false) Boolean isAssigned,
@Parameter(description = "Filter by closed status (true = closed, false = open)")
@RequestParam(name = "isClosed", required = false) Boolean isClosed,
@Parameter(description = "Filter issues that contain all of the specified labels")
@RequestParam(name = "filteredLabels", required = false) Set<String> filteredLabels,
@Parameter(description = "Exclude issues that contain any of the specified labels")
@RequestParam(name = "excludedLabels", required = false) Set<String> excludedLabels,
@Parameter(description = "Filter issues by repository programming languages")
@RequestParam(name = "filteredLanguages", required = false) Set<String> filteredLanguages) {
return getIssues(isAssigned, isClosed, filteredLabels, excludedLabels, filteredLanguages).size();
}

@Operation(summary = "Get total stars count",
description = "Returns the sum of stars across all configured repositories")
@ApiResponse(responseCode = "200", description = "Successfully retrieved the total stars count")
@GetMapping("/api/v2/repositories/stars")
public long getStarsCount() {
return issueCache.getRepositories().stream().mapToLong(repo -> repo.stars()).sum();
}

@Operation(summary = "Get repository count",
description = "Returns the total number of configured repositories")
@ApiResponse(responseCode = "200", description = "Successfully retrieved the repository count")
@GetMapping("/api/v2/repositories/count")
public long getRepositoryCount() {
return issueCache.getRepositories().size();
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/openelements/issues/config/OpenApiConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.openelements.issues.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class OpenApiConfig {

@Bean
public OpenAPI goodFirstIssueOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("Good First Issue Provider API")
.description("REST API for discovering good first issues from open-source projects on GitHub. "
+ "This service aggregates issues labeled as 'good first issue' from configured repositories "
+ "and provides endpoints to query issues, contributors, and repository statistics.")
.version("2.0.0")
.contact(new Contact()
.name("Open Elements")
.url("https://github.com/OpenElements/good-first-issue-provider"))
.license(new License()
.name("Apache 2.0")
.url("https://www.apache.org/licenses/LICENSE-2.0")));
}
}
8 changes: 7 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,10 @@ management:
exposure:
include:
- health
- prometheus
- prometheus
springdoc:
swagger-ui:
path: /swagger-ui.html
enabled: true
api-docs:
path: /v3/api-docs