Skip to content

Add tag-based Firebase distribution pipeline#145

Merged
moondev03 merged 3 commits into
developfrom
feat/firebase-distribution
May 31, 2026
Merged

Add tag-based Firebase distribution pipeline#145
moondev03 merged 3 commits into
developfrom
feat/firebase-distribution

Conversation

@moondev03
Copy link
Copy Markdown
Member

@moondev03 moondev03 commented May 31, 2026

📌 작업 내용

  • PR merge label 기준으로 semantic version tag를 자동 생성하도록 GitHub Actions를 추가했습니다.
  • Firebase App Distribution 배포를 develop push 기반에서 vX.Y.Z tag push 기반으로 전환했습니다.
  • CI에서 google-services.json을 secret으로 주입하도록 바꿨습니다.
  • 배포 성공/실패 결과를 Discord webhook으로 전송하도록 추가했습니다.

🧩 관련 이슈


📸 스크린샷


📢 Notes

  • 버전 label 우선순위는 major > minor > patch 입니다.
  • label이 없으면 자동으로 patch bump 됩니다.
  • Firebase 배포는 이제 PR merge -> tag 생성 -> tag push -> distribution 플로우로 동작합니다.

Summary by CodeRabbit

릴리스 노트

  • 신규 기능

    • Firebase App Distribution을 통한 앱 배포 자동화 추가
  • 작업(Chores)

    • Google 서비스 플러그인 통합 구성 완료
    • PR 병합 시 자동 버전 태깅 워크플로우 추가
    • CI 파이프라인에서 서명 및 구성 파일 자동 생성 기능 적용
    • Gradle 버전 관리 시스템 개선

@moondev03 moondev03 self-assigned this May 31, 2026
@moondev03 moondev03 requested a review from HamBeomJoon as a code owner May 31, 2026 17:46
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 31, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

PR은 Google Services 플러그인을 Gradle에 통합하고, 버전 관리를 동적으로 처리하며, 버전 태그 자동 생성과 Firebase 배포 자동화를 위한 두 개의 새로운 GitHub Actions 워크플로우를 추가합니다.

Changes

CI/CD 및 빌드 자동화

Layer / File(s) Summary
Google Services 플러그인 설정
Prezel/gradle/libs.versions.toml, Prezel/build.gradle.kts, Prezel/app/build.gradle.kts
Google Services 플러그인 com.google.gms:google-services v4.4.4을 버전 카탈로그에 등록하고, 루트 Gradle에서 알리아스로 선언한 후 앱 모듈에 적용합니다.
버전 관리 자동화 및 태깅
Prezel/app/build.gradle.kts, .github/workflows/version-tag-on-merge.yml
앱 모듈에서 ANDROID_VERSION_CODE/ANDROID_VERSION_NAME를 Gradle 속성→환경변수→기본값 순으로 조회하는 provider를 추가하고, develop 브랜치로의 PR 병합 시 PR 라벨(major/minor/patch)에 따라 자동으로 버전 태그를 생성하여 푸시합니다.
PR CI에 google-services.json 생성 추가
.github/workflows/android-pr-ci.yaml
기존 Android PR CI 워크플로우에 secrets.GOOGLE_SERVICES_JSON으로부터 Prezel/app/google-services.json 파일을 생성하는 단계를 추가합니다.
Firebase App Distribution 배포 워크플로우
.github/workflows/firebase-app-distribution.yml
버전 태그(v*) 푸시 이벤트 시 실행되는 새로운 워크플로우로, 빌드 환경(JDK 21, Gradle 캐시) 설정 후 디버그 APK를 빌드하고, Firebase App Distribution에 테스터 그룹과 함께 업로드하며, 배포 결과를 Discord 웹훅을 통해 알립니다.

Possibly related PRs

  • Team-Prezel/Prezel-Android#15: android-pr-ci.yaml 워크플로우의 확장으로 local.propertiesapp/google-services.json 생성 설정과 관련이 있습니다.

Suggested labels

🧹 chore

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 PR의 핵심 변경사항인 태그 기반 Firebase 배포 파이프라인 추가를 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명은 템플릿의 모든 필수 섹션을 포함하고 있으며, 작업 내용과 주요 사항들이 명확하게 기술되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
.github/workflows/firebase-app-distribution.yml (2)

82-100: ⚡ Quick win

curl JSON 페이로드에 GitHub 표현식을 직접 보간하지 마세요 (template injection).

