diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml new file mode 100644 index 00000000..aed861b5 --- /dev/null +++ b/.github/workflows/dev-cd.yml @@ -0,0 +1,43 @@ +# github repository actions 페이지에 나타날 이름 +name: CD to dev using github actions + +# event trigger +# develop 브랜치에 pull_request가 닫혔을 때 실행 +on: + pull_request: + types: [ closed ] + branches: [ "develop" ] + +permissions: + contents: read + +jobs: + DEV-CD: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: build-artifacts + + ## docker build & push to production + - name: Docker build & push to prod + run: | + docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} + docker build -t ${{ secrets.DOCKER_REPO }} . + docker push ${{ secrets.DOCKER_REPO }} + + ## deploy to dev + - name: Deploy to prod + uses: appleboy/ssh-action@master + id: deploy + with: + host: ${{ secrets.DEV_HOST }} + username: ${{ secrets.DEV_HOST_USERNAME }} + key: ${{ secrets.DEV_HOST_KEY }} + port: ${{ secrets.DEV_HOST_PORT }} + script: | + docker rm -f taskflow + docker image rm ${{ secrets.DOCKER_REPO }} -f + docker run --name taskflow --network host -d -p 8080:8080 ${{ secrets.DOCKER_REPO }} --restart on-failure \ No newline at end of file diff --git a/.github/workflows/dev-ci.yml b/.github/workflows/dev-ci.yml new file mode 100644 index 00000000..2abf0f3e --- /dev/null +++ b/.github/workflows/dev-ci.yml @@ -0,0 +1,50 @@ +# github repository actions 페이지에 나타날 이름 +name: CI/CD using github actions + +# event trigger +# develop 브랜치에 pull_request가 열렸을 때 실행 +on: + pull_request: + types: [opened, synchronize, closed] + branches: [ "develop" ] + +permissions: + contents: read + +jobs: + CI: + if: github.event.action == 'opened' || github.event.action == 'synchronize' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: 'Set up jdk' + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' # https://github.com/actions/setup-java + + - run: touch ./Dockerfile + - run: echo "${{ secrets.DEV_DOCKERFILE }}" > ./Dockerfile + + # gradle caching - 빌드 시간 향상 + - 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- + + ## gradle build + - name: Build with Gradle + run: | + chmod +x ./gradlew + ./gradlew build + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: build-artifacts + path: build/libs/*.jar \ No newline at end of file diff --git a/build.gradle b/build.gradle index f29319ad..55f6b27e 100644 --- a/build.gradle +++ b/build.gradle @@ -69,6 +69,10 @@ dependencies { // Junit testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + testImplementation 'org.testcontainers:junit-jupiter' + testImplementation 'org.springframework.boot:spring-boot-testcontainers' + testImplementation 'org.testcontainers:elasticsearch:1.20.4' + testImplementation 'com.redis:testcontainers-redis:2.2.2' // Json implementation 'com.fasterxml.jackson.core:jackson-databind:2.15.1' diff --git a/src/main/java/clap/server/config/elastic/ElasticsearchConfig.java b/src/main/java/clap/server/config/elastic/ElasticsearchConfig.java index 026a142f..32e5193d 100644 --- a/src/main/java/clap/server/config/elastic/ElasticsearchConfig.java +++ b/src/main/java/clap/server/config/elastic/ElasticsearchConfig.java @@ -1,6 +1,7 @@ package clap.server.config.elastic; import clap.server.adapter.outbound.infrastructure.elastic.repository.TaskElasticRepository; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.client.ClientConfiguration; import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration; @@ -10,11 +11,14 @@ @EnableElasticsearchRepositories(basePackageClasses = {TaskElasticRepository.class}) public class ElasticsearchConfig extends ElasticsearchConfiguration { + @Value("${spring.elasticsearch.uris}") + private String elasticUrl; + @Override public ClientConfiguration clientConfiguration() { return ClientConfiguration.builder() - .connectedTo("127.0.0.1:9200") + .connectedTo(elasticUrl) .withConnectTimeout(30000) .withSocketTimeout(30000) .build(); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 64c7f036..18de6d00 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,6 +9,8 @@ spring: - optional:classpath:env.properties application: name: taskflow + elasticsearch: + uris: ${ELASTIC_URI:127.0.0.1:9200} web.resources.add-mappings: false diff --git a/src/test/java/clap/server/TaskflowApplicationTests.java b/src/test/java/clap/server/TaskflowApplicationTests.java index 542e3b68..41766b64 100644 --- a/src/test/java/clap/server/TaskflowApplicationTests.java +++ b/src/test/java/clap/server/TaskflowApplicationTests.java @@ -1,13 +1,48 @@ package clap.server; +import clap.server.adapter.outbound.persistense.repository.member.MemberRepository; +import com.redis.testcontainers.RedisContainer; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import static org.assertj.core.api.Assertions.assertThat; + +//@DataElasticsearchTest +@Testcontainers @SpringBootTest class TaskflowApplicationTests { + @Autowired + private MemberRepository memberRepository; + + @Container +// @ServiceConnection + public static ElasticsearchContainer ES_CONTAINER = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.17.5"); + + @Container + @ServiceConnection + public static RedisContainer REDIS_CONTAINER = new RedisContainer(DockerImageName.parse("redis:6.2.6")); + + @DynamicPropertySource + static void configureProperties(DynamicPropertyRegistry registry) { + // Elasticsearch 설정 + registry.add("spring.elasticsearch.uris", ES_CONTAINER::getHttpHostAddress); + } + @Test void contextLoads() { + assertThat(memberRepository.findAll()).isEmpty(); + assertThat(ES_CONTAINER.isRunning()).isTrue(); + assertThat(REDIS_CONTAINER.isRunning()).isTrue(); + System.out.println("Redis: " + REDIS_CONTAINER.getHost() + ":" + REDIS_CONTAINER.getMappedPort(6379)); + System.out.println("Elasticsearch URL: " + ES_CONTAINER.getHttpHostAddress()); } - } diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 00000000..5e5c5c04 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,19 @@ +spring: + # H2 Setting Info (H2 Console에 접속하기 위한 설정정보 입력) + h2: + console: + enabled: false # H2 Console을 사용할지 여부 (H2 Console은 H2 Database를 UI로 제공해주는 기능) + path: /h2 # H2 Console의 Path + # Database Setting Info (Database를 H2로 사용하기 위해 H2연결 정보 입력) + datasource: + driver-class-name: org.h2.Driver # Database를 H2로 사용하겠다. + url: jdbc:h2:mem:testdb # H2 접속 정보 + username: taskflow # H2 접속 시 입력할 username 정보 (원하는 것으로 입력) + password: # H2 접속 시 입력할 password 정보 (원하는 것으로 입력) + jpa: + hibernate: + ddl-auto: create + +swagger: + server: + url: http://localhost:8080 \ No newline at end of file