The rationale of this pull request is to * have more maintainable and granular code * not maintain the custom made job engine * allow the users to customize the defaults of the releaser more easy * allow the users to create their own steps without the need to change any existing code * allow the users to fully change the flows and tasks logic * abstract underlying batch mechanism (Spring Batch) so it doesn't leak to production code * allow parallelization of the release process and release tasks
224 lines
8.1 KiB
Java
224 lines
8.1 KiB
Java
/*
|
|
* Copyright 2013-2019 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 releaser.cloud.docs;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import releaser.internal.ReleaserProperties;
|
|
import releaser.internal.docs.CustomProjectDocumentationUpdater;
|
|
import releaser.internal.git.ProjectGitHandler;
|
|
import releaser.internal.project.ProjectVersion;
|
|
import releaser.internal.project.Projects;
|
|
|
|
import org.springframework.util.FileSystemUtils;
|
|
import org.springframework.util.StringUtils;
|
|
|
|
/**
|
|
* @author Marcin Grzejszczak
|
|
*/
|
|
class SpringCloudCustomProjectDocumentationUpdater
|
|
implements CustomProjectDocumentationUpdater {
|
|
|
|
private static final Logger log = LoggerFactory
|
|
.getLogger(SpringCloudCustomProjectDocumentationUpdater.class);
|
|
|
|
private final ProjectGitHandler gitHandler;
|
|
|
|
private final ReleaserProperties releaserProperties;
|
|
|
|
SpringCloudCustomProjectDocumentationUpdater(ProjectGitHandler gitHandler,
|
|
ReleaserProperties releaserProperties) {
|
|
this.gitHandler = gitHandler;
|
|
this.releaserProperties = releaserProperties;
|
|
}
|
|
|
|
/**
|
|
* Updates the documentation repository if current release train version is greater or
|
|
* equal than the one stored in the repo.
|
|
* @param currentProject project to update the docs repo for
|
|
* @param bomBranch the bom project branch
|
|
* @return {@link File cloned temporary directory} - {@code null} if wrong version is
|
|
* used
|
|
*/
|
|
@Override
|
|
public File updateDocsRepoForReleaseTrain(File clonedDocumentationProject,
|
|
ProjectVersion currentProject, Projects projects, String bomBranch) {
|
|
log.debug("Cloning the doc project to [{}]", clonedDocumentationProject);
|
|
ProjectVersion releaseTrainProject = new ProjectVersion(
|
|
this.releaserProperties.getMetaRelease().getReleaseTrainProjectName(),
|
|
branchToReleaseVersion(bomBranch));
|
|
File currentReleaseFolder = new File(clonedDocumentationProject, currentFolder(
|
|
releaseTrainProject.projectName, releaseTrainProject.version));
|
|
// remove the old way
|
|
removeAFolderWithRedirection(currentReleaseFolder);
|
|
File docsRepo = updateTheDocsRepo(releaseTrainProject, clonedDocumentationProject,
|
|
currentReleaseFolder);
|
|
return pushChanges(docsRepo);
|
|
}
|
|
|
|
/**
|
|
* Updates the documentation repository if current release train version is greater or
|
|
* equal than the one stored in the repo.
|
|
* @param currentProject project to update the docs repo for
|
|
* @return {@link File cloned temporary directory} - {@code null} if wrong version is
|
|
* used
|
|
*/
|
|
@Override
|
|
public File updateDocsRepoForSingleProject(File clonedDocumentationProject,
|
|
ProjectVersion currentProject, Projects projects) {
|
|
if (!projects.containsProject(currentProject.projectName)) {
|
|
log.warn(
|
|
"Can't update the documentation repo for project [{}] cause it's not present on the projects list {}",
|
|
currentProject.projectName, projects);
|
|
return clonedDocumentationProject;
|
|
}
|
|
log.info("Updating link to documentation for project [{}]",
|
|
currentProject.projectName);
|
|
ProjectVersion projectVersion = projects.forName(currentProject.projectName);
|
|
File currentProjectReleaseFolder = new File(clonedDocumentationProject,
|
|
currentFolder(projectVersion.projectName, projectVersion.version));
|
|
removeAFolderWithRedirection(currentProjectReleaseFolder);
|
|
try {
|
|
updateTheDocsRepo(projectVersion, clonedDocumentationProject,
|
|
currentProjectReleaseFolder);
|
|
log.info("Processed [{}] for project with name [{}]",
|
|
currentProjectReleaseFolder, projectVersion.projectName);
|
|
}
|
|
catch (Exception ex) {
|
|
log.warn("Exception occurred while trying o update the symlink of a project ["
|
|
+ projectVersion.projectName + "]", ex);
|
|
}
|
|
return pushChanges(clonedDocumentationProject);
|
|
}
|
|
|
|
private void removeAFolderWithRedirection(File currentReleaseFolder) {
|
|
if (!isSymbolinkLink(currentReleaseFolder)) {
|
|
FileSystemUtils.deleteRecursively(currentReleaseFolder);
|
|
}
|
|
}
|
|
|
|
private boolean isSymbolinkLink(File currentFolder) {
|
|
return Files.isSymbolicLink(currentFolder.toPath());
|
|
}
|
|
|
|
private String currentFolder(String projectName, String projectVersion) {
|
|
boolean releaseTrain = new ProjectVersion(projectName, projectVersion)
|
|
.isReleaseTrain();
|
|
// release train -> static/current
|
|
// project -> static/spring-cloud-sleuth/current
|
|
return releaseTrain ? "current"
|
|
: (StringUtils.hasText(projectName) ? projectName : "") + "/current";
|
|
}
|
|
|
|
String linkToVersion(File file) {
|
|
if (Files.isSymbolicLink(file.toPath())) {
|
|
try {
|
|
Path path = Files.readSymbolicLink(file.toPath());
|
|
// current -> Hoxton.SR2
|
|
// spring-cloud-sleuth/current -> spring-cloud-sleuth/1.2.3.RELEASE
|
|
return folderName(path.toString());
|
|
}
|
|
catch (IOException ex) {
|
|
throw new IllegalStateException(ex);
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private String folderName(String path) {
|
|
int last = path.lastIndexOf(File.separator);
|
|
return last > 0 ? path.substring(last + 1) : path;
|
|
}
|
|
|
|
private String concreteVersionFolder(ProjectVersion projectVersion) {
|
|
String projectName = projectVersion.projectName;
|
|
boolean releaseTrain = projectVersion.isReleaseTrain();
|
|
// release train -> static/Hoxton.SR2/
|
|
// project -> static/spring-cloud-sleuth/1.2.3.RELEASE/
|
|
String prefix = releaseTrain ? projectVersion.version
|
|
: (projectName + "/" + projectVersion.version);
|
|
return prefix + "/";
|
|
}
|
|
|
|
private File pushChanges(File docsRepo) {
|
|
this.gitHandler.pushCurrentBranch(docsRepo);
|
|
log.info("Committed and pushed changes to the documentation project");
|
|
return docsRepo;
|
|
}
|
|
|
|
private File updateTheDocsRepo(ProjectVersion projectVersion,
|
|
File documentationProject, File currentVersionFolder) {
|
|
try {
|
|
String storedVersion = linkToVersion(currentVersionFolder);
|
|
String currentVersion = projectVersion.version;
|
|
boolean newerVersion = StringUtils.isEmpty(storedVersion)
|
|
|| isMoreMature(storedVersion, currentVersion);
|
|
if (!newerVersion) {
|
|
log.info("Current version [{}] is not newer than the stored one [{}]",
|
|
currentVersion, storedVersion);
|
|
return documentationProject;
|
|
}
|
|
boolean deleted = Files.deleteIfExists(currentVersionFolder.toPath())
|
|
|| FileSystemUtils.deleteRecursively(currentVersionFolder.toPath());
|
|
if (deleted) {
|
|
log.info("Deleted current version folder link at [{}]",
|
|
currentVersionFolder);
|
|
}
|
|
boolean creatingParentDirs = currentVersionFolder.getParentFile().mkdirs();
|
|
if (!creatingParentDirs) {
|
|
log.warn("Failed to create parent directory of [{}]",
|
|
currentVersionFolder);
|
|
}
|
|
File newTarget = new File(projectVersion.version);
|
|
Files.createSymbolicLink(currentVersionFolder.toPath(), newTarget.toPath());
|
|
log.info("Updated the link [{}] to point to [{}]",
|
|
currentVersionFolder.toPath(),
|
|
Files.readSymbolicLink(currentVersionFolder.toPath()));
|
|
return commitChanges(currentVersion, documentationProject);
|
|
}
|
|
catch (IOException e) {
|
|
throw new IllegalStateException(e);
|
|
}
|
|
}
|
|
|
|
private boolean isMoreMature(String storedVersion, String currentVersion) {
|
|
return new ProjectVersion("project", currentVersion)
|
|
.isMoreMature(new ProjectVersion("project", storedVersion));
|
|
}
|
|
|
|
private String branchToReleaseVersion(String branch) {
|
|
if (branch.startsWith("v")) {
|
|
return branch.substring(1);
|
|
}
|
|
return branch;
|
|
}
|
|
|
|
private File commitChanges(String currentVersion, File documentationProject)
|
|
throws IOException {
|
|
log.info("Updated the symbolic links");
|
|
this.gitHandler.commit(documentationProject,
|
|
"Updating the link to the current version to [" + currentVersion + "]");
|
|
return documentationProject;
|
|
}
|
|
|
|
}
|