cat <<EOF(따옴표 없는 구분자) 내부에 ${{ github.ref_name }}(Line 92), ${{ env.ANDROID_VERSION_NAME }}(Line 96), ${{ vars.FIREBASE_APP_DISTRIBUTION_GROUPS }}(Line 100)이 직접 펼쳐집니다. 값에 "나 셸/JSON 메타문자가 포함되면 페이로드가 깨지거나 코드 주입으로 이어질 수 있습니다. 이미 STATUS_TITLE 등은 env로 처리하고 있으니 동일하게 env 변수로 전달한 뒤 셸 변수로 참조하세요.

🛡️ env 변수 사용으로 변경
         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 }}
+          TAG_NAME: ${{ github.ref_name }}
+          TESTER_GROUPS: ${{ vars.FIREBASE_APP_DISTRIBUTION_GROUPS }}

그리고 JSON 본문에서 ${{ github.ref_name }}$TAG_NAME, ${{ env.ANDROID_VERSION_NAME }}$ANDROID_VERSION_NAME, ${{ vars.FIREBASE_APP_DISTRIBUTION_GROUPS }}$TESTER_GROUPS로 참조하세요. 가능하면 jq -n으로 페이로드를 생성하면 이스케이프가 안전하게 처리됩니다.

zizmor가 Line 92/96/100을 template-injection으로 플래그했습니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/firebase-app-distribution.yml around lines 82 - 100, The
here-doc JSON payload currently interpolates GitHub expressions directly (e.g.,
${{ github.ref_name }}, ${{ env.ANDROID_VERSION_NAME }}, ${{
vars.FIREBASE_APP_DISTRIBUTION_GROUPS }}) which risks template/JSON injection;
instead export those values into environment variables (e.g., TAG_NAME,
ANDROID_VERSION_NAME, TESTER_GROUPS and keep STATUS_TITLE/STATUS_COLOR as envs)
in the workflow and reference the shell vars ($TAG_NAME, $ANDROID_VERSION_NAME,
$TESTER_GROUPS) inside the payload, or preferably build the payload with a safe
JSON tool like jq -n to ensure proper escaping; update the curl invocation and
payload construction (symbols to update: STATUS_TITLE, STATUS_COLOR, TAG_NAME,
ANDROID_VERSION_NAME, ANDROID_VERSION_CODE, TESTER_GROUPS) so no GitHub
expressions are expanded inside an unquoted here-doc.

20-33: ⚖️ Poor tradeoff

서드파티/외부 액션을 커밋 SHA로 고정하는 것을 권장합니다.

actions/checkout@v5, actions/setup-java@v5, wzieba/Firebase-Distribution-Github-Action@v1이 가변 태그로 참조되어 있습니다. 배포 워크플로우는 시크릿(서비스 계정 자격증명, 웹훅)에 접근하므로 공급망 보안 차원에서 커밋 해시 고정을 권장합니다. zizmor도 unpinned-uses로 플래그했습니다.

Also applies to: 56-56

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/firebase-app-distribution.yml around lines 20 - 33, The
workflow is using unpinned third-party actions (actions/checkout@v5,
actions/setup-java@v5, wzieba/Firebase-Distribution-Github-Action@v1) which
should be fixed by replacing the tag refs with their corresponding commit SHAs;
locate each usage in the workflow and swap the tag (e.g., `@v5` or `@v1`) for the
full commit SHA from the action's upstream repository, verify the SHA matches
the intended release, and update any uses/ lines so the workflow references the
exact commit to avoid supply-chain drift.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/firebase-app-distribution.yml:
- Line 75: Normalize the EVENT_TIMESTAMP before embedding: capture
EVENT_TIMESTAMP (the existing ENV var) in the run step, convert it to UTC
ISO8601 with a Z suffix (e.g. use date -u -d "$EVENT_TIMESTAMP"
'+%Y-%m-%dT%H:%M:%SZ') and export that normalized value (e.g.
NORMALIZED_TIMESTAMP) so the Discord embed uses NORMALIZED_TIMESTAMP instead of
EVENT_TIMESTAMP; this ensures head_commit.timestamp offsets are converted to the
required "...Z" UTC format when the embed timestamp is sent.

