From 18912cb6b7c4e083821d020ef7c3095f257af62c Mon Sep 17 00:00:00 2001 From: moondev03 Date: Mon, 1 Jun 2026 02:33:41 +0900 Subject: [PATCH 1/3] ci: automate version tags and Firebase distribution --- .../workflows/firebase-app-distribution.yml | 66 +++++++++++++++ .github/workflows/version-tag-on-merge.yml | 83 +++++++++++++++++++ Prezel/app/build.gradle.kts | 15 ++++ Prezel/build.gradle.kts | 1 + Prezel/gradle/libs.versions.toml | 2 + 5 files changed, 167 insertions(+) create mode 100644 .github/workflows/firebase-app-distribution.yml create mode 100644 .github/workflows/version-tag-on-merge.yml diff --git a/.github/workflows/firebase-app-distribution.yml b/.github/workflows/firebase-app-distribution.yml new file mode 100644 index 00000000..5d669dda --- /dev/null +++ b/.github/workflows/firebase-app-distribution.yml @@ -0,0 +1,66 @@ +name: Firebase App Distribution + +on: + push: + tags: [ "v*" ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + distribute: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: Prezel + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '21' + cache: 'gradle' + cache-dependency-path: | + Prezel/*.gradle* + Prezel/**/gradle-wrapper.properties + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Create local.properties + run: echo "${{ secrets.LOCAL_PROPERTIES_CONTENTS }}" > ./local.properties + + - name: Create google-services.json + run: | + cat <<'EOF' > ./app/google-services.json + ${{ secrets.GOOGLE_SERVICES_JSON }} + EOF + + - name: Prepare version metadata + run: | + echo "ANDROID_VERSION_CODE=${GITHUB_RUN_NUMBER}" >> "$GITHUB_ENV" + echo "ANDROID_VERSION_NAME=${GITHUB_REF_NAME#v}" >> "$GITHUB_ENV" + + - name: Build Debug APK + run: ./gradlew assembleDebug --build-cache --parallel + + - name: Upload to Firebase App Distribution + uses: wzieba/Firebase-Distribution-Github-Action@v1 + with: + appId: ${{ vars.FIREBASE_APP_ID }} + serviceCredentialsFileContent: ${{ secrets.CREDENTIAL_FILE_CONTENT }} + groups: ${{ vars.FIREBASE_APP_DISTRIBUTION_GROUPS }} + releaseNotes: | + Tag: ${{ github.ref_name }} + Commit: ${{ github.sha }} + Actor: ${{ github.actor }} + Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + file: ./Prezel/app/build/outputs/apk/debug/app-debug.apk diff --git a/.github/workflows/version-tag-on-merge.yml b/.github/workflows/version-tag-on-merge.yml new file mode 100644 index 00000000..315cd9f4 --- /dev/null +++ b/.github/workflows/version-tag-on-merge.yml @@ -0,0 +1,83 @@ +name: Version Tag On Merge + +on: + pull_request: + branches: [ "develop" ] + types: [ "closed" ] + +permissions: + contents: write + +jobs: + tag-version: + if: ${{ github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' }} + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Determine next version tag + env: + PR_LABELS_JSON: ${{ toJson(github.event.pull_request.labels.*.name) }} + TARGET_SHA: ${{ github.event.pull_request.merge_commit_sha }} + run: | + set -euo pipefail + + git fetch --tags --force + + existing_tag="$(git tag --points-at "$TARGET_SHA" --list 'v*' | sort -V | tail -n 1)" + if [ -n "$existing_tag" ]; then + echo "TAG_NAME=$existing_tag" >> "$GITHUB_ENV" + echo "TAG_ALREADY_EXISTS=true" >> "$GITHUB_ENV" + exit 0 + fi + + bump="patch" + if [[ "$PR_LABELS_JSON" == *'"major"'* ]]; then + bump="major" + elif [[ "$PR_LABELS_JSON" == *'"minor"'* ]]; then + bump="minor" + elif [[ "$PR_LABELS_JSON" == *'"patch"'* ]]; then + bump="patch" + fi + + latest_tag="$(git tag --list 'v*' | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | tail -n 1 || true)" + latest_tag="${latest_tag:-v0.0.0}" + version="${latest_tag#v}" + + IFS='.' read -r major minor patch <<< "$version" + + case "$bump" in + major) + major=$((major + 1)) + minor=0 + patch=0 + ;; + minor) + minor=$((minor + 1)) + patch=0 + ;; + patch) + patch=$((patch + 1)) + ;; + esac + + echo "TAG_NAME=v${major}.${minor}.${patch}" >> "$GITHUB_ENV" + echo "TAG_ALREADY_EXISTS=false" >> "$GITHUB_ENV" + echo "BUMP_TYPE=$bump" >> "$GITHUB_ENV" + + - name: Create version tag + if: ${{ env.TAG_ALREADY_EXISTS == 'false' }} + env: + TARGET_SHA: ${{ github.event.pull_request.merge_commit_sha }} + run: | + set -euo pipefail + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + git tag -a "$TAG_NAME" "$TARGET_SHA" -m "Release $TAG_NAME" + git push origin "$TAG_NAME" diff --git a/Prezel/app/build.gradle.kts b/Prezel/app/build.gradle.kts index 7146cf96..f4751910 100644 --- a/Prezel/app/build.gradle.kts +++ b/Prezel/app/build.gradle.kts @@ -2,11 +2,26 @@ plugins { alias(libs.plugins.prezel.android.application.compose) alias(libs.plugins.prezel.hilt) alias(libs.plugins.kotlinx.serialization) + alias(libs.plugins.google.gms.google.services) } +val androidVersionCodeProvider = providers + .gradleProperty("ANDROID_VERSION_CODE") + .orElse(providers.environmentVariable("ANDROID_VERSION_CODE")) + .orElse("1") +val androidVersionNameProvider = providers + .gradleProperty("ANDROID_VERSION_NAME") + .orElse(providers.environmentVariable("ANDROID_VERSION_NAME")) + .orElse("0.1.0") + android { namespace = "com.team.prezel" + defaultConfig { + versionCode = androidVersionCodeProvider.get().toInt() + versionName = androidVersionNameProvider.get() + } + buildTypes { debug { isMinifyEnabled = false diff --git a/Prezel/build.gradle.kts b/Prezel/build.gradle.kts index 80ba2255..df024318 100644 --- a/Prezel/build.gradle.kts +++ b/Prezel/build.gradle.kts @@ -9,6 +9,7 @@ plugins { alias(libs.plugins.detekt) apply true alias(libs.plugins.hilt) apply false alias(libs.plugins.ksp) apply false + alias(libs.plugins.google.gms.google.services) apply false } subprojects { diff --git a/Prezel/gradle/libs.versions.toml b/Prezel/gradle/libs.versions.toml index 695cab9c..27fbe390 100644 --- a/Prezel/gradle/libs.versions.toml +++ b/Prezel/gradle/libs.versions.toml @@ -29,6 +29,7 @@ kotlinxSerialization = "1.9.0" kakao = "2.23.2" lottie = "6.6.7" balloonCompose = "1.7.6" +googleGmsGoogleServices = "4.4.4" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -113,6 +114,7 @@ prezel-android-feature-impl = { id = "prezel.android.feature.impl" } prezel-android-feature-api = { id = "prezel.android.feature.api" } prezel-hilt = { id = "prezel.hilt" } prezel-jvm-library = { id = "prezel.jvm.library" } +google-gms-google-services = { id = "com.google.gms.google-services", version.ref = "googleGmsGoogleServices" } [bundles] android-compose = [ From 8d1d8f6e32620681e016b14f5dff8186fff993bc Mon Sep 17 00:00:00 2001 From: moondev03 Date: Mon, 1 Jun 2026 02:35:05 +0900 Subject: [PATCH 2/3] ci: inject google services config in PR builds --- .github/workflows/android-pr-ci.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/android-pr-ci.yaml b/.github/workflows/android-pr-ci.yaml index 34d1da9b..5070f801 100644 --- a/.github/workflows/android-pr-ci.yaml +++ b/.github/workflows/android-pr-ci.yaml @@ -38,6 +38,12 @@ jobs: - name: Create local.properties run: echo "${{ secrets.LOCAL_PROPERTIES_CONTENTS }}" > ./local.properties + - name: Create google-services.json + run: | + cat <<'EOF' > ./app/google-services.json + ${{ secrets.GOOGLE_SERVICES_JSON }} + EOF + - name: Run Ktlint run: ./gradlew ktlintCheck --build-cache --parallel From f74ea607ed8fa893510cb0bbf067815a2de31096 Mon Sep 17 00:00:00 2001 From: moondev03 Date: Mon, 1 Jun 2026 02:41:40 +0900 Subject: [PATCH 3/3] ci: notify Discord on distribution results --- .../workflows/firebase-app-distribution.yml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.github/workflows/firebase-app-distribution.yml b/.github/workflows/firebase-app-distribution.yml index 5d669dda..38015e14 100644 --- a/.github/workflows/firebase-app-distribution.yml +++ b/.github/workflows/firebase-app-distribution.yml @@ -64,3 +64,52 @@ jobs: Actor: ${{ github.actor }} Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} file: ./Prezel/app/build/outputs/apk/debug/app-debug.apk + + - name: Send Discord Notification + if: always() + env: + DISCORD_WEBHOOK: ${{ secrets.DISTRIBUTION_DISCORD_HOOK_URL }} + STATUS_TITLE: ${{ job.status == 'success' && '✅ Firebase Debug 배포 성공' || '❌ Firebase Debug 배포 실패' }} + STATUS_COLOR: ${{ job.status == 'success' && '3066993' || '15158332' }} + BUILD_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + EVENT_TIMESTAMP: ${{ github.event.head_commit.timestamp || github.event.repository.pushed_at }} + run: | + if [ -z "$DISCORD_WEBHOOK" ]; then + echo "DISTRIBUTION_DISCORD_HOOK_URL is not set. Skipping Discord notification." + exit 0 + fi + + curl -H "Content-Type: application/json" -X POST -d "$(cat <" + }, + { + "name": "👥 Tester Group", + "value": "${{ vars.FIREBASE_APP_DISTRIBUTION_GROUPS }}" + }, + { + "name": "🔗 Action Log", + "value": "[바로가기]($BUILD_URL)" + } + ], + "footer": { + "text": "Prezel Firebase Distribution" + }, + "timestamp": "$EVENT_TIMESTAMP" + } + ] + } + EOF + )" "$DISCORD_WEBHOOK"