feat: 알림 읽음 처리 기능 추가 (#88) #116
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD | |
| on: | |
| push: | |
| branches: [ "main", "dev" ] | |
| workflow_call: | |
| inputs: | |
| environment: | |
| required: true | |
| type: string | |
| description: 'Target environment (main or dev)' | |
| ref: | |
| required: true | |
| type: string | |
| description: 'Target ref (refs/heads/main or refs/heads/dev)' | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| environment: ${{ inputs.environment || github.ref_name }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4.2.2 | |
| with: | |
| ref: ${{ inputs.ref || github.ref }} | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v4.7.1 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '21' | |
| cache: gradle | |
| - name: Cache Gradle packages | |
| uses: actions/cache@v4.2.3 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| ${{ runner.os }}-gradle- | |
| - name: Build with Gradle | |
| run: ./gradlew clean build | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3.10.0 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3.4.0 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Cache Docker layers | |
| uses: actions/cache@v4.2.3 | |
| with: | |
| path: /tmp/.buildx-cache | |
| key: ${{ runner.os }}-buildx-${{ github.sha }} | |
| restore-keys: | | |
| ${{ runner.os }}-buildx- | |
| - name: Build and Push Docker image | |
| uses: docker/build-push-action@v6.16.0 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: ${{ secrets.DOCKER_USERNAME }}/${{ secrets.IMAGE_NAME }}:latest | |
| platforms: ${{ (inputs.ref || github.ref) == 'refs/heads/main' && 'linux/amd64' || 'linux/arm64' }} | |
| cache-from: type=local,src=/tmp/.buildx-cache | |
| cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max | |
| - name: Move cache | |
| run: | | |
| rm -rf /tmp/.buildx-cache | |
| mv /tmp/.buildx-cache-new /tmp/.buildx-cache | |
| - name: Notify Discord (CI/CD - Build) - Failure Only | |
| if: failure() | |
| env: | |
| DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
| run: | | |
| STATUS="${{ job.status }}" # 여기서는 항상 failure | |
| COLOR=15158332 | |
| TITLE="❌ Build & Push Failed" | |
| REPO="${{ github.repository }}" | |
| RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| BRANCH="${{ github.ref_name }}" | |
| SHA7="$(echo "${{ github.sha }}" | cut -c1-7)" | |
| payload=$(cat <<EOF | |
| { | |
| "username": "GitHub Actions", | |
| "embeds": [ | |
| { | |
| "title": "${TITLE}", | |
| "url": "${RUN_URL}", | |
| "color": ${COLOR}, | |
| "fields": [ | |
| { "name": "Repository", "value": "${REPO}", "inline": true }, | |
| { "name": "Branch", "value": "${BRANCH}", "inline": true }, | |
| { "name": "Commit", "value": "${SHA7}", "inline": true }, | |
| { "name": "Status", "value": "${STATUS}", "inline": true }, | |
| { "name": "Logs", "value": "[Open Actions Run](${RUN_URL})", "inline": false } | |
| ] | |
| } | |
| ] | |
| } | |
| EOF | |
| ) | |
| curl -sS -H "Content-Type: application/json" -d "$payload" "$DISCORD_WEBHOOK_URL" | |
| deploy: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| environment: ${{ inputs.environment || github.ref_name }} | |
| steps: | |
| - name: SSH to Server and Deploy | |
| uses: appleboy/ssh-action@v1.2.2 | |
| with: | |
| host: ${{ secrets.SERVER_HOST }} | |
| port: ${{ secrets.SERVER_PORT }} | |
| username: ${{ secrets.SERVER_USERNAME }} | |
| key: ${{ secrets.SERVER_KEY }} | |
| script: | | |
| cd ${{ secrets.SERVER_DEPLOY_PATH }} | |
| cat << 'EOF' > ./env | |
| DB_URL=${{ secrets.DB_URL }} | |
| DB_USERNAME=${{ secrets.DB_USERNAME }} | |
| DB_PASSWORD=${{ secrets.DB_PASSWORD }} | |
| REDIS_HOST=${{ secrets.REDIS_HOST }} | |
| REDIS_PORT=${{ secrets.REDIS_PORT }} | |
| DDL_AUTO=${{ secrets.DDL_AUTO }} | |
| SHOW_SQL=${{ secrets.SHOW_SQL }} | |
| OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} | |
| KAKAO_CLIENT_ID=${{ secrets.KAKAO_CLIENT_ID }} | |
| KAKAO_REDIRECT_URI=${{ secrets.KAKAO_REDIRECT_URI }} | |
| APPLE_TEAM_ID=${{ secrets.APPLE_TEAM_ID }} | |
| APPLE_LOGIN_KEY=${{ secrets.APPLE_LOGIN_KEY }} | |
| APPLE_PRIVATE_KEY=${{ secrets.APPLE_PRIVATE_KEY }} | |
| APPLE_SERVICE_ID=${{ secrets.APPLE_SERVICE_ID }} | |
| APPLE_CLIENT_ID=${{ secrets.APPLE_CLIENT_ID }} | |
| APPLE_REDIRECT_URI=${{ secrets.APPLE_REDIRECT_URI }} | |
| JWT_SECRET=${{ secrets.JWT_SECRET }} | |
| JWT_ACCESS_TOKEN_EXPIRATION_TIME=${{ secrets.JWT_ACCESS_TOKEN_EXPIRATION_TIME }} | |
| JWT_REFRESH_TOKEN_EXPIRATION_TIME=${{ secrets.JWT_REFRESH_TOKEN_EXPIRATION_TIME }} | |
| ALLOWED_ORIGIN_PATTERNS=${{ secrets.ALLOWED_ORIGIN_PATTERNS }} | |
| ALLOWED_METHODS=${{ secrets.ALLOWED_METHODS }} | |
| ALLOWED_HEADERS=${{ secrets.ALLOWED_HEADERS }} | |
| EXPOSED_HEADERS=${{ secrets.EXPOSED_HEADERS }} | |
| ALLOWED_PATTERN=${{ secrets.ALLOWED_PATTERN }} | |
| PERMIT_ALL_URLS=${{ secrets.PERMIT_ALL_URLS }} | |
| FIREBASE_PROJECT_ID=${{ secrets.FIREBASE_PROJECT_ID }} | |
| FIREBASE_SERVICE_ACCOUNT_KEY=${{ secrets.FIREBASE_SERVICE_ACCOUNT_KEY }} | |
| SGIS_SERVICE_ID=${{ secrets.SGIS_SERVICE_ID }} | |
| SGIS_SERVICE_SECRET=${{ secrets.SGIS_SERVICE_SECRET }} | |
| SES_FROM_EMAIL=${{ secrets.SES_FROM_EMAIL }} | |
| EMAIL_CODE_TTL_SECONDS=${{ secrets.EMAIL_CODE_TTL_SECONDS }} | |
| EMAIL_VERIFIED_TTL_SECONDS=${{ secrets.EMAIL_VERIFIED_TTL_SECONDS }} | |
| EMAIL_COOLDOWN_SECONDS=${{ secrets.EMAIL_COOLDOWN_SECONDS }} | |
| EMAIL_MAX_ATTEMPTS=${{ secrets.EMAIL_MAX_ATTEMPTS }} | |
| AWS_REGION=${{ secrets.AWS_REGION }} | |
| AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| AWS_S3_REGION=${{ secrets.AWS_S3_REGION }} | |
| AWS_S3_PUBLIC_BUCKET=${{ secrets.AWS_S3_PUBLIC_BUCKET }} | |
| AWS_S3_PRIVATE_BUCKET=${{ secrets.AWS_S3_PRIVATE_BUCKET }} | |
| AWS_S3_PRESIGNED_URL_EXPIRATION_MINUTES=${{ secrets.AWS_S3_PRESIGNED_URL_EXPIRATION_MINUTES }} | |
| EOF | |
| ./deploy.sh | |
| docker image prune -f | |
| - name: Notify Discord (CI/CD - Deploy) | |
| if: always() | |
| env: | |
| DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} | |
| run: | | |
| STATUS="${{ job.status }}" | |
| if [ "$STATUS" = "success" ]; then | |
| COLOR=3066993 | |
| TITLE="✅ Deploy Success" | |
| else | |
| COLOR=15158332 | |
| TITLE="❌ Deploy Failed" | |
| fi | |
| REPO="${{ github.repository }}" | |
| RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| BRANCH="${{ github.ref_name }}" | |
| SHA="${{ github.sha }}" | |
| SHA7="$(echo "$SHA" | cut -c1-7)" | |
| payload=$(cat <<EOF | |
| { | |
| "username": "GitHub Actions", | |
| "embeds": [ | |
| { | |
| "title": "${TITLE}", | |
| "url": "${RUN_URL}", | |
| "color": ${COLOR}, | |
| "fields": [ | |
| { "name": "Repository", "value": "${REPO}", "inline": true }, | |
| { "name": "Branch", "value": "${BRANCH}", "inline": true }, | |
| { "name": "Commit", "value": "${SHA7}", "inline": true }, | |
| { "name": "Status", "value": "${STATUS}", "inline": true }, | |
| { "name": "Logs", "value": "[Open Actions Run](${RUN_URL})", "inline": false } | |
| ] | |
| } | |
| ] | |
| } | |
| EOF | |
| ) | |
| curl -sS -H "Content-Type: application/json" -d "$payload" "$DISCORD_WEBHOOK_URL" |