In @.github/workflows/version-tag-on-merge.yml:
- Around line 17-20: The workflow currently uses actions/checkout@v5 without a
token, causing the default GITHUB_TOKEN to be used so the subsequent git push
origin "$TAG_NAME" is treated as a GITHUB_TOKEN-originated push and will not
trigger firebase-app-distribution.yml; update the checkout step in
version-tag-on-merge.yml (the actions/checkout@v5 block where fetch-depth: 0 is
set) to include with: token: ${{ secrets.TAG_PUSH_TOKEN }} and ensure
persist-credentials: true (or set persist-credentials appropriately) so the tag
push (git push origin "$TAG_NAME") uses the PAT/GitHub App token instead of the
default GITHUB_TOKEN.

In `@Prezel/app/build.gradle.kts`:
- Line 5: The build applies the google-services plugin via
alias(libs.plugins.google.gms.google.services) but does not set googleServices {
missingGoogleServicesStrategy = ... }, which causes builds to fail when
app/google-services.json is absent; update Prezel/app/build.gradle.kts to add a
googleServices block (e.g., missingGoogleServicesStrategy =
com.google.gms.googleservices.DefaultPlugin.MissingGoogleServicesStrategy.WARN
or IGNORE) adjacent to the plugin application to avoid hard ERRORs, and also
update the repo README/local setup docs to describe how/where to obtain Place
the google-services.json (Prezel/app/google-services.json) for local development
and note that CI workflows generate it under Prezel so local dev must add it
manually.

---

Nitpick comments:
In @.github/workflows/firebase-app-distribution.yml:
- Around line 82-100: The here-doc JSON payload currently interpolates GitHub
expressions directly (e.g., ${{ github.ref_name }}, ${{ env.ANDROID_VERSION_NAME
}}, ${{ vars.FIREBASE_APP_DISTRIBUTION_GROUPS }}) which risks template/JSON
injection; instead export those values into environment variables (e.g.,
TAG_NAME, ANDROID_VERSION_NAME, TESTER_GROUPS and keep STATUS_TITLE/STATUS_COLOR
as envs) in the workflow and reference the shell vars ($TAG_NAME,
$ANDROID_VERSION_NAME, $TESTER_GROUPS) inside the payload, or preferably build
the payload with a safe JSON tool like jq -n to ensure proper escaping; update
the curl invocation and payload construction (symbols to update: STATUS_TITLE,
STATUS_COLOR, TAG_NAME, ANDROID_VERSION_NAME, ANDROID_VERSION_CODE,
TESTER_GROUPS) so no GitHub expressions are expanded inside an unquoted
here-doc.
- Around line 20-33: The workflow is using unpinned third-party actions
(actions/checkout@v5, actions/setup-java@v5,
wzieba/Firebase-Distribution-Github-Action@v1) which should be fixed by
replacing the tag refs with their corresponding commit SHAs; locate each usage
in the workflow and swap the tag (e.g., `@v5` or `@v1`) for the full commit SHA from
the action's upstream repository, verify the SHA matches the intended release,
and update any uses/ lines so the workflow references the exact commit to avoid
supply-chain drift.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e3455249-3ebc-493e-940a-3b7c164b8964

📥 Commits

Reviewing files that changed from the base of the PR and between e3831de and f74ea60.

📒 Files selected for processing (6)
  • .github/workflows/android-pr-ci.yaml
  • .github/workflows/firebase-app-distribution.yml
  • .github/workflows/version-tag-on-merge.yml
  • Prezel/app/build.gradle.kts
  • Prezel/build.gradle.kts
  • Prezel/gradle/libs.versions.toml

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 }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the workflow file and print the relevant section around line ~75
FILE=".github/workflows/firebase-app-distribution.yml"
if [ -f "$FILE" ]; then
  echo "== $FILE (around line 60-90) =="
  nl -ba "$FILE" | sed -n '60,95p'
else
  echo "File not found: $FILE" >&2
  exit 1
fi

Repository: Team-Prezel/Prezel-Android

Length of output: 205


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/firebase-app-distribution.yml"
if [ ! -f "$FILE" ]; then
  echo "File not found: $FILE" >&2
  exit 1
fi

echo "== $FILE (around line 60-95) =="
awk 'NR>=60 && NR<=95 {printf "%d:%s\n", NR, $0}' "$FILE"

Repository: Team-Prezel/Prezel-Android

Length of output: 1873


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE=".github/workflows/firebase-app-distribution.yml"

echo "== $FILE (top 1-70) =="
awk 'NR>=1 && NR<=70 {printf "%d:%s\n", NR, $0}' "$FILE"

