-
-
Notifications
You must be signed in to change notification settings - Fork 3
Introduce ShadowJar to avoid dependency conflicts #375
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
Conversation
Caution Review failedThe pull request is closed. 📝 WalkthroughSummary by CodeRabbit
WalkthroughAdds a shadow (shaded) publishing convention and applies it across modules, updates CI to use the Gradle wrapper, run Maven integration tests and submit dependency graphs, introduces a Maven sample + tests, adjusts EditorConfig, and changes response APIs to accept numeric HTTP status codes with derived HttpStatusCode. Changes
Sequence Diagram(s)sequenceDiagram
participant CI as GitHub Actions
participant GW as ./gradlew
participant ShadowConv as shadow-convention (buildSrc)
participant Build as Project Build
participant LocalMaven as publishToMavenLocal
participant MavenSample as Maven (sample)
participant DepJob as dependency-submission
rect rgb(220,235,255)
CI->>GW: run --rerun-tasks clean build publishToMavenLocal koverXmlReport
GW->>ShadowConv: apply shadow-convention
ShadowConv->>Build: configure shadowJar (minimize, relocate)
Build->>LocalMaven: publish shadow artifacts
end
rect rgb(235,255,220)
CI->>MavenSample: run mvn --batch-mode test (ai-mocks-openai/samples/shadow)
MavenSample-->>CI: test results
end
rect rgb(255,245,215)
CI->>DepJob: trigger dependency-submission job
DepJob->>DepJob: generate & submit dependency graph
DepJob-->>CI: submission result
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (22)
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 |
Coverage summary from CodacySee diff coverage on Codacy
Coverage variation details
Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: Diff coverage details
Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: See your quality gate settings Change summary preferencesFootnotes
|
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: 20
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (11)
.editorconfig (2)
42-45
: Add indent_style = tab to the XML sectionindent_size = tab without indent_style = tab is ambiguous; declare indent_style = tab under [*.xml].
File: .editorconfig (lines 42-45)
[*.xml] +indent_style = tab tab_width = 4 indent_size = tab
Reformat a sample XML and ensure CI linters pass.
26-34
: Kotlin: set indent_style=tab when using indent_size=tab (spec mismatch).root sets indent_style = space (line 8) while [*.{kt,kts}] only sets indent_size = tab (line 27) in .editorconfig — make the Kotlin section explicit.
[*.{kt,kts}] -indent_size = tab +indent_style = tab +indent_size = tab +tab_width = 4Run formatting checks (e.g., ./gradlew spotlessCheck or ./gradlew ktlintCheck) to confirm no new violations.
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/AbstractResponseDefinition.kt (1)
27-33
: Enforce invariant: keep httpStatusCode and httpStatus in syncRight now callers can pass mismatched values (e.g., 200 with HttpStatusCode.NotFound). Add a runtime check to prevent drift across the codebase.
Apply this diff:
public abstract class AbstractResponseDefinition<T>( public val contentType: ContentType? = null, public val httpStatusCode: Int = 200, public val httpStatus: HttpStatusCode = HttpStatusCode.fromValue(httpStatusCode), public val headers: (ResponseHeaders.() -> Unit)? = null, public val headerList: List<Pair<String, String>> = emptyList(), public open val delay: Duration = Duration.ZERO, public var responseBody: T? = null, ) { + init { + require(httpStatus.value == httpStatusCode) { + "httpStatus ($httpStatus) must match httpStatusCode ($httpStatusCode)" + } + }mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt (4)
116-124
: Streaming builder not migrated: add httpStatusCode and propagate to baseThis still accepts only
httpStatus
, causinghttpStatusCode
to stick at 200. Mirror the non-streaming builder.Apply this diff:
@Suppress("LongParameterList") public open class StreamingResponseDefinitionBuilder<P : Any, T>( public val request: CapturedRequest<P>, public var flow: Flow<T>? = null, public var chunks: MutableList<T> = mutableListOf(), public var delayBetweenChunks: Duration = Duration.ZERO, - httpStatus: HttpStatusCode = HttpStatusCode.OK, + httpStatusCode: Int = 200, + httpStatus: HttpStatusCode = HttpStatusCode.fromValue(httpStatusCode), headers: MutableList<Pair<String, String>> = mutableListOf(), -) : AbstractResponseDefinitionBuilder<P, T>(httpStatus = httpStatus, headers = headers) { +) : AbstractResponseDefinitionBuilder<P, T>( + httpStatusCode = httpStatusCode, + httpStatus = httpStatus, + headers = headers, +) {
136-145
: Also pass httpStatusCode to StreamResponseDefinition.build()Without this,
StreamResponseDefinition
uses its default (200) even when the builder changed status.Apply this diff:
public override fun build(): StreamResponseDefinition<P, T> = StreamResponseDefinition( chunkFlow = flow, chunks = chunks.toList(), + httpStatusCode = httpStatusCode, httpStatus = httpStatus, headers = headersLambda, headerList = Collections.unmodifiableList(headers), delayBetweenChunks = delayBetweenChunks, delay = delay, )
22-62
: Optional: centralize sync by constraining the APIConsider removing
httpStatus
as a public var from builders and making it derived fromhttpStatusCode
only. This eliminates the possibility of drift entirely.
1-147
: Sync httpStatus and httpStatusCode in AbstractResponseDefinitionBuilderMultiple call sites assign only httpStatus (HttpStatusCode) while httpStatusCode (Int) remains stale — this yields inconsistent ResponseDefinition/StreamResponseDefinition instances. Fix by keeping the two fields in sync (either update call sites to set both or add bidirectional setters that update the other).
Instances found (assign-only httpStatus):
- mokksy/src/jvmTest/kotlin/me/kpavlov/mokksy/TypesafeMethodsIT.kt:221
- mokksy/src/jvmTest/kotlin/me/kpavlov/mokksy/BodyMatchingIT.kt:50
- mokksy/src/jvmTest/kotlin/me/kpavlov/mokksy/MokksySseIT.kt:80
- mokksy/src/commonTest/kotlin/me/kpavlov/mokksy/BuildingStepTest.kt:60, 69, 77
- ai-mocks-openai/src/jvmTest/kotlin/me/kpavlov/aimocks/openai/official/completions/ChatCompletionOpenaiTest.kt:90, 137
Suggested minimal change (AbstractResponseDefinitionBuilder): make the properties use private backing fields and update each other to avoid recursion, e.g.
private var _httpStatusCode: Int = 200
public var httpStatusCode: Int
get() = _httpStatusCode
set(value) {
_httpStatusCode = value
_httpStatus = HttpStatusCode.fromValue(value)
}private var _httpStatus: HttpStatusCode = HttpStatusCode.fromValue(_httpStatusCode)
public var httpStatus: HttpStatusCode
get() = _httpStatus
set(value) {
_httpStatus = value
_httpStatusCode = value.value
}Alternatively, remove the redundant field and use a single source-of-truth. Addressing this is required.
buildSrc/src/main/kotlin/dokka-convention.gradle.kts (1)
13-17
: Fix Dokka sourceLink branch: master → main.The repo’s default branch is “main”; pointing Dokka to “master” breaks source links.
Apply:
- remoteUrl("https://github.com/mokksy/ai-mocks/tree/master") + remoteUrl("https://github.com/mokksy/ai-mocks/tree/main")Makefile (1)
46-53
: sourcesJar task likely unnecessary or missing at root.Root “sourcesJar” often doesn’t exist in MPP; publishing already attaches sources if configured. This can fail the target.
Apply:
- ./gradlew clean build check sourcesJar publishToMavenLocal + ./gradlew clean build check publishToMavenLocalIf you do need sources, enable withSourcesJar in the convention plugin instead of invoking a root task.
.github/workflows/gradle.yml (1)
31-36
: Build JDK 24 may be too bleeding-edge.Consider LTS (17/21) or a matrix; some tooling (Dokka, KSP, Kover) and upstream clients may lag 24 support.
Example:
- - name: Set up JDK 24 + - name: Set up JDK uses: actions/setup-java@v5 with: - java-version: 24 + java-version: 21 distribution: 'temurin'Or use a matrix over [17, 21].
ai-mocks-ollama/build.gradle.kts (1)
43-51
: Duplicate dependency declaration.
implementation(libs.langchain4j.kotlin)
appears twice (Line 43 and Line 49). Remove one.- implementation(libs.langchain4j.kotlin) // Note: There's no specific Ollama client in langchain4j or spring-ai yet // If/when they become available, they should be added here implementation(project.dependencies.platform(libs.langchain4j.bom)) implementation(project.dependencies.platform(libs.spring.ai.bom)) implementation(project.dependencies.platform(libs.spring.bom)) - implementation(libs.langchain4j.kotlin) + implementation(libs.langchain4j.kotlin) implementation(libs.langchain4j.ollama)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (18)
.editorconfig
(2 hunks).github/workflows/gradle.yml
(2 hunks)Makefile
(1 hunks)ai-mocks-a2a/build.gradle.kts
(2 hunks)ai-mocks-anthropic/build.gradle.kts
(2 hunks)ai-mocks-gemini/build.gradle.kts
(2 hunks)ai-mocks-ollama/build.gradle.kts
(2 hunks)ai-mocks-openai/build.gradle.kts
(2 hunks)ai-mocks-openai/samples/shadow/pom.xml
(1 hunks)ai-mocks-openai/samples/shadow/src/test/java/com/example/OpenAITest.java
(1 hunks)buildSrc/build.gradle.kts
(1 hunks)buildSrc/src/main/kotlin/dokka-convention.gradle.kts
(1 hunks)buildSrc/src/main/kotlin/shadow-convention.gradle.kts
(1 hunks)mokksy/build.gradle.kts
(2 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/AbstractResponseDefinition.kt
(1 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinition.kt
(2 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt
(3 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/StreamResponseDefinition.kt
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
ai-mocks-openai/samples/shadow/src/test/java/com/example/OpenAITest.java (2)
ai-mocks-core/src/commonMain/kotlin/me/kpavlov/aimocks/core/ModelRequestSpecification.kt (1)
requestBodyContains
(46-49)ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/model/chat/ChatCompletionRequestBuilder.kt (1)
maxCompletionTokens
(135-138)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: build
- GitHub Check: submit-gradle
🔇 Additional comments (12)
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinition.kt (1)
37-43
: Propagate consistent status pair to the superclass (after fixing defaults)After adjusting defaults above, this call site is fine. Just ensure all builders/callers pass matching pairs or rely on the base-class
require
.mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt (1)
83-90
: Good: ResponseDefinitionBuilder forwards both status fields to the baseForwarding both
httpStatusCode
andhttpStatus
is correct; once the mutator is fixed, they’ll remain consistent.mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/StreamResponseDefinition.kt (1)
51-63
: Fail fast on inconsistent httpStatus/httpStatusCodeConstructor accepts both httpStatusCode and httpStatus; ensure callers can’t pass inconsistent pairs — validate here or rely on the base-class invariant. If adding local validation:
public open class StreamResponseDefinition<P, T>( @@ ) : AbstractResponseDefinition<T>( @@ ) { + init { + require(httpStatus.value == httpStatusCode) { + "httpStatus ($httpStatus) must match httpStatusCode ($httpStatusCode)" + } + }Also check the Streaming builder in ResponseDefinitionBuilders.kt — it currently passes only httpStatus (httpStatusCode defaults to 200) and can desync.
buildSrc/src/main/kotlin/dokka-convention.gradle.kts (1)
23-23
: No-op formatting change — OK to merge.ai-mocks-openai/samples/shadow/src/test/java/com/example/OpenAITest.java (1)
91-93
: Double-check expected exception type.500 may map to a different exception depending on SDK version (e.g., OpenAIException/ServiceUnavailable). Ensure CI confirms this.
ai-mocks-anthropic/build.gradle.kts (1)
7-8
: Shadow convention applied — LGTM.Consistent with repo-wide shading approach.
ai-mocks-a2a/build.gradle.kts (1)
8-9
: Shadow convention inclusion — OK.ai-mocks-openai/samples/shadow/pom.xml (1)
22-25
: Bump com.openai:openai-java-client-okhttp to 3.6.0.
ai-mocks-openai/samples/shadow/pom.xml (lines 22–25) currently pins com.openai:openai-java-client-okhttp:3.1.2; upstream latest stable is com.openai:openai-java-client-okhttp:3.6.0 (released 2025-09-19). Update the version or justify pinning.buildSrc/build.gradle.kts (1)
16-16
: Shadow plugin dependency: confirm version and compatibility with your Gradle wrapper.9.1.0 is the GradleUp fork. Make sure your wrapper uses a compatible Gradle version; otherwise task types and DSL may differ.
Would you like me to add a small check that prints Gradle and Shadow versions during CI?
ai-mocks-gemini/build.gradle.kts (1)
7-8
: Applying shadow-convention here is fine.No issues spotted with plugin application.
mokksy/build.gradle.kts (1)
8-9
: Shadow plugin applied — OK.Matches the shared convention usage.
ai-mocks-ollama/build.gradle.kts (1)
7-8
: Plugin application is consistent.No issues here.
- name: OpenAI Maven Integration Tests | ||
working-directory: ai-mocks-openai/samples/shadow | ||
run: mvn --batch-mode test | ||
|
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.
Align Maven test JDK with POM (Java 17).
The Maven step currently runs on JDK 24. Set up Java 17 before mvn test to match <maven.compiler.release>.
+ - name: Set up JDK 17 for Maven sample
+ uses: actions/setup-java@v5
+ with:
+ java-version: 17
+ distribution: 'temurin'
- name: OpenAI Maven Integration Tests
working-directory: ai-mocks-openai/samples/shadow
run: mvn --batch-mode test
📝 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.
- name: OpenAI Maven Integration Tests | |
working-directory: ai-mocks-openai/samples/shadow | |
run: mvn --batch-mode test | |
- name: Set up JDK 17 for Maven sample | |
uses: actions/setup-java@v5 | |
with: | |
java-version: 17 | |
distribution: 'temurin' | |
- name: OpenAI Maven Integration Tests | |
working-directory: ai-mocks-openai/samples/shadow | |
run: mvn --batch-mode test |
🤖 Prompt for AI Agents
.github/workflows/gradle.yml around lines 59 to 62: the Maven integration-test
step runs under JDK 24 while the project POM compiles for Java 17; add a setup
step immediately before the mvn --batch-mode test to install and configure Java
17 (for example using actions/setup-java with java-version: '17' and an
appropriate distribution like temurin) so the mvn test runs using Java 17 and
matches <maven.compiler.release>.
`shadow-convention` | ||
id("com.gradleup.shadow") | ||
// id("org.openapi.generator") version "7.12.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.
🛠️ Refactor suggestion
🧩 Analysis chain
Avoid double-applying Shadow plugin.
If shadow-convention already applies com.gradleup.shadow, this explicit id is redundant and can cause confusion.
`shadow-convention`
- id("com.gradleup.shadow")
Verification script:
🏁 Script executed:
#!/bin/bash
# Check if shadow plugin is applied inside the convention
rg -n "id\\(\"com\\.gradleup\\.shadow\"\\)" buildSrc -C2 || true
# Check other modules for duplicate direct plugin application
rg -n "id\\(\"com\\.gradleup\\.shadow\"\\)" -g '!buildSrc/**' -C2 || true
Length of output: 538
Remove duplicate com.gradleup.shadow plugin
shadow-convention already applies com.gradleup.shadow (buildSrc/src/main/kotlin/shadow-convention.gradle.kts:6), so remove the explicit id("com.gradleup.shadow") from ai-mocks-openai/build.gradle.kts (lines 8–11).
`shadow-convention`
- id("com.gradleup.shadow")
📝 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.
`shadow-convention` | |
id("com.gradleup.shadow") | |
// id("org.openapi.generator") version "7.12.0" | |
} | |
`shadow-convention` | |
// id("org.openapi.generator") version "7.12.0" | |
} |
🤖 Prompt for AI Agents
In ai-mocks-openai/build.gradle.kts around lines 8 to 11, remove the duplicate
explicit plugin application id("com.gradleup.shadow") because the
shadow-convention plugin
(buildSrc/src/main/kotlin/shadow-convention.gradle.kts:6) already applies it;
edit the file to delete the id("com.gradleup.shadow") line (and any
now-unnecessary adjacent blank/comment line if desired) and keep the
shadow-convention reference only.
<dependency> | ||
<groupId>dev.langchain4j</groupId> | ||
<artifactId>langchain4j-open-ai</artifactId> | ||
<version>1.5.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.openai</groupId> | ||
<artifactId>openai-java-client-okhttp</artifactId> | ||
<version>3.1.2</version> | ||
</dependency> |
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.
🧹 Nitpick
Scope demo deps to test.
These are only used by tests; avoid leaking to compile/runtime.
- <dependency>
+ <dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
<version>1.5.0</version>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java-client-okhttp</artifactId>
<version>3.1.2</version>
+ <scope>test</scope>
</dependency>
📝 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.
<dependency> | |
<groupId>dev.langchain4j</groupId> | |
<artifactId>langchain4j-open-ai</artifactId> | |
<version>1.5.0</version> | |
</dependency> | |
<dependency> | |
<groupId>com.openai</groupId> | |
<artifactId>openai-java-client-okhttp</artifactId> | |
<version>3.1.2</version> | |
</dependency> | |
<dependency> | |
<groupId>dev.langchain4j</groupId> | |
<artifactId>langchain4j-open-ai</artifactId> | |
<version>1.5.0</version> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>com.openai</groupId> | |
<artifactId>openai-java-client-okhttp</artifactId> | |
<version>3.1.2</version> | |
<scope>test</scope> | |
</dependency> |
🤖 Prompt for AI Agents
In ai-mocks-openai/samples/shadow/pom.xml around lines 16 to 25, the
langchain4j-open-ai and openai-java-client-okhttp dependencies are declared
without a scope and are only needed for tests; update each <dependency> block to
include a <scope>test</scope> element so they are not included on the
compile/runtime classpath and are only available to the test phase.
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-api</artifactId> | ||
<version>5.13.4</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> |
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
JUnit engine missing — tests may not run.
Use the aggregator “junit-jupiter” or add “junit-jupiter-engine”.
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <version>5.13.4</version>
- <scope>test</scope>
- </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <version>5.13.4</version>
+ <scope>test</scope>
+ </dependency>
🌐 Web query:
Confirm current Maven coordinates for JUnit 5 aggregator “junit-jupiter” and whether it brings the engine transitively.
💡 Result:
-
Maven coordinates (artifact, without fixing a version):
- groupId: org.junit.jupiter
- artifactId: junit-jupiter. (docs.junit.org)
-
Does the junit-jupiter aggregator bring the engine transitively?
- Yes — the junit-jupiter aggregator POM transitively pulls in junit-jupiter-api, junit-jupiter-params and junit-jupiter-engine (the engine is a runtime dependency). (docs.junit.org)
Tip: manage versions with the junit-bom (org.junit:junit-bom) to keep consistent versions. (docs.junit.org)
Citations:
- 1: https://docs.junit.org/5.13.0-M3/user-guide/index.html?utm_source=openai
- 2: https://docs.junit.org/5.13.0-M3/user-guide/index.html?utm_source=openai
- 3: https://docs.junit.org/5.13.0-M3/user-guide/index.html?utm_source=openai
JUnit engine missing — add the engine or use the junit-jupiter aggregator.
File: ai-mocks-openai/samples/shadow/pom.xml (lines 40-45)
junit-jupiter-api alone does not bring the test engine; use org.junit.jupiter:junit-jupiter (aggregator, which transitively includes junit-jupiter-engine) or add org.junit.jupiter:junit-jupiter-engine as a test dependency. Consider managing versions with org.junit:junit-bom.
- <dependency>
- <groupId>org.junit.jupiter</groupId>
- <artifactId>junit-jupiter-api</artifactId>
- <version>5.13.4</version>
- <scope>test</scope>
- </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <version>5.13.4</version>
+ <scope>test</scope>
+ </dependency>
📝 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.
<groupId>org.junit.jupiter</groupId> | |
<artifactId>junit-jupiter-api</artifactId> | |
<version>5.13.4</version> | |
<scope>test</scope> | |
</dependency> | |
</dependencies> | |
<dependency> | |
<groupId>org.junit.jupiter</groupId> | |
<artifactId>junit-jupiter</artifactId> | |
<version>5.13.4</version> | |
<scope>test</scope> | |
</dependency> | |
</dependencies> |
🤖 Prompt for AI Agents
In ai-mocks-openai/samples/shadow/pom.xml around lines 40-45, the pom currently
depends only on org.junit.jupiter:junit-jupiter-api which does not include a
test engine; update the dependencies to either replace or add an aggregator
(org.junit.jupiter:junit-jupiter) so the engine is transitively included, or
keep junit-jupiter-api and explicitly add org.junit.jupiter:junit-jupiter-engine
with scope test; optionally manage versions via org.junit:junit-bom in
dependencyManagement and reference its version for consistency.
tasks.shadowJar { | ||
|
||
minimize { | ||
exclude(dependency("kotlin:.*:.*")) | ||
} | ||
|
||
dependencies { | ||
relocate("io.ktor", "dev.mokksy.relocated.io.ktor") | ||
relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization") | ||
} | ||
} |
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.
Safer ShadowJar configuration: correct Kotlin exclude, add service file merging, and avoid relocating public API libs.
- exclude(dependency("kotlin:.:.")) won’t match Kotlin (group is org.jetbrains.kotlin) → risk of stripping stdlib during minimize.
- Many libs (Ktor, serialization) use ServiceLoader resources; merge them to avoid runtime failures.
- Relocating kotlinx.serialization (and possibly io.ktor) can break consumers if any of those types/annotations appear in your public API. Consider making relocations opt-in per-module or restricting to internals-only modules.
-tasks.shadowJar {
-
- minimize {
- exclude(dependency("kotlin:.*:.*"))
- }
-
- dependencies {
- relocate("io.ktor", "dev.mokksy.relocated.io.ktor")
- relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization")
- }
-}
+tasks.named<ShadowJar>("shadowJar") {
+ // Ensure reproducible, distinct artifact
+ archiveClassifier.set("all")
+
+ // Keep Kotlin stdlib/coroutines intact during minimize
+ minimize {
+ exclude(dependency("org.jetbrains.kotlin:.*:.*"))
+ exclude(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-.*:.*"))
+ }
+
+ // Merge service files to preserve SPI wiring
+ mergeServiceFiles()
+
+ // Optional/safer: gate relocations behind a project property
+ val enableRelocation = providers.gradleProperty("shadow.relocate").orElse("false").map { it.toBoolean() }.get()
+ if (enableRelocation) {
+ // WARNING: Do not relocate libraries that leak into your public API
+ relocate("io.ktor", "dev.mokksy.relocated.io.ktor")
+ // Avoid relocating kotlinx.serialization unless it is strictly internal
+ // relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization")
+ }
+}
📝 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.
tasks.shadowJar { | |
minimize { | |
exclude(dependency("kotlin:.*:.*")) | |
} | |
dependencies { | |
relocate("io.ktor", "dev.mokksy.relocated.io.ktor") | |
relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization") | |
} | |
} | |
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") { | |
// Ensure reproducible, distinct artifact | |
archiveClassifier.set("all") | |
// Keep Kotlin stdlib/coroutines intact during minimize | |
minimize { | |
exclude(dependency("org.jetbrains.kotlin:.*:.*")) | |
exclude(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-.*:.*")) | |
} | |
// Merge service files to preserve SPI wiring | |
mergeServiceFiles() | |
// Optional/safer: gate relocations behind a project property | |
val enableRelocation = providers.gradleProperty("shadow.relocate").orElse("false").map { it.toBoolean() }.get() | |
if (enableRelocation) { | |
// WARNING: Do not relocate libraries that leak into your public API | |
relocate("io.ktor", "dev.mokksy.relocated.io.ktor") | |
// Avoid relocating kotlinx.serialization unless it is strictly internal | |
// relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization") | |
} | |
} |
🤖 Prompt for AI Agents
In buildSrc/src/main/kotlin/shadow-convention.gradle.kts around lines 9 to 19,
the ShadowJar config is unsafe: the Kotlin minimize exclude uses the wrong group
(so stdlib may be stripped), service loader files aren’t merged (risking runtime
failures), and relocating public API libraries (kotlinx.serialization, io.ktor)
can break consumers; change the minimize exclude to match org.jetbrains.kotlin
artifacts (e.g. exclude(dependency("org.jetbrains.kotlin:.*:.*"))), configure
the ShadowJar to merge service files (e.g. use mergeServiceFiles() in the
transform/merge configuration), and remove or make relocations opt-in/restricted
to internal modules (do not relocate kotlinx.serialization and avoid relocating
io.ktor unless this jar is strictly internal or provide a flag to apply
relocations per-module).
tasks.assemble { | ||
dependsOn(tasks.shadowJar) | ||
} |
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.
🧹 Nitpick
Assemble depending on shadowJar: consider making it opt-in.
For all modules, this slows builds and forces shading when not needed (e.g., during dev/test). Prefer a separate lifecycle task (e.g., shadowAll
) or guard with a property.
-tasks.assemble {
- dependsOn(tasks.shadowJar)
-}
+if (providers.gradleProperty("shadow.on.assemble").orElse("false").map { it.toBoolean() }.get()) {
+ tasks.named("assemble").configure { dependsOn(tasks.named("shadowJar")) }
+}
If CI depends on shaded jars, set -Pshadow.on.assemble=true in the workflow instead of enforcing it universally.
Makefile
Outdated
rm -rf ~/.m2/repository/me/kpavlov/aimocks ~/.m2/repository/me/kpavlov/mokksy | ||
./gradlew clean build dokkaJavadocJar publishToMavenLocal koverHtmlReport |
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.
Avoid nuking ~/.m2; isolate Maven Local per-project.
Deleting user-wide caches is risky and non‑portable. Prefer a project-scoped Maven local dir via Gradle.
Example:
-build:
- rm -rf ~/.m2/repository/me/kpavlov/aimocks ~/.m2/repository/me/kpavlov/mokksy
- ./gradlew clean build dokkaJavadocJar publishToMavenLocal koverHtmlReport
+build:
+ # Use a project-local Maven repo to avoid wiping ~/.m2
+ ./gradlew \
+ -Dorg.gradle.maven.repo.local=.m2-local \
+ clean build dokkaJavadocJar publishToMavenLocal koverHtmlReport
And similarly in “publish”.
Committable suggestion skipped: line range outside the PR's diff.
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinition.kt
Outdated
Show resolved
Hide resolved
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt
Show resolved
Hide resolved
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: 11
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (8)
ai-mocks-a2a/build.gradle.kts
(2 hunks)ai-mocks-anthropic/build.gradle.kts
(2 hunks)ai-mocks-gemini/build.gradle.kts
(2 hunks)ai-mocks-ollama/build.gradle.kts
(2 hunks)ai-mocks-openai/build.gradle.kts
(2 hunks)ai-mocks-openai/samples/shadow/pom.xml
(1 hunks)buildSrc/src/main/kotlin/publish-convention.gradle.kts
(2 hunks)mokksy/build.gradle.kts
(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: dependency-submission
- GitHub Check: build
- GitHub Check: submit-gradle
🔇 Additional comments (7)
ai-mocks-openai/samples/shadow/pom.xml (3)
7-7
: Typo in artifactId.Use “shadowed”.
- <artifactId>mokksy-openai-shadewed</artifactId> + <artifactId>mokksy-openai-shadowed</artifactId>
26-35
: Scope demo deps to test.These are only used in tests; don’t leak to compile/runtime.
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>1.5.0</version> + <scope>test</scope> </dependency> <dependency> <groupId>com.openai</groupId> <artifactId>openai-java-client-okhttp</artifactId> <version>3.1.2</version> + <scope>test</scope> </dependency>
55-60
: JUnit engine missing — switch to aggregator.Replace junit-jupiter-api with junit-jupiter (brings the engine).
- <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - <version>5.13.4</version> - <scope>test</scope> - </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <version>5.13.4</version> + <scope>test</scope> + </dependency>ai-mocks-openai/build.gradle.kts (1)
8-10
: Remove duplicate Shadow plugin application.shadow-convention already applies com.gradleup.shadow.
`shadow-convention` - id("com.gradleup.shadow")
ai-mocks-gemini/build.gradle.kts (1)
66-77
: Merge shaded jar and sources into one publication.-publishing { - publications { - create<MavenPublication>("shadow") { - artifactId = project.name + "-all" - artifact(tasks["shadowJar"]) - } - create<MavenPublication>("shadowSourcesJar") { - artifactId = project.name + "-all" - artifact(tasks["jvmSourcesJar"]) - } - } -} +publishing { + publications { + create<MavenPublication>("shadowAll") { + artifactId = project.name + "-all" + artifact(tasks.named("shadowJar")) + artifact(tasks.named("jvmSourcesJar")) + } + } +}ai-mocks-ollama/build.gradle.kts (1)
72-83
: Prevent repository conflicts: publish one GAV with multiple artifacts.-publishing { - publications { - create<MavenPublication>("shadow") { - artifactId = project.name + "-all" - artifact(tasks["shadowJar"]) - } - create<MavenPublication>("shadowSourcesJar") { - artifactId = project.name + "-all" - artifact(tasks["jvmSourcesJar"]) - } - } -} +publishing { + publications { + create<MavenPublication>("shadowAll") { + artifactId = project.name + "-all" + artifact(tasks.named("shadowJar")) + artifact(tasks.named("jvmSourcesJar")) + } + } +}buildSrc/src/main/kotlin/publish-convention.gradle.kts (1)
68-71
: SCM URLs: use canonical forms — manual verification requiredBlocked: Gradle daemon failed to start and ~/.m2/repository is missing in the sandbox; run ./gradlew :ai-mocks-openai:publishToMavenLocal -x test locally and confirm the generated POM's scm entries.
File: buildSrc/src/main/kotlin/publish-convention.gradle.kts (lines 68–71)
- connection = "scm:git:git://github.com/mokksy/ai-mocks.git" - developerConnection = "scm:git:ssh://github.com/mokksy/ai-mocks.git" - url = "https://github.com/mokksy/ai-mocks" + connection = "scm:git:https://github.com/mokksy/ai-mocks.git" + developerConnection = "scm:git:ssh://[email protected]/mokksy/ai-mocks.git" + url = "https://github.com/mokksy/ai-mocks"
ai-mocks-gemini/build.gradle.kts
Outdated
tasks.shadowJar { | ||
archiveClassifier = "" | ||
archiveExtension = "jar" | ||
} |
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.
Use .set(...) for archive properties in Kotlin DSL.
-tasks.shadowJar {
- archiveClassifier = ""
- archiveExtension = "jar"
-}
+tasks.shadowJar {
+ archiveClassifier.set("")
+ archiveExtension.set("jar")
+}
📝 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.
tasks.shadowJar { | |
archiveClassifier = "" | |
archiveExtension = "jar" | |
} | |
tasks.shadowJar { | |
archiveClassifier.set("") | |
archiveExtension.set("jar") | |
} |
🤖 Prompt for AI Agents
In ai-mocks-gemini/build.gradle.kts around lines 61 to 64, the Kotlin DSL
archive properties are being set via assignment which is incorrect; replace the
direct assignments with the property setters (use archiveClassifier.set("") and
archiveExtension.set("jar")) to correctly configure the shadowJar task in Kotlin
DSL.
ai-mocks-openai/build.gradle.kts
Outdated
tasks.shadowJar { | ||
archiveClassifier = "" | ||
archiveExtension = "jar" | ||
} |
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.
Kotlin DSL fix: set archive props via .set(...).
-tasks.shadowJar {
- archiveClassifier = ""
- archiveExtension = "jar"
-}
+tasks.shadowJar {
+ archiveClassifier.set("")
+ archiveExtension.set("jar")
+}
🤖 Prompt for AI Agents
In ai-mocks-openai/build.gradle.kts around lines 65 to 68, the ShadowJar task is
setting archiveClassifier and archiveExtension using direct assignment which is
invalid in Kotlin DSL; replace those assignments with the property setters, e.g.
call archiveClassifier.set("") and archiveExtension.set("jar") on the task's
archive properties so the values are configured via the Gradle Property API.
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" | ||
xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>com.example</groupId> | ||
<artifactId>mokksy-openai-shadewed</artifactId> | ||
<version>1.0.0-SNAPSHOT</version> | ||
|
||
<properties> | ||
<java.version>17</java.version> | ||
<maven.compiler.release>${java.version}</maven.compiler.release> | ||
</properties> | ||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>org.jetbrains.kotlin</groupId> | ||
<artifactId>kotlin-bom</artifactId> | ||
<version>1.9.25</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>dev.langchain4j</groupId> | ||
<artifactId>langchain4j-open-ai</artifactId> | ||
<version>1.5.0</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.openai</groupId> | ||
<artifactId>openai-java-client-okhttp</artifactId> | ||
<version>3.1.2</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-simple</artifactId> | ||
<version>2.0.17</version> | ||
<scope>runtime</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.assertj</groupId> | ||
<artifactId>assertj-core</artifactId> | ||
<version>3.27.4</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>me.kpavlov.aimocks</groupId> | ||
<artifactId>ai-mocks-openai-all</artifactId> | ||
<version>0.5.0-SNAPSHOT</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-api</artifactId> | ||
<version>5.13.4</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
</project> |
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.
Pin Surefire for JUnit 5.
Without an explicit surefire ≥2.22, Jupiter tests may not run.
</dependencies>
</project>
+<build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>3.5.0</version>
+ </plugin>
+ </plugins>
+ <pluginManagement/>
+</build>
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In ai-mocks-openai/samples/shadow/pom.xml around lines 1 to 61, the POM lacks an
explicit Maven Surefire Plugin declaration so JUnit Jupiter tests may not run;
add a build->plugins entry declaring maven-surefire-plugin with a version >=
2.22 (e.g., 2.22.2 or a newer stable release) to ensure Surefire runs JUnit 5
tests, or alternatively configure the Maven Surefire Provider for JUnit
Platform; place this plugin configuration inside a <build><plugins> section in
the pom.
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: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
.editorconfig (1)
43-46
: Also set indent_style=tab for XML.Keep Kotlin/XML consistent; otherwise IDEs may mix tabs/spaces.
[*.xml] +indent_style = tab tab_width = 4 indent_size = tab
ai-mocks-ollama/build.gradle.kts (1)
43-51
: Duplicate dependency: langchain4j-kotlin listed twice.Remove one to keep the graph clean.
implementation(libs.langchain4j.kotlin) // Note: There's no specific Ollama client in langchain4j or spring-ai yet // If/when they become available, they should be added here implementation(project.dependencies.platform(libs.langchain4j.bom)) implementation(project.dependencies.platform(libs.spring.ai.bom)) implementation(project.dependencies.platform(libs.spring.bom)) - implementation(libs.langchain4j.kotlin) implementation(libs.langchain4j.ollama)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (12)
.editorconfig
(2 hunks).github/workflows/gradle.yml
(2 hunks)Makefile
(2 hunks)RELEASE.md
(1 hunks)ai-mocks-a2a/build.gradle.kts
(2 hunks)ai-mocks-anthropic/build.gradle.kts
(2 hunks)ai-mocks-gemini/build.gradle.kts
(2 hunks)ai-mocks-ollama/build.gradle.kts
(2 hunks)ai-mocks-openai/build.gradle.kts
(2 hunks)ai-mocks-openai/samples/shadow/pom.xml
(1 hunks)ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt
(1 hunks)mokksy/build.gradle.kts
(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (11)
ai-mocks-openai/samples/shadow/pom.xml (4)
7-7
: Typo in artifactId.- <artifactId>mokksy-openai-shadewed</artifactId> + <artifactId>mokksy-openai-shadowed</artifactId>
26-35
: Scope demo client deps to test.These are only needed by tests.
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>1.5.0</version> + <scope>test</scope> </dependency> <dependency> <groupId>com.openai</groupId> <artifactId>openai-java-client-okhttp</artifactId> <version>3.1.2</version> + <scope>test</scope> </dependency>
55-60
: JUnit engine missing — use aggregator or add engine.- <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - <version>5.13.4</version> - <scope>test</scope> - </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <version>5.13.4</version> + <scope>test</scope> + </dependency>
1-61
: Pin Surefire to run JUnit 5.Ensure a modern surefire runs Jupiter tests.
</dependencies> +</project> +<build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.5.0</version> + </plugin> + </plugins> +</build> -</project>ai-mocks-openai/build.gradle.kts (1)
8-9
: Remove duplicate Shadow plugin application.shadow-convention already applies com.gradleup.shadow.
- `shadow-convention` - id("com.gradleup.shadow") + `shadow-convention`Makefile (2)
3-5
: Don’t delete ~/.m2; use a project-local Maven repo.Safer and CI-friendly; avoids nuking user caches.
- rm -rf ~/.m2/repository/me/kpavlov/aimocks ~/.m2/repository/me/kpavlov/mokksy && \ - ./gradlew --rerun-tasks clean build publishToMavenLocal koverHtmlReport && \ - (cd ai-mocks-openai/samples/shadow && mvn test) + ./gradlew --rerun-tasks \ + -Dorg.gradle.maven.repo.local=.m2-local \ + clean build publishToMavenLocal koverHtmlReport && \ + (cd ai-mocks-openai/samples/shadow && mvn -Dmaven.repo.local=.m2-local test)
48-49
: Same here: avoid rm -rf on ~/.m2 and publish to project-local repo.- ./gradlew --rerun-tasks clean build check sourcesJar publishToMavenLocal + ./gradlew --rerun-tasks \ + -Dorg.gradle.maven.repo.local=.m2-local \ + clean build check sourcesJar publishToMavenLocalai-mocks-anthropic/build.gradle.kts (1)
62-75
: Use lazy task providers in publication.Prevents eager configuration and speeds up configuration time.
- artifact(tasks["shadowJar"]) { + artifact(tasks.named("shadowJar")) { classifier = "" extension = "jar" } - artifact(tasks["jvmSourcesJar"]) { + artifact(tasks.named("jvmSourcesJar")) { classifier = "sources" }ai-mocks-ollama/build.gradle.kts (1)
67-80
: Use lazy providers for artifacts in publication.- artifact(tasks["shadowJar"]) { + artifact(tasks.named("shadowJar")) { classifier = "" extension = "jar" } - artifact(tasks["jvmSourcesJar"]) { + artifact(tasks.named("jvmSourcesJar")) { classifier = "sources" }mokksy/build.gradle.kts (1)
8-8
: Confirm shadowJar task sets empty classifier at the task level.If the empty classifier isn’t set on the ShadowJar task (via the convention), publishing with
classifier = ""
here won’t rename the produced file; it only affects POM metadata. Prefer configuringarchiveClassifier.set("")
on the task and keep the publication clean..github/workflows/gradle.yml (1)
59-61
: Align Maven sample to JDK 17 before mvn test.The Maven sample compiles for Java 17; switch toolchain before running tests.
Apply this diff:
+ - name: Set up JDK 17 for Maven sample + uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: 'temurin' - name: OpenAI Maven Integration Tests working-directory: ai-mocks-openai/samples/shadow run: mvn --batch-mode test
[*.{kt,kts}] | ||
indent_size = 4 | ||
tab_width = 4 | ||
indent_size = tab | ||
max_line_length = 100 |
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.
Set indent_style=tab for Kotlin to match indent_size=tab.
Without indent_style=tab, many tools will still insert spaces despite indent_size=tab.
Apply:
[*.{kt,kts}]
+indent_style = tab
tab_width = 4
indent_size = tab
max_line_length = 100
📝 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.
[*.{kt,kts}] | |
indent_size = 4 | |
tab_width = 4 | |
indent_size = tab | |
max_line_length = 100 | |
[*.{kt,kts}] | |
indent_style = tab | |
tab_width = 4 | |
indent_size = tab | |
max_line_length = 100 |
🤖 Prompt for AI Agents
In .editorconfig around lines 26 to 29, the Kotlin section lacks an indent_style
setting causing some tools to insert spaces; add "indent_style = tab" to the
[*.{kt,kts}] block so it explicitly uses tabs to match indent_size = tab and
prevent tools from defaulting to spaces.
.github/workflows/gradle.yml
Outdated
- name: Build with Gradle | ||
run: gradle clean build dokkaGenerate dokkaJavadocJar sourcesJar koverXmlReport | ||
run: ./gradlew --rerun-tasks --no-daemon clean build publishToMavenLocal koverXmlReport |
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.
🧹 Nitpick
Minor: Add Maven cache to speed up the sample test.
Caching ~/.m2/repository
cuts test time and avoids re-downloading the shaded artifact.
Apply this diff just before the Maven test step:
+ - name: Cache Maven repository
+ uses: actions/cache@v4
+ with:
+ path: ~/.m2/repository
+ key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ maven-${{ runner.os }}-
📝 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.
run: ./gradlew --rerun-tasks --no-daemon clean build publishToMavenLocal koverXmlReport | |
run: ./gradlew --rerun-tasks --no-daemon clean build publishToMavenLocal koverXmlReport | |
- name: Cache Maven repository | |
uses: actions/cache@v4 | |
with: | |
path: ~/.m2/repository | |
key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} | |
restore-keys: | | |
maven-${{ runner.os }}- |
🤖 Prompt for AI Agents
.github/workflows/gradle.yml around line 57: the workflow currently reruns
Gradle tasks without caching Maven artifacts which slows tests and re-downloads
the shaded artifact; add an actions/cache step immediately before the
Maven/Gradle test step that caches ~/.m2/repository with an appropriate key
(e.g., runnerOS + hash of relevant build files like settings.gradle or
build.gradle(.kts) or pom.xml) and a restore-keys fallback so the cache is
restored on subsequent runs to speed up the sample test.
publishing { | ||
publications { | ||
create<MavenPublication>("shadow") { | ||
artifactId = project.name + "-standalone" | ||
artifact(tasks["shadowJar"]) { | ||
classifier = "" | ||
extension = "jar" | ||
} | ||
artifact(tasks["jvmSourcesJar"]) { | ||
classifier = "sources" | ||
} | ||
} | ||
} | ||
} |
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.
🧹 Nitpick
Switch to lazy providers for publication artifacts.
- artifact(tasks["shadowJar"]) {
+ artifact(tasks.named("shadowJar")) {
classifier = ""
extension = "jar"
}
- artifact(tasks["jvmSourcesJar"]) {
+ artifact(tasks.named("jvmSourcesJar")) {
classifier = "sources"
}
📝 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.
publishing { | |
publications { | |
create<MavenPublication>("shadow") { | |
artifactId = project.name + "-standalone" | |
artifact(tasks["shadowJar"]) { | |
classifier = "" | |
extension = "jar" | |
} | |
artifact(tasks["jvmSourcesJar"]) { | |
classifier = "sources" | |
} | |
} | |
} | |
} | |
publishing { | |
publications { | |
create<MavenPublication>("shadow") { | |
artifactId = project.name + "-standalone" | |
artifact(tasks.named("shadowJar")) { | |
classifier = "" | |
extension = "jar" | |
} | |
artifact(tasks.named("jvmSourcesJar")) { | |
classifier = "sources" | |
} | |
} | |
} | |
} |
🤖 Prompt for AI Agents
In ai-mocks-a2a/build.gradle.kts around lines 68 to 81, switch direct task
accesses to lazy providers so publication artifact references are evaluated
lazily: replace tasks["shadowJar"] and tasks["jvmSourcesJar"] with
tasks.named("shadowJar") and tasks.named("jvmSourcesJar") (or the corresponding
TaskProvider variables) when calling artifact(...), and configure
classifier/extension inside the artifact block; this ensures the publication
uses TaskProvider-based lazy evaluation and avoids eager task realization during
configuration.
publishing { | ||
publications { | ||
create<MavenPublication>("shadow") { | ||
artifactId = project.name + "-standalone" | ||
artifact(tasks["shadowJar"]) { | ||
classifier = "" | ||
extension = "jar" | ||
} | ||
artifact(tasks["jvmSourcesJar"]) { | ||
classifier = "sources" | ||
} | ||
} |
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.
🧹 Nitpick
Avoid eager task realization in publishing.
Use tasks.named(...) providers for publication artifacts.
- create<MavenPublication>("shadow") {
+ create<MavenPublication>("shadow") {
artifactId = project.name + "-standalone"
- artifact(tasks["shadowJar"]) {
+ artifact(tasks.named("shadowJar")) {
classifier = ""
extension = "jar"
}
- artifact(tasks["jvmSourcesJar"]) {
+ artifact(tasks.named("jvmSourcesJar")) {
classifier = "sources"
}
}
🤖 Prompt for AI Agents
In ai-mocks-openai/build.gradle.kts around lines 65-76, the publication
currently realizes tasks eagerly via tasks["shadowJar"] and
tasks["jvmSourcesJar"]; replace those with task providers using
tasks.named("shadowJar") and tasks.named("jvmSourcesJar") so the publication
references task providers instead of forcing task realization. Update the
artifact calls to pass the TaskProvider for each artifact and keep the
classifier/extension configuration in the artifact block.
name = "MockOpenai", | ||
verbose = verbose, | ||
) { config -> |
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.
🧹 Nitpick
🧩 Analysis chain
Named server improves observability; verify uniqueness expectations in mokksy.
Hard‑coding name = "MockOpenai"
is fine and helpful for logs/tracing. If mokksy enforces unique names per running server, parallel tests or multiple mock instances could collide. Please confirm uniqueness semantics and whether we need a follow‑up to allow overriding the name in tests (without changing the current public API).
Run this to spot other ServerConfiguration(
call sites lacking an explicit name
:
🏁 Script executed:
#!/bin/bash
# Inspect nearby args for each ServerConfiguration usage
rg -nP --type=kt -C3 '\bServerConfiguration\s*\('
Length of output: 26
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Searching repo for ServerConfiguration occurrences..."
rg -n -C3 'ServerConfiguration' || true
echo "----"
echo "Searching for name assignments (literal 'name = ' and 'name=')..."
rg -n -C1 'name =' || true
rg -n -C1 'name=' || true
echo "----"
echo "Searching for occurrences of MockOpenai..."
rg -n -C3 'MockOpenai' || true
echo "----"
FILE=ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt
if [ -f "$FILE" ]; then
echo "Printing $FILE (first 200 lines):"
sed -n '1,200p' "$FILE" || true
else
echo "$FILE not found; listing Kotlin files under ai-mocks-openai:"
rg -n --hidden --glob 'ai-mocks-openai/**' '\.kt' || true
fi
Length of output: 96903
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Print MokksyServer.kt (first 400 lines) ==="
sed -n '1,400p' mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/MokksyServer.kt || true
echo
echo "=== Search for configuration.name usages ==="
rg -n --hidden --no-ignore-vcs --type kotlin 'configuration\.name' || true
echo
echo "=== Search for accessing ServerConfiguration.name or comparing server names ==="
rg -n --hidden --no-ignore-vcs --type kotlin 'ServerConfiguration|configuration.name|configuration\\.name|\\.name\\s*==' || true
echo
echo "=== Search for global server registry/collection variables (servers, activeServers, instances) ==="
rg -n --hidden --no-ignore-vcs --type kotlin '\bservers\b|\bactiveServers\b|\binstances\b|\bregistered\b' || true
Length of output: 27099
Named server improves observability — Mokksy does not enforce unique server names; consider making the mock name overridable
ServerConfiguration defaults to name = "Mokksy" and mokksy has no global registry/enforcement of unique server names; the name is used only for logging/stub toString (ServerConfiguration.kt; AbstractMockLlm.kt; Stub.kt). MockOpenai sets name = "MockOpenai" (ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt:33–36) while many other mocks rely on the default. No runtime collision will be thrown by mokksy, but identical names can make logs ambiguous in parallel tests — consider adding an optional name parameter/overload on MockOpenai (and other mocks) to allow tests to override the server name for clearer observability.
🤖 Prompt for AI Agents
In ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt
around lines 34 to 36, MockOpenai hardcodes name = "MockOpenai", which can
create ambiguous logs in parallel tests; add an optional name parameter (with
default "MockOpenai") to the MockOpenai constructor or factory overload and pass
that value into the ServerConfiguration creation instead of the hardcoded
string; update callers/tests to accept the new optional parameter as needed and
mirror this pattern on other mock classes if desired for consistency.
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: 15
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt (1)
3-14
: Fix missing import for ChatCompletionRequest (compile error)
ChatCompletionRequest::class
is referenced but not imported; it’s in...openai.model.chat
. Add the import.import me.kpavlov.aimocks.openai.responses.OpenaiResponsesRequestSpecification +import me.kpavlov.aimocks.openai.model.chat.ChatCompletionRequest import me.kpavlov.mokksy.ServerConfiguration
Also applies to: 56-59
ai-mocks-anthropic/build.gradle.kts (1)
1-9
: Shading strategy: confirm relocations to prevent clashes (esp. ktor/kotlinx)For “standalone” artifacts, verify relocation rules in
shadow-convention
don’t relocate Kotlin stdlib/ktor/kotlinx unless intentional; relocating these can break consumers.ai-mocks-openai/samples/OpenaiLc4jSample.ipynb (1)
75-87
: Replace unsupported DSL call with a supported overload.The model.chat { … } builder isn’t available; call an existing overload.
- val result = - model.chat { - parameters = - OpenAiChatRequestParameters - .builder() - .maxCompletionTokens(120) - .temperature(0.42) - .modelName("4o") - .seed(100500) - .build() - messages += userMessage("Say Hello") - } + val result = model.chat(userMessage("Say Hello")).github/workflows/gradle.yml (1)
63-71
: Include Maven Surefire reports in the JUnit summary.Current glob only catches Gradle reports; add Surefire to see Maven test results.
- name: Publish Test Report uses: mikepenz/action-junit-report@v5 if: success() || failure() # always run even if the previous step fails with: - report_paths: '**/test-results/**/TEST-*.xml' + report_paths: | + **/test-results/**/TEST-*.xml + **/surefire-reports/TEST-*.xml annotate_only: true detailed_summary: true flaky_summary: true include_empty_in_summary: false skip_success_summary: truemokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt (3)
52-54
: Builder mutator desyncs status fields
httpStatus(status: Int)
updates onlyhttpStatus
, leavinghttpStatusCode
stale. Add an overload and set both.- public fun httpStatus(status: Int) { - this.httpStatus = HttpStatusCode.fromValue(status) - } + public fun httpStatus(status: Int) { + this.httpStatusCode = status + this.httpStatus = HttpStatusCode.fromValue(status) + } + + public fun httpStatus(status: HttpStatusCode) { + this.httpStatusCode = status.value + this.httpStatus = status + }
116-124
: Streaming builder passes only httpStatus; httpStatusCode remains 200Forward both to the base builder to keep invariants and avoid 200/XXX mismatches.
) : AbstractResponseDefinitionBuilder<P, T>( - httpStatus = httpStatus, - headers = headers - ) { + httpStatusCode = httpStatus.value, + httpStatus = httpStatus, + headers = headers + ) {
136-145
: StreamResponseDefinition build omits httpStatusCodePass
httpStatusCode
to the product to avoid defaulting to 200.public override fun build(): StreamResponseDefinition<P, T> = StreamResponseDefinition( chunkFlow = flow, chunks = chunks.toList(), + httpStatusCode = httpStatusCode, httpStatus = httpStatus, headers = headersLambda, headerList = Collections.unmodifiableList(headers), delayBetweenChunks = delayBetweenChunks, delay = delay, )
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (22)
.editorconfig
(2 hunks).github/workflows/gradle.yml
(2 hunks)Makefile
(2 hunks)RELEASE.md
(1 hunks)ai-mocks-a2a/build.gradle.kts
(2 hunks)ai-mocks-anthropic/build.gradle.kts
(2 hunks)ai-mocks-gemini/build.gradle.kts
(2 hunks)ai-mocks-ollama/build.gradle.kts
(2 hunks)ai-mocks-openai/build.gradle.kts
(2 hunks)ai-mocks-openai/samples/OpenaiLc4jSample.ipynb
(6 hunks)ai-mocks-openai/samples/shadow/pom.xml
(1 hunks)ai-mocks-openai/samples/shadow/src/test/java/com/example/OpenAITest.java
(1 hunks)ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt
(1 hunks)buildSrc/build.gradle.kts
(1 hunks)buildSrc/src/main/kotlin/dokka-convention.gradle.kts
(1 hunks)buildSrc/src/main/kotlin/publish-convention.gradle.kts
(2 hunks)buildSrc/src/main/kotlin/shadow-convention.gradle.kts
(1 hunks)mokksy/build.gradle.kts
(2 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/AbstractResponseDefinition.kt
(1 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinition.kt
(2 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt
(3 hunks)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/StreamResponseDefinition.kt
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
ai-mocks-openai/samples/shadow/src/test/java/com/example/OpenAITest.java (4)
ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt (3)
baseUrl
(133-133)completion
(45-49)completion
(51-92)mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt (4)
build
(61-61)build
(91-100)build
(136-145)delayMillis
(48-50)ai-mocks-core/src/commonMain/kotlin/me/kpavlov/aimocks/core/ModelRequestSpecification.kt (1)
requestBodyContains
(46-49)ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/model/chat/ChatCompletionRequestBuilder.kt (1)
maxCompletionTokens
(135-138)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Codacy Static Code Analysis
- GitHub Check: build
🔇 Additional comments (26)
.editorconfig (3)
40-40
: LGTM: build-scope import-on-demand override is clear.Scoped formatting for build Kotlin files is explicit and consistent.
26-29
: Set indent_style=tab for Kotlin to actually use tabs.Currently inherits indent_style=space from [*]; many tools will keep inserting spaces even with indent_size=tab.
[*.{kt,kts}] tab_width = 4 indent_size = tab +indent_style = tab max_line_length = 100
43-45
: Don't add indent_style = tab — repository XML files are space‑indented.Set [*.xml] to
indent_style = space
andindent_size = 4
in .editorconfig (lines ~43–45), or convert the XML files (e.g. ai-mocks-openai/samples/shadow/pom.xml) to tabs before addingindent_style = tab
.Likely an incorrect or invalid review comment.
buildSrc/src/main/kotlin/dokka-convention.gradle.kts (1)
23-27
: LGTM — formatting‑only changeNo behavioral impact.
ai-mocks-openai/src/commonMain/kotlin/me/kpavlov/aimocks/openai/MockOpenai.kt (1)
27-36
: Allow overriding server name to avoid ambiguous logs in parallel runsMake the name configurable with a default.
-public open class MockOpenai( - - port: Int = 0, - verbose: Boolean = true, -) : AbstractMockLlm( +public open class MockOpenai( + port: Int = 0, + verbose: Boolean = true, + name: String = "MockOpenai", +) : AbstractMockLlm( port = port, configuration = ServerConfiguration( - name = "MockOpenai", + name = name, verbose = verbose, ) { config ->RELEASE.md (1)
16-16
: Make --rerun-tasks opt‑in; don’t slow releases by defaultIt bypasses up‑to‑date checks and remote cache without clear benefit for publish flows.
- --stacktrace --rerun-tasks --warning-mode=all \ + --stacktrace --warning-mode=all \Consider adding a short note below the snippet: “If you suspect stale outputs or changed publishing metadata, append --rerun-tasks.”
Makefile (2)
3-5
: Do not delete user‑wide ~/.m2; use a project‑local Maven repo and drop --rerun-tasksSafer for contributors/CI and faster via caching.
-build: - rm -rf ~/.m2/repository/me/kpavlov/aimocks ~/.m2/repository/me/kpavlov/mokksy && \ - ./gradlew --rerun-tasks clean build publishToMavenLocal koverHtmlReport && \ - (cd ai-mocks-openai/samples/shadow && mvn test) +build: + ./gradlew -Dorg.gradle.maven.repo.local=.m2-local \ + clean build publishToMavenLocal koverHtmlReport && \ + (cd ai-mocks-openai/samples/shadow && mvn -Dmaven.repo.local="$(PWD)/.m2-local" test)
47-49
: Same here: avoid nuking ~/.m2 and make reruns opt‑inKeep builds isolated and cache‑friendly.
-publish: - rm -rf ~/.m2/repository/me/kpavlov/aimocks ~/.m2/repository/me/kpavlov/mokksy - ./gradlew --rerun-tasks clean build check sourcesJar publishToMavenLocal +publish: + ./gradlew -Dorg.gradle.maven.repo.local=.m2-local \ + clean build check sourcesJar publishToMavenLocalai-mocks-openai/samples/shadow/src/test/java/com/example/OpenAITest.java (2)
32-39
: Make tests deterministicRandomized params can cause flakiness; use fixed values and no‑op setup.
- private double temperature; - private long maxTokens; + private double temperature = 0.42; + private long maxTokens = 256; @@ - void beforeEach() { - temperature = RANDOM.nextDouble(0.0, 1.0); - maxTokens = RANDOM.nextLong(100, 500); - } + void beforeEach() { /* deterministic */ }
59-61
: Remove redundant role override for user message
ofUser(...)
already impliesrole=user
.- ChatCompletionUserMessageParam.builder() - .role(JsonValue.from("user")) - .content("Just say 'Hey!'").build()))) + ChatCompletionUserMessageParam.builder() + .content("Just say 'Hey!'").build())))ai-mocks-a2a/build.gradle.kts (1)
68-81
: Switch to lazy providers for artifactsAlign with other modules and best practices.
- create<MavenPublication>("shadow") { + create<MavenPublication>("shadow") { artifactId = project.name + "-standalone" - artifact(tasks["shadowJar"]) { + artifact(tasks.named("shadowJar")) { classifier = "" extension = "jar" } - artifact(tasks["jvmSourcesJar"]) { + artifact(tasks.named("jvmSourcesJar")) { classifier = "sources" } }buildSrc/build.gradle.kts (1)
16-16
: No action needed — Shadow 9.1.0 is compatible with the Gradle wrapper (9.1.0).gradle/wrapper/gradle-wrapper.properties shows Gradle 9.1.0; buildSrc/build.gradle.kts:16 pins com.gradleup.shadow:shadow-gradle-plugin:9.1.0. Shadow 9.1.0 requires Gradle ≥8.11 (compatible with Gradle 9) and Java 11+ — ensure CI/dev JDK is ≥11.
ai-mocks-openai/samples/shadow/pom.xml (3)
7-7
: Typo in artifactId.Use “shadowed”.
- <artifactId>mokksy-openai-shadewed</artifactId> + <artifactId>mokksy-openai-shadowed</artifactId>
26-35
: Scope demo client deps to test.Prevent leaking to compile/runtime.
<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai</artifactId> <version>1.5.0</version> + <scope>test</scope> </dependency> <dependency> <groupId>com.openai</groupId> <artifactId>openai-java-client-okhttp</artifactId> <version>3.1.2</version> + <scope>test</scope> </dependency>
55-60
: JUnit engine missing; pin Surefire.Use the aggregator that brings the engine and ensure Surefire ≥2.22.
- <dependency> - <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter-api</artifactId> - <version>5.13.4</version> - <scope>test</scope> - </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <version>5.13.4</version> + <scope>test</scope> + </dependency>Also add (near end of POM):
</dependencies> +<build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <version>3.5.0</version> + </plugin> + </plugins> +</build> </project>ai-mocks-openai/build.gradle.kts (1)
8-9
: Remove duplicate Shadow plugin.shadow-convention already applies com.gradleup.shadow.
`shadow-convention` - id("com.gradleup.shadow")
ai-mocks-openai/samples/OpenaiLc4jSample.ipynb (1)
99-125
: Notebook execution currently fails — verify stub DSL names.Errors show unresolved identifiers (assistantContent, finishReason). Confirm the actual DSL property names exposed by MockOpenai completion/responds builders and update the cell accordingly.
buildSrc/src/main/kotlin/publish-convention.gradle.kts (3)
46-50
: POM metadata assignments look good.
53-55
: License block is correct.
73-76
: Issue management block looks good.buildSrc/src/main/kotlin/shadow-convention.gradle.kts (4)
1-1
: Fix ShadowJar import for GradleUp fork.Use the GradleUp task class; drop the Companion accessor.
-import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.Companion.shadowJar +import com.gradleup.shadow.tasks.ShadowJar
3-7
: Use corebase
plugin id.
org.gradle.base
is not a valid id. Use thebase
plugin.plugins { `maven-publish` - id("org.gradle.base") + base id("com.gradleup.shadow") // https://gradleup.com/shadow }
9-20
: Harden ShadowJar config: correct minimize excludes, merge SPI files, avoid relocating Kotlin/public API, and use typed task access.
- Wrong exclude pattern risks stripping Kotlin stdlib.
- Missing mergeServiceFiles() can break ServiceLoader at runtime.
- Relocating
kotlin
(and oftenkotlinx.serialization
) is dangerous; avoid unless strictly internal.- Prefer
tasks.named<ShadowJar>("shadowJar")
.-tasks.shadowJar { - - minimize { - exclude(dependency("kotlin:.*:.*")) - } - - dependencies { - relocate("io.ktor", "dev.mokksy.relocated.io.ktor") - relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization") - relocate("kotlin", "dev.mokksy.relocated.kotlin") - } -} +tasks.named<ShadowJar>("shadowJar") { + archiveClassifier.set("all") + + minimize { + // Keep Kotlin + Coroutines + exclude(dependency("org.jetbrains.kotlin:.*:.*")) + exclude(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-.*:.*")) + } + + // Preserve SPI wiring + mergeServiceFiles() + + // Optional: enable relocations with -Pshadow.relocate=true + val enableRelocation = providers.gradleProperty("shadow.relocate") + .map(String::toBoolean).getOrElse(false) + if (enableRelocation) { + // Avoid relocating libraries that leak into public API + relocate("io.ktor", "dev.mokksy.relocated.io.ktor") + // Consider NOT relocating kotlinx.serialization unless fully internal + // relocate("kotlinx.serialization", "dev.mokksy.relocated.kotlinx.serialization") + } +}
22-24
: Don’t force shading on every assemble; gate behind a property.Keeps local/dev builds fast; enable in CI with -Pshadow.on.assemble=true.
-tasks.assemble { - dependsOn(tasks.shadowJar) -} +if (providers.gradleProperty("shadow.on.assemble").map(String::toBoolean).getOrElse(false)) { + tasks.named("assemble").configure { + dependsOn(tasks.named("shadowJar")) + } +}.github/workflows/gradle.yml (1)
57-61
: Set JDK 17 for Maven sample and cache ~/.m2.The sample POM targets Java 17; run Maven tests on JDK 17 and cache the Maven repo.
- name: Build with Gradle run: ./gradlew --rerun-tasks --no-daemon clean build publishToMavenLocal koverXmlReport + - name: Set up JDK 17 for Maven sample + uses: actions/setup-java@v5 + with: + java-version: 17 + distribution: temurin + + - name: Cache Maven repository + uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: maven-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} + restore-keys: | + maven-${{ runner.os }}- + - name: OpenAI Maven Integration Tests working-directory: ai-mocks-openai/samples/shadow run: mvn --batch-mode testmokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinition.kt (1)
31-33
: Compilation error: default parameter references a later parameter
httpStatusCode: Int = httpStatus.value
is illegal in Kotlin. Fix the defaults.- httpStatusCode: Int = httpStatus.value, - httpStatus: HttpStatusCode = HttpStatusCode.fromValue(httpStatusCode), + httpStatusCode: Int = 200, + httpStatus: HttpStatusCode = HttpStatusCode.fromValue(httpStatusCode),
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinition.kt
Show resolved
Hide resolved
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt
Show resolved
Hide resolved
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/ResponseDefinitionBuilders.kt
Show resolved
Hide resolved
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/StreamResponseDefinition.kt
Show resolved
Hide resolved
mokksy/src/commonMain/kotlin/me/kpavlov/mokksy/response/StreamResponseDefinition.kt
Show resolved
Hide resolved
- Introduced `shadow-convention` in build scripts for multiple modules. - Enabled `shadow` publication in Maven configuration. - Added sample OpenAI `pom.xml` and example tests utilizing MockOpenai. - Added `httpStatusCode` with default value `200` in response classes and builders.
Adds shadow (shaded artifact) support and publishing across modules, updates CI to use the Gradle wrapper and adds a dependency-submission job, introduces a Maven sample with OpenAI integration tests, updates Makefile and .editorconfig formatting, and changes mokksy response APIs to accept numeric HTTP status codes with derived HttpStatusCode.