Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/android-pr-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
115 changes: 115 additions & 0 deletions .github/workflows/firebase-app-distribution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
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

- 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 }}
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 timestamp๋Š” 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.

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 <<EOF
{
"embeds": [
{
"title": "$STATUS_TITLE",
"description": "Firebase Distribution Debug APK ๋ฐฐํฌ๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
"color": $STATUS_COLOR,
"fields": [
{
"name": "๐Ÿท Tag",
"value": "${{ github.ref_name }}"
},
{
"name": "๐Ÿ“ฆ Version",
"value": "${{ env.ANDROID_VERSION_NAME }} ใƒป #${{ github.run_number }} <${{ env.ANDROID_VERSION_CODE }}>"
},
{
"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"
83 changes: 83 additions & 0 deletions .github/workflows/version-tag-on-merge.yml
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +17 to +20
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.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.


- 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"
15 changes: 15 additions & 0 deletions Prezel/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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.

}

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
Expand Down
1 change: 1 addition & 0 deletions Prezel/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions Prezel/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down Expand Up @@ -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 = [
Expand Down