From 755ea05b158d5ee2298876d6e31512659a196057 Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 00:08:26 +0400 Subject: [PATCH 01/42] feat(persistence): set up JPA,Flayway and integration test with TestContainers --- backend/Task | 0 backend/There | 0 .../dev/cleat/api/CleatApiApplication.java | 2 +- .../api/src/main/resources/application.yml | 21 +++++--- backend/build.gradle.kts | 10 ++-- backend/gradle.properties | 1 + backend/initializationError | 0 backend/libs/persistence/build.gradle.kts | 13 ++++- .../dev/cleat/persistence/AccountEntity.java | 32 +++++++++++ .../cleat/persistence/AccountRepository.java | 8 +++ .../dev/cleat/persistence/RepoEntity.java | 30 +++++++++++ .../V1__create_account_and_repo_tables.sql | 13 +++++ .../persistence/AccountRepositoryTest.java | 54 +++++++++++++++++++ .../persistence/PersistenceTestConfig.java | 14 +++++ 14 files changed, 184 insertions(+), 14 deletions(-) create mode 100644 backend/Task create mode 100644 backend/There create mode 100644 backend/initializationError create mode 100644 backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java create mode 100644 backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java create mode 100644 backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java create mode 100644 backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql create mode 100644 backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java create mode 100644 backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java diff --git a/backend/Task b/backend/Task new file mode 100644 index 0000000..e69de29 diff --git a/backend/There b/backend/There new file mode 100644 index 0000000..e69de29 diff --git a/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java b/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java index 0ed835e..3f74745 100644 --- a/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java +++ b/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java @@ -3,7 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -@SpringBootApplication +@SpringBootApplication(scanBasePackages = "dev.cleat") public class CleatApiApplication { public static void main(String[] args) { SpringApplication.run(CleatApiApplication.class); diff --git a/backend/apps/api/src/main/resources/application.yml b/backend/apps/api/src/main/resources/application.yml index 31322b9..ec2f24f 100644 --- a/backend/apps/api/src/main/resources/application.yml +++ b/backend/apps/api/src/main/resources/application.yml @@ -1,13 +1,18 @@ spring: application: name: cleat-api - autoconfigure: - exclude: - # Temporary: database is not wired yet. - # Remove these excludes once datasource is configured in issue #5. - - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration - - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - - org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration + + + datasource: + url: jdbc:postgresql://localhost:5432/cleat_test + driver-class-name: org.postgresql.Driver + + jpa: + hibernate: + ddl-auto: validate + + flyway: + enabled: true server: port: 8080 @@ -24,3 +29,5 @@ management: enabled: false db: enabled: false + + diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 734c508..0844c90 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -1,6 +1,5 @@ import com.diffplug.gradle.spotless.SpotlessExtension import org.gradle.api.plugins.quality.CheckstyleExtension -import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { java @@ -32,11 +31,12 @@ subprojects { the().apply { imports { - mavenBom(SpringBootPlugin.BOM_COORDINATES) + mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.3") } } - configure { + + extensions.configure { java { palantirJavaFormat() removeUnusedImports() @@ -46,7 +46,7 @@ subprojects { } } - configure { + extensions.configure { toolVersion = "10.26.1" configFile = rootProject.file("config/checkstyle/checkstyle.xml") isIgnoreFailures = false @@ -55,4 +55,4 @@ subprojects { tasks.withType { useJUnitPlatform() } -} +} \ No newline at end of file diff --git a/backend/gradle.properties b/backend/gradle.properties index 8c5fc5c..6e2e266 100644 --- a/backend/gradle.properties +++ b/backend/gradle.properties @@ -1,3 +1,4 @@ org.gradle.caching=true org.gradle.parallel=true org.gradle.configuration-cache=true +systemProp.DOCKER_HOST=unix:///var/run/docker.sock diff --git a/backend/initializationError b/backend/initializationError new file mode 100644 index 0000000..e69de29 diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index 4da8a80..3dfb9c1 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -3,11 +3,22 @@ plugins { } dependencies { + testImplementation(project(":apps:api")) + testRuntimeOnly(project(":apps:api")) api(project(":libs:domain")) implementation(project(":libs:common")) api("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.flywaydb:flyway-core") - implementation("org.flywaydb:flyway-database-postgresql") + compileOnly("org.projectlombok:lombok") + annotationProcessor("org.projectlombok:lombok") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") + testImplementation("org.testcontainers:junit-jupiter") + testImplementation("org.testcontainers:postgresql") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + + implementation("org.springframework.boot:spring-boot-starter") } + + diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java new file mode 100644 index 0000000..af230bc --- /dev/null +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -0,0 +1,32 @@ + package dev.cleat.persistence; + + import jakarta.persistence.*; + import lombok.*; + import lombok.experimental.FieldDefaults; + import org.hibernate.annotations.CreationTimestamp; + import java.time.Instant; + import java.util.ArrayList; + import java.util.List; + import java.util.UUID; + +@Entity +@Table(name="account") +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) + public class AccountEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + UUID id; + + @CreationTimestamp + @Column(nullable = false,updatable = false) + Instant createdAt; + + @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + List repos = new ArrayList<>(); + + } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java new file mode 100644 index 0000000..023b2b4 --- /dev/null +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java @@ -0,0 +1,8 @@ +package dev.cleat.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface AccountRepository extends JpaRepository { +} diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java new file mode 100644 index 0000000..684889e --- /dev/null +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -0,0 +1,30 @@ +package dev.cleat.persistence; +import jakarta.persistence.*; +import lombok.*; +import lombok.experimental.FieldDefaults; +import org.hibernate.annotations.CreationTimestamp; +import java.time.Instant; +import java.util.UUID; + +@Entity +@Table(name = "repo") +@NoArgsConstructor +@Setter +@Getter +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +@AllArgsConstructor +public class RepoEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + UUID id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="account_id",nullable = false) + AccountEntity account; + + @CreationTimestamp + @Column(nullable = false,updatable = false) + Instant createdAt; +} diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql new file mode 100644 index 0000000..a4dc874 --- /dev/null +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -0,0 +1,13 @@ +CREATE TABLE account ( + id UUID PRIMARY KEY , + created_at TIMESTAMP WITH TIME ZONE NOT NULL +); + +CREATE TABLE repo( + id UUID PRIMARY KEY, + account_id UUID NOT NULL , + created_at TIMESTAMP WITH TIME ZONE NOT NULL , + CONSTRAINT fk_repo_account + FOREIGN KEY (account_id) + REFERENCES account(id) +) \ No newline at end of file diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java new file mode 100644 index 0000000..993bb8e --- /dev/null +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -0,0 +1,54 @@ +package dev.cleat.persistence; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.ArrayList; +import java.util.List; + +@DataJpaTest +@Testcontainers +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class AccountRepositoryTest { + + @Container + static PostgreSQLContainer postgres = + new PostgreSQLContainer<>("postgres:16"); + + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + registry.add("spring.datasource.username", postgres::getUsername); + registry.add("spring.datasource.password", postgres::getPassword); + + registry.add("spring.flyway.enabled", () -> false); + } + + @Autowired + AccountRepository accountRepository; + + @Test + void should_save_account_with_repo() { + AccountEntity account = new AccountEntity(); + + RepoEntity repo = new RepoEntity(); + repo.setAccount(account); + + account.setRepos(List.of(repo)); + + AccountEntity saved = accountRepository.save(account); + + Assertions.assertNotNull(saved.getId()); + Assertions.assertEquals(1, saved.getRepos().size()); + } +} \ No newline at end of file diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java new file mode 100644 index 0000000..0d22710 --- /dev/null +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java @@ -0,0 +1,14 @@ +package dev.cleat.persistence; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootConfiguration +@EnableAutoConfiguration +@EnableJpaRepositories(basePackages = "dev.cleat.persistence") +@EntityScan(basePackages = "dev.cleat.persistence") +public class PersistenceTestConfig { +} \ No newline at end of file From 06b601f11881ca198fb6c7deba6a9cb8906abc2c Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 00:24:14 +0400 Subject: [PATCH 02/42] style(persistence): fix code formatting and violations detected by spotless --- .../dev/cleat/persistence/AccountEntity.java | 63 ++++++----- .../cleat/persistence/AccountRepository.java | 14 +-- .../dev/cleat/persistence/RepoEntity.java | 61 ++++++----- .../persistence/AccountRepositoryTest.java | 103 +++++++++--------- .../persistence/PersistenceTestConfig.java | 26 ++--- 5 files changed, 129 insertions(+), 138 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index af230bc..6ecda8d 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -1,32 +1,31 @@ - package dev.cleat.persistence; - - import jakarta.persistence.*; - import lombok.*; - import lombok.experimental.FieldDefaults; - import org.hibernate.annotations.CreationTimestamp; - import java.time.Instant; - import java.util.ArrayList; - import java.util.List; - import java.util.UUID; - -@Entity -@Table(name="account") -@NoArgsConstructor -@AllArgsConstructor -@Setter -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) - public class AccountEntity { - - @Id - @GeneratedValue(strategy = GenerationType.UUID) - UUID id; - - @CreationTimestamp - @Column(nullable = false,updatable = false) - Instant createdAt; - - @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - List repos = new ArrayList<>(); - - } +package dev.cleat.persistence; + +import jakarta.persistence.*; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import lombok.*; +import lombok.experimental.FieldDefaults; +import org.hibernate.annotations.CreationTimestamp; + +@Entity +@Table(name = "account") +@NoArgsConstructor +@AllArgsConstructor +@Setter +@Getter +@FieldDefaults(level = AccessLevel.PRIVATE) +public class AccountEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + UUID id; + + @CreationTimestamp + @Column(nullable = false, updatable = false) + Instant createdAt; + + @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + List repos = new ArrayList<>(); +} diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java index 023b2b4..822d78a 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountRepository.java @@ -1,8 +1,6 @@ -package dev.cleat.persistence; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.UUID; - -public interface AccountRepository extends JpaRepository { -} +package dev.cleat.persistence; + +import java.util.UUID; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface AccountRepository extends JpaRepository {} diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index 684889e..808129c 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -1,30 +1,31 @@ -package dev.cleat.persistence; -import jakarta.persistence.*; -import lombok.*; -import lombok.experimental.FieldDefaults; -import org.hibernate.annotations.CreationTimestamp; -import java.time.Instant; -import java.util.UUID; - -@Entity -@Table(name = "repo") -@NoArgsConstructor -@Setter -@Getter -@Builder -@FieldDefaults(level = AccessLevel.PRIVATE) -@AllArgsConstructor -public class RepoEntity { - - @Id - @GeneratedValue(strategy = GenerationType.UUID) - UUID id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name="account_id",nullable = false) - AccountEntity account; - - @CreationTimestamp - @Column(nullable = false,updatable = false) - Instant createdAt; -} +package dev.cleat.persistence; + +import jakarta.persistence.*; +import java.time.Instant; +import java.util.UUID; +import lombok.*; +import lombok.experimental.FieldDefaults; +import org.hibernate.annotations.CreationTimestamp; + +@Entity +@Table(name = "repo") +@NoArgsConstructor +@Setter +@Getter +@Builder +@FieldDefaults(level = AccessLevel.PRIVATE) +@AllArgsConstructor +public class RepoEntity { + + @Id + @GeneratedValue(strategy = GenerationType.UUID) + UUID id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "account_id", nullable = false) + AccountEntity account; + + @CreationTimestamp + @Column(nullable = false, updatable = false) + Instant createdAt; +} diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 993bb8e..3504741 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,54 +1,49 @@ -package dev.cleat.persistence; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.context.annotation.Import; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import java.util.ArrayList; -import java.util.List; - -@DataJpaTest -@Testcontainers -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -class AccountRepositoryTest { - - @Container - static PostgreSQLContainer postgres = - new PostgreSQLContainer<>("postgres:16"); - - @DynamicPropertySource - static void props(DynamicPropertyRegistry registry) { - registry.add("spring.datasource.url", postgres::getJdbcUrl); - registry.add("spring.datasource.username", postgres::getUsername); - registry.add("spring.datasource.password", postgres::getPassword); - - registry.add("spring.flyway.enabled", () -> false); - } - - @Autowired - AccountRepository accountRepository; - - @Test - void should_save_account_with_repo() { - AccountEntity account = new AccountEntity(); - - RepoEntity repo = new RepoEntity(); - repo.setAccount(account); - - account.setRepos(List.of(repo)); - - AccountEntity saved = accountRepository.save(account); - - Assertions.assertNotNull(saved.getId()); - Assertions.assertEquals(1, saved.getRepos().size()); - } -} \ No newline at end of file +package dev.cleat.persistence; + +import java.util.List; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@DataJpaTest +@Testcontainers +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +class AccountRepositoryTest { + + @Container + static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); + + @DynamicPropertySource + static void props(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + registry.add("spring.datasource.username", postgres::getUsername); + registry.add("spring.datasource.password", postgres::getPassword); + + registry.add("spring.flyway.enabled", () -> false); + } + + @Autowired + AccountRepository accountRepository; + + @Test + void should_save_account_with_repo() { + AccountEntity account = new AccountEntity(); + + RepoEntity repo = new RepoEntity(); + repo.setAccount(account); + + account.setRepos(List.of(repo)); + + AccountEntity saved = accountRepository.save(account); + + Assertions.assertNotNull(saved.getId()); + Assertions.assertEquals(1, saved.getRepos().size()); + } +} diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java index 0d22710..4b32283 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java @@ -1,14 +1,12 @@ -package dev.cleat.persistence; - -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; - -@SpringBootConfiguration -@EnableAutoConfiguration -@EnableJpaRepositories(basePackages = "dev.cleat.persistence") -@EntityScan(basePackages = "dev.cleat.persistence") -public class PersistenceTestConfig { -} \ No newline at end of file +package dev.cleat.persistence; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootConfiguration +@EnableAutoConfiguration +@EnableJpaRepositories(basePackages = "dev.cleat.persistence") +@EntityScan(basePackages = "dev.cleat.persistence") +public class PersistenceTestConfig {} From 7524cebb55263d5c4dd722502d06d5c82ba0b966 Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 00:35:01 +0400 Subject: [PATCH 03/42] fix(persistence): remove star imports and order them alphabetically in RepoEntity --- .../dev/cleat/persistence/AccountEntity.java | 16 ++++++++++++++-- .../java/dev/cleat/persistence/RepoEntity.java | 17 +++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 6ecda8d..452b5f2 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -1,11 +1,23 @@ package dev.cleat.persistence; -import jakarta.persistence.*; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import lombok.*; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.FieldDefaults; import org.hibernate.annotations.CreationTimestamp; diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index 808129c..28857fe 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -1,9 +1,22 @@ package dev.cleat.persistence; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import java.time.Instant; import java.util.UUID; -import lombok.*; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; import lombok.experimental.FieldDefaults; import org.hibernate.annotations.CreationTimestamp; From 35f04ea5d4778e09fb698e89fcee53b4dae1a04d Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 00:42:45 +0400 Subject: [PATCH 04/42] fix(test): fix checkstyle method name and resolve pipeline test failure causes --- .../apps/api/src/test/java/dev/cleat/api/CleatApiTests.java | 3 ++- .../test/java/dev/cleat/persistence/AccountRepositoryTest.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java b/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java index aa02220..558819f 100644 --- a/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java +++ b/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java @@ -3,7 +3,8 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest +@SpringBootTest( + properties = {"spring.datasource.url=", "spring.flyway.enabled=false", "spring.jpa.hibernate.ddl-auto=none"}) public class CleatApiTests { @Test diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 3504741..162bad3 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -33,7 +33,7 @@ static void props(DynamicPropertyRegistry registry) { AccountRepository accountRepository; @Test - void should_save_account_with_repo() { + void shouldSaveAccountWithRepo() { AccountEntity account = new AccountEntity(); RepoEntity repo = new RepoEntity(); From 18196e167831befce1ac82196acc59a346021208 Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 00:50:14 +0400 Subject: [PATCH 05/42] fix(test): exclude db autoconfig in api test and pass dynamic flyway credentials in persistence test --- .../api/src/test/java/dev/cleat/api/CleatApiTests.java | 10 ++++++++-- .../dev/cleat/persistence/AccountRepositoryTest.java | 4 +++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java b/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java index 558819f..74f3070 100644 --- a/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java +++ b/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java @@ -1,10 +1,16 @@ package dev.cleat.api; import org.junit.jupiter.api.Test; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; -@SpringBootTest( - properties = {"spring.datasource.url=", "spring.flyway.enabled=false", "spring.jpa.hibernate.ddl-auto=none"}) +@SpringBootTest +@EnableAutoConfiguration( + exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, FlywayAutoConfiguration.class + }) public class CleatApiTests { @Test diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 162bad3..c1d4fb7 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -6,14 +6,16 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -@DataJpaTest +@DataJpaTest(properties = {"spring.jpa.hibernate.ddl-auto=validate"}) @Testcontainers +@Import(PersistenceTestConfig.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) class AccountRepositoryTest { From 98f29aa92d153d9cfe5196503e16ca53a718ef4c Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 00:55:14 +0400 Subject: [PATCH 06/42] fix(persistence): import FlywayAutoConfiguration explicitly in repository test --- .../cleat/persistence/AccountRepositoryTest.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index c1d4fb7..68fd13a 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,9 +1,12 @@ package dev.cleat.persistence; +import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; @@ -16,8 +19,9 @@ @DataJpaTest(properties = {"spring.jpa.hibernate.ddl-auto=validate"}) @Testcontainers @Import(PersistenceTestConfig.class) +@ImportAutoConfiguration(FlywayAutoConfiguration.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) -class AccountRepositoryTest { +public class AccountRepositoryTest { @Container static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); @@ -28,7 +32,9 @@ static void props(DynamicPropertyRegistry registry) { registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); - registry.add("spring.flyway.enabled", () -> false); + registry.add("spring.flyway.url", postgres::getJdbcUrl); + registry.add("spring.flyway.user", postgres::getUsername); + registry.add("spring.flyway.password", postgres::getPassword); } @Autowired @@ -37,11 +43,11 @@ static void props(DynamicPropertyRegistry registry) { @Test void shouldSaveAccountWithRepo() { AccountEntity account = new AccountEntity(); - RepoEntity repo = new RepoEntity(); repo.setAccount(account); - - account.setRepos(List.of(repo)); + List repos = new ArrayList<>(); + repos.add(repo); + account.setRepos(repos); AccountEntity saved = accountRepository.save(account); From 361a2c860d76f822d4ba7261d9ec9e59a8f0e3bd Mon Sep 17 00:00:00 2001 From: Arzu Date: Thu, 11 Jun 2026 01:01:39 +0400 Subject: [PATCH 07/42] fix(persistence): add flyway-database-postgresql driver dependency for runtime and test --- backend/libs/persistence/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index 3dfb9c1..dabda2e 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -9,6 +9,8 @@ dependencies { implementation(project(":libs:common")) api("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.flywaydb:flyway-core") + runtimeOnly("org.flywaydb:flyway-database-postgresql") + testRuntimeOnly("org.flywaydb:flyway-database-postgresql") compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") runtimeOnly("org.postgresql:postgresql") From 338329dda11b4a98085f2ca8e5c091f5da1e563b Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 21:25:30 +0400 Subject: [PATCH 08/42] refactor: revert api configuration and cleanup project structure --- backend/There | 0 .../api/src/main/java/dev/cleat/api/.gitkeep} | 0 .../api/src/main/resources/application.yml | 23 +++++++------------ backend/gradle.properties | 2 +- backend/gradlew | 0 backend/initializationError | 0 backend/libs/persistence/build.gradle.kts | 3 --- 7 files changed, 9 insertions(+), 19 deletions(-) delete mode 100644 backend/There rename backend/{Task => apps/api/src/main/java/dev/cleat/api/.gitkeep} (100%) mode change 100755 => 100644 backend/gradlew delete mode 100644 backend/initializationError diff --git a/backend/There b/backend/There deleted file mode 100644 index e69de29..0000000 diff --git a/backend/Task b/backend/apps/api/src/main/java/dev/cleat/api/.gitkeep similarity index 100% rename from backend/Task rename to backend/apps/api/src/main/java/dev/cleat/api/.gitkeep diff --git a/backend/apps/api/src/main/resources/application.yml b/backend/apps/api/src/main/resources/application.yml index ec2f24f..53b779a 100644 --- a/backend/apps/api/src/main/resources/application.yml +++ b/backend/apps/api/src/main/resources/application.yml @@ -1,18 +1,13 @@ spring: application: name: cleat-api - - - datasource: - url: jdbc:postgresql://localhost:5432/cleat_test - driver-class-name: org.postgresql.Driver - - jpa: - hibernate: - ddl-auto: validate - - flyway: - enabled: true + autoconfigure: + exclude: + # Temporary: database is not wired yet. + # Remove these excludes once datasource is configured in issue #5. + - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + - org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration server: port: 8080 @@ -28,6 +23,4 @@ management: redis: enabled: false db: - enabled: false - - + enabled: false \ No newline at end of file diff --git a/backend/gradle.properties b/backend/gradle.properties index 6e2e266..97f8878 100644 --- a/backend/gradle.properties +++ b/backend/gradle.properties @@ -1,4 +1,4 @@ org.gradle.caching=true org.gradle.parallel=true org.gradle.configuration-cache=true -systemProp.DOCKER_HOST=unix:///var/run/docker.sock + diff --git a/backend/gradlew b/backend/gradlew old mode 100755 new mode 100644 diff --git a/backend/initializationError b/backend/initializationError deleted file mode 100644 index e69de29..0000000 diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index dabda2e..3d625c0 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -3,7 +3,6 @@ plugins { } dependencies { - testImplementation(project(":apps:api")) testRuntimeOnly(project(":apps:api")) api(project(":libs:domain")) implementation(project(":libs:common")) @@ -18,8 +17,6 @@ dependencies { testImplementation("org.testcontainers:junit-jupiter") testImplementation("org.testcontainers:postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") - - implementation("org.springframework.boot:spring-boot-starter") } From 697704b8ef32eb583f64fa7439d1ba469e67253e Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 21:30:04 +0400 Subject: [PATCH 09/42] fix: ensure gradlew is executable --- backend/gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 backend/gradlew diff --git a/backend/gradlew b/backend/gradlew old mode 100644 new mode 100755 From 4327ad5d6d219f46be5f7028dae1a83ae0537f60 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 21:44:52 +0400 Subject: [PATCH 10/42] test: fix persistence test context and remove redundant bean configuration --- backend/gradlew | 0 .../dev/cleat/persistence/AccountRepositoryTest.java | 1 - .../dev/cleat/persistence/PersistenceTestConfig.java | 10 +++++----- .../persistence/src/test/resources/application.yml | 4 ++++ 4 files changed, 9 insertions(+), 6 deletions(-) mode change 100755 => 100644 backend/gradlew create mode 100644 backend/libs/persistence/src/test/resources/application.yml diff --git a/backend/gradlew b/backend/gradlew old mode 100755 new mode 100644 diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 68fd13a..b52eb8c 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -19,7 +19,6 @@ @DataJpaTest(properties = {"spring.jpa.hibernate.ddl-auto=validate"}) @Testcontainers @Import(PersistenceTestConfig.class) -@ImportAutoConfiguration(FlywayAutoConfiguration.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AccountRepositoryTest { diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java index 4b32283..5512c45 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java @@ -1,12 +1,12 @@ package dev.cleat.persistence; -import org.springframework.boot.SpringBootConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; + import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -@SpringBootConfiguration -@EnableAutoConfiguration +@Configuration // @SpringBootConfiguration əvəzinə @EnableJpaRepositories(basePackages = "dev.cleat.persistence") @EntityScan(basePackages = "dev.cleat.persistence") -public class PersistenceTestConfig {} +public class PersistenceTestConfig { +} diff --git a/backend/libs/persistence/src/test/resources/application.yml b/backend/libs/persistence/src/test/resources/application.yml new file mode 100644 index 0000000..a58b8f4 --- /dev/null +++ b/backend/libs/persistence/src/test/resources/application.yml @@ -0,0 +1,4 @@ +spring: + flyway: + enabled: true + fail-on-missing-locations: false \ No newline at end of file From a4161249cb6f6b092c7e563bc094c018a6faac0f Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 21:49:55 +0400 Subject: [PATCH 11/42] style: apply spotless code formatting --- .../java/dev/cleat/persistence/AccountRepositoryTest.java | 2 -- .../java/dev/cleat/persistence/PersistenceTestConfig.java | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index b52eb8c..8051cc9 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -5,8 +5,6 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java index 5512c45..3113131 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java @@ -1,6 +1,5 @@ package dev.cleat.persistence; - import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -8,5 +7,4 @@ @Configuration // @SpringBootConfiguration əvəzinə @EnableJpaRepositories(basePackages = "dev.cleat.persistence") @EntityScan(basePackages = "dev.cleat.persistence") -public class PersistenceTestConfig { -} +public class PersistenceTestConfig {} From a2c0c0c31762024542c513e5b28dc1d98226732b Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 22:05:29 +0400 Subject: [PATCH 12/42] fix(ci): fix gradle execution permission --- .github/workflows/backend-ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/backend-ci.yml b/.github/workflows/backend-ci.yml index fb22214..dbd6c5d 100644 --- a/.github/workflows/backend-ci.yml +++ b/.github/workflows/backend-ci.yml @@ -30,5 +30,8 @@ jobs: - name: Set up Gradle uses: gradle/actions/setup-gradle@v4 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + - name: Spotless, Checkstyle, compile, and test run: ./gradlew check --no-daemon From 435658e0e077d9ca92f11baa260a3513401eebb6 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 22:17:43 +0400 Subject: [PATCH 13/42] fix: fix initialization error using ContextConfiguration --- .../java/dev/cleat/persistence/AccountRepositoryTest.java | 6 ++---- .../java/dev/cleat/persistence/PersistenceTestConfig.java | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 8051cc9..f6edc28 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -8,6 +8,7 @@ import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; @@ -16,7 +17,7 @@ @DataJpaTest(properties = {"spring.jpa.hibernate.ddl-auto=validate"}) @Testcontainers -@Import(PersistenceTestConfig.class) +@ContextConfiguration(classes = {PersistenceTestConfig.class}) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AccountRepositoryTest { @@ -29,9 +30,6 @@ static void props(DynamicPropertyRegistry registry) { registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); - registry.add("spring.flyway.url", postgres::getJdbcUrl); - registry.add("spring.flyway.user", postgres::getUsername); - registry.add("spring.flyway.password", postgres::getPassword); } @Autowired diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java index 3113131..2e6a61d 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java @@ -4,7 +4,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -@Configuration // @SpringBootConfiguration əvəzinə +@Configuration @EnableJpaRepositories(basePackages = "dev.cleat.persistence") @EntityScan(basePackages = "dev.cleat.persistence") public class PersistenceTestConfig {} From 6bf74a09ee4981e9944b0d942814189a8152ee5f Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 22:19:13 +0400 Subject: [PATCH 14/42] style: apply spotless code formatting --- .../test/java/dev/cleat/persistence/AccountRepositoryTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index f6edc28..9448bae 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -7,7 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.context.annotation.Import; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; @@ -29,7 +28,6 @@ static void props(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); registry.add("spring.datasource.username", postgres::getUsername); registry.add("spring.datasource.password", postgres::getPassword); - } @Autowired From 52a7fc0baba33fd593dd17f6ce3478fe72fbdf2a Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 22:40:35 +0400 Subject: [PATCH 15/42] refactor: revert unnecessary scanBasePackages from application class --- .../java/dev/cleat/api/CleatApiApplication.java | 2 +- .../cleat/persistence/AccountRepositoryTest.java | 13 +++++-------- .../cleat/persistence/PersistenceTestConfig.java | 10 ---------- 3 files changed, 6 insertions(+), 19 deletions(-) delete mode 100644 backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java diff --git a/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java b/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java index 3f74745..0ed835e 100644 --- a/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java +++ b/backend/apps/api/src/main/java/dev/cleat/api/CleatApiApplication.java @@ -3,7 +3,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -@SpringBootApplication(scanBasePackages = "dev.cleat") +@SpringBootApplication public class CleatApiApplication { public static void main(String[] args) { SpringApplication.run(CleatApiApplication.class); diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 9448bae..9132dac 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,23 +1,20 @@ package dev.cleat.persistence; -import java.util.ArrayList; -import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; -import org.springframework.test.context.ContextConfiguration; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -@DataJpaTest(properties = {"spring.jpa.hibernate.ddl-auto=validate"}) +import java.util.ArrayList; +import java.util.List; + +@SpringBootTest @Testcontainers -@ContextConfiguration(classes = {PersistenceTestConfig.class}) -@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AccountRepositoryTest { @Container diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java deleted file mode 100644 index 2e6a61d..0000000 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/PersistenceTestConfig.java +++ /dev/null @@ -1,10 +0,0 @@ -package dev.cleat.persistence; - -import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; - -@Configuration -@EnableJpaRepositories(basePackages = "dev.cleat.persistence") -@EntityScan(basePackages = "dev.cleat.persistence") -public class PersistenceTestConfig {} From c5544e6d41f46415b71ff2b621530d58ca437657 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Thu, 11 Jun 2026 22:45:08 +0400 Subject: [PATCH 16/42] style: fix spotless violations in AccountRepositoryTest --- .../java/dev/cleat/persistence/AccountRepositoryTest.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 9132dac..e622ed9 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,5 +1,7 @@ package dev.cleat.persistence; +import java.util.ArrayList; +import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -10,9 +12,6 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -import java.util.ArrayList; -import java.util.List; - @SpringBootTest @Testcontainers public class AccountRepositoryTest { From f23748c98e4a3cb0261fd6226fcc94f3ceb5dfa9 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 09:38:26 +0400 Subject: [PATCH 17/42] style: fix code formatting with spotless --- .../java/dev/cleat/persistence/AccountRepositoryTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index e622ed9..8ed08a2 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -5,7 +5,10 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; @@ -14,6 +17,9 @@ @SpringBootTest @Testcontainers +@ComponentScan(basePackages = "dev.cleat.persistence") +@EnableJpaRepositories(basePackages = "dev.cleat.persistence") +@EntityScan(basePackages = "dev.cleat.persistence") public class AccountRepositoryTest { @Container From 1f34b90048288bfa7999aa2f4e50a83c3444b542 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 09:54:56 +0400 Subject: [PATCH 18/42] refactor: remove autoconfigure excludes to enable database support --- backend/apps/api/src/main/resources/application.yml | 9 +-------- .../dev/cleat/persistence/AccountRepositoryTest.java | 10 +++------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/backend/apps/api/src/main/resources/application.yml b/backend/apps/api/src/main/resources/application.yml index 53b779a..2396031 100644 --- a/backend/apps/api/src/main/resources/application.yml +++ b/backend/apps/api/src/main/resources/application.yml @@ -1,13 +1,6 @@ spring: application: name: cleat-api - autoconfigure: - exclude: - # Temporary: database is not wired yet. - # Remove these excludes once datasource is configured in issue #5. - - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration - - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - - org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration server: port: 8080 @@ -23,4 +16,4 @@ management: redis: enabled: false db: - enabled: false \ No newline at end of file + enabled: true \ No newline at end of file diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 8ed08a2..5fed459 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -5,21 +5,17 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -@SpringBootTest +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) @Testcontainers -@ComponentScan(basePackages = "dev.cleat.persistence") -@EnableJpaRepositories(basePackages = "dev.cleat.persistence") -@EntityScan(basePackages = "dev.cleat.persistence") +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AccountRepositoryTest { @Container From 013edadbafd915863adfd15bc0e37e6cedf1daf2 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 10:48:47 +0400 Subject: [PATCH 19/42] test: link persistence tests to application context --- backend/apps/api/build.gradle.kts | 1 + backend/libs/persistence/build.gradle.kts | 2 +- .../test/java/dev/cleat/persistence/AccountRepositoryTest.java | 3 ++- backend/libs/persistence/src/test/resources/application.yml | 1 - 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/apps/api/build.gradle.kts b/backend/apps/api/build.gradle.kts index 2a5efe5..4704145 100644 --- a/backend/apps/api/build.gradle.kts +++ b/backend/apps/api/build.gradle.kts @@ -3,6 +3,7 @@ plugins { } dependencies { + implementation(project(":apps:api")) implementation(project(":libs:common")) implementation(project(":libs:domain")) implementation(project(":libs:persistence")) diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index 3d625c0..5ba399d 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } dependencies { - testRuntimeOnly(project(":apps:api")) + implementation(project(":apps:api")) api(project(":libs:domain")) implementation(project(":libs:common")) api("org.springframework.boot:spring-boot-starter-data-jpa") diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 5fed459..211c67a 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,5 +1,6 @@ package dev.cleat.persistence; +import dev.cleat.api.CleatApiApplication; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Assertions; @@ -13,7 +14,7 @@ import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) +@SpringBootTest(classes = CleatApiApplication.class) @Testcontainers @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AccountRepositoryTest { diff --git a/backend/libs/persistence/src/test/resources/application.yml b/backend/libs/persistence/src/test/resources/application.yml index a58b8f4..46fff37 100644 --- a/backend/libs/persistence/src/test/resources/application.yml +++ b/backend/libs/persistence/src/test/resources/application.yml @@ -1,4 +1,3 @@ spring: flyway: enabled: true - fail-on-missing-locations: false \ No newline at end of file From 5b9fbbdd7dc49699567692a70c1ba4ca76c065e3 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 10:57:09 +0400 Subject: [PATCH 20/42] test: refactor persistence test to use testconainers with local test configuration --- backend/libs/persistence/build.gradle.kts | 1 - .../java/dev/cleat/persistence/AccountRepositoryTest.java | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index 5ba399d..ac776de 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -3,7 +3,6 @@ plugins { } dependencies { - implementation(project(":apps:api")) api(project(":libs:domain")) implementation(project(":libs:common")) api("org.springframework.boot:spring-boot-starter-data-jpa") diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 211c67a..80933f9 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,6 +1,5 @@ package dev.cleat.persistence; -import dev.cleat.api.CleatApiApplication; import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Assertions; @@ -8,17 +7,21 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -@SpringBootTest(classes = CleatApiApplication.class) +@SpringBootTest @Testcontainers @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public class AccountRepositoryTest { + @TestConfiguration + static class TestConfig {} + @Container static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); From 22609256de84edffe9e7d65c865bfb7ddecbaa05 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 12:07:16 +0400 Subject: [PATCH 21/42] fix(persistence): resolve context loading issues in AccountRepositoryTest --- backend/libs/persistence/build.gradle.kts | 2 +- .../dev/cleat/persistence/AccountRepositoryTest.java | 10 ++++------ .../dev/cleat/persistence/TestPersistenceConfig.java | 10 ++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 backend/libs/persistence/src/test/java/dev/cleat/persistence/TestPersistenceConfig.java diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index ac776de..661d6b8 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -1,8 +1,8 @@ plugins { `java-library` } - dependencies { + testImplementation(project(":libs:persistence")) api(project(":libs:domain")) implementation(project(":libs:common")) api("org.springframework.boot:spring-boot-starter-data-jpa") diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 80933f9..9e20037 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -6,22 +6,20 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers; -@SpringBootTest +@DataJpaTest @Testcontainers @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@ContextConfiguration(classes = TestPersistenceConfig.class) public class AccountRepositoryTest { - @TestConfiguration - static class TestConfig {} - @Container static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/TestPersistenceConfig.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/TestPersistenceConfig.java new file mode 100644 index 0000000..c5e1ce7 --- /dev/null +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/TestPersistenceConfig.java @@ -0,0 +1,10 @@ +package dev.cleat.persistence; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@Configuration +@EnableJpaRepositories(basePackages = "dev.cleat.persistence") +@EntityScan(basePackages = "dev.cleat.persistence") +public class TestPersistenceConfig {} From 2bf9b32d20bdcb0d28876c4353661f86b9913a5d Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 12:12:37 +0400 Subject: [PATCH 22/42] refactor(persistence): remove circular dependency in persistence module tests --- backend/libs/persistence/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index 661d6b8..ba11450 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -2,7 +2,6 @@ plugins { `java-library` } dependencies { - testImplementation(project(":libs:persistence")) api(project(":libs:domain")) implementation(project(":libs:common")) api("org.springframework.boot:spring-boot-starter-data-jpa") From 55470121c49aacffefabee21f39e9f29bcdd0c32 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 12:19:36 +0400 Subject: [PATCH 23/42] fix(build): remove circular project dependency in apps:api --- backend/apps/api/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/apps/api/build.gradle.kts b/backend/apps/api/build.gradle.kts index 4704145..2a5efe5 100644 --- a/backend/apps/api/build.gradle.kts +++ b/backend/apps/api/build.gradle.kts @@ -3,7 +3,6 @@ plugins { } dependencies { - implementation(project(":apps:api")) implementation(project(":libs:common")) implementation(project(":libs:domain")) implementation(project(":libs:persistence")) From 3a50cdfb732332abc273f0f511450a4ece0ec722 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 12:34:42 +0400 Subject: [PATCH 24/42] refactor(persistence): cllean up dependencies --- backend/libs/persistence/build.gradle.kts | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index ba11450..3f3fe79 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -7,7 +7,6 @@ dependencies { api("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.flywaydb:flyway-core") runtimeOnly("org.flywaydb:flyway-database-postgresql") - testRuntimeOnly("org.flywaydb:flyway-database-postgresql") compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") runtimeOnly("org.postgresql:postgresql") @@ -15,7 +14,6 @@ dependencies { testImplementation("org.testcontainers:junit-jupiter") testImplementation("org.testcontainers:postgresql") testRuntimeOnly("org.junit.platform:junit-platform-launcher") - implementation("org.springframework.boot:spring-boot-starter") } From 0e354020e2b18da7bc9ed1f5318d133be0b431ac Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 12:48:13 +0400 Subject: [PATCH 25/42] refactor(persistence): remove Lombok in favor of standard Java boilerplate --- backend/libs/persistence/build.gradle.kts | 2 - .../dev/cleat/persistence/AccountEntity.java | 52 +++++++++++++----- .../dev/cleat/persistence/RepoEntity.java | 54 +++++++++++++------ 3 files changed, 76 insertions(+), 32 deletions(-) diff --git a/backend/libs/persistence/build.gradle.kts b/backend/libs/persistence/build.gradle.kts index 3f3fe79..c79da08 100644 --- a/backend/libs/persistence/build.gradle.kts +++ b/backend/libs/persistence/build.gradle.kts @@ -7,8 +7,6 @@ dependencies { api("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.flywaydb:flyway-core") runtimeOnly("org.flywaydb:flyway-database-postgresql") - compileOnly("org.projectlombok:lombok") - annotationProcessor("org.projectlombok:lombok") runtimeOnly("org.postgresql:postgresql") testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.testcontainers:junit-jupiter") diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 452b5f2..427bb93 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -13,31 +13,55 @@ import java.util.ArrayList; import java.util.List; import java.util.UUID; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.experimental.FieldDefaults; import org.hibernate.annotations.CreationTimestamp; @Entity @Table(name = "account") -@NoArgsConstructor -@AllArgsConstructor -@Setter -@Getter -@FieldDefaults(level = AccessLevel.PRIVATE) public class AccountEntity { @Id @GeneratedValue(strategy = GenerationType.UUID) - UUID id; + private UUID id; @CreationTimestamp @Column(nullable = false, updatable = false) - Instant createdAt; + private Instant createdAt; @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, fetch = FetchType.LAZY) - List repos = new ArrayList<>(); + private List repos = new ArrayList<>(); + + public AccountEntity(UUID id, Instant createdAt, List repos) { + this.id = id; + this.createdAt = createdAt; + this.repos = repos; + } + + public AccountEntity() {} + + public UUID getId() { + return id; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public List getRepos() { + return repos; + } + + public AccountEntity setId(UUID id) { + this.id = id; + return this; + } + + public AccountEntity setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + return this; + } + + public AccountEntity setRepos(List repos) { + this.repos = repos; + return this; + } } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index 28857fe..8d9f8da 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -11,34 +11,56 @@ import jakarta.persistence.Table; import java.time.Instant; import java.util.UUID; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.experimental.FieldDefaults; import org.hibernate.annotations.CreationTimestamp; @Entity @Table(name = "repo") -@NoArgsConstructor -@Setter -@Getter -@Builder -@FieldDefaults(level = AccessLevel.PRIVATE) -@AllArgsConstructor public class RepoEntity { @Id @GeneratedValue(strategy = GenerationType.UUID) - UUID id; + private UUID id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "account_id", nullable = false) - AccountEntity account; + private AccountEntity account; @CreationTimestamp @Column(nullable = false, updatable = false) - Instant createdAt; + private Instant createdAt; + + public RepoEntity() {} + + public RepoEntity(UUID id, AccountEntity account, Instant createdAt) { + this.id = id; + this.account = account; + this.createdAt = createdAt; + } + + public UUID getId() { + return id; + } + + public RepoEntity setId(UUID id) { + this.id = id; + return this; + } + + public AccountEntity getAccount() { + return account; + } + + public RepoEntity setAccount(AccountEntity account) { + this.account = account; + return this; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public RepoEntity setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + return this; + } } From 4e17e129287568a1f902552a42dbb557278d6e4a Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 14:11:43 +0400 Subject: [PATCH 26/42] feat(persistence): add account and repo schema and entities --- .../dev/cleat/persistence/AccountEntity.java | 163 +++++++++-- .../dev/cleat/persistence/RepoEntity.java | 267 +++++++++++++++++- .../V1__create_account_and_repo_tables.sql | 36 ++- 3 files changed, 431 insertions(+), 35 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 427bb93..62a8886 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -1,15 +1,7 @@ package dev.cleat.persistence; -import jakarta.persistence.CascadeType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.OneToMany; -import jakarta.persistence.Table; -import java.time.Instant; +import jakarta.persistence.*; +import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -23,15 +15,63 @@ public class AccountEntity { @GeneratedValue(strategy = GenerationType.UUID) private UUID id; + @Column(nullable = false) + private String login; + + @Column(nullable = false) + private String name; + + @Column(nullable = false) + private String type; + + @Column(nullable = false) + private String plan; + + @Column(name = "repo_count") + private Integer repoCount = 0; + + @Column(name = "member_count") + private Integer memberCount = 0; + + @Column(name = "posture_score") + private Double postureScore = 0.0; + + @Column(name = "monthly_spend") + private Double monthlySpend = 0.0; + + @Column(name = "reclaimable") + private Double reclaimable = 0.0; + @CreationTimestamp - @Column(nullable = false, updatable = false) - private Instant createdAt; + @Column(name = "created_at", nullable = false, updatable = false) + private OffsetDateTime createdAt; - @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, fetch = FetchType.LAZY) + @OneToMany(mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true) private List repos = new ArrayList<>(); - public AccountEntity(UUID id, Instant createdAt, List repos) { + public AccountEntity( + UUID id, + String login, + String name, + String type, + String plan, + Integer repoCount, + Integer memberCount, + Double postureScore, + Double monthlySpend, + Double reclaimable, + OffsetDateTime createdAt, + List repos) { this.id = id; + this.login = login; + this.name = name; + this.type = type; + this.plan = plan; + this.repoCount = repoCount; + this.memberCount = memberCount; + this.postureScore = postureScore; + this.monthlySpend = monthlySpend; + this.reclaimable = reclaimable; this.createdAt = createdAt; this.repos = repos; } @@ -42,24 +82,105 @@ public UUID getId() { return id; } - public Instant getCreatedAt() { - return createdAt; + public AccountEntity setId(UUID id) { + this.id = id; + return this; } - public List getRepos() { - return repos; + public String getLogin() { + return login; } - public AccountEntity setId(UUID id) { - this.id = id; + public AccountEntity setLogin(String login) { + this.login = login; + return this; + } + + public String getName() { + return name; + } + + public AccountEntity setName(String name) { + this.name = name; + return this; + } + + public String getType() { + return type; + } + + public AccountEntity setType(String type) { + this.type = type; + return this; + } + + public String getPlan() { + return plan; + } + + public AccountEntity setPlan(String plan) { + this.plan = plan; return this; } - public AccountEntity setCreatedAt(Instant createdAt) { + public Integer getRepoCount() { + return repoCount; + } + + public AccountEntity setRepoCount(Integer repoCount) { + this.repoCount = repoCount; + return this; + } + + public Integer getMemberCount() { + return memberCount; + } + + public AccountEntity setMemberCount(Integer memberCount) { + this.memberCount = memberCount; + return this; + } + + public Double getPostureScore() { + return postureScore; + } + + public AccountEntity setPostureScore(Double postureScore) { + this.postureScore = postureScore; + return this; + } + + public Double getMonthlySpend() { + return monthlySpend; + } + + public AccountEntity setMonthlySpend(Double monthlySpend) { + this.monthlySpend = monthlySpend; + return this; + } + + public Double getReclaimable() { + return reclaimable; + } + + public AccountEntity setReclaimable(Double reclaimable) { + this.reclaimable = reclaimable; + return this; + } + + public OffsetDateTime getCreatedAt() { + return createdAt; + } + + public AccountEntity setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; return this; } + public List getRepos() { + return repos; + } + public AccountEntity setRepos(List repos) { this.repos = repos; return this; diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index 8d9f8da..d6f50f1 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -3,13 +3,11 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; -import java.time.Instant; +import java.time.OffsetDateTime; import java.util.UUID; import org.hibernate.annotations.CreationTimestamp; @@ -18,25 +16,92 @@ public class RepoEntity { @Id - @GeneratedValue(strategy = GenerationType.UUID) private UUID id; + @Column(nullable = false) + private String name; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "account_id", nullable = false) private AccountEntity account; - @CreationTimestamp - @Column(nullable = false, updatable = false) - private Instant createdAt; + @Column(nullable = false) + private String visibility; - public RepoEntity() {} + private String language; + private Integer stars = 0; + private String defaultBranch; + private Boolean branchProtected = false; + private Boolean hasReadme = false; + private Boolean hasLicense = false; + private Boolean hasContributing = false; + private Boolean hasCodeowners = false; + private Boolean hasCi = false; + private Double sizeMb = 0.0; + private OffsetDateTime lastPushedAt; + private Boolean archived = false; + private Double openVulns = 0.0; + private Double openSecrets = 0.0; + private Integer openCodeAlerts = 0; + private Integer staleBranches = 0; + private Integer openPRs = 0; + private Double hygieneScore = 0.0; - public RepoEntity(UUID id, AccountEntity account, Instant createdAt) { + @CreationTimestamp + @Column(name = "created_at", nullable = false, updatable = false) + private OffsetDateTime createdAt; + + public RepoEntity( + UUID id, + String name, + AccountEntity account, + String visibility, + String language, + Integer stars, + String defaultBranch, + Boolean branchProtected, + Boolean hasReadme, + Boolean hasLicense, + Boolean hasContributing, + Boolean hasCodeowners, + Boolean hasCi, + Double sizeMb, + OffsetDateTime lastPushedAt, + Boolean archived, + Double openVulns, + Double openSecrets, + Integer openCodeAlerts, + Integer staleBranches, + Integer openPRs, + Double hygieneScore, + OffsetDateTime createdAt) { this.id = id; + this.name = name; this.account = account; + this.visibility = visibility; + this.language = language; + this.stars = stars; + this.defaultBranch = defaultBranch; + this.branchProtected = branchProtected; + this.hasReadme = hasReadme; + this.hasLicense = hasLicense; + this.hasContributing = hasContributing; + this.hasCodeowners = hasCodeowners; + this.hasCi = hasCi; + this.sizeMb = sizeMb; + this.lastPushedAt = lastPushedAt; + this.archived = archived; + this.openVulns = openVulns; + this.openSecrets = openSecrets; + this.openCodeAlerts = openCodeAlerts; + this.staleBranches = staleBranches; + this.openPRs = openPRs; + this.hygieneScore = hygieneScore; this.createdAt = createdAt; } + public RepoEntity() {} + public UUID getId() { return id; } @@ -46,6 +111,15 @@ public RepoEntity setId(UUID id) { return this; } + public String getName() { + return name; + } + + public RepoEntity setName(String name) { + this.name = name; + return this; + } + public AccountEntity getAccount() { return account; } @@ -55,11 +129,182 @@ public RepoEntity setAccount(AccountEntity account) { return this; } - public Instant getCreatedAt() { + public String getVisibility() { + return visibility; + } + + public RepoEntity setVisibility(String visibility) { + this.visibility = visibility; + return this; + } + + public String getLanguage() { + return language; + } + + public RepoEntity setLanguage(String language) { + this.language = language; + return this; + } + + public Integer getStars() { + return stars; + } + + public RepoEntity setStars(Integer stars) { + this.stars = stars; + return this; + } + + public String getDefaultBranch() { + return defaultBranch; + } + + public RepoEntity setDefaultBranch(String defaultBranch) { + this.defaultBranch = defaultBranch; + return this; + } + + public Boolean getBranchProtected() { + return branchProtected; + } + + public RepoEntity setBranchProtected(Boolean branchProtected) { + this.branchProtected = branchProtected; + return this; + } + + public Boolean getHasReadme() { + return hasReadme; + } + + public RepoEntity setHasReadme(Boolean hasReadme) { + this.hasReadme = hasReadme; + return this; + } + + public Boolean getHasLicense() { + return hasLicense; + } + + public RepoEntity setHasLicense(Boolean hasLicense) { + this.hasLicense = hasLicense; + return this; + } + + public Boolean getHasContributing() { + return hasContributing; + } + + public RepoEntity setHasContributing(Boolean hasContributing) { + this.hasContributing = hasContributing; + return this; + } + + public Boolean getHasCodeowners() { + return hasCodeowners; + } + + public RepoEntity setHasCodeowners(Boolean hasCodeowners) { + this.hasCodeowners = hasCodeowners; + return this; + } + + public Boolean getHasCi() { + return hasCi; + } + + public RepoEntity setHasCi(Boolean hasCi) { + this.hasCi = hasCi; + return this; + } + + public Double getSizeMb() { + return sizeMb; + } + + public RepoEntity setSizeMb(Double sizeMb) { + this.sizeMb = sizeMb; + return this; + } + + public OffsetDateTime getLastPushedAt() { + return lastPushedAt; + } + + public RepoEntity setLastPushedAt(OffsetDateTime lastPushedAt) { + this.lastPushedAt = lastPushedAt; + return this; + } + + public Boolean getArchived() { + return archived; + } + + public RepoEntity setArchived(Boolean archived) { + this.archived = archived; + return this; + } + + public Double getOpenVulns() { + return openVulns; + } + + public RepoEntity setOpenVulns(Double openVulns) { + this.openVulns = openVulns; + return this; + } + + public Double getOpenSecrets() { + return openSecrets; + } + + public RepoEntity setOpenSecrets(Double openSecrets) { + this.openSecrets = openSecrets; + return this; + } + + public Integer getOpenCodeAlerts() { + return openCodeAlerts; + } + + public RepoEntity setOpenCodeAlerts(Integer openCodeAlerts) { + this.openCodeAlerts = openCodeAlerts; + return this; + } + + public Integer getStaleBranches() { + return staleBranches; + } + + public RepoEntity setStaleBranches(Integer staleBranches) { + this.staleBranches = staleBranches; + return this; + } + + public Integer getOpenPRs() { + return openPRs; + } + + public RepoEntity setOpenPRs(Integer openPRs) { + this.openPRs = openPRs; + return this; + } + + public Double getHygieneScore() { + return hygieneScore; + } + + public RepoEntity setHygieneScore(Double hygieneScore) { + this.hygieneScore = hygieneScore; + return this; + } + + public OffsetDateTime getCreatedAt() { return createdAt; } - public RepoEntity setCreatedAt(Instant createdAt) { + public RepoEntity setCreatedAt(OffsetDateTime createdAt) { this.createdAt = createdAt; return this; } diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index a4dc874..3ff3027 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -1,13 +1,43 @@ CREATE TABLE account ( - id UUID PRIMARY KEY , + id UUID PRIMARY KEY, + login VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(50) NOT NULL, + plan VARCHAR(50) NOT NULL, + repo_count INT DEFAULT 0, + member_count INT DEFAULT 0, + posture_score FLOAT DEFAULT 0.0, + monthly_spend FLOAT DEFAULT 0.0, + reclaimable FLOAT DEFAULT 0.0, created_at TIMESTAMP WITH TIME ZONE NOT NULL ); CREATE TABLE repo( id UUID PRIMARY KEY, - account_id UUID NOT NULL , + account_id UUID NOT NULL, + name VARCHAR(255) NOT NULL, + visibility VARCHAR(50) NOT NULL, + language VARCHAR(100), + stars int DEFAULT 0, + default_branch VARCHAR(255), + branch_protected BOOLEAN DEFAULT FALSE, + has_readme BOOLEAN DEFAULT FALSE, + has_license BOOLEAN DEFAULT FALSE, + has_contributing BOOLEAN DEFAULT FALSE, + has_codeowners BOOLEAN DEFAULT FALSE, + has_ci BOOLEAN DEFAULT FALSE, + size_mb FLOAT DEFAULT 0.0, + last_pushed_at TIMESTAMP WITH TIME ZONE, + archived BOOLEAN DEFAULT FALSE, + open_vulns FLOAT DEFAULT 0.0, + open_secrets FLOAT DEFAULT 0.0, + open_code_alert INT DEFAULT 0, + stale_branches INT DEFAULT 0, + open_prs INT DEFAULT 0, + hygiene_score FLOAT DEFAULT 0.0, created_at TIMESTAMP WITH TIME ZONE NOT NULL , CONSTRAINT fk_repo_account FOREIGN KEY (account_id) REFERENCES account(id) -) \ No newline at end of file +); + From ab8e69a3ae142894050c97576f1a54b22a977d52 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 14:21:22 +0400 Subject: [PATCH 27/42] refactor(persistence): fix checkstyle violations and optimize imports --- .../src/main/java/dev/cleat/persistence/AccountEntity.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 62a8886..8cdcb4f 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -1,6 +1,11 @@ package dev.cleat.persistence; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; From cc796aa559eacf5a5199b54998bbd0f62743d21f Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 14:28:52 +0400 Subject: [PATCH 28/42] fix(persistence): import missing JPA annotations for AccountEntity --- .../src/main/java/dev/cleat/persistence/AccountEntity.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 8cdcb4f..4a8ef17 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -1,10 +1,12 @@ package dev.cleat.persistence; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import java.time.OffsetDateTime; import java.util.ArrayList; From 54fd1f263cd41005040cc27ec7929442a168e5cd Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 14:35:06 +0400 Subject: [PATCH 29/42] fix(persistence): resolve IdentifierGenerationException by adding @GeneratedValue to RepoEntity --- .../src/main/java/dev/cleat/persistence/RepoEntity.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index d6f50f1..73783f1 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -3,19 +3,23 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import org.hibernate.annotations.CreationTimestamp; + import java.time.OffsetDateTime; import java.util.UUID; -import org.hibernate.annotations.CreationTimestamp; @Entity @Table(name = "repo") public class RepoEntity { @Id + @GeneratedValue(strategy = GenerationType.UUID) private UUID id; @Column(nullable = false) From 0b49008e166268aa15700071abec51d478409347 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 14:40:51 +0400 Subject: [PATCH 30/42] chore(persistence): fix import ordering violations via spotless --- .../src/main/java/dev/cleat/persistence/RepoEntity.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index 73783f1..da38f03 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -9,10 +9,9 @@ import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; -import org.hibernate.annotations.CreationTimestamp; - import java.time.OffsetDateTime; import java.util.UUID; +import org.hibernate.annotations.CreationTimestamp; @Entity @Table(name = "repo") From 205bd206708f414aae70512fb87b81969c19cedd Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 15:47:35 +0400 Subject: [PATCH 31/42] chore(persistence): add index to repo account_id for performance --- .../db/migration/V1__create_account_and_repo_tables.sql | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index 3ff3027..928290c 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -41,3 +41,6 @@ CREATE TABLE repo( REFERENCES account(id) ); +CREATE INDEX idx_repo_account_id ON repo(account_id); + + From c301b0f90e5594f3f387d950f80be8a5c379ef78 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 16:01:35 +0400 Subject: [PATCH 32/42] test(persistence): improve AccountRepositoryTest with flush and clear for robust validation --- .../persistence/AccountRepositoryTest.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 9e20037..bb36867 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -1,12 +1,12 @@ package dev.cleat.persistence; -import java.util.ArrayList; import java.util.List; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; @@ -23,6 +23,9 @@ public class AccountRepositoryTest { @Container static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); + @Autowired + private TestEntityManager testEntityManager; + @DynamicPropertySource static void props(DynamicPropertyRegistry registry) { registry.add("spring.datasource.url", postgres::getJdbcUrl); @@ -37,14 +40,12 @@ static void props(DynamicPropertyRegistry registry) { void shouldSaveAccountWithRepo() { AccountEntity account = new AccountEntity(); RepoEntity repo = new RepoEntity(); + account.setRepos(List.of(repo)); repo.setAccount(account); - List repos = new ArrayList<>(); - repos.add(repo); - account.setRepos(repos); - - AccountEntity saved = accountRepository.save(account); - - Assertions.assertNotNull(saved.getId()); - Assertions.assertEquals(1, saved.getRepos().size()); + accountRepository.saveAndFlush(account); + testEntityManager.clear(); + AccountEntity found = accountRepository.findById(account.getId()).orElseThrow(); + Assertions.assertNotNull(found.getId()); + Assertions.assertEquals(1, found.getRepos().size()); } } From 771159612ac15b42e5d39a0e2bf4e28bf1678f87 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 16:16:36 +0400 Subject: [PATCH 33/42] test(persistence): implement robust test for Account-Repo persistence --- .../cleat/persistence/AccountRepositoryTest.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index bb36867..7797a49 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -37,15 +37,24 @@ static void props(DynamicPropertyRegistry registry) { AccountRepository accountRepository; @Test - void shouldSaveAccountWithRepo() { - AccountEntity account = new AccountEntity(); - RepoEntity repo = new RepoEntity(); + void shouldSaveAccountWithRepos() { + AccountEntity account = new AccountEntity() + .setLogin("test-user") + .setName("Test User") + .setType("USER") + .setPlan("FREE"); + + RepoEntity repo = + new RepoEntity().setName("test-repo").setVisibility("PUBLIC").setAccount(account); + account.setRepos(List.of(repo)); repo.setAccount(account); accountRepository.saveAndFlush(account); testEntityManager.clear(); AccountEntity found = accountRepository.findById(account.getId()).orElseThrow(); + Assertions.assertNotNull(found.getId()); Assertions.assertEquals(1, found.getRepos().size()); + Assertions.assertEquals("test-repo", found.getRepos().getFirst().getName()); } } From 8595d5b228afd0968d50eff809e47d0b0c944e8b Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 16:24:16 +0400 Subject: [PATCH 34/42] fix(persistence): align RepoEntity column names with schema --- .../db/migration/V1__create_account_and_repo_tables.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index 928290c..2bb1039 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -31,7 +31,7 @@ CREATE TABLE repo( archived BOOLEAN DEFAULT FALSE, open_vulns FLOAT DEFAULT 0.0, open_secrets FLOAT DEFAULT 0.0, - open_code_alert INT DEFAULT 0, + open_code_alerts INT DEFAULT 0, stale_branches INT DEFAULT 0, open_prs INT DEFAULT 0, hygiene_score FLOAT DEFAULT 0.0, From 452fd667148a976509408aabe35a99ea11028704 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 16:39:57 +0400 Subject: [PATCH 35/42] fix(persistence): resolve column name typo in RepoEntity to match schema --- .../dev/cleat/persistence/AccountEntity.java | 8 ++-- .../dev/cleat/persistence/RepoEntity.java | 39 ++++++++++++++++++- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 4a8ef17..0f57692 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -22,16 +22,16 @@ public class AccountEntity { @GeneratedValue(strategy = GenerationType.UUID) private UUID id; - @Column(nullable = false) + @Column(name = "login", nullable = false) private String login; - @Column(nullable = false) + @Column(name = "name", nullable = false) private String name; - @Column(nullable = false) + @Column(name = "type", nullable = false) private String type; - @Column(nullable = false) + @Column(name = "plan", nullable = false) private String plan; @Column(name = "repo_count") diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index da38f03..c026910 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -21,33 +21,68 @@ public class RepoEntity { @GeneratedValue(strategy = GenerationType.UUID) private UUID id; - @Column(nullable = false) + @Column(name = "name", nullable = false) private String name; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "account_id", nullable = false) private AccountEntity account; - @Column(nullable = false) + @Column(name = "visibility", nullable = false) private String visibility; + @Column(name = "language") private String language; + + @Column(name = "stars") private Integer stars = 0; + + @Column(name = "default_branch") private String defaultBranch; + + @Column(name = "branch_protected") private Boolean branchProtected = false; + + @Column(name = "has_readme") private Boolean hasReadme = false; + + @Column(name = "has_license") private Boolean hasLicense = false; + + @Column(name = "has_contributing") private Boolean hasContributing = false; + + @Column(name = "has_codeowners") private Boolean hasCodeowners = false; + + @Column(name = "has_ci") private Boolean hasCi = false; + + @Column(name = "size_mb") private Double sizeMb = 0.0; + + @Column(name = "last_pushed_at") private OffsetDateTime lastPushedAt; + + @Column(name = "archived") private Boolean archived = false; + + @Column(name = "open_vulns") private Double openVulns = 0.0; + + @Column(name = "open_secrets") private Double openSecrets = 0.0; + + @Column(name = "open_code_alerts") private Integer openCodeAlerts = 0; + + @Column(name = "stale_branches") private Integer staleBranches = 0; + + @Column(name = "open_prs") private Integer openPRs = 0; + + @Column(name = "hygiene_score") private Double hygieneScore = 0.0; @CreationTimestamp From 72212a80339a6636bec9efd542d2991d1a825ca3 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 16:53:12 +0400 Subject: [PATCH 36/42] refactor(persistence): revert hardcoded spring boot version to use BOM_COORDINATES --- backend/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/build.gradle.kts b/backend/build.gradle.kts index 0844c90..9cacf33 100644 --- a/backend/build.gradle.kts +++ b/backend/build.gradle.kts @@ -1,5 +1,5 @@ import com.diffplug.gradle.spotless.SpotlessExtension -import org.gradle.api.plugins.quality.CheckstyleExtension +import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { java @@ -31,7 +31,7 @@ subprojects { the().apply { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.3") + mavenBom(SpringBootPlugin.BOM_COORDINATES) } } From 3bfc522429cb69353c34cb340493ad807154df97 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 21:39:44 +0400 Subject: [PATCH 37/42] chore(persistence): update entity types and database schemas --- .../dev/cleat/persistence/AccountEntity.java | 30 +++---- .../dev/cleat/persistence/AccountType.java | 6 ++ .../main/java/dev/cleat/persistence/Plan.java | 7 ++ .../dev/cleat/persistence/RepoEntity.java | 52 ++++++------- .../dev/cleat/persistence/Visibility.java | 7 ++ .../V1__create_account_and_repo_tables.sql | 78 ++++++++++--------- .../persistence/AccountRepositoryTest.java | 12 +-- 7 files changed, 107 insertions(+), 85 deletions(-) create mode 100644 backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java create mode 100644 backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java create mode 100644 backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 0f57692..3bdd7b3 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -3,6 +3,8 @@ import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; @@ -29,10 +31,12 @@ public class AccountEntity { private String name; @Column(name = "type", nullable = false) - private String type; + @Enumerated(EnumType.STRING) + private AccountType type; - @Column(name = "plan", nullable = false) - private String plan; + @Column(name = "plan") + @Enumerated(EnumType.STRING) + private Plan plan; @Column(name = "repo_count") private Integer repoCount = 0; @@ -41,7 +45,7 @@ public class AccountEntity { private Integer memberCount = 0; @Column(name = "posture_score") - private Double postureScore = 0.0; + private Integer postureScore = 0; @Column(name = "monthly_spend") private Double monthlySpend = 0.0; @@ -60,11 +64,11 @@ public AccountEntity( UUID id, String login, String name, - String type, - String plan, + AccountType type, + Plan plan, Integer repoCount, Integer memberCount, - Double postureScore, + Integer postureScore, Double monthlySpend, Double reclaimable, OffsetDateTime createdAt, @@ -112,20 +116,20 @@ public AccountEntity setName(String name) { return this; } - public String getType() { + public AccountType getType() { return type; } - public AccountEntity setType(String type) { + public AccountEntity setType(AccountType type) { this.type = type; return this; } - public String getPlan() { + public Plan getPlan() { return plan; } - public AccountEntity setPlan(String plan) { + public AccountEntity setPlan(Plan plan) { this.plan = plan; return this; } @@ -148,11 +152,11 @@ public AccountEntity setMemberCount(Integer memberCount) { return this; } - public Double getPostureScore() { + public Integer getPostureScore() { return postureScore; } - public AccountEntity setPostureScore(Double postureScore) { + public AccountEntity setPostureScore(Integer postureScore) { this.postureScore = postureScore; return this; } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java new file mode 100644 index 0000000..d792f6a --- /dev/null +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java @@ -0,0 +1,6 @@ +package dev.cleat.persistence; + +public enum AccountType { + USER, + ORG +} diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java new file mode 100644 index 0000000..efcd285 --- /dev/null +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java @@ -0,0 +1,7 @@ +package dev.cleat.persistence; + +public enum Plan { + FREE, + TEAM, + ENTERPRISE +} diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index c026910..ebb7bfd 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -28,62 +28,62 @@ public class RepoEntity { @JoinColumn(name = "account_id", nullable = false) private AccountEntity account; - @Column(name = "visibility", nullable = false) - private String visibility; + @Column(name = "visibility") + private Visibility visibility; @Column(name = "language") private String language; @Column(name = "stars") - private Integer stars = 0; + private Integer stars; @Column(name = "default_branch") private String defaultBranch; @Column(name = "branch_protected") - private Boolean branchProtected = false; + private Boolean branchProtected; @Column(name = "has_readme") - private Boolean hasReadme = false; + private Boolean hasReadme; @Column(name = "has_license") - private Boolean hasLicense = false; + private Boolean hasLicense; @Column(name = "has_contributing") - private Boolean hasContributing = false; + private Boolean hasContributing; @Column(name = "has_codeowners") - private Boolean hasCodeowners = false; + private Boolean hasCodeowners; @Column(name = "has_ci") - private Boolean hasCi = false; + private Boolean hasCi; @Column(name = "size_mb") - private Double sizeMb = 0.0; + private Double sizeMb; @Column(name = "last_pushed_at") private OffsetDateTime lastPushedAt; @Column(name = "archived") - private Boolean archived = false; + private Boolean archived; @Column(name = "open_vulns") - private Double openVulns = 0.0; + private Integer openVulns; @Column(name = "open_secrets") - private Double openSecrets = 0.0; + private Integer openSecrets; @Column(name = "open_code_alerts") - private Integer openCodeAlerts = 0; + private Integer openCodeAlerts; @Column(name = "stale_branches") - private Integer staleBranches = 0; + private Integer staleBranches; @Column(name = "open_prs") - private Integer openPRs = 0; + private Integer openPRs; @Column(name = "hygiene_score") - private Double hygieneScore = 0.0; + private Double hygieneScore; @CreationTimestamp @Column(name = "created_at", nullable = false, updatable = false) @@ -93,7 +93,7 @@ public RepoEntity( UUID id, String name, AccountEntity account, - String visibility, + Visibility visibility, String language, Integer stars, String defaultBranch, @@ -106,8 +106,8 @@ public RepoEntity( Double sizeMb, OffsetDateTime lastPushedAt, Boolean archived, - Double openVulns, - Double openSecrets, + Integer openVulns, + Integer openSecrets, Integer openCodeAlerts, Integer staleBranches, Integer openPRs, @@ -167,11 +167,11 @@ public RepoEntity setAccount(AccountEntity account) { return this; } - public String getVisibility() { + public Visibility getVisibility() { return visibility; } - public RepoEntity setVisibility(String visibility) { + public RepoEntity setVisibility(Visibility visibility) { this.visibility = visibility; return this; } @@ -284,20 +284,20 @@ public RepoEntity setArchived(Boolean archived) { return this; } - public Double getOpenVulns() { + public Integer getOpenVulns() { return openVulns; } - public RepoEntity setOpenVulns(Double openVulns) { + public RepoEntity setOpenVulns(Integer openVulns) { this.openVulns = openVulns; return this; } - public Double getOpenSecrets() { + public Integer getOpenSecrets() { return openSecrets; } - public RepoEntity setOpenSecrets(Double openSecrets) { + public RepoEntity setOpenSecrets(Integer openSecrets) { this.openSecrets = openSecrets; return this; } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java new file mode 100644 index 0000000..d5920b6 --- /dev/null +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java @@ -0,0 +1,7 @@ +package dev.cleat.persistence; + +public enum Visibility { + PUBLIC, + PRIVATE, + INTERNAL +} diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index 2bb1039..8844941 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -1,44 +1,46 @@ CREATE TABLE account ( - id UUID PRIMARY KEY, - login VARCHAR(255) NOT NULL, - name VARCHAR(255) NOT NULL, - type VARCHAR(50) NOT NULL, - plan VARCHAR(50) NOT NULL, - repo_count INT DEFAULT 0, - member_count INT DEFAULT 0, - posture_score FLOAT DEFAULT 0.0, - monthly_spend FLOAT DEFAULT 0.0, - reclaimable FLOAT DEFAULT 0.0, - created_at TIMESTAMP WITH TIME ZONE NOT NULL + id UUID PRIMARY KEY, + login VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(50) NOT NULL, + plan VARCHAR(50), + repo_count INTEGER DEFAULT 0, + member_count INTEGER DEFAULT 0, + posture_score INTEGER DEFAULT 0, + monthly_spend DOUBLE PRECISION DEFAULT 0.0, + reclaimable DOUBLE PRECISION DEFAULT 0.0, + created_at TIMESTAMP WITH TIME ZONE NOT NULL ); -CREATE TABLE repo( - id UUID PRIMARY KEY, - account_id UUID NOT NULL, - name VARCHAR(255) NOT NULL, - visibility VARCHAR(50) NOT NULL, - language VARCHAR(100), - stars int DEFAULT 0, - default_branch VARCHAR(255), - branch_protected BOOLEAN DEFAULT FALSE, - has_readme BOOLEAN DEFAULT FALSE, - has_license BOOLEAN DEFAULT FALSE, - has_contributing BOOLEAN DEFAULT FALSE, - has_codeowners BOOLEAN DEFAULT FALSE, - has_ci BOOLEAN DEFAULT FALSE, - size_mb FLOAT DEFAULT 0.0, - last_pushed_at TIMESTAMP WITH TIME ZONE, - archived BOOLEAN DEFAULT FALSE, - open_vulns FLOAT DEFAULT 0.0, - open_secrets FLOAT DEFAULT 0.0, - open_code_alerts INT DEFAULT 0, - stale_branches INT DEFAULT 0, - open_prs INT DEFAULT 0, - hygiene_score FLOAT DEFAULT 0.0, - created_at TIMESTAMP WITH TIME ZONE NOT NULL , - CONSTRAINT fk_repo_account - FOREIGN KEY (account_id) - REFERENCES account(id) +CREATE TABLE repo ( + id UUID PRIMARY KEY, + name VARCHAR(255) NOT NULL, + account_id UUID NOT NULL, + visibility VARCHAR(50), + language VARCHAR(100), + stars INTEGER, + default_branch VARCHAR(255), + branch_protected BOOLEAN, + has_readme BOOLEAN, + has_license BOOLEAN, + has_contributing BOOLEAN, + has_codeowners BOOLEAN, + has_ci BOOLEAN, + size_mb DOUBLE PRECISION, + last_pushed_at TIMESTAMP WITH TIME ZONE, + archived BOOLEAN, + open_vulns INTEGER, + open_secrets INTEGER, + open_code_alerts INTEGER, + stale_branches INTEGER, + open_prs INTEGER, + hygiene_score DOUBLE PRECISION, + created_at TIMESTAMP WITH TIME ZONE NOT NULL, + + CONSTRAINT fk_account + FOREIGN KEY(account_id) + REFERENCES account(id) + ON DELETE CASCADE ); CREATE INDEX idx_repo_account_id ON repo(account_id); diff --git a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java index 7797a49..2cf33ca 100644 --- a/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java +++ b/backend/libs/persistence/src/test/java/dev/cleat/persistence/AccountRepositoryTest.java @@ -38,14 +38,10 @@ static void props(DynamicPropertyRegistry registry) { @Test void shouldSaveAccountWithRepos() { - AccountEntity account = new AccountEntity() - .setLogin("test-user") - .setName("Test User") - .setType("USER") - .setPlan("FREE"); - - RepoEntity repo = - new RepoEntity().setName("test-repo").setVisibility("PUBLIC").setAccount(account); + AccountEntity account = + new AccountEntity().setLogin("test-user").setName("Test User").setType(AccountType.USER); + + RepoEntity repo = new RepoEntity().setName("test-repo").setAccount(account); account.setRepos(List.of(repo)); repo.setAccount(account); From 3b080168bb40771d9adede70adf821560812686f Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Fri, 12 Jun 2026 23:36:29 +0400 Subject: [PATCH 38/42] feat(persistence): implement Enums with @JsonValue for correct JSON serialization --- .../dev/cleat/persistence/AccountType.java | 16 ++++++++++++++-- .../main/java/dev/cleat/persistence/Plan.java | 18 +++++++++++++++--- .../java/dev/cleat/persistence/Visibility.java | 18 +++++++++++++++--- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java index d792f6a..9d462b7 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java @@ -1,6 +1,18 @@ package dev.cleat.persistence; +import com.fasterxml.jackson.annotation.JsonValue; + public enum AccountType { - USER, - ORG + USER("user"), + ORG("org"); + private final String value; + + AccountType(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java index efcd285..e070080 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java @@ -1,7 +1,19 @@ package dev.cleat.persistence; +import com.fasterxml.jackson.annotation.JsonValue; + public enum Plan { - FREE, - TEAM, - ENTERPRISE + FREE("Free"), + TEAM("Team"), + ENTERPRISE("Enterprise"); + private final String value; + + Plan(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java index d5920b6..1b7499e 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java @@ -1,7 +1,19 @@ package dev.cleat.persistence; +import com.fasterxml.jackson.annotation.JsonValue; + public enum Visibility { - PUBLIC, - PRIVATE, - INTERNAL + PUBLIC("public"), + PRIVATE("private"), + INTERNAL("internal"); + private final String value; + + Visibility(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } } From c9b9732ca27816e618aaca45ed92053d5b8ee1f6 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Sat, 13 Jun 2026 12:32:29 +0400 Subject: [PATCH 39/42] chore(persistence): fix enum mapping,restore ddl-validate,and cleanup api config --- .../api/src/main/resources/application.yml | 9 ++- .../java/dev/cleat/api/CleatApiTests.java | 7 -- .../dev/cleat/persistence/AccountType.java | 16 +---- .../main/java/dev/cleat/persistence/Plan.java | 17 +---- .../dev/cleat/persistence/RepoEntity.java | 3 + .../dev/cleat/persistence/Visibility.java | 18 +---- .../V1__create_account_and_repo_tables.sql | 70 +++++++++---------- .../src/test/resources/application.yml | 3 + 8 files changed, 54 insertions(+), 89 deletions(-) diff --git a/backend/apps/api/src/main/resources/application.yml b/backend/apps/api/src/main/resources/application.yml index 2396031..6bde21e 100644 --- a/backend/apps/api/src/main/resources/application.yml +++ b/backend/apps/api/src/main/resources/application.yml @@ -1,6 +1,13 @@ spring: application: name: cleat-api + autoconfigure: + exclude: + # Temporary: database is not wired yet. + # Remove these excludes once datasource is configured in issue #5. + - org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration + - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration + - org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration server: port: 8080 @@ -15,5 +22,3 @@ management: enabled: true redis: enabled: false - db: - enabled: true \ No newline at end of file diff --git a/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java b/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java index 74f3070..aa02220 100644 --- a/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java +++ b/backend/apps/api/src/test/java/dev/cleat/api/CleatApiTests.java @@ -1,16 +1,9 @@ package dev.cleat.api; import org.junit.jupiter.api.Test; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest -@EnableAutoConfiguration( - exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class, FlywayAutoConfiguration.class - }) public class CleatApiTests { @Test diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java index 9d462b7..d792f6a 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountType.java @@ -1,18 +1,6 @@ package dev.cleat.persistence; -import com.fasterxml.jackson.annotation.JsonValue; - public enum AccountType { - USER("user"), - ORG("org"); - private final String value; - - AccountType(String value) { - this.value = value; - } - - @JsonValue - public String getValue() { - return value; - } + USER, + ORG } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java index e070080..752828f 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Plan.java @@ -1,19 +1,6 @@ package dev.cleat.persistence; -import com.fasterxml.jackson.annotation.JsonValue; - public enum Plan { - FREE("Free"), - TEAM("Team"), - ENTERPRISE("Enterprise"); - private final String value; - - Plan(String value) { - this.value = value; - } - - @JsonValue - public String getValue() { - return value; - } + FREE, + TEAM } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index ebb7bfd..cb93599 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -2,6 +2,8 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -29,6 +31,7 @@ public class RepoEntity { private AccountEntity account; @Column(name = "visibility") + @Enumerated(EnumType.STRING) private Visibility visibility; @Column(name = "language") diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java index 1b7499e..d5920b6 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/Visibility.java @@ -1,19 +1,7 @@ package dev.cleat.persistence; -import com.fasterxml.jackson.annotation.JsonValue; - public enum Visibility { - PUBLIC("public"), - PRIVATE("private"), - INTERNAL("internal"); - private final String value; - - Visibility(String value) { - this.value = value; - } - - @JsonValue - public String getValue() { - return value; - } + PUBLIC, + PRIVATE, + INTERNAL } diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index 8844941..8810520 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -1,48 +1,46 @@ CREATE TABLE account ( - id UUID PRIMARY KEY, - login VARCHAR(255) NOT NULL, - name VARCHAR(255) NOT NULL, - type VARCHAR(50) NOT NULL, - plan VARCHAR(50), - repo_count INTEGER DEFAULT 0, - member_count INTEGER DEFAULT 0, - posture_score INTEGER DEFAULT 0, - monthly_spend DOUBLE PRECISION DEFAULT 0.0, - reclaimable DOUBLE PRECISION DEFAULT 0.0, - created_at TIMESTAMP WITH TIME ZONE NOT NULL + id UUID PRIMARY KEY, + login VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + type VARCHAR(50) NOT NULL, + plan VARCHAR(50), + repo_count INTEGER DEFAULT 0, + member_count INTEGER DEFAULT 0, + posture_score INTEGER DEFAULT 0, + monthly_spend DOUBLE PRECISION DEFAULT 0.0, + reclaimable DOUBLE PRECISION DEFAULT 0.0, + created_at TIMESTAMP WITH TIME ZONE NOT NULL ); CREATE TABLE repo ( - id UUID PRIMARY KEY, - name VARCHAR(255) NOT NULL, - account_id UUID NOT NULL, - visibility VARCHAR(50), - language VARCHAR(100), - stars INTEGER, - default_branch VARCHAR(255), + id UUID PRIMARY KEY, + name VARCHAR(255) NOT NULL, + account_id UUID NOT NULL, + visibility VARCHAR(50), + language VARCHAR(100), + stars INTEGER, + default_branch VARCHAR(255), branch_protected BOOLEAN, - has_readme BOOLEAN, - has_license BOOLEAN, + has_readme BOOLEAN, + has_license BOOLEAN, has_contributing BOOLEAN, - has_codeowners BOOLEAN, - has_ci BOOLEAN, - size_mb DOUBLE PRECISION, - last_pushed_at TIMESTAMP WITH TIME ZONE, - archived BOOLEAN, - open_vulns INTEGER, - open_secrets INTEGER, + has_codeowners BOOLEAN, + has_ci BOOLEAN, + size_mb DOUBLE PRECISION, + last_pushed_at TIMESTAMP WITH TIME ZONE, + archived BOOLEAN, + open_vulns INTEGER, + open_secrets INTEGER, open_code_alerts INTEGER, - stale_branches INTEGER, - open_prs INTEGER, - hygiene_score DOUBLE PRECISION, - created_at TIMESTAMP WITH TIME ZONE NOT NULL, + stale_branches INTEGER, + open_prs INTEGER, + hygiene_score DOUBLE PRECISION, + created_at TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT fk_account - FOREIGN KEY(account_id) - REFERENCES account(id) - ON DELETE CASCADE + FOREIGN KEY (account_id) + REFERENCES account(id) + ON DELETE CASCADE ); CREATE INDEX idx_repo_account_id ON repo(account_id); - - diff --git a/backend/libs/persistence/src/test/resources/application.yml b/backend/libs/persistence/src/test/resources/application.yml index 46fff37..f9f0212 100644 --- a/backend/libs/persistence/src/test/resources/application.yml +++ b/backend/libs/persistence/src/test/resources/application.yml @@ -1,3 +1,6 @@ spring: flyway: enabled: true + jpa: + hibernate: + ddl-auto: validate From 76dc4617fe8bcaf290226da93f13461fdbc9aaa6 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Sat, 13 Jun 2026 13:36:35 +0400 Subject: [PATCH 40/42] refactor(persistence): update data types for account and repo entities --- .../dev/cleat/persistence/AccountEntity.java | 23 ++++++++++--------- .../dev/cleat/persistence/RepoEntity.java | 8 +++---- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java index 3bdd7b3..33cb645 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/AccountEntity.java @@ -10,6 +10,7 @@ import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import java.math.BigDecimal; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.List; @@ -39,19 +40,19 @@ public class AccountEntity { private Plan plan; @Column(name = "repo_count") - private Integer repoCount = 0; + private Integer repoCount; @Column(name = "member_count") - private Integer memberCount = 0; + private Integer memberCount; @Column(name = "posture_score") - private Integer postureScore = 0; + private Integer postureScore; @Column(name = "monthly_spend") - private Double monthlySpend = 0.0; + private BigDecimal monthlySpend; @Column(name = "reclaimable") - private Double reclaimable = 0.0; + private BigDecimal reclaimable; @CreationTimestamp @Column(name = "created_at", nullable = false, updatable = false) @@ -69,8 +70,8 @@ public AccountEntity( Integer repoCount, Integer memberCount, Integer postureScore, - Double monthlySpend, - Double reclaimable, + BigDecimal monthlySpend, + BigDecimal reclaimable, OffsetDateTime createdAt, List repos) { this.id = id; @@ -161,20 +162,20 @@ public AccountEntity setPostureScore(Integer postureScore) { return this; } - public Double getMonthlySpend() { + public BigDecimal getMonthlySpend() { return monthlySpend; } - public AccountEntity setMonthlySpend(Double monthlySpend) { + public AccountEntity setMonthlySpend(BigDecimal monthlySpend) { this.monthlySpend = monthlySpend; return this; } - public Double getReclaimable() { + public BigDecimal getReclaimable() { return reclaimable; } - public AccountEntity setReclaimable(Double reclaimable) { + public AccountEntity setReclaimable(BigDecimal reclaimable) { this.reclaimable = reclaimable; return this; } diff --git a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java index cb93599..1cebae4 100644 --- a/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java +++ b/backend/libs/persistence/src/main/java/dev/cleat/persistence/RepoEntity.java @@ -86,7 +86,7 @@ public class RepoEntity { private Integer openPRs; @Column(name = "hygiene_score") - private Double hygieneScore; + private Integer hygieneScore; @CreationTimestamp @Column(name = "created_at", nullable = false, updatable = false) @@ -114,7 +114,7 @@ public RepoEntity( Integer openCodeAlerts, Integer staleBranches, Integer openPRs, - Double hygieneScore, + Integer hygieneScore, OffsetDateTime createdAt) { this.id = id; this.name = name; @@ -332,11 +332,11 @@ public RepoEntity setOpenPRs(Integer openPRs) { return this; } - public Double getHygieneScore() { + public Integer getHygieneScore() { return hygieneScore; } - public RepoEntity setHygieneScore(Double hygieneScore) { + public RepoEntity setHygieneScore(Integer hygieneScore) { this.hygieneScore = hygieneScore; return this; } From c86845767fc7797c457241044961172f0a6ef69a Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Sat, 13 Jun 2026 13:46:21 +0400 Subject: [PATCH 41/42] refactor(flyway): update data types in migration scripts for consistency --- .../V1__create_account_and_repo_tables.sql | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index 8810520..eb4d6ca 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -7,35 +7,35 @@ CREATE TABLE account ( repo_count INTEGER DEFAULT 0, member_count INTEGER DEFAULT 0, posture_score INTEGER DEFAULT 0, - monthly_spend DOUBLE PRECISION DEFAULT 0.0, - reclaimable DOUBLE PRECISION DEFAULT 0.0, + monthly_spend DECIMAL(19,4) DEFAULT 0.0, + reclaimable DECIMAL(19,4) PRECISION DEFAULT 0.0, created_at TIMESTAMP WITH TIME ZONE NOT NULL ); CREATE TABLE repo ( - id UUID PRIMARY KEY, - name VARCHAR(255) NOT NULL, - account_id UUID NOT NULL, - visibility VARCHAR(50), - language VARCHAR(100), - stars INTEGER, - default_branch VARCHAR(255), + id UUID PRIMARY KEY, + name VARCHAR(255) NOT NULL, + account_id UUID NOT NULL, + visibility VARCHAR(50), + language VARCHAR(100), + stars INTEGER, + default_branch VARCHAR(255), branch_protected BOOLEAN, - has_readme BOOLEAN, - has_license BOOLEAN, + has_readme BOOLEAN, + has_license BOOLEAN, has_contributing BOOLEAN, - has_codeowners BOOLEAN, - has_ci BOOLEAN, - size_mb DOUBLE PRECISION, - last_pushed_at TIMESTAMP WITH TIME ZONE, - archived BOOLEAN, - open_vulns INTEGER, - open_secrets INTEGER, + has_codeowners BOOLEAN, + has_ci BOOLEAN, + size_mb DOUBLE PRECISION, + last_pushed_at TIMESTAMP WITH TIME ZONE, + archived BOOLEAN, + open_vulns INTEGER, + open_secrets INTEGER, open_code_alerts INTEGER, - stale_branches INTEGER, - open_prs INTEGER, - hygiene_score DOUBLE PRECISION, - created_at TIMESTAMP WITH TIME ZONE NOT NULL, + stale_branches INTEGER, + open_prs INTEGER, + hygiene_score INTEGER, + created_at TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT fk_account FOREIGN KEY (account_id) From 1e7624811796a1d83bd9b954e9f237d0650573e2 Mon Sep 17 00:00:00 2001 From: arzunusretova12-debug Date: Sat, 13 Jun 2026 13:51:41 +0400 Subject: [PATCH 42/42] fix(flyway): resolve SQL syntax error in migration --- .../db/migration/V1__create_account_and_repo_tables.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql index eb4d6ca..9c7ccd8 100644 --- a/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql +++ b/backend/libs/persistence/src/main/resources/db/migration/V1__create_account_and_repo_tables.sql @@ -8,7 +8,7 @@ CREATE TABLE account ( member_count INTEGER DEFAULT 0, posture_score INTEGER DEFAULT 0, monthly_spend DECIMAL(19,4) DEFAULT 0.0, - reclaimable DECIMAL(19,4) PRECISION DEFAULT 0.0, + reclaimable DECIMAL(19,4) DEFAULT 0.0, created_at TIMESTAMP WITH TIME ZONE NOT NULL );