echo
echo "== $FILE (95-160) =="
awk 'NR>=95 && NR<=160 {printf "%d:%s\n", NR, $0}' "$FILE"

Repository: Team-Prezel/Prezel-Android

Length of output: 3258


🌐 Web query:

Discord embed timestamp format ISO8601 required

💡 Result:

When adding a timestamp to a Discord embed, the API strictly requires an ISO 8601 formatted string [1][2]. The expected format is a string representing UTC time [3][1]. While often referred to as ISO 8601, it is implemented as a specific subset of the standard, typically following the pattern YYYY-MM-DDTHH:MM:SS.MSSZ [3][1]. The Z suffix is essential to indicate Zulu (UTC) time [1]. Key technical considerations: - Data Type: The timestamp field in the embed object must be a string, not a Unix integer or other numeric type [1][2]. - Timezone: The input should be provided in UTC. The Discord client automatically adjusts the displayed time based on the local timezone settings of the viewing user [3][4][1]. - Format Constraints: Avoid using timezone-aware variations with offsets (such as +00:00 or +01:00) that deviate from the standard Z-suffix format, as these may cause API errors [5][6]. For developers, common practice is to use language-specific methods to generate this string, such as new Date.toISOString in JavaScript [7]. Passing raw timestamps or objects directly without conversion to this specific string format will result in a validation error [1][2].

Citations:


🌐 Web query:

GitHub push event payload head_commit timestamp null pushed_at format

💡 Result:

In the GitHub “push” webhook payload, head_commit is typed as object or null [1][2]. When it’s present, its timestamp field is an ISO 8601 / RFC 3339 date-time string (for example 2018-06-19T19:03:12-07:00) [3]. So: - head_commit.timestamp format: ISO 8601 / RFC 3339 date-time string like YYYY-MM-DDTHH:MM:SS±HH:MM (or Z) [3]. - head_commit can be null: yes (object or null) [1][2]. - If head_commit is null, use the webhook’s commits[] array (each commit object includes its own timestamp) as the alternative source of commit times [1]. Regarding pushed_at: that field appears in other GitHub API contexts (e.g., repository REST responses) and is not the timestamp field inside the webhook’s head_commit object [4].

Citations:


🌐 Web query:

GitHub Actions github.event.repository.pushed_at type ISO8601

💡 Result:

In GitHub Actions, the github.event context provides access to the full webhook payload of the event that triggered the workflow run [1][2]. When this event includes a repository object, the pushed_at property is represented as a string containing an ISO 8601-formatted timestamp [3][4]. The format follows the standard UTC timestamp convention: YYYY-MM-DDTHH:MM:SSZ [3]. Key details regarding this field include: - Context Availability: The structure of github.event depends entirely on the specific event type that triggered the workflow (e.g., push, pull_request) [1][2]. - Data Type: While it is parsed as a string in the JSON payload, it represents a point in time [3][4]. - Meaning: The pushed_at timestamp indicates the date and time of the last commit pushed to the repository [3]. It is distinct from updated_at, which reflects changes to the repository object itself (such as updates to the description, homepage, or primary language) [3]. Because github.event is a direct mirror of the GitHub webhook payload for that event, it adheres to the data formats defined in the GitHub REST API and Webhook documentation [1][2].

Citations:


🌐 Web query:

GitHub push webhook payload repository.pushed_at format ISO8601

💡 Result:

In the GitHub API and webhook payloads, the pushed_at field is formatted as an ISO 8601 string, typically in the format YYYY-MM-DDTHH:MM:SSZ [1][2]. This timestamp represents the date and time of the last commit pushed to the repository [1][2]. Because GitHub standardizes its REST API and webhook timestamps to this ISO 8601 format, it is suitable for direct parsing by most modern programming languages and data processing tools [3][1].

Citations:


🌐 Web query:

Discord embed timestamp accepts ISO8601 with timezone offset -07:00

💡 Result:

