diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6910ea3..7644fe1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,5 +22,7 @@ jobs: - uses: gradle/actions/setup-gradle@v4 - name: Validate wrapper uses: gradle/actions/wrapper-validation@v4 - - name: Build, test, lint, and verify local publication - run: ./gradlew build lint :flextrack:publishToMavenLocal --stacktrace + - name: Build, test, and lint + run: ./gradlew build lint --stacktrace + - name: Verify publication metadata and artifacts + run: ./gradlew :flextrack:generatePomFileForMavenPublication :flextrack:generateMetadataFileForMavenPublication :flextrack:bundleReleaseAar :flextrack:sourceReleaseJar :flextrack:emptyJavadocJar --stacktrace diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03e72dc..4511986 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,6 @@ on: permissions: contents: read - packages: write jobs: publish: @@ -21,9 +20,23 @@ jobs: - uses: gradle/actions/setup-gradle@v4 - name: Verify tag matches SDK version run: test "${GITHUB_REF_NAME#v}" = "$(sed -n 's/version = "\(.*\)"/\1/p' flextrack/build.gradle.kts | head -1)" + - name: Verify publishing secrets + env: + MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + SIGNING_KEY: ${{ secrets.SIGNING_KEY }} + SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }} + run: | + test -n "$MAVEN_CENTRAL_USERNAME" + test -n "$MAVEN_CENTRAL_PASSWORD" + test -n "$SIGNING_KEY" + test -n "$SIGNING_PASSWORD" - name: Verify release run: ./gradlew clean :flextrack:test :flextrack:lint :flextrack:assembleRelease - - name: Publish to GitHub Packages - run: ./gradlew :flextrack:publishReleasePublicationToGitHubPackagesRepository + - name: Publish and release to Maven Central + run: ./gradlew :flextrack:publishAndReleaseToMavenCentral --no-configuration-cache env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7da6425..1af6b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## 1.2.0 - 2026-08-18 + +### Added + +- Kotlin-native configuration and client builders. +- Smart, GDPR, CCPA, privacy-region, and performance routing presets. +- Versioned consent management and dynamic tracking context enrichment. +- Public pattern matching, sampling, and validation utilities. +- Thread-safe `RecordingTracker`/`MockTracker` and `NoOpTracker` implementations. +- Typed tracker capability, lifecycle, registry diagnostics, and public failures. +- Expanded package-level Flutter parity coverage with 168 tests. + +### Changed + +- Publishes from the Central Publisher Portal under + `io.github.alirezat66:flextrack` with signed sources and Javadoc artifacts. +- Replaces authenticated GitHub Packages installation with public Maven Central + installation. + +### Compatibility + +- Kotlin source packages and the Android namespace remain `dev.flextrack`. +- Existing `1.1.0` users only need to replace the Maven dependency coordinates. +- Core and Runtime Specifications remain `1.0.0`. + ## 1.1.0 - 2026-08-18 ### Added diff --git a/README.md b/README.md index 8ab8abd..af034b8 100644 --- a/README.md +++ b/README.md @@ -19,30 +19,15 @@ The Kotlin SDK targets Android API 21+ and implements ## Installation -The release workflow publishes version `1.1.0` through GitHub Packages. After -the release tag is pushed, add the repository and credentials to your Gradle -settings, then add the dependency: - -```kotlin -repositories { - maven { - url = uri("https://maven.pkg.github.com/alirezat66/flex_track_kotlin") - credentials { - username = providers.gradleProperty("gpr.user").orNull - password = providers.gradleProperty("gpr.key").orNull - } - } -} -``` +FlexTrack is published to Maven Central. No repository declaration or GitHub +token is required when the project already uses `mavenCentral()`. ```kotlin dependencies { - implementation("dev.flextrack:flextrack:1.1.0") + implementation("io.github.alirezat66:flextrack:1.2.0") } ``` -GitHub Packages requires a GitHub username and a token with `read:packages`. - ## Quick start Implement an event and a destination adapter: diff --git a/build.gradle.kts b/build.gradle.kts index 67644a8..9a560ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,4 +6,5 @@ plugins { alias(libs.plugins.kotlin.compose) apply false alias(libs.plugins.ksp) apply false alias(libs.plugins.hilt) apply false + alias(libs.plugins.maven.publish) apply false } diff --git a/docs/maven-central-release.md b/docs/maven-central-release.md new file mode 100644 index 0000000..608373f --- /dev/null +++ b/docs/maven-central-release.md @@ -0,0 +1,28 @@ +# Maven Central release + +FlexTrack Kotlin publishes as `io.github.alirezat66:flextrack` through the +Sonatype Central Publisher Portal. Credentials and signing material must never +be committed to this repository. + +## One-time publisher setup + +1. Sign in to with the `alirezat66` GitHub + account and confirm that `io.github.alirezat66` is verified under + **View Namespaces**. +2. Generate a Central Portal user token. Store its generated username and + password as GitHub Actions secrets `MAVEN_CENTRAL_USERNAME` and + `MAVEN_CENTRAL_PASSWORD`. +3. Create a password-protected OpenPGP signing key and publish its public key to + a supported keyserver. +4. Export the complete ASCII-armored private key to the `SIGNING_KEY` GitHub + Actions secret and store its passphrase as `SIGNING_PASSWORD`. + +## Release + +1. Update the project version and changelog. +2. Merge the release branch into `main` and ensure CI passes. +3. Create and push a matching `vMAJOR.MINOR.PATCH` tag. +4. The release workflow verifies the tag, runs tests/lint/release assembly, + signs every publication, uploads it, and requests automatic release. +5. Confirm the deployment reaches `PUBLISHED` in the Central Portal, then test + resolution from a clean project using only `mavenCentral()`. diff --git a/flextrack/build.gradle.kts b/flextrack/build.gradle.kts index dd9b48c..adb43a7 100644 --- a/flextrack/build.gradle.kts +++ b/flextrack/build.gradle.kts @@ -1,11 +1,15 @@ +import com.vanniktech.maven.publish.AndroidSingleVariantLibrary +import com.vanniktech.maven.publish.JavadocJar +import com.vanniktech.maven.publish.SourcesJar + plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) - `maven-publish` + alias(libs.plugins.maven.publish) } -group = "dev.flextrack" -version = "1.1.0" +group = "io.github.alirezat66" +version = "1.2.0" android { namespace = "dev.flextrack" @@ -40,12 +44,6 @@ android { it.useJUnitPlatform() } } - - publishing { - singleVariant("release") { - withSourcesJar() - } - } } dependencies { @@ -59,53 +57,46 @@ dependencies { androidTestImplementation(libs.kotlinx.coroutines.test) } -publishing { - repositories { - maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/alirezat66/flex_track_kotlin") - credentials { - username = providers.gradleProperty("gpr.user") - .orElse(providers.environmentVariable("GITHUB_ACTOR")) - .orNull - password = providers.gradleProperty("gpr.key") - .orElse(providers.environmentVariable("GITHUB_TOKEN")) - .orNull - } - } - } - publications { - register("release") { - groupId = project.group.toString() - artifactId = "flextrack" - version = project.version.toString() +mavenPublishing { + configure( + AndroidSingleVariantLibrary( + variant = "release", + sourcesJar = SourcesJar.Sources(), + javadocJar = JavadocJar.Empty(), + ), + ) + coordinates( + groupId = "io.github.alirezat66", + artifactId = "flextrack", + version = project.version.toString(), + ) + publishToMavenCentral(automaticRelease = true) + signAllPublications() - afterEvaluate { - from(components["release"]) + pom { + name.set("FlexTrack Kotlin") + description.set("Consent-aware, deterministic analytics routing for Android and Kotlin.") + inceptionYear.set("2026") + url.set("https://github.com/alirezat66/flex_track_kotlin") + licenses { + license { + name.set("MIT License") + url.set("https://opensource.org/licenses/MIT") + distribution.set("repo") } - - pom { - name.set("FlexTrack Kotlin") - description.set("Consent-aware, deterministic analytics routing for Android and Kotlin.") - url.set("https://github.com/alirezat66/flex_track_kotlin") - licenses { - license { - name.set("MIT License") - url.set("https://opensource.org/licenses/MIT") - } - } - developers { - developer { - id.set("alirezat66") - name.set("Reza Taghizadeh") - } - } - scm { - url.set("https://github.com/alirezat66/flex_track_kotlin") - connection.set("scm:git:https://github.com/alirezat66/flex_track_kotlin.git") - developerConnection.set("scm:git:ssh://git@github.com/alirezat66/flex_track_kotlin.git") - } + } + developers { + developer { + id.set("alirezat66") + name.set("Reza Taghizadeh") + email.set("alirezataghizadeh66@gmail.com") + url.set("https://github.com/alirezat66") } } + scm { + url.set("https://github.com/alirezat66/flex_track_kotlin") + connection.set("scm:git:git://github.com/alirezat66/flex_track_kotlin.git") + developerConnection.set("scm:git:ssh://git@github.com/alirezat66/flex_track_kotlin.git") + } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 29f42f6..74ffe68 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,6 +20,7 @@ hilt = "2.57.1" hiltNavigationCompose = "1.3.0" ksp = "2.0.21-1.0.28" datastore = "1.2.0" +mavenPublish = "0.37.0" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -58,3 +59,4 @@ kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } +maven-publish = { id = "com.vanniktech.maven.publish", version.ref = "mavenPublish" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1bb4daf..5b59f90 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,8 @@ pluginManagement { repositories { + maven("https://maven-central.storage-download.googleapis.com/maven2/") { + name = "GoogleMavenCentralMirror" + } google { content { includeGroupByRegex("com\\.android.*") @@ -15,6 +18,9 @@ dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() + maven("https://maven-central.storage-download.googleapis.com/maven2/") { + name = "GoogleMavenCentralMirror" + } mavenCentral() } }