Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: CI/CD 스크립트 작성 #1

Merged
merged 2 commits into from
Feb 14, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/yappu-world-server-lambda-cd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: yappu-world-server-lambda-cd

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'corretto'
cache: gradle

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Create .env file
run: |
mkdir -p src/main/resources
echo "DISCORD_SERVER_ALERT_WEBHOOK=${{ secrets.DISCORD_SERVER_ALERT_WEBHOOK }}" > src/main/resources/.env
cat src/main/resources/.env

- name: Build ShadowJar
run: |
./gradlew shadowJar

- name: Install AWS CLI
run: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# AWS Credentials
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_BOT_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_BOT_SECRET_KEY }}
aws-region: ap-northeast-2

- name: Deploy to AWS Lambda
run: |
export AWS_PAGER=""
aws lambda update-function-code \
--function-name sendSentryAlertsToDiscord \
--zip-file fileb://build/libs/yappu-world-server-lambda-shadow.jar

# Discord Notification
- name: CD Success Notification
uses: sarisia/actions-status-discord@v1
if: success()
with:
title: ✅ Lambda 배포 성공 ✅
webhook: ${{ secrets.DISCORD_SERVER_WEBHOOK }}
color: 0x00FF00
username: 페페훅

- name: CD Failure Notification
uses: sarisia/actions-status-discord@v1
if: failure()
with:
title: ❗️Lambda 배포 실패 ❗️
webhook: ${{ secrets.DISCORD_SERVER_WEBHOOK }}
color: 0xFF0000
username: 페페훅
53 changes: 53 additions & 0 deletions .github/workflows/yappu-world-server-lambda-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: yappu-world-server-lambda-ci

on:
pull_request:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4

- name: Setup JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'corretto'
cache: gradle

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Create .env file
run: |
mkdir -p src/main/resources
echo "DISCORD_SERVER_ALERT_WEBHOOK=${{ secrets.DISCORD_SERVER_TEST_WEBHOOK }}" > src/main/resources/.env
cat src/main/resources/.env

- name: Compile and run test
run: |
./gradlew check

# Discord Notification
- name: CI Success Notification
uses: sarisia/actions-status-discord@v1
if: success()
with:
title: ✅ Lambda CI 성공 ✅
webhook: ${{ secrets.DISCORD_SERVER_WEBHOOK }}
color: 0x00FF00
username: 페페훅

- name: CI Failure Notification
uses: sarisia/actions-status-discord@v1
if: failure()
with:
title: ❗️Lambda CI 실패 ❗️
webhook: ${{ secrets.DISCORD_SERVER_WEBHOOK }}
color: 0xFF0000
username: 페페훅
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -359,3 +359,4 @@ gradle-app.setting
# End of https://www.toptal.com/developers/gitignore/api/intellij,intellij+iml,intellij+all,kotlin,gradle,linux,macos,windows

src/main/resources/.env
.secrets
18 changes: 14 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -21,11 +21,21 @@ dependencies {
implementation("io.github.cdimascio:dotenv-kotlin:6.5.0")

testImplementation(kotlin("test"))
testImplementation("io.mockk:mockk:1.13.14")
}

tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(17)
}
}

tasks {
test {
useJUnitPlatform()
}

shadowJar {
archiveBaseName.set("yappu-world-server-lambda") // JAR 기본 이름
archiveVersion.set("") // 버전 제거
archiveClassifier.set("shadow") // 기본 bootJar와 구분
}
}
2 changes: 1 addition & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "yappu-world-sentry-lambda"
rootProject.name = "yappu-world-server-lambda"

4 changes: 2 additions & 2 deletions src/main/kotlin/discord/DiscordClient.kt
Original file line number Diff line number Diff line change
@@ -12,14 +12,14 @@ class DiscordClient {
suspend fun send(message: DiscordMessage): DiscordWebhookResponse {
val dotenv = Dotenv.load()
val response = HttpClient(CIO).use { client ->
client.post(dotenv["DISCORD_WEBHOOK"]) {
client.post(dotenv["DISCORD_SERVER_ALERT_WEBHOOK"]) {
contentType(ContentType.Application.Json)
setBody(jacksonObjectMapper().writeValueAsString(message))
}
}

return DiscordWebhookResponse(
response.status,
response.status.value,
response.body<String>()
)
}
4 changes: 1 addition & 3 deletions src/main/kotlin/discord/DiscordWebhookResponse.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package co.discord

import io.ktor.http.*

data class DiscordWebhookResponse(
val status: HttpStatusCode,
val status: Int,
val response: String
)
8 changes: 5 additions & 3 deletions src/main/kotlin/handler/SentryDiscordWebhookHandler.kt
Original file line number Diff line number Diff line change
@@ -10,7 +10,9 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import kotlinx.coroutines.runBlocking

class SentryDiscordWebhookHandler : RequestHandler<Any, APIGatewayProxyResponseEvent> {
class SentryDiscordWebhookHandler(
private val discordClient: DiscordClient = DiscordClient()
) : RequestHandler<Any, APIGatewayProxyResponseEvent> {

override fun handleRequest(input: Any, context: Context): APIGatewayProxyResponseEvent {
val event = parseEvent(input)
@@ -31,7 +33,7 @@ class SentryDiscordWebhookHandler : RequestHandler<Any, APIGatewayProxyResponseE
)
)

return runBlocking { DiscordClient().send(message) }
return runBlocking { discordClient.send(message) }
.let {
APIGatewayProxyResponseEvent()
.withStatusCode(200)
@@ -47,4 +49,4 @@ class SentryDiscordWebhookHandler : RequestHandler<Any, APIGatewayProxyResponseE
}
return data["event"] as Map<*, *>
}
}
}
27 changes: 27 additions & 0 deletions src/test/kotlin/handler/SentryDiscordWebhookHandlerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package handler

import co.discord.DiscordClient
import co.handler.SentryDiscordWebhookHandler
import com.amazonaws.services.lambda.runtime.Context
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import io.mockk.mockk
import org.junit.jupiter.api.Test
import support.fixture.SentryDiscordWebhookHandlerFixture
import kotlin.test.assertTrue

class SentryDiscordWebhookHandlerTest {

val mockContext = mockk<Context>()

// 실행 결과는 test-webhook channel을 확인하세요
@Test
fun `데이터를 파싱하여 디스코드에 메세지를 보낸다`() {
val responseEvent = SentryDiscordWebhookHandler(DiscordClient()).handleRequest(
SentryDiscordWebhookHandlerFixture.body,
mockContext
)

val parsedResponseBody = jacksonObjectMapper().readValue(responseEvent.body, Map::class.java)
assertTrue { (parsedResponseBody["status"].toString()).startsWith("2") }
}
}
Loading