From f7a69cf6a96c3ffb659966260aea412f7bdc4cf2 Mon Sep 17 00:00:00 2001 From: Corey Puffalt Date: Mon, 25 May 2026 11:31:36 -0600 Subject: [PATCH] Issue #492 restore compile-only reactor module so downstream resolution works When a cached build did not reach the package phase the cache entry's primary artifact is the target/classes directory rather than a jar. restoreProjectArtifacts only set project.getArtifact() to the restored artifact when the cached file was a regular jar, leaving directory artifacts unbound. In a multi-module reactor that meant downstream modules could not find the upstream's classes on the second `mvn clean compile` invocation and fell through to remote repositories with "Could not find artifact ...:jar:...-SNAPSHOT". For directory artifacts, set the file on the existing project artifact instead of replacing it with RestoredArtifact. RestoredArtifact.getFile always re-routes through its restoreToDiskConsumer, which would later break package-phase plugins (e.g. jar:jar) that update the artifact's file via setFile. Adds CompileOnlyReactorRestoreTest covering this case. --- .../maven/buildcache/CacheControllerImpl.java | 7 +++ .../its/CompileOnlyReactorRestoreTest.java | 57 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/test/java/org/apache/maven/buildcache/its/CompileOnlyReactorRestoreTest.java diff --git a/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java b/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java index 08dabc0b..53625170 100644 --- a/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java +++ b/src/main/java/org/apache/maven/buildcache/CacheControllerImpl.java @@ -481,6 +481,13 @@ public ArtifactRestorationReport restoreProjectArtifacts(CacheResult cacheResult if (!project.hasLifecyclePhase("package")) { project.addLifecyclePhase("package"); } + } else if (restoredProjectArtifact != null) { + // Directory artifact (target/classes from compile-only build). + // Point the existing project artifact at the restored directory so reactor dependency + // resolution can locate this module's compiled output. Don't replace the artifact: + // RestoredArtifact.getFile() always re-routes through restoreToDiskConsumer, which would + // break later phases (e.g. jar:jar) that update the file via setFile(). + project.getArtifact().setFile(restoredProjectArtifact.getFile()); } restoredAttachedArtifacts.forEach(project::addAttachedArtifact); restorationReport.setSuccess(true); diff --git a/src/test/java/org/apache/maven/buildcache/its/CompileOnlyReactorRestoreTest.java b/src/test/java/org/apache/maven/buildcache/its/CompileOnlyReactorRestoreTest.java new file mode 100644 index 00000000..c5abf802 --- /dev/null +++ b/src/test/java/org/apache/maven/buildcache/its/CompileOnlyReactorRestoreTest.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.Arrays; + +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; + +/** + * Reproducer for Issue #492: + * {@code clean compile} twice in a multi-module reactor fails to resolve the upstream module. + * + *

On the second run the cache extension restores the upstream module's compiled + * output but, because no jar was produced in the original cached build, downstream + * dependency resolution falls through to remote repositories with + * {@code Could not find artifact ...:jar:...-SNAPSHOT}. + */ +@IntegrationTest("src/test/projects/issue-393-compile-restore") +class CompileOnlyReactorRestoreTest { + + @Test + void cleanCompileTwiceResolvesUpstreamFromReactorCache(Verifier verifier) throws VerificationException { + verifier.setAutoclean(false); + + verifier.setLogFileName("../log-compile-1.txt"); + verifier.executeGoals(Arrays.asList("clean", "compile")); + verifier.verifyErrorFreeLog(); + + verifier.setLogFileName("../log-compile-2.txt"); + verifier.executeGoals(Arrays.asList("clean", "compile")); + verifier.verifyErrorFreeLog(); + verifier.verifyTextInLog( + "Found cached build, restoring org.apache.maven.caching.test.jpms:issue-393-app from cache"); + verifier.verifyTextInLog("Skipping plugin execution (cached): compiler:compile"); + verifier.verifyFilePresent("app/target/classes/module-info.class"); + verifier.verifyFilePresent("consumer/target/classes/module-info.class"); + } +}