From 6a9c3c80275f9e33e82feb5355c9a534c95a6c9e Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Mon, 14 Nov 2022 08:48:59 +0100 Subject: [PATCH] Refactor GPG key handling to allow using separate GPG keys. Closes #7 --- Jenkinsfile | 3 +- ci/prepare-and-build.bash | 5 +++- ci/prepare-and-build.template | 3 +- ci/release.properties | 2 +- .../data/release/build/MavenBuildSystem.java | 18 +++++++++-- .../deployment/DeploymentProperties.java | 10 +++++-- .../data/release/git/GitOperations.java | 30 +++++++++++++++---- .../data/release/git/GitProperties.java | 7 +++++ .../data/release/issues/github/GitHub.java | 2 +- .../resources/application-jenkins.properties | 10 ++++++- 10 files changed, 74 insertions(+), 16 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6f50882..df3e705 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -29,11 +29,12 @@ pipeline { GIT_AUTHOR = credentials('spring-data-release-git-author') GIT_EMAIL = credentials('spring-data-release-git-email') GIT_PASSWORD = credentials('3a20bcaa-d8ad-48e3-901d-9fbc941376ee') - GITHUB_API_URL = credentials('spring-data-release-github-api-url') DEPLOYMENT_API_KEY = credentials('repo_spring_io-jenkins-release-token') STAGING_PROFILE_ID = credentials('spring-data-release-deployment-maven-central-staging-profile-id') PASSPHRASE = credentials('spring-gpg-passphrase') KEYRING = credentials('spring-signing-secring.gpg') + GIT_SIGNING_KEY = credentials('spring-gpg-github-private-key-jenkins') + GIT_SIGNING_KEY_PASSWORD = credentials('spring-gpg-github-passphrase-jenkins') SONATYPE = credentials('oss-login') GPG_KEYNAME = credentials('spring-data-release-gpg-keyname') } diff --git a/ci/prepare-and-build.bash b/ci/prepare-and-build.bash index 7da0f58..ea0de6f 100755 --- a/ci/prepare-and-build.bash +++ b/ci/prepare-and-build.bash @@ -11,7 +11,7 @@ export PATH="$MAVEN_HOME/bin:$JAVA_HOME/bin:$PATH" export JENKINS_HOME=/tmp/jenkins-home export RELEASE_TOOLS_CACHE=${JENKINS_HOME}/.m2/spring-data-release-tools -export LOGS_DIR=${JENKINS_HOME}/spring-data-shell/logs +export LOGS_DIR=$(pwd)/logs export SETTINGS_XML=${JENKINS_HOME}/settings.xml mkdir -p ${RELEASE_TOOLS_CACHE} @@ -47,6 +47,9 @@ else ls -lR ~/.gnupg id + echo "${GIT_SIGNING_KEY_PASSWORD}" | /usr/bin/gpg --batch --yes --passphrase-fd 0 --import "${GIT_SIGNING_KEY}" + /usr/bin/gpg -k + function spring-data-release-shell { java \ -Dspring.profiles.active=jenkins \ diff --git a/ci/prepare-and-build.template b/ci/prepare-and-build.template index dd79063..6b18cb5 100644 --- a/ci/prepare-and-build.template +++ b/ci/prepare-and-build.template @@ -1,4 +1,5 @@ -verify deployment workspace cleanup +verify github +verify deployment release prepare ${VERSION} release build ${VERSION} diff --git a/ci/release.properties b/ci/release.properties index 1cd962b..b5abcf9 100644 --- a/ci/release.properties +++ b/ci/release.properties @@ -1,2 +1,2 @@ # Release train version -release.version=2022.0.0-RC2 +release.version=2021.2.6 diff --git a/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java b/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java index 9de9775..863dba7 100644 --- a/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java +++ b/src/main/java/org/springframework/data/release/build/MavenBuildSystem.java @@ -40,7 +40,6 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.IOUtils; - import org.springframework.core.annotation.Order; import org.springframework.core.env.Environment; import org.springframework.data.release.build.CommandLine.Argument; @@ -49,6 +48,7 @@ import org.springframework.data.release.build.Pom.Artifact; import org.springframework.data.release.deployment.DefaultDeploymentInformation; import org.springframework.data.release.deployment.DeploymentInformation; import org.springframework.data.release.deployment.DeploymentProperties; +import org.springframework.data.release.deployment.DeploymentProperties.MavenCentral; import org.springframework.data.release.deployment.StagingRepository; import org.springframework.data.release.io.Workspace; import org.springframework.data.release.model.ArtifactVersion; @@ -63,7 +63,6 @@ import org.springframework.data.release.utils.Logger; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; - import org.xmlbeam.ProjectionFactory; import org.xmlbeam.XBProjector; import org.xmlbeam.dom.DOMAccess; @@ -418,6 +417,8 @@ class MavenBuildSystem implements BuildSystem { logger.log(BUILD, "Verifying Maven Build System…"); + Gpg gpg = getGpg(); + CommandLine arguments = CommandLine.of(Goal.CLEAN, Goal.VERIFY, // profile("central"), // SKIP_TESTS, // @@ -488,6 +489,8 @@ class MavenBuildSystem implements BuildSystem { logger.log(module, "Deploying artifacts to Sonatype OSS Nexus…"); + Gpg gpg = getGpg(); + CommandLine arguments = CommandLine.of(Goal.CLEAN, Goal.DEPLOY, // profile("ci,release,central"), // SKIP_TESTS, // @@ -510,6 +513,17 @@ class MavenBuildSystem implements BuildSystem { doWithProjection(file, Pom.class, callback); } + private Gpg getGpg() { + + MavenCentral mavenCentral = properties.getMavenCentral(); + + if (mavenCentral.hasGpgConfiguration()) { + return mavenCentral.getGpg(); + } + + return gpg; + } + /** * TODO: Move XML file callbacks using the {@link ProjectionFactory} to {@link Workspace}. */ diff --git a/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java b/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java index adedb37..a76aa22 100644 --- a/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java +++ b/src/main/java/org/springframework/data/release/deployment/DeploymentProperties.java @@ -15,17 +15,18 @@ */ package org.springframework.data.release.deployment; -import lombok.Data; - import java.net.URI; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.data.release.model.Gpg; import org.springframework.data.release.model.Password; import org.springframework.data.release.utils.HttpBasicCredentials; import org.springframework.stereotype.Component; import org.springframework.util.Assert; import org.springframework.web.util.UriTemplate; +import lombok.Data; + /** * @author Oliver Gierke * @author Mark Paluch @@ -126,6 +127,11 @@ public class DeploymentProperties { private String stagingProfileId; + private Gpg gpg; + + public boolean hasGpgConfiguration() { + return gpg != null && gpg.isGpgAvailable(); + } } } diff --git a/src/main/java/org/springframework/data/release/git/GitOperations.java b/src/main/java/org/springframework/data/release/git/GitOperations.java index 5be4057..63c74e2 100644 --- a/src/main/java/org/springframework/data/release/git/GitOperations.java +++ b/src/main/java/org/springframework/data/release/git/GitOperations.java @@ -25,7 +25,19 @@ import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.TimeZone; +import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; @@ -58,7 +70,6 @@ import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.TagOpt; import org.eclipse.jgit.transport.URIish; - import org.springframework.data.release.io.Workspace; import org.springframework.data.release.issues.IssueTracker; import org.springframework.data.release.issues.Ticket; @@ -697,6 +708,8 @@ public class GitOperations { String email = gitProperties.getEmail(); boolean allowEmpty = all; + Gpg gpg = getGpg(); + logger.log(project, "git commit -m \"%s\" %s --author=\"%s <%s>\"", commit.getSummary(), gpg.isGpgAvailable() ? "-S" + gpg.getKeyname() : "", author, email); @@ -1077,6 +1090,15 @@ public class GitOperations { void doWithGit(Git git) throws Exception; } + private Gpg getGpg() { + + if (gitProperties.hasGpgConfiguration()) { + return gitProperties.getGpg(); + } + + return gpg; + } + /** * {@link CredentialsProvider} for GPG Keys used with JGit Commit Signing. */ @@ -1127,8 +1149,4 @@ public class GitOperations { return false; } } - - private static class VersionedIterations { - - } } diff --git a/src/main/java/org/springframework/data/release/git/GitProperties.java b/src/main/java/org/springframework/data/release/git/GitProperties.java index 74079db..aa33c73 100644 --- a/src/main/java/org/springframework/data/release/git/GitProperties.java +++ b/src/main/java/org/springframework/data/release/git/GitProperties.java @@ -24,6 +24,7 @@ import javax.annotation.PostConstruct; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.data.release.model.Gpg; import org.springframework.data.release.model.Password; import org.springframework.data.release.utils.HttpBasicCredentials; import org.springframework.stereotype.Component; @@ -43,6 +44,8 @@ public class GitProperties { private @Getter(AccessLevel.PRIVATE) Password password; private String username, author, email; + private Gpg gpg; + @PostConstruct public void init() { @@ -64,4 +67,8 @@ public class GitProperties { public HttpBasicCredentials getHttpCredentials() { return new HttpBasicCredentials(username, password); } + + public boolean hasGpgConfiguration() { + return gpg != null && gpg.isGpgAvailable(); + } } diff --git a/src/main/java/org/springframework/data/release/issues/github/GitHub.java b/src/main/java/org/springframework/data/release/issues/github/GitHub.java index 8b20ba3..81c47bb 100644 --- a/src/main/java/org/springframework/data/release/issues/github/GitHub.java +++ b/src/main/java/org/springframework/data/release/issues/github/GitHub.java @@ -614,7 +614,7 @@ public class GitHub extends GitHubSupport implements IssueTracker { throw new IllegalStateException(String.format("Cannot obtain /user. Status: %s", entity.getStatusCode())); } - logger.log("GitHub", "Authentication verified!"); + logger.log("GitHub", "Authentication verified."); } private String getDocumentationLinks(ModuleIteration module, DocumentationMetadata documentation) { diff --git a/src/main/resources/application-jenkins.properties b/src/main/resources/application-jenkins.properties index a1ad224..a0db912 100644 --- a/src/main/resources/application-jenkins.properties +++ b/src/main/resources/application-jenkins.properties @@ -3,7 +3,10 @@ git.author=${GIT_AUTHOR} git.email=${GIT_EMAIL} git.password=${GIT_PASSWORD} -github.api.url=${GITHUB_API_URL} +git.gpg.keyname=6743E1BD +git.gpg.passphrase=${GIT_SIGNING_KEY_PASSWORD} +git.gpg.secretKeyring=${GNUPGHOME}/secring.gpg +git.gpg.executable=/usr/bin/gpg deployment.username=${DEPLOYMENT_API_KEY_USR} deployment.password=${DEPLOYMENT_API_KEY_PSW} @@ -22,5 +25,10 @@ maven.home=${MAVEN_HOME} maven.console-logger=false maven.repo.local=${RELEASE_TOOLS_CACHE} +maven.maven-central.gpg.keyname=${GPG_KEYNAME} +maven.maven-central.gpg.passphrase=${PASSPHRASE} +maven.maven-central.gpg.secretKeyring=${GNUPGHOME}/secring.gpg +maven.maven-central.gpg.executable=/usr/bin/gpg + io.workDir=dist io.logs=${LOGS_DIR}