Skip to content

Commit

Permalink
Merge pull request #601 from tukcomCD2024/develop_back_notification
Browse files Browse the repository at this point in the history
feat : develop_back_notification -> develop_back
  • Loading branch information
seokho-1116 authored Jul 30, 2024
2 parents 8cf1008 + 5e597a4 commit 004f3c0
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 8 deletions.
149 changes: 149 additions & 0 deletions .github/workflows/notification-application-prod-ci-cd-flow.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
name: notification-prod-ci/cd

on:
push:
branches:
- prod_back_notification
- 'hotfix/[0-9a-zA-z]+-B-prod-notification-#[0-9a-zA-z]+'
pull_request:
branches:
- prod_back_notification

jobs:
build_and_test:
name: build and test
if: ${{github.event_name == 'pull_request' }}
runs-on: ubuntu-latest

defaults:
run:
working-directory: ./backend/core

steps:
- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'liberica'

- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.CI_PAT }}

- name: formatting
uses: axel-op/googlejavaformat-action@v3
with:
args: "--replace"
skip-commit: true

- name: grant execute permission for gradlew
run: chmod +x ./gradlew

- name: test
run: ./gradlew clean test

deploy-notification:
name: notification application deploy
if: ${{ github.event_name == 'push' }}
runs-on: ubuntu-latest

defaults:
run:
working-directory: ./backend/notification

permissions:
id-token: write
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.CI_PAT }}

- name: set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'liberica'
cache: gradle

- name: grant execute permission for gradlew
run: chmod +x ./gradlew

- name: build gradle
run: ./gradlew clean build

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ${{ secrets.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ steps.login-ecr.outputs.registry }}/${{ secrets.AWS_PROD_NOTIFICATION_REPOSITORY_NAME }}
tags: |
type=raw,value={{date 'YYYYMMDD-HHmmss'}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: ./backend/notification
push: true
tags: ${{ steps.meta.outputs.tags }}
provenance: false

- name: Get Github action IP
id: ip
uses: haythem/[email protected]

- name: Add Github Actions IP to Security group
run: |
aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_PROD_CORE_NOTI_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
- name: Connect ec2 and Run Docker Container
uses: appleboy/[email protected]
env:
AWS_ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
with:
host: ${{ secrets.SSH_PROD_CORE_NOTI_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key: ${{ secrets.SSH_PROD_CORE_NOTI_PRIVATE_KEY }}
port: ${{ secrets.SSH_PORT }}
script: |
docker ps -q --filter "name=notification" | xargs -r docker stop
docker ps -aq --filter "name=notification" | xargs -r docker rm
aws ecr get-login-password --region ${{ secrets.AWS_REGION }} | docker login --username ${{ secrets.AWS_DOCKER_USER }} --password-stdin ${{ secrets.AWS_USER_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com
docker image prune -f
docker pull ${{ steps.meta.outputs.tags }}
docker run -d -p 8081:8081 -e ENVIRONMENT=prod --name notification --network ec2-user_backend ${{ steps.meta.outputs.tags }}
- name: Remove Github Actions IP from security group
if: always()
run: |
aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_PROD_CORE_NOTI_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
- uses: sarisia/actions-status-discord@v1
if: success()
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
status: ${{ job.status }}
content: "여러분 <@384742716933668867> <@1084774841460215839> <@545902166842408960> <@1081452554149449748>\n 배포 완료했습니다!!"
title: "알림 운영 서버 배포 완료 알림"
description: "백엔드 알림 개발 브랜치에 깃허브 액션으로 운영 서버 배포 완료"
image: ${{ secrets.EMBED_IMAGE }}
color: 0x0000ff
url: "https://github.com/tukcomCD2024/DroidBlossom/actions"
username: GitHub Actions Bot
avatar_url: ${{ secrets.AVATAR_URL }}
9 changes: 9 additions & 0 deletions backend/notification/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ dependencies {
//AOP
implementation 'org.springframework.boot:spring-boot-starter-aop'

// loki
implementation 'com.github.loki4j:loki-logback-appender:1.4.1'

// Spring Actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'

// Prometheus
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
import site.timecapsulearchive.notification.global.entity.BaseEntity;

@Entity
@Table(name = "notification")
@Getter
@SQLDelete(sql = "UPDATE notification SET deleted_at = now() WHERE notification_id = ?")
@Where(clause = "deleted_at is null")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(name = "NOTIFICATION")
public class Notification extends BaseEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package site.timecapsulearchive.notification.global.config;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
Expand All @@ -11,6 +13,7 @@
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import site.timecapsulearchive.notification.global.error.InternalServerException;

@Configuration
@EnableRabbit
Expand Down Expand Up @@ -141,6 +144,15 @@ public CachingConnectionFactory connectionFactory() {
connectionFactory.setUsername(rabbitmqProperties.userName());
connectionFactory.setPassword(rabbitmqProperties.password());
connectionFactory.setVirtualHost(rabbitmqProperties.virtualHost());

if (rabbitmqProperties.isSslEnabled()) {
try {
connectionFactory.getRabbitConnectionFactory().useSslProtocol();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
throw new InternalServerException(e);
}
}

return connectionFactory;
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
package site.timecapsulearchive.notification.global.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

@ConfigurationProperties(prefix = "spring.rabbitmq")
public record RabbitmqProperties(
String host,
int port,
String userName,
String password,
String virtualHost
String virtualHost,
@NestedConfigurationProperty
SSL ssl
) {
protected record SSL(
boolean enabled
) {

}
}

public Boolean isSslEnabled() {
return ssl != null && ssl.enabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ public abstract class BaseEntity {

@LastModifiedDate
private ZonedDateTime updatedAt;

private ZonedDateTime deletedAt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,15 @@ protected ResponseEntity<ErrorResponse> handleRequestTypeNotValidException(
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(response);
}

@ExceptionHandler(InternalServerException.class)
protected ResponseEntity<ErrorResponse> handleInternalServerException(
InternalServerException e
) {
log.error(e.getMessage(), e);

final ErrorResponse errorResponse = ErrorResponse.exception();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(errorResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package site.timecapsulearchive.notification.global.error;

public class InternalServerException extends RuntimeException {

public InternalServerException(Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class MemberRepository {
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

public String findFCMToken(Long memberId) {
String sql = "SELECT m.fcm_token FROM member m WHERE m.member_id = ?";
String sql = "SELECT m.fcm_token FROM member m WHERE m.member_id = ? and m.deleted_at is null";

return jdbcTemplate.queryForObject(
sql,
Expand All @@ -26,7 +26,7 @@ public String findFCMToken(Long memberId) {
}

public List<String> findFCMTokens(List<Long> memberIds) {
final String sql = "SELECT m.fcm_token FROM member m WHERE m.member_id IN (:memberIds)";
final String sql = "SELECT m.fcm_token FROM member m WHERE m.member_id IN (:memberIds) and m.deleted_at is null";

final SqlParameterSource parameters = new MapSqlParameterSource("memberIds", memberIds);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ INSERT INTO notification (
image_url,
created_at,
updated_at,
status
status,
deleted_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
new BatchPreparedStatementSetter() {

Expand All @@ -49,6 +50,7 @@ public void setValues(final PreparedStatement ps, final int i) throws SQLExcepti
ps.setTimestamp(7, Timestamp.valueOf(ZonedDateTime.now().toLocalDateTime()));
ps.setTimestamp(8, Timestamp.valueOf(ZonedDateTime.now().toLocalDateTime()));
ps.setString(9, String.valueOf(NotificationStatus.SUCCESS));
ps.setNull(10, Types.TIMESTAMP);
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion backend/notification/src/main/resources/config
55 changes: 55 additions & 0 deletions backend/notification/src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="LOKI" class="com.github.loki4j.logback.Loki4jAppender">
<http>
<url>http://10.0.0.8:3100/loki/api/v1/push</url>
</http>
<format>
<label>
<pattern>app=${name},host=${HOSTNAME},level=%level</pattern>
<readMarkers>true</readMarkers>
</label>
<message>
<pattern>
{
"level":"%level",
"class":"%logger{36}",
"thread":"%thread",
"message": "%message",
"requestId": "%X{X-Request-ID}"
}
</pattern>
</message>
</format>
</appender>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
</Pattern>
</encoder>
</appender>

<springProfile name="prod">
<logger name="org.hibernate" level="error" additivity="false">
<appender-ref ref="STDOUT"/>
<appender-ref ref="LOKI"/>
</logger>

<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="LOKI"/>
</root>
</springProfile>

<springProfile name="local | dev | container">
<logger name="org.hibernate" level="error" additivity="false">
<appender-ref ref="STDOUT"/>
</logger>

<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</springProfile>
</configuration>

0 comments on commit 004f3c0

Please sign in to comment.