Add tag-based Firebase distribution pipeline#145
Conversation
📝 WalkthroughWalkthroughPR은 Google Services 플러그인을 Gradle에 통합하고, 버전 관리를 동적으로 처리하며, 버전 태그 자동 생성과 Firebase 배포 자동화를 위한 두 개의 새로운 GitHub Actions 워크플로우를 추가합니다. ChangesCI/CD 및 빌드 자동화
Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.github/workflows/firebase-app-distribution.yml (2)
82-100: ⚡ Quick wincurl 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
📒 Files selected for processing (6)
.github/workflows/android-pr-ci.yaml.github/workflows/firebase-app-distribution.yml.github/workflows/version-tag-on-merge.ymlPrezel/app/build.gradle.ktsPrezel/build.gradle.ktsPrezel/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 }} |
There was a problem hiding this comment.
🧩 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
fiRepository: 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:
- 1: https://dominatetools.com/blog/discord-bot-embed-timestamp-anatomy/
- 2: https://stackoverflow.com/questions/60183529/discord-js-embed-timestamp-not-able-to-parse-a-unix-timestamp
- 3: https://birdie0.github.io/discord-webhooks-guide/structure/embed/timestamp.html
- 4: https://github.com/discordjs/guide/blob/67e127aa/guide/popular-topics/embeds.md
- 5: timestamp field of embed object is of type timestamp and not type date discord/discord-api-docs#291
- 6: timestamp field of embed object is of type timestamp and not type date discord/discord-api-docs#291
- 7: https://discordjs.guide/legacy/popular-topics/embeds
🌐 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:
- 1: https://docs.github.com/en/webhooks/webhook-events-and-payloads
- 2: https://docs.github.com/en/webhooks/webhook-events-and-payloads?actionType=added_to_repository
- 3: include head_commit in push webhooks if tag go-gitea/gitea#5266
- 4: https://stackoverflow.com/questions/15918588/github-api-v3-what-is-the-difference-between-pushed-at-and-updated-at
🌐 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:
- 1: https://github.com/github/docs/blob/main/content/actions/reference/workflows-and-actions/contexts.md
- 2: https://docs.github.com/en/actions/reference/workflows-and-actions/contexts
- 3: https://stackoverflow.com/questions/15918588/github-api-v3-what-is-the-difference-between-pushed-at-and-updated-at
- 4: pushed_at or created_at? llnl/scraper#27
🌐 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:
- 1: https://stackoverflow.com/questions/15918588/github-api-v3-what-is-the-difference-between-pushed-at-and-updated-at
- 2: pushed_at or created_at? llnl/scraper#27
- 3: https://dev.to/flowkithq/save-any-webhook-data-to-a-database-automatically-with-n8n-free-workflow-json-14lh
🌐 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:
- 1: timestamp field of embed object is of type timestamp and not type date discord/discord-api-docs#291
- 2: timestamp field of embed object is of type timestamp and not type date discord/discord-api-docs#291
- 3: https://birdie0.github.io/discord-webhooks-guide/structure/embed/timestamp.html
🌐 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:
- 1: timestamp field of embed object is of type timestamp and not type date discord/discord-api-docs#291
- 2: Timestamp data types are unclear discord/discord-api-docs#3132
- 3: https://devforum.roblox.com/t/how-to-get-the-discord-webhook-iso8601-timestamp/562870
- 4: https://stackoverflow.com/questions/35856437/iso-8601-date-time-format-combining-z-and-offset-of-0000
- 5: EmbedBuilder Timestamp ignores DateTimeOffset's Offset discord-net/Discord.Net#918
Discord embed timestamp는 UTC ISO8601(...Z)로 정규화 필요
.github/workflows/firebase-app-distribution.yml에서EVENT_TIMESTAMP: ${{ github.event.head_commit.timestamp || github.event.repository.pushed_at }}를 그대로 embedtimestamp에 넣고 있는데,repository.pushed_at은 Unix epoch 정수가 아니라 ISO8601 문자열이라 해당 우려는 낮습니다.- 하지만
head_commit.timestamp는 RFC3339의 타임존 오프셋(-07:00 등)을 포함할 수 있고 Discord embedtimestamp는Z형태만 안정적으로 허용하므로,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.
| - name: Checkout repository | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| fetch-depth: 0 |
There was a problem hiding this comment.
🧩 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:
- 1: https://stackoverflow.com/questions/67550727/push-event-doesnt-trigger-workflow-on-push-paths
- 2: https://stackoverflow.com/questions/73576785/github-workflow-fails-to-run-when-code-is-pushed-into-branch
- 3: https://stackoverflow.com/questions/78460233/how-to-avoid-bot-triggering-workflow-in-gha
- 4: https://stackoverflow.com/questions/76326444/prevent-recursive-workflow-triggering-on-merge-push-to-main-branch
- 5: https://winbuzzer.com/2026/05/26/megalodon-hit-5561-github-repos-through-malicious-workflows-xcxwbn/
- 6: https://code.dblock.org/2023/04/29/triggering-ci-from-pull-requests-and-force-pushes-in-github-actions.html
- 7: https://docs.github.com/actions/reference/authentication-in-a-workflow
- 8: https://stackoverflow.com/questions/77439861/push-from-github-actions-did-not-trigger-a-workflow
- 9: https://stackoverflow.com/questions/79512658/cant-trigger-push-workflow-when-push-happens-in-action
🏁 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 || trueRepository: 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 || trueRepository: Team-Prezel/Prezel-Android
Length of output: 8902
기본 GITHUB_TOKEN으로 푸시한 태그는 firebase-app-distribution.yml을 트리거하지 못합니다.
version-tag-on-merge.yml의actions/checkout@v5에token:을 지정하지 않아 기본GITHUB_TOKEN이 로컬 자격 증명으로 사용되고,git push origin "$TAG_NAME"(태그 푸시)도 그 토큰으로 수행됩니다.- GitHub는
GITHUB_TOKEN이 발생시킨push이벤트(태그 포함)로는 다른 워크플로우 실행을 만들지 않도록 제한하므로,firebase-app-distribution.yml의on: push: tags: ["v*"]트리거 체인이 끊깁니다.
TAG_PUSH_TOKEN(PAT) 또는 GitHub App 토큰을 사용하도록 version-tag-on-merge.yml의 actions/checkout에 with: 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) |
There was a problem hiding this comment.
🧩 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 || trueRepository: 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' . || trueRepository: 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 || trueRepository: 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* || trueRepository: 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:
- 1: https://github.com/google/play-services-plugins/blob/master/google-services-plugin/README.md
- 2: https://stackoverflow.com/questions/48418357/disable-google-services-gradle-plugin-for-specific-flavour
🏁 Script executed:
#!/bin/bash
set -euo pipefail
rg -n -i 'google-services\.json|google services|missingGoogleServicesStrategy|firebase' README.md scripts .github/workflows .github || trueRepository: 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 || trueRepository: 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 || trueRepository: 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.
📌 작업 내용
developpush 기반에서vX.Y.Ztag push 기반으로 전환했습니다.google-services.json을 secret으로 주입하도록 바꿨습니다.🧩 관련 이슈
📸 스크린샷
📢 Notes
major > minor > patch입니다.PR merge -> tag 생성 -> tag push -> distribution플로우로 동작합니다.Summary by CodeRabbit
릴리스 노트
신규 기능
작업(Chores)