Skip to content

Commit 3bc060c

Browse files
authored
Add CI matrix testing and fix dependency scopes (#2)
## Summary - **Bump Spring Boot baseline** to 3.5.12 (Spring Framework 6.2.17) — lowest actively supported version - **Fix kafka-clients scope** from `implementation` to `compileOnly` — consumer provides their own version - **Add CI version matrix** testing okapi-spring-boot with Spring Boot 3.5/4.0 and okapi-kafka with Kafka 3.9/4.0 - **Fix MockProducer compat** — updated constructor for Kafka 3.9/4.0 cross-compatibility - **Document** supported versions in README and dependency strategy in CLAUDE.md ## Verified compatibility | Module | Versions tested | |--------|----------------| | okapi-spring-boot | Spring Boot 3.5.12 + 4.0.4 | | okapi-kafka | Kafka 3.9.0 + 4.0.2 | ## Test plan - [x] `./gradlew test` — all tests pass with baseline versions - [x] `./gradlew :okapi-spring-boot:test -PspringBootVersion=4.0.4 -PspringVersion=7.0.6` — passes - [x] `./gradlew :okapi-kafka:test -PkafkaVersion=4.0.2` — passes - [ ] CI workflow runs on this PR (first run)
1 parent bdb43eb commit 3bc060c

6 files changed

Lines changed: 100 additions & 11 deletions

File tree

.github/workflows/ci.yml

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ permissions:
1010
pull-requests: write # auto-merge requirement
1111

1212
jobs:
13-
ci:
13+
build:
14+
name: Build & Test (core modules)
1415
runs-on: ubuntu-24.04
1516
strategy:
1617
fail-fast: false
@@ -32,8 +33,8 @@ jobs:
3233
- name: Check formatting
3334
run: ./gradlew ktlintCheck
3435

35-
- name: Test
36-
run: ./gradlew test
36+
- name: Build and test core modules
37+
run: ./gradlew build -x :okapi-spring-boot:test -x :okapi-kafka:test -x ktlintCheck
3738

3839
- name: Upload test results
3940
uses: actions/upload-artifact@v7
@@ -42,10 +43,53 @@ jobs:
4243
name: test-results-java-${{ matrix.java }}
4344
path: '**/build/test-results/test/TEST-*.xml'
4445

46+
spring-compat:
47+
name: "Spring Boot ${{ matrix.spring-boot }}"
48+
runs-on: ubuntu-24.04
49+
needs: build
50+
strategy:
51+
matrix:
52+
include:
53+
- spring-boot: "3.5.12"
54+
spring: "6.2.17"
55+
- spring-boot: "4.0.4"
56+
spring: "7.0.6"
57+
steps:
58+
- uses: actions/checkout@v4
59+
- uses: actions/setup-java@v4
60+
with:
61+
distribution: 'temurin'
62+
java-version: 21
63+
- uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4
64+
65+
- name: Test okapi-spring-boot
66+
run: >-
67+
./gradlew :okapi-spring-boot:test
68+
-PspringBootVersion=${{ matrix.spring-boot }}
69+
-PspringVersion=${{ matrix.spring }}
70+
71+
kafka-compat:
72+
name: "Kafka ${{ matrix.kafka }}"
73+
runs-on: ubuntu-24.04
74+
needs: build
75+
strategy:
76+
matrix:
77+
kafka: ["3.9.0", "4.0.2"]
78+
steps:
79+
- uses: actions/checkout@v4
80+
- uses: actions/setup-java@v4
81+
with:
82+
distribution: 'temurin'
83+
java-version: 21
84+
- uses: gradle/actions/setup-gradle@748248ddd2a24f49513d8f472f81c3a07d4d50e1 # v4.4.4
85+
86+
- name: Test okapi-kafka
87+
run: ./gradlew :okapi-kafka:test -PkafkaVersion=${{ matrix.kafka }}
88+
4589
auto-merge-dependabot:
4690
# only for PRs by dependabot[bot]
4791
if: github.event.pull_request.user.login == 'dependabot[bot]'
48-
needs: [ ci ]
92+
needs: [ build ]
4993
uses: softwaremill/github-actions-workflows/.github/workflows/auto-merge.yml@main
5094
secrets:
5195
github-token: ${{ secrets.SOFTWAREMILL_CI_PR_TOKEN }}

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ Messages are stored in a database table within the same transaction as your busi
1515
| `okapi-spring-boot` | Spring Boot autoconfiguration |
1616
| `okapi-bom` | Bill of Materials for version alignment |
1717

18+
## Compatibility
19+
20+
| Dependency | Supported Versions | Notes |
21+
|---|---|---|
22+
| Java | 21+ | Required |
23+
| Spring Boot | 3.5.x, 4.0.x | `okapi-spring-boot` module |
24+
| Kafka Clients | 3.9.x, 4.x | `okapi-kafka` module — you provide `kafka-clients` dependency |
25+
| Exposed | 1.x | `okapi-postgres`, `okapi-mysql` modules — you provide Exposed |
26+
| Docker | Required for tests | Testcontainers-based integration tests |
27+
1828
## Quick Start (Spring Boot)
1929

2030
```kotlin
@@ -46,6 +56,10 @@ fun placeOrder(order: Order) {
4656
}
4757
```
4858

59+
> **Note:** `okapi-kafka` requires you to add `org.apache.kafka:kafka-clients` to your project.
60+
> `okapi-postgres`/`okapi-mysql` require Exposed ORM dependencies.
61+
> Spring and Kafka versions are not forced by okapi — you control them.
62+
4963
Autoconfiguration handles scheduling, retries, and delivery automatically.
5064

5165
## Standalone Usage

gradle/libs.versions.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ testcontainers = "1.20.5"
99
postgresql = "42.7.5"
1010
mysql = "9.2.0"
1111
kafkaClients = "3.9.0"
12-
spring = "6.2.3"
13-
springBoot = "3.4.3"
12+
spring = "6.2.17"
13+
springBoot = "3.5.12"
1414
wiremock = "3.10.0"
1515

1616
[libraries]

okapi-kafka/build.gradle.kts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,22 @@ dependencies {
66
implementation(project(":okapi-core"))
77
implementation(libs.jacksonModuleKotlin)
88
implementation(libs.jacksonDatatypeJsr310)
9-
implementation(libs.kafkaClients)
9+
compileOnly(libs.kafkaClients)
1010

11+
testImplementation(libs.kafkaClients)
1112
testImplementation(libs.kotestRunnerJunit5)
1213
testImplementation(libs.kotestAssertionsCore)
1314
}
15+
16+
// CI version override: ./gradlew :okapi-kafka:test -PkafkaVersion=4.0.2
17+
val kafkaVersion: String? by project
18+
19+
if (kafkaVersion != null) {
20+
configurations.configureEach {
21+
resolutionStrategy.eachDependency {
22+
if (requested.group == "org.apache.kafka") {
23+
useVersion(kafkaVersion!!)
24+
}
25+
}
26+
}
27+
}

okapi-kafka/src/test/kotlin/com/softwaremill/okapi/kafka/KafkaMessageDelivererTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,27 @@ class KafkaMessageDelivererTest : FunSpec({
2020
}
2121

2222
test("successful send → Success") {
23-
val producer = MockProducer(true, StringSerializer(), StringSerializer())
23+
val producer = MockProducer(true, null, StringSerializer(), StringSerializer())
2424
val deliverer = KafkaMessageDeliverer(producer)
2525
deliverer.deliver(entry()) shouldBe DeliveryResult.Success
2626
}
2727

2828
test("retriable exception (NetworkException) → RetriableFailure") {
29-
val producer = MockProducer(true, StringSerializer(), StringSerializer())
29+
val producer = MockProducer(true, null, StringSerializer(), StringSerializer())
3030
producer.sendException = NetworkException("broker down")
3131
val deliverer = KafkaMessageDeliverer(producer)
3232
deliverer.deliver(entry()).shouldBeInstanceOf<DeliveryResult.RetriableFailure>()
3333
}
3434

3535
test("permanent exception (AuthenticationException) → PermanentFailure") {
36-
val producer = MockProducer(true, StringSerializer(), StringSerializer())
36+
val producer = MockProducer(true, null, StringSerializer(), StringSerializer())
3737
producer.sendException = AuthenticationException("bad credentials")
3838
val deliverer = KafkaMessageDeliverer(producer)
3939
deliverer.deliver(entry()).shouldBeInstanceOf<DeliveryResult.PermanentFailure>()
4040
}
4141

4242
test("permanent exception (RecordTooLargeException) → PermanentFailure") {
43-
val producer = MockProducer(true, StringSerializer(), StringSerializer())
43+
val producer = MockProducer(true, null, StringSerializer(), StringSerializer())
4444
producer.sendException = RecordTooLargeException("too big")
4545
val deliverer = KafkaMessageDeliverer(producer)
4646
deliverer.deliver(entry()).shouldBeInstanceOf<DeliveryResult.PermanentFailure>()

okapi-spring-boot/build.gradle.kts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,20 @@ dependencies {
3636
testImplementation(libs.postgresql)
3737
testImplementation(libs.wiremock)
3838
}
39+
40+
// CI version override: ./gradlew :okapi-spring-boot:test -PspringBootVersion=4.0.4 -PspringVersion=7.0.6
41+
val springBootVersion: String? by project
42+
val springVersion: String? by project
43+
44+
if (springBootVersion != null || springVersion != null) {
45+
configurations.configureEach {
46+
resolutionStrategy.eachDependency {
47+
if (springBootVersion != null && requested.group == "org.springframework.boot") {
48+
useVersion(springBootVersion!!)
49+
}
50+
if (springVersion != null && requested.group == "org.springframework") {
51+
useVersion(springVersion!!)
52+
}
53+
}
54+
}
55+
}

0 commit comments

Comments
 (0)