Conversation
add Gradle test workflow
add local development runtime setup
add initial database migration
Claude/Codex 개발 환경 설정 추가
There was a problem hiding this comment.
Code Review
This pull request sets up the local development environment, GitHub Actions CI/CD templates, and autonomous agent/skill definitions for a Spring Boot backend utilizing PostgreSQL/PostGIS and Redis. The reviewer provided valuable feedback pointing out critical issues: MySQL-specific syntax in the database schema guidelines that contradicts the PostgreSQL 16 stack, a missing Redis container in the integration tests which would cause CI failures, potential Spring Boot component scanning issues due to the documented package structure in AGENTS.md, and several leftover references to a template project name (anchor) alongside branch naming inconsistencies.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| ```sql | ||
| id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, | ||
| created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), | ||
| updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) |
There was a problem hiding this comment.
The SQL example uses MySQL-specific syntax (DATETIME(6) and ON UPDATE CURRENT_TIMESTAMP(6)). Since the project tech stack explicitly uses PostgreSQL 16, this syntax will cause Flyway migrations to fail with syntax errors. In PostgreSQL, use TIMESTAMP or TIMESTAMPTZ for date-time columns, and handle automatic updates on modification using triggers or application-level auditing (such as Hibernate's @UpdateTimestamp or Spring Data's @LastModifiedDate).
| user_id BIGINT NOT NULL, | ||
| key_value VARCHAR(64) NOT NULL, | ||
| created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), | ||
| updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), |
There was a problem hiding this comment.
The SQL example uses MySQL-specific syntax (DATETIME(6) and ON UPDATE CURRENT_TIMESTAMP(6)). Since the project tech stack explicitly uses PostgreSQL 16, this syntax will cause Flyway migrations to fail with syntax errors. In PostgreSQL, use TIMESTAMP or TIMESTAMPTZ for date-time columns, and handle automatic updates on modification using triggers or application-level auditing (such as Hibernate's @UpdateTimestamp or Spring Data's @LastModifiedDate).
| ```sql | ||
| id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, | ||
| created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), | ||
| updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) |
There was a problem hiding this comment.
The SQL example uses MySQL-specific syntax (DATETIME(6) and ON UPDATE CURRENT_TIMESTAMP(6)). Since the project tech stack explicitly uses PostgreSQL 16, this syntax will cause Flyway migrations to fail with syntax errors. In PostgreSQL, use TIMESTAMP or TIMESTAMPTZ for date-time columns, and handle automatic updates on modification using triggers or application-level auditing (such as Hibernate's @UpdateTimestamp or Spring Data's @LastModifiedDate).
| user_id BIGINT NOT NULL, | ||
| key_value VARCHAR(64) NOT NULL, | ||
| created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), | ||
| updated_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), |
There was a problem hiding this comment.
The SQL example uses MySQL-specific syntax (DATETIME(6) and ON UPDATE CURRENT_TIMESTAMP(6)). Since the project tech stack explicitly uses PostgreSQL 16, this syntax will cause Flyway migrations to fail with syntax errors. In PostgreSQL, use TIMESTAMP or TIMESTAMPTZ for date-time columns, and handle automatic updates on modification using triggers or application-level auditing (such as Hibernate's @UpdateTimestamp or Spring Data's @LastModifiedDate).
| companion object { | ||
| private val postgisImage = DockerImageName | ||
| .parse("postgis/postgis:16-3.5-alpine") | ||
| .asCompatibleSubstituteFor("postgres") | ||
|
|
||
| @Container | ||
| @ServiceConnection | ||
| @JvmStatic | ||
| val postgres = PostgreSQLContainer<Nothing>("postgres:16-alpine") | ||
| val postgres = PostgisContainer(postgisImage) | ||
| .withInitScript("db/init/001_enable_postgis.sql") | ||
| } |
There was a problem hiding this comment.
The application context depends on Redis (spring-boot-starter-data-redis is on the classpath and configured in application.yaml), but MuddaApplicationTests only configures a PostgreSQL/PostGIS container. In environments where Redis is not running locally (such as CI pipelines), the context load test will fail. Since com.redis:testcontainers-redis is already in the test dependencies, you should spin up a Redis container alongside the PostgreSQL container using @Container and @ServiceConnection.
companion object {
private val postgisImage = DockerImageName
.parse("postgis/postgis:16-3.5-alpine")
.asCompatibleSubstituteFor("postgres")
@Container
@ServiceConnection
@JvmStatic
val postgres = PostgisContainer(postgisImage)
.withInitScript("db/init/001_enable_postgis.sql")
@Container
@ServiceConnection
@JvmStatic
val redis = com.redis.testcontainers.RedisContainer(DockerImageName.parse("redis:7.4-alpine"))
}| ## Package Structure | ||
|
|
||
| ``` | ||
| domain | ||
| ├── {domainName} # e.g. capsule, unlock, social, security, notification, storage | ||
| │ ├── presentation | ||
| │ │ ├── request | ||
| │ │ ├── response | ||
| │ │ └── controller | ||
| │ ├── application | ||
| │ │ └── impl | ||
| │ ├── domain | ||
| │ │ ├── entity | ||
| │ │ ├── type | ||
| │ │ └── repository | ||
| │ └── infrastructure | ||
| │ | ||
| global | ||
| ├── common | ||
| ├── config | ||
| ├── security | ||
| ├── exception | ||
| ├── response | ||
| ├── annotation | ||
| ├── util | ||
| └── property | ||
| ``` |
There was a problem hiding this comment.
The package structure defined in AGENTS.md lists domain and global as top-level directories. If an autonomous agent follows this literally and creates src/main/kotlin/domain and src/main/kotlin/global outside the root package team.cklob.mudda, Spring Boot's component scanning will fail to detect any of the beans (controllers, services, repositories) because they reside outside the @SpringBootApplication package hierarchy. Please clarify in the documentation that these packages must reside under the root package team.cklob.mudda (i.e., src/main/kotlin/team/cklob/mudda/domain and src/main/kotlin/team/cklob/mudda/global).
| ./gradlew check | ||
|
|
||
| # Run a specific test class | ||
| ./gradlew test --tests "anchor.capsule.*" |
There was a problem hiding this comment.
There is a reference to anchor in the test execution command (anchor.capsule.*) which appears to be a leftover from a template or previous project name. Since the actual project name is mudda and the root package is team.cklob.mudda, this reference should be updated to team.cklob.mudda.domain.capsule.* (or similar) to maintain consistency and prevent errors when running tests.
| ./gradlew test --tests "anchor.capsule.*" | |
| ./gradlew test --tests "team.cklob.mudda.domain.capsule.*" |
References
- Unify project name references across all documentation files (such as
CLAUDE.mdandAGENTS.md) to match the actual GitHub repository or organization name to maintain consistency.
| - **Trigger**: PR open / push (all branches) | ||
| - **Steps**: `lint + compile (ktlint, Gradle)` -> `unit test (JUnit5, MockK)` -> `integration test (Testcontainers)` | ||
| - All three steps (`needs: [lint, unit, integration]`) must pass before proceeding. | ||
| - **Docker build + GHCR push**: pushes the image as `ghcr.io/.../anchor:$SHA`. This step runs **only on the develop/main branches**; regular PR branches stop after lint/test. |
There was a problem hiding this comment.
There is a reference to anchor in the Docker image name (ghcr.io/.../anchor:$SHA) which appears to be a leftover from a template or previous project name. Since the actual project name is mudda, this reference should be updated to ghcr.io/.../mudda:$SHA to maintain consistency.
| - **Docker build + GHCR push**: pushes the image as `ghcr.io/.../anchor:$SHA`. This step runs **only on the develop/main branches**; regular PR branches stop after lint/test. | |
| - **Docker build + GHCR push**: pushes the image as ghcr.io/.../mudda:$SHA. This step runs **only on the develop/main branches**; regular PR branches stop after lint/test. |
References
- Unify project name references across all documentation files (such as
CLAUDE.mdandAGENTS.md) to match the actual GitHub repository or organization name to maintain consistency.
|
|
||
| - Example: `feat: #12 :: add capsule creation api`, `fix: #34 :: fix geofence radius calculation bug` | ||
| - Omit `#<issue-number> ::` entirely only for trivial changes with no tracking issue. | ||
| - Branch naming: `<type>/<issue-number>-<kebab-case-description>`, e.g. `feature/12-capsule-creation`, `fix/34-geofence-radius-bug`. |
There was a problem hiding this comment.
The branch naming convention example uses feature/12-capsule-creation, but the allowed commit types list feat (not feature). This is inconsistent with .agents/skills/git-commit/SKILL.md which specifies <type>/<issue-number>-<kebab-case-description> (e.g., feat/12-capsule-creation). Please update the example to feat/12-capsule-creation to align with the actual conventions.
| - Branch naming: `<type>/<issue-number>-<kebab-case-description>`, e.g. `feature/12-capsule-creation`, `fix/34-geofence-radius-bug`. | |
| - Branch naming: <type>/<issue-number>-<kebab-case-description>, e.g. feat/12-capsule-creation, fix/34-geofence-radius-bug. |
References
- Ensure all Git and commit convention documentation (such as
AGENTS.mdandCLAUDE.md) is fully aligned with the actual commit message formats and branch naming conventions enforced by the project's automated tools.
No description provided.