From a449fcf42af3a0a02e2ea75de17b90d4beeb3392 Mon Sep 17 00:00:00 2001 From: David Lynn Date: Fri, 11 Mar 2022 12:53:36 +0000 Subject: [PATCH 1/5] Feature/357 deploy to maven central (#477) As mentioned in the gradle plugin documentation: https://github.com/google/protobuf-gradle-plugin#customizing-protobuf-compilation exe is the default classifier, so use this for all binaries. Further, we publish all existing binaries. --- .github/workflows/release.yaml | 13 ++++++++ build.gradle | 56 ++++++++++++++++++++++++++++++++++ settings.gradle | 1 + 3 files changed, 70 insertions(+) create mode 100644 build.gradle create mode 100644 settings.gradle diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index e14a0b7d..2efebad5 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -29,3 +29,16 @@ jobs: args: release --rm-dist env: GITHUB_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }} + - name: Set up Java + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + - name: Publish package + uses: gradle/gradle-build-action@v2 + with: + gradle-version: 7.4 + arguments: publish + env: + MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..5a36610f --- /dev/null +++ b/build.gradle @@ -0,0 +1,56 @@ +plugins { + id 'maven-publish' +} + +publishing { + + publications { + maven(MavenPublication) { + groupId = 'io.github.pseudomuto' + artifactId = rootProject.name + version = System.getenv("GITHUB_REF_NAME") + + //linux 64 arm + artifact("$projectDir/dist/protoc-gen-doc_linux_arm64/protoc-gen-doc") { + classifier 'linux-aarch_64' + extension 'exe' + } + //linux 64 intel + artifact("$projectDir/dist/protoc-gen-doc_linux_amd64/protoc-gen-doc") { + classifier 'linux-x86_64' + extension 'exe' + } + //mac 64 arm + artifact("$projectDir/dist/protoc-gen-doc_darwin_arm64/protoc-gen-doc") { + classifier 'osx-aarch_64' + extension 'exe' + } + //mac 64 intel + artifact("$projectDir/dist/protoc-gen-doc_darwin_amd64/protoc-gen-doc") { + classifier 'osx-x86_64' + extension 'exe' + } + //windows 64 arm + artifact("$projectDir/dist/protoc-gen-doc_windows_arm64/protoc-gen-doc.exe") { + classifier 'windows-aarch_64' + extension 'exe' + } + //windows 64 intel + artifact("$projectDir/dist/protoc-gen-doc_windows_amd64/protoc-gen-doc.exe") { + classifier 'windows-x86_64' + extension 'exe' + } + } + } + + repositories { + maven { + name = "OSSRH" + url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + credentials { + username = System.getenv("MAVEN_USERNAME") + password = System.getenv("MAVEN_PASSWORD") + } + } + } +} diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 00000000..a8a3b3f3 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'protoc-gen-doc' From 16b156d4bda3463a24306175b9db7d4941a73ac0 Mon Sep 17 00:00:00 2001 From: David Lynn Date: Fri, 11 Mar 2022 13:17:48 +0000 Subject: [PATCH 2/5] Bugfix/357 fix maven url (#478) https://issues.sonatype.org/browse/OSSRH-78889 mentioned that it has put this repository onto the new cluster. We should change the upload URL. --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 5a36610f..7001b86e 100644 --- a/build.gradle +++ b/build.gradle @@ -46,7 +46,7 @@ publishing { repositories { maven { name = "OSSRH" - url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" + url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" credentials { username = System.getenv("MAVEN_USERNAME") password = System.getenv("MAVEN_PASSWORD") From cb5e8a8fb250239b3350077fab6dbae78fd97692 Mon Sep 17 00:00:00 2001 From: David Lynn Date: Mon, 14 Mar 2022 13:27:49 +0000 Subject: [PATCH 3/5] Issue #357 Add extra steps needed for official Maven Central release. (#479) The previous commits managed to upload the artifacts to the staging area, however these could not pass the review due to missing requirements. This required more information to be provided in the POM file, and the releases signed. This commit adds the information and signing. The signing is done by GPG and requires 2 new secrets to be provided: * GPG_SIGNING_KEY: The GPG key in armoured form. * GPG_SIGNING_PASSWORD: The password for signing the artifact. If a GPG key does not already exist, this guide can be followed: https://docs.github.com/en/authentication/managing-commit-signature-verification/generating-a-new-gpg-key The value needed for the GPG_SIGNING_KEY secret can be found by: * Finding the key name using `gpg --list-keys` * Outputting the key using `gpg --armor --export-secret-key [name] > ~/my-key.asc` * Copying the contents of that text file to the secret. Once a release is done, the aritfacts will appear in the staging repository here: https://s01.oss.sonatype.org/#stagingRepositories This staging repository can be "closed" which will execute the checks. If all checks pass (they have in my experiments) the "Release" workflow will become available. The only strangeness I encountered was that originally only 2 of the releases were getting signed. This appears to be an issue with publishing files of the same name. I have worked around the issue by creating a copy of the files under names which include their architecture. After I did this the signing worked correctly. --- .github/workflows/release.yaml | 2 + .gitignore | 2 + CONTRIBUTING.md | 6 +++ build.gradle | 93 ++++++++++++++++++++++++++-------- 4 files changed, 83 insertions(+), 20 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2efebad5..446a0399 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -42,3 +42,5 @@ jobs: env: MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} + ORG_GRADLE_PROJECT_signingKey: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGKEY }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_SIGNINGPASSWORD }} diff --git a/.gitignore b/.gitignore index 11a78782..53d06e3d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ +/.gradle /bin +/build /coverage.txt /dist /tmp/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2a1ebf74..775bb5f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -76,3 +76,9 @@ From an up-to-date master, do the following: 1. `git push origin master --tags`. Once the tag is on GitHub, the release action will handle pushing to docker and creating a release in GitHub. + +### Publish the Maven artifacts + +1. Head over to https://s01.oss.sonatype.org/#stagingRepositories +1. Verify the contents of the staging repo and close it +1. After successful closing (test suite is run), release the repo diff --git a/build.gradle b/build.gradle index 7001b86e..eeeaa5a5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,44 +1,70 @@ plugins { id 'maven-publish' + id 'signing' } -publishing { +group = 'io.github.pseudomuto' +publishing { publications { maven(MavenPublication) { groupId = 'io.github.pseudomuto' artifactId = rootProject.name version = System.getenv("GITHUB_REF_NAME") + pom { + name = groupId + ':' + rootProject.name + description = 'This is a documentation generator plugin for the Google Protocol Buffers compiler (protoc). The plugin can generate HTML, JSON, DocBook, and Markdown documentation from comments in your .proto files.' + url = 'https://github.com/pseudomuto/protoc-gen-doc' + licenses { + license { + name = 'MIT License' + url = 'https://github.com/pseudomuto/protoc-gen-doc/blob/master/LICENSE.md' + } + } + developers { + developer { + id = 'pseudomuto' + name = 'David Muto' + email = 'david.muto@gmail.com' + } + } + scm { + connection = 'scm:git:git@github.com:pseudomuto/protoc-gen-doc.git' + developerConnection = 'scm:git:git@github.com:pseudomuto/protoc-gen-doc.git' + url = 'https://github.com/pseudomuto/protoc-gen-doc' + } + } + //linux 64 arm - artifact("$projectDir/dist/protoc-gen-doc_linux_arm64/protoc-gen-doc") { - classifier 'linux-aarch_64' - extension 'exe' + artifact("$buildDir/dist/protoc-gen-doc_linux_arm64") { + classifier 'linux-aarch_64' + extension 'exe' } //linux 64 intel - artifact("$projectDir/dist/protoc-gen-doc_linux_amd64/protoc-gen-doc") { - classifier 'linux-x86_64' - extension 'exe' + artifact("$buildDir/dist/protoc-gen-doc_linux_amd64") { + classifier 'linux-x86_64' + extension 'exe' } //mac 64 arm - artifact("$projectDir/dist/protoc-gen-doc_darwin_arm64/protoc-gen-doc") { - classifier 'osx-aarch_64' - extension 'exe' + artifact("$buildDir/dist/protoc-gen-doc_darwin_arm64") { + classifier 'osx-aarch_64' + extension 'exe' } //mac 64 intel - artifact("$projectDir/dist/protoc-gen-doc_darwin_amd64/protoc-gen-doc") { - classifier 'osx-x86_64' - extension 'exe' + artifact("$buildDir/dist/protoc-gen-doc_darwin_amd64") { + classifier 'osx-x86_64' + extension 'exe' } //windows 64 arm - artifact("$projectDir/dist/protoc-gen-doc_windows_arm64/protoc-gen-doc.exe") { - classifier 'windows-aarch_64' - extension 'exe' + artifact("$buildDir/dist/protoc-gen-doc_windows_arm64") { + classifier 'windows-aarch_64' + extension 'exe' } //windows 64 intel - artifact("$projectDir/dist/protoc-gen-doc_windows_amd64/protoc-gen-doc.exe") { - classifier 'windows-x86_64' - extension 'exe' + artifact("$buildDir/dist/protoc-gen-doc_windows_amd64") { + classifier 'windows-x86_64' + extension 'exe' } } } @@ -46,7 +72,9 @@ publishing { repositories { maven { name = "OSSRH" - url = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + def releasesRepoUrl = "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" + def snapshotsRepoUrl = "https://s01.oss.sonatype.org/content/repositories/snapshots/" + url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl credentials { username = System.getenv("MAVEN_USERNAME") password = System.getenv("MAVEN_PASSWORD") @@ -54,3 +82,28 @@ publishing { } } } + +signing { + def signingKey = project.getProperty('signingKey') + def signingPassword = project.getProperty('signingPassword') + useInMemoryPgpKeys(signingKey, signingPassword) + sign publishing.publications.maven +} + +// A strange issue with signing meant that only the first files (with the same name) got signed. +// To workaround this, rename all executables to include architecture. +tasks.register('flattenDistDirectory', Copy) { + from("$projectDir/dist") { + include "**/protoc-gen-doc" + include "**/protoc-gen-doc.exe" + eachFile { file -> + file.name = file.relativePath.parent.lastName + file.relativePath = new RelativePath(true, file.relativePath.segments.drop(1)) + } + includeEmptyDirs = false + } + into "$buildDir/dist" +} + +publish.dependsOn flattenDistDirectory +signMavenPublication.mustRunAfter flattenDistDirectory From ebeafcb3250350a5114ab21245142f5f909dc7b4 Mon Sep 17 00:00:00 2001 From: David Muto Date: Mon, 14 Mar 2022 10:45:25 -0400 Subject: [PATCH 4/5] Adding example for usage with Gradle (#481) Now that the artifacts are published to Nexus, I've added an example project showing how it can be used with gradle. --- README.md | 3 ++ examples/gradle/.gitignore | 2 ++ examples/gradle/README.md | 5 +++ examples/gradle/build.gradle | 29 +++++++++++++++++ examples/gradle/settings.gradle | 1 + examples/gradle/src/main/proto/Demo.proto | 38 +++++++++++++++++++++++ 6 files changed, 78 insertions(+) create mode 100644 examples/gradle/.gitignore create mode 100644 examples/gradle/README.md create mode 100644 examples/gradle/build.gradle create mode 100644 examples/gradle/settings.gradle create mode 100644 examples/gradle/src/main/proto/Demo.proto diff --git a/README.md b/README.md index 40c45399..2bdc8587 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,9 @@ If you'd like to install this locally, you can `go get` it. Alternatively, you can download a pre-built release for your platform from the [releases][] page. +Finally, this plugin is also available on Maven Central. For details about how to use it, check out the [gradle +example](examples/gradle). + ## Invoking the Plugin The plugin is invoked by passing the `--doc_out`, and `--doc_opt` options to the `protoc` compiler. The option has the diff --git a/examples/gradle/.gitignore b/examples/gradle/.gitignore new file mode 100644 index 00000000..67bcc2f7 --- /dev/null +++ b/examples/gradle/.gitignore @@ -0,0 +1,2 @@ +.gradle/ +build/ diff --git a/examples/gradle/README.md b/examples/gradle/README.md new file mode 100644 index 00000000..a5892edd --- /dev/null +++ b/examples/gradle/README.md @@ -0,0 +1,5 @@ +# Gradle Example + +This is an example project that leverages protoc-gen-doc. You can test it out by running `gradle generateProto`. + +After a successful run, you should see `grpc-docs.md` in the _build/generated/source/proto/main/doc_ directory. diff --git a/examples/gradle/build.gradle b/examples/gradle/build.gradle new file mode 100644 index 00000000..0031af7e --- /dev/null +++ b/examples/gradle/build.gradle @@ -0,0 +1,29 @@ +plugins { + id 'java' + id 'com.google.protobuf' version '0.8.18' +} + +protobuf { + protoc { + artifact = "com.google.protobuf:protoc:3.19.4" + } + plugins { + doc { + artifact = "io.github.pseudomuto:protoc-gen-doc:v1.5.1" + } + } + + generateProtoTasks { + all().each { task -> + task.plugins { + doc { + option 'markdown,grpc-docs.md' + } + } + } + } +} + +repositories { + mavenCentral() +} diff --git a/examples/gradle/settings.gradle b/examples/gradle/settings.gradle new file mode 100644 index 00000000..69c97751 --- /dev/null +++ b/examples/gradle/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'gradle-demo' diff --git a/examples/gradle/src/main/proto/Demo.proto b/examples/gradle/src/main/proto/Demo.proto new file mode 100644 index 00000000..c100988c --- /dev/null +++ b/examples/gradle/src/main/proto/Demo.proto @@ -0,0 +1,38 @@ +/** + * Demo proto with sample messages. + * + * This file is really just an example. The data model is completely + * fictional. + * + * For examples of more complex protos, see examples/proto in the protoc-gen-doc repo. + */ +syntax = "proto3"; + +package com.example; + +/** + * Represents a mail address. + */ +message Address { + string address_line_1 = 1; /** First address line. */ + string address_line_2 = 2; /** Second address line. */ + string address_line_3 = 3; /** Second address line. */ + + string town = 4; /// Address town. + string county = 5; /// Address county, if applicable. + string country = 6; /// Address country. +} + +/** + * Represents a customer. + */ +message Customer { + int32 id = 1; /// Unique customer ID. + string first_name = 2; /// Customer first name. + string last_name = 3; /// Customer last name. + string details = 4; /// Customer details. + + string email_address = 5; /// Customer e-mail address. + repeated string phone_number = 6; /// Customer phone numbers, primary first. + repeated Address mail_addresses = 7; /// Customer mail addresses, primary first. +} From a0aae67ea2fca1c046ce56ee46334b61b6386ed9 Mon Sep 17 00:00:00 2001 From: David Lynn Date: Tue, 15 Mar 2022 12:02:32 +0000 Subject: [PATCH 5/5] Issue #357 Fix version number in Maven (#482) It is not usual for a version number to be prefixed with v... in Maven. An easy fix to strip this "v" when it exists. --- build.gradle | 4 ++++ examples/gradle/build.gradle | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index eeeaa5a5..10b7d2fd 100644 --- a/build.gradle +++ b/build.gradle @@ -11,6 +11,10 @@ publishing { groupId = 'io.github.pseudomuto' artifactId = rootProject.name version = System.getenv("GITHUB_REF_NAME") + // Strip "v" from version number + if (version.startsWith("v")) { + version = version.substring(1) + } pom { name = groupId + ':' + rootProject.name diff --git a/examples/gradle/build.gradle b/examples/gradle/build.gradle index 0031af7e..0f0a3abe 100644 --- a/examples/gradle/build.gradle +++ b/examples/gradle/build.gradle @@ -9,7 +9,7 @@ protobuf { } plugins { doc { - artifact = "io.github.pseudomuto:protoc-gen-doc:v1.5.1" + artifact = "io.github.pseudomuto:protoc-gen-doc:1.5.1" } }