-
Notifications
You must be signed in to change notification settings - Fork 1
π GitHub Code of Conduct Integration #4
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
Open
danielmarv
wants to merge
17
commits into
OpenElements:main
Choose a base branch
from
danielmarv:slack-int
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
5d2eff8
openAI fix
hendrikebbers d43aabc
prompt as file
hendrikebbers 1206a11
Update GitHub Code of Conduct provider configuration
danielmarv 0f93651
Refactor GitHub integration: streamline Code of Conduct file handlingβ¦
danielmarv 5edca0a
Add ViolationReport and ViolationReportRepository classes with CRUD oβ¦
danielmarv 0e34a74
Implement AnalysisService and ViolationReportService with analysis anβ¦
danielmarv aabdc3a
Add DTO classes for analysis and violation reporting: AnalysisDto, Paβ¦
danielmarv 45cad4e
Refactor DTOs to use records for AnalysisDto, PagedResponse, TrendAnaβ¦
danielmarv 319d890
Implement ViolationReportController with endpoints for retrieving vioβ¦
danielmarv b23f668
Update GitHub Code of Conduct provider configuration to use OpenElemeβ¦
danielmarv e007b38
Refactor AnalysisDto and ViolationReportDto to use records; update Anβ¦
danielmarv 424fa2e
Remove severity parameter from getReports method in ViolationReportCoβ¦
danielmarv 4e2d4d2
Remove severity filtering method from ViolationReportRepository; updaβ¦
danielmarv aee988b
Update default page size to 100 in ViolationReportController for imprβ¦
danielmarv 3dafab6
Refactor pagination parameter validation in ViolationReportControllerβ¦
danielmarv 28048bf
Remove comment placeholder in getStats method of ViolationReportContrβ¦
danielmarv 0096310
`Removed TrendSummaryDto and related methods from AnalysisController β¦
danielmarv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
src/main/java/com/openelements/conduct/api/dto/AnalysisDto.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| package com.openelements.conduct.api.dto; | ||
|
|
||
| import org.jspecify.annotations.NonNull; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| public record AnalysisDto( | ||
| // Total counts | ||
| int totalNoViolationCount, | ||
| int totalPossibleViolationCount, | ||
| int totalViolationCount, | ||
|
|
||
| // Daily averages | ||
| int averageNoViolationCountPerDay, | ||
| int averagePossibleViolationCountPerDay, | ||
| int averageViolationCountPerDay, | ||
|
|
||
| // Daily maximums | ||
| int maxNoViolationCountPerDay, | ||
| int maxPossibleViolationCountPerDay, | ||
| int maxViolationCountPerDay, | ||
|
|
||
| // This week averages | ||
| int averageNoViolationCountPerDayInThisWeek, | ||
| int averagePossibleViolationCountPerDayInThisWeek, | ||
| int averageViolationCountPerDayInThisWeek, | ||
|
|
||
| // Growth metrics | ||
| double generalGrowthOfChecksInPercentage, | ||
| double growthOfNoViolationCountAgainstLastWeek, | ||
| double growthOfPossibleViolationCountAgainstLastWeek, | ||
| double growthOfViolationCountAgainstLastWeek, | ||
|
|
||
| @NonNull LocalDateTime analysisTimestamp | ||
| ) {} | ||
15 changes: 15 additions & 0 deletions
15
src/main/java/com/openelements/conduct/api/dto/PagedResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.openelements.conduct.api.dto; | ||
|
|
||
| import org.jspecify.annotations.NonNull; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record PagedResponse<T>( | ||
danielmarv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| @NonNull List<T> content, | ||
| int page, | ||
| int size, | ||
| long totalElements, | ||
| int totalPages, | ||
| boolean first, | ||
| boolean last | ||
| ) {} | ||
11 changes: 11 additions & 0 deletions
11
src/main/java/com/openelements/conduct/api/dto/TrendSummaryDto.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package com.openelements.conduct.api.dto; | ||
|
|
||
| import org.jspecify.annotations.NonNull; | ||
|
|
||
| public record TrendSummaryDto( | ||
| @NonNull String trend, | ||
| double changePercentage, | ||
| @NonNull String description, | ||
| long totalReports, | ||
| double averageViolationsPerDay | ||
| ) {} |
18 changes: 18 additions & 0 deletions
18
src/main/java/com/openelements/conduct/api/dto/ViolationReportDto.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.openelements.conduct.api.dto; | ||
|
|
||
| import com.openelements.conduct.data.ViolationState; | ||
| import org.jspecify.annotations.NonNull; | ||
| import org.jspecify.annotations.Nullable; | ||
|
|
||
| import java.net.URI; | ||
| import java.time.LocalDateTime; | ||
|
|
||
| public record ViolationReportDto( | ||
| @NonNull String id, | ||
| @Nullable String messageTitle, | ||
| @NonNull String messageContent, | ||
| @NonNull URI linkToViolation, | ||
| @NonNull ViolationState violationState, | ||
| @NonNull String reason, | ||
| @NonNull LocalDateTime timestamp | ||
| ) {} |
28 changes: 28 additions & 0 deletions
28
src/main/java/com/openelements/conduct/controller/AnalysisController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.openelements.conduct.controller; | ||
|
|
||
| import com.openelements.conduct.api.dto.AnalysisDto; | ||
| import com.openelements.conduct.service.AnalysisService; | ||
| import org.jspecify.annotations.NonNull; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.web.bind.annotation.GetMapping; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/v1/analysis") | ||
| public class AnalysisController { | ||
|
|
||
| private final AnalysisService analysisService; | ||
|
|
||
| @Autowired | ||
| public AnalysisController(@NonNull AnalysisService analysisService) { | ||
| this.analysisService = Objects.requireNonNull(analysisService, "analysisService must not be null"); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public AnalysisDto getAnalysis() { | ||
| return analysisService.generateAnalysis(); | ||
| } | ||
| } |
100 changes: 100 additions & 0 deletions
100
src/main/java/com/openelements/conduct/controller/ConfigurationController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| package com.openelements.conduct.controller; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.core.env.Environment; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/v1/config") | ||
| public class ConfigurationController { | ||
|
|
||
| private final Environment environment; | ||
|
|
||
| @Autowired | ||
| public ConfigurationController(Environment environment) { | ||
| this.environment = environment; | ||
| } | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<Map<String, Object>> getConfiguration() { | ||
danielmarv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Map<String, Object> config = new HashMap<>(); | ||
|
|
||
| // Only expose non-sensitive configuration | ||
| config.put("application.name", environment.getProperty("spring.application.name", "Conduct Guardian")); | ||
| config.put("discord.enabled", environment.getProperty("guardian.integration.discord.enabled", "false")); | ||
| config.put("slack.enabled", environment.getProperty("guardian.integration.slack.enabled", "false")); | ||
| config.put("openai.enabled", environment.getProperty("guardian.integration.openai.enabled", "false")); | ||
| config.put("openai.model", environment.getProperty("guardian.integration.openai.model", "gpt-3.5-turbo")); | ||
| config.put("github.coc.enabled", environment.getProperty("guardian.integration.github.coc.enabled", "true")); | ||
| config.put("log.enabled", environment.getProperty("guardian.integration.log.enabled", "true")); | ||
|
|
||
| return ResponseEntity.ok(config); | ||
| } | ||
|
|
||
| @GetMapping("/integrations") | ||
| public ResponseEntity<IntegrationStatus> getIntegrationStatus() { | ||
| IntegrationStatus status = new IntegrationStatus( | ||
| Boolean.parseBoolean(environment.getProperty("guardian.integration.discord.enabled", "false")), | ||
| Boolean.parseBoolean(environment.getProperty("guardian.integration.slack.enabled", "false")), | ||
| Boolean.parseBoolean(environment.getProperty("guardian.integration.openai.enabled", "false")), | ||
| Boolean.parseBoolean(environment.getProperty("guardian.integration.github.coc.enabled", "true")), | ||
| Boolean.parseBoolean(environment.getProperty("guardian.integration.log.enabled", "true")) | ||
| ); | ||
|
|
||
| return ResponseEntity.ok(status); | ||
| } | ||
|
|
||
| @PostMapping("/validate") | ||
| public ResponseEntity<ValidationResult> validateConfiguration(@RequestBody ConfigValidationRequest request) { | ||
danielmarv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // Validate configuration without exposing sensitive data | ||
| boolean isValid = true; | ||
| String message = "Configuration is valid"; | ||
|
|
||
| // Add validation logic here | ||
| if (request.checkOpenAI() && !hasOpenAIConfig()) { | ||
| isValid = false; | ||
| message = "OpenAI configuration is incomplete"; | ||
| } | ||
|
|
||
| if (request.checkDiscord() && !hasDiscordConfig()) { | ||
| isValid = false; | ||
| message = "Discord configuration is incomplete"; | ||
| } | ||
|
|
||
| return ResponseEntity.ok(new ValidationResult(isValid, message)); | ||
| } | ||
|
|
||
| private boolean hasOpenAIConfig() { | ||
| return environment.getProperty("guardian.integration.openai.apiKey") != null && | ||
| !environment.getProperty("guardian.integration.openai.apiKey", "").isEmpty(); | ||
| } | ||
|
|
||
| private boolean hasDiscordConfig() { | ||
| return environment.getProperty("guardian.integration.discord.token") != null && | ||
| !environment.getProperty("guardian.integration.discord.token", "").isEmpty(); | ||
| } | ||
|
|
||
| public record IntegrationStatus( | ||
| boolean discordEnabled, | ||
| boolean slackEnabled, | ||
| boolean openaiEnabled, | ||
| boolean githubCocEnabled, | ||
| boolean logEnabled | ||
| ) {} | ||
|
|
||
| public record ConfigValidationRequest( | ||
| boolean checkOpenAI, | ||
| boolean checkDiscord, | ||
| boolean checkSlack, | ||
| boolean checkGitHub | ||
| ) {} | ||
|
|
||
| public record ValidationResult( | ||
| boolean isValid, | ||
| String message | ||
| ) {} | ||
| } | ||
60 changes: 60 additions & 0 deletions
60
src/main/java/com/openelements/conduct/controller/ViolationReportController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| package com.openelements.conduct.controller; | ||
|
|
||
| import com.openelements.conduct.api.dto.PagedResponse; | ||
| import com.openelements.conduct.api.dto.ViolationReportDto; | ||
| import com.openelements.conduct.data.ViolationState; | ||
| import com.openelements.conduct.service.ViolationReportService; | ||
| import org.jspecify.annotations.NonNull; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.format.annotation.DateTimeFormat; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| import java.time.LocalDateTime; | ||
| import java.util.Objects; | ||
|
|
||
| @RestController | ||
| @RequestMapping("/api/v1/violation-reports") | ||
| public class ViolationReportController { | ||
|
|
||
| private final ViolationReportService violationReportService; | ||
|
|
||
| @Autowired | ||
| public ViolationReportController(@NonNull ViolationReportService violationReportService) { | ||
| this.violationReportService = Objects.requireNonNull(violationReportService, "violationReportService must not be null"); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public ResponseEntity<PagedResponse<ViolationReportDto>> getReports( | ||
| @RequestParam(defaultValue = "0") int page, | ||
| @RequestParam(defaultValue = "20") int size, | ||
| @RequestParam(defaultValue = "timestamp") String sortBy, | ||
| @RequestParam(defaultValue = "desc") String sortDir, | ||
| @RequestParam(required = false) ViolationState violationState, | ||
| @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startDate, | ||
| @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endDate) { | ||
|
|
||
| if (page < 0) page = 0; | ||
| if (size <= 0 || size > 100) size = 100; | ||
|
|
||
| PagedResponse<ViolationReportDto> response = violationReportService.getReports( | ||
| page, size, sortBy, sortDir, violationState, null, startDate, endDate | ||
| ); | ||
|
|
||
| return ResponseEntity.ok(response); | ||
| } | ||
|
|
||
| @GetMapping("/{id}") | ||
| public ResponseEntity<ViolationReportDto> getReportById(@PathVariable String id) { | ||
danielmarv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return violationReportService.getReportById(id) | ||
| .map(ResponseEntity::ok) | ||
| .orElse(ResponseEntity.notFound().build()); | ||
| } | ||
|
|
||
| @GetMapping("/stats") | ||
| public ResponseEntity<ReportStats> getStats() { | ||
| return ResponseEntity.ok(new ReportStats("Statistics endpoint - implement as needed")); | ||
| } | ||
|
|
||
| public record ReportStats(String message) {} | ||
| } | ||
7 changes: 7 additions & 0 deletions
7
src/main/java/com/openelements/conduct/integration/github/GitHubClient.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.openelements.conduct.integration.github; | ||
|
|
||
| import com.fasterxml.jackson.databind.JsonNode; | ||
|
|
||
| public interface GitHubClient { | ||
danielmarv marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| JsonNode getRepositoryFileContent(String owner, String repo, String path, String branch) throws Exception; | ||
| } | ||
40 changes: 40 additions & 0 deletions
40
src/main/java/com/openelements/conduct/integration/github/GitHubClientImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package com.openelements.conduct.integration.github; | ||
|
|
||
| import com.fasterxml.jackson.databind.JsonNode; | ||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.http.*; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.web.client.RestTemplate; | ||
|
|
||
| @Component | ||
| public class GitHubClientImpl implements GitHubClient { | ||
|
|
||
| private final RestTemplate restTemplate = new RestTemplate(); | ||
| private final ObjectMapper objectMapper = new ObjectMapper(); | ||
| private final String githubToken; | ||
|
|
||
| public GitHubClientImpl(@Value("${guardian.integration.github.coc.token:}") String githubToken) { | ||
| this.githubToken = githubToken; | ||
| } | ||
|
|
||
| @Override | ||
| public JsonNode getRepositoryFileContent(String owner, String repo, String path, String branch) throws Exception { | ||
| String url = String.format("https://api.github.com/repos/%s/%s/contents/%s?ref=%s", owner, repo, path, branch); | ||
|
|
||
| HttpHeaders headers = new HttpHeaders(); | ||
| headers.set("Accept", "application/vnd.github.v3+json"); | ||
| if (githubToken != null && !githubToken.isBlank()) { | ||
| headers.setBearerAuth(githubToken); | ||
| } | ||
|
|
||
| HttpEntity<Void> request = new HttpEntity<>(headers); | ||
| ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, request, String.class); | ||
|
|
||
| if (response.getStatusCode().is2xxSuccessful()) { | ||
| return objectMapper.readTree(response.getBody()); | ||
| } | ||
|
|
||
| throw new RuntimeException("Failed to fetch file from GitHub: " + response.getStatusCode()); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.