diff --git a/.github/labeler.yml b/.github/labeler.yml index 4dfc18607..da8d934b3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -14,6 +14,12 @@ script: - changed-files: - any-glob-to-any-file: '**/scripts/**' +# resource 폴더 하위에 있는 파일이 변경되거나, 브랜치 이름이 resource로 시작하면 resource 라벨을 붙인다. +resource: + - changed-files: + - any-glob-to-any-file: '**/resource/**' + - head-branch: ['^resource', 'resource'] + # 브랜치 이름이 feat 또는 feature로 시작하면 feature 라벨을 붙인다. feature: - head-branch: ['^feat', 'feat', '^feature', 'feature'] diff --git a/.github/workflows/ecs-cd.yml b/.github/workflows/ecs-cd.yml new file mode 100644 index 000000000..57f179f52 --- /dev/null +++ b/.github/workflows/ecs-cd.yml @@ -0,0 +1,95 @@ +name: DEV - Deploy to Amazon ECS + +on: + push: + branches: + - main + workflow_dispatch: +env: + AWS_REGION: ap-northeast-2 + ECR_REPOSITORY: few-ecr + ECS_SERVICE: few-ecs-service + ECS_CLUSTER: few-ecs-cluster + ECS_TASK_DEFINITION: task-definition.json + TASK_DEFINITION_NAME: few-ecs-task + CONTAINER_NAME: few-container + +jobs: + build-and-push-docker-image: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + cache: gradle + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.DEV_AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.DEV_AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + - name: Login to Amazon ECR + id: login-ecr + uses: aws-actions/amazon-ecr-login@v1 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Jooq Code Generation + run: | + ./gradlew jooqCodegenAll + + - name: Test with Gradle + run: | + ./gradlew test + + - name: Generate OpenAPI3 + run: | + ./gradlew --info api:openapi3 -PserverUrl=https://api.fewletter.site + + - name: Generate Swagger + run: | + ./gradlew --info api:generateStaticSwaggerUIApi + + - name: Build with Gradle bootBuildImage, tag, and push image to Amazon ECR + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + run: | + GIT_HASH=$(git rev-parse --short HEAD) + ./gradlew buildEcsDockerImage -PimageName=${ECR_REGISTRY}/${ECR_REPOSITORY}:latest + docker tag ${ECR_REGISTRY}/${ECR_REPOSITORY}:latest ${ECR_REGISTRY}/${ECR_REPOSITORY}:${GIT_HASH} + docker push ${ECR_REGISTRY}/${ECR_REPOSITORY} --all-tags + - name: Get ECR Repository image path + id: get-docker-image-path + env: + ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} + run: | + GIT_HASH=$(git rev-parse --short HEAD) + echo ${ECR_REGISTRY}/${ECR_REPOSITORY}:${GIT_HASH} + echo "::set-output name=image::${ECR_REGISTRY}/${ECR_REPOSITORY}:${GIT_HASH}" + - name: Download task definition + run: | + aws ecs describe-task-definition --task-definition ${TASK_DEFINITION_NAME} --query taskDefinition > task-definition.json + - name: Fill in the new image ID in the Amazon ECS task definition + id: task-definition + uses: aws-actions/amazon-ecs-render-task-definition@v1 + with: + task-definition: ${{ env.ECS_TASK_DEFINITION }} + container-name: ${{ env.CONTAINER_NAME }} + image: ${{ steps.get-docker-image-path.outputs.image }} + + - name: Deploy Amazon ECS task definition + id: ecs-deployment + uses: aws-actions/amazon-ecs-deploy-task-definition@v1 + with: + task-definition: ${{ steps.task-definition.outputs.task-definition }} + service: ${{ env.ECS_SERVICE }} + cluster: ${{ env.ECS_CLUSTER }} + wait-for-service-stability: true diff --git a/api/build.gradle.kts b/api/build.gradle.kts index cb5b35fef..c771e38e7 100644 --- a/api/build.gradle.kts +++ b/api/build.gradle.kts @@ -185,4 +185,23 @@ tasks.register("buildDockerImage") { ) } } +} + +tasks.register("buildEcsDockerImage") { + dependsOn("bootJar") + + doLast { + exec { + workingDir(".") + commandLine( + "docker", + "build", + "-t", + imageName, + "--build-arg", + "RELEASE_VERSION=$releaseVersion", + '.' + ) + } + } } \ No newline at end of file diff --git a/api/src/main/resources/logback-spring.xml b/api/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..757f28ae8 --- /dev/null +++ b/api/src/main/resources/logback-spring.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + ${TRACE_ID_CONSOLE_PATTERN} + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/storage/src/main/kotlin/com/few/storage/config/ClientConfig.kt b/storage/src/main/kotlin/com/few/storage/config/ClientConfig.kt index 1c074d889..b95ab3f8a 100644 --- a/storage/src/main/kotlin/com/few/storage/config/ClientConfig.kt +++ b/storage/src/main/kotlin/com/few/storage/config/ClientConfig.kt @@ -8,6 +8,7 @@ import com.amazonaws.services.s3.AmazonS3ClientBuilder import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile @Configuration class ClientConfig( @@ -17,8 +18,9 @@ class ClientConfig( @Value("\${storage.region}") val region: String, ) { + @Profile("!prd") @Bean - fun s3StorageClient(): AmazonS3Client { + fun localS3StorageClient(): AmazonS3Client { val builder = AmazonS3ClientBuilder.standard() .withCredentials( AWSStaticCredentialsProvider( @@ -39,4 +41,21 @@ class ClientConfig( return client as AmazonS3Client } } + + @Profile("prd") + @Bean + fun prdS3StorageClient(): AmazonS3Client { + AmazonS3Client.builder() + .withRegion(region) + .withCredentials( + AWSStaticCredentialsProvider( + BasicAWSCredentials( + accessKey, + secretKey + ) + ) + ).build().let { client -> + return client as AmazonS3Client + } + } } \ No newline at end of file