Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a105193
feat(gitprovider): GitLab sync — Issue entity
FelixTJDietrich Feb 28, 2026
9f4f84b
fix(gitprovider): format Repository.java for CI
FelixTJDietrich Feb 28, 2026
a227a5f
fix(gitprovider): resolve CI failures — architecture and DB models
FelixTJDietrich Feb 28, 2026
a5d4634
fix(gitprovider): resolve architecture test violations
FelixTJDietrich Feb 28, 2026
23e6f46
refactor(gitprovider): consolidate migration changelog
FelixTJDietrich Feb 28, 2026
d209b15
refactor(gitprovider): migrate to synthetic PKs with GitProvider FK a…
FelixTJDietrich Feb 28, 2026
2bd24d2
fix(workspace): resolve provisioning bugs for GitLab and GitHub sync
FelixTJDietrich Feb 28, 2026
9ae64ac
feat(gitprovider): add GitLab incremental sync and fix NATS repositor…
FelixTJDietrich Feb 28, 2026
6aff117
fix(gitprovider): resolve CI failures from synthetic PK migration
FelixTJDietrich Feb 28, 2026
cc7007f
fix(ai): seed git_provider in test fixtures for NOT NULL constraint
FelixTJDietrich Feb 28, 2026
15428d8
fix(ai): delete documents before user in test cleanup (FK constraint)
FelixTJDietrich Feb 28, 2026
6a7e9e2
fix(db): regenerate ERD and models from clean database
FelixTJDietrich Feb 28, 2026
b6bc235
fix(gitprovider): fix milestone lookup and PR processor test after sy…
FelixTJDietrich Mar 1, 2026
1f5090b
fix(gitprovider): fix PR message handler test for synthetic PK lookups
FelixTJDietrich Mar 1, 2026
2d61220
fix(gitprovider): fix processDeleted and remaining integration tests …
FelixTJDietrich Mar 1, 2026
3436f52
fix(gitprovider): resolve all PR review comments and clean up documen…
FelixTJDietrich Mar 1, 2026
4bbe9fa
fix(gitprovider): add remaining unstaged changes from previous sessions
FelixTJDietrich Mar 1, 2026
cb042d3
fix(gitprovider): fix Lombok JPA anti-patterns and migration safety
FelixTJDietrich Mar 1, 2026
2592094
fix(gitprovider): add provider_native_id unique constraints to JPA en…
FelixTJDietrich Mar 1, 2026
0f8c448
fix(gitprovider): enforce JPA best practices — LAZY fetch, equals/has…
FelixTJDietrich Mar 1, 2026
4c02060
fix(gitprovider): add JOIN FETCH for lazy Label.repository access
FelixTJDietrich Mar 1, 2026
8aa25f3
feat(gitprovider): add nested overflow pagination for GitLab labels/a…
FelixTJDietrich Mar 1, 2026
486e651
fix(leaderboard): unproxy Hibernate entity before PullRequest type check
FelixTJDietrich Mar 1, 2026
b72a18b
fix(gitprovider): fix migration safety for TRUNCATE CASCADE and const…
FelixTJDietrich Mar 1, 2026
6d16f38
feat(gitprovider): consolidate git-provider migration into single cha…
FelixTJDietrich Mar 1, 2026
744c9bc
chore(db): regenerate Drizzle schema and ERD docs
FelixTJDietrich Mar 1, 2026
91ba100
fix(db): remove duplicate constraints from generated Drizzle schema
FelixTJDietrich Mar 1, 2026
b12732f
feat(db): consolidate git-provider migration into single changelog
FelixTJDietrich Mar 2, 2026
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
33 changes: 28 additions & 5 deletions .graphqlrc.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,39 @@
# GraphQL Configuration for Hephaestus
# Enables VSCode IntelliSense for GraphQL operations against GitHub API
# Enables VSCode IntelliSense for GraphQL operations against GitHub and GitLab APIs
# Extension: GraphQL.vscode-graphql
# Docs: https://the-guild.dev/graphql/config

projects:
github:
# GitHub GraphQL API schema (downloaded from docs.github.com)
schema: "server/application-server/src/main/resources/graphql/github/schema.github.graphql"

