Skip to content

Commit

Permalink
Lock plugin versions (#152)
Browse files Browse the repository at this point in the history
A simple mojo to lock plugin versions.

It needs to be run in top level  module
and will gather all the plugins used in reactor
and upsert pluginManagement entries for them.

If -DapplyToPom is used.
  • Loading branch information
cstamas authored Dec 16, 2024
1 parent d711a14 commit 327c8dd
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,8 @@ interface EditSession extends Closeable {
EditSession createEditSession(Path pom) throws IOException;

/**
* Calculates list of "latest" artifacts based on {@link #versions(String, Source, Predicate)} query result.
* Calculates list of "latest" artifacts based on {@link #versions(String, Source, Predicate)} query result
* Contains only artifacts that have updates.
*/
default List<Artifact> calculateUpdates(Map<Artifact, List<Version>> versions) {
return versions.entrySet().stream()
Expand All @@ -434,7 +435,22 @@ default List<Artifact> calculateUpdates(Map<Artifact, List<Version>> versions) {
.setVersion(e.getValue().get(e.getValue().size() - 1).toString()))
.collect(Collectors.toList());
}
;

/**
* Calculates list of "latest" artifacts based on {@link #versions(String, Source, Predicate)} query result.
* Contains every artifact, even those that are already "latest".
*/
default List<Artifact> calculateLatest(Map<Artifact, List<Version>> versions) {
return versions.entrySet().stream()
.map(e -> e.getKey()
.setVersion(
e.getValue().isEmpty()
? e.getKey().getVersion()
: e.getValue()
.get(e.getValue().size() - 1)
.toString()))
.collect(Collectors.toList());
}

Result<List<Artifact>> doManagedPlugins(EditSession es, Op op, Source<Artifact> artifacts) throws Exception;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.resolution.ArtifactDescriptorException;
import org.eclipse.aether.resolution.VersionRangeResolutionException;
import org.eclipse.aether.version.InvalidVersionSpecificationException;
Expand Down Expand Up @@ -158,19 +159,51 @@ protected ResolutionRoot pluginAsResolutionRoot(ToolboxCommando toolboxCommando,
}

protected List<ResolutionRoot> allProjectManagedPluginsAsResolutionRoots(ToolboxCommando toolboxCommando) {
return allProjectManagedPluginsAsResolutionRoots(toolboxCommando, mavenProject);
}

protected List<ResolutionRoot> allProjectPluginsAsResolutionRoots(ToolboxCommando toolboxCommando) {
return allProjectPluginsAsResolutionRoots(toolboxCommando, mavenProject);
}

protected List<ResolutionRoot> allProjectManagedPluginsAsResolutionRoots(
ToolboxCommando toolboxCommando, MavenProject mavenProject) {
return pluginResolutionRoots(
projectBuildBaseSelector(),
buildManagedPluginsExtractor(),
definedInModel(mavenProject.getModel()),
pluginToResolutionRoot(toolboxCommando));
pluginToResolutionRoot(toolboxCommando),
mavenProject);
}

protected List<ResolutionRoot> allProjectPluginsAsResolutionRoots(ToolboxCommando toolboxCommando) {
protected List<ResolutionRoot> allProjectPluginsAsResolutionRoots(
ToolboxCommando toolboxCommando, MavenProject mavenProject) {
return pluginResolutionRoots(
projectBuildBaseSelector(),
buildPluginsExtractor(),
definedInModel(mavenProject.getModel()),
pluginToResolutionRoot(toolboxCommando));
pluginToResolutionRoot(toolboxCommando),
mavenProject);
}

protected List<ResolutionRoot> allManagedPluginsAsResolutionRoots(
ToolboxCommando toolboxCommando, MavenProject mavenProject) {
return pluginResolutionRoots(
projectBuildBaseSelector(),
buildManagedPluginsExtractor(),
p -> true,
pluginToResolutionRoot(toolboxCommando),
mavenProject);
}

protected List<ResolutionRoot> allPluginsAsResolutionRoots(
ToolboxCommando toolboxCommando, MavenProject mavenProject) {
return pluginResolutionRoots(
projectBuildBaseSelector(),
buildPluginsExtractor(),
p -> true,
pluginToResolutionRoot(toolboxCommando),
mavenProject);
}

protected List<ResolutionRoot> allProfileManagedPluginsAsResolutionRoots(
Expand All @@ -179,7 +212,8 @@ protected List<ResolutionRoot> allProfileManagedPluginsAsResolutionRoots(
profileBuildBaseSelector(profileId),
buildManagedPluginsExtractor(),
definedInModel(mavenProject.getModel()),
pluginToResolutionRoot(toolboxCommando));
pluginToResolutionRoot(toolboxCommando),
mavenProject);
}

