diff --git a/.github/workflows/publish-api-docs.yml b/.github/workflows/publish-api-docs.yml index 92ff09ec09..b0450efdf4 100644 --- a/.github/workflows/publish-api-docs.yml +++ b/.github/workflows/publish-api-docs.yml @@ -1,4 +1,4 @@ -name: Publish API Docs to GitHub Pages +name: Publish API docs and record SDK version on: workflow_call: @@ -20,6 +20,16 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: + - name: Validate access to version data service + uses: embrace-io/public-actions/upload-sdk-version@88167cd1a3fce3418e26c8c842026e6dfab99e41 + with: + platform: 'android' + version: ${{ inputs.rc_version }} + dryRun: true + uploadUrl: ${{ vars.SDK_VERSION_URL }} + env: + SDK_VERSION_TOKEN: ${{ secrets.SDK_VERSION_TOKEN }} + - name: Configure git run: | git config --global user.name 'embrace-ci[bot]' @@ -60,3 +70,13 @@ jobs: git config --global user.email "embrace-ci@users.noreply.github.com" git commit --allow-empty --message "CI/CD: Automatically generated documentation for ${RC_VERSION}" docs/ git push --force origin gh-pages + + - name: Record SDK Version History + uses: embrace-io/public-actions/upload-sdk-version@88167cd1a3fce3418e26c8c842026e6dfab99e41 + with: + platform: 'android' + version: ${{ inputs.rc_version }} + dryRun: false + uploadUrl: ${{ vars.SDK_VERSION_URL }} + env: + SDK_VERSION_TOKEN: ${{ secrets.SDK_VERSION_TOKEN }} diff --git a/.github/workflows/publish-snapshot.yml b/.github/workflows/publish-snapshot.yml new file mode 100644 index 0000000000..b7696bd6ef --- /dev/null +++ b/.github/workflows/publish-snapshot.yml @@ -0,0 +1,51 @@ +name: Publish snapshot + +env: + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_TOKEN_USER }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_TOKEN_USER_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.MAVEN_ANDROID_SIGNING_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.MAVEN_ANDROID_GPG_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.MAVEN_ANDROID_SIGNING_PASSWORD }} + +on: + schedule: + - cron: '0 5 * * *' # Runs every day at 5:00 UTC + workflow_dispatch: + inputs: + snapshot_name: + description: 'Name of the snapshot to be published. -SNAPSHOT will be appended automatically, so just add a name. e.g. 7.7.0' + required: false + +permissions: + contents: read + +jobs: + release: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - name: Set snapshot_name in gradle.properties if set + env: + SNAPSHOT_NAME: ${{ inputs.snapshot_name }} + run: | + if [ -n "$SNAPSHOT_NAME" ]; then + sed -i -r "s#^version=.*#version=${SNAPSHOT_NAME}-SNAPSHOT#" gradle.properties + git add gradle.properties + fi + + - name: Fail if version is not -SNAPSHOT + run: | + grep -q -- '-SNAPSHOT$' gradle.properties || (echo "ERROR: version must end with -SNAPSHOT" && exit 1) + + - name: Setup Java + uses: actions/setup-java@v4 + with: + distribution: 'adopt' + java-version: 17 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 + + - name: Publish to Maven Central + run: | + ./gradlew publishToMavenCentral --no-configuration-cache --stacktrace diff --git a/.github/workflows/release-workflow.yml b/.github/workflows/release-workflow.yml index 2833a373a4..e69de29bb2 100644 --- a/.github/workflows/release-workflow.yml +++ b/.github/workflows/release-workflow.yml @@ -1,74 +0,0 @@ -name: Release RC and Update Docs - -env: - SONATYPE_USERNAME: ${{ secrets.SONATYPE_TOKEN_USER }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_TOKEN_USER_PASSWORD }} - MAVEN_QA_USER: github - MAVEN_QA_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} - mavenSigningKeyId: ${{ secrets.MAVEN_ANDROID_SIGNING_KEY }} - mavenSigningKeyRingFileEncoded: ${{ secrets.MAVEN_ANDROID_GPG_KEY }} - mavenSigningKeyPassword: ${{ secrets.MAVEN_ANDROID_SIGNING_PASSWORD }} - -on: - workflow_dispatch: - inputs: - rc_version: - description: 'SDK version this workflow run will release. Specify e.g. 7.1.2. It will use the branch "release/".' - required: true - -permissions: - contents: read - -jobs: - release-to-maven-central: - runs-on: ubuntu-latest - timeout-minutes: 60 - steps: - - name: Validate access to version data service - uses: embrace-io/public-actions/upload-sdk-version@88167cd1a3fce3418e26c8c842026e6dfab99e41 - with: - platform: 'android' - version: ${{ inputs.rc_version }} - dryRun: true - uploadUrl: ${{ vars.SDK_VERSION_URL }} - env: - SDK_VERSION_TOKEN: ${{ secrets.SDK_VERSION_TOKEN }} - - - name: Checkout SDK - uses: actions/checkout@v4 - with: - ref: release/${{ inputs.rc_version }} - fetch-depth: 0 - persist-credentials: false - - - name: Setup Java - uses: actions/setup-java@v4 - with: - distribution: 'adopt' - java-version: 17 - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 - - - name: Release to Maven Central - run: | - ./gradlew findSonatypeStagingRepository releaseSonatypeStagingRepository -Dorg.gradle.parallel=false --no-build-cache --no-configuration-cache --stacktrace - - - name: Record SDK Version History - uses: embrace-io/public-actions/upload-sdk-version@88167cd1a3fce3418e26c8c842026e6dfab99e41 - with: - platform: 'android' - version: ${{ inputs.rc_version }} - dryRun: false - uploadUrl: ${{ vars.SDK_VERSION_URL }} - env: - SDK_VERSION_TOKEN: ${{ secrets.SDK_VERSION_TOKEN }} - - publish-api-docs: - name: Publish API Docs to GitHub Pages - uses: ./.github/workflows/publish-api-docs.yml - secrets: inherit - permissions: - contents: write - with: - rc_version: ${{ inputs.rc_version }} diff --git a/.github/workflows/upload-artifacts-to-sonatype.yml b/.github/workflows/upload-artifacts-to-maven-central.yml similarity index 54% rename from .github/workflows/upload-artifacts-to-sonatype.yml rename to .github/workflows/upload-artifacts-to-maven-central.yml index 1199f74809..8448385d4f 100644 --- a/.github/workflows/upload-artifacts-to-sonatype.yml +++ b/.github/workflows/upload-artifacts-to-maven-central.yml @@ -1,13 +1,11 @@ -name: Upload artifacts to Sonatype +name: Upload artifacts to Maven Central env: - SONATYPE_USERNAME: ${{ secrets.SONATYPE_TOKEN_USER }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_TOKEN_USER_PASSWORD }} - MAVEN_QA_USER: github - MAVEN_QA_PASSWORD: ${{ secrets.NEXUS_PASSWORD }} - mavenSigningKeyId: ${{ secrets.MAVEN_ANDROID_SIGNING_KEY }} - mavenSigningKeyRingFileEncoded: ${{ secrets.MAVEN_ANDROID_GPG_KEY }} - mavenSigningKeyPassword: ${{ secrets.MAVEN_ANDROID_SIGNING_PASSWORD }} + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_TOKEN_USER }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_TOKEN_USER_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.MAVEN_ANDROID_SIGNING_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.MAVEN_ANDROID_GPG_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.MAVEN_ANDROID_SIGNING_PASSWORD }} on: workflow_call: @@ -29,12 +27,6 @@ jobs: timeout-minutes: 60 runs-on: ubuntu-latest steps: - - name: Decode Keystore - run: | - mkdir "$RUNNER_TEMP"/keystore - echo $mavenSigningKeyRingFileEncoded | base64 -di > "$RUNNER_TEMP"/keystore/2DE631C1.gpg - echo "mavenSigningKeyRingFile=$RUNNER_TEMP/keystore/2DE631C1.gpg" >> $GITHUB_ENV - - name: Configure git run: | git config --global user.name 'embrace-ci[bot]' @@ -55,9 +47,9 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 - - name: Publish and close Sonatype repository + - name: Publish to Maven Central run: | - ./gradlew publishAllPublicationsToSonatypeRepository -x embrace-gradle-plugin-integration-tests:publishAllPublicationsToSonatypeRepository closeSonatypeStagingRepository -Dorg.gradle.parallel=false --no-build-cache --no-configuration-cache --stacktrace + ./gradlew publishToMavenCentral --no-configuration-cache --stacktrace - name: Publish git tag env: diff --git a/build.gradle.kts b/build.gradle.kts index 55f703cba3..65076a0215 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -import java.time.Duration import org.jetbrains.dokka.gradle.DokkaTaskPartial plugins { @@ -6,7 +5,6 @@ plugins { kotlin("jvm") apply false alias(libs.plugins.google.ksp) apply false id("com.android.library") apply false - alias(libs.plugins.nexus.publish) alias(libs.plugins.dokka) alias(libs.plugins.kover) } @@ -14,22 +12,6 @@ plugins { group = "io.embrace" version = project.version -nexusPublishing { - repositories { - sonatype { - username = System.getenv("SONATYPE_USERNAME") - password = System.getenv("SONATYPE_PASSWORD") - nexusUrl.set(uri("https://ossrh-staging-api.central.sonatype.com/service/local/")) - } - } - transitionCheckOptions { - maxRetries.set(60) - delayBetween.set(Duration.ofSeconds(20)) - } - connectTimeout.set(Duration.ofMinutes(15)) - clientTimeout.set(Duration.ofMinutes(15)) -} - subprojects { if (project.name == "embrace-android-sdk" || project.name == "embrace-android-api") { apply(plugin = "org.jetbrains.dokka") diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 26674e8116..1c73b00863 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -19,6 +19,7 @@ dependencies { implementation(libs.agp) implementation(libs.detekt.gradle.plugin) implementation(libs.binary.compatibility.validator) + implementation(libs.vanniktech.maven.publish) } gradlePlugin { diff --git a/buildSrc/src/main/kotlin/io/embrace/internal/ProductionModuleConfig.kt b/buildSrc/src/main/kotlin/io/embrace/internal/ProductionModuleConfig.kt index 30b38962bc..6c6f973aa4 100644 --- a/buildSrc/src/main/kotlin/io/embrace/internal/ProductionModuleConfig.kt +++ b/buildSrc/src/main/kotlin/io/embrace/internal/ProductionModuleConfig.kt @@ -7,13 +7,12 @@ import org.gradle.kotlin.dsl.getByType fun Project.configureProductionModule( android: LibraryExtension, - module: EmbraceBuildLogicExtension + module: EmbraceBuildLogicExtension, ) { with(project.pluginManager) { apply("checkstyle") apply("org.jetbrains.kotlinx.kover") - apply("maven-publish") - apply("signing") + apply("com.vanniktech.maven.publish") apply("binary-compatibility-validator") } @@ -37,16 +36,6 @@ fun Project.configureProductionModule( } } - publishing { - - // create component with single publication variant - // https://developer.android.com/studio/publish-library/configure-pub-variants#single-pub-var - singleVariant("release") { - withSourcesJar() - withJavadocJar() - } - } - sourceSets { getByName("test").java.srcDir("src/integrationTest/java") getByName("test").kotlin.srcDir("src/integrationTest/kotlin") diff --git a/buildSrc/src/main/kotlin/io/embrace/internal/PublishConfig.kt b/buildSrc/src/main/kotlin/io/embrace/internal/PublishConfig.kt index 87653740d9..4ec05618e8 100644 --- a/buildSrc/src/main/kotlin/io/embrace/internal/PublishConfig.kt +++ b/buildSrc/src/main/kotlin/io/embrace/internal/PublishConfig.kt @@ -1,95 +1,40 @@ package io.embrace.internal -import java.net.URI +import com.vanniktech.maven.publish.MavenPublishBaseExtension import org.gradle.api.Project -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.register -import org.gradle.kotlin.dsl.withType -import org.gradle.plugins.signing.Sign -import org.gradle.plugins.signing.SigningExtension fun Project.configurePublishing() { - val publishing = project.extensions.getByType(PublishingExtension::class.java) - - // https://developer.android.com/studio/publish-library/upload-library - publishing.apply { - publications { - register("release") { - addPublication(this, "release") - } - } - - // configure repositories where the publication can be hosted - repositories { - // beta releases - maven { - credentials { - username = System.getenv("MAVEN_QA_USER") - password = System.getenv("MAVEN_QA_PASSWORD") + project.pluginManager.withPlugin("com.vanniktech.maven.publish") { + val mavenPublishing = project.extensions.getByType(MavenPublishBaseExtension::class.java) + mavenPublishing.apply { + coordinates("io.embrace", project.name, project.version.toString()) + + publishToMavenCentral() + signAllPublications() + + pom { + name.set(project.name) + description.set("Embrace Android SDK") + url.set("https://github.com/embrace-io/embrace-android-sdk") + licenses { + license { + name.set("Embrace License") + url.set("https://embrace.io/docs/terms-of-service/") + } } - name = "Qa" - url = URI.create("https://repo.embrace.io/repository/beta") - } - // the android-testing maven repository is used for publishing snapshots - maven { - credentials { - username = System.getenv("MAVEN_QA_USER") - password = System.getenv("MAVEN_QA_PASSWORD") + developers { + developer { + id.set("dev1") + name.set("Embrace") + email.set("support@embrace.io") + } + } + scm { + connection.set("scm:git:github.com/embrace-io/embrace-android-sdk.git") + developerConnection.set("scm:git:ssh://github.com/embrace-io/embrace-android-sdk.git") + url.set("https://github.com/embrace-io/embrace-android-sdk/tree/main") } - name = "Snapshot" - url = URI.create("https://repo.embrace.io/repository/android-testing") - } - } - } - - val signing = project.extensions.getByType(SigningExtension::class.java) - - signing.apply { - val keyId = System.getenv("mavenSigningKeyId") - val key = System.getenv("mavenSigningKeyRingFileEncoded") - val password = System.getenv("mavenSigningKeyPassword") - useInMemoryPgpKeys(keyId, key, password) - sign(publishing.publications.getByName("release")) - } - - project.tasks.withType(Sign::class).configureEach { - enabled = !project.version.toString().endsWith("-SNAPSHOT") - } -} - -private fun Project.addPublication(publication: MavenPublication, componentName: String) = with(publication) { - groupId = "io.embrace" - artifactId = project.name - version = project.version.toString() - - afterEvaluate { - from(components[componentName]) - } - - // append some license metadata to the POM. - pom { - name.set(project.name) - description.set("Embrace Android SDK") - url.set("https://github.com/embrace-io/embrace-android-sdk") - licenses { - license { - name.set("Embrace License") - url.set("https://embrace.io/docs/terms-of-service/") - } - } - developers { - developer { - id.set("dev1") - name.set("Embrace") - email.set("support@embrace.io") } } - scm { - connection.set("scm:git:github.com/embrace-io/embrace-android-sdk.git") - developerConnection.set("scm:git:ssh://github.com/embrace-io/embrace-android-sdk.git") - url.set("https://github.com/embrace-io/embrace-android-sdk/tree/main") - } } } diff --git a/embrace-gradle-plugin/build.gradle.kts b/embrace-gradle-plugin/build.gradle.kts index 3671e66675..f3a166bf13 100644 --- a/embrace-gradle-plugin/build.gradle.kts +++ b/embrace-gradle-plugin/build.gradle.kts @@ -2,8 +2,7 @@ plugins { kotlin("jvm") id("java-gradle-plugin") id("groovy") - id("maven-publish") - id("signing") + id("com.vanniktech.maven.publish") alias(libs.plugins.google.ksp) alias(libs.plugins.buildconfig) id("io.embrace.internal.build-logic") @@ -37,17 +36,6 @@ buildConfig { buildConfigField("String", "VERSION", "\"$version\"") } -allprojects { - extra["signing.keyId"] = System.getenv("mavenSigningKeyId") - extra["signing.secretKeyRingFile"] = System.getenv("mavenSigningKeyRingFile") - extra["signing.password"] = System.getenv("mavenSigningKeyPassword") -} - -java { - withJavadocJar() - withSourcesJar() -} - // marker artifact publication gradlePlugin { plugins { @@ -61,105 +49,35 @@ gradlePlugin { } } -// maven-publish plugin publications settings -publishing { - publications { - create("pluginMaven") { - pom { - artifactId = "embrace-swazzler" - name = "embrace-swazzler" - group = "io.embrace" - description = "Embrace Gradle Plugin" - url = "https://github.com/embrace-io/embrace-android-sdk" - licenses { - license { - name = "Embrace License" - url = "https://embrace.io/docs/terms-of-service/" - } - } - developers { - developer { - id = "dev1" - name = "Embrace" - email = "support@embrace.io" - } - } - scm { - connection = "scm:git:github.com/embrace-io/embrace-android-sdk.git" - developerConnection = "scm:git:ssh://github.com/embrace-io/embrace-android-sdk.git" - url = "https://github.com/embrace-io/embrace-android-sdk/tree/main" - } - } - } - } +// Configure Vanniktech Maven Publish Plugin +mavenPublishing { + coordinates("io.embrace", "embrace-swazzler", project.version.toString()) - afterEvaluate { - publications { - named("embraceGradlePluginMarkerMaven") { - pom { - name = "embrace-swazzler" - artifactId = "io.embrace.swazzler.gradle.plugin" - group = "io.embrace" - description = "Embrace Gradle Plugin" - url = "https://github.com/embrace-io/embrace-android-sdk" - licenses { - license { - name = "Embrace License" - url = "https://embrace.io/docs/terms-of-service/" - } - } - developers { - developer { - id = "dev1" - name = "Embrace" - email = "support@embrace.io" - } - } - scm { - connection = "scm:git:github.com/embrace-io/embrace-android-sdk.git" - developerConnection = "scm:git:ssh://github.com/embrace-io/embrace-android-sdk.git" - url = "https://github.com/embrace-io/embrace-android-sdk/tree/main" - } - } - } - } - signing { - setRequired { gradle.taskGraph.hasTask("publishEmbraceGradlePluginMarkerMavenPublicationToSonatypeRepository") } - sign(publishing.publications["embraceGradlePluginMarkerMaven"]) - } - } + publishToMavenCentral() + signAllPublications() - repositories { - // beta releases - maven { - credentials { - username = System.getenv("MAVEN_QA_USER") - password = System.getenv("MAVEN_QA_PASSWORD") + pom { + name = "embrace-swazzler" + group = "io.embrace" + description = "Embrace Gradle Plugin" + url = "https://github.com/embrace-io/embrace-android-sdk" + licenses { + license { + name = "Embrace License" + url = "https://embrace.io/docs/terms-of-service/" } - name = "Qa" - url = uri("https://repo.embrace.io/repository/beta") } - // the android-testing maven repository is used for publishing snapshots - maven { - credentials { - username = System.getenv("MAVEN_QA_USER") - password = System.getenv("MAVEN_QA_PASSWORD") + developers { + developer { + id = "dev1" + name = "Embrace" + email = "support@embrace.io" } - name = "Snapshot" - url = uri("https://repo.embrace.io/repository/android-testing") } - // sonatype repo that provides path to publishing on mavencentral - maven { - credentials { - username = System.getenv("SONATYPE_USERNAME") - password = System.getenv("SONATYPE_PASSWORD") - } - name = "sonatype" - url = uri("https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/") + scm { + connection = "scm:git:github.com/embrace-io/embrace-android-sdk.git" + developerConnection = "scm:git:ssh://github.com/embrace-io/embrace-android-sdk.git" + url = "https://github.com/embrace-io/embrace-android-sdk/tree/main" } } - signing { - setRequired { gradle.taskGraph.hasTask("publishPluginMavenPublicationToSonatypeRepository") } - sign(publishing.publications["pluginMaven"]) - } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 44e9870a60..9b34297a01 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,7 +27,6 @@ androidxRunner = "1.6.2" androidxJunit = "1.2.1" mockwebserver = "4.12.0" ksp = "2.1.21-2.0.2" -nexus = "1.3.0" appcompat = "1.7.1" asmUtil = "9.7" gradleTestKit = "8.11.1" @@ -37,10 +36,12 @@ buildconfig = "5.6.7" agp-api = "7.4.2" apktoolLib = "2.11.1" bundletool = "1.18.1" +vanniktechMavenPublish = "0.33.0" [libraries] binary-compatibility-validator = { module = "org.jetbrains.kotlinx:binary-compatibility-validator", version.ref = "binaryCompatibilityValidator" } detekt-gradle-plugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" } +vanniktech-maven-publish = { module = "com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin", version.ref = "vanniktechMavenPublish" } agp = { module = "com.android.tools.build:gradle", version.ref = "agp" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlinGradlePlugin" } lifecycle-runtime = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } @@ -89,7 +90,6 @@ opentelemetry-java-aliases = { module = "io.embrace.opentelemetry.kotlin:opentel [plugins] google-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -nexus-publish = { id = "io.github.gradle-nexus.publish-plugin", version.ref = "nexus" } agp-library = { id = "com.android.library", version.ref = "agp" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }