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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ci-gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ kotlin.code.style=official
org.gradle.caching=true
org.gradle.parallel=true
android.enableR8.fullMode=true
org.gradle.configureondemand=true
# TODO: Not compatible with wasmJS
org.gradle.configureondemand=false
android.enableJetifier=false
kotlin.incremental.usePreciseJavaTracking=true
org.gradle.configuration-cache.problems=warn
Expand All @@ -32,7 +33,6 @@ kotlin.native.binary.appStateTracking=enabled
kotlin.native.binary.objcExportSuspendFunctionLaunchThreadRestriction=none
# Native incremental compilation
kotlin.incremental.native=true
android.experimental.additionalArtifactsInModel=true
kotlin.apple.xcodeCompatibility.nowarn=true
# Enable new k/n GC
kotlin.native.binary.gc=cms
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ hs_err_pid*
/app/debug/output-metadata.json
/.idea/deploymentTargetDropDown.xml
/.idea/other.xml
/.kotlin/

### Custom rules
.firebase-service-account.json
Expand Down
28 changes: 28 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Repository Guidelines

## Project Structure & Module Organization

- `core/` is the Kotlin Multiplatform library. Shared code lives in `core/src/commonMain/kotlin/pro/respawn/apiresult/`.
- JVM tests live in `core/src/jvmTest/kotlin/pro/respawn/apiresult/test/`.
- `app/` is a sample Android app. Kotlin sources are under `app/src/main/kotlin/…` and resources in `app/src/main/res/`.
- `buildSrc/` contains Gradle convention plugins and shared build logic.
- `docs/` holds documentation sources; `detekt.yml` defines lint rules.

## Build, Test, and Development Commands

- `./gradlew :core:jvmTest` — runs JVM unit tests for the library.
- `./gradlew :app:assembleDebug` — builds the sample app APK.
- `./gradlew detektAll` — runs Detekt across the project.
- `./gradlew detektFormat` — applies Detekt auto-corrections.

## Testing Guidelines

- Tests use Kotest with the JUnit 5 platform.
- Place JVM tests in `core/src/jvmTest/...` and name files `*Tests.kt`.
- Add tests for new operators or error-handling behaviors; keep operator coverage high.

## Commit & Pull Request Guidelines

- Commit subjects are short, imperative, and lowercase (for example, `fix publish workflow`).
- Release/version commits use a plain version string, optionally with the PR number (for example, `2.1.0 (#14)`).
- PRs should include: a concise description, rationale for changes, and tests run. Update docs/KDoc when the public API changes.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ Ready to try? Start with reading the [Quickstart Guide](https://opensource.respa
## License

```
Copyright 2022-2025 Respawn Team and contributors
Copyright 2022-2026 Respawn Team and contributors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
12 changes: 9 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi

plugins {
id("com.android.application")
kotlin("android")
id("kotlin-parcelize")
alias(libs.plugins.compose.compiler)
}

kotlin {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(Config.jvmTarget)
}
}

android {
configureAndroid()

Expand All @@ -22,9 +31,6 @@ android {
buildConfig = true
compose = true
}
kotlinOptions {
jvmTarget = Config.jvmTarget.target
}
}

dependencies {
Expand Down
20 changes: 8 additions & 12 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.KotlinMultiplatform
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import com.vanniktech.maven.publish.MavenPublishBasePlugin
import com.vanniktech.maven.publish.SonatypeHost
import nl.littlerobots.vcu.plugin.versionCatalogUpdate
import nl.littlerobots.vcu.plugin.versionSelector
import org.gradle.kotlin.dsl.withType
Expand Down Expand Up @@ -48,14 +47,8 @@ subprojects {
plugins.withType<MavenPublishBasePlugin> {
the<MavenPublishBaseExtension>().apply {
val isReleaseBuild = properties["release"]?.toString().toBoolean()
configure(
KotlinMultiplatform(
javadocJar = JavadocJar.Empty(),
sourcesJar = true,
androidVariantsToPublish = listOf("release"),
)
)
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL, false)
configure(KotlinMultiplatform(javadocJar = JavadocJar.Empty(), sourcesJar = true))
publishToMavenCentral()
if (isReleaseBuild) signAllPublications()
coordinates(Config.artifactId, name, Config.version(isReleaseBuild))
pom {
Expand Down Expand Up @@ -87,7 +80,12 @@ subprojects {
tasks {
withType<Test>().configureEach {
useJUnitPlatform()
filter { isFailOnNoMatchingTests = true }
val isAndroidUnitTest = name.contains("UnitTest")
// Android unit test tasks can exist without sources; don't fail those on empty discovery.
filter { isFailOnNoMatchingTests = !isAndroidUnitTest }
if (isAndroidUnitTest) {
failOnNoDiscoveredTests = false
}
}
}
}
Expand All @@ -111,8 +109,6 @@ versionCatalogUpdate {

keep {
keepUnusedVersions = true
keepUnusedLibraries = true
keepUnusedPlugins = true
}
}

Expand Down
16 changes: 6 additions & 10 deletions buildSrc/src/main/kotlin/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ object Config {
const val artifactId = "$group.$artifact"

const val majorRelease = 2
const val minorRelease = 1
const val minorRelease = 2
const val patch = 0
const val postfix = "" // include dash
const val versionName = "$majorRelease.$minorRelease.$patch$postfix"
Expand All @@ -37,9 +37,9 @@ object Config {

val jvmTarget = JvmTarget.JVM_11
val javaVersion = JavaVersion.VERSION_11
const val compileSdk = 35
const val compileSdk = 36
const val targetSdk = compileSdk
const val minSdk = 21
const val minSdk = 23
const val appMinSdk = 26
const val publishingVariant = "release"

Expand All @@ -54,16 +54,12 @@ object Config {
val compilerArgs = listOf(
"-Xbackend-threads=0", // parallel IR compilation
"-Xexpect-actual-classes",
"-Xwasm-use-new-exception-proposal",
"-Xconsistent-data-class-copy-visibility",
"-Xsuppress-warning=NOTHING_TO_INLINE",
"-Xsuppress-warning=UNUSED_ANONYMOUS_PARAMETER",
"-Xwasm-debugger-custom-formatters"
"-Xwarning-level=NOTHING_TO_INLINE:disabled",
"-Xwarning-level=UNUSED_ANONYMOUS_PARAMETER:disabled"
)
val jvmCompilerArgs = buildList {
addAll(compilerArgs)
add("-Xjvm-default=all") // enable all jvm optimizations
add("-Xcontext-receivers")
add("-jvm-default=no-compatibility") // enable all jvm optimizations
add("-Xstring-concat=inline")
add("-Xlambdas=indy")
add("-Xjdk-release=${jvmTarget.target}")
Expand Down
9 changes: 0 additions & 9 deletions buildSrc/src/main/kotlin/ConfigureAndroid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,6 @@ fun Project.configureAndroidLibrary(variant: LibraryExtension) = variant.apply {
consumerProguardFiles(file(Config.consumerProguardFile))
}

buildTypes {
release {
setProperty(
"archivesBaseName",
project.name
)
}
}

libraryVariants.all {
sourceSets {
getByName(name) {
Expand Down
3 changes: 2 additions & 1 deletion buildSrc/src/main/kotlin/ConfigureMultiplatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ fun Project.configureMultiplatform(
}

if (wasmJs) wasmJs {
moduleName = this@configureMultiplatform.name
outputModuleName.set(this@configureMultiplatform.name)
nodejs()
browser()
binaries.library()
Expand All @@ -60,6 +60,7 @@ fun Project.configureMultiplatform(
nodejs()
}

@Suppress("DEPRECATION")
if (android) androidTarget {
publishLibraryVariants(Config.publishingVariant)
compilerOptions {
Expand Down
10 changes: 6 additions & 4 deletions buildSrc/src/main/kotlin/pro.respawn.android-library.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi

plugins {
kotlin("android")
id("com.android.library")
}

kotlin {
explicitApi()
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
jvmTarget.set(Config.jvmTarget)
}
}

android {
configureAndroidLibrary(this)

kotlinOptions {
jvmTarget = Config.jvmTarget.target
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ kotlin.code.style=official
org.gradle.caching=true
org.gradle.parallel=true
android.enableR8.fullMode=true
org.gradle.configureondemand=true
# TODO: Not compatible with wasmJS
# org.gradle.configureondemand=true
android.enableJetifier=false
kotlin.incremental.usePreciseJavaTracking=true
org.gradle.configuration-cache.problems=warn
Expand All @@ -32,7 +33,6 @@ kotlin.native.binary.appStateTracking=enabled
kotlin.native.binary.objcExportSuspendFunctionLaunchThreadRestriction=none
# Native incremental compilation
kotlin.incremental.native=true
android.experimental.additionalArtifactsInModel=true
kotlin.apple.xcodeCompatibility.nowarn=true
# Enable new k/n GC
kotlin.native.binary.gc=cms
Expand Down
38 changes: 20 additions & 18 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
[versions]
atomicfu = "0.26.0"
compose = "1.7.6"
compose-activity = "1.10.0-rc01"
compose-material3 = "1.3.1"
atomicfu = "0.30.0-beta"
compose = "1.10.0"
compose-activity = "1.12.2"
compose-material3 = "1.4.0"
composeDetektPlugin = "1.4.0"
core-ktx = "1.15.0"
coroutines = "1.10.1"
dependencyAnalysisPlugin = "2.6.1"
detekt = "1.23.7"
detektFormattingPlugin = "1.23.7"
dokka = "2.0.0"
gradleAndroid = "8.7.3"
gradleDoctorPlugin = "0.10.0"
kotest = "6.0.0.M1"
kotlin = "2.1.0"
lifecycle = "2.8.7"
maven-publish-plugin = "0.30.0"
core-ktx = "1.17.0"
coroutines = "1.10.2"
dependencyAnalysisPlugin = "3.5.1"
detekt = "1.23.8"
detektFormattingPlugin = "1.23.8"
dokka = "2.1.0"
gradleAndroid = "8.13.0"
gradleDoctorPlugin = "0.12.1"
kotest = "6.0.7"
kotlin = "2.3.0"
lifecycle = "2.10.0"
maven-publish-plugin = "0.35.0"
turbine = "1.0.0"
versionCatalogUpdatePlugin = "0.8.4"
versionCatalogUpdatePlugin = "1.0.1"

[libraries]
android-gradle = { module = "com.android.tools.build:gradle", version.ref = "gradleAndroid" }
Expand All @@ -35,7 +35,9 @@ detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting",
detekt-gradle = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" }
detekt-libraries = { module = "io.gitlab.arturbosch.detekt:detekt-rules-libraries", version.ref = "detekt" }
dokka-android = { module = "org.jetbrains.dokka:android-documentation-plugin", version.ref = "dokka" }
dokka-gradle = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" }
kotest-assertions-table = { module = "io.kotest:kotest-assertions-table", version.ref = "kotest" }
kotest-framework = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" }
kotest-junit = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" }
kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest" }
Expand All @@ -46,11 +48,11 @@ kotlin-gradle = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test-common", version.ref = "kotlin" }
lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" }
dokka-gradle = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }

[bundles]
unittest = [
"kotest-assertions",
"kotest-assertions-table",
"kotest-framework",
"kotest-property",
"kotlin-coroutines-test",
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
9 changes: 3 additions & 6 deletions gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions gradlew.bat

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions scripts/update_deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

GRADLE_VER="$1"

if [ -z "$GRADLE_VER" ]; then
GRADLE_VER="latest"
fi

./gradlew wrapper --gradle-version "$GRADLE_VER" --distribution-type bin
./gradlew wrapper --gradle-version "$GRADLE_VER" --distribution-type bin
./gradlew versionCatalogUpdate --no-configuration-cache