diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..ac32beb --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,57 @@ +name: Onetime CI/CD with Gradle + +on: + push: + branches: [ "main", "develop" ] + pull_request: + branches: [ "main", "develop" ] + +permissions: + contents: read + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - name: ⏱️Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + + - name: ⏱️Gradle Caching - 빌드 시간 향상 + uses: actions/cache@v3 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: ⏱️gradle build를 위한 권한을 부여합니다. + run: chmod +x gradlew + + - name: ⏱️gradle build 중입니다. + run: ./gradlew build -x test + + - name: ⏱️NCP Container Registry에 로그인 후, docker image build 후 NCP Container Registry에 push합니다. + run: | + docker login -u ${{ secrets.NCP_API_ACCESS_KEY }} -p ${{ secrets.NCP_API_SECRET_KEY }} ${{secrets.NCP_CONTAINER_REGISTRY_PUBLIC_ENDPOINT}} + docker build -f Dockerfile -t ${{ secrets.NCP_CONTAINER_REGISTRY_PUBLIC_ENDPOINT }}/${{ secrets.NCP_CONTAINER_REGISTRY_IMAGE }} . + docker push ${{ secrets.NCP_CONTAINER_REGISTRY_PUBLIC_ENDPOINT }}/${{ secrets.NCP_CONTAINER_REGISTRY_IMAGE }} + + - name: ⏱️NCP Container Registry에서 pull 후 deploy합니다. + uses: appleboy/ssh-action@master + with: + username: ${{ secrets.NCP_SERVER_USERNAME }} + password: ${{ secrets.NCP_SERVER_PASSWORD }} + host: ${{ secrets.NCP_SERVER_HOST }} + port: ${{ secrets.NCP_SERVER_PORT }} + script: | + chmod 777 ./deploy.sh + ./deploy.sh + docker image prune -f \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0c71c20 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM openjdk:17 + +COPY ./build/libs/onetime-0.0.1-SNAPSHOT.jar app.jar + +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/build.gradle b/build.gradle index 1d2e047..d9628dc 100644 --- a/build.gradle +++ b/build.gradle @@ -24,15 +24,18 @@ repositories { } dependencies { + // Web + implementation 'org.springframework.boot:spring-boot-starter-web' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + // DB implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + runtimeOnly 'com.mysql:mysql-connector-j' + // Security implementation 'org.springframework.boot:spring-boot-starter-security' - implementation 'org.springframework.boot:spring-boot-starter-web' + testImplementation 'org.springframework.security:spring-security-test' + // Lombok compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testImplementation 'org.springframework.security:spring-security-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { diff --git a/src/main/java/side/onetime/controller/TestConrtoller.java b/src/main/java/side/onetime/controller/TestConrtoller.java new file mode 100644 index 0000000..083cb9b --- /dev/null +++ b/src/main/java/side/onetime/controller/TestConrtoller.java @@ -0,0 +1,13 @@ +package side.onetime.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TestConrtoller { + + @GetMapping("/api/v1/test") + public String test() { + return "Onetime!"; + } +} \ No newline at end of file diff --git a/src/main/java/side/onetime/global/config/SecurityConfig.java b/src/main/java/side/onetime/global/config/SecurityConfig.java new file mode 100644 index 0000000..583ae43 --- /dev/null +++ b/src/main/java/side/onetime/global/config/SecurityConfig.java @@ -0,0 +1,46 @@ +package side.onetime.global.config; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; + +import java.util.Collections; + +@RequiredArgsConstructor +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + // CORS 설정 + CorsConfigurationSource corsConfigurationSource() { + return request -> { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowedHeaders(Collections.singletonList("*")); + config.setAllowedMethods(Collections.singletonList("*")); + config.setAllowedOriginPatterns(Collections.singletonList("*")); // 허용할 origin + config.setAllowCredentials(true); + return config; + }; + } + + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + httpSecurity. + httpBasic(HttpBasicConfigurer::disable) + .cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource())) // CORS 설정 추가 + .csrf(AbstractHttpConfigurer::disable) + .authorizeHttpRequests(authorize -> + authorize + .requestMatchers("/**").permitAll() + ); + + return httpSecurity.build(); + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..25e1f76 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,25 @@ +server: + port: ${SERVER_PORT} + +spring: + datasource: + url: ${DATABASE_URL} + username: ${DATABASE_HOST} + password: ${DATABASE_PW} + driver-class-name: com.mysql.cj.jdbc.Driver + + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + hibernate: + ddl-auto: update + + defer-datasource-initialization: true + open-in-view: false + generate-ddl: true + show-sql: true + + sql: + init: + mode: always \ No newline at end of file diff --git a/src/test/java/side/onetime/OnetimeApplicationTests.java b/src/test/java/side/onetime/OnetimeApplicationTests.java index f7ed414..4f060d7 100644 --- a/src/test/java/side/onetime/OnetimeApplicationTests.java +++ b/src/test/java/side/onetime/OnetimeApplicationTests.java @@ -2,8 +2,7 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest +@SpringBootTest(classes = OnetimeApplicationTests.class) class OnetimeApplicationTests { @Test