-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feat] 초기 세팅 작업 완료 #14
Conversation
* chore: TestContainers 의존성 추가 * chore: Testcontainers MySQL 데이터소스 및 Hibernate 설정 추가 * chore: MySQL Testcontainer 설정 추가 * test: 테스트 환경용 @activeprofiles("test") 추가 * test: 테스트 전용 SpringApplication 구성 및 TestcontainersConfig 추가 * chore: test 환경 ddl-auto 수정 * chore: EOL 추가
* chore: Spring Security 의존성 추가 * chore: Spring Security 설정 init * chore: Spring Security 설정 수정 불필요한 swagger 설정 제거 및 default filter 위치 수정 * chore: private 메서드 코드 컨벤션 적용 * chore: HealthCheck 라우터 추가 * chore: 불필요한 swagger security 제거
* feat: resource 환경변수 .env 활용 & DB RDS MySQL Datasource JPA & Docker 컨테이너화 및 로컬 빌드 테스트용 compose 파일 생성 * feat: Dev 이미지 빌드 및 ECR 업로드 후, EC2 자동 배포 GitAction 플로우 생성 * test: GitAction 배포 테스트 * feat: Devlopment 자동배포 workflow 테스트 완료 * fix: EOL (맨 밑 개행) 추가안된 파일 수정
* chore: Swagger 의존성 추가 * chore: Swagger 설정 init * feat: 현재 Spring Profile을 반환하는 유틸리티 * feat: 환경 상수 정의 추가 * feat: URL 상수 정의 추가 * chore: 환경별 Swagger 설정 * feat: 헬스 체크 API 문서화 적용 * feat: 헬스 체크 API 추가 * refac: 첫줄 공백 추가 (컨벤션) * chore: private 메서드 코드 컨벤션 적용 및 EOL 추가 * chore: 프로필 상태 util 클래스명 변경 SpringEnvironmentUtil -> ProfileResolver * chore: JWT Authorization Bearer 추가 * refac: EnvironmentConstants enum 제거
* feat: 전역적 예외 및 핸들러 추가 * refactor: 500 서버 에러 코드 추가 * feat: 에러 응답에 code 필드를 포함하도록 변경 * feat: ErrorResponse 필드 보완 및 유효성 검사 실패 에러 응답 추가 * feat: 공통 성공 응답 클래스 정의 * refactor: 예외 및 성공 응답 반환 공통 로직 추출 * feat: 서버 에러 응답 구체화 * feat: 성공 응답시 다양한 status 응답할 수 있도록 변경 * feat: 유효성 예외 발생 시 상태코드 400 반환 * feat: 유효하지 않은 API 경로 예외 핸들러 추가
* chore: Testcontainers의 JDBC URL 인식 설정 * refac: test 환경 변수 추가 * test: 테스트 통합 환경 구축 * test: Health Check 통합 테스트 추가 * refac: EOL 해결 * chore: datasource 관련 설정들을 모두 제거 TestcontainersConfig 파일 기준의 이미지로 Test 환경을 구축을 위함 * chore: amd64 호환성 경고 해결 * chore: application dev 파일 수정 * chore: dialect 중복 제거 * fix: test시 swagger config 오류 해결 * chore: IntegrationTest와 ControllerTest 분리 IntegrationTest -> RestAssured ControllerTest -> MockMVC * test: HealthCheck IntegrationTest, ControllerTest * refac: EOL 해결
* feat: 로컬 환경에서 Private RDS 터널링 셋업 * chore: 불필요한 annotation 제거 및 변수명 수정
* refactor: 프로젝트명 변경 및 코드 스타일 통일 * docs: README 프로젝트명 변경 * refactor: 불필요한 설정 필드 제거 * refactor: 머지된 클래스에 대해 프로젝트명 변경 * refactor: 불필요한 설정 필드 제거
* test: ci gitaction workflow * test: use v4 artifact * feat: gitaction 자동 CI flow 구현 * feat: CODEOWNERS 추가
WalkthroughThis pull request introduces several new files and configuration changes across the repository. It adds GitHub workflows for development deployment and CI testing, updates build and deployment scripts (including Docker, Gradle, and Docker Compose), and establishes the main Spring Boot entry point with supporting configurations for security, SSH tunneling, Swagger, error handling, and health checks. It also provides dedicated configuration files for different environments and a comprehensive suite of test classes and configurations for integration, controller, repository, and mock testing. Changes
Sequence Diagram(s)sequenceDiagram
participant Dev as Developer
participant Repo as GitHub Repo
participant Build as Build Job
participant Deploy as Deploy Job
participant EC2 as EC2 Instance
Dev->>Repo: Push changes to 'develop'
Repo->>Build: Trigger cd.develop.yml workflow
Build->>Repo: Checkout code, build Docker image, push to ECR
Build->>Deploy: Signal build completion
Deploy->>EC2: SSH deploy - stop old container, pull & run new container
EC2-->>Deploy: Container updated
Deploy-->>Repo: Workflow completes
sequenceDiagram
participant Client as Client
participant App as Application
participant HC as HealthController
participant GR as GlobalResponseHandler
Client->>App: GET /api/health
App->>HC: Invoke healthCheck()
HC->>GR: Pass response for status handling
GR-->>App: Adjust response status
App-->>Client: Return 200 OK "ok"
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 18
🧹 Nitpick comments (32)
src/main/java/com/evenly/took/global/exception/ErrorCode.java (1)
5-10
: LGTM! Consider adding interface documentation.The interface is well-designed with clear method contracts. Consider adding Javadoc to document the interface's purpose and method contracts.
package com.evenly.took.global.exception; import org.springframework.http.HttpStatus; +/** + * Interface for defining error codes with associated HTTP status and message. + */ public interface ErrorCode { + /** + * @return the HTTP status associated with this error code + */ HttpStatus getStatus(); + /** + * @return the error message associated with this error code + */ String getMessage(); }src/main/java/com/evenly/took/global/exception/TookException.java (1)
8-11
: Add serialVersionUID for serializable exception class.Since exceptions are serializable by default, it's recommended to add a serialVersionUID to maintain serialization compatibility across different versions.
@Getter @AllArgsConstructor public class TookException extends RuntimeException { + private static final long serialVersionUID = 1L; private final ErrorCode errorCode; }
src/test/java/com/evenly/took/TookApplicationTests.java (1)
9-14
: Consider adding basic smoke tests.While the contextLoads test verifies Spring context loading, consider adding basic smoke tests to verify critical beans and configurations.
@SpringBootTest @ActiveProfiles("test") class TookApplicationTests { @Test void contextLoads() { } + + @Test + void smokeTest(@Autowired ApplicationContext context) { + assertThat(context).isNotNull(); + assertThat(context.getEnvironment().getActiveProfiles()) + .contains("test"); + } }src/test/java/com/evenly/took/TestTookApplication.java (1)
7-11
: Add class documentation for test application entry point.Consider adding documentation to explain the purpose of this test application class and its relationship with Testcontainers.
+/** + * Test application entry point that includes Testcontainers configuration. + * This class enables running the application with test containers for integration testing. + */ public class TestTookApplication { + /** + * Main method that starts the application with test container configuration. + * @param args command line arguments + */ public static void main(String[] args) { SpringApplication.from(TookApplication::main).with(TestcontainersConfig.class).run(args); }src/main/java/com/evenly/took/global/health/HealthController.java (1)
11-14
: Consider enhancing the health check response.The current implementation returns a simple "ok" string. Consider returning a more detailed health status that includes:
- Application version
- System metrics (memory, CPU usage)
- Database connectivity status
- External service dependencies status
This would provide better insights into the application's health.
Example enhancement:
- public String healthCheck() { - return "ok"; + public HealthStatus healthCheck() { + return HealthStatus.builder() + .status("UP") + .version(applicationVersion) + .timestamp(Instant.now()) + .details(Map.of( + "database", checkDatabaseHealth(), + "memory", getMemoryMetrics() + )) + .build();src/test/java/com/evenly/took/global/health/HealthControllerIntegrationTest.java (1)
11-19
: Enhance test coverage and follow naming conventions.
- The test method name uses Korean. Consider using English for consistency across the codebase.
- The test only verifies the status code. Consider also validating the response body.
Apply this diff:
- void Health_Check_통합_테스트_성공() { + void healthCheck_ShouldReturnOkResponse() { given().log().all() .when() .get("/api/health") .then() .log().all() - .statusCode(200); + .statusCode(200) + .body(equalTo("ok"));src/main/java/com/evenly/took/global/common/constants/EnvironmentConstants.java (1)
8-16
: Consider using an enum for environment types.Using an enum would provide better type safety, validation, and additional functionality like checking if an environment is production or development.
Example enhancement:
-@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class EnvironmentConstants { - public static final String PROD_ENV = "prod"; - public static final String DEV_ENV = "dev"; - public static final String LOCAL_ENV = "local"; - public static final String TEST_ENV = "test"; - public static final List<String> PROD_AND_DEV_ENV = List.of(PROD_ENV, DEV_ENV); +public enum Environment { + PROD("prod"), + DEV("dev"), + LOCAL("local"), + TEST("test"); + + private final String value; + + Environment(String value) { + this.value = value; + } + + public String getValue() { + return value; + } + + public boolean isProduction() { + return this == PROD; + } + + public boolean isDevelopment() { + return this == DEV; + } + + public static List<Environment> getProdAndDevEnv() { + return List.of(PROD, DEV); + } }src/main/java/com/evenly/took/global/exception/CommonErrorCode.java (1)
12-14
: Consider adding more common error codes.The current set of error codes is minimal. Consider adding more common scenarios such as:
UNAUTHORIZED
(401)FORBIDDEN
(403)NOT_FOUND
(404)METHOD_NOT_ALLOWED
(405)CONFLICT
(409)public enum CommonErrorCode implements ErrorCode { INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "서버 관리자에게 문의하세요."), INVALID_REQUEST_VALUE(HttpStatus.BAD_REQUEST, "유효하지 않은 요청값입니다."), INVALID_REQUEST_URL(HttpStatus.BAD_REQUEST, "유효하지 않은 경로입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "인증이 필요합니다."), + FORBIDDEN(HttpStatus.FORBIDDEN, "접근 권한이 없습니다."), + NOT_FOUND(HttpStatus.NOT_FOUND, "리소스를 찾을 수 없습니다."), + METHOD_NOT_ALLOWED(HttpStatus.METHOD_NOT_ALLOWED, "지원하지 않는 HTTP 메소드입니다."), + CONFLICT(HttpStatus.CONFLICT, "리소스가 이미 존재합니다."), ;src/main/java/com/evenly/took/global/health/HealthApi.java (1)
12-16
: Consider enhancing the health check response.The current health check returns a simple "ok" string. Consider returning more detailed health information such as:
- Application version
- Database connectivity status
- Memory usage
- System uptime
@Operation(summary = "헬스 체크 API 입니다.") @ApiResponse(responseCode = "200", description = "서버의 상태 정보를 응답합니다.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = HealthResponse.class))) HealthResponse healthCheck(); @Schema(description = "Health check response") record HealthResponse( @Schema(example = "UP") String status, @Schema(example = "1.0.0") String version, @Schema(example = "true") boolean dbConnected, @Schema(example = "85%") String memoryUsage, @Schema(example = "PT24H") Duration uptime ) {}src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java (1)
18-22
: Consider using UTC for timestamp.The current implementation uses system default timezone. Consider using UTC for consistency across different deployment environments.
- this.timestamp = LocalDateTime.now(); + this.timestamp = LocalDateTime.now(Clock.systemUTC());Don't forget to add the import:
import java.time.Clock;src/test/java/com/evenly/took/global/config/TestcontainersConfig.java (1)
12-19
: Consider updating MySQL version and externalizing test configuration.
- The MySQL version (8.0.26) is relatively old. Consider using a more recent version.
- Test database configuration could be externalized to properties file.
- return new MySQLContainer<>(DockerImageName.parse("mysql/mysql-server:8.0.26")) + return new MySQLContainer<>(DockerImageName.parse("mysql/mysql-server:8.0.36")) .withDatabaseName("testdb") .withUsername("test") .withPassword("test");Create
src/test/resources/application-test.yml
:test: database: name: testdb username: test password: test version: 8.0.36Then update the configuration to use these properties:
@Value("${test.database.name}") private String databaseName; @Value("${test.database.username}") private String username; @Value("${test.database.password}") private String password; @Value("${test.database.version}") private String version; @Bean @ServiceConnection MySQLContainer<?> mysqlContainer() { return new MySQLContainer<>(DockerImageName.parse("mysql/mysql-server:" + version)) .withDatabaseName(databaseName) .withUsername(username) .withPassword(password); }src/test/java/com/evenly/took/global/repository/RepositoryTest.java (2)
12-16
: Consider using in-memory database for faster test execution.The current configuration uses the actual database for tests, which could slow down test execution. Consider using an in-memory database like H2 for faster test execution, unless there are specific database features that need to be tested.
Apply this diff to use an in-memory database:
-@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) +@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
12-17
: Add transaction management configuration.Consider adding
@Transactional
annotation to ensure proper transaction management in tests.Add the following import and annotation:
+import org.springframework.transaction.annotation.Transactional; @DataJpaTest @ExtendWith(SpringExtension.class) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) @ActiveProfiles(TEST_ENV) @Ignore +@Transactional public abstract class RepositoryTest {src/test/java/com/evenly/took/global/health/HealthControllerTest.java (2)
14-23
: Enhance test coverage with additional test cases.The current test only verifies the success case. Consider adding:
- Negative test cases
- Response body verification
Add the following test methods:
@Test void healthCheck_ShouldReturnSuccessResponse() throws Exception { // given, when ResultActions resultActions = requestHealthCheck(); // then resultActions .andExpect(status().isOk()) .andExpect(jsonPath("$.status").value("OK")) .andExpect(jsonPath("$.message").exists()) .andExpect(jsonPath("$.timestamp").exists()); } @Test void healthCheck_WhenServerError_ShouldReturn500() throws Exception { // given when(healthService.check()).thenThrow(new RuntimeException("Service unavailable")); // when ResultActions resultActions = requestHealthCheck(); // then resultActions .andExpect(status().isInternalServerError()) .andExpect(jsonPath("$.error").exists()); }
15-15
: Consider using English for test method names.For consistency and better IDE support, consider using English for test method names.
Apply this diff:
-void Health_Check_Controller_테스트_성공() throws Exception { +void healthCheck_ShouldReturnOkStatus() throws Exception {src/main/java/com/evenly/took/global/response/SuccessResponse.java (2)
15-16
: Consider internationalization for messages.The default message is hardcoded in Korean. Consider using message source for internationalization support.
Apply this diff to support i18n:
+import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; @Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public class SuccessResponse { private static final HttpStatus DEFAULT_HTTP_STATUS = HttpStatus.OK; - private static final String DEFAULT_MESSAGE = "요청이 성공적으로 처리되었습니다."; + private static final String DEFAULT_MESSAGE_KEY = "response.success.default"; + + @Autowired + private static MessageSource messageSource; + + private static String getDefaultMessage() { + return messageSource.getMessage( + DEFAULT_MESSAGE_KEY, + null, + LocaleContextHolder.getLocale() + ); + }
23-29
: Add data validation and timezone handling.Consider adding null checks for data and using a specific timezone for timestamp.
Apply this diff:
+import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Objects; public static SuccessResponse of(Object data) { + Objects.requireNonNull(data, "Response data cannot be null"); return new SuccessResponse( DEFAULT_HTTP_STATUS, - DEFAULT_MESSAGE, - LocalDateTime.now(), + getDefaultMessage(), + ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime(), data); } public static SuccessResponse of(HttpStatus status, Object data) { + Objects.requireNonNull(status, "HTTP status cannot be null"); + Objects.requireNonNull(data, "Response data cannot be null"); return new SuccessResponse( status, - DEFAULT_MESSAGE, - LocalDateTime.now(), + getDefaultMessage(), + ZonedDateTime.now(ZoneId.of("Asia/Seoul")).toLocalDateTime(), data); }src/test/java/com/evenly/took/global/controller/ControllerTest.java (1)
23-30
: Add class-level documentation.This abstract class serves as a base for controller tests. Consider adding Javadoc to explain its purpose and usage for other developers.
+/** + * Base class for controller tests providing common test infrastructure. + * Configures MockMvc and ObjectMapper for use in subclasses. + * + * Usage: + * <pre> + * class YourControllerTest extends ControllerTest { + * @Test + * void testEndpoint() { + * mvc.perform(get("/your-endpoint")) + * .andExpect(status().isOk()); + * } + * } + * </pre> + */ public abstract class ControllerTest {src/main/java/com/evenly/took/global/util/ProfileResolver.java (1)
19-24
: Consider caching the current profile.The
getCurrentProfile()
method performs stream operations on each call. Since profiles rarely change during runtime, consider caching the result.+private String cachedProfile; + public String getCurrentProfile() { + if (cachedProfile == null) { + cachedProfile = resolveCurrentProfile(); + } + return cachedProfile; +} + +private String resolveCurrentProfile() { return getActiveProfiles() .filter(profile -> profile.equals(PROD_ENV) || profile.equals(DEV_ENV)) .findFirst() .orElse(LOCAL_ENV); }src/test/java/com/evenly/took/global/integration/IntegrationTest.java (1)
32-36
: Enhance RestAssured setup with additional configurations.The current RestAssured setup is basic. Consider adding more robust configuration.
@BeforeEach public void setUp() { RestAssured.baseURI = "http://localhost"; RestAssured.port = port; + RestAssured.enableLoggingOfRequestAndResponseIfValidationFails(); + RestAssured.useRelaxedHTTPSValidation(); + RestAssured.config = RestAssured.config() + .objectMapperConfig(new ObjectMapperConfig() + .jackson2ObjectMapperFactory((type, s) -> objectMapper)); }src/main/java/com/evenly/took/global/exception/dto/ValidationErrorResponse.java (1)
30-37
: Consider adding JSON serialization control.The
FieldErrorDetail
record could benefit from JSON serialization annotations for better control over the API response format.+@JsonPropertyOrder({"field", "message", "value"}) private record FieldErrorDetail( + @JsonProperty("field") String field, + @JsonProperty("message") String message, + @JsonProperty("value") + @JsonInclude(JsonInclude.Include.NON_NULL) Object value) {src/main/java/com/evenly/took/global/config/security/WebSecurityConfig.java (1)
26-31
: Consider restricting Swagger UI access in productionThe Swagger endpoints are completely open. While this is fine for development, consider restricting access in production.
Consider environment-specific security:
-http.securityMatcher("/swagger-ui/**", "/v3/api-docs/**") +http.securityMatcher("/swagger-ui/**", "/v3/api-docs/**") + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/swagger-ui/**", "/v3/api-docs/**") + .access(new WebExpressionAuthorizationManager( + "hasIpAddress('localhost') or hasRole('ADMIN')")));src/main/java/com/evenly/took/global/config/swagger/SwaggerConfig.java (2)
77-82
: Complete the TODO for production and development URLsThe server URL configuration has commented-out cases for production and development environments.
Would you like me to help implement the production and development URL configurations? This could include:
- Environment-specific URL constants
- Configuration properties for URLs
- URL validation logic
33-34
: Consider using semantic versioning formatThe version is injected via
@Value
but there's no validation of the version format.Add version format validation:
@PostConstruct private void validateVersion() { if (!version.matches("^\\d+\\.\\d+\\.\\d+$")) { throw new IllegalStateException("Version must follow semantic versioning format (x.y.z)"); } }Dockerfile (1)
1-5
: Build Stage Optimization Suggestion.The build stage setup is correctly implemented. As an enhancement, consider adding a clean-up command after installing packages (e.g., removing the apt cache) to reduce the final image size:
RUN apt-get update && apt-get install -y curl unzip +RUN rm -rf /var/lib/apt/lists/*
.github/workflows/ci.yml (3)
6-6
: Remove Trailing Whitespace.A trailing whitespace was detected on line 6. Removing this will help maintain clean YAML formatting.
🧰 Tools
🪛 YAMLlint (1.35.1)
[error] 6-6: trailing spaces
(trailing-spaces)
15-15
: Update Checkout Action Version.The workflow uses
actions/checkout@v3
, which a static analysis hint flagged as outdated. Consider upgrading to a newer version if available to benefit from improved features and fixes.🧰 Tools
🪛 actionlint (1.7.4)
15-15: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
17-19
: Update JDK Setup Action Version.Similarly, the
actions/setup-java@v3
action might be outdated as indicated by static analysis. An upgrade to the latest stable release is recommended to ensure compatibility and stability during CI runs.🧰 Tools
🪛 actionlint (1.7.4)
18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
src/main/resources/application-local.yml (1)
1-49
: Local Environment and SSH Tunnel Configuration
This configuration file adequately sets up the local environment, including database connectivity, JPA settings, Swagger configuration, and SSH tunneling parameters. One point to consider is the datasource URL at line 7:url: jdbc:mysql://127.0.0.1:[forwardedPort]/${DB_DATABASE}?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=true
The literal
[forwardedPort]
might be better replaced with an environment variable (e.g.,${FORWARDED_PORT}
) or a configurable property. This change would enhance flexibility and reduce the risk of having an unintentional hardcoded value.build.gradle (1)
1-55
: Build Script Review and Dependency Cleanup
The newbuild.gradle
file is well-structured and includes essential plugins, Java toolchain configuration, and dependencies for your Spring Boot project. A couple of observations:
- Duplicate Dependency: The MySQL connector dependency appears twice (once at line 36 and again at line 44). It is recommended to remove the duplicate to avoid any potential resolution conflicts or confusion.
- SSH Tunneling Dependency: The inclusion of the JSch library supports SSH tunneling configuration. Ensure that version
0.2.17
meets your security and compatibility requirements.A suggested diff to remove the duplication in the dependency block is:
- runtimeOnly 'com.mysql:mysql-connector-j' … - // DB - runtimeOnly 'com/h2database:h2' - runtimeOnly 'com/mysql:mysql-connector-j' + // DB + runtimeOnly 'com.h2database:h2'Overall, the build script aligns well with the project setup for Spring Boot and integration testing using Testcontainers.
.github/workflows/cd.develop.yml (2)
36-37
: Pin the SSH Action VersionThe deployment job uses
appleboy/ssh-action@master
. For stability and to avoid unexpected changes, consider pinning to a specific release version (for example,@v0.1.7
or the latest stable version).- uses: appleboy/ssh-action@master + uses: appleboy/[email protected]
42-47
: Enhance Deployment Script RobustnessIt is advisable to add error handling within the deployment script. Inserting
set -e
ensures that the script halts on errors, and using|| true
afterdocker stop
anddocker rm
prevents failures if the container isn’t running or already removed.- script: | - sudo docker stop dev-app - sudo docker rm dev-app - sudo docker image prune -a -f - sudo docker pull public.ecr.aws/${{ secrets.AWS_ACCOUNT_ID }}/${{ secrets.DEV_ECR_REPO }}:latest - sudo docker run --name dev-app --env-file .env -d -p 8080:8080 -t public.ecr.aws/${{ secrets.AWS_ACCOUNT_ID }}/${{ secrets.DEV_ECR_REPO }}:latest + script: | + set -e + sudo docker stop dev-app || true + sudo docker rm dev-app || true + sudo docker image prune -a -f + sudo docker pull public.ecr.aws/${{ secrets.AWS_ACCOUNT_ID }}/${{ secrets.DEV_ECR_REPO }}:latest + sudo docker run --name dev-app --env-file .env -d -p 8080:8080 -t public.ecr.aws/${{ secrets.AWS_ACCOUNT_ID }}/${{ secrets.DEV_ECR_REPO }}:latest
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
gradle/wrapper/gradle-wrapper.jar
is excluded by!**/*.jar
📒 Files selected for processing (44)
.github/CODEOWNERS
(1 hunks).github/workflows/cd.develop.yml
(1 hunks).github/workflows/ci.yml
(1 hunks).gitignore
(1 hunks)Dockerfile
(1 hunks)README.md
(1 hunks)build.gradle
(1 hunks)docker-compose.yml
(1 hunks)gradle/wrapper/gradle-wrapper.properties
(1 hunks)gradlew
(1 hunks)gradlew.bat
(1 hunks)settings.gradle
(1 hunks)src/main/java/com/evenly/took/TookApplication.java
(1 hunks)src/main/java/com/evenly/took/global/common/constants/EnvironmentConstants.java
(1 hunks)src/main/java/com/evenly/took/global/common/constants/UrlConstants.java
(1 hunks)src/main/java/com/evenly/took/global/config/datasource/SshDataSourceConfig.java
(1 hunks)src/main/java/com/evenly/took/global/config/security/WebSecurityConfig.java
(1 hunks)src/main/java/com/evenly/took/global/config/ssh/SshTunnelingInitializer.java
(1 hunks)src/main/java/com/evenly/took/global/config/swagger/SwaggerConfig.java
(1 hunks)src/main/java/com/evenly/took/global/exception/CommonErrorCode.java
(1 hunks)src/main/java/com/evenly/took/global/exception/ErrorCode.java
(1 hunks)src/main/java/com/evenly/took/global/exception/GlobalExceptionHandler.java
(1 hunks)src/main/java/com/evenly/took/global/exception/TookException.java
(1 hunks)src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java
(1 hunks)src/main/java/com/evenly/took/global/exception/dto/ServerErrorResponse.java
(1 hunks)src/main/java/com/evenly/took/global/exception/dto/ValidationErrorResponse.java
(1 hunks)src/main/java/com/evenly/took/global/health/HealthApi.java
(1 hunks)src/main/java/com/evenly/took/global/health/HealthController.java
(1 hunks)src/main/java/com/evenly/took/global/response/GlobalResponseHandler.java
(1 hunks)src/main/java/com/evenly/took/global/response/SuccessResponse.java
(1 hunks)src/main/java/com/evenly/took/global/util/ProfileResolver.java
(1 hunks)src/main/resources/application-dev.yml
(1 hunks)src/main/resources/application-local.yml
(1 hunks)src/main/resources/application-prod.yml
(1 hunks)src/test/java/com/evenly/took/TestTookApplication.java
(1 hunks)src/test/java/com/evenly/took/TookApplicationTests.java
(1 hunks)src/test/java/com/evenly/took/global/config/TestcontainersConfig.java
(1 hunks)src/test/java/com/evenly/took/global/controller/ControllerTest.java
(1 hunks)src/test/java/com/evenly/took/global/health/HealthControllerIntegrationTest.java
(1 hunks)src/test/java/com/evenly/took/global/health/HealthControllerTest.java
(1 hunks)src/test/java/com/evenly/took/global/integration/IntegrationTest.java
(1 hunks)src/test/java/com/evenly/took/global/repository/RepositoryTest.java
(1 hunks)src/test/java/com/evenly/took/global/service/MockTest.java
(1 hunks)src/test/resources/application-test.yml
(1 hunks)
✅ Files skipped from review due to trivial changes (4)
- settings.gradle
- README.md
- .github/CODEOWNERS
- src/main/java/com/evenly/took/TookApplication.java
🧰 Additional context used
🪛 actionlint (1.7.4)
.github/workflows/cd.develop.yml
14-14: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
17-17: the runner of "aws-actions/configure-aws-credentials@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
.github/workflows/ci.yml
15-15: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🪛 YAMLlint (1.35.1)
.github/workflows/ci.yml
[error] 6-6: trailing spaces
(trailing-spaces)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: test
🔇 Additional comments (17)
src/main/java/com/evenly/took/global/common/constants/UrlConstants.java (1)
6-8
: LGTM! Good use of Lombok and enum for constants.The class structure follows best practices by:
- Using an enum to ensure type safety for URL constants
- Leveraging Lombok to reduce boilerplate code
src/main/java/com/evenly/took/global/health/HealthController.java (1)
1-9
: LGTM! Controller setup looks good.The controller is properly configured with appropriate annotations and implements the
HealthApi
interface.src/main/java/com/evenly/took/global/exception/CommonErrorCode.java (1)
8-10
: LGTM! Well-structured error code enum.The class is well-designed with appropriate Lombok annotations and implements the
ErrorCode
interface.src/main/java/com/evenly/took/global/health/HealthApi.java (1)
9-10
: LGTM! Well-documented API interface.The interface is properly tagged for OpenAPI documentation.
src/main/java/com/evenly/took/global/exception/dto/ErrorResponse.java (1)
11-16
: LGTM! Well-structured error response DTO.The class is well-designed with immutable fields and appropriate use of Lombok.
src/test/java/com/evenly/took/global/config/TestcontainersConfig.java (1)
9-10
: LGTM! Well-structured test configuration.The configuration class is properly annotated and follows Spring Boot test conventions.
gradlew.bat (1)
1-94
: LGTM! Standard Gradle wrapper batch scriptThe Windows Gradle wrapper script is correctly configured with proper error handling and environment checks.
gradlew (1)
1-252
: LGTM! Standard Gradle wrapper shell scriptThe POSIX-compliant Gradle wrapper script is properly configured with comprehensive error handling and environment detection.
docker-compose.yml (1)
1-11
: Service Definition Verification fordep_application
.The new service definition is clear and includes the necessary keys such as
build
,container_name
,env_file
, andports
. Please ensure that the referenced.env
file exists at the root of your project, and verify that port8080
is not conflicting with any other services during local testing.gradle/wrapper/gradle-wrapper.properties (1)
1-7
: Gradle Wrapper Configuration Updates.The modifications correctly define the wrapper properties for a consistent Gradle setup. These additions ensure that Gradle distributions are stored in a predictable location with proper caching and network timeout settings. Confirm that the specified Gradle version (8.11.1) meets your project requirements.
Dockerfile (1)
9-15
: Deployment Stage Validation.The deployment stage correctly copies over the built JAR file and sets the container’s entrypoint. Verify that the wildcard pattern (
*.jar
) reliably selects the intended artifact—if the build might produce multiple JAR files, consider specifying the exact filename to avoid ambiguity.src/test/resources/application-test.yml (1)
1-21
: Test Environment Configuration Review.The
application-test.yml
file is well structured for a test environment. It properly configures the application name, JPA settings (with a temporary DB schema viacreate-drop
), and detailed SQL logging. Confirm that these settings are used only in tests sinceddl-auto: create-drop
and verbose SQL logging are not advised for production environments..github/workflows/ci.yml (1)
14-41
: CI Workflow Structure Review.The CI workflow is structured properly—it checks out the code, sets up JDK 17, creates a
.env
file from a secret, grants execute permission togradlew
, runs tests, and uploads test results. Ensure that the secretCI_ENV_FILE
is managed securely and that all file paths and environment variables are correctly configured. Overall, the workflow meets the initial setup objectives.🧰 Tools
🪛 actionlint (1.7.4)
15-15: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
18-18: the runner of "actions/setup-java@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
.gitignore (1)
73-75
: SSH Key Ignore Rule Added
The addition of a rule to ignore*.pem
files is an important step in preventing sensitive SSH key files from being accidentally committed to the repository. This change enhances security by ensuring private keys used for SSH tunneling are not tracked.src/main/resources/application-dev.yml (1)
1-39
: Development Configuration for Dev Profile
This new configuration file for thedev
profile is well-organized. It sets up the datasource using environment variables and specifies Hibernate and Swagger properties consistent with a development environment. Please verify that theuseSSL=true
setting is appropriate for your development environment, as it may sometimes be omitted in favor of simpler setups.src/main/resources/application-prod.yml (1)
1-39
: Production Configuration Setup
The production configuration is clearly delineated with profile activation and environment-specific settings. Disabling SQL logging (show_sql: false
) and SQL comments is appropriate in production for performance and security reasons. Ensure that all environment variables (e.g.,DB_HOST
,DB_PORT
) are correctly set in your production environment for a smooth deployment..github/workflows/cd.develop.yml (1)
23-30
: Validate Docker Image Push CommandsThe commands for logging into AWS ECR Public and pushing the Docker image are clear and correctly utilize secrets for credentials. No issues were found with this segment.
LOCAL_SERVER_URL("http://localhost:8080"), | ||
; | ||
|
||
private final String value; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider moving URL to configuration properties.
Hardcoding URLs directly in the code reduces flexibility and makes environment-specific configurations harder to manage. Consider:
- Moving the URL to
application.yml
or environment-specific properties files - Using Spring's
@Value
or@ConfigurationProperties
to inject the URL
Example approach:
@Value("${app.url}")
private String serverUrl;
With corresponding configuration in application-local.yml
:
app:
url: http://localhost:8080
This allows for easier configuration management across different environments (local, dev, prod).
import org.junit.Ignore; | ||
import org.junit.jupiter.api.extension.ExtendWith; | ||
import org.mockito.junit.jupiter.MockitoExtension; | ||
import org.springframework.test.context.ActiveProfiles; | ||
|
||
@ExtendWith(MockitoExtension.class) | ||
@ActiveProfiles(TEST_ENV) | ||
@Ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace deprecated JUnit 4 @Ignore
with JUnit 5 @Disabled
.
The class uses JUnit 5 (org.junit.jupiter
) but includes a JUnit 4 annotation. Replace @Ignore
with the JUnit 5 equivalent.
Apply this diff:
-import org.junit.Ignore;
+import org.junit.jupiter.api.Disabled;
@ExtendWith(MockitoExtension.class)
@ActiveProfiles(TEST_ENV)
-@Ignore
+@Disabled
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import org.junit.Ignore; | |
import org.junit.jupiter.api.extension.ExtendWith; | |
import org.mockito.junit.jupiter.MockitoExtension; | |
import org.springframework.test.context.ActiveProfiles; | |
@ExtendWith(MockitoExtension.class) | |
@ActiveProfiles(TEST_ENV) | |
@Ignore | |
import org.junit.jupiter.api.Disabled; | |
import org.junit.jupiter.api.extension.ExtendWith; | |
import org.mockito.junit.jupiter.MockitoExtension; | |
import org.springframework.test.context.ActiveProfiles; | |
@ExtendWith(MockitoExtension.class) | |
@ActiveProfiles(TEST_ENV) | |
@Disabled |
private ErrorDetail(Exception ex) { | ||
this(ex.getClass().getSimpleName(), ex.getMessage(), ex.getStackTrace()[0].getClassName()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add null safety checks.
The constructor assumes the exception and its stack trace are non-null. Add null checks to prevent NullPointerException
.
Apply this diff to add null safety:
private ErrorDetail(Exception ex) {
- this(ex.getClass().getSimpleName(), ex.getMessage(), ex.getStackTrace()[0].getClassName());
+ this(ex != null ? ex.getClass().getSimpleName() : "Unknown",
+ ex != null ? ex.getMessage() : "No message available",
+ ex != null && ex.getStackTrace().length > 0
+ ? ex.getStackTrace()[0].getClassName()
+ : "No stack trace available");
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
private ErrorDetail(Exception ex) { | |
this(ex.getClass().getSimpleName(), ex.getMessage(), ex.getStackTrace()[0].getClassName()); | |
} | |
private ErrorDetail(Exception ex) { | |
this(ex != null ? ex.getClass().getSimpleName() : "Unknown", | |
ex != null ? ex.getMessage() : "No message available", | |
ex != null && ex.getStackTrace().length > 0 | |
? ex.getStackTrace()[0].getClassName() | |
: "No stack trace available"); | |
} |
Avoid exposing stack trace in production.
Exposing stack trace information could reveal sensitive implementation details. Consider removing or masking stack trace in production environments.
Apply this diff to make stack trace optional based on environment:
+import org.springframework.core.env.Environment;
+import org.springframework.beans.factory.annotation.Autowired;
+
private record ErrorDetail(String exception,
String message,
String stackTrace) {
+ @Autowired
+ private static Environment environment;
private ErrorDetail(Exception ex) {
- this(ex.getClass().getSimpleName(), ex.getMessage(), ex.getStackTrace()[0].getClassName());
+ this(ex.getClass().getSimpleName(),
+ ex.getMessage(),
+ shouldExposeStackTrace() ? ex.getStackTrace()[0].getClassName() : null);
}
+
+ private static boolean shouldExposeStackTrace() {
+ return environment != null &&
+ environment.acceptsProfiles("dev", "test");
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
private ErrorDetail(Exception ex) { | |
this(ex.getClass().getSimpleName(), ex.getMessage(), ex.getStackTrace()[0].getClassName()); | |
} | |
import org.springframework.core.env.Environment; | |
import org.springframework.beans.factory.annotation.Autowired; | |
private record ErrorDetail(String exception, | |
String message, | |
String stackTrace) { | |
@Autowired | |
private static Environment environment; | |
private ErrorDetail(Exception ex) { | |
this(ex.getClass().getSimpleName(), | |
ex.getMessage(), | |
shouldExposeStackTrace() ? ex.getStackTrace()[0].getClassName() : null); | |
} | |
private static boolean shouldExposeStackTrace() { | |
return environment != null && | |
environment.acceptsProfiles("dev", "test"); | |
} | |
} |
|
||
import static com.evenly.took.global.common.constants.EnvironmentConstants.*; | ||
|
||
import org.junit.Ignore; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Replace JUnit 4's @ignore with JUnit 5's @disabled.
The class uses JUnit 5 annotations but includes JUnit 4's @Ignore
. For consistency, use JUnit 5's @Disabled
annotation instead.
-import org.junit.Ignore;
+import org.junit.jupiter.api.Disabled;
-@Ignore
+@Disabled
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import org.junit.Ignore; | |
import org.junit.jupiter.api.Disabled; | |
@Disabled | |
public abstract class ControllerTest { | |
// Provides MockMvc and ObjectMapper for subclasses | |
// Other test infrastructure code remains here | |
} |
@RequiredArgsConstructor | ||
public class ProfileResolver { | ||
|
||
private final Environment environment; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add null check for environment.
The environment
field is injected by Spring but should be validated to prevent NullPointerException.
private final Environment environment;
+
+@PostConstruct
+private void validateEnvironment() {
+ if (environment == null) {
+ throw new IllegalStateException("Environment must not be null");
+ }
+}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
private final Environment environment; | |
private final Environment environment; | |
@PostConstruct | |
private void validateEnvironment() { | |
if (environment == null) { | |
throw new IllegalStateException("Environment must not be null"); | |
} | |
} |
@Value("${ssh.host}") | ||
private String sshHost; | ||
|
||
@Value("${ssh.user}") | ||
private String sshUser; | ||
|
||
@Value("${ssh.port}") | ||
private int sshPort; | ||
|
||
@Value("${ssh.private-key-path}") | ||
private String privateKey; | ||
|
||
@Value("${ssh.db-host}") | ||
private String databaseHost; | ||
|
||
@Value("${ssh.db-port}") | ||
private int databasePort; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add validation for injected values
Add validation annotations to ensure required properties are properly configured.
- @Value("${ssh.host}")
+ @Value("${ssh.host}")
+ @NotBlank(message = "SSH host cannot be blank")
private String sshHost;
- @Value("${ssh.user}")
+ @Value("${ssh.user}")
+ @NotBlank(message = "SSH user cannot be blank")
private String sshUser;
@Value("${ssh.port}")
+ @Range(min = 1, max = 65535, message = "SSH port must be between 1 and 65535")
private int sshPort;
- @Value("${ssh.private-key-path}")
+ @Value("${ssh.private-key-path}")
+ @NotBlank(message = "Private key path cannot be blank")
private String privateKey;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
@Value("${ssh.host}") | |
private String sshHost; | |
@Value("${ssh.user}") | |
private String sshUser; | |
@Value("${ssh.port}") | |
private int sshPort; | |
@Value("${ssh.private-key-path}") | |
private String privateKey; | |
@Value("${ssh.db-host}") | |
private String databaseHost; | |
@Value("${ssh.db-port}") | |
private int databasePort; | |
@Value("${ssh.host}") | |
@NotBlank(message = "SSH host cannot be blank") | |
private String sshHost; | |
@Value("${ssh.user}") | |
@NotBlank(message = "SSH user cannot be blank") | |
private String sshUser; | |
@Value("${ssh.port}") | |
@Range(min = 1, max = 65535, message = "SSH port must be between 1 and 65535") | |
private int sshPort; | |
@Value("${ssh.private-key-path}") | |
@NotBlank(message = "Private key path cannot be blank") | |
private String privateKey; | |
@Value("${ssh.db-host}") | |
private String databaseHost; | |
@Value("${ssh.db-port}") | |
private int databasePort; |
http.authorizeHttpRequests(authorize -> authorize | ||
.requestMatchers("/public/**").permitAll() | ||
.requestMatchers("/api/health").permitAll() | ||
.anyRequest().authenticated()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing JWT authentication configuration
The security configuration lacks JWT token validation despite JWT being configured in Swagger.
Add JWT authentication:
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
// In securityFilterChain:
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
// TODO: 임시 cors 설정 | ||
@Bean | ||
public CorsConfigurationSource corsConfigurationSource() { | ||
CorsConfiguration configuration = new CorsConfiguration(); | ||
configuration.addAllowedOrigin("*"); | ||
configuration.addAllowedHeader("*"); | ||
configuration.addAllowedMethod("*"); | ||
configuration.setAllowCredentials(true); | ||
|
||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||
source.registerCorsConfiguration("/**", configuration); | ||
return source; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Security Risk: Overly permissive CORS configuration
The current CORS configuration allows all origins (*
), headers, and methods while enabling credentials. This combination is not secure and browsers will block it. When allowCredentials
is true, allowedOrigins
cannot be *
.
Replace with specific allowed origins:
-configuration.addAllowedOrigin("*");
+configuration.setAllowedOrigins(List.of("http://localhost:3000", "https://your-frontend-domain.com"));
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// TODO: 임시 cors 설정 | |
@Bean | |
public CorsConfigurationSource corsConfigurationSource() { | |
CorsConfiguration configuration = new CorsConfiguration(); | |
configuration.addAllowedOrigin("*"); | |
configuration.addAllowedHeader("*"); | |
configuration.addAllowedMethod("*"); | |
configuration.setAllowCredentials(true); | |
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | |
source.registerCorsConfiguration("/**", configuration); | |
return source; | |
} | |
// TODO: 임시 cors 설정 | |
@Bean | |
public CorsConfigurationSource corsConfigurationSource() { | |
CorsConfiguration configuration = new CorsConfiguration(); | |
- configuration.addAllowedOrigin("*"); | |
+ configuration.setAllowedOrigins(List.of("http://localhost:3000", "https://your-frontend-domain.com")); | |
configuration.addAllowedHeader("*"); | |
configuration.addAllowedMethod("*"); | |
configuration.setAllowCredentials(true); | |
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | |
source.registerCorsConfiguration("/**", configuration); | |
return source; | |
} |
- name: Configure AWS credentials | ||
uses: aws-actions/configure-aws-credentials@v1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update AWS Credentials Action Version
The step configuring AWS credentials uses aws-actions/configure-aws-credentials@v1
. For enhanced support and security, please update this action to the latest version (e.g., @v2
).
- uses: aws-actions/configure-aws-credentials@v1
+ uses: aws-actions/configure-aws-credentials@v2
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
- name: Configure AWS credentials | |
uses: aws-actions/configure-aws-credentials@v1 | |
- name: Configure AWS credentials | |
uses: aws-actions/configure-aws-credentials@v2 |
🧰 Tools
🪛 actionlint (1.7.4)
17-17: the runner of "aws-actions/configure-aws-credentials@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
- name: Checkout | ||
uses: actions/checkout@v2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update Checkout Action Version
The workflow currently uses actions/checkout@v2
, which is flagged as outdated by static analysis. Upgrading to actions/checkout@v3
is recommended to leverage improvements in security and performance.
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: Checkout | |
uses: actions/checkout@v3 |
🧰 Tools
🪛 actionlint (1.7.4)
14-14: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
…into feat/2-initial-setup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/pr-size-labeler.yml (1)
17-22
: Improve PR Head Fetch and Diff Parsing Robustness
The newly added commands successfully fetch the PR's head commit into a local branch (pr-branch
) and compute the changed lines by comparing it with the base branch. However, the extraction of changed lines usingtail -n 1 | cut -d' ' -f4
could be fragile if the output format ofgit diff --stat
changes or if there are unexpected spacing variations. Consider adopting a more robust parsing method (e.g., usingawk
or regex) to handle such edge cases and ensure the script reliably extracts the line count.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드래빗 리뷰까지 확인 완!
모두모두 수고하셨습니다 드디어 develop에 첫 커밋이라니 감격
* docs: 이슈 템플릿 설정 * chore: PR 크기 자동 라벨링 workflow * [Feat] 초기 세팅 작업 완료 (#14) * feat: ✨initial setup * [Feat] test container 환경 적용 (#3) * chore: TestContainers 의존성 추가 * chore: Testcontainers MySQL 데이터소스 및 Hibernate 설정 추가 * chore: MySQL Testcontainer 설정 추가 * test: 테스트 환경용 @activeprofiles("test") 추가 * test: 테스트 전용 SpringApplication 구성 및 TestcontainersConfig 추가 * chore: test 환경 ddl-auto 수정 * chore: EOL 추가 * [Feat] security config 설정 (#6) * chore: Spring Security 의존성 추가 * chore: Spring Security 설정 init * chore: Spring Security 설정 수정 불필요한 swagger 설정 제거 및 default filter 위치 수정 * chore: private 메서드 코드 컨벤션 적용 * chore: HealthCheck 라우터 추가 * chore: 불필요한 swagger security 제거 * [Feat] DB 세팅 및 배포 플로우 자동화 기본 작업 (#5) * feat: resource 환경변수 .env 활용 & DB RDS MySQL Datasource JPA & Docker 컨테이너화 및 로컬 빌드 테스트용 compose 파일 생성 * feat: Dev 이미지 빌드 및 ECR 업로드 후, EC2 자동 배포 GitAction 플로우 생성 * test: GitAction 배포 테스트 * feat: Devlopment 자동배포 workflow 테스트 완료 * fix: EOL (맨 밑 개행) 추가안된 파일 수정 * [Feat] swagger config setup (#8) * chore: Swagger 의존성 추가 * chore: Swagger 설정 init * feat: 현재 Spring Profile을 반환하는 유틸리티 * feat: 환경 상수 정의 추가 * feat: URL 상수 정의 추가 * chore: 환경별 Swagger 설정 * feat: 헬스 체크 API 문서화 적용 * feat: 헬스 체크 API 추가 * refac: 첫줄 공백 추가 (컨벤션) * chore: private 메서드 코드 컨벤션 적용 및 EOL 추가 * chore: 프로필 상태 util 클래스명 변경 SpringEnvironmentUtil -> ProfileResolver * chore: JWT Authorization Bearer 추가 * refac: EnvironmentConstants enum 제거 * [Feat] 전역적 예외 및 핸들러 추가 (#4) * feat: 전역적 예외 및 핸들러 추가 * refactor: 500 서버 에러 코드 추가 * feat: 에러 응답에 code 필드를 포함하도록 변경 * feat: ErrorResponse 필드 보완 및 유효성 검사 실패 에러 응답 추가 * feat: 공통 성공 응답 클래스 정의 * refactor: 예외 및 성공 응답 반환 공통 로직 추출 * feat: 서버 에러 응답 구체화 * feat: 성공 응답시 다양한 status 응답할 수 있도록 변경 * feat: 유효성 예외 발생 시 상태코드 400 반환 * feat: 유효하지 않은 API 경로 예외 핸들러 추가 * [Feat] 테스트 통합 환경 구축 (#9) * chore: Testcontainers의 JDBC URL 인식 설정 * refac: test 환경 변수 추가 * test: 테스트 통합 환경 구축 * test: Health Check 통합 테스트 추가 * refac: EOL 해결 * chore: datasource 관련 설정들을 모두 제거 TestcontainersConfig 파일 기준의 이미지로 Test 환경을 구축을 위함 * chore: amd64 호환성 경고 해결 * chore: application dev 파일 수정 * chore: dialect 중복 제거 * fix: test시 swagger config 오류 해결 * chore: IntegrationTest와 ControllerTest 분리 IntegrationTest -> RestAssured ControllerTest -> MockMVC * test: HealthCheck IntegrationTest, ControllerTest * refac: EOL 해결 * [Feat] Private RDS 로컬 EC2 인스턴스 터널링 작업 (#10) * feat: 로컬 환경에서 Private RDS 터널링 셋업 * chore: 불필요한 annotation 제거 및 변수명 수정 * [Refactor] 프로젝트명 변경 (#11) * refactor: 프로젝트명 변경 및 코드 스타일 통일 * docs: README 프로젝트명 변경 * refactor: 불필요한 설정 필드 제거 * refactor: 머지된 클래스에 대해 프로젝트명 변경 * refactor: 불필요한 설정 필드 제거 * [Feat] GitAction CI workflow 구현 (#13) * test: ci gitaction workflow * test: use v4 artifact * feat: gitaction 자동 CI flow 구현 * feat: CODEOWNERS 추가 * refactor: @ignore -> @disabled junit5에서 @ignore이 deprecated 되었으므로 변경 * chore: PR 크기 라벨링 전체PR 작업 기준으로 작동하도록 변경 --------- Co-authored-by: 나경호 <[email protected]> Co-authored-by: SCY <[email protected]> * [Fix] Swagger 환경별 url 설정 수정 (#16) * fix: swagger 환경별 url 설정방법 변경 * chore: swagger 환경별 url 설정 junit5에서 @ignore이 deprecated 되었으므로 변경 * chore: 환경별 url 설정법 변경으로 인한 test 환경 설정 수정 junit5에서 @ignore이 deprecated 되었으므로 변경 * [Feat] PR 플로우 개선 작업 (#19) * chore: PR 크기 라벨링 워크플로우 수정 & 코드래빗 설정 YAML 파일 추가 * fix: EOL (맨 밑 개행) 추가안된 파일 수정 * fix: 잘못들어간 문자 제거 * [Feat] OAuth 및 JWT 인증 기능 구현 및 Composite 패턴 적용 (#20) * feat: OAuth 인가 코드 요청 기능 구현 * feat: OAuth 타입 관련 예외 처리 추가 * feat: OAuth 인증 후 사용자 정보를 조회하는 UserClient 인터페이스 및 Composite 구현 * feat: JWT 발급 및 validation 기능 추가 * feat: JWT 발급 및 validation filter * feat: OAuth 인증 처리 및 JWT 토큰 발급 service * feat: OAuth 컨트롤러 추가 - OAuth 인가 요청 URL 리다이렉트 API 추가 - OAuth 로그인 후 JWT 발급 API 추가 - API 문서화를 위한 Swagger 설정 포함 * feat: User/OAuth 관련 domain 추가 * feat: User Repository 추가 * chore: RestClient 설정 * chore: jwt 변수 properties 및 의존성 추가 * feat: jwt 예외코드 및 response dto 추가 * feat: 공통 time entity 추가 * chore: Jpa Auditing 설정 * chore: jwt properties 설정 방식 변경 * test: AuthCode Request Url Provider Composite 동작 test * test: access token 생성/validate test * test: User Client Composite 동작 Test * test: 공통 Mock User Factory 추가 * chore: oauth controller swagger 적용 및 security path 추가 * [Feat] PR 플로우 개선 작업 (#19) * chore: PR 크기 라벨링 워크플로우 수정 & 코드래빗 설정 YAML 파일 추가 * fix: EOL (맨 밑 개행) 추가안된 파일 수정 * fix: 잘못들어간 문자 제거 * feat: OAuth 인가 코드 요청 기능 구현 * feat: OAuth 타입 관련 예외 처리 추가 * feat: OAuth 인증 후 사용자 정보를 조회하는 UserClient 인터페이스 및 Composite 구현 * feat: JWT 발급 및 validation 기능 추가 * feat: JWT 발급 및 validation filter * feat: OAuth 인증 처리 및 JWT 토큰 발급 service * feat: OAuth 컨트롤러 추가 - OAuth 인가 요청 URL 리다이렉트 API 추가 - OAuth 로그인 후 JWT 발급 API 추가 - API 문서화를 위한 Swagger 설정 포함 * feat: User/OAuth 관련 domain 추가 * feat: User Repository 추가 * chore: RestClient 설정 * chore: jwt 변수 properties 및 의존성 추가 * feat: jwt 예외코드 및 response dto 추가 * feat: 공통 time entity 추가 * chore: Jpa Auditing 설정 * chore: jwt properties 설정 방식 변경 * test: AuthCode Request Url Provider Composite 동작 test * test: access token 생성/validate test * test: User Client Composite 동작 Test * test: 공통 Mock User Factory 추가 * chore: oauth controller swagger 적용 및 security path 추가 * refac: nullable=false -> @NotNull * refac: 불필요 컬럼 제거 * refac: OAuthId -> OAuthIdentifier * refac: mapp -> 불변 mapp * refac: jwt 불필요한 반환 제거 * refac: jwt accessToken 변수 추출 * refac: jwt 유효성 검증에 예외처리 추가 * test: jwt 유효성 검증 예외처리 테스트 * rename: mock -> stub으로 네이밍 변경 * refac: jwt 예외 추가 * refac: 토큰 응답 방식 변경 --------- Co-authored-by: 찬기 <[email protected]> * refac: 폴더 구조 변경 (#22) * [Feat] Redis 환경 구성 및 테스트 플로우 구축 (#23) * feat: Redis Lettuce Client 세팅 및 RedisService 구현 & Docker Compose Redis 연동 실행환경 구성 * feat: Redis TestContainer 가상 환경 테스트 환경 구성 * refac: Docker Build 시, test 결과 무시 & 로컬에서 .env 통해 개별적으로 Redis 환경 구축 * fix: Convention 적용 & 테스트 코드 형식 통일 * [Feat] refresh token으로 로그인 상태 유지 (#24) * feat: 로그인 시 refresh token 발급 및 헤더에 응답 * feat: 매 요청에서 token 검증 및 재발급 * test: OAuthService 로그인 로직 * refac: refresh token 만료 환경 변수 추출 * test: UuidTokenProvider 클래스 * fix: 인증 로직 통합 테스트하면서 잘못된 로직 수정 * refac: 인증 필터 이름 변경 * test: mock user 추출 * test: ServiceTest 추출 * refac: 패키지 구조 기존 구조랑 통일 * refac: 스웨거 문서 수정 * refac: 불필요한 생성자 제거 * refac: 레디스 데이터 초기화 메서드 테스트로 이동 * refac: 로그인 시 응답 토큰 위치 헤더 -> 바디 * refac: oauth url API 응답 형식 통일 * test: 응답 형태 변경에 따른 테스트 코드 수정 * feat: 응답 DTO 스웨거 설명 추가 * refac: 공통 응답 클래스 data 필드 타입 변경 Object -> 제네릭 * refac: refresh token 발급 방식 변경 - 기존: AT 만료 시 함께 보낸 RT로 갱신 - 수정: AT 만료 시 /refresh API를 통해 갱신 * refac: 서비스 계층의 책임 분리를 위해 TokenProvider 추가 * refac: Auth 에러 코드 통합 및 static import 제거 * refac: 커밋 7ad1105 보완 * refac: filter 에러 응답 형태 통일 * refac: 인증 도메인 용어 통일 oauth -> auth * refac: 패키지 위치 통일 - 기존: global > exception > [feature] - 개선: [feature] > exception * refac: 불필요한 커스텀 예외 제거 - 기존: 여러개의 커스텀 예외 사용 - 개선: 하나의 커스텀 예외 사용 * refac: 인증 관련 클래스 auth feature 패키지로 이동 * docs: 스웨거 문서 정리 * refac: 인증 필터에서 상황에 따른 예외 반환 * refac: login API HTTP method GET -> POST * [Feat] 카카오 로그인 구현 (#31) * chore: 각 서버 환경별 변수 보완 * refac: 토큰 프로퍼티 네이밍 수정 * feat: 카카오 인증 코드 발급 경로 제공 * feat: 요청 파라미터가 유효하지 않은 경우 400 예외 반환 * feat: 카카오 토큰 발급 및 사용자 정보 조회 * refac: 커스텀 예외 메시지 추가 * refac: client > kakao 패키지 추가 및 관련 클래스 이동 * refac: 각 카카오 외부 API 접근 클래스 책임 분리 * refac: EnableConfigurationProperties Config 클래스로 이동 * feat: 해당 요청을 수행하는 핸들러가 없을 때 400 예외 반환 * refac: 유효하지 않은 카카오 인증 코드 예외 메시지 수정 * refac: 올바른 예외를 반환하도록 수정 * refac: mock server 초기화 로직 위치 변경 * refac: response body 재사용 가능하도록 * feat: 카카오 인증 코드 유효하지 않을 경우 반환 상태 코드 변경 * refac: client > kakao 하위 패키지 통일 * chore: dev 및 prod 서버 환경변수 업데이트 * refac: 카카오 리프레시 토큰 유효기간 응답 타입 올바르게 수정 * feat: 응답 바디 형식에 따른 예외 처리 * [Feat] 구글 로그인 구현 (#27) * chore: dev, prod 환경 env 변수명 갱신 * refac: auth token properties 폴더 구조 및 네이밍 변경 * feat: 구글 인증 코드 요청 Provider * feat: 구글 유저 조회 client * feat: 구글 oauth 예외코드 추가 * chore: 구글 oauth env 설정 * chore: CORS origin url pattern 을 통한 유연성 추가 원활한 작업을 위한 임시 추가이므로 추후에 변경되어야함 * refac: Google client 에서 token 발급과 정보 조회 분리 * feat: token 발급과 정보 조회 dto 추가 * feat: 예외 handler 추가 및 예러 코드 추가 * test: google 소셜 로그인 mock test * test: 구글 provider test 공통 Mock 클래스 추가 * refac: 애매한 예외 변수명 변경 * refac: 예외 메시지를 테스트에서 검증을 위한 수정 * test: 예외 발생 시점 수정 * refac: 환경변수 properties 공통 적용 방식으로 수정 * refac: 토큰 요청 시 request dto 추가 * refac: 폴더 구조 변경 * [Feat] 애플 로그인 구현 (#33) * feat: Apple 로그인 구현 및 디버깅 완료 * feat: Apple 로그인 테스트 코드 작성 * fix: 간단한 PR 이슈 수정 * fix: ErrorHandler InputStream 객체 중복사용 제거 * fix: 테스트 코드 conflict 해결 * [Refactor] 환경변수 개선 및 프로퍼티 관련 패키지 이동 (#35) * refac: 환경별 공통으로 사용되는 환경변수 추출 * refac: 인증 피처 프로퍼티 클래스 위치 이동 * refac: `@ConfigurationPropertiesScan`으로 감지하고 있으므로 프로퍼티를 빈으로 등록하는 클래스 제거 * refac: spring.datasource.url 베이스 데이터 수정 * fix: 클래스별 restClient 분리를 위해 restClientBuilder 빈 복사 후 빌드 (#37) * [Feat] 소셜 로그인 정보 추가 (#41) * feat: 사용자 엔티티에 이메일 필드 추가 * feat: 카카오 소셜 로그인 시 사용자 이름 및 이메일 정보 가져오기 * feat: 애플 소셜 로그인 시 사용자 이름 및 이메일 정보 가져오기 * feat: 구글 소셜 로그인 시 사용자 이름 및 이메일 정보 가져오기 * [Feat] S3 서비스 구현 feat: S3 서비스 구현 및 테스트 케이스 작성 (#42) * [Docs] 명함 Swagger Open API (#43) * docs: 명함 Swagger Open API init * feat: 썸네일 명함에 대표로 보여줄 정보 타입 * docs: 내 명함 목록 조회 api * feat: 내 명함 목록 조회 dto 추가 * docs: 링크 스크랩 및 직군 조회 스웨거 API 추가 * docs: 직군 조회 응답에 id 추가 * feat: SnsType 추가 * feat: SnsType 추가 * docs: 스크랩 대상 타입 String -> LinkType * docs: 명함 추가 API docs * docs: 특정 명함의 모든 상세 정보를 조회 swagger api 추가 * feat: 특정 명함의 모든 상세 정보를 조회 dto 추가 * refac: 직군 클래스명 CardJob -> Job * docs: Swagger 명세 Mapping URL 제거 & 기본 created Response 추가 * fix: conflict 해결 * feat: 쿼리 파라미터 없는 경우 예외 처리 * refac: LinkType 이넘 형식 통일 * refac: Job Type 추가 * feat: MultiPart Request Object 변환 Converter 구현 및 명함 추가 API docs * feat: MultiPart Request Object 변환 Converter 구현 및 명함 추가 API docs * docs: swagger 불필요한 어노테이션 제거 * fix: EOL 추가 --------- Co-authored-by: SCY <[email protected]> Co-authored-by: 찬기 <[email protected]> * [Feat] 명함에 필요한 Entity 추가 (#47) * chore: swagger Authorization header 설정 추가 * feat: Card Entity 추가 * feat: Career Entity 추가 * feat: User Entity Column 추가 * feat: Not Null 조건 추가 * refac: 불필요한 생성자 제거 * refac: 정적팩토리 위치 변경 vo -> dto * [Deploy] nginx 무중단 배포 작업 완료 (#48) * [Feat] 사용자 정보를 컨트롤러 메서드에 주입하는 LoginUserArgumentResolver 구현 (#51) * feat: 사용자 정보를 컨트롤러 메서드에 주입하는 LoginUserArgumentResolver 구현 * feat: 사용자 정보를 컨트롤러 메서드에 주입하는 LoginUserArgumentResolver 구현 * refac: EOL 추가 * [Feat] 블로그 및 프로젝트 페이지 크롤링 (#52) * feat: 블로그 및 프로젝트 페이지 크롤링 * refac: 빈 문자열 상수화 * feat: og 링크 필드명 수정 * [Feat] 명함 커리어 전체 조회 API (#54) * feat: 전체 커리어 조회 API * refac: 합의된 메서드 네이밍 컨벤션 적용 * refac: 엔티티와 DTO 간 변환 로직 MapStruct 활용 * feat: Career 클래스에서 BaseTimeEntity 제거 및 컬럼명 케이스 통일 * test: 테스트 컨테이너 생성 후 career 데이터 추가 * test: 데이터베이스 초기화 시 테스트간 간섭 제거 * [Feat] 현재 로그인한 사용자가 소유한 모든 명함 목록을 조회 API (#55) * feat: 현재 로그인한 사용자가 소유한 모든 명함 목록을 조회 API * chore: MapStruct 설정 * refac: 불필요한 메서드 제거 * test: CardMapper Test * feat: Card Test용 Factory 추가 * test: IntegrationTest에서 JWT filter mocking * chore: Card Test용 Factory 수정 * test: 내 명함 목록 integrationTest 추가 * test: Jwt Mocking 용 integrationTest * test: 테스크명 수정 * feat: merge [Feat] 명함 커리어 전체 조회 API * refac: MapStruct MyCardListResponse 반환 Mapper 추가 * [Feat] 특정 명함의 모든 상세 정보를 조회 (#57) * feat: 특정 명함의 모든 상세 정보를 조회 API * test: 특정 명함의 모든 상세 정보를 조회 test * refac: Service Layer 메서드명 컨벤션 적용 * test: 테스크명 수정 * feat: request dto valid 추가 * test: 오류 수정 * refac: MapStruct mapper 사용 * refac: LazyLoading으로 인한 Transaction 추가 * [Feat] Docker 배포 환경 KST 적용 #60 * [Feat] 명함 추가 API 구현 (#53) * fix: header 불필요 보안 체크 제거 * feat: 명함 생성 API 구현 * feat: 필드 유효성 검증 로직 추가 & 테스트 케이스 작성 * fix: controller, service 네이밍 컨벤션 * fix: develop 브랜치 파일 이동 반영 * fix: 테스트 코드 conflict 해결 * fix: PR Comment 반영 * [Feat] 링크 스크랩 API 연결 및 크롤러 기능 보완 (#58) * feat: 링크 스크랩 API 연결 * feat: API 요청 형식 변경 및 MapStruct 도입 * feat: 네이버 블로그 크롤러 추가 * refac: 크롤러 코드 형식 통일 * refac: 링크의 호스트 서버에서 파싱하도록 수정 * feat: 비핸스 크롤링 로직 구현 * chore: WebDriverManager 버전 업그레이드 * refac: WebDriver 빈 등록 제거 * refac: toResponse 메서드명 구체화 * test: 실행시간 측정 로직 추가 * test: careers 초기 데이터 삽입 방식 변경 및 데이터 Fixture 도입 * test: 통합테스트에서 모킹 제거 * refac: 크롤러 예외 처리 책임 이동 * feat: 서버에서 동작하도록 크롬 드라이버 추가 * chore: Dockerfile 명령어 위치 수정 * docs: 스웨거 쿼리 파라미터 요청 형태 JSON -> 개별 필드 * [Fix] Docker chrome driver 위치 설정 변경 (#61) * fix: docker chrome driver 위치 설정 변경 * fix: downgrade chrome browser version * fix: Multipart String Request 데이터 Converter 예외 케이스 처리 추가 * [Fix] 동적 크롤링 시 서버 메모리 부족 문제 해결 (#64) * refac: 웹 드라이버 관리 클래스 이름 변경 * fix: 서버에서 /dev/shm 공간 사용하지 않도록 옵션 추가 * chore: 서버 테스트를 위한 스크립트 트리거 변경 * fix: disable dev shm 옵션 제거 * fix: 크롬 드라이버 버전 설정 코드 제거 * chore: 크롬 드라이버 설치 로직 제거 * chore: 크롬 브라우저 설치 로직 추가 * feat: 크롬 드라이버 설치 시 캐싱 활용하여 속도 개선 * feat: 크롬 드라이버 설치 시 캐싱 활용하지 않도록 * chore: 크롬 브라우저 경로 지정 * chore: 크롬 브라우저 종류 변경 * chore: 크롬 브라우저 종류 변경 * chore: 현 브랜치 코드로 재배포 * chore: 캐시 제거 및 최신 chromium 설치 * chore: 캐시 제거 및 최신 chromium 설치 * chore: chromium 대신 google chrome 설치 * chore: wget 의존성 추가 * chore: 크롬 브라우저 경로 변경 * refac: resolutionCache 재적용 * refac: binary path 옵션 제거 * refac: driver cache 재적용 * refac: WebDriverManager 의존성 제거 * WebDriverManager 없이 Selenium의 최신 버전에서 제공하는 SeleniumManager 활용하도록 * chore: CI/CD 스크립트 원상복구 * chore: 명함생성 제한 임시 해제(프론트 작업 편의 목적) * [Feat] FCM 푸시알림 초기 설계 (#66) * feat: FCM 푸시알림 초기 설계 * feat: FCM 서버 연결 후 테스트 환경에서의 외부 의존 제거 및 import 정리 * [Fix] FCM 키 파일 읽기 방식 변경 (#70) * fix: 배포 환경에서 JSON 인식 불가하여 경로 기반 관리로 변경 * chore: 배포 환경에서의 테스트를 위한 트리거 변경 * refac: 리소스 파일이 아닌 파일 시스템 경로 직접 사용 * chore: CI/CD 트리거 원상복구 * [Test] 테스트 데이터 삽입 환경 개선 (#73) * refac: UserFixture 및 UserFactory 도입 * refac: CardFixture 및 CardFactory 도입 (+ Career) * refac: 메서드명과 필드명 통일 * [Feat] 폴더 기본 CRUD API 추가 (#72) * fix: 크롤링 API 더미데이터 응답하도록 * [Fix] 애플 인증키 파일 경로 관리되도록 수정 (#79) * fix: 애플 인증키 파일 경로 관리되도록 수정 * fix: 테스트 케이스 파일 읽어오도록 mocking 수정 & 인증키 파싱 로직 수정 * [Feat] 명함 공유 및 폴더 설정 CRUD 기능 작업 (#75) * feat: 폴더 기본 CRUD API 추가 * feat: 명함 공유 API 명세 작업 & 외부 공유용 명함 정보 조회 API 작업 완료 * feat: 명함 공유 CRUD & 명함 폴더설정 API 작업 완료 * fix: Swagger Description 수정 * feat: 명함&폴더 테스트 케이스 Base Factory Fixture 클래스 생성 * [Feat] 로그아웃 및 회원탈퇴 기능 구현 (#77) * feat: 폴더 기본 CRUD API 추가 * feat: 명함 공유 API 명세 작업 & 외부 공유용 명함 정보 조회 API 작업 완료 * feat: 명함 공유 CRUD & 명함 폴더설정 API 작업 완료 * feat: auth logout 기능 추가 * feat: auth 회원탈퇴 기능 추가 * test: 로그인, 회원탈퇴 test * fix: Swagger Description 수정 * fix: Auth Swagger Security 수정 * feat: 명함&폴더 테스트 케이스 Base Factory Fixture 클래스 생성 * fix: WithdrawService에서 같은 레벨의 의존성을 갖도록 수정 * fix: 화이트리스트 annotation 추가 * test: 회원탈퇴, 로그아웃 테스트 추가 --------- Co-authored-by: 찬기 <[email protected]> * [Feat] 카카오 로그인 보안 강화 작업 (#82) * feat: 회원탈퇴 시 OAuth 정보 삭제 * feat: 카카오 소셜로그인 client secret 도입 * [Test] 공유 받은 명함 및 폴더 관리 테스트 (#86) * feat: 폴더 기본 CRUD API 추가 * feat: 명함 공유 API 명세 작업 & 외부 공유용 명함 정보 조회 API 작업 완료 * feat: 명함 공유 CRUD & 명함 폴더설정 API 작업 완료 * fix: Swagger Description 수정 * feat: 명함&폴더 테스트 케이스 Base Factory Fixture 클래스 생성 * feat: 받은명함 CRUD 테스트 케이스 작성중 * test: 카드 통합테스트 전체적인 given절 보완 * test: fixture 생성 시 필수 필드 없을 경우 예외 처리 --------- Co-authored-by: 찬기 <[email protected]> * feat: 크롤링 API 재활성화 * [Feat] 로깅 시스템 구축 및 IP 차단 메커니즘 구현 (#87) * feat: IP 기반 Rate Limiting 및 차단 시스템 구현 - 초당 요청 수 기반 IP 차단 필터 추가 - 차단된 IP 데이터베이스 영구 저장 구현 - IP별 요청 카운터 메모리 캐싱 및 관리 - 차단된 IP 로깅 시스템 추가 * chore: 로깅 설정 및 환경 구성 최적화 - 로그 종류별 파일 분리 및 롤링 정책 설정 - 요청/응답, 차단 IP 로그 전용 어펜더 구성 - IP 차단 관련 설정 값 application.yml에 추가 - 로그 보관 기간 및 용량 제한 설정 * feat: 개인정보 민감 API 로깅 제어 어노테이션 구현 - PrivacySensitiveLogging 어노테이션 정의 - 컨트롤러/메서드 수준의 로깅 제어 기능 추가 - 개인정보가 포함된 API에 어노테이션 적용 - 요청/응답 본문의 선택적 로깅 기능 구현 * feat: 로깅 기본 인프라 구축 * feat: 요청 응답 logging 설정 * test: 블랙리스트 test * fix: auth api에 @PrivacySensitiveLogging 추가 * test: 필요한 경우만 테스트를 실행하도록 변경 * fix: logs 경로 절대 경로로 변경 * feat: FCM 서버 연결 주석 처리 * chore: 람다 관련 임시 주석처리 * [Deploy] 프로덕션 배포 환경 구축 (#84) * test: 프로덕션 배포 테스트 * deploy: 프로덕션 배포 환경 구축 완료 --------- Co-authored-by: 나경호 <[email protected]> Co-authored-by: SCY <[email protected]>
issue #2
작업 List
Summary by CodeRabbit
New Features
Configurations
Documentation
Tests
Code Ownership
Error Handling