diff --git a/.github/workflows/be_cd-test.yml b/.github/workflows/be_cd-test.yml index 80030354e..ae068096e 100644 --- a/.github/workflows/be_cd-test.yml +++ b/.github/workflows/be_cd-test.yml @@ -40,8 +40,8 @@ jobs: - name: Image build and push run: | - docker build --build-arg PROFILE=test --build-arg DEPENDENCY=build/dependency -t ${{ secrets.DOCKER_REPO_NAME }}/springboot-app:test-latest --platform linux/arm64 . - docker push ${{ secrets.DOCKER_REPO_NAME }}/springboot-app:test-latest + docker build --build-arg PROFILE=test --build-arg DEPENDENCY=build/dependency -t ${{ secrets.DOCKER_REPO_NAME }}/springboot-app --platform linux/arm64 . + docker push ${{ secrets.DOCKER_REPO_NAME }}/springboot-app - name: Upload docker-compose yaml script to artifact uses: actions/upload-artifact@v4 @@ -69,6 +69,12 @@ jobs: - name: Extract secrets as .be_app-env file run: | + chmod +x ./deploy.sh + source ./deploy.sh + + echo "BLUE_PORT=$BLUE_PORT" >> $GITHUB_ENV + echo "GREEN_PORT=$GREEN_PORT" >> $GITHUB_ENV + cat < ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env # Docker Hub info from Github Secrets @@ -94,48 +100,27 @@ jobs: INSTANCE_NAME=${{ secrets.INSTANCE_A_NAME }} # Server App - BLUE_SERVER_BINDING_PORT=${{ secrets.BLUE_SERVER_BINDING_PORT }} - GREEN_SERVER_BINDING_PORT=${{ secrets.GREEN_SERVER_BINDING_PORT }} + BLUE_SERVER_BINDING_PORT=${BLUE_PORT} + GREEN_SERVER_BINDING_PORT=${GREEN_PORT} SERVER_LOGS_PATH=${{ secrets.SERVER_LOGS_PATH }} EOF - - name: Stop and remove existing containers - run: | - sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml down --rmi all - - name: Deploy docker container - run: | - sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml up -d - - # 실행중인 서버 확인 - - name: Determine Active and Inactive Ports (Blue/Green) - id: determine-ports + - name: Start the new (green/blue) environment run: | - ip="127.0.0.1" - ports=(8080 8081) - for port in "${ports[@]}"; do - RESPONSE=$(curl -s http://$ip:$port/api/actuator/health) - IS_ACTIVE=$(echo ${RESPONSE} | grep 'UP' | wc -l) - if [ $IS_ACTIVE -eq 1 -a $port -eq "8080" ]; then - echo "BLUE_PORT=8080" >> $GITHUB_ENV - echo "GREEN_PORT=8081" >> $GITHUB_ENV - elif [ $IS_ACTIVE -eq 1 -a $port -eq "8081" ]; then - echo "BLUE_PORT=8081" >> $GITHUB_ENV - echo "GREEN_PORT=8080" >> $GITHUB_ENV - fi - done + sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml -p $GREEN_PORT up -d - - name: Start the new (green/blue) environment + - name: remove old spring-app image run: | - sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml -p ${{ env.GREEN_PORT }} up -d + sudo docker image rm -f coduo2024/springboot-app; - name: Wait for new environment to be healthy run: | - until sudo docker inspect --format '{{json .State.Health.Status}}' ${env.GREEN_PORT}_springboot-app | grep "healthy"; do sleep 5; done + until curl -sf http://localhost:${GREEN_PORT}/api/actuator/health | grep "UP"; do sleep 5; done - - name: Switch traffic to new environment + - name: Reload NGINX run: | - sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml -p ${{ env.GREEN_PORT }} up -d --scale springboot-app=1 + sudo systemctl reload nginx - name: Stop and remove the old environment run: | - sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml -p ${{ env.BLUE_PORT }} down + sudo docker-compose --env-file ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/.be_app-env -f ${{ secrets.DOCKER_COMPOSE_YAML_PATH }}/be_app-docker-compose.yml -p $BLUE_PORT down diff --git a/backend/be_app-docker-compose.yml b/backend/be_app-docker-compose.yml index c232f4106..f6e3dcb21 100644 --- a/backend/be_app-docker-compose.yml +++ b/backend/be_app-docker-compose.yml @@ -1,38 +1,10 @@ services: - - springboot-blue: - container_name: coduo_springboot-app-blue - image: ${DOCKER_REPO_NAME}/springboot-app:test-latest - platform: linux/arm64 - ports: - - "${BLUE_SERVER_BINDING_PORT}:8080" - volumes: - - ${SERVER_LOGS_PATH}/springboot-app/blue:/logs - - ${SERVER_LOGS_PATH}/springboot-app/backup/blue:/logs/backup - environment: - SPRING_DATASOURCE_REPLICA_MASTER_JDBC-URL: ${MASTER_DB_URL} - SPRING_DATASOURCE_REPLICA_MASTER_USERNAME: ${MASTER_DB_USERNAME} - SPRING_DATASOURCE_REPLICA_MASTER_PASSWORD: ${MASTER_DB_PASSWORD} - SPRING_DATASOURCE_REPLICA_SLAVE_JDBC-URL: ${SLAVE_DB_URL} - SPRING_DATASOURCE_REPLICA_SLAVE_USERNAME: ${SLAVE_DB_USERNAME} - SPRING_DATASOURCE_REPLICA_SLAVE_PASSWORD: ${SLAVE_DB_PASSWORD} - SPRING_JPA_HIBERNATE_DDL-AUTO: ${DDL_AUTO} - OAUTH_GITHUB_CLIENT_ID: ${CLIENT_ID} - OAUTH_GITHUB_CLIENT_SECRET: ${CLIENT_SECRET} - OAUTH_GITHUB_REDIRECT_URI: ${CLIENT_REDIRECT_URI} - JWT_SIGN_KEY: ${JWT_KEY} - EC2_PREFIX: ${INSTANCE_NAME} - SERVER_PORT: ${BLUE_SERVER_BINDING_PORT} - restart: on-failure - networks: - - coduo_net - springboot-green: - container_name: coduo_springboot-app-green - image: ${DOCKER_REPO_NAME}/springboot-app:test-latest + container_name: coduo_springboot-app-${GREEN_SERVER_BINDING_PORT} + image: ${DOCKER_REPO_NAME}/springboot-app platform: linux/arm64 ports: - - "${GREEN_SERVER_BINDING_PORT}:8081" + - "${GREEN_SERVER_BINDING_PORT}:${GREEN_SERVER_BINDING_PORT}" volumes: - ${SERVER_LOGS_PATH}/springboot-app/green:/logs - ${SERVER_LOGS_PATH}/springboot-app/backup/green:/logs/backup diff --git a/backend/src/main/java/site/coduo/common/controller/CommonController.java b/backend/src/main/java/site/coduo/common/controller/CommonController.java index bc4b16862..52babbe25 100644 --- a/backend/src/main/java/site/coduo/common/controller/CommonController.java +++ b/backend/src/main/java/site/coduo/common/controller/CommonController.java @@ -8,11 +8,11 @@ public class CommonController { @GetMapping("/health-check") public String healthCheck() { - return "Coduo is OK"; + return "Coduo is OK!"; } @GetMapping("/help") public String help() { - return "불쌍한 켈리를 살려주세요..."; + return "히히"; } } diff --git a/backend/src/main/java/site/coduo/member/controller/docs/AuthControllerDocs.java b/backend/src/main/java/site/coduo/member/controller/docs/AuthControllerDocs.java index e5ce6adcd..cfbe4825e 100644 --- a/backend/src/main/java/site/coduo/member/controller/docs/AuthControllerDocs.java +++ b/backend/src/main/java/site/coduo/member/controller/docs/AuthControllerDocs.java @@ -19,9 +19,8 @@ @Tag(name = "인증/인가 API") public interface AuthControllerDocs { - @Operation(summary = "로그아웃 요청을 한다..") - @ApiResponse(responseCode = "200", description = "회원 정보(유저이름)을 등록한다.", content - = @Content(schema = @Schema(contentMediaType = MediaType.APPLICATION_JSON_VALUE))) + @Operation(summary = "로그아웃 요청을 한다.") + @ApiResponse(responseCode = "200", description = "로그아웃 요청 성공.") @ApiResponse(responseCode = "401", description = "인증 실패", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = ApiErrorResponse.class))) diff --git a/backend/src/main/java/site/coduo/pairroom/controller/docs/PairRoomDocs.java b/backend/src/main/java/site/coduo/pairroom/controller/docs/PairRoomDocs.java index af71bc5e6..1e44d02ca 100644 --- a/backend/src/main/java/site/coduo/pairroom/controller/docs/PairRoomDocs.java +++ b/backend/src/main/java/site/coduo/pairroom/controller/docs/PairRoomDocs.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -58,8 +59,8 @@ ResponseEntity updatePairRoomStatus( ); @Operation(summary = "자신의 페어룸을 조회한다.") - @ApiResponse(responseCode = "200", description = "페어룸 조회 성공", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, - schema = @Schema(implementation = PairRoomMemberResponse.class))) + @ApiResponse(responseCode = "200", description = "페어룸 조회 성공", content = @Content( + array = @ArraySchema(schema = @Schema(implementation = PairRoomMemberResponse.class)))) ResponseEntity> getPairRooms( @Parameter( in = ParameterIn.COOKIE, @@ -74,7 +75,7 @@ ResponseEntity> getPairRooms( @ApiResponse(responseCode = "200", description = "페어룸 존재 여부", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE, schema = @Schema(implementation = PairRoomExistResponse.class))) ResponseEntity pairRoomExists(String accessCode); - + @Operation(summary = "페어룸을 삭제한다.") @ApiResponse(responseCode = "204", description = "페어룸 삭제 성공") ResponseEntity deletePairRoom( diff --git a/backend/src/main/java/site/coduo/todo/controller/docs/TodoDocs.java b/backend/src/main/java/site/coduo/todo/controller/docs/TodoDocs.java index 46d1aa0e6..a68cb8d57 100644 --- a/backend/src/main/java/site/coduo/todo/controller/docs/TodoDocs.java +++ b/backend/src/main/java/site/coduo/todo/controller/docs/TodoDocs.java @@ -57,6 +57,7 @@ ResponseEntity updateTodoOrder( ); @Operation(summary = "투두를 삭제한다.") + @ApiResponse(responseCode = "204", description = "투두 삭제 성공") ResponseEntity deleteTodo( @Parameter(description = "삭제할 투두 id") @PathVariable("todoId") final long todoId