This is an automated email from the ASF dual-hosted git repository. olamy pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-build-cache-extension.git
The following commit(s) were added to refs/heads/master by this push: new 8dac5c2 [MBUILDCACHE-115] - fix execution scope seeding outside of forced mode (#217) 8dac5c2 is described below commit 8dac5c28af1e26f038083c57e4f68c299d76e7a2 Author: Sebastian Tiemann <se...@mailbox.org> AuthorDate: Wed Jun 4 12:52:45 2025 +0200 [MBUILDCACHE-115] - fix execution scope seeding outside of forced mode (#217) * [MBUILDCACHE-115] - fix execution scope seeding outside of forced mode - added the provided reproduction project as IT - Remove protobuf-plugin config parts from IT that are not maven4 compatible. --- .../BuildCacheMojosExecutionStrategy.java | 146 ++++++++++----------- .../apache/maven/buildcache/its/Issue115Test.java | 57 ++++++++ .../projects/mbuildcache-115/.mvn/extensions.xml | 25 ++++ src/test/projects/mbuildcache-115/pom.xml | 82 ++++++++++++ .../mbuildcache-115/src/main/protobuf/test.proto | 8 ++ 5 files changed, 244 insertions(+), 74 deletions(-) diff --git a/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java b/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java index 424ca28..a63eccd 100644 --- a/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java +++ b/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java @@ -220,90 +220,88 @@ private CacheRestorationStatus restoreProject( MojoExecutionRunner mojoExecutionRunner, CacheConfig cacheConfig) throws LifecycleExecutionException, MojoExecutionException { - mojoExecutionScope.enter(); - try { - final Build build = cacheResult.getBuildInfo(); - final MavenProject project = cacheResult.getContext().getProject(); - final MavenSession session = cacheResult.getContext().getSession(); - mojoExecutionScope.seed(MavenProject.class, project); - mojoExecutionScope.seed(MavenSession.class, session); - final List<MojoExecution> cachedSegment = - lifecyclePhasesHelper.getCachedSegment(project, mojoExecutions, build); - - // Verify cache consistency for cached mojos - LOGGER.debug("Verify consistency on cached mojos"); - Set<MojoExecution> forcedExecutionMojos = new HashSet<>(); - for (MojoExecution cacheCandidate : cachedSegment) { - if (cacheController.isForcedExecution(project, cacheCandidate)) { - forcedExecutionMojos.add(cacheCandidate); - } else { - if (!verifyCacheConsistency( - cacheCandidate, build, project, session, mojoExecutionRunner, cacheConfig)) { - LOGGER.info("A cached mojo is not consistent, continuing with non cached build"); - return CacheRestorationStatus.FAILURE; - } + + final Build build = cacheResult.getBuildInfo(); + final MavenProject project = cacheResult.getContext().getProject(); + final MavenSession session = cacheResult.getContext().getSession(); + final List<MojoExecution> cachedSegment = + lifecyclePhasesHelper.getCachedSegment(project, mojoExecutions, build); + + // Verify cache consistency for cached mojos + LOGGER.debug("Verify consistency on cached mojos"); + Set<MojoExecution> forcedExecutionMojos = new HashSet<>(); + for (MojoExecution cacheCandidate : cachedSegment) { + if (cacheController.isForcedExecution(project, cacheCandidate)) { + forcedExecutionMojos.add(cacheCandidate); + } else { + if (!verifyCacheConsistency( + cacheCandidate, build, project, session, mojoExecutionRunner, cacheConfig)) { + LOGGER.info("A cached mojo is not consistent, continuing with non cached build"); + return CacheRestorationStatus.FAILURE; } } + } - // Restore project artifacts - ArtifactRestorationReport restorationReport = cacheController.restoreProjectArtifacts(cacheResult); - if (!restorationReport.isSuccess()) { - LOGGER.info("Cannot restore project artifacts, continuing with non cached build"); - return restorationReport.isRestoredFilesInProjectDirectory() - ? CacheRestorationStatus.FAILURE_NEEDS_CLEAN - : CacheRestorationStatus.FAILURE; - } + // Restore project artifacts + ArtifactRestorationReport restorationReport = cacheController.restoreProjectArtifacts(cacheResult); + if (!restorationReport.isSuccess()) { + LOGGER.info("Cannot restore project artifacts, continuing with non cached build"); + return restorationReport.isRestoredFilesInProjectDirectory() + ? CacheRestorationStatus.FAILURE_NEEDS_CLEAN + : CacheRestorationStatus.FAILURE; + } - // Execute mandatory mojos (forced by configuration) - LOGGER.debug("Execute mandatory mojos in the cache segment"); - for (MojoExecution cacheCandidate : cachedSegment) { - if (forcedExecutionMojos.contains(cacheCandidate)) { - LOGGER.info( - "Mojo execution is forced by project property: {}", - cacheCandidate.getMojoDescriptor().getFullGoalName()); + // Execute mandatory mojos (forced by configuration) + LOGGER.debug("Execute mandatory mojos in the cache segment"); + for (MojoExecution cacheCandidate : cachedSegment) { + if (forcedExecutionMojos.contains(cacheCandidate)) { + LOGGER.info( + "Mojo execution is forced by project property: {}", + cacheCandidate.getMojoDescriptor().getFullGoalName()); + // need maven 4 as minumum + // mojoExecutionScope.seed( + // org.apache.maven.api.plugin.Log.class, + // new DefaultLog(LoggerFactory.getLogger( + // cacheCandidate.getMojoDescriptor().getFullGoalName()))); + // mojoExecutionScope.seed(Project.class, ((DefaultSession) + // session.getSession()).getProject(project)); + // mojoExecutionScope.seed( + // org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(cacheCandidate)); + mojoExecutionRunner.run(cacheCandidate); + } else { + LOGGER.info( + "Skipping plugin execution (cached): {}", + cacheCandidate.getMojoDescriptor().getFullGoalName()); + // Need to populate cached candidate executions for the build cache save result + Mojo mojo = null; + mojoExecutionScope.enter(); + try { + mojoExecutionScope.seed(MavenProject.class, project); mojoExecutionScope.seed(MojoExecution.class, cacheCandidate); - // need maven 4 as minumum - // mojoExecutionScope.seed( - // org.apache.maven.api.plugin.Log.class, - // new DefaultLog(LoggerFactory.getLogger( - // cacheCandidate.getMojoDescriptor().getFullGoalName()))); - // mojoExecutionScope.seed(Project.class, ((DefaultSession) - // session.getSession()).getProject(project)); - // mojoExecutionScope.seed( - // org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution(cacheCandidate)); - mojoExecutionRunner.run(cacheCandidate); - } else { - LOGGER.info( - "Skipping plugin execution (cached): {}", - cacheCandidate.getMojoDescriptor().getFullGoalName()); - // Need to populate cached candidate executions for the build cache save result - Mojo mojo = null; - try { - mojo = mavenPluginManager.getConfiguredMojo(Mojo.class, session, cacheCandidate); - MojoExecutionEvent mojoExecutionEvent = - new MojoExecutionEvent(session, project, cacheCandidate, mojo); - mojoListener.beforeMojoExecution(mojoExecutionEvent); - } catch (PluginConfigurationException | PluginContainerException e) { - throw new RuntimeException(e); - } finally { - if (mojo != null) { - mavenPluginManager.releaseMojo(mojo, cacheCandidate); - } + + mojo = mavenPluginManager.getConfiguredMojo(Mojo.class, session, cacheCandidate); + MojoExecutionEvent mojoExecutionEvent = + new MojoExecutionEvent(session, project, cacheCandidate, mojo); + mojoListener.beforeMojoExecution(mojoExecutionEvent); + } catch (PluginConfigurationException | PluginContainerException e) { + throw new RuntimeException(e); + } finally { + mojoExecutionScope.exit(); + if (mojo != null) { + mavenPluginManager.releaseMojo(mojo, cacheCandidate); } } } + } - // Execute mojos after the cache segment - LOGGER.debug("Execute mojos post cache segment"); - List<MojoExecution> postCachedSegment = - lifecyclePhasesHelper.getPostCachedSegment(project, mojoExecutions, build); - for (MojoExecution mojoExecution : postCachedSegment) { - mojoExecutionRunner.run(mojoExecution); - } - return CacheRestorationStatus.SUCCESS; - } finally { - mojoExecutionScope.exit(); + // Execute mojos after the cache segment + LOGGER.debug("Execute mojos post cache segment"); + List<MojoExecution> postCachedSegment = + lifecyclePhasesHelper.getPostCachedSegment(project, mojoExecutions, build); + for (MojoExecution mojoExecution : postCachedSegment) { + mojoExecutionRunner.run(mojoExecution); } + return CacheRestorationStatus.SUCCESS; } private boolean verifyCacheConsistency( diff --git a/src/test/java/org/apache/maven/buildcache/its/Issue115Test.java b/src/test/java/org/apache/maven/buildcache/its/Issue115Test.java new file mode 100644 index 0000000..1de8319 --- /dev/null +++ b/src/test/java/org/apache/maven/buildcache/its/Issue115Test.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 + * + * http://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.apache.maven.buildcache.its; + +import java.util.List; + +import org.apache.maven.buildcache.its.junit.IntegrationTest; +import org.apache.maven.it.VerificationException; +import org.apache.maven.it.Verifier; +import org.junit.jupiter.api.Test; + +@IntegrationTest("src/test/projects/mbuildcache-115") +public class Issue115Test { + + private static final String PROJECT_NAME = "org.apache.maven.caching.test:mbuildcache-115"; + private static final String RESTORED_MESSAGE = "Found cached build, restoring " + PROJECT_NAME + " from cache"; + + @Test + void buildShouldRestoreProjectWithoutError(Verifier verifier) throws VerificationException { + verifier.setAutoclean(false); + verifier.setLogFileName("../log-1.txt"); + verifier.executeGoal("package"); + verifier.verifyErrorFreeLog(); + // verify protobuf-plugin is present and has run + verifier.verifyFilePresent("target/generated-sources/protobuf/Test.java"); + verifyTextNotInLog(verifier, RESTORED_MESSAGE); + + verifier.executeGoal("package"); + verifier.verifyTextInLog(RESTORED_MESSAGE); + verifier.verifyErrorFreeLog(); + } + + private static void verifyTextNotInLog(Verifier verifier, String text) throws VerificationException { + List<String> lines = verifier.loadFile(verifier.getBasedir(), verifier.getLogFileName(), false); + for (String line : lines) { + if (Verifier.stripAnsi(line).contains(text)) { + throw new VerificationException("Text found in log: " + text); + } + } + } +} diff --git a/src/test/projects/mbuildcache-115/.mvn/extensions.xml b/src/test/projects/mbuildcache-115/.mvn/extensions.xml new file mode 100644 index 0000000..8df78f8 --- /dev/null +++ b/src/test/projects/mbuildcache-115/.mvn/extensions.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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 + + http://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. + +--> +<extensions> + <extension> + <groupId>org.apache.maven.extensions</groupId> + <artifactId>maven-build-cache-extension</artifactId> + <version>${projectVersion}</version> + </extension> +</extensions> diff --git a/src/test/projects/mbuildcache-115/pom.xml b/src/test/projects/mbuildcache-115/pom.xml new file mode 100644 index 0000000..18371f4 --- /dev/null +++ b/src/test/projects/mbuildcache-115/pom.xml @@ -0,0 +1,82 @@ +<!-- + + 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 + + http://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. + +--> +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.maven.caching.test</groupId> + <artifactId>mbuildcache-115</artifactId> + <version>0.0.1-SNAPSHOT</version> + <packaging>jar</packaging> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + </properties> + + <build> + <plugins> + <plugin> + <groupId>io.github.ascopes</groupId> + <artifactId>protobuf-maven-plugin</artifactId> + <version>2.7.0</version> + + <configuration> + <protocVersion>3.24.0</protocVersion> + + <binaryMavenPlugins> + <binaryMavenPlugin> + <groupId>io.grpc</groupId> + <artifactId>protoc-gen-grpc-java</artifactId> + <version>1.58.0</version> + </binaryMavenPlugin> + </binaryMavenPlugins> + </configuration> + + <executions> + <execution> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>versions-maven-plugin</artifactId> + <version>2.16.0</version> + <configuration> + <generateBackupPoms>false</generateBackupPoms> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + + <dependencies> + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + <version>4.30.2</version> + </dependency> + </dependencies> + +</project> diff --git a/src/test/projects/mbuildcache-115/src/main/protobuf/test.proto b/src/test/projects/mbuildcache-115/src/main/protobuf/test.proto new file mode 100644 index 0000000..4327335 --- /dev/null +++ b/src/test/projects/mbuildcache-115/src/main/protobuf/test.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +message Person { + string firstName = 1; + string lastName = 2; + int32 age = 3; + float heightInMeters = 4; +} \ No newline at end of file