protected List<ResolutionRoot> allProfilePluginsAsResolutionRoots(
Expand All @@ -188,14 +222,16 @@ protected List<ResolutionRoot> allProfilePluginsAsResolutionRoots(
profileBuildBaseSelector(profileId),
buildPluginsExtractor(),
definedInModel(mavenProject.getModel()),
pluginToResolutionRoot(toolboxCommando));
pluginToResolutionRoot(toolboxCommando),
mavenProject);
}

private <T> List<T> pluginResolutionRoots(
Function<Model, BuildBase> selector,
Function<BuildBase, List<Plugin>> extractor,
Predicate<Plugin> predicate,
Function<Plugin, T> transformer) {
Function<Plugin, T> transformer,
MavenProject mavenProject) {
List<T> result = new ArrayList<>();
List<Plugin> plugins = extractor.apply(selector.apply(mavenProject.getModel()));
if (plugins != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2023-2024 Maveniverse Org.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*/
package eu.maveniverse.maven.toolbox.plugin.mp;

import eu.maveniverse.maven.toolbox.plugin.MPPluginMojoSupport;
import eu.maveniverse.maven.toolbox.shared.ArtifactMatcher;
import eu.maveniverse.maven.toolbox.shared.ResolutionRoot;
import eu.maveniverse.maven.toolbox.shared.Result;
import eu.maveniverse.maven.toolbox.shared.ToolboxCommando;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.version.Version;

/**
* Locks available versions of Maven Project used plugins.
*/
@Mojo(name = "lock-plugin-versions", aggregator = true, threadSafe = true)
public class LockPluginVersionsMojo extends MPPluginMojoSupport {
/**
* The plugin matcher spec.
*/
@Parameter(property = "artifactMatcherSpec", defaultValue = "any()")
private String artifactMatcherSpec;

/**
* Artifact version matcher spec string, default is 'noSnapshotsAndPreviews()'.
*/
@Parameter(property = "artifactVersionMatcherSpec", defaultValue = "noSnapshotsAndPreviews()")
private String artifactVersionMatcherSpec;

/**
* Apply results to POM.
*/
@Parameter(property = "applyToPom")
private boolean applyToPom;

@Override
protected Result<Boolean> doExecute() throws Exception {
ToolboxCommando toolboxCommando = getToolboxCommando();
ArtifactMatcher artifactMatcher = toolboxCommando.parseArtifactMatcherSpec(artifactMatcherSpec);

Map<Artifact, List<Version>> allPlugins = new HashMap<>();
for (MavenProject project : mavenSession.getProjects()) {
Result<Map<Artifact, List<Version>>> managedPlugins = toolboxCommando.versions(
"managed plugins",
() -> allManagedPluginsAsResolutionRoots(toolboxCommando, project).stream()
.map(ResolutionRoot::getArtifact)
.filter(artifactMatcher),
toolboxCommando.parseArtifactVersionMatcherSpec(artifactVersionMatcherSpec));
if (managedPlugins.isSuccess()) {
allPlugins.putAll(managedPlugins.getData().orElseThrow());
} else {
return Result.failure(managedPlugins.getMessage());
}
Result<Map<Artifact, List<Version>>> plugins = toolboxCommando.versions(
"plugins",
() -> allPluginsAsResolutionRoots(toolboxCommando, project).stream()
.map(ResolutionRoot::getArtifact)
.filter(artifactMatcher),
toolboxCommando.parseArtifactVersionMatcherSpec(artifactVersionMatcherSpec));
if (plugins.isSuccess()) {
allPlugins.putAll(plugins.getData().orElseThrow());
} else {
return Result.failure(plugins.getMessage());
}
}

if (applyToPom) {
List<Artifact> pluginsUpdates = toolboxCommando.calculateLatest(allPlugins);
if (!pluginsUpdates.isEmpty()) {
try (ToolboxCommando.EditSession editSession =
toolboxCommando.createEditSession(mavenProject.getFile().toPath())) {
toolboxCommando.doManagedPlugins(editSession, ToolboxCommando.Op.UPSERT, pluginsUpdates::stream);
}
}
}
return Result.success(true);
}
}

0 comments on commit 327c8dd

Please sign in to comment.