Introduce verify command to verify configuration settings.
Closes #182.
This commit is contained in:
@@ -19,8 +19,13 @@ Add an `application-local.properties` to the project root and add the following
|
|||||||
- `deployment.password` - The encrypted Artifactory password..
|
- `deployment.password` - The encrypted Artifactory password..
|
||||||
- `gpg.keyname` - The GPG key name.
|
- `gpg.keyname` - The GPG key name.
|
||||||
- `gpg.password` - The password of your GPG key.
|
- `gpg.password` - The password of your GPG key.
|
||||||
- `gpg.executable` - Path to your GPG executable, typically `/usr/local/MacGPG2/bin/gpg2` or `/usr/local/bin/gpg`.
|
- `gpg.executable` - Path to your GPG executable, typically `/usr/local/MacGPG2/bin/gpg2`
|
||||||
- `sagan.key` - Sagan authentication token. Must be a valid GitHub token. Can be the same as `git.password` when using a GitHub token as password.
|
or `/usr/local/bin/gpg`.
|
||||||
|
- `sagan.key` - Sagan authentication token. Must be a valid GitHub token. Can be the same
|
||||||
|
as `git.password` when using a GitHub token as password.
|
||||||
|
|
||||||
|
After that, run the `verify` command (`$ verify`) to verify your settings (authentication,
|
||||||
|
correct Maven, Java, and GPG setup).
|
||||||
|
|
||||||
See `application-local.template` for details.
|
See `application-local.template` for details.
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import org.springframework.data.release.model.Module;
|
|||||||
import org.springframework.data.release.model.ModuleIteration;
|
import org.springframework.data.release.model.ModuleIteration;
|
||||||
import org.springframework.data.release.model.Phase;
|
import org.springframework.data.release.model.Phase;
|
||||||
import org.springframework.data.release.model.Project;
|
import org.springframework.data.release.model.Project;
|
||||||
|
import org.springframework.data.release.model.Projects;
|
||||||
import org.springframework.data.release.model.Train;
|
import org.springframework.data.release.model.Train;
|
||||||
import org.springframework.data.release.model.TrainIteration;
|
import org.springframework.data.release.model.TrainIteration;
|
||||||
import org.springframework.data.release.utils.Logger;
|
import org.springframework.data.release.utils.Logger;
|
||||||
@@ -198,6 +199,12 @@ public class BuildOperations {
|
|||||||
executor.doWithBuildSystemAnyOrder(iteration, BuildSystem::triggerPreReleaseCheck);
|
executor.doWithBuildSystemAnyOrder(iteration, BuildSystem::triggerPreReleaseCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void verify() {
|
||||||
|
|
||||||
|
BuildSystem buildSystem = buildSystems.getRequiredPluginFor(Projects.BUILD);
|
||||||
|
buildSystem.verify();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the build system for the module contained in the given {@link ModuleIteration} and executes the given
|
* Selects the build system for the module contained in the given {@link ModuleIteration} and executes the given
|
||||||
* function with it.
|
* function with it.
|
||||||
@@ -215,4 +222,5 @@ public class BuildOperations {
|
|||||||
|
|
||||||
return function.apply(buildSystems.getPluginFor(module.getProject(), exception), module);
|
return function.apply(buildSystems.getPluginFor(module.getProject(), exception), module);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,4 +72,9 @@ interface BuildSystem extends Plugin<Project> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
<M extends ProjectAware> M triggerPreReleaseCheck(M module);
|
<M extends ProjectAware> M triggerPreReleaseCheck(M module);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify general functionality and correctness of the build setup.
|
||||||
|
*/
|
||||||
|
void verify();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,7 @@ class CommandLine {
|
|||||||
public static final Goal INSTALL = Goal.goal("install");
|
public static final Goal INSTALL = Goal.goal("install");
|
||||||
public static final Goal DEPLOY = Goal.goal("deploy");
|
public static final Goal DEPLOY = Goal.goal("deploy");
|
||||||
public static final Goal VALIDATE = Goal.goal("validate");
|
public static final Goal VALIDATE = Goal.goal("validate");
|
||||||
|
public static final Goal VERIFY = Goal.goal("verify");
|
||||||
|
|
||||||
String goal;
|
String goal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,6 +306,28 @@ class MavenBuildSystem implements BuildSystem {
|
|||||||
return isMavenProject(project);
|
return isMavenProject(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.release.build.BuildSystem#verify()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void verify() {
|
||||||
|
|
||||||
|
logger.log(BUILD, "Verifying Maven Build System…");
|
||||||
|
|
||||||
|
CommandLine arguments = CommandLine.of(Goal.CLEAN, Goal.VERIFY, //
|
||||||
|
profile("central"), //
|
||||||
|
SKIP_TESTS, //
|
||||||
|
arg("gpg.executable").withValue(gpg.getExecutable()), //
|
||||||
|
arg("gpg.keyname").withValue(gpg.getKeyname()), //
|
||||||
|
arg("gpg.password").withValue(gpg.getPassword()));
|
||||||
|
|
||||||
|
mvn.execute(BUILD, arguments);
|
||||||
|
|
||||||
|
mvn.execute(BUILD, CommandLine.of(Goal.goal("nexus-staging:rc-list-profiles"), //
|
||||||
|
profile("central")));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggers Maven commands to deploy module artifacts to Spring Artifactory.
|
* Triggers Maven commands to deploy module artifacts to Spring Artifactory.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2021 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.springframework.data.release.cli;
|
||||||
|
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.NonNull;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
import org.springframework.data.release.CliComponent;
|
||||||
|
import org.springframework.data.release.TimedCommand;
|
||||||
|
import org.springframework.data.release.build.BuildOperations;
|
||||||
|
import org.springframework.data.release.deployment.DeploymentOperations;
|
||||||
|
import org.springframework.data.release.git.GitOperations;
|
||||||
|
import org.springframework.data.release.issues.github.GitHub;
|
||||||
|
import org.springframework.data.release.issues.jira.Jira;
|
||||||
|
import org.springframework.data.release.sagan.SaganClient;
|
||||||
|
import org.springframework.data.release.utils.Logger;
|
||||||
|
import org.springframework.shell.core.annotation.CliCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commands to verify a correct Release Tools Setup.
|
||||||
|
*
|
||||||
|
* @author Mark Paluch
|
||||||
|
*/
|
||||||
|
@CliComponent
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@FieldDefaults(level = AccessLevel.PRIVATE, makeFinal = true)
|
||||||
|
class VerifyCommands extends TimedCommand {
|
||||||
|
|
||||||
|
@NonNull GitOperations git;
|
||||||
|
@NonNull GitHub github;
|
||||||
|
@NonNull DeploymentOperations deployment;
|
||||||
|
@NonNull BuildOperations build;
|
||||||
|
@NonNull Jira jira;
|
||||||
|
@NonNull SaganClient saganClient;
|
||||||
|
@NonNull Logger logger;
|
||||||
|
|
||||||
|
@CliCommand("verify")
|
||||||
|
public void verifyReleaseTools() {
|
||||||
|
|
||||||
|
// Git checkout build
|
||||||
|
git.verify();
|
||||||
|
|
||||||
|
// Maven interaction
|
||||||
|
build.verify();
|
||||||
|
|
||||||
|
// Artifactory verification
|
||||||
|
deployment.verifyAuthentication();
|
||||||
|
|
||||||
|
// GitHub verification
|
||||||
|
github.verifyAuthentication();
|
||||||
|
|
||||||
|
// Jira verification
|
||||||
|
jira.verifyAuthentication();
|
||||||
|
|
||||||
|
// Sagan Verification
|
||||||
|
saganClient.verifyAuthentication();
|
||||||
|
|
||||||
|
logger.log("Verify", "All settings are verified. You can ship a release now.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -812,6 +812,13 @@ public class GitOperations {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify general Git operations.
|
||||||
|
*/
|
||||||
|
public void verify() {
|
||||||
|
checkout(Projects.BUILD, Branch.MASTER);
|
||||||
|
}
|
||||||
|
|
||||||
private void cherryPickCommitToBranch(ObjectId id, Project project, Branch branch) {
|
private void cherryPickCommitToBranch(ObjectId id, Project project, Branch branch) {
|
||||||
|
|
||||||
doWithGit(project, git -> {
|
doWithGit(project, git -> {
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ import org.springframework.http.HttpEntity;
|
|||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.web.client.HttpStatusCodeException;
|
import org.springframework.web.client.HttpStatusCodeException;
|
||||||
@@ -62,7 +63,7 @@ import org.springframework.web.client.HttpStatusCodeException;
|
|||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
class GitHub extends GitHubSupport implements IssueTracker {
|
public class GitHub extends GitHubSupport implements IssueTracker {
|
||||||
|
|
||||||
private static final String MILESTONE_URI = "/repos/spring-projects/{repoName}/milestones?state={state}";
|
private static final String MILESTONE_URI = "/repos/spring-projects/{repoName}/milestones?state={state}";
|
||||||
private static final String ISSUES_BY_MILESTONE_AND_ASSIGNEE_URI_TEMPLATE = "/repos/spring-projects/{repoName}/issues?milestone={id}&state=all&assignee={assignee}";
|
private static final String ISSUES_BY_MILESTONE_AND_ASSIGNEE_URI_TEMPLATE = "/repos/spring-projects/{repoName}/issues?milestone={id}&state=all&assignee={assignee}";
|
||||||
@@ -565,6 +566,28 @@ class GitHub extends GitHubSupport implements IssueTracker {
|
|||||||
logger.log(module, "GitHub Release up to date");
|
logger.log(module, "GitHub Release up to date");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify GitHub authentication.
|
||||||
|
*/
|
||||||
|
public void verifyAuthentication() {
|
||||||
|
|
||||||
|
logger.log("GitHub", "Verifying GitHub Authentication…");
|
||||||
|
|
||||||
|
String repositoryName = GitProject.of(Projects.BUILD).getRepositoryName();
|
||||||
|
|
||||||
|
Map<String, Object> parameters = newUrlTemplateVariables();
|
||||||
|
parameters.put("repoName", repositoryName);
|
||||||
|
|
||||||
|
// /user requires authentication
|
||||||
|
ResponseEntity<Object> entity = operations.getForEntity("/user", Object.class);
|
||||||
|
|
||||||
|
if (!entity.getStatusCode().is2xxSuccessful()) {
|
||||||
|
throw new IllegalStateException(String.format("Cannot obtain /user. Status: %s", entity.getStatusCode()));
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log("GitHub", "Authentication verified!");
|
||||||
|
}
|
||||||
|
|
||||||
private String getDocumentationLinks(ModuleIteration module, DocumentationMetadata documentation) {
|
private String getDocumentationLinks(ModuleIteration module, DocumentationMetadata documentation) {
|
||||||
|
|
||||||
String referenceDocUrl = documentation.getReferenceDocUrl(module.getTrain());
|
String referenceDocUrl = documentation.getReferenceDocUrl(module.getTrain());
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import org.springframework.web.util.DefaultUriBuilderFactory;
|
|||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
class Jira implements JiraConnector {
|
public class Jira implements JiraConnector {
|
||||||
|
|
||||||
private static final String CREATE_ISSUES_TEMPLATE = "/issue";
|
private static final String CREATE_ISSUES_TEMPLATE = "/issue";
|
||||||
private static final String ISSUE_TEMPLATE = "/issue/{ticketId}";
|
private static final String ISSUE_TEMPLATE = "/issue/{ticketId}";
|
||||||
@@ -620,6 +620,22 @@ class Jira implements JiraConnector {
|
|||||||
return project.uses(Tracker.JIRA);
|
return project.uses(Tracker.JIRA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify Jira Authentication.
|
||||||
|
*/
|
||||||
|
public void verifyAuthentication() {
|
||||||
|
|
||||||
|
logger.log("Jira", "Verifying Jira Authentication…");
|
||||||
|
|
||||||
|
ResponseEntity<Object> entity = operations.getForEntity("/myself", Object.class);
|
||||||
|
|
||||||
|
if (!entity.getStatusCode().is2xxSuccessful()) {
|
||||||
|
throw new IllegalStateException("Cannot access Jira user profile");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log("Jira", "Authentication verified!");
|
||||||
|
}
|
||||||
|
|
||||||
protected JiraComponents getJiraComponents(ProjectKey projectKey) {
|
protected JiraComponents getJiraComponents(ProjectKey projectKey) {
|
||||||
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ import java.util.List;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import org.springframework.data.release.model.Project;
|
import org.springframework.data.release.model.Project;
|
||||||
|
import org.springframework.data.release.model.Projects;
|
||||||
import org.springframework.data.release.utils.Logger;
|
import org.springframework.data.release.utils.Logger;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.client.RestOperations;
|
import org.springframework.web.client.RestOperations;
|
||||||
|
|
||||||
import com.jayway.jsonpath.JsonPath;
|
import com.jayway.jsonpath.JsonPath;
|
||||||
@@ -104,6 +106,26 @@ class DefaultSaganClient implements SaganClient {
|
|||||||
createVersions(versions, resource, versionsInSagan);
|
createVersions(versions, resource, versionsInSagan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.release.sagan.SaganClient#verifyAuthentication()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void verifyAuthentication() {
|
||||||
|
|
||||||
|
URI resource = properties.getProjectReleasesResource(Projects.BUILD);
|
||||||
|
|
||||||
|
logger.log("Sagan", "Verifying Sagan Authentication…");
|
||||||
|
|
||||||
|
ResponseEntity<String> entity = operations.getForEntity(resource, String.class);
|
||||||
|
|
||||||
|
if (!entity.getStatusCode().is2xxSuccessful()) {
|
||||||
|
throw new IllegalStateException("Cannot access Jira user profile");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log("Sagan", "Authentication verified!");
|
||||||
|
}
|
||||||
|
|
||||||
private void createVersions(MaintainedVersions versions, URI resource, List<String> versionsInSagan) {
|
private void createVersions(MaintainedVersions versions, URI resource, List<String> versionsInSagan) {
|
||||||
|
|
||||||
versions.stream() //
|
versions.stream() //
|
||||||
|
|||||||
@@ -85,4 +85,13 @@ class DummySaganClient implements SaganClient {
|
|||||||
public String getProjectMetadata(Project project) {
|
public String getProjectMetadata(Project project) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.release.sagan.SaganClient#verifyAuthentication()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void verifyAuthentication() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ import org.springframework.data.release.model.Project;
|
|||||||
* Interface to abstract the actual interaction with the Sagan server.
|
* Interface to abstract the actual interaction with the Sagan server.
|
||||||
*
|
*
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
|
* @author Mark Paluch
|
||||||
*/
|
*/
|
||||||
interface SaganClient {
|
public interface SaganClient {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the project metadata for the given {@link MaintainedVersion}.
|
* Returns the project metadata for the given {@link MaintainedVersion}.
|
||||||
@@ -47,4 +48,9 @@ interface SaganClient {
|
|||||||
* @param versions must not be {@literal null}.
|
* @param versions must not be {@literal null}.
|
||||||
*/
|
*/
|
||||||
void updateProjectMetadata(Project project, MaintainedVersions versions);
|
void updateProjectMetadata(Project project, MaintainedVersions versions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify correct authentication setup.
|
||||||
|
*/
|
||||||
|
void verifyAuthentication();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user