Skip to content
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

[WALWAL-148] Dev, Prod 환경 분리 #56

Merged
merged 10 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .github/workflows/develop-build-deploy.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: Develop Build & Deploy

on:
push:
branches: [ "develop" ]
Expand All @@ -9,18 +10,21 @@ env:
jobs:
build-deploy:
runs-on: ubuntu-latest
environment: DEV
strategy:
matrix:
java-version: [ 17 ]
distribution: [ 'zulu' ]
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Java
# JDK를 17 버전으로 세팅
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.java-version }}
distribution: 'zulu'
distribution: ${{ matrix.distribution }}

- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
Expand Down Expand Up @@ -69,6 +73,7 @@ jobs:
version_label: "walwal-dev-${{ steps.format-time.outputs.replaced }}"
region: ap-northeast-2
deployment_package: deployment-package.zip
wait_for_environment_recovery: 180

# Slack 알림
- name: Send Deploy Result to Slack
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ services:
- TZ=Asia/Seoul
network_mode: host
env_file:
- .env
- ~/.env
redis:
image: "redis:alpine"
container_name: redis
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.depromeet.stonebed.global.annotation;

import com.depromeet.stonebed.global.common.constants.EnvironmentConstants;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Conditional({OnProfileCondition.class})
public @interface ConditionalOnProfile {
EnvironmentConstants[] value() default {EnvironmentConstants.LOCAL};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.depromeet.stonebed.global.annotation;

import static java.util.Objects.*;

import com.depromeet.stonebed.global.common.constants.EnvironmentConstants;
import java.util.Arrays;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class OnProfileCondition implements Condition {

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String[] activeProfiles = context.getEnvironment().getActiveProfiles();
EnvironmentConstants[] targetProfiles = getTargetProfiles(metadata);

return Arrays.stream(targetProfiles)
.anyMatch(
targetProfile ->
Arrays.asList(activeProfiles).contains(targetProfile.getValue()));
}

private EnvironmentConstants[] getTargetProfiles(AnnotatedTypeMetadata metadata) {
return (EnvironmentConstants[])
requireNonNull(
metadata.getAnnotationAttributes(
ConditionalOnProfile.class.getName()),
"target Profiles가 null입니다.")
.get("value");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분에서 requireNonNull로 널 체크를 하고 있는데 명시적으로 예외처리를 체크하는 건 어떤가요?
Optional 처리해서 널 값다루거나 예외를 던지는 식으로요!

Copy link
Member Author

@char-yb char-yb Jul 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

requireNonNull의 두 번째 인자로 에러 메세지를 던지는 방식은 어떤가용??

"target Profiles가 null입니다." 이런 식으로요!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

원래는 if문을 통한 예외 처리가 일반적이라고 생각했는데, 보내주신 레퍼런스를 확인해보니 requireNonNull로 처리하고 에러메세지를 던지는것도 가독성이 좋아보이네용! 좋습니다~!

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.depromeet.stonebed.global.common.constants;

import static com.depromeet.stonebed.global.common.constants.EnvironmentConstants.Constants.*;

import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@AllArgsConstructor
public enum EnvironmentConstants {
PROD(PROD_ENV),
DEV(DEV_ENV),
LOCAL(LOCAL_ENV);

private final String value;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public static class Constants {
public static final String PROD_ENV = "prod";
public static final String DEV_ENV = "dev";
public static final String LOCAL_ENV = "local";
public static final List<String> PROD_AND_DEV_ENV = List.of(PROD_ENV, DEV_ENV);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.depromeet.stonebed.global.config.security;

import static com.depromeet.stonebed.global.common.constants.EnvironmentConstants.*;
import static com.depromeet.stonebed.global.common.constants.SwaggerUrlConstants.*;
import static org.springframework.http.HttpHeaders.*;
import static org.springframework.security.config.Customizer.*;

import com.depromeet.stonebed.domain.auth.application.JwtTokenService;
import com.depromeet.stonebed.global.common.constants.SwaggerUrlConstants;
import com.depromeet.stonebed.global.annotation.ConditionalOnProfile;
import com.depromeet.stonebed.global.filter.JwtAuthenticationFilter;
import com.depromeet.stonebed.global.util.CookieUtil;
import com.depromeet.stonebed.global.util.SpringEnvironmentUtil;
import com.depromeet.stonebed.infra.properties.SwaggerProperties;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
Expand All @@ -33,6 +36,7 @@
public class WebSecurityConfig {
private final JwtTokenService jwtTokenService;
private final CookieUtil cookieUtil;
private final SpringEnvironmentUtil springEnvironmentUtil;

private final SwaggerProperties swaggerProperties;

Expand Down Expand Up @@ -73,12 +77,16 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti

@Bean
@Order(1)
@ConditionalOnProfile({DEV, LOCAL})
public SecurityFilterChain swaggerFilterChain(HttpSecurity http) throws Exception {
defaultFilterChain(http);

http.securityMatcher(SwaggerUrlConstants.getSwaggerUrls()).httpBasic(withDefaults());
http.securityMatcher(getSwaggerUrls()).httpBasic(withDefaults());

http.authorizeHttpRequests(authorize -> authorize.anyRequest().permitAll());
http.authorizeHttpRequests(
springEnvironmentUtil.isDevProfile()
? authorize -> authorize.anyRequest().authenticated()
: authorize -> authorize.anyRequest().permitAll());

return http.build();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.depromeet.stonebed.global.config.swagger;

import static com.depromeet.stonebed.global.common.constants.UrlConstants.*;

import com.depromeet.stonebed.global.common.constants.UrlConstants;
import com.depromeet.stonebed.global.util.SpringEnvironmentUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.core.jackson.ModelResolver;
import io.swagger.v3.oas.models.Components;
Expand All @@ -11,17 +11,21 @@
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class SwaggerConfig {
private static final String PACKAGES_TO_SCAN = "com.depromeet.stonebed";
private static final String SWAGGER_API_TITLE = "WalWal 프로젝트 API 문서";
private static final String SWAGGER_API_DESCRIPTION = "WalWal 프로젝트 API 문서입니다.";

private final SpringEnvironmentUtil springEnvironmentUtil;

@Value("${api.version}")
private String apiVersion;

Expand All @@ -39,12 +43,17 @@ public OpenAPI openAPI() {
.description(SWAGGER_API_DESCRIPTION));
}

private String getServerUrl() {
return switch (springEnvironmentUtil.getCurrentProfile()) {
case "prod" -> UrlConstants.PROD_SERVER_URL.getValue();
case "dev" -> UrlConstants.DEV_SERVER_URL.getValue();
default -> UrlConstants.LOCAL_SERVER_URL.getValue();
};
}

private List<Server> swaggerServers() {
Server localServer =
new Server().url(LOCAL_SERVER_URL.getValue()).description(SWAGGER_API_DESCRIPTION);
Server devServer =
new Server().url(LOCAL_SERVER_URL.getValue()).description(SWAGGER_API_DESCRIPTION);
return List.of(localServer, devServer);
Server server = new Server().url(getServerUrl()).description(SWAGGER_API_DESCRIPTION);
return List.of(server);
}

private Components authSetting() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
@RequiredArgsConstructor
public class CookieUtil {

private final SpringEnvironmentUtil springEnvironmentUtil;

public HttpHeaders generateTokenCookies(String accessToken, String refreshToken) {

String sameSite = determineSameSitePolicy();
Expand Down Expand Up @@ -40,10 +42,9 @@ public HttpHeaders generateTokenCookies(String accessToken, String refreshToken)
}

private String determineSameSitePolicy() {
// TODO: prod 환경 구성 시 주석 해제
// if (springEnvironmentUtil.isProdProfile()) {
// return Cookie.SameSite.STRICT.attributeValue();
// }
if (springEnvironmentUtil.isProdProfile()) {
return Cookie.SameSite.STRICT.attributeValue();
}
return Cookie.SameSite.NONE.attributeValue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.depromeet.stonebed.global.util;

import static com.depromeet.stonebed.global.common.constants.EnvironmentConstants.Constants.*;

import java.util.Arrays;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
@RequiredArgsConstructor
public class SpringEnvironmentUtil {

private final Environment environment;

public String getCurrentProfile() {
return getActiveProfiles()
.filter(profile -> profile.equals(PROD_ENV) || profile.equals(DEV_ENV))
.findFirst()
.orElse(LOCAL_ENV);
}

public boolean isProdProfile() {
return getActiveProfiles().anyMatch(PROD_ENV::equals);
}

public boolean isDevProfile() {
return getActiveProfiles().anyMatch(DEV_ENV::equals);
}

public boolean isProdAndDevProfile() {
return getActiveProfiles().anyMatch(PROD_AND_DEV_ENV::contains);
}

private Stream<String> getActiveProfiles() {
return Arrays.stream(environment.getActiveProfiles());
}
}
6 changes: 6 additions & 0 deletions src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ spring:
jpa:
hibernate:
ddl-auto: update
show-sql: ${SHOW_SQL:true}
properties:
hibernate:
format_sql: ${FORMAT_SQL:true}
defer-datasource-initialization: true
open-in-view: false

logging:
level:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ void checkPerson() {

// then
then(person.getPersonId()).isNotNull();
then(person.getPersonName()).isNotBlank();
then(person.getPersonNo().length()).isBetween(1, 16);
}

Expand All @@ -54,7 +53,12 @@ void testOrder() {
// when
Order actual =
sut.giveMeBuilder(Order.class)
.set("orderNo", Arbitraries.strings().ofMinLength(1).ofMaxLength(16))
.set(
"orderNo",
Arbitraries.strings()
.ofMinLength(1)
.ofMaxLength(16)
.map(it -> "orderNo-" + it))
.set("productName", Arbitraries.strings().ofMinLength(2).ofMaxLength(10))
.set("price", Arbitraries.longs().between(0, 1000))
.set("quantity", Arbitraries.integers().between(1, 100))
Expand Down
Loading
Loading