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
4 changes: 4 additions & 0 deletions .github/workflows/android-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ jobs:
run: |
echo '${{ secrets.LOCAL_PROPERTIES }}' >> ./local.properties

- name: Generate keystore.properties
run: |
echo '${{ secrets.KEYSTORE_PROPERTIES }}' >> ./keystore.properties

- name: Generate google-services.json
run: echo '${{ secrets.GOOGLE_SERVICES }}' | base64 -d > ./app/google-services.json

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ render.experimental.xml
# Keystore files
*.jks
*.keystore
keystore.properties

# Google Services (e.g. APIs or Firebase)
google-services.json
Expand Down
37 changes: 32 additions & 5 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import java.util.Properties

plugins {
alias(libs.plugins.booket.android.application)
Expand All @@ -12,21 +13,47 @@ plugins {
android {
namespace = "com.ninecraft.booket"

defaultConfig {
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", getApiKey("KAKAO_NATIVE_APP_KEY"))
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = getApiKey("KAKAO_NATIVE_APP_KEY").trim('"')
signingConfigs {
create("release") {
val propertiesFile = rootProject.file("keystore.properties")
val properties = Properties()
properties.load(propertiesFile.inputStream())
storeFile = rootProject.file(properties["STORE_FILE"] as String)
storePassword = properties["STORE_PASSWORD"] as String
keyAlias = properties["KEY_ALIAS"] as String
keyPassword = properties["KEY_PASSWORD"] as String
}
Comment on lines +21 to +25
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

NPE 위험: 프로퍼티 강제 캐스팅

properties["STORE_FILE"] as String 식은 키 누락 시 NullPointerException을 유발합니다. 안전한 프로퍼티 조회로 변경해 주세요.

-storeFile = rootProject.file(properties["STORE_FILE"] as String)
-storePassword = properties["STORE_PASSWORD"] as String
-keyAlias = properties["KEY_ALIAS"] as String
-keyPassword = properties["KEY_PASSWORD"] as String
+storeFile = rootProject.file(requireNotNull(properties["STORE_FILE"]) { "STORE_FILE missing" } as String)
+storePassword = requireNotNull(properties["STORE_PASSWORD"]) { "STORE_PASSWORD missing" } as String
+keyAlias = requireNotNull(properties["KEY_ALIAS"]) { "KEY_ALIAS missing" } as String
+keyPassword = requireNotNull(properties["KEY_PASSWORD"]) { "KEY_PASSWORD missing" } as String
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
storeFile = rootProject.file(properties["STORE_FILE"] as String)
storePassword = properties["STORE_PASSWORD"] as String
keyAlias = properties["KEY_ALIAS"] as String
keyPassword = properties["KEY_PASSWORD"] as String
}
storeFile = rootProject.file(requireNotNull(properties["STORE_FILE"]) { "STORE_FILE missing" } as String)
storePassword = requireNotNull(properties["STORE_PASSWORD"]) { "STORE_PASSWORD missing" } as String
keyAlias = requireNotNull(properties["KEY_ALIAS"]) { "KEY_ALIAS missing" } as String
keyPassword = requireNotNull(properties["KEY_PASSWORD"]) { "KEY_PASSWORD missing" } as String
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 20 to 24, the code uses forced casting like
properties["STORE_FILE"] as String, which can cause a NullPointerException if
the key is missing. Change these to safely retrieve the properties by using safe
calls or providing default values, for example by using
properties.get("STORE_FILE")?.toString() or checking for null before assignment
to avoid runtime exceptions.

}
Comment on lines +16 to 26
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

keystore.properties 존재 여부 미검사 → CI 빌드 실패 가능성

rootProject.file("keystore.properties")가 존재하지 않는 환경(예: PR CI, 외부 컨트리뷰터)에서 inputStream() 호출 시 FileNotFoundException으로 빌드가 즉시 실패합니다.
파일 부재 시 디버그·스냅샷 빌드는 서명 없이 통과하도록 가드 로직을 넣어주세요.

-val propertiesFile = rootProject.file("keystore.properties")
-val properties = Properties()
-properties.load(propertiesFile.inputStream())
+val propertiesFile = rootProject.file("keystore.properties")
+if (!propertiesFile.exists()) {
+    logger.warn("⚠️  keystore.properties not found – skipping release signing config.")
+    return@create               // signingConfig.release 생성 중단
+}
+val properties = Properties().apply {
+    propertiesFile.inputStream().use { load(it) }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
signingConfigs {
create("release") {
val propertiesFile = rootProject.file("keystore.properties")
val properties = Properties()
properties.load(propertiesFile.inputStream())
storeFile = rootProject.file(properties["STORE_FILE"] as String)
storePassword = properties["STORE_PASSWORD"] as String
keyAlias = properties["KEY_ALIAS"] as String
keyPassword = properties["KEY_PASSWORD"] as String
}
}
signingConfigs {
create("release") {
val propertiesFile = rootProject.file("keystore.properties")
if (!propertiesFile.exists()) {
logger.warn("⚠️ keystore.properties not found – skipping release signing config.")
return@create
}
val properties = Properties().apply {
propertiesFile.inputStream().use { load(it) }
}
storeFile = rootProject.file(properties["STORE_FILE"] as String)
storePassword = properties["STORE_PASSWORD"] as String
keyAlias = properties["KEY_ALIAS"] as String
keyPassword = properties["KEY_PASSWORD"] as String
}
}
🤖 Prompt for AI Agents
In app/build.gradle.kts around lines 15 to 25, the code assumes the
keystore.properties file always exists, causing a build failure if it is
missing. Add a check to verify if the keystore.properties file exists before
loading it. If the file is absent, skip the signing configuration to allow debug
and snapshot builds to proceed without signing, preventing CI build failures in
environments without the file.


buildTypes {
release {
isMinifyEnabled = false
getByName("debug") {
isDebuggable = true
applicationIdSuffix = ".dev"
manifestPlaceholders += mapOf(
"appName" to "@string/app_name_dev",
)
}

getByName("release") {
isDebuggable = false
isMinifyEnabled = true
isShrinkResources = true
signingConfig = signingConfigs.getByName("release")
manifestPlaceholders += mapOf(
"appName" to "@string/app_name",
)
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}

defaultConfig {
buildConfigField("String", "KAKAO_NATIVE_APP_KEY", getApiKey("KAKAO_NATIVE_APP_KEY"))
manifestPlaceholders["KAKAO_NATIVE_APP_KEY"] = getApiKey("KAKAO_NATIVE_APP_KEY").trim('"')
}

buildFeatures {
buildConfig = true
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:label="${appName}"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<resources>
<string name="app_name">Reed</string>
<string name="app_name_dev">Reed.dev</string>
</resources>
1 change: 0 additions & 1 deletion core/designsystem/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<resources>
<string name="app_name">Reed</string>
<string name="network_error_message">네트워크 연결이 불안해요.\n잠시후 다시 이용해주세요.</string>
<string name="server_error_message">이용에 불편을 드려 죄송합니다.\n잠시후 다시 이용해주세요.</string>
<string name="unknown_error_message">알 수 없는 오류가 발생하였습니다.</string>
Expand Down
Loading