GPG key in order to publish

Hi guys, I am new with java development. I have finished my library and I have used gradle in order to build and publish it.
I want to publish to sonatype which as I understand will make it public.
In order to achieve that I have generated a gpg key, exported it with --armor and pasted the contents to github secrets.
My issue is when I try to read it back from github repo secrest it fails.
Is there a workaround for this?
Thanks

hey @jkvargas , take a look at plantuml workflow file which reads it back and uses it:

signing {
	useGpgCmd()
	sign(publishing.publications["maven"])
}

and in the workflow file:

      - name: Setup gpg
        if: env.ARTIFACT_SIGNING_KEY
        id: gpg
        env:
          ARTIFACT_SIGNING_KEY: ${{ secrets.ARTIFACT_SIGNING_KEY }}
        run: |
          echo "Importing key ..."
          echo "${ARTIFACT_SIGNING_KEY}" | gpg --batch --import --import-options import-show
          echo "Getting key id ..."
          key_id="$(echo "${ARTIFACT_SIGNING_KEY}" | gpg --batch --show-keys --with-colons | awk -F: '$1 == "sec" { print $5 }')"
          echo "::set-output name=key_id::${key_id}"
      - name: Sign artifacts
        if: env.GPG_KEYNAME
        env:
          GPG_KEYNAME: ${{ steps.gpg.outputs.key_id }}
          GPG_PASSPHRASE: ${{ secrets.ARTIFACT_SIGNING_PASSPHRASE }}
        run: |
          gradle sign \
            "-Psigning.gnupg.keyName=${GPG_KEYNAME}" \
            "-Psigning.gnupg.passphrase=${GPG_PASSPHRASE}"

I will try it out, @soloturn.
By the way, did you just ctrl+c, ctrl+v the contents of your key into the github secrets site?

i guess i did the same as you, export it:

Why that complex with importing and exporting and extracting and so on?
Gradle has much better support for the GitHub Actions use-case.
That’s exactly what signing { useInMemoryPgpKeys(...) } is for.
You can directly provide the ascii-armored secret key to Gradle with that.

1 Like

i guess one has to decide for local complication or github complication in this case. i saw now that putting the key into the local.properties file would be the way to make it work on both. so you mean doing something like ths?

gpg --export-secret-keys --armor AABBCCDD > AABBCCDD.asc
signingKey=-----BEGIN PGP PRIVATE KEY BLOCK-----\n\nescaped key\n-----END PGP PRIVATE KEY BLOCK-----\n
signingPassphrase=pass
ossrhUsername=user
ossrhPassword=pass
signing {
	if (hasProperty("signingPassphrase")) {
		val signingKey: String? by project
		val signingPassphrase: String? by project
		useInMemoryPgpKeys(signingKey, signingPassphrase)
		sign(publishing.publications)
	}
}
publish:
    name: Publish Artifacts
    needs: [build]
    if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v2
        - name: Set up JDK 8
          uses: actions/setup-java@v2
          with:
            java-version: '8'
            distribution: 'temurin'
        - name: Publish with Gradle
          env:
            ORG_GRADLE_PROJECT_sonatypePassword: ${{ secrets.SONATYPE_PASSWORD }}
            ORG_GRADLE_PROJECT_sonatypeUsername: ${{ secrets.SONATYPE_USERNAME }}
            ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PGP_SECRET }}
            ORG_GRADLE_PROJECT_signingPassphrase: ${{ secrets.PGP_PASSPHRASE }}
          run: ./gradlew publishToSonatype

What do you mean with that?
If you want to publish signed both, from local and CI, you can also do logic like “if property is set, use in memory, if not use gpg command”. Or “if GitHub, use in memory, if not use gpg command”. Or similar logic.

1 Like

Great progess,

plugins {
    id 'java-library'
    id 'jvm-test-suite'
    id 'maven-publish'
    id 'signing'
}

group 'com.evervault'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

def getRepositoryUsername() {
    return hasProperty("ossrhUsername") ? ossrhUsername : ""
}

def getRepositoryPassword() {
    return hasProperty("ossrhPassword") ? ossrhPassword : ""
}

def getKeyFile() {
    return hasProperty("signingKey") ? signingKey : ""
}

def getKeyPassword() {
    return hasProperty("signingPassword") ? signingPassword : ""
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter:5.7.2'
    testImplementation "com.github.tomakehurst:wiremock-jre8:2.32.0"
    testImplementation "org.mockito:mockito-core:3.+"

    implementation 'com.google.code.gson:gson:2.8.9'
    implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.70'
}

java {
    withJavadocJar()
    withSourcesJar()
}

testing {
    suites {
        test {
            useJUnitJupiter()
        }
        integrationTests(JvmTestSuite) {
            dependencies {
                implementation project
                implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: '1.70'
            }
        }
    }
}

publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java

            artifact sourcesJar
            artifact javadocJar

            pom {
                name = 'mycompany'
                description = 'mycompany SDK enabling developers to integrate their applications with mycompany services'
                url = 'https://github.com/mycompany/mycompany
                scm {
                    url = 'https://github.com/mycompany/mycompany'
                    connection = 'scm:git:ssh://git@github.mycompany/mycompany.git'
                }
                licenses {
                    license {
                        name = 'The MIT License (MIT)'
                        url = 'https://mit-license.org/'
                    }
                }
                developers {
                    developer {
                        name = 'mycompany'
                        organization = 'mycompany'
                        email = 'mycompany@mycompany.com'
                    }
                }
                organization {
                    name = 'mycompany'
                    url = 'https://www.mycompany.com/'
                }
            }
        }
    }
    repositories {
        maven {
            name = 'sonatype'
            def releasesRepoUrl = 'https://oss.sonatype.org/service/local/staging/deploy/maven2'
            def snapshotsRepoUrl = 'https://oss.sonatype.org/content/repositories/snapshots'
            url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl
            credentials {
                username getRepositoryUsername()
                password getRepositoryPassword()
            }
        }
    }
}

signing {
    useInMemoryPgpKeys(getKeyFile(), getKeyPassword())
    sign publishing.publications.mavenJava
}

javadoc {
    if(JavaVersion.current().isJava9Compatible()) {
        options.addBooleanOption('html5', true)
    }
}

Error: -13T15:20:29.068+0000 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] > Invalid publication ‘mavenJava’: multiple artifacts with the identical extension and classifier (‘jar’, ‘sources’).

I suppose my artifacts are not correct.

Exactly.
withJavadocJar() and withSourcesJar() already add those jars to the java component.
And then you add them a second time to the publication manually.
Just remove the manual addition.