Discord embed timestamp does not reliably accept ISO8601 timezone-offset forms like -07:00 (e.g., 2018-01-01T00:00:00-07:00) in the Discord API for embed timestamps. Evidence: the Discord API embed timestamp appears to be a restricted ISO8601/RFC3339 subset that (per documented discussion) does not accept timezone-aware ISO8601 offsets such as +00:00 or +01:00, and only accepts Z or no timezone indicator (examples treated as valid are essentially the form with an optional Z). Specifically, a Discord API docs issue notes the embed timestamp format matches a regex subset where the timezone component is (Z)? and states it “doesn’t accept timezone aware ISO8601, e.g. +00:00 or +01:00 etc.” [1][2]. Practical guidance: - Prefer Z (UTC) timestamps, e.g. 2026-05-31T18:23:45.000Z. - If you have a -07:00 timestamp, convert it to UTC before sending so you end up with a Z string. Caveat: some third-party client libraries/documentation may imply broader ISO8601 support, but the Discord embed timestamp strictness issue above indicates offset forms are not consistently accepted by the API for embeds. [1][2][3]

Citations:


🌐 Web query:

discord webhook embed timestamp valid ISO8601 Z vs offset

💡 Result:

Discord webhooks and API objects generally expect timestamps in ISO 8601 format [1][2]. For the timestamp field in an embed object, the API accepts ISO 8601 strings [1]. Regarding the specific format, the industry standard and Discord's expected input for ISO 8601 timestamps is a string that represents the date and time, typically ending in 'Z' (indicating UTC) [1][3]. While ISO 8601 allows for both 'Z' and numerical UTC offsets (e.g., +00:00), using 'Z' is the standard way to denote UTC [4]. Some implementation issues in third-party libraries have historically shown that passing an explicit offset (like +00:00) may be handled differently than 'Z' depending on how the underlying JSON serializer treats the string [5]. To ensure maximum compatibility and avoid potential serialization errors, it is recommended to format your timestamp as a UTC string ending with 'Z' [3]. In summary: - The timestamp field in Discord embeds accepts ISO 8601 format [1]. - You should use the 'Z' suffix to denote UTC rather than adding a numerical offset (like +00:00) to ensure consistent behavior across different environments [3][4]. - Always format as YYYY-MM-DDTHH:MM:SSZ [3].

Citations:


Discord embed timestamp는 UTC ISO8601(...Z)로 정규화 필요

  • .github/workflows/firebase-app-distribution.yml에서 EVENT_TIMESTAMP: ${{ github.event.head_commit.timestamp || github.event.repository.pushed_at }}를 그대로 embed timestamp에 넣고 있는데, repository.pushed_at은 Unix epoch 정수가 아니라 ISO8601 문자열이라 해당 우려는 낮습니다.
  • 하지만 head_commit.timestamp는 RFC3339의 타임존 오프셋(-07:00 등)을 포함할 수 있고 Discord embed timestampZ 형태만 안정적으로 허용하므로, run 단계에서 date -u -d "$EVENT_TIMESTAMP" '+%Y-%m-%dT%H:%M:%SZ'처럼 UTC로 변환해 넣는 것을 권장합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/firebase-app-distribution.yml at line 75, Normalize the
EVENT_TIMESTAMP before embedding: capture EVENT_TIMESTAMP (the existing ENV var)
in the run step, convert it to UTC ISO8601 with a Z suffix (e.g. use date -u -d
"$EVENT_TIMESTAMP" '+%Y-%m-%dT%H:%M:%SZ') and export that normalized value (e.g.
NORMALIZED_TIMESTAMP) so the Discord embed uses NORMALIZED_TIMESTAMP instead of
EVENT_TIMESTAMP; this ensures head_commit.timestamp offsets are converted to the
required "...Z" UTC format when the embed timestamp is sent.

Comment on lines +17 to +20
- name: Checkout repository
uses: actions/checkout@v5
with:
fetch-depth: 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🌐 Web query:

GitHub Actions default GITHUB_TOKEN push does not trigger workflow runs

💡 Result:

GitHub Actions is intentionally designed so that events triggered by the default GITHUB_TOKEN do not create new workflow runs [1][2][3]. This security feature prevents infinite loops and accidental recursive workflow execution [1][2][4]. Key details regarding this behavior: - Scope and Exception: When you perform an action (such as a git push) using the GITHUB_TOKEN, GitHub will not trigger any workflows that are configured to run on that specific event (e.g., on: push) [1][2][3]. Notable exceptions to this rule are the workflow_dispatch and repository_dispatch events, which can still be triggered by the GITHUB_TOKEN [2][3][5]. - Solution: If you require a workflow to be triggered by an action performed within another workflow, you must use a different authentication token that is not the default GITHUB_TOKEN [1][6][4]. Common alternatives include: - Personal Access Token (PAT): A classic or fine-grained PAT with the necessary repository permissions [1][4]. - GitHub App Token: A token generated from a GitHub App installation, which is often considered a more secure, principle-of-least-privilege approach [6][7]. - Implementation: When using an alternative token with the actions/checkout action, you must explicitly provide it to ensure your git operations use that token rather than the default one [1][8][9]: - uses: actions/checkout@v4 with: token: ${{ secrets.YOUR_PAT_OR_APP_TOKEN }} If you do not use the correct token in the checkout step, the actions/checkout action may persist the default GITHUB_TOKEN in the local repository configuration, causing subsequent git commands to authenticate as the default token despite other configurations [2][4].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the workflows
ls -la .github/workflows || true
rg -n "version-tag-on-merge\.yml|version-tag-on-merge" .github/workflows -S || true

