You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2023/06/01 06:43:16 UTC
[maven-build-cache-extension] branch master updated: [MBUILDCACHE-25] Fixes N+1 cache processings for forked executions (#34)
This is an automated email from the ASF dual-hosted git repository.
gnodet 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 481fec0 [MBUILDCACHE-25] Fixes N+1 cache processings for forked executions (#34)
481fec0 is described below
commit 481fec0bd313d2c44a11de0d450507658df43242
Author: Alex Ashitkin <as...@gmail.com>
AuthorDate: Thu Jun 1 02:43:10 2023 -0400
[MBUILDCACHE-25] Fixes N+1 cache processings for forked executions (#34)
Co-authored-by: aashitki <al...@db.com>
Co-authored-by: Guillaume Nodet <gn...@gmail.com>
---
pom.xml | 17 ++++
.../BuildCacheMojosExecutionStrategy.java | 7 +-
.../maven/buildcache/LifecyclePhasesHelper.java | 4 +
.../its/ForkedExecutionCoreExtensionTest.java | 24 ++++-
.../maven/buildcache/its/ForkedExecutionsTest.java | 104 +++++++++++++++++++++
.../.mvn/extensions.xml | 25 +++++
.../.mvn/maven-build-cache-config.xml | 28 ++++++
.../pom.xml | 26 +-----
.../maven/buildcache/ForkedExecutionClass.java | 24 +++++
.../forked-executions-core-extension/pom.xml | 25 -----
10 files changed, 229 insertions(+), 55 deletions(-)
diff --git a/pom.xml b/pom.xml
index 2c201cd..5fe6854 100644
--- a/pom.xml
+++ b/pom.xml
@@ -81,6 +81,7 @@ under the License.
<jxpathVersion>1.3</jxpathVersion>
<resolverVersion>1.9.7</resolverVersion>
<slf4jVersion>1.7.32</slf4jVersion>
+ <wiremockVersion>2.35.0</wiremockVersion>
<xmlunitVersion>2.6.4</xmlunitVersion>
<maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile>
<maven.site.path>extensions-archives/${project.artifactId}-LATEST</maven.site.path>
@@ -233,6 +234,22 @@ under the License.
<version>${mockitoVersion}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock-jre8</artifactId>
+ <version>${wiremockVersion}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-alpn-java-client</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-alpn-java-server</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
</dependencies>
<build>
diff --git a/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java b/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java
index 0505b17..c9af6c7 100644
--- a/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java
+++ b/src/main/java/org/apache/maven/buildcache/BuildCacheMojosExecutionStrategy.java
@@ -100,7 +100,10 @@ public class BuildCacheMojosExecutionStrategy implements MojosExecutionStrategy
CacheResult result = CacheResult.empty();
boolean skipCache = cacheConfig.isSkipCache() || MavenProjectInput.isSkipCache(project);
boolean cacheIsDisabled = MavenProjectInput.isCacheDisabled(project);
- if (source == Source.LIFECYCLE) {
+ // Forked execution should be thought as a part of originating mojo internal implementation
+ // If forkedExecution is detected, it means that originating mojo is not cached so forks should rerun too
+ boolean forkedExecution = lifecyclePhasesHelper.isForkedProject(project);
+ if (source == Source.LIFECYCLE && !forkedExecution) {
List<MojoExecution> cleanPhase = lifecyclePhasesHelper.getCleanSegment(project, mojoExecutions);
for (MojoExecution mojoExecution : cleanPhase) {
mojoExecutionRunner.run(mojoExecution);
@@ -134,7 +137,7 @@ public class BuildCacheMojosExecutionStrategy implements MojosExecutionStrategy
cacheController.save(result, mojoExecutions, executionEvents);
}
- if (cacheConfig.isFailFast() && !result.isSuccess() && !skipCache) {
+ if (cacheConfig.isFailFast() && !result.isSuccess() && !skipCache && !forkedExecution) {
throw new LifecycleExecutionException(
"Failed to restore project[" + getVersionlessProjectKey(project) + "] from cache, failing build.",
project);
diff --git a/src/main/java/org/apache/maven/buildcache/LifecyclePhasesHelper.java b/src/main/java/org/apache/maven/buildcache/LifecyclePhasesHelper.java
index 33d8a3e..c37facc 100644
--- a/src/main/java/org/apache/maven/buildcache/LifecyclePhasesHelper.java
+++ b/src/main/java/org/apache/maven/buildcache/LifecyclePhasesHelper.java
@@ -213,4 +213,8 @@ public class LifecyclePhasesHelper extends AbstractExecutionListener {
}
return list;
}
+
+ public boolean isForkedProject(MavenProject project) {
+ return forkedProjectToOrigin.containsKey(project);
+ }
}
diff --git a/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionCoreExtensionTest.java b/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionCoreExtensionTest.java
index 6972e84..d111834 100644
--- a/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionCoreExtensionTest.java
+++ b/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionCoreExtensionTest.java
@@ -32,6 +32,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.apache.maven.buildcache.xml.CacheConfigImpl.CACHE_LOCATION_PROPERTY_NAME;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/**
* Runs project which contains plugin with forked execution - pmd
@@ -63,16 +64,33 @@ public class ForkedExecutionCoreExtensionTest {
Lists.newArrayList("-D" + CACHE_LOCATION_PROPERTY_NAME + "=" + tempDirectory.toAbsolutePath()));
verifier.executeGoal("verify");
verifier.verifyTextInLog("Started forked project");
+ // forked execution actually runs
verifier.verifyTextInLog(
- "Mojo execution pmd:pmd:emptyLifecyclePhase:maven-pmd-plugin:org.apache.maven.plugins is forked,"
- + " returning phase verify from originating mojo "
- + "default:check:verify:maven-pmd-plugin:org.apache.maven.plugins");
+ "[DEBUG] Starting mojo execution: pmd:pmd:emptyLifecyclePhase:maven-pmd-plugin:org.apache.maven.plugins");
+ // checking that forked execution doesn't hook into lifecycle
+ assertThrows(
+ VerificationException.class,
+ () -> verifier.verifyTextInLog(
+ "Mojo execution pmd:pmd:emptyLifecyclePhase:maven-pmd-plugin:org.apache.maven.plugins is forked,"
+ + " returning phase verify from originating mojo "
+ + "default:check:verify:maven-pmd-plugin:org.apache.maven.plugins"));
verifier.verifyTextInLog("[INFO] BUILD SUCCESS");
verifier.setLogFileName("../log-2.txt");
verifier.executeGoal("verify");
verifier.verifyErrorFreeLog();
verifier.verifyTextInLog("Found cached build, restoring " + PROJECT_NAME + " from cache");
+ // checking that fork originating mojo pmd:check is cached
+ verifier.verifyTextInLog("[INFO] Skipping plugin execution (cached): pmd:check");
+ // and because of that forked execution pmd:pmd didn't run
+ assertThrows(
+ VerificationException.class,
+ () -> verifier.verifyTextInLog(
+ "[DEBUG] Starting mojo execution: pmd:pmd:emptyLifecyclePhase:maven-pmd-plugin:org.apache.maven.plugins"));
+ // and didn't appear in cache lifecycle
+ assertThrows(
+ VerificationException.class,
+ () -> verifier.verifyTextInLog("[INFO] Skipping plugin execution (cached): pmd:pmd"));
verifier.verifyTextInLog("[INFO] BUILD SUCCESS");
}
}
diff --git a/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionsTest.java b/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionsTest.java
new file mode 100644
index 0000000..627dd8a
--- /dev/null
+++ b/src/test/java/org/apache/maven/buildcache/its/ForkedExecutionsTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import com.github.tomakehurst.wiremock.common.ConsoleNotifier;
+import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
+import com.github.tomakehurst.wiremock.matching.UrlPathPattern;
+import com.google.common.collect.Lists;
+import org.apache.commons.io.FileUtils;
+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.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.exactly;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.notFound;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.put;
+import static com.github.tomakehurst.wiremock.client.WireMock.putRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+
+/**
+ * Verifies MBUILDCACHE-25 - build cache calculated and saved exactly once in presence of forked executions
+ */
+@IntegrationTest("src/test/projects/forked-executions-core-extension-remote")
+public class ForkedExecutionsTest {
+
+ private static final String PROJECT_NAME = "org.apache.maven.caching.test.simple:forked-executions-core-extension";
+
+ @RegisterExtension
+ static WireMockExtension wm = WireMockExtension.newInstance()
+ .options(wireMockConfig().dynamicPort().notifier(new ConsoleNotifier(true)))
+ .build();
+
+ private Path tempDirectory;
+
+ @BeforeEach
+ void setUp() throws IOException {
+ tempDirectory = Files.createTempDirectory("build-cache-test-");
+ }
+
+ @AfterEach
+ void tearDown() throws IOException {
+ FileUtils.deleteDirectory(tempDirectory.toFile());
+ }
+
+ @Test
+ void testForkedExecution(Verifier verifier) throws VerificationException {
+
+ UrlPathPattern buildInfoPath = urlPathMatching(".*/buildinfo.xml");
+ wm.stubFor(get(buildInfoPath).willReturn(notFound()));
+ wm.stubFor(put(buildInfoPath).willReturn(ok()));
+
+ UrlPathPattern jarPath = urlPathMatching(".*/forked-executions-core-extension-remote.jar");
+ wm.stubFor(put(jarPath).willReturn(ok()));
+
+ UrlPathPattern cacheReportPath = urlPathMatching(".*/build-cache-report.xml");
+ wm.stubFor(put(cacheReportPath).willReturn(ok()));
+
+ verifier.setAutoclean(false);
+
+ verifier.setLogFileName("../log-1.txt");
+ verifier.setMavenDebug(true);
+ verifier.setCliOptions(Lists.newArrayList(
+ "-Dmaven.build.cache.location=" + tempDirectory.toAbsolutePath(),
+ "-Dmaven.build.cache.remote.url=http:////localhost:"
+ + wm.getRuntimeInfo().getHttpPort(),
+ "-Dmaven.build.cache.remote.save.enabled=true"));
+ verifier.executeGoal("verify");
+ verifier.verifyTextInLog("Started forked project");
+ verifier.verifyTextInLog("BUILD SUCCESS");
+
+ wm.verify(exactly(1), getRequestedFor(buildInfoPath));
+ wm.verify(exactly(1), putRequestedFor(buildInfoPath));
+ wm.verify(exactly(1), putRequestedFor(jarPath));
+ wm.verify(exactly(1), putRequestedFor(cacheReportPath));
+ }
+}
diff --git a/src/test/projects/forked-executions-core-extension-remote/.mvn/extensions.xml b/src/test/projects/forked-executions-core-extension-remote/.mvn/extensions.xml
new file mode 100644
index 0000000..8df78f8
--- /dev/null
+++ b/src/test/projects/forked-executions-core-extension-remote/.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/forked-executions-core-extension-remote/.mvn/maven-build-cache-config.xml b/src/test/projects/forked-executions-core-extension-remote/.mvn/maven-build-cache-config.xml
new file mode 100644
index 0000000..573de40
--- /dev/null
+++ b/src/test/projects/forked-executions-core-extension-remote/.mvn/maven-build-cache-config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+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.
+-->
+
+<cache xmlns="http://maven.apache.org/BUILD-CACHE-CONFIG/1.0.0">
+ <configuration>
+ <remote>
+ <url>http://to-be-overridden-on-cli-and-point-to-wiremock</url>
+ </remote>
+ </configuration>
+</cache>
diff --git a/src/test/projects/forked-executions-core-extension/pom.xml b/src/test/projects/forked-executions-core-extension-remote/pom.xml
similarity index 59%
copy from src/test/projects/forked-executions-core-extension/pom.xml
copy to src/test/projects/forked-executions-core-extension-remote/pom.xml
index 5069341..ebc9a69 100644
--- a/src/test/projects/forked-executions-core-extension/pom.xml
+++ b/src/test/projects/forked-executions-core-extension-remote/pom.xml
@@ -20,7 +20,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.maven.caching.test.simple</groupId>
- <artifactId>forked-executions-core-extension</artifactId>
+ <artifactId>forked-executions-core-extension-remote</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
@@ -51,31 +51,7 @@
</dependency>
</dependencies>
</plugin>
-<!-- [WARNING] The POM for org.apache.maven.wagon:wagon-http:jar:1.0-beta-6 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for /Users/aashitki/.m2/repository/org/apache/maven/wagon/wagon-http/1.0-beta-6/wagon-http-1.0-beta-6.pom-->
-<!-- <plugin>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </plugin>-->
-<!-- <plugin>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http-shared</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </plugin>-->
</plugins>
</build>
-<!-- <dependencies>-->
-<!-- <dependency>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </dependency>-->
-<!-- <dependency>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http-shared</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </dependency>-->
-<!-- </dependencies>-->
-
</project>
\ No newline at end of file
diff --git a/src/test/projects/forked-executions-core-extension-remote/src/main/java/org/apache/maven/buildcache/ForkedExecutionClass.java b/src/test/projects/forked-executions-core-extension-remote/src/main/java/org/apache/maven/buildcache/ForkedExecutionClass.java
new file mode 100644
index 0000000..920b9f9
--- /dev/null
+++ b/src/test/projects/forked-executions-core-extension-remote/src/main/java/org/apache/maven/buildcache/ForkedExecutionClass.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+class ForkedExecutionClass
+{
+
+}
\ No newline at end of file
diff --git a/src/test/projects/forked-executions-core-extension/pom.xml b/src/test/projects/forked-executions-core-extension/pom.xml
index 5069341..0effb24 100644
--- a/src/test/projects/forked-executions-core-extension/pom.xml
+++ b/src/test/projects/forked-executions-core-extension/pom.xml
@@ -51,31 +51,6 @@
</dependency>
</dependencies>
</plugin>
-<!-- [WARNING] The POM for org.apache.maven.wagon:wagon-http:jar:1.0-beta-6 is invalid, transitive dependencies (if any) will not be available: 1 problem was encountered while building the effective model for /Users/aashitki/.m2/repository/org/apache/maven/wagon/wagon-http/1.0-beta-6/wagon-http-1.0-beta-6.pom-->
-<!-- <plugin>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </plugin>-->
-<!-- <plugin>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http-shared</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </plugin>-->
</plugins>
</build>
-
-<!-- <dependencies>-->
-<!-- <dependency>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </dependency>-->
-<!-- <dependency>-->
-<!-- <groupId>org.apache.maven.wagon</groupId>-->
-<!-- <artifactId>wagon-http-shared</artifactId>-->
-<!-- <version>3.5.2</version>-->
-<!-- </dependency>-->
-<!-- </dependencies>-->
-
</project>
\ No newline at end of file