# GraphQL operations (Spring's standard location)
documents: "server/application-server/src/main/resources/graphql-documents/**/*.graphql"


# GraphQL operations (queries, mutations, fragments)
documents:
- "server/application-server/src/main/resources/graphql/github/operations/**/*.graphql"
- "server/application-server/src/main/resources/graphql/github/fragments/**/*.graphql"

# Restrict this project to GitHub files only (prevents cross-schema validation)
include:
- "server/application-server/src/main/resources/graphql/github/**"

extensions:
languageService:
enableHover: true
enableAutoComplete: true
enableValidation: true

gitlab:
# GitLab GraphQL API schema
schema: "server/application-server/src/main/resources/graphql/gitlab/schema.gitlab.graphql"

# GitLab GraphQL operations
documents: "server/application-server/src/main/resources/graphql/gitlab/operations/**/*.graphql"

# Restrict this project to GitLab files only (prevents cross-schema validation)
include:
- "server/application-server/src/main/resources/graphql/gitlab/**"

extensions:
languageService:
enableHover: true
Expand Down
17 changes: 16 additions & 1 deletion docs/contributor/erd/schema.mmd
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ erDiagram
VARCHAR(128) category_id FK
BIGINT answer_chosen_by_id FK
BIGINT answer_comment_id FK,UK
VARCHAR(10) provider "NOT NULL"
}

DiscussionCategory {
Expand Down Expand Up @@ -148,6 +149,7 @@ erDiagram
BIGINT discussion_id FK
BIGINT author_id FK
BIGINT parent_comment_id FK
VARCHAR(10) provider "NOT NULL"
}

DiscussionLabel {
Expand Down Expand Up @@ -235,6 +237,7 @@ erDiagram
VARCHAR(40) head_ref_oid
VARCHAR(255) base_ref_name
VARCHAR(40) base_ref_oid
VARCHAR(10) provider "NOT NULL"
}

IssueAssignee {
Expand All @@ -256,6 +259,7 @@ erDiagram
BIGINT author_id FK
BIGINT issue_id FK
TEXT body
VARCHAR(10) provider "NOT NULL"
}

IssueLabel {
Expand Down Expand Up @@ -300,18 +304,21 @@ erDiagram
INTEGER closed_issues_count "NOT NULL"
INTEGER open_issues_count "NOT NULL"
TIMESTAMPTZ last_sync_at
VARCHAR(10) provider "NOT NULL"
}

Organization {
BIGINT id PK
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
VARCHAR(255) avatar_url
BIGINT github_id UK "NOT NULL"
BIGINT provider_id UK "NOT NULL"
VARCHAR(255) html_url
VARCHAR(255) login UK "NOT NULL"
VARCHAR(255) name
TIMESTAMPTZ last_sync_at
VARCHAR(10) provider UK "NOT NULL"
VARCHAR(10) provider UK "NOT NULL"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
}

OrganizationMembership {
Expand Down Expand Up @@ -344,6 +351,7 @@ erDiagram
TIMESTAMPTZ status_updates_synced_at
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
VARCHAR(10) provider "NOT NULL"
}

ProjectField {
Expand Down Expand Up @@ -381,6 +389,7 @@ erDiagram
BIGINT creator_id FK
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
VARCHAR(10) provider "NOT NULL"
}

ProjectStatusUpdate {
Expand All @@ -395,6 +404,7 @@ erDiagram
BIGINT creator_id FK
TIMESTAMPTZ created_at
TIMESTAMPTZ updated_at
VARCHAR(10) provider "NOT NULL"
}

PullRequestBadPractice {
Expand Down Expand Up @@ -452,6 +462,7 @@ erDiagram
TEXT body
TEXT diff_hunk
BOOLEAN outdated
VARCHAR(10) provider "NOT NULL"
}

PullRequestReviewThread {
Expand All @@ -470,6 +481,7 @@ erDiagram
BOOLEAN outdated
BOOLEAN collapsed
BIGINT resolved_by_id FK
VARCHAR(10) provider "NOT NULL"
}

Repository {
Expand All @@ -489,6 +501,7 @@ erDiagram
BIGINT organization_id FK
TIMESTAMPTZ last_sync_at
BOOLEAN has_discussions_enabled "NOT NULL"
VARCHAR(10) provider UK "NOT NULL"
}

RepositoryCollaborator {
Expand Down Expand Up @@ -529,6 +542,7 @@ erDiagram
BIGINT parent_id
VARCHAR(32) privacy
TIMESTAMPTZ updated_at
VARCHAR(10) provider "NOT NULL"
}

TeamMembership {
Expand All @@ -553,6 +567,7 @@ erDiagram
VARCHAR(255) login
VARCHAR(255) name
VARCHAR(255) type
VARCHAR(10) provider "NOT NULL"
}

UserPreference {
Expand Down
110 changes: 105 additions & 5 deletions server/application-server/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,8 @@
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/graphql</source>
<source>${project.build.directory}/generated-sources/graphql-github</source>
<source>${project.build.directory}/generated-sources/graphql-gitlab</source>
</sources>
</configuration>
</execution>
Expand Down Expand Up @@ -533,7 +534,7 @@
</graphqlSchemas>

<!-- Output configuration -->
<outputDir>${project.build.directory}/generated-sources/graphql</outputDir>
<outputDir>${project.build.directory}/generated-sources/graphql-github</outputDir>
<packageName>de.tum.in.www1.hephaestus.gitprovider.graphql.github</packageName>
<apiPackageName>de.tum.in.www1.hephaestus.gitprovider.graphql.github.api</apiPackageName>
<modelPackageName>de.tum.in.www1.hephaestus.gitprovider.graphql.github.model
Expand Down Expand Up @@ -600,6 +601,104 @@
</customTemplates>
</configuration>
</execution>
<!-- GitLab GraphQL Code Generator -->
<!-- Generates type-safe Java classes from GitLab GraphQL schema -->
<execution>
<id>generate-gitlab-graphql-client</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<skip>${graphql.codegen.skip}</skip>
<!-- GitLab schema is large, skip size limit check -->
<skipSchemaSizeLimit>true</skipSchemaSizeLimit>

<!-- Schema location -->
<graphqlSchemas>
<rootDir>${project.basedir}/src/main/resources/graphql/gitlab</rootDir>
</graphqlSchemas>

<!-- Output configuration (separate dir to avoid codegen cleanup conflicts) -->
<outputDir>${project.build.directory}/generated-sources/graphql-gitlab</outputDir>
<packageName>de.tum.in.www1.hephaestus.gitprovider.graphql.gitlab</packageName>
<apiPackageName>de.tum.in.www1.hephaestus.gitprovider.graphql.gitlab.api</apiPackageName>
<modelPackageName>de.tum.in.www1.hephaestus.gitprovider.graphql.gitlab.model
</modelPackageName>
<modelNamePrefix>GL</modelNamePrefix>

<!-- Client-side code generation (for consuming GitLab API) -->
<generateClient>true</generateClient>
<generateApis>false</generateApis>
<generateDataFetchingEnvironmentArgumentInApis>false
</generateDataFetchingEnvironmentArgumentInApis>

<!-- Model generation options -->
<generateBuilder>true</generateBuilder>
<generateEqualsAndHashCode>true</generateEqualsAndHashCode>
<generateToString>true</generateToString>
<generateParameterizedFieldsResolvers>false</generateParameterizedFieldsResolvers>
<generateModelsForRootTypes>false</generateModelsForRootTypes>
<generateAllMethodInProjection>true</generateAllMethodInProjection>
<!-- GitLab schema has types with 300+ fields (e.g., Project).
All-args constructors for these exceed the JVM 255-parameter limit. -->
<generateNoArgsConstructorOnly>true</generateNoArgsConstructorOnly>

<!-- Java config -->
<generatedLanguage>JAVA</generatedLanguage>
<addGeneratedAnnotation>true</addGeneratedAnnotation>
<generatedAnnotation>jakarta.annotation.Generated</generatedAnnotation>
<modelValidationAnnotation>@jakarta.annotation.Generated("graphql-codegen")
</modelValidationAnnotation>

<!-- GitLab-specific scalar mappings -->
<customTypesMapping>
<Time>java.time.OffsetDateTime</Time>
<ISO8601DateTime>java.time.OffsetDateTime</ISO8601DateTime>
<ISO8601Date>java.time.LocalDate</ISO8601Date>
<GlobalID>java.lang.String</GlobalID>
<JSON>java.lang.Object</JSON>
<UntrustedRegexp>java.lang.String</UntrustedRegexp>
<Duration>java.lang.String</Duration>
<BigInt>java.math.BigInteger</BigInt>
<TodoableID>java.lang.String</TodoableID>
<UserID>java.lang.String</UserID>
<IterationID>java.lang.String</IterationID>
<MilestoneID>java.lang.String</MilestoneID>
<WorkItemID>java.lang.String</WorkItemID>
<IssueID>java.lang.String</IssueID>
<ProjectID>java.lang.String</ProjectID>
<GroupID>java.lang.String</GroupID>
<LabelsFilterType>java.lang.String</LabelsFilterType>
<NegatedIterationWildcardId>java.lang.String</NegatedIterationWildcardId>
<Upload>java.lang.String</Upload>
<Color>java.lang.String</Color>
<PaymentMethodID>java.lang.String</PaymentMethodID>
<NamespaceID>java.lang.String</NamespaceID>
<AuditEventsStreamingHeadersID>java.lang.String</AuditEventsStreamingHeadersID>
<AuditEventsExternalAuditEventDestinationID>java.lang.String</AuditEventsExternalAuditEventDestinationID>
<GoogleCloudLoggingConfigurationID>java.lang.String</GoogleCloudLoggingConfigurationID>
<AmazonS3ConfigurationID>java.lang.String</AmazonS3ConfigurationID>
<InstanceAuditEventsStreamingHeadersID>java.lang.String</InstanceAuditEventsStreamingHeadersID>
<InstanceExternalAuditEventDestinationID>java.lang.String</InstanceExternalAuditEventDestinationID>
<InstanceGoogleCloudLoggingConfigurationID>java.lang.String</InstanceGoogleCloudLoggingConfigurationID>
<InstanceAmazonS3ConfigurationID>java.lang.String</InstanceAmazonS3ConfigurationID>
<JsonString>java.lang.String</JsonString>
</customTypesMapping>

<!-- Naming conventions -->
<modelNameSuffix></modelNameSuffix>
<requestSuffix>Request</requestSuffix>
<responseSuffix>Response</responseSuffix>
<responseProjectionSuffix>ResponseProjection</responseProjectionSuffix>

<!-- Use same custom template as GitHub for @SuppressWarnings -->
<customTemplatesRoot>${project.basedir}/src/main/resources/graphql/templates
</customTemplatesRoot>
<customTemplates>
<RESPONSE_PROJECTION>response_projection.ftl</RESPONSE_PROJECTION>
</customTemplates>
</configuration>
</execution>
</executions>
</plugin>
<!-- Post-processing for GraphQL generated code (cross-platform) -->
Expand All @@ -622,7 +721,7 @@
<!-- Delete Relay files that depend on missing Query root type -->
<delete failonerror="false">
<fileset
dir="${project.build.directory}/generated-sources/graphql/de/tum/in/www1/hephaestus/gitprovider/graphql/github/model">
dir="${project.build.directory}/generated-sources/graphql-github/de/tum/in/www1/hephaestus/gitprovider/graphql/github/model">
<include name="RelayQueryRequest.java"/>
<include name="RelayQueryResponse.java"/>
</fileset>
Expand All @@ -634,7 +733,7 @@
<substitution
expression="@SuppressWarnings(&quot;deprecation&quot;)${line.separator}\1"/>
<fileset
dir="${project.build.directory}/generated-sources/graphql/de/tum/in/www1/hephaestus/gitprovider/graphql/github/model">
dir="${project.build.directory}/generated-sources/graphql-github/de/tum/in/www1/hephaestus/gitprovider/graphql/github/model">
<include name="ProjectPendingCardsParametrizedInput.java"/>
<include name="IssueProjectCardsParametrizedInput.java"/>
<include name="PullRequestProjectCardsParametrizedInput.java"/>
Expand Down Expand Up @@ -825,7 +924,8 @@
<failOnViolation>false</failOnViolation>
<!-- Exclude generated code -->
<excludeRoots>
<excludeRoot>${project.build.directory}/generated-sources/graphql</excludeRoot>
<excludeRoot>${project.build.directory}/generated-sources/graphql-github</excludeRoot>
<excludeRoot>${project.build.directory}/generated-sources/graphql-gitlab</excludeRoot>
</excludeRoots>
</configuration>
</plugin>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public class CommitAuthorEnrichmentService {
* @param scopeId the scope ID for GraphQL client authentication
* @return the number of commits enriched
*/
public int enrichCommitAuthors(Long repositoryId, String nameWithOwner, @Nullable Long scopeId) {
public int enrichCommitAuthors(Long repositoryId, String nameWithOwner, @Nullable Long scopeId, Long providerId) {
// Phase 1: Find all distinct unresolved emails from the database
List<String> unresolvedAuthorEmails = commitRepository.findDistinctUnresolvedAuthorEmailsByRepositoryId(
repositoryId
Expand Down Expand Up @@ -175,7 +175,8 @@ public int enrichCommitAuthors(Long repositoryId, String nameWithOwner, @Nullabl
nameWithOwner,
scopeId,
stillUnresolvedAuthorEmails,
stillUnresolvedCommitterEmails
stillUnresolvedCommitterEmails,
providerId
);

int total = enrichedByEmail + enrichedByApi;
Expand Down Expand Up @@ -232,7 +233,8 @@ private int enrichByGitHubGraphQl(
String nameWithOwner,
Long scopeId,
List<String> unresolvedAuthorEmails,
List<String> unresolvedCommitterEmails
List<String> unresolvedCommitterEmails,
Long providerId
) {
// Collect all unique unresolved emails
Set<String> allUnresolvedEmails = new HashSet<>(unresolvedAuthorEmails);
Expand Down Expand Up @@ -280,7 +282,13 @@ private int enrichByGitHubGraphQl(
);

// Fetch commit authors in batches via GraphQL
Map<String, String> emailToLogin = fetchCommitAuthorsBatched(nameWithOwner, scopeId, validShas, shaToEmail);
Map<String, String> emailToLogin = fetchCommitAuthorsBatched(
nameWithOwner,
scopeId,
validShas,
shaToEmail,
providerId
);

// Bulk update: for each email → login, resolve login → user_id,
// then update all commits with that email
Expand Down Expand Up @@ -351,7 +359,8 @@ private Map<String, String> fetchCommitAuthorsBatched(
String nameWithOwner,
Long scopeId,
List<String> shas,
Map<String, String> shaToEmail
Map<String, String> shaToEmail,
Long providerId
) {
Map<String, String> emailToLogin = new HashMap<>();
Map<Long, GitHubUserDTO> usersToUpsert = new HashMap<>();
Expand Down Expand Up @@ -401,7 +410,7 @@ private Map<String, String> fetchCommitAuthorsBatched(
emailToLogin.putAll(batchResult);
}

upsertUsers(usersToUpsert, nameWithOwner);
upsertUsers(usersToUpsert, nameWithOwner, providerId);

return emailToLogin;
}
Expand Down Expand Up @@ -648,7 +657,7 @@ private UserSnapshot extractUserSnapshot(Map<String, Object> commitData, String
}
}

private void upsertUsers(Map<Long, GitHubUserDTO> usersToUpsert, String nameWithOwner) {
private void upsertUsers(Map<Long, GitHubUserDTO> usersToUpsert, String nameWithOwner, Long providerId) {
if (usersToUpsert.isEmpty()) {
return;
}
Expand All @@ -658,7 +667,7 @@ private void upsertUsers(Map<Long, GitHubUserDTO> usersToUpsert, String nameWith
continue;
}
try {
userProcessor.ensureExists(dto);
userProcessor.ensureExists(dto, providerId);
processed++;
} catch (Exception e) {
log.debug(
Expand Down
Loading
Loading