diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ee87f8f..b189d9d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -52,6 +52,16 @@ jobs: # release-pipeline debuggability (runs once per tag, CC savings are zero). run: ./gradlew --no-daemon publishToMavenCentral --no-configuration-cache + - name: Publish plugin to Gradle Plugin Portal + # Tag-only: the Portal rejects SNAPSHOT versions; branch pushes produce SNAPSHOTs. + # publishPlugins uploads directly — no manual promotion step unlike Maven Central. + if: startsWith(github.ref, 'refs/tags/') + env: + GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }} + GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }} + ORG_GRADLE_PROJECT_VERSION_NAME: ${{ steps.version.outputs.VERSION_NAME }} + run: ./gradlew --no-daemon :featured-gradle-plugin:publishPlugins --no-configuration-cache + publish-xcframework: name: Publish XCFramework to GitHub Release # Only runs for version tags — not for SNAPSHOT pushes to main. diff --git a/featured-gradle-plugin/build.gradle.kts b/featured-gradle-plugin/build.gradle.kts index f4628d8..83e60de 100644 --- a/featured-gradle-plugin/build.gradle.kts +++ b/featured-gradle-plugin/build.gradle.kts @@ -1,7 +1,10 @@ +import org.gradle.api.publish.maven.tasks.PublishToMavenRepository + plugins { alias(libs.plugins.kotlinJvm) alias(libs.plugins.kotlinSerialization) `java-gradle-plugin` + alias(libs.plugins.pluginPublish) alias(libs.plugins.mavenPublish) } @@ -13,14 +16,22 @@ kotlin { } gradlePlugin { + website.set("https://github.com/AndroidBroadcast/Featured") + vcsUrl.set("https://github.com/AndroidBroadcast/Featured") plugins { create("featured") { id = "dev.androidbroadcast.featured" implementationClass = "dev.androidbroadcast.featured.gradle.FeaturedPlugin" + displayName = "Featured Gradle Plugin" + description = "Gradle plugin for Featured – generates type-safe configuration flag declarations" + tags.set(listOf("featured", "feature-flags", "configuration", "codegen", "kotlin-multiplatform")) } create("featuredApplication") { id = "dev.androidbroadcast.featured.application" implementationClass = "dev.androidbroadcast.featured.gradle.FeaturedApplicationPlugin" + displayName = "Featured Application Gradle Plugin" + description = "Featured aggregator plugin – merges per-module flag manifests into a single generated registry" + tags.set(listOf("featured", "feature-flags", "configuration", "codegen", "kotlin-multiplatform")) } } } @@ -59,6 +70,27 @@ mavenPublishing { } } +// The java-gradle-plugin marker artifacts (one per plugin id, the second under its own +// groupId) are resolved via the Gradle Plugin Portal, where `publishPlugins` uploads them. +// Vanniktech binds every MavenPublication — markers included — to the Maven Central +// repository, which would pollute the Central listing with two stub marker artifacts. +// Disable only the marker -> Central tasks so Central carries just the clean +// `featured-gradle-plugin` impl jar (+ sources/javadoc/pom); the Portal still receives the +// markers via `publishPlugins`, which uploads publications directly over HTTP independently +// of these maven-publish repository tasks. +// +// Match on the task name (which Gradle fixes at registration time) rather than the task's +// `repository`/`publication` properties: maven-publish wires those properties later, in an +// afterEvaluate, so a `configureEach` action that reads them runs too early and sees them +// unset. The name `publishPublicationToRepository` is always correct here. +// `publishPluginMavenPublication...` (the impl) ends with `PluginMavenPublication...`, not +// `PluginMarkerMavenPublication...`, so it is intentionally left enabled. +tasks.withType().configureEach { + if (name.endsWith("PluginMarkerMavenPublicationToMavenCentralRepository")) { + enabled = false + } +} + // A separate configuration whose resolved jars are appended to the pluginUnderTestMetadata // classpath. This makes GradleRunner.withPluginClasspath() inject them into the TestKit // subprocess, which is necessary for compileOnly dependencies (like AGP) that the plugin diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 94e2a25..a315c2c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -29,6 +29,7 @@ spotless = "8.4.0" ktlint = "1.8.0" turbine = "1.2.1" mavenPublish = "0.36.0" +pluginPublish = "2.1.1" dokka = "2.2.0" detekt = "1.23.8" configcat = "5.1.0" @@ -93,5 +94,6 @@ kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" } skie = { id = "co.touchlab.skie", version.ref = "skie" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } mavenPublish = { id = "com.vanniktech.maven.publish", version.ref = "mavenPublish" } +pluginPublish = { id = "com.gradle.plugin-publish", version.ref = "pluginPublish" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } androidKmpLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }