-
Notifications
You must be signed in to change notification settings - Fork 79
GOG Auth Migration to Kotlin Implementation #414
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
GOG Auth Migration to Kotlin Implementation #414
Conversation
…ing auth information and doing REST API requests correctly.
📝 WalkthroughWalkthroughReplaces the GOGDL/command-based auth with an HTTP OAuth2 flow using OkHttp; exchanges and refreshes tokens, persists credentials in Changes
Sequence Diagram(s)sequenceDiagram
participant App
participant HTTP as OkHttp Client
participant GOG as GOG OAuth Server
participant FS as File Storage
App->>HTTP: GET token endpoint (clientId, clientSecret, code)
HTTP->>GOG: HTTP request
GOG-->>HTTP: JSON {access_token, refresh_token, expires_in, user_id}
HTTP-->>App: parsed token payload
App->>FS: write/update `gog_auth.json` (tokens, loginTime, expires_in)
Note over App,FS: On credential use
App->>FS: read `gog_auth.json`
FS-->>App: stored tokens + loginTime
App->>App: check expiration (loginTime + expires_in)
alt expired
App->>HTTP: GET refresh endpoint (refresh_token)
HTTP->>GOG: HTTP request
GOG-->>HTTP: JSON {access_token, refresh_token, expires_in}
HTTP-->>App: parsed refreshed tokens
App->>FS: update `gog_auth.json`
end
App-->>App: return valid credentials
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (1)
284-293: Potential race condition on concurrent file access.If
getGameCredentialsis called concurrently for different games, both calls read the auth file, modifyauthJson, and write back. The second write could overwrite changes from the first. Consider using a mutex or synchronized file access.🔧 Suggested approach using Mutex
Add a mutex at the class level:
private val authFileMutex = kotlinx.coroutines.sync.Mutex()Then wrap the read-modify-write operations:
+ authFileMutex.withLock { // Store the new game-specific credentials json.put("loginTime", System.currentTimeMillis() / 1000.0) authJson.put(clientId, json) // Write updated auth file - authFile.writeText(authJson.toString(2)) + withContext(Dispatchers.IO) { + authFile.writeText(authJson.toString(2)) + } + }
🤖 Fix all issues with AI agents
In @app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt:
- Around line 134-136: The blocking call
authFile.writeText(authData.toString(2)) in GOGAuthManager should be moved onto
the IO dispatcher; wrap that write inside withContext(Dispatchers.IO) {
authFile.writeText(...) } (or perform the write in a
CoroutineScope(Dispatchers.IO).launch) and ensure the enclosing function is
suspend or dispatches appropriately and that kotlinx.coroutines.Dispatchers and
withContext are imported so file I/O doesn’t run on the main thread.
- Around line 157-160: The file read is performed on the calling thread in
GOGAuthManager where authFile.readText() and JSONObject parsing occur; wrap the
blocking read in withContext(Dispatchers.IO) to perform IO on the IO dispatcher
and return the file content to the caller for JSON parsing. Update the code
surrounding authFile.readText() (referencing authFile, authConfigPath, and
authJson) to call withContext(Dispatchers.IO) { authFile.readText() } (importing
kotlinx.coroutines.Dispatchers and withContext) so only the blocking read runs
on IO while JSON construction happens off that dispatcher.
🧹 Nitpick comments (2)
app/src/main/java/app/gamenative/service/gog/GOGConstants.kt (1)
27-29: Public OAuth2 client credentials - static analysis false positive.The Gitleaks alert is a false positive. GOG's OAuth2 flow uses publicly known client credentials embedded in the official GOG Galaxy desktop client. This is standard practice for OAuth2 "public clients" (native/desktop apps) where the client secret cannot be kept confidential. The comment correctly documents this.
However, consider adding a more detailed comment explaining why these are safe to expose, to prevent future confusion or re-flagging:
📝 Suggested documentation improvement
- // GOG Client ID for authentication - These are public and not sensitive information. + // GOG Client ID and Secret for authentication. + // These are public values extracted from the GOG Galaxy client and are intentionally + // non-secret for OAuth2 public client flows (native apps cannot protect secrets). const val GOG_CLIENT_ID = "46899977096215655" const val GOG_CLIENT_SECRET = "9d85c43b1482497dbbce61f6e4aa173a433796eeae2ca8c5f6129f2dc4de46d9"app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (1)
82-95: Potential issue: Response body consumed twice on error path.On line 87,
response.body?.string()is called to get the error body. However, OkHttp response bodies can only be consumed once. If you later tried to use the body again, it would fail. In this specific code path it's fine since you return immediately, but this pattern is fragile.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.ktapp/src/main/java/app/gamenative/service/gog/GOGConstants.kt
🧰 Additional context used
🧬 Code graph analysis (1)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (1)
app/src/main/java/app/gamenative/service/gog/GOGService.kt (2)
getStoredCredentials(119-121)hasStoredCredentials(114-116)
🪛 Gitleaks (8.30.0)
app/src/main/java/app/gamenative/service/gog/GOGConstants.kt
[high] 29-29: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (7)
app/src/main/java/app/gamenative/service/gog/GOGConstants.kt (1)
34-35: LGTM!The OAuth authorization URL is correctly constructed with the necessary parameters. The
layout=clientparameter aligns with the standard GOG Galaxy client authentication flow.app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (6)
27-30: LGTM!The singleton
OkHttpClientwith 30-second timeouts is appropriate for authentication operations. OkHttp clients are designed to be shared across requests for connection pooling efficiency.
169-183: LGTM!The token expiration logic is correct. The recursive call to
getStoredCredentialsafter refresh is safe since refreshed tokens won't immediately expire, preventing infinite recursion.
352-416: Consistent file I/O pattern - same concerns apply.The refresh logic is correct. The same file I/O dispatcher concerns mentioned earlier apply to this function as well (lines 363, 408).
418-433: LGTM!The URL code extraction logic correctly handles both direct authorization codes and full redirect URLs containing the code parameter.
310-333: LGTM!The validation logic cleanly delegates to
getStoredCredentials, which handles token refresh automatically. The error handling appropriately distinguishes between "no credentials" (returnsfalse) and actual failures (returnsResult.failure).
338-350: LGTM!The logout implementation correctly handles both cases: existing file deletion and non-existent file. Consider making this a
suspend funwithwithContext(Dispatchers.IO)for consistency with other file operations, but the current synchronous approach is acceptable for this simple operation.
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (2)
226-229: File I/O not wrapped inDispatchers.IO- potential ANR.
authFile.readText()on line 228 performs blocking I/O on the caller's coroutine context. Other methods likeauthenticateWithCodeandgetStoredCredentialscorrectly usewithContext(Dispatchers.IO)for file operations.🐛 Proposed fix
// Read auth file - val authContent = authFile.readText() + val authContent = withContext(Dispatchers.IO) { authFile.readText() } val authJson = JSONObject(authContent)
290-299: File write insideuseblock not on IO dispatcher.The file write at line 295 (
authFile.writeText(...)) performs blocking I/O within the response processing block but outside anyDispatchers.IOcontext. This should be wrapped for consistency and to avoid blocking the coroutine.🐛 Proposed fix
// Store the new game-specific credentials json.put("loginTime", System.currentTimeMillis() / 1000.0) authJson.put(clientId, json) // Write updated auth file - authFile.writeText(authJson.toString(2)) + withContext(Dispatchers.IO) { + authFile.writeText(authJson.toString(2)) + } Timber.i("Successfully obtained game-specific token for clientId: $clientId") json
🤖 Fix all issues with AI agents
In @app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt:
- Around line 368-370: The file read is happening on the calling coroutine
context (authFile.readText()) inside GOGAuthManager; wrap the blocking I/O in
withContext(Dispatchers.IO) so the read and JSONObject creation occur off the
main thread. Specifically, move the authFile.readText() call into a
withContext(Dispatchers.IO) block and assign its result to authContent there
before constructing authJson, ensuring the coroutine uses Dispatchers.IO for
file I/O.
- Around line 264-271: The code in GOGAuthManager that builds the request URL
for the game-specific token is using a hardcoded "https://auth.gog.com/token"
which prevents tests from swapping in a MockWebServer; update the builder to use
the existing configurable tokenUrl property (the same tokenUrl used elsewhere)
instead of the hardcoded string, e.g. call tokenUrl.toHttpUrl().newBuilder() and
then add the same query parameters (client_id, client_secret, grant_type,
refresh_token) so tests can point tokenUrl to a MockWebServer endpoint while
preserving the current parameter construction in the method that requests the
game-specific token.
🧹 Nitpick comments (5)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (3)
86-99: Response body consumed twice risk - potential issue with error handling.If
response.isSuccessfulis false on line 90, you readresponse.body?.string()for the error body. However, if somehow the code continued (which it doesn't due toreturn), you'd have an issue. The current flow is correct, but there's a subtle issue: on success, ifresponse.bodyis null (rare but possible), you return failure, but the error message won't indicate why.Consider adding clarity to the empty response error:
💡 Suggested improvement
- val responseBody = response.body?.string() ?: return Result.failure(Exception("Empty response")) + val responseBody = response.body?.string() ?: return Result.failure(Exception("Empty response body from auth server"))
40-43: Consider makinghasStoredCredentialsa suspend function.This performs a file existence check on the calling thread. While fast, for consistency with the stated goal of running file operations off the IO thread, consider making this a suspend function or documenting that callers should invoke it from appropriate contexts.
430-445: URL-decoding is technically RFC-compliant but not required for GOG.RFC 6749 specifies that authorization code parameters are transmitted via URL-encoded query strings, which suggests URL-decoding is appropriate. However, GOG's authorization codes are opaque, URL-safe strings that don't contain special characters requiring decoding. While adding
URLDecoder.decode(cleanCode, "UTF-8")would be more RFC-strict, it's unnecessary for GOG's actual behavior and won't prevent authentication failures. The current implementation is sufficient.app/src/test/java/app/gamenative/service/gog/GOGAuthManagerTest.kt (2)
47-54:createTempDiris deprecated - usekotlin.io.path.createTempDirectory.The
createTempDirfunction is deprecated in Kotlin. Consider using the newerkotlin.io.path.createTempDirectoryAPI.♻️ Proposed fix
+import kotlin.io.path.createTempDirectory + @Before fun setUp() { closeable = MockitoAnnotations.openMocks(this) mockWebServer = MockWebServer() mockWebServer.start() - tempDir = createTempDir("gogtest") + tempDir = createTempDirectory("gogtest").toFile() `when`(context.filesDir).thenReturn(tempDir) }
239-251: Consider adding tests forgetGameCredentials,clearStoredCredentials, andhasStoredCredentials.The test suite covers the main authentication flows but doesn't include tests for:
getGameCredentials- game-specific token retrievalclearStoredCredentials- logout functionalityhasStoredCredentials- credential existence checkNote: Testing
getGameCredentialswould require fixing the hardcoded token URL issue flagged in the main file.Would you like me to generate test cases for these methods?
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.ktapp/src/test/java/app/gamenative/service/gog/GOGAuthManagerTest.kt
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-19T17:13:01.017Z
Learnt from: utkarshdalal
Repo: utkarshdalal/GameNative PR: 159
File: app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt:136-136
Timestamp: 2025-09-19T17:13:01.017Z
Learning: In LibraryAppScreen.kt, the user prefers to use runBlocking to maintain synchronous APIs when underlying methods have been converted to suspend functions, rather than refactoring all calling code to be async. This approach prevents UI breakage and maintains API compatibility. The user confirmed this is acceptable when performance is not a concern.
Applied to files:
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt
📚 Learning: 2025-09-19T17:07:27.941Z
Learnt from: utkarshdalal
Repo: utkarshdalal/GameNative PR: 159
File: app/src/main/java/app/gamenative/service/DownloadService.kt:6-6
Timestamp: 2025-09-19T17:07:27.941Z
Learning: In app/src/main/java/app/gamenative/service/DownloadService.kt, the getSizeFromStoreDisplay() function uses runBlocking to call SteamService.getDownloadableDepots() because the latter was converted from synchronous to suspend in this PR. The user confirmed the previous synchronous implementation worked fine, and if performance is acceptable, keeping runBlocking is a valid approach.
Applied to files:
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt
🧬 Code graph analysis (1)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (1)
app/src/main/java/app/gamenative/service/gog/GOGService.kt (2)
getStoredCredentials(119-121)hasStoredCredentials(114-116)
🔇 Additional comments (5)
app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt (1)
27-34: LGTM - HTTP client configuration with reasonable timeouts.The OkHttpClient setup with 30-second connect and read timeouts is appropriate for network operations. The internal
tokenUrlfield for testing is a clean approach.app/src/test/java/app/gamenative/service/gog/GOGAuthManagerTest.kt (4)
97-119: LGTM - Failure test case correctly validates error handling.The test properly validates that HTTP errors are propagated with the response body included in the error message.
121-139: LGTM - Stored credentials test validates happy path.The test correctly sets up non-expired credentials and verifies retrieval.
141-182: LGTM - Refresh flow test is comprehensive.The test correctly validates the token refresh mechanism when credentials expire.
211-237: LGTM - Code extraction tests cover all edge cases.The tests comprehensively validate URL parsing with various parameter combinations and plain code input.
| // Request game-specific token using Galaxy's refresh token | ||
| Timber.d("Requesting game-specific token for clientId: $clientId") | ||
| val tokenUrl = "https://auth.gog.com/token?client_id=$clientId&client_secret=$clientSecret&grant_type=refresh_token&refresh_token=$refreshToken" | ||
| val tokenUrl = "https://auth.gog.com/token".toHttpUrl().newBuilder() | ||
| .addQueryParameter("client_id", clientId) | ||
| .addQueryParameter("client_secret", clientSecret) | ||
| .addQueryParameter("grant_type", "refresh_token") | ||
| .addQueryParameter("refresh_token", refreshToken) | ||
| .build() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Hardcoded token URL prevents testing with MockWebServer.
This method uses a hardcoded "https://auth.gog.com/token" instead of the configurable tokenUrl property used elsewhere. This makes the method untestable with MockWebServer.
♻️ Proposed fix for consistency
// Request game-specific token using Galaxy's refresh token
Timber.d("Requesting game-specific token for clientId: $clientId")
- val tokenUrl = "https://auth.gog.com/token".toHttpUrl().newBuilder()
+ val gameTokenUrl = tokenUrl.toHttpUrl().newBuilder()
.addQueryParameter("client_id", clientId)
.addQueryParameter("client_secret", clientSecret)
.addQueryParameter("grant_type", "refresh_token")
.addQueryParameter("refresh_token", refreshToken)
.build()
val request = okhttp3.Request.Builder()
- .url(tokenUrl)
+ .url(gameTokenUrl)
.get()
.build()📝 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.
| // Request game-specific token using Galaxy's refresh token | |
| Timber.d("Requesting game-specific token for clientId: $clientId") | |
| val tokenUrl = "https://auth.gog.com/token?client_id=$clientId&client_secret=$clientSecret&grant_type=refresh_token&refresh_token=$refreshToken" | |
| val tokenUrl = "https://auth.gog.com/token".toHttpUrl().newBuilder() | |
| .addQueryParameter("client_id", clientId) | |
| .addQueryParameter("client_secret", clientSecret) | |
| .addQueryParameter("grant_type", "refresh_token") | |
| .addQueryParameter("refresh_token", refreshToken) | |
| .build() | |
| // Request game-specific token using Galaxy's refresh token | |
| Timber.d("Requesting game-specific token for clientId: $clientId") | |
| val gameTokenUrl = tokenUrl.toHttpUrl().newBuilder() | |
| .addQueryParameter("client_id", clientId) | |
| .addQueryParameter("client_secret", clientSecret) | |
| .addQueryParameter("grant_type", "refresh_token") | |
| .addQueryParameter("refresh_token", refreshToken) | |
| .build() | |
| val request = okhttp3.Request.Builder() | |
| .url(gameTokenUrl) | |
| .get() | |
| .build() |
🤖 Prompt for AI Agents
In @app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt around lines
264 - 271, The code in GOGAuthManager that builds the request URL for the
game-specific token is using a hardcoded "https://auth.gog.com/token" which
prevents tests from swapping in a MockWebServer; update the builder to use the
existing configurable tokenUrl property (the same tokenUrl used elsewhere)
instead of the hardcoded string, e.g. call tokenUrl.toHttpUrl().newBuilder() and
then add the same query parameters (client_id, client_secret, grant_type,
refresh_token) so tests can point tokenUrl to a MockWebServer endpoint while
preserving the current parameter construction in the method that requests the
game-specific token.
| // Read current credentials | ||
| val authContent = authFile.readText() | ||
| val authJson = JSONObject(authContent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File I/O not wrapped in Dispatchers.IO.
The file read at line 369 should be wrapped in withContext(Dispatchers.IO) for consistency with other methods and to prevent potential ANR issues.
🐛 Proposed fix
// Read current credentials
- val authContent = authFile.readText()
+ val authContent = withContext(Dispatchers.IO) { authFile.readText() }
val authJson = JSONObject(authContent)📝 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.
| // Read current credentials | |
| val authContent = authFile.readText() | |
| val authJson = JSONObject(authContent) | |
| // Read current credentials | |
| val authContent = withContext(Dispatchers.IO) { authFile.readText() } | |
| val authJson = JSONObject(authContent) |
🤖 Prompt for AI Agents
In @app/src/main/java/app/gamenative/service/gog/GOGAuthManager.kt around lines
368 - 370, The file read is happening on the calling coroutine context
(authFile.readText()) inside GOGAuthManager; wrap the blocking I/O in
withContext(Dispatchers.IO) so the read and JSONObject creation occur off the
main thread. Specifically, move the authFile.readText() call into a
withContext(Dispatchers.IO) block and assign its result to authContent there
before constructing authJson, ensuring the coroutine uses Dispatchers.IO for
file I/O.
| // Update credentials in auth file | ||
| tokenJson.put("loginTime", System.currentTimeMillis() / 1000.0) | ||
| authJson.put(clientId, tokenJson) | ||
| authFile.writeText(authJson.toString(2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
File write not on IO dispatcher.
Line 414 performs blocking file I/O without Dispatchers.IO wrapping.
🐛 Proposed fix
// Update credentials in auth file
tokenJson.put("loginTime", System.currentTimeMillis() / 1000.0)
authJson.put(clientId, tokenJson)
- authFile.writeText(authJson.toString(2))
+ withContext(Dispatchers.IO) {
+ authFile.writeText(authJson.toString(2))
+ }📝 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.
| // Update credentials in auth file | |
| tokenJson.put("loginTime", System.currentTimeMillis() / 1000.0) | |
| authJson.put(clientId, tokenJson) | |
| authFile.writeText(authJson.toString(2)) | |
| // Update credentials in auth file | |
| tokenJson.put("loginTime", System.currentTimeMillis() / 1000.0) | |
| authJson.put(clientId, tokenJson) | |
| withContext(Dispatchers.IO) { | |
| authFile.writeText(authJson.toString(2)) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
app/build.gradle.kts (1)
86-86: Address the deprecatedresourceConfigurationsAPI flagged by pipeline.The pipeline warning indicates
resourceConfigurationsis deprecated. Migrate to the recommendedandroidResources.localeFiltersAPI.Proposed fix
- resourceConfigurations += listOf( + androidResources.localeFilters += listOf( "en", // English (default) "da", // Danish "pt-rBR", // Portuguese (Brazilian) "zh-rTW", // Traditional Chinese "zh-rCN", // Simplified Chinese "fr", // French "de", // German "uk", // Ukrainian "it", // Italian // TODO: Add more languages here using the ISO 639-1 locale code with regional qualifiers (e.g., "pt-rPT" for European Portuguese) )
🤖 Fix all issues with AI agents
In @app/build.gradle.kts:
- Around line 297-298: Replace the hardcoded test dependencies
testImplementation("org.json:json:20231013") and
testImplementation("com.squareup.okhttp3:mockwebserver:5.1.0") with
version-catalog references (e.g., use libs.json-org and libs.mockwebserver) and
add the corresponding entries to the version catalog: add versions json-org =
"20231013" and mockwebserver = "5.1.0" under [versions], and libraries json-org
= { module = "org.json:json", version.ref = "json-org" } and mockwebserver = {
module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" }
under [libraries] so the app/build.gradle.kts testImplementation calls reference
the catalog instead of hardcoded strings.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/build.gradle.kts
🧰 Additional context used
🪛 GitHub Actions: Pull Request build check
app/build.gradle.kts
[warning] 86-86: Deprecated Gradle feature used: 'resourceConfigurations: MutableSet' is deprecated. For language resource configurations in applications, use androidResources.localeFilters.
| testImplementation("org.json:json:20231013") | ||
| testImplementation("com.squareup.okhttp3:mockwebserver:5.1.0") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the app/build.gradle.kts file around lines 297-298
head -310 app/build.gradle.kts | tail -30Repository: utkarshdalal/GameNative
Length of output: 1425
🏁 Script executed:
# Check if libs.versions.toml exists and examine its structure
find . -name "libs.versions.toml" -o -name "gradle.versions.toml"Repository: utkarshdalal/GameNative
Length of output: 94
🏁 Script executed:
# Get a broader view of the build.gradle.kts to understand dependency patterns
grep -n "testImplementation\|implementation" app/build.gradle.kts | head -30Repository: utkarshdalal/GameNative
Length of output: 1604
🏁 Script executed:
# Examine the libs.versions.toml structure
cat ./gradle/libs.versions.tomlRepository: utkarshdalal/GameNative
Length of output: 12001
🏁 Script executed:
# Search for any okhttp references in gradle files
rg -i "okhttp" --type gradle --type tomlRepository: utkarshdalal/GameNative
Length of output: 511
Add hardcoded test dependencies to version catalog for consistency.
The project uses the libs.* version catalog pattern for dependency management. The new test dependencies should follow this pattern instead of using hardcoded strings.
Additionally, org.json:json:20231013 is not currently in the version catalog and needs to be added. The mockwebserver version (5.1.0) aligns with the OkHttp version already defined in the catalog, so there's no compatibility concern.
Update gradle/libs.versions.toml:
Version catalog additions
[versions]
json-org = "20231013"
mockwebserver = "5.1.0"
[libraries]
json-org = { module = "org.json:json", version.ref = "json-org" }
mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" }Then in app/build.gradle.kts:
Dependency declarations
- testImplementation("org.json:json:20231013")
- testImplementation("com.squareup.okhttp3:mockwebserver:5.1.0")
+ testImplementation(libs.json.org)
+ testImplementation(libs.mockwebserver)🤖 Prompt for AI Agents
In @app/build.gradle.kts around lines 297 - 298, Replace the hardcoded test
dependencies testImplementation("org.json:json:20231013") and
testImplementation("com.squareup.okhttp3:mockwebserver:5.1.0") with
version-catalog references (e.g., use libs.json-org and libs.mockwebserver) and
add the corresponding entries to the version catalog: add versions json-org =
"20231013" and mockwebserver = "5.1.0" under [versions], and libraries json-org
= { module = "org.json:json", version.ref = "json-org" } and mockwebserver = {
module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" }
under [libraries] so the app/build.gradle.kts testImplementation calls reference
the catalog instead of hardcoded strings.
… into gog-kotlin-migration-initial
Description
Implementation Details:
This is mostly just storing/retrieving details from the JSON file we store the credentials in and running REST API requests to the GOG auth service.
Summary by CodeRabbit
Bug Fixes
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.