# Show the full relevant sections with line numbers for version-tag-on-merge.yml
if [ -f .github/workflows/version-tag-on-merge.yml ]; then
  echo "==== version-tag-on-merge.yml (head) ===="
  nl -ba .github/workflows/version-tag-on-merge.yml | head -n 120
fi

# Find firebase-app-distribution workflow and show its trigger config
fb_file="$(ls .github/workflows | rg -n "firebase-app-distribution" || true)"
echo "==== Candidate firebase-app-distribution workflow files ===="
ls .github/workflows | rg -i "firebase.*distribution" || true

for f in .github/workflows/*; do
  if [ -f "$f" ] && rg -q "firebase-app-distribution" "$f"; then
    echo "==== file: $f (trigger section) ===="
    nl -ba "$f" | sed -n '1,220p'
  fi
done

# If there is a file named exactly firebase-app-distribution.yml, dump it
if [ -f .github/workflows/firebase-app-distribution.yml ]; then
  echo "==== firebase-app-distribution.yml ===="
  nl -ba .github/workflows/firebase-app-distribution.yml | head -n 260
fi

# Generic search for tags trigger
rg -n "on:\s*push:|push:\s*tags|tags:" .github/workflows -S || true

Repository: Team-Prezel/Prezel-Android

Length of output: 572


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Workflows =="
ls -la .github/workflows

echo "== version-tag-on-merge.yml =="
# show first 200 lines with line numbers
cat -n .github/workflows/version-tag-on-merge.yml | head -n 220

echo "== firebase-app-distribution.yml (top/trigger) =="
# show first 260 lines with line numbers
cat -n .github/workflows/firebase-app-distribution.yml | head -n 260

echo "== Find git push / tags usage in version-tag-on-merge.yml =="
rg -n "git push|push origin|TAG_NAME|tags|refs/tags" .github/workflows/version-tag-on-merge.yml -S || true

echo "== Find checkout token/persist-credentials in version-tag-on-merge.yml =="
rg -n "actions/checkout|persist-credentials|token:" .github/workflows/version-tag-on-merge.yml -S || true

echo "== Find push: tags trigger in firebase-app-distribution.yml =="
rg -n "on:\s*push|push:\s*tags|tags:" .github/workflows/firebase-app-distribution.yml -S || true

echo "== Also search for other workflows triggered by tags push =="
rg -n "push:\s*tags" .github/workflows -S || true

Repository: Team-Prezel/Prezel-Android

Length of output: 8902


기본 GITHUB_TOKEN으로 푸시한 태그는 firebase-app-distribution.yml을 트리거하지 못합니다.

  • version-tag-on-merge.ymlactions/checkout@v5token:을 지정하지 않아 기본 GITHUB_TOKEN이 로컬 자격 증명으로 사용되고, git push origin "$TAG_NAME"(태그 푸시)도 그 토큰으로 수행됩니다.
  • GitHub는 GITHUB_TOKEN이 발생시킨 push 이벤트(태그 포함)로는 다른 워크플로우 실행을 만들지 않도록 제한하므로, firebase-app-distribution.ymlon: push: tags: ["v*"] 트리거 체인이 끊깁니다.

TAG_PUSH_TOKEN(PAT) 또는 GitHub App 토큰을 사용하도록 version-tag-on-merge.ymlactions/checkoutwith: token: ${{ secrets... }}를 명시(필요 시 persist-credentials: true도 함께)하고, 해당 토큰으로 태그 푸시가 되게 변경하세요.

🧰 Tools
🪛 zizmor (1.25.2)

[warning] 17-20: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 18-18: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/version-tag-on-merge.yml around lines 17 - 20, The
workflow currently uses actions/checkout@v5 without a token, causing the default
GITHUB_TOKEN to be used so the subsequent git push origin "$TAG_NAME" is treated
as a GITHUB_TOKEN-originated push and will not trigger
firebase-app-distribution.yml; update the checkout step in
version-tag-on-merge.yml (the actions/checkout@v5 block where fetch-depth: 0 is
set) to include with: token: ${{ secrets.TAG_PUSH_TOKEN }} and ensure
persist-credentials: true (or set persist-credentials appropriately) so the tag
push (git push origin "$TAG_NAME") uses the PAT/GitHub App token instead of the
default GITHUB_TOKEN.

alias(libs.plugins.prezel.android.application.compose)
alias(libs.plugins.prezel.hilt)
alias(libs.plugins.kotlinx.serialization)
alias(libs.plugins.google.gms.google.services)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# google-services.json 관련 셋업 문서/언급 확인
rg -n -i 'google-services.json' --glob '!*.gradle*' --glob '!**/.github/**'

Repository: Team-Prezel/Prezel-Android

Length of output: 52


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) 확인 대상 build.gradle.kts의 관련 구간 출력
echo "== Prezel/app/build.gradle.kts (lines ~1-80) =="
nl -ba Prezel/app/build.gradle.kts | sed -n '1,120p'

# 2) repo 전체에서 google-services.json / googleServices 블록 / MissingGoogleServicesStrategy 사용처 탐색
echo
echo "== rg for google-services.json =="
rg -n --hidden -S -i 'google-services\.json' .

echo
echo "== rg for googleServices { =="
rg -n --hidden -S -i 'googleServices\s*\{' .

echo
echo "== rg for MissingGoogleServicesStrategy =="
rg -n --hidden -S -i 'MissingGoogleServicesStrategy' .

echo
echo "== rg for missingGoogleServicesStrategy =="
rg -n --hidden -S -i 'missingGoogleServicesStrategy' .

# 3) CI/워크플로우에서 파일을 생성/복사하는지 확인 (GitHub Actions)
echo
echo "== rg for google-services within .github/ =="
rg -n --hidden -S -i 'google-services' .github || true

Repository: Team-Prezel/Prezel-Android

Length of output: 179


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 필요한 경우, google-services plugin 적용이 다른 모듈/루트에도 있는지 빠르게 확인
echo "== rg for alias(libs.plugins.google.gms.google.services) =="
rg -n --hidden -S 'google\.services' Prezel || true

echo
echo "== rg for com.google.gms:google-services =="
rg -n --hidden -S 'com\.google\.gms:google-services' . || true

Repository: Team-Prezel/Prezel-Android

Length of output: 346


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# build.gradle.kts 앞부분(플러그인/관련 설정 포함) 확인
echo "== Prezel/app/build.gradle.kts (1-120p) =="
cat -n Prezel/app/build.gradle.kts | sed -n '1,120p'

echo
echo "== googleServices 블록(googleServices { ... }) 유무: gradle 파일들 =="
rg -n --hidden -S -i 'googleServices\s*\{' Prezel -g'*.gradle*' -g'*.kts' || true

echo
echo "== MissingGoogleServicesStrategy / missingGoogleServicesStrategy 사용처 =="
rg -n --hidden -S -i 'MissingGoogleServicesStrategy|missingGoogleServicesStrategy' Prezel -g'*.gradle*' -g'*.kts' || true

echo
echo "== google-services.json 전체 문자열(문서/스크립트 포함) 검색 =="
rg -n --hidden -S -i 'google-services\.json' . || true

echo
echo "== GitHub Actions/워크플로우에서 google-services.json 생성/복사 흔적 =="
rg -n --hidden -S -i 'google-services\.json|googleServices' .github || true

Repository: Team-Prezel/Prezel-Android

Length of output: 4257


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== top-level dirs =="
ls -la

echo
echo "== settings.gradle.kts (있으면) =="
ls -ლა settings.gradle.kts 2>/dev/null || true
ls -la Prezel/settings.gradle.kts 2>/dev/null || true
[ -f settings.gradle.kts ] && sed -n '1,200p' settings.gradle.kts || true
[ -f Prezel/settings.gradle.kts ] && sed -n '1,200p' Prezel/settings.gradle.kts || true

echo
echo "== .github/workflows: google-services.json 생성 스텝 =="
rg -n --hidden -S -i "Create google-services\.json|google-services\.json" .github/workflows || true

echo
echo "== workflow들이 어느 디렉토리에서 실행되는지 (working-directory 존재 여부) =="
rg -n --hidden -S -i "working-directory" .github/workflows || true

echo
echo "== .gitignore google-services.json 라인 =="
rg -n --hidden -S 'google-services\.json' .gitignore .gitignore* || true

Repository: Team-Prezel/Prezel-Android

Length of output: 4101


🌐 Web query:

Google Services Gradle plugin missingGoogleServicesStrategy default value ERROR

💡 Result:

The default value for missingGoogleServicesStrategy in the Google Services Gradle plugin is MissingGoogleServicesStrategy.ERROR [1]. This configuration option is used to define how the plugin should behave when the google-services.json file is missing for a specific build variant [1]. When set to its default (ERROR), the build will fail if the file is not found [1]. To change this behavior, you can configure the googleServices block in your build.gradle.kts (or build.gradle) file [1]. Valid options for missingGoogleServicesStrategy are: - IGNORE: The plugin will not attempt to process the JSON file and will not throw an error or warning [1]. - WARN: The plugin will print a warning but allow the build to continue [1]. - ERROR: The default behavior; the build will fail if the file is missing [1]. Example usage in build.gradle.kts: kotlin googleServices { missingGoogleServicesStrategy = MissingGoogleServicesStrategy.WARN } This is particularly useful in projects with multiple build variants or product flavors where not every variant requires Google Services or a google-services.json file [2][1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -i 'google-services\.json|google services|missingGoogleServicesStrategy|firebase' README.md scripts .github/workflows .github || true

Repository: Team-Prezel/Prezel-Android

Length of output: 2872


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .gitignore (google-services.json 포함 근처 20줄) =="
sed -n '1,120p' .gitignore | nl -ba | sed -n '20,60p'

echo
echo "== README.md google-services 관련 언급 (가능한 경우) =="
rg -n -i 'google-services\.json|google services|Firebase' README.md || true

echo
echo "== 추가: local 셋업 문서/스크립트에서 google-services.json 언급 =="
rg -n -i 'google-services\.json|google services' scripts .github/workflows || true

Repository: Team-Prezel/Prezel-Android

Length of output: 181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== .gitignore (google-services.json 포함 근처 20줄) =="
sed -n '20,45p' .gitignore

echo
echo "== README.md google-services/Firebase 관련 언급 =="
rg -n -i 'google-services\.json|google services|MissingGoogleServicesStrategy|Firebase' README.md || true

echo
echo "== scripts/ 내 언급 =="
rg -n -i 'google-services\.json|google services|MissingGoogleServicesStrategy|Firebase' scripts .github/workflows || true

Repository: Team-Prezel/Prezel-Android

Length of output: 1793


google-services.json 없으면 빌드가 실패할 수 있습니다

  • Prezel/app/build.gradle.kts에서 alias(libs.plugins.google.gms.google.services)(google-services 플러그인)을 적용했지만 googleServices { missingGoogleServicesStrategy = ... } 설정이 없어 기본이 ERROR입니다.
  • CI에서는 .github/workflows/android-pr-ci.yaml, .github/workflows/firebase-app-distribution.yml에서 working-directory: Prezel 기준으로 ./app/google-services.json(= Prezel/app/google-services.json)를 생성하므로, 로컬 개발이나 다른 빌드 경로에선 파일 준비가 누락되면 실패할 수 있습니다.
  • README 등 로컬 셋업 문서에 google-services.json 준비/다운로드 안내가 보이지 않아 추가가 필요합니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Prezel/app/build.gradle.kts` at line 5, The build applies the google-services
plugin via alias(libs.plugins.google.gms.google.services) but does not set
googleServices { missingGoogleServicesStrategy = ... }, which causes builds to
fail when app/google-services.json is absent; update Prezel/app/build.gradle.kts
to add a googleServices block (e.g., missingGoogleServicesStrategy =
com.google.gms.googleservices.DefaultPlugin.MissingGoogleServicesStrategy.WARN
or IGNORE) adjacent to the plugin application to avoid hard ERRORs, and also
update the repo README/local setup docs to describe how/where to obtain Place
the google-services.json (Prezel/app/google-services.json) for local development
and note that CI workflows generate it under Prezel so local dev must add it
manually.

@moondev03 moondev03 merged commit 09c824b into develop May 31, 2026
3 checks passed
@moondev03 moondev03 deleted the feat/firebase-distribution branch May 31, 2026 17:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants