diff --git a/.github/workflows/ci-manual-publish-jvm-release.yml b/.github/workflows/ci-manual-publish-jvm-release.yml new file mode 100644 index 000000000..3ad33415b --- /dev/null +++ b/.github/workflows/ci-manual-publish-jvm-release.yml @@ -0,0 +1,61 @@ +name: Manually Publish Release - JVM Protobuf +on: + workflow_dispatch: + branches: + - master +jobs: + build: + name: Manually publish release + runs-on: ubuntu-latest + env: + JAVA_OPTS: -Xmx2g -Dorg.gradle.daemon=false + #services: + # flow-emulator: + # image: gcr.io/flow-container-registry/emulator + # env: + # FLOW_VERBOSE: true + # FLOW_PORT: 3569 + # FLOW_INTERVAL: 5s + # FLOW_PERSIST: false + # ports: + # - 3569:3569 + steps: + - name: Get current date + id: date + run: echo "::set-output name=date::$(date +'%Y%m%d%H%M%S')" + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v2 + with: + java-version: '21' + java-package: jdk + distribution: 'adopt' + + - name: Make gradle executable + run: chmod +x ./protobuf/gradlew + + - name: Build + id: build + run: cd protobuf && ./gradlew --warning-mode all check build + + - name: Publish release + env: + JAVA_OPTS: -Xmx2g -Dorg.gradle.daemon=false + ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.FLOW_JVM_SDK_SONATYPE_USERNAME }}' + ORG_GRADLE_PROJECT_mavenCentralPassword: '${{ secrets.FLOW_JVM_SDK_SONATYPE_PASSWORD }}' + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.FLOW_JVM_SDK_SIGNING_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.FLOW_JVM_SDK_SIGNING_PASSWORD }} + + run: | + cd protobuf + if [[ "${{ secrets.FLOW_JVM_SDK_CICD_PUBLISH_ENABLED }}" != "true" ]]; + then + exit 0; + fi + ./gradlew \ + -Psigning.key="${{ secrets.FLOW_JVM_SDK_SIGNING_KEY }}" \ + -Psigning.password="${{ secrets.FLOW_JVM_SDK_SIGNING_PASSWORD }}" \ + publishAndReleaseToMavenCentral --no-configuration-cache diff --git a/.github/workflows/ci-manual-publish-jvm-snapshot.yml b/.github/workflows/ci-manual-publish-jvm-snapshot.yml new file mode 100644 index 000000000..698a44cef --- /dev/null +++ b/.github/workflows/ci-manual-publish-jvm-snapshot.yml @@ -0,0 +1,61 @@ +name: Manually Publish Snapshot - JVM Protobuf +on: + workflow_dispatch: + branches: + - master +jobs: + build: + name: Manually publish snapshot + runs-on: ubuntu-latest + env: + JAVA_OPTS: -Xmx2g -Dorg.gradle.daemon=false + #services: + # flow-emulator: + # image: gcr.io/flow-container-registry/emulator + # env: + # FLOW_VERBOSE: true + # FLOW_PORT: 3569 + # FLOW_INTERVAL: 5s + # FLOW_PERSIST: false + # ports: + # - 3569:3569 + steps: + - name: Get current date + id: date + run: echo "::set-output name=date::$(date +'%Y%m%d%H%M%S')" + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v2 + with: + java-version: '21' + java-package: jdk + distribution: 'adopt' + + - name: Make gradle executable + run: chmod +x ./protobuf/gradlew + + - name: Build + id: build + run: cd protobuf && ./gradlew --warning-mode all check build + + - name: Publish snapshot + env: + JAVA_OPTS: -Xmx2g -Dorg.gradle.daemon=false + ORG_GRADLE_PROJECT_mavenCentralUsername: '${{ secrets.FLOW_JVM_SDK_SONATYPE_USERNAME }}' + ORG_GRADLE_PROJECT_mavenCentralPassword: '${{ secrets.FLOW_JVM_SDK_SONATYPE_PASSWORD }}' + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.FLOW_JVM_SDK_SIGNING_KEY }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.FLOW_JVM_SDK_SIGNING_PASSWORD }} + + run: | + cd protobuf + if [[ "${{ secrets.FLOW_JVM_SDK_CICD_PUBLISH_ENABLED }}" != "true" ]]; + then + exit 0; + fi + ./gradlew \ + -Psigning.key="${{ secrets.FLOW_JVM_SDK_SIGNING_KEY }}" \ + -Psigning.password="${{ secrets.FLOW_JVM_SDK_SIGNING_PASSWORD }}" \ + publishToMavenCentral --no-configuration-cache diff --git a/.github/workflows/ci-pull-request-jvm-protobuf.yml b/.github/workflows/ci-pull-request-jvm-protobuf.yml new file mode 100644 index 000000000..38ad0d1d1 --- /dev/null +++ b/.github/workflows/ci-pull-request-jvm-protobuf.yml @@ -0,0 +1,36 @@ +name: Build Pull Request - JVM Protobuf +on: pull_request + +jobs: + build: + name: Build pull request + runs-on: ubuntu-latest + env: + JAVA_OPTS: -Xmx2g -Dorg.gradle.daemon=false + #services: + # flow-emulator: + # image: gcr.io/flow-container-registry/emulator + # env: + # FLOW_VERBOSE: true + # FLOW_PORT: 3569 + # FLOW_INTERVAL: 5s + # FLOW_PERSIST: false + # ports: + # - 3569:3569 + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Java + uses: actions/setup-java@v2 + with: + java-version: '21' + java-package: jdk + distribution: 'adopt' + + - name: Make gradle executable + run: chmod +x ./protobuf/gradlew + + - name: Build + id: build + run: cd protobuf && ./gradlew --warning-mode all check build diff --git a/protobuf/README.md b/protobuf/README.md index 6db032358..ab3c45222 100644 --- a/protobuf/README.md +++ b/protobuf/README.md @@ -27,12 +27,19 @@ JVM support is in the alpha stage; many steps require manual intervention. `./gradlew generateProto` compiles Protobuf files into local Java classes. -### Publishing +### Publishing with GitHub Actions -`./gradlew publishToSonatype` prepares and publishes compiled classes into JAR and uploads to OSSRH staging repository. +The "com.vanniktech.maven.publish" plugin is used to automate Maven releases for JVM protobuf generation. More information on the release process can be found here [here](https://vanniktech.github.io/gradle-maven-publish-plugin/central/). -This requires signing artifacts which is done by [Signing Gradle plugin](https://docs.gradle.org/current/userguide/signing_plugin.html) - it requires -external configuration and appropriate GPG Keys. Please refer to plugin and [OSSRH](https://central.sonatype.org/pages/working-with-pgp-signatures.html) -documentation. -Uploading to staging repo requires an approved Sonatype account. Please refer to [Gradle Nexus Publish Plugin](https://github.com/gradle-nexus/publish-plugin) -documentation how to provide credentials. +There are two GitHub Actions configured to run on the master branch: + +- SNAPSHOT: On every commit to the `master` branch a build is performed and if successful it is deployed as a snapshot version. +- RELEASE: Whenever a tag is created with the pattern of `vXXX` a version with the name XXX is built and if successful deployed as a release version. + +The following GitHub repository secrets configure these actions: + +- `FLOW_JVM_SDK_CICD_PUBLISH_ENABLED`: (optional) Must be `true` for the publishing of artifacts to happen (defaults to `false`) +- `FLOW_JVM_SDK_SIGNING_KEY`: (required if publish enabled) ascii armored version of the pgp key for signing releases +- `FLOW_JVM_SDK_SIGNING_PASSWORD`: (required if publish enabled) password to the pgp key +- `FLOW_JVM_SDK_SONATYPE_USERNAME`: (required if publish enabled) sonatype username +- `FLOW_JVM_SDK_SONATYPE_PASSWORD`: (required if publish enabled) sonatype password diff --git a/protobuf/build.gradle.kts b/protobuf/build.gradle.kts index 85e102ed8..c42ac15ee 100644 --- a/protobuf/build.gradle.kts +++ b/protobuf/build.gradle.kts @@ -1,17 +1,88 @@ import com.google.protobuf.gradle.* +import com.vanniktech.maven.publish.SonatypeHost +fun getProp(name: String, defaultValue: String? = null): String? { + return project.findProperty("flow.$name")?.toString()?.trim()?.ifBlank { null } + ?: project.findProperty(name)?.toString()?.trim()?.ifBlank { null } + ?: defaultValue +} + +// configuration variables +val defaultGroupId = "org.onflow" +val defaultVersion = "1.0.0" + +group = getProp("groupId", defaultGroupId)!! +version = when { + getProp("version") !in setOf("unspecified", null) -> { getProp("version")!! } + getProp("snapshotDate") != null -> { "${defaultVersion.replace("-SNAPSHOT", "")}.${getProp("snapshotDate")!!}-SNAPSHOT" } + else -> { defaultVersion } +} plugins { - id("com.google.protobuf") version "0.8.15" + id("com.google.protobuf") version "0.9.4" + kotlin("jvm") version "1.9.22" `java-library` `maven-publish` signing id("io.github.gradle-nexus.publish-plugin") version "1.0.0" + id ("com.vanniktech.maven.publish") version "0.28.0" } val protobufVersion = "3.14.0" val grpcVersion = "1.35.0" +dependencies { + api("com.google.protobuf:protobuf-java:$protobufVersion") + api("io.grpc:grpc-netty-shaded:$grpcVersion") + api("io.grpc:grpc-protobuf:$grpcVersion") + api("io.grpc:grpc-stub:$grpcVersion") + api("javax.annotation:javax.annotation-api:1.3.2") +} + +java { + sourceCompatibility = JavaVersion.VERSION_20 + targetCompatibility = JavaVersion.VERSION_20 +} + +tasks.named("generateProto") { + dependsOn(tasks.named("processResources")) + dependsOn(tasks.named("extractIncludeTestProto")) + dependsOn(tasks.named("extractTestProto")) +} + +tasks { + mavenPublishing { + publishToMavenCentral(SonatypeHost.DEFAULT, true) + + coordinates(group.toString(), "flow", version.toString()) + + signAllPublications() + + pom { + licenses { + license { + name.set("The Apache License, Version 2.0") + url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + name.set(project.name) + url.set("https://onflow.org") + description.set("The Flow Blockchain") + scm { + url.set("https://github.com/onflow/flow") + connection.set("scm:git:git@github.com/onflow/flow.git") + developerConnection.set("scm:git:git@github.com/onflow/flow.git") + } + developers { + developer { + name.set("Flow Developers") + url.set("https://onflow.org") + } + } + } + } +} + protobuf { protoc { artifact = "com.google.protobuf:protoc:$protobufVersion" @@ -30,54 +101,13 @@ protobuf { } } -dependencies { - api("com.google.protobuf:protobuf-java:$protobufVersion") - api("io.grpc:grpc-netty-shaded:$grpcVersion") - api("io.grpc:grpc-protobuf:$grpcVersion") - api("io.grpc:grpc-stub:$grpcVersion") - api("javax.annotation:javax.annotation-api:1.3.2") -} - -nexusPublishing { - repositories { - sonatype() - } -} - -publishing { - publications { - create("mavenJava") { - from(components["java"]) - - pom { - licenses { - license { - name.set("The Apache License, Version 2.0") - url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") - } - } - name.set(project.name) - url.set("https://onflow.org") - description.set("The Flow Blockchain") - scm { - url.set("https://github.com/onflow/flow") - connection.set("scm:git:git@github.com/onflow/flow.git") - developerConnection.set("scm:git:git@github.com/onflow/flow.git") - } - developers { - developer { - name.set("Flow Developers") - url.set("https://onflow.org") - } - } - } - } - } -} - signing { - useGpgCmd() //use gpg2 - sign(publishing.publications["mavenJava"]) + if (getProp("signing.key") != null) { + useInMemoryPgpKeys(getProp("signing.key"), getProp("signing.password")) + } else { + useGpgCmd() + } + sign(publishing.publications) } sourceSets { @@ -97,16 +127,7 @@ java { withSourcesJar() } -tasks.compileJava { - sourceCompatibility = "1.8" - targetCompatibility = "1.8" -} - repositories { mavenCentral() } -group = "org.onflow" - -// TODO - grab version from Git -version = "0.21" diff --git a/protobuf/gradle/wrapper/gradle-wrapper.properties b/protobuf/gradle/wrapper/gradle-wrapper.properties index 2a563242c..a59520664 100644 --- a/protobuf/gradle/wrapper/gradle-wrapper.properties +++ b/protobuf/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists