diff --git a/.gitignore b/.gitignore index c2e4dd6..e749f84 100644 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,8 @@ build-log.txt # Generated files for local development (configured via local.properties) sample/src/main/res/raw/debug_ca.crt sample/src/main/res/xml/network_security_config.xml + +# Release artifacts (temporary files created by release script) +device-sdk-*.aar +device-sdk-*.jar +*.asc diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c4d7fd..338386f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # Changelog -## 0.1.0 (unreleased) +## 0.1.0 (2026-01-09) - Initial release diff --git a/CLAUDE.md b/CLAUDE.md index d72a99d..e17d0bd 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -87,9 +87,11 @@ If a commit fails due to formatting, run `precious tidy -g` and retry. ### Publishing +See `README.dev.md` for the full release process. For manual publishing: + ```bash -# Publish to Maven Central (requires credentials in local.properties) -./gradlew :device-sdk:publishReleasePublicationToMavenCentralRepository +# Publish to Maven Central via Central Portal (requires credentials in local.properties) +./gradlew :device-sdk:publishAndReleaseToMavenCentral ``` ## Architecture @@ -298,21 +300,16 @@ Access in build files: `libs.ktor.client.core`, `libs.plugins.kotlin.android` ## Maven Publishing Configuration -Located in `device-sdk/build.gradle.kts`: - -- POM metadata from `gradle.properties` (POM_NAME, POM_URL, etc.) -- Signing configuration placeholders in `gradle.properties` -- Actual credentials should be in `local.properties` (gitignored) +Publishing uses the +[Vanniktech Maven Publish](https://github.com/vanniktech/gradle-maven-publish-plugin) +plugin configured in `device-sdk/build.gradle.kts`. The plugin publishes to +Maven Central via Central Portal with automatic release. -**Required for publishing:** +Credentials are read from `~/.m2/settings.xml` (server id `central`) to share +credentials with other MaxMind Maven projects. GPG signing uses the system `gpg` +command, so existing `~/.gnupg` configuration is used automatically. -```properties -signing.keyId=... -signing.password=... -signing.secretKeyRingFile=... -mavenCentralUsername=... -mavenCentralPassword=... -``` +See `README.dev.md` for the full release process and credential setup. ## Module Structure diff --git a/README.dev.md b/README.dev.md new file mode 100644 index 0000000..19f2017 --- /dev/null +++ b/README.dev.md @@ -0,0 +1,149 @@ +# Preparing your environment for a release + +- Ensure you have access to publish to the repository on + [Central Portal](https://central.sonatype.com/). + - See the section about Central Portal access. +- You need a GPG secret key. You need to publish it as well. + - See the section about setting up GPG. +- Ensure the SSH key you use on GitHub.com is available. + - e.g., `~/.ssh/id_rsa`. +- Ensure an appropriate `~/.gitconfig` is set up. + - The release process generates commits. +- Ensure you have the necessary dependencies available: + - Java 17+ (Android Studio JDK recommended) + - Android SDK with API 34+ +- Ensure [gh](https://github.com/cli/cli) is set up and in your `PATH`. + +## Setting up Central Portal access + +To get this access, first create a Central Portal account at +[central.sonatype.com](https://central.sonatype.com/). + +You will need access to the `com.maxmind` namespace. Contact MaxMind operations +to request access to the namespace. + +### Configuring credentials + +This project reads credentials from Maven's `~/.m2/settings.xml`, allowing you +to share credentials with other MaxMind Java/Maven projects. + +Configure your `~/.m2/settings.xml` for Central Portal. See +[these instructions](https://central.sonatype.org/publish/publish-portal-maven/#credentials): + +```xml + + + + central + + + + + +``` + +GPG signing uses the system `gpg` command (same as Maven projects), so your +existing `~/.gnupg` configuration will be used automatically. + +**Alternative: local.properties** + +You can also configure credentials in `local.properties` (takes precedence over +settings.xml): + +```properties +mavenCentralUsername= +mavenCentralPassword= +``` + +**For CI/CD**, set environment variables: + +- `ORG_GRADLE_PROJECT_mavenCentralUsername` +- `ORG_GRADLE_PROJECT_mavenCentralPassword` + +Some links about Central Portal: + +- [Maven Central Repository homepage](https://central.sonatype.com/) +- [Publishing guide](https://central.sonatype.org/publish/publish-portal-maven/) + +## Setting up GPG + +You need a key. It is fine to create/use your own, but you'll probably want one +with your MaxMind email address. + +If you need to generate a key: `gpg --gen-key`. + +If you have one and need to export/import it: + + gpg --export-secret-keys --armor > secretkey.gpg + gpg --import secretkey.gpg + gpg --edit-key + +and enter `trust` and choose ultimate. + +Make sure the key shows up in `gpg --list-secret-keys`. + +Make sure you publish it to a keyserver. See +[here](http://central.sonatype.org/pages/working-with-pgp-signatures.html) for +more info. + +### gpg "inappropriate ioctl" errors + +Add this to `~/.gnupg/gpg.conf`: + + use-agent + pinentry-mode loopback + +Add this to `~/.gnupg/gpg-agent.conf`: + + allow-loopback-pinentry + +# Releasing + +## Steps + +1. Ensure you can run `./gradlew :device-sdk:test` and + `./gradlew :device-sdk:assemble` successfully. Run `./gradlew clean` after. + +2. Create a release branch off `main`. Ensure you have a clean checkout. + - We'll be generating commits. + - When the release is complete, deliver the release PR for review. + +3. Review open issues and PRs to see if any can easily be fixed, closed, or + merged. + +4. Review `CHANGELOG.md` for completeness and correctness. + +5. Set a version and a date in `CHANGELOG.md` and commit that. + - The format must be: `## X.Y.Z (YYYY-MM-DD)` (markdown heading). + - It gets used in the release process. + +6. Bump copyright year in `README.md` if appropriate. + - You don't need to update the version. `./dev-bin/release.sh` does this. + +7. Run `./dev-bin/release.sh` + - This will run tests, update versions, publish to Maven Central, and create + a GitHub release. + +8. This will prompt you several times. Generally you need to say `y` or `n`. + +9. You may be prompted about dependency updates. Review them and decide if you + want to update before releasing. + +10. If you get HTTP 401 errors from Central Portal, check your credentials in + `~/.m2/settings.xml` (or `local.properties`). + +11. After completion, a release will be on GitHub and Maven Central. + +12. Create a PR to merge the release branch back to main. + +## Updating dependencies + +Review the versions from the dependency update check. If you want to update: + +1. Make a branch +2. Update versions in `gradle/libs.versions.toml` +3. Run `./gradlew :device-sdk:test` and fix any errors +4. Push and ensure CI completes successfully +5. Merge + +If you did this in the middle of releasing, start the release process over. diff --git a/README.md b/README.md index 58f458f..75f5f0d 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Add the dependency to your app's `build.gradle.kts`: ```kotlin dependencies { - implementation("com.maxmind.device:device-sdk:0.1.0-SNAPSHOT") + implementation("com.maxmind.device:device-sdk:0.1.0") } ``` @@ -24,7 +24,7 @@ dependencies { ```groovy dependencies { - implementation 'com.maxmind.device:device-sdk:0.1.0-SNAPSHOT' + implementation 'com.maxmind.device:device-sdk:0.1.0' } ``` diff --git a/build.gradle.kts b/build.gradle.kts index f63e1b5..c1f449a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,11 +6,13 @@ plugins { alias(libs.plugins.kotlin.serialization) apply false alias(libs.plugins.dokka) apply false alias(libs.plugins.detekt) apply false + alias(libs.plugins.maven.publish) apply false + alias(libs.plugins.dependency.updates) } allprojects { group = "com.maxmind.device" - version = "0.1.0-SNAPSHOT" + version = "0.1.0" } tasks.register("clean", Delete::class) { diff --git a/dev-bin/release.sh b/dev-bin/release.sh new file mode 100755 index 0000000..62902cd --- /dev/null +++ b/dev-bin/release.sh @@ -0,0 +1,243 @@ +#!/bin/bash + +set -eu -o pipefail + +# Pre-flight checks - verify all required tools are available and configured +# before making any changes to the repository + +check_command() { + if ! command -v "$1" &>/dev/null; then + echo "Error: $1 is not installed or not in PATH" + exit 1 + fi +} + +# Verify gh CLI is authenticated +if ! gh auth status &>/dev/null; then + echo "Error: gh CLI is not authenticated. Run 'gh auth login' first." + exit 1 +fi + +# Verify we can access this repository via gh +if ! gh repo view --json name &>/dev/null; then + echo "Error: Cannot access repository via gh. Check your authentication and repository access." + exit 1 +fi + +# Verify git can connect to the remote (catches SSH key issues, etc.) +if ! git ls-remote origin &>/dev/null; then + echo "Error: Cannot connect to git remote. Check your git credentials/SSH keys." + exit 1 +fi + +check_command perl +check_command ./gradlew +check_command mise + +# Ensure mise is activated and all tools from mise.toml are installed +if ! mise current &>/dev/null; then + echo "Error: mise is not activated in your shell." + echo "Run 'eval \"\$(mise activate bash)\"' or add it to your shell config." + exit 1 +fi +mise install --quiet + +# Check that we're not on the main branch +current_branch=$(git branch --show-current) +if [ "$current_branch" = "main" ]; then + echo "Error: Releases should not be done directly on the main branch." + echo "Please create a release branch and run this script from there." + exit 1 +fi + +# Fetch latest changes and check that we're not behind origin/main +echo "Fetching from origin..." +git fetch origin + +if ! git merge-base --is-ancestor origin/main HEAD; then + echo "Error: Current branch is behind origin/main." + echo "Please merge or rebase with origin/main before releasing." + exit 1 +fi + +changelog=$(cat CHANGELOG.md) + +# Parse changelog in format: ## X.Y.Z (YYYY-MM-DD) +regex='## ([0-9]+\.[0-9]+\.[0-9]+[a-zA-Z0-9\-]*) \(([0-9]{4}-[0-9]{2}-[0-9]{2})\) + +((.| +)*)' + +if [[ ! $changelog =~ $regex ]]; then + echo "Could not find date line in change log!" + echo "Expected format: ## X.Y.Z (YYYY-MM-DD)" + exit 1 +fi + +version="${BASH_REMATCH[1]}" +date="${BASH_REMATCH[2]}" +# Extract notes until the next version header or end of file +notes="$(echo "${BASH_REMATCH[3]}" | sed -n -e '/^## [0-9]\+\.[0-9]\+\.[0-9]\+/,$!p')" + +if [[ "$date" != "$(date +"%Y-%m-%d")" ]]; then + echo "$date is not today!" + exit 1 +fi + +tag="v$version" + +if [ -n "$(git status --porcelain)" ]; then + echo ". is not clean." >&2 + exit 1 +fi + +# Check for dependency updates +# Note: --no-parallel is required for Gradle 9+ compatibility +echo "" +echo "Checking for dependency updates..." +./gradlew dependencyUpdates -Drevision=release --no-parallel --no-daemon + +read -r -n 1 -p "Continue given above dependencies? (y/n) " should_continue +echo "" + +if [ "$should_continue" != "y" ]; then + echo "Aborting" + exit 1 +fi + +# Run tests +echo "" +echo "Running tests..." +./gradlew :device-sdk:test --no-daemon + +read -r -n 1 -p "Continue given above tests? (y/n) " should_continue +echo "" + +if [ "$should_continue" != "y" ]; then + echo "Aborting" + exit 1 +fi + +# Update version in build.gradle.kts +echo "" +echo "Updating version to $version..." +perl -pi -e "s/version = \"[^\"]+\"/version = \"$version\"/" build.gradle.kts + +# Update version in README.md +perl -pi -e "s/com\.maxmind\.device:device-sdk:[0-9]+\.[0-9]+\.[0-9]+[a-zA-Z0-9\-]*/com.maxmind.device:device-sdk:$version/g" README.md + +git diff + +read -r -n 1 -p "Commit changes? (y/n) " should_commit +echo "" +if [ "$should_commit" != "y" ]; then + echo "Aborting" + exit 1 +fi + +git add build.gradle.kts README.md +git commit -m "Preparing for $version" + +# Build and publish to Maven Central +echo "" +echo "Building and publishing to Maven Central..." + +# Read credentials from ~/.m2/settings.xml and export as env vars +# (Gradle properties from settings.xml don't work with Vanniktech plugin) +if [ -z "${ORG_GRADLE_PROJECT_mavenCentralUsername:-}" ]; then + settings_xml="$HOME/.m2/settings.xml" + if [ -f "$settings_xml" ]; then + # Extract username and password for server id "central" using yq + # The [.settings.servers.server] | flatten handles both single server (object) and multiple servers (array) + maven_username=$(yq -p xml -oy '[.settings.servers.server] | flatten | .[] | select(.id == "central") | .username' "$settings_xml" 2>/dev/null) + maven_password=$(yq -p xml -oy '[.settings.servers.server] | flatten | .[] | select(.id == "central") | .password' "$settings_xml" 2>/dev/null) + + if [ -n "$maven_username" ] && [ -n "$maven_password" ]; then + export ORG_GRADLE_PROJECT_mavenCentralUsername="$maven_username" + export ORG_GRADLE_PROJECT_mavenCentralPassword="$maven_password" + echo "Using Maven Central credentials from ~/.m2/settings.xml" + else + echo "Error: Maven Central credentials not found in ~/.m2/settings.xml (server id 'central')" + exit 1 + fi + else + echo "Error: ~/.m2/settings.xml not found and ORG_GRADLE_PROJECT_mavenCentralUsername not set" + exit 1 + fi +fi + +./gradlew :device-sdk:publishAndReleaseToMavenCentral --no-daemon + +echo "" +echo "Release notes for $version:" +echo "" +echo "$notes" +echo "" + +read -r -n 1 -p "Push to origin? (y/n) " should_push +echo "" + +if [ "$should_push" != "y" ]; then + echo "Aborting" + exit 1 +fi + +git push + +# Create GitHub release with artifacts +echo "" +echo "Creating GitHub release..." + +# Build outputs location +build_dir="device-sdk/build/outputs/aar" + +# Clean up any previous release artifacts +rm -f device-sdk-*.aar device-sdk-*.jar device-sdk-*.asc 2>/dev/null || true + +# Collect release artifacts +release_files=() + +# AAR file +aar_file="$build_dir/device-sdk-release.aar" +if [ -f "$aar_file" ]; then + cp "$aar_file" "device-sdk-$version.aar" + release_files+=("device-sdk-$version.aar") +fi + +# Sources JAR (from publications) +sources_jar=$(find device-sdk/build -name "*-sources.jar" -type f 2>/dev/null | head -1) +if [ -n "$sources_jar" ]; then + cp "$sources_jar" "device-sdk-$version-sources.jar" + release_files+=("device-sdk-$version-sources.jar") +fi + +# Javadoc JAR +javadoc_jar=$(find device-sdk/build -name "*-javadoc.jar" -type f 2>/dev/null | head -1) +if [ -n "$javadoc_jar" ]; then + cp "$javadoc_jar" "device-sdk-$version-javadoc.jar" + release_files+=("device-sdk-$version-javadoc.jar") +fi + +# Sign artifacts for GitHub release +for file in "${release_files[@]}"; do + gpg --armor --detach-sign "$file" +done + +# Add signature files to release +for file in "${release_files[@]}"; do + if [ -f "$file.asc" ]; then + release_files+=("$file.asc") + fi +done + +gh release create --target "$(git branch --show-current)" -t "$version" -n "$notes" "$tag" "${release_files[@]}" + +# Cleanup temporary files +for file in device-sdk-*.aar device-sdk-*.jar device-sdk-*.asc; do + rm -f "$file" 2>/dev/null || true +done + +echo "" +echo "Release $version complete!" +echo "GitHub release: https://github.com/maxmind/device-android/releases/tag/$tag" +echo "Maven Central: https://central.sonatype.com/artifact/com.maxmind.device/device-sdk/$version" diff --git a/device-sdk/build.gradle.kts b/device-sdk/build.gradle.kts index 65d0291..7c73861 100644 --- a/device-sdk/build.gradle.kts +++ b/device-sdk/build.gradle.kts @@ -5,8 +5,8 @@ plugins { alias(libs.plugins.dokka) alias(libs.plugins.detekt) alias(libs.plugins.ktlint) - id("maven-publish") - id("signing") + alias(libs.plugins.maven.publish) + signing id("tech.apter.junit5.jupiter.robolectric-extension-gradle-plugin") version "0.9.0" } @@ -46,17 +46,6 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = "17" - - // Enable explicit API mode for better library API design - freeCompilerArgs += - listOf( - "-Xexplicit-api=strict", - "-opt-in=kotlin.RequiresOptIn", - ) - } - buildFeatures { buildConfig = true } @@ -66,12 +55,17 @@ android { isIncludeAndroidResources = true } } +} - publishing { - singleVariant("release") { - withSourcesJar() - withJavadocJar() - } +kotlin { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) + + // Enable explicit API mode for better library API design + freeCompilerArgs.addAll( + "-Xexplicit-api=strict", + "-opt-in=kotlin.RequiresOptIn", + ) } } @@ -113,81 +107,64 @@ detekt { buildUponDefaultConfig = true } -// Dokka configuration -tasks.dokkaHtml.configure { - outputDirectory.set(layout.buildDirectory.dir("dokka")) +// Dokka configuration (V2 API) +dokka { + dokkaPublications.html { + outputDirectory.set(layout.buildDirectory.dir("dokka")) + } } -// Maven publishing configuration -publishing { - publications { - create("release") { - groupId = project.group.toString() - artifactId = "device-sdk" - version = project.version.toString() +// Maven Central publishing configuration (using Vanniktech plugin) +// Only configure Maven Central upload when real credentials are available. +// Credentials come from env vars (set by release.sh from ~/.m2/settings.xml) +// or can be provided directly via ORG_GRADLE_PROJECT_mavenCentralUsername +val mavenCentralUsername = providers.gradleProperty("mavenCentralUsername").orNull ?: "" +val hasMavenCentralCredentials = mavenCentralUsername.isNotEmpty() - afterEvaluate { - from(components["release"]) +mavenPublishing { + if (hasMavenCentralCredentials) { + publishToMavenCentral(com.vanniktech.maven.publish.SonatypeHost.CENTRAL_PORTAL, automaticRelease = true) + } + signAllPublications() + + coordinates( + groupId = "com.maxmind.device", + artifactId = "device-sdk", + version = project.version.toString(), + ) + + pom { + name.set("MaxMind Device SDK") + description.set("Android SDK for collecting and reporting device data to MaxMind") + inceptionYear.set("2025") + url.set("https://github.com/maxmind/device-android") + + licenses { + license { + name.set("Apache License, Version 2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") + distribution.set("repo") } + } - pom { - name.set(findProperty("POM_NAME")?.toString() ?: "MaxMind Device SDK") - description.set( - findProperty("POM_DESCRIPTION")?.toString() - ?: "Android SDK for collecting and reporting device data to MaxMind", - ) - url.set(findProperty("POM_URL")?.toString() ?: "") - inceptionYear.set(findProperty("POM_INCEPTION_YEAR")?.toString() ?: "2025") - - licenses { - license { - name.set(findProperty("POM_LICENSE_NAME")?.toString() ?: "") - url.set(findProperty("POM_LICENSE_URL")?.toString() ?: "") - distribution.set(findProperty("POM_LICENSE_DIST")?.toString() ?: "") - } - } - - developers { - developer { - id.set(findProperty("POM_DEVELOPER_ID")?.toString() ?: "") - name.set(findProperty("POM_DEVELOPER_NAME")?.toString() ?: "") - url.set(findProperty("POM_DEVELOPER_URL")?.toString() ?: "") - } - } - - scm { - url.set(findProperty("POM_SCM_URL")?.toString() ?: "") - connection.set(findProperty("POM_SCM_CONNECTION")?.toString() ?: "") - developerConnection.set( - findProperty("POM_SCM_DEV_CONNECTION")?.toString() ?: "", - ) - } + developers { + developer { + id.set("maxmind") + name.set("MaxMind, Inc.") + url.set("https://www.maxmind.com/") } } - } - repositories { - maven { - name = "mavenCentral" - url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2/") - credentials { - username = findProperty("mavenCentralUsername")?.toString() ?: "" - password = findProperty("mavenCentralPassword")?.toString() ?: "" - } + scm { + url.set("https://github.com/maxmind/device-android") + connection.set("scm:git:git://github.com/maxmind/device-android.git") + developerConnection.set("scm:git:ssh://git@github.com/maxmind/device-android.git") } } } -// Signing configuration +// Configure signing to use GPG command (like Maven) instead of in-memory keys +// This respects ~/.gnupg configuration and gpg-agent signing { - if (findProperty("signing.keyId") != null) { - sign(publishing.publications["release"]) - } -} - -// Task to generate Javadoc from Dokka -tasks.register("javadocJar") { - dependsOn(tasks.dokkaHtml) - archiveClassifier.set("javadoc") - from(tasks.dokkaHtml.get().outputDirectory) + useGpgCmd() } diff --git a/gradle.properties b/gradle.properties index a419b64..debd080 100644 --- a/gradle.properties +++ b/gradle.properties @@ -24,27 +24,24 @@ android.defaults.buildfeatures.renderscript=false android.defaults.buildfeatures.resvalues=false android.defaults.buildfeatures.shaders=false -# Maven Publishing Configuration (set these in local.properties or CI environment) -# signing.keyId= -# signing.password= -# signing.secretKeyRingFile= -# mavenCentralUsername= -# mavenCentralPassword= - -# Library metadata -POM_NAME=MaxMind Device SDK -POM_DESCRIPTION=Android SDK for collecting and reporting device data to MaxMind -POM_INCEPTION_YEAR=2025 -POM_URL=https://github.com/maxmind/device-android - -POM_LICENSE_NAME=Apache License, Version 2.0 -POM_LICENSE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt -POM_LICENSE_DIST=repo - -POM_SCM_URL=https://github.com/maxmind/device-android -POM_SCM_CONNECTION=scm:git:git://github.com/maxmind/device-android.git -POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/maxmind/device-android.git - -POM_DEVELOPER_ID=maxmind -POM_DEVELOPER_NAME=MaxMind, Inc. -POM_DEVELOPER_URL=https://www.maxmind.com/ +# Maven Central Publishing Configuration (Central Portal) +# +# Credentials are read from ~/.m2/settings.xml (server id "central") +# to share credentials with other MaxMind Maven projects. +# +# GPG signing uses the system gpg command (~/.gnupg configuration). +# +# Alternatively, set in local.properties (takes precedence): +# mavenCentralUsername= +# mavenCentralPassword= +# +# For CI/CD, set environment variables: +# ORG_GRADLE_PROJECT_mavenCentralUsername +# ORG_GRADLE_PROJECT_mavenCentralPassword +# +# See README.dev.md for full setup instructions. + +# Empty placeholders for Vanniktech maven-publish plugin (prevents build service errors) +# Real credentials are provided via env vars set by release.sh from ~/.m2/settings.xml +mavenCentralUsername= +mavenCentralPassword= diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a34882e..017210f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,6 +39,10 @@ turbine = "1.2.1" # Material (for sample app) material = "1.12.0" +# Publishing +mavenPublish = "0.30.0" +dependencyUpdates = "0.53.0" + [libraries] # Kotlin kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } @@ -87,6 +91,8 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" } +maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "mavenPublish" } +dependency-updates = { id = "com.github.ben-manes.versions", version.ref = "dependencyUpdates" } [bundles] ktor = ["ktor-client-core", "ktor-client-android", "ktor-client-content-negotiation", "ktor-serialization-kotlinx-json", "ktor-client-logging"] diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000..641898a --- /dev/null +++ b/mise.toml @@ -0,0 +1,5 @@ +[tools] +# Java 21 is required - Dokka doesn't support Java 25+ yet +java = "temurin-21" +# yq is used by release.sh to parse ~/.m2/settings.xml for Maven Central credentials +yq = "latest" diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts index 34d531c..f5b08dc 100644 --- a/sample/build.gradle.kts +++ b/sample/build.gradle.kts @@ -62,16 +62,18 @@ android { targetCompatibility = JavaVersion.VERSION_17 } - kotlinOptions { - jvmTarget = "17" - } - buildFeatures { viewBinding = true buildConfig = true } } +kotlin { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) + } +} + dependencies { // SDK module implementation(project(":device-sdk"))