All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.danielflower.mavenplugins.release.Reactor Maven / Gradle / Ivy

Go to download

A maven release plugin built for multi-maven-module git repositories allowing continuous deployment

There is a newer version: 3.6.4
Show newest version
package com.github.danielflower.mavenplugins.release;

import org.apache.maven.model.Dependency;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class Reactor {

    private final List modulesInBuildOrder;

    public Reactor(List modulesInBuildOrder) {
        this.modulesInBuildOrder = modulesInBuildOrder;
    }

    public List getModulesInBuildOrder() {
        return modulesInBuildOrder;
    }

    public static Reactor fromProjects(Log log, LocalGitRepo gitRepo, MavenProject rootProject, List projects, Long buildNumber, List modulesToForceRelease) throws ValidationException, GitAPIException, MojoExecutionException {
        DiffDetector detector = new TreeWalkingDiffDetector(gitRepo.git.getRepository());
        List modules = new ArrayList();
        VersionNamer versionNamer = new VersionNamer();
        for (MavenProject project : projects) {
            String relativePathToModule = calculateModulePath(rootProject, project);
            String artifactId = project.getArtifactId();
            String versionWithoutBuildNumber = project.getVersion().replace("-SNAPSHOT", "");
            List previousTagsForThisModule = AnnotatedTagFinder.tagsForVersion(gitRepo.git, artifactId, versionWithoutBuildNumber);


            Collection previousBuildNumbers = new ArrayList();
            if (previousTagsForThisModule != null) {
                for (AnnotatedTag previousTag : previousTagsForThisModule) {
                    previousBuildNumbers.add(previousTag.buildNumber());
                }
            }

            Collection remoteBuildNumbers = getRemoteBuildNumbers(gitRepo, artifactId, versionWithoutBuildNumber);
            previousBuildNumbers.addAll(remoteBuildNumbers);

            VersionName newVersion = versionNamer.name(project.getVersion(), buildNumber, previousBuildNumbers);

            boolean oneOfTheDependenciesHasChanged = false;
            String changedDependency = null;
            for (ReleasableModule module : modules) {
                if (module.willBeReleased()) {
                    for (Dependency dependency : project.getModel().getDependencies()) {
                        if (dependency.getGroupId().equals(module.getGroupId()) && dependency.getArtifactId().equals(module.getArtifactId())) {
                            oneOfTheDependenciesHasChanged = true;
                            changedDependency = dependency.getArtifactId();
                            break;
                        }
                    }
                    if (project.getParent() != null
                            && (project.getParent().getGroupId().equals(module.getGroupId()) && project.getParent().getArtifactId().equals(module.getArtifactId()))) {
                        oneOfTheDependenciesHasChanged = true;
                        changedDependency = project.getParent().getArtifactId();
                        break;
                    }
                }
                if (oneOfTheDependenciesHasChanged) {
                    break;
                }
            }

            String equivalentVersion = null;

            if(modulesToForceRelease != null && modulesToForceRelease.contains(artifactId)) {
                log.info("Releasing " + artifactId + " " + newVersion.releaseVersion() + " as we was asked to forced release.");
            }else if (oneOfTheDependenciesHasChanged) {
                log.info("Releasing " + artifactId + " " + newVersion.releaseVersion() + " as " + changedDependency + " has changed.");
            } else {
                AnnotatedTag previousTagThatIsTheSameAsHEADForThisModule = hasChangedSinceLastRelease(previousTagsForThisModule, detector, project, relativePathToModule);
                if (previousTagThatIsTheSameAsHEADForThisModule != null) {
                    equivalentVersion = previousTagThatIsTheSameAsHEADForThisModule.version() + "." + previousTagThatIsTheSameAsHEADForThisModule.buildNumber();
                    log.info("Will use version " + equivalentVersion + " for " + artifactId + " as it has not been changed since that release.");
                } else {
                    log.info("Will use version " + newVersion.releaseVersion() + " for " + artifactId + " as it has changed since the last release.");
                }
            }
            ReleasableModule module = new ReleasableModule(project, newVersion, equivalentVersion, relativePathToModule);
            modules.add(module);
        }

        if (!atLeastOneBeingReleased(modules)) {
            log.warn("No changes have been detected in any modules so will re-release them all");
            List newList = new ArrayList();
            for (ReleasableModule module : modules) {
                newList.add(module.createReleasableVersion());
            }
            modules = newList;
        }

        return new Reactor(modules);
    }

    private static Collection getRemoteBuildNumbers(LocalGitRepo gitRepo, String artifactId, String versionWithoutBuildNumber) throws GitAPIException {
        Collection remoteTagRefs = gitRepo.allRemoteTags();
        Collection remoteBuildNumbers = new ArrayList();
        String tagWithoutBuildNumber = artifactId + "-" + versionWithoutBuildNumber;
        for (Ref remoteTagRef : remoteTagRefs) {
            String remoteTagName = remoteTagRef.getName();
            Long buildNumber = AnnotatedTagFinder.buildNumberOf(tagWithoutBuildNumber, remoteTagName);
            if (buildNumber != null) {
                remoteBuildNumbers.add(buildNumber);
            }
        }
        return remoteBuildNumbers;
    }

    private static boolean atLeastOneBeingReleased(List modules) {
        for (ReleasableModule module : modules) {
            if (module.willBeReleased()) {
                return true;
            }
        }
        return false;
    }

    private static String calculateModulePath(MavenProject rootProject, MavenProject project) throws MojoExecutionException {
        // Getting canonical files because on Windows, it's possible one returns "C:\..." and the other "c:\..." which is rather amazing
        File projectRoot;
        File moduleRoot;
        try {
            projectRoot = rootProject.getBasedir().getCanonicalFile();
            moduleRoot = project.getBasedir().getCanonicalFile();
        } catch (IOException e) {
            throw new MojoExecutionException("Could not find directory paths for maven project", e);
        }
        String relativePathToModule = Repository.stripWorkDir(projectRoot, moduleRoot);
        if (relativePathToModule.length() == 0) {
            relativePathToModule = ".";
        }
        return relativePathToModule;
    }

    static AnnotatedTag hasChangedSinceLastRelease(List previousTagsForThisModule, DiffDetector detector, MavenProject project, String relativePathToModule) throws MojoExecutionException {
        try {
            if (previousTagsForThisModule.size() == 0) return null;
            boolean hasChanged = detector.hasChangedSince(relativePathToModule, project.getModel().getModules(), previousTagsForThisModule);
            return hasChanged ? null : tagWithHighestBuildNumber(previousTagsForThisModule);
        } catch (Exception e) {
            throw new MojoExecutionException("Error while detecting whether or not " + project.getArtifactId() + " has changed since the last release", e);
        }
    }

    private static AnnotatedTag tagWithHighestBuildNumber(List tags) {
        AnnotatedTag cur = null;
        for (AnnotatedTag tag : tags) {
            if (cur == null || tag.buildNumber() > cur.buildNumber()) {
                cur = tag;
            }
        }
        return cur;
    }

    public ReleasableModule findByLabel(String label) {
        for (ReleasableModule module : modulesInBuildOrder) {
            String currentLabel = module.getGroupId() + ":" + module.getArtifactId();
            if (currentLabel.equals(label)) {
                return module;
            }
        }
        return null;
    }

    public ReleasableModule find(String groupId, String artifactId, String version) throws UnresolvedSnapshotDependencyException {
        ReleasableModule value = findByLabel(groupId + ":" + artifactId);
        if (value == null) {
            throw new UnresolvedSnapshotDependencyException(groupId, artifactId, version);
        }
        return value;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy