diff --git a/.coderabbit.yaml b/.coderabbit.yaml deleted file mode 100644 index fc3d7d8..0000000 --- a/.coderabbit.yaml +++ /dev/null @@ -1,127 +0,0 @@ -# ─────────── 전역(공통) 설정 ─────────── -language: ko-KR -tone_instructions: "1. 리뷰 시에는 변경 사항의 문제점이나 한계점을 구체적으로 짚어주고, \n 2. 왜 해당 부분이 비효율적이거나 권장되지 않는지 명확한 근거와 함께 설명해주세요. \n 3. 대안을 제시할 땐, 선택지를 제안하면서 각각의 장단점도 논리적으로 설명해주세요. \n 4. 단순 지적보다는 개선 방향에 집중하고, 학습적인 관점에서 이해를 돕는 코멘트를 남겨주세요. \n 5. 지나치게 딱딱하지 않되, 논리의 흐름이 분명하게 전달되도록 해주세요." - -# ─────────── 리뷰(Reviews) 전반 ─────────── -reviews: - profile: chill - high_level_summary: true - high_level_summary_placeholder: "🤖 Code Rabbit PR 요약" - review_status: true - commit_status: true - - # 워크스루/자동화/부가 기능 - collapse_walkthrough: false - changed_files_summary: false - sequence_diagrams: false - assess_linked_issues: true - related_issues: false - related_prs: false - suggested_labels: false - auto_apply_labels: false - suggested_reviewers: false - auto_assign_reviewers: false - poem: false - - # 경로별 리뷰 지침 및 제외 폴더 - path_instructions: - - path: android/** - instructions: | - - 1. 코틀린 공식 스타일 가이드 및 팀 컨벤션을 우선적으로 반영하여, 가독성, 안전성(Null/예외처리), 테스트/유지보수 용이성, 안드로이드 특화 사항(라이프사이클, 리소스, 권한 등)에 대해 리뷰해주세요. - - 2. 최신 코틀린/안드로이드 트렌드, 주석 및 문서화, 팀 스타일 통일성도 함께 확인해 주세요. - - 3. 각 리뷰 포인트별로 문제점과 대안, 장단점을 논리적으로 제시하고, 필요한 경우 예시 코드도 추가해 주세요. - - 4. 리뷰가 너무 많아서 피로감을 줄 수 있으니, 꼭 필요한 부분에 집중해주고, 나머지는 캡션으로 설명해주세요. - - 5. 리뷰 남겨주는 부분은 해당 라인 범위의 코멘트에 작성해주세요. - - path: backend/** - instructions: | - - 1. 팀 및 공식 컨벤션, 가독성, 예외처리, 테스트/확장/유지보수성, 모듈화, API/DB/보안 설계 기준을 기반으로 리뷰해주세요. - - 2. 최신 트렌드, 불필요한 로직, 클린코드, 리팩토링, 서비스/도메인 설계, 공통 예외 처리, 확장성도 함께 확인해주세요. - - 3. 각 피드백은 문제점·대안·장단점을 짧고 논리적으로, 예시 코드가 있다면 간결히 포함해 주세요. - - 4. 팀 내 스타일 통일성도 확인해주세요. - - 5. 미작성한 테스트 코드 케이스가 있다면, 어떤 테스트가 필요한지 제안해주세요. (예: 컨트롤러는 인수 테스트, 나머지는 단위 테스트) - - 6. 리뷰 남겨주는 부분은 해당 라인 범위의 코멘트에 작성해주세요. - - path: frontend/** - instructions: | - - 우리는 백엔드 개발자 팀으로, 관리자 페이지 프론트엔드를 Vibe 코딩 방식으로 빠르게 구현했습니다. - - React에 대한 전문적인 이해도가 부족한 상태이므로, 다음과 같은 기준으로 리뷰해 주세요: - - 1. 코드 스타일이나 컴포넌트 구조 등 전반적인 구조에 대한 일반적인 피드백은 생략해 주세요. - - 2. 보안상 취약점이 될 수 있는 부분 (예: XSS, CSRF, 사용자 입력 검증 부족 등) 은 반드시 알려주세요. - - 3. 화면 상 명백하게 어색하거나 비정상적으로 동작할 수 있는 UI/UX 요소만 지적해 주세요. - - 4. 빠른 배포를 목적으로 하기 때문에, 논리상 큰 이상이 없는 부분은 코멘트하지 않으셔도 됩니다. - - 5. 실제 사용자에게 혼동을 줄 수 있는 부분(버튼 비노출, 접근 불가능 등)이 있다면 꼭 알려주세요. - - 6. 해당 PR에는 테스트 코드가 포함되지 않았으며, 테스트 커버리지나 테스트 방식에 대한 피드백은 생략해 주세요. - - 위 기준을 바탕으로 꼭 필요한 피드백 위주로 리뷰 부탁드립니다. - - # 리뷰 진행/캐시/자동화 - abort_on_close: true - disable_cache: false - - auto_review: - enabled: true - auto_incremental_review: true - base_branches: [ "android", "backend", "frontend" ] - - finishing_touches: - docstrings: - enabled: true - unit_tests: - enabled: true - -# ─────────── 채팅(Chat) 설정 ─────────── -chat: - auto_reply: true - -# ─────────── 지식 기반(Knowledge base) ─────────── -knowledge_base: - opt_out: false - - web_search: - enabled: true - - code_guidelines: - enabled: true - filePatterns: - - backend/code-style.md - - android/code-style.md - - learnings: - scope: auto - issues: - scope: local - pull_requests: - scope: local - -# ─────────── 코드 생성(Code generation) ─────────── -code_generation: - docstrings: - language: ko-KR - path_instructions: - - path: backend/** - instructions: | - - JavaDoc 공식 형식으로, 한글로 Docstring을 작성해주세요. - - 메서드 목적, 파라미터, 반환값, 예외 정보를 명확하게 기술해 주세요. - - 외부 API 등 공개 메서드는 상세히, 내부용은 핵심만 요약해 주세요. - - - path: android/** - instructions: | - - 모든 public 함수에 대해 KDoc 양식을 따라 한글로 간결하게 Docstring을 작성해주세요. - - 함수 목적, 파라미터, 반환값, 예외를 명확하게 기술해 주세요. - - 샘플 코드/사용 예시는 필요한 경우에만 포함해 주세요. - - unit_tests: - path_instructions: - - path: backend/** - instructions: | - - Controller는 인수테스트(API 엔드포인트 통합 테스트) 나머지 영역은 함수/클래스 단위의 단위 테스트 - - Given-When-Then 패턴을 적용 - -# ─────────── 코드 분석 도구(Tools) ─────────── -tools: - hadolint: - enabled: true - gitleaks: - enabled: true - sqlfluff: - enabled: true - oxc: - enabled: true diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index cddec7f..a6a4007 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -2,20 +2,17 @@ name: Android CI on: pull_request: - # 'main' 또는 'android' 브랜치로 PR이 병합될 때 트리거 branches: - main - develop - # 'android' 디렉토리 내의 파일이 변경되었을 때만 워크플로우를 실행 - path: - - '/**' jobs: Run-PR-Test: runs-on: ubuntu-latest - defaults: - run: - working-directory: android + + permissions: + contents: write + checks: write steps: - name: Repository Checkout @@ -34,7 +31,7 @@ jobs: ~/.gradle/caches ~/.gradle/wrapper ~/.android/build-cache - key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/build.gradle.kts', 'android/**/settings.gradle.kts', 'android/**/gradle-wrapper.properties', 'android/gradle/libs.versions.toml', 'android/**/gradle.properties') }} + key: ${{ runner.os }}-gradle-${{ hashFiles('**/build.gradle.kts', '**/settings.gradle.kts', '**/gradle-wrapper.properties', 'gradle/libs.versions.toml', '**/gradle.properties') }} restore-keys: | ${{ runner.os }}-gradle- @@ -52,8 +49,7 @@ jobs: - name: Restore keystore file run: | - mkdir -p app - echo "$KEYSTORE_BASE64" | base64 --decode > ./app/festabook_appkey.jks + echo "$KEYSTORE_BASE64" | base64 --decode > app/festabook_appkey.jks echo "JKS_FILE_PATH=./app/festabook_appkey.jks" >> local.properties echo "STORE_PASSWORD=${{ secrets.STORE_PASSWORD }}" >> local.properties echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> local.properties @@ -62,20 +58,22 @@ jobs: env: KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} - - name: Clean Project - run: ./gradlew clean - - name: Run ktlint run: ./gradlew ktlintCheck - - - name: Run Unit Test - run: ./gradlew test + + - name: Run Debug Unit Test (for Develop PRs) + if: github.base_ref == 'develop' + run: ./gradlew testDebugUnitTest + + - name: Run Release Unit Test (for Main PRs) + if: github.base_ref == 'main' + run: ./gradlew testReleaseUnitTest - name: Publish Unit Test Results if: always() uses: EnricoMi/publish-unit-test-result-action@v2 with: - files: android/app/build/test-results/**/TEST-*.xml + files: app/build/test-results/**/TEST-*.xml check_name: '테스트 결과 🛠️' check_run_annotations: 'none' comment_mode: 'off' diff --git a/.github/workflows/android-release-drafter.yml b/.github/workflows/android-release-drafter.yml new file mode 100644 index 0000000..b0c9b59 --- /dev/null +++ b/.github/workflows/android-release-drafter.yml @@ -0,0 +1,121 @@ +name: Android CD + +on: + push: + branches: + - main + +permissions: + contents: write + pull-requests: write + +jobs: + Upload-Release-Bundle: + runs-on: ubuntu-latest + outputs: + version_code: ${{ steps.get_version.outputs.version_code }} + + steps: + - name: Repository Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Gradle cache + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.android/build-cache + key: ${{ runner.os }}-gradle-${{ hashFiles('android/**/build.gradle.kts', 'android/**/settings.gradle.kts', 'android/**/gradle-wrapper.properties', 'android/gradle/libs.versions.toml', 'android/**/gradle.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + + - name: Create local.properties with BASE_URL + run: | + echo BASE_URL=\"${{ secrets.BASE_URL }}\" > local.properties + echo BASE_URL_DEV=\"${{ secrets.BASE_URL_DEV }}\" >> local.properties + echo NAVER_MAP_CLIENT_ID=\"${{ secrets.NAVER_MAP_CLIENT_ID }}\" >> local.properties + echo NAVER_MAP_STYLE_ID=\"${{ secrets.NAVER_MAP_STYLE_ID }}\" >> local.properties + + - name: Load Google Service file + env: + DATA: ${{ secrets.GOOGLE_SERVICES_JSON }} + run: echo "$DATA" > app/google-services.json + + - name: Restore keystore file + run: | + echo "$KEYSTORE_BASE64" | base64 --decode > app/festabook_appkey.jks + echo "JKS_FILE_PATH=./festabook_appkey.jks" >> local.properties + echo "STORE_PASSWORD=${{ secrets.STORE_PASSWORD }}" >> local.properties + echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> local.properties + echo "KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> local.properties + + env: + KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }} + + - name: Build Release AAB + run: ./gradlew app:bundleRelease + + #versionName의 숫자만 추출합니다 ex) versionName = "v1.2.1" -> 1.2.1 + - name: Extract Version Code + id: get_version + run: | + VERSION_NAME=$(grep -oP 'versionName = "\K[^"]+' app/build.gradle.kts | head -1 | sed 's/[v ]//g') + echo "version_code=$VERSION_NAME" >> $GITHUB_OUTPUT + echo "Extracted Version: $VERSION_NAME" + + - name: Upload Release Artifact + uses: actions/upload-artifact@v4 + with: + name: app-release-bundle-${{ steps.get_version.outputs.version_code }} + path: app/build/outputs/bundle/release/app-release.aab + retention-days: 7 + + #번들이 업로드가 완료된 후 버전 태그를 작성합니다 + Release-Drafter: + runs-on: ubuntu-latest + needs: Upload-Release-Bundle + + steps: + - name: Repository Checkout + uses: actions/checkout@v4 + + #추출한 버전을 drafter에 적용합니다 + - name: Update Draft Release + uses: release-drafter/release-drafter@v6 + with: + version: ${{ needs.Upload-Release-Bundle.outputs.version_code }} + config-name: template/release-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # hotfix 머지 시, main의 변경사항을 develop에 자동 반영합니다 + # 번들이 업로드가 완료된 후 실행됩니다 + Reflect-Changes-Into-Develop: + runs-on: ubuntu-latest + needs: Upload-Release-Bundle + + steps: + - name: Develop Branch Checkout + uses: actions/checkout@v4 + with: + ref: develop + fetch-depth: 0 + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Configure Git User + run: | + git config user.name "GitHub Actions Bot" + git config user.email "actions@github.com" + + - name: Merge Main into Develop + run: | + git fetch origin main + git merge origin/main + git push origin develop \ No newline at end of file diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml deleted file mode 100644 index 6e2d19d..0000000 --- a/.github/workflows/release-drafter.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Release Drafter - -on: - push: - branches: - - release/* - - main - -permissions: - contents: write - pull-requests: write - -jobs: - update_release_draft: - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Update Draft Release - if: startsWith(github.ref, 'refs/heads/release/') - uses: release-drafter/release-drafter@v6 - with: - config-name: template/release-drafter.yml - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Publish Release - if: github.ref == 'refs/heads/main' - id: drafter - uses: release-drafter/release-drafter@v6 - with: - config-name: template/release-drafter.yml - publish: true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/app/build.gradle.kts b/app/build.gradle.kts index dac82a6..51201f5 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,6 +5,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.serialization) alias(libs.plugins.kotlin.compose) + alias(libs.plugins.ktlint) id("kotlin-kapt") id("kotlin-parcelize") id("com.google.gms.google-services")