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.git

commit 3660924fc22efa13a006eb6977be9010063cdc61
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Oct 8 06:36:19 2025 +0000

    Add phase upgrade support for Maven 4.1.0 model upgrades
    
    This commit implements automatic phase name upgrades when upgrading
    Maven projects from model version 4.0.0 to 4.1.0. The deprecated
    Maven 3 phase names are automatically converted to their Maven 4
    equivalents:
    
    - pre-clean → before:clean
    - post-clean → after:clean
    - pre-integration-test → before:integration-test
    - post-integration-test → after:integration-test
    - pre-site → before:site
    - post-site → after:site
    
    The upgrade functionality:
    - Only applies when upgrading to model version 4.1.0 or higher
    - Processes all plugin executions in build/plugins, build/pluginManagement,
      and profile/build/plugins sections
    - Preserves non-deprecated phase names unchanged
    - Includes comprehensive test coverage for all scenarios
    
    This enhancement ensures that Maven projects upgrading to 4.1.0 will
    automatically have their deprecated phase references updated to use
    the new Maven 4 phase naming convention.
---
 .../invoker/mvnup/goals/ModelUpgradeStrategy.java  | 120 ++++++
 .../invoker/mvnup/goals/UpgradeConstants.java      |   2 +
 .../mvnup/goals/ModelUpgradeStrategyTest.java      | 461 +++++++++++++++++++++
 3 files changed, 583 insertions(+)

diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java
index 3a1392c43e..d6e3d8f331 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategy.java
@@ -19,6 +19,7 @@
 package org.apache.maven.cling.invoker.mvnup.goals;
 
 import java.nio.file.Path;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -44,8 +45,15 @@
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlAttributes.SCHEMA_LOCATION;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlAttributes.XSI_NAMESPACE_PREFIX;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlAttributes.XSI_NAMESPACE_URI;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.BUILD;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.EXECUTION;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.EXECUTIONS;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.MODULE;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.MODULES;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PHASE;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PLUGIN;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PLUGINS;
+import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PLUGIN_MANAGEMENT;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PROFILE;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.PROFILES;
 import static 
org.apache.maven.cling.invoker.mvnup.goals.UpgradeConstants.XmlElements.SUBPROJECT;
@@ -143,6 +151,7 @@ private void performModelUpgrade(
         // Convert modules to subprojects (for 4.1.0 and higher)
         if (ModelVersionUtils.isVersionGreaterOrEqual(targetModelVersion, 
MODEL_VERSION_4_1_0)) {
             convertModulesToSubprojects(pomDocument, context);
+            upgradeDeprecatedPhases(pomDocument, context);
         }
 
         // Update modelVersion to target version (perhaps removed later during 
inference step)
@@ -256,4 +265,115 @@ private String getNamespaceForModelVersion(String 
modelVersion) {
             return MAVEN_4_0_0_NAMESPACE;
         }
     }
+
+    /**
+     * Upgrades deprecated Maven 3 phase names to Maven 4 equivalents.
+     * This replaces pre-/post- phases with before:/after: phases.
+     */
+    private void upgradeDeprecatedPhases(Document pomDocument, UpgradeContext 
context) {
+        // Create mapping of deprecated phases to their Maven 4 equivalents
+        Map<String, String> phaseUpgrades = createPhaseUpgradeMap();
+
+        Element root = pomDocument.getRootElement();
+        Namespace namespace = root.getNamespace();
+
+        int totalUpgrades = 0;
+
+        // Upgrade phases in main build section
+        totalUpgrades += upgradePhaseElements(root.getChild(BUILD, namespace), 
namespace, phaseUpgrades, context);
+
+        // Upgrade phases in profiles
+        Element profilesElement = root.getChild(PROFILES, namespace);
+        if (profilesElement != null) {
+            List<Element> profileElements = 
profilesElement.getChildren(PROFILE, namespace);
+            for (Element profileElement : profileElements) {
+                Element profileBuildElement = profileElement.getChild(BUILD, 
namespace);
+                totalUpgrades += upgradePhaseElements(profileBuildElement, 
namespace, phaseUpgrades, context);
+            }
+        }
+
+        if (totalUpgrades > 0) {
+            context.detail("Upgraded " + totalUpgrades + " deprecated phase 
name(s) to Maven 4 equivalents");
+        }
+    }
+
+    /**
+     * Creates the mapping of deprecated phase names to their Maven 4 
equivalents.
+     */
+    private Map<String, String> createPhaseUpgradeMap() {
+        Map<String, String> phaseUpgrades = new HashMap<>();
+
+        // Clean lifecycle aliases
+        phaseUpgrades.put("pre-clean", "before:clean");
+        phaseUpgrades.put("post-clean", "after:clean");
+
+        // Default lifecycle aliases
+        phaseUpgrades.put("pre-integration-test", "before:integration-test");
+        phaseUpgrades.put("post-integration-test", "after:integration-test");
+
+        // Site lifecycle aliases
+        phaseUpgrades.put("pre-site", "before:site");
+        phaseUpgrades.put("post-site", "after:site");
+
+        return phaseUpgrades;
+    }
+
+    /**
+     * Upgrades phase elements within a build section.
+     */
+    private int upgradePhaseElements(
+            Element buildElement, Namespace namespace, Map<String, String> 
phaseUpgrades, UpgradeContext context) {
+        if (buildElement == null) {
+            return 0;
+        }
+
+        int upgrades = 0;
+
+        // Check plugins section
+        Element pluginsElement = buildElement.getChild(PLUGINS, namespace);
+        if (pluginsElement != null) {
+            upgrades += upgradePhaseElementsInPlugins(pluginsElement, 
namespace, phaseUpgrades, context);
+        }
+
+        // Check pluginManagement section
+        Element pluginManagementElement = 
buildElement.getChild(PLUGIN_MANAGEMENT, namespace);
+        if (pluginManagementElement != null) {
+            Element managedPluginsElement = 
pluginManagementElement.getChild(PLUGINS, namespace);
+            if (managedPluginsElement != null) {
+                upgrades += 
upgradePhaseElementsInPlugins(managedPluginsElement, namespace, phaseUpgrades, 
context);
+            }
+        }
+
+        return upgrades;
+    }
+
+    /**
+     * Upgrades phase elements within a plugins section.
+     */
+    private int upgradePhaseElementsInPlugins(
+            Element pluginsElement, Namespace namespace, Map<String, String> 
phaseUpgrades, UpgradeContext context) {
+        int upgrades = 0;
+
+        List<Element> pluginElements = pluginsElement.getChildren(PLUGIN, 
namespace);
+        for (Element pluginElement : pluginElements) {
+            Element executionsElement = pluginElement.getChild(EXECUTIONS, 
namespace);
+            if (executionsElement != null) {
+                List<Element> executionElements = 
executionsElement.getChildren(EXECUTION, namespace);
+                for (Element executionElement : executionElements) {
+                    Element phaseElement = executionElement.getChild(PHASE, 
namespace);
+                    if (phaseElement != null) {
+                        String currentPhase = phaseElement.getTextTrim();
+                        String newPhase = phaseUpgrades.get(currentPhase);
+                        if (newPhase != null) {
+                            phaseElement.setText(newPhase);
+                            context.detail("Upgraded phase: " + currentPhase + 
" → " + newPhase);
+                            upgrades++;
+                        }
+                    }
+                }
+            }
+        }
+
+        return upgrades;
+    }
 }
diff --git 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java
 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java
index 253728c508..f8fd5494bc 100644
--- 
a/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java
+++ 
b/impl/maven-cli/src/main/java/org/apache/maven/cling/invoker/mvnup/goals/UpgradeConstants.java
@@ -77,9 +77,11 @@ public static final class XmlElements {
         public static final String TEST_OUTPUT_DIRECTORY = 
"testOutputDirectory";
         public static final String EXTENSIONS = "extensions";
         public static final String EXECUTIONS = "executions";
+        public static final String EXECUTION = "execution";
         public static final String GOALS = "goals";
         public static final String INHERITED = "inherited";
         public static final String CONFIGURATION = "configuration";
+        public static final String PHASE = "phase";
 
         // Module elements
         public static final String MODULES = "modules";
diff --git 
a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java
 
b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java
index 2a0c3c1719..ab20e4c132 100644
--- 
a/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java
+++ 
b/impl/maven-cli/src/test/java/org/apache/maven/cling/invoker/mvnup/goals/ModelUpgradeStrategyTest.java
@@ -324,6 +324,467 @@ void shouldProvideMeaningfulDescription() {
         }
     }
 
+    @Nested
+    @DisplayName("Phase Upgrades")
+    class PhaseUpgradeTests {
+
+        @Test
+        @DisplayName("should upgrade deprecated phases to Maven 4 equivalents 
in 4.1.0")
+        void shouldUpgradeDeprecatedPhasesIn410() throws Exception {
+            Document document = createDocumentWithDeprecatedPhases();
+            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), 
document);
+
+            // Create context with --model-version=4.1.0 option to trigger 
phase upgrade
+            UpgradeOptions options = mock(UpgradeOptions.class);
+            when(options.modelVersion()).thenReturn(Optional.of("4.1.0"));
+            when(options.all()).thenReturn(Optional.empty());
+            UpgradeContext context = createMockContext(options);
+
+            UpgradeResult result = strategy.apply(context, pomMap);
+
+            assertTrue(result.success(), "Model upgrade should succeed");
+            assertTrue(result.modifiedCount() > 0, "Should have upgraded 
phases");
+
+            // Verify phases were upgraded
+            verifyCleanPluginPhases(document);
+            verifyFailsafePluginPhases(document);
+            verifySitePluginPhases(document);
+            verifyPluginManagementPhases(document);
+            verifyProfilePhases(document);
+        }
+
+        private Document createDocumentWithDeprecatedPhases() throws Exception 
{
+            String pomXml =
+                    """
+                <?xml version="1.0" encoding="UTF-8"?>
+                <project xmlns="http://maven.apache.org/POM/4.0.0";>
+                    <modelVersion>4.0.0</modelVersion>
+                    <groupId>com.example</groupId>
+                    <artifactId>test-project</artifactId>
+                    <version>1.0.0</version>
+                    <build>
+                        <plugins>
+                            <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-clean-plugin</artifactId>
+                                <version>3.2.0</version>
+                                <executions>
+                                    <execution>
+                                        <id>pre-clean-test</id>
+                                        <phase>pre-clean</phase>
+                                        <goals>
+                                            <goal>clean</goal>
+                                        </goals>
+                                    </execution>
+                                    <execution>
+                                        <id>post-clean-test</id>
+                                        <phase>post-clean</phase>
+                                        <goals>
+                                            <goal>clean</goal>
+                                        </goals>
+                                    </execution>
+                                </executions>
+                            </plugin>
+                            <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-failsafe-plugin</artifactId>
+                                <version>3.0.0-M7</version>
+                                <executions>
+                                    <execution>
+                                        <id>pre-integration-test-setup</id>
+                                        <phase>pre-integration-test</phase>
+                                        <goals>
+                                            <goal>integration-test</goal>
+                                        </goals>
+                                    </execution>
+                                    <execution>
+                                        <id>post-integration-test-cleanup</id>
+                                        <phase>post-integration-test</phase>
+                                        <goals>
+                                            <goal>verify</goal>
+                                        </goals>
+                                    </execution>
+                                </executions>
+                            </plugin>
+                            <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-site-plugin</artifactId>
+                                <version>3.12.1</version>
+                                <executions>
+                                    <execution>
+                                        <id>pre-site-setup</id>
+                                        <phase>pre-site</phase>
+                                        <goals>
+                                            <goal>site</goal>
+                                        </goals>
+                                    </execution>
+                                    <execution>
+                                        <id>post-site-cleanup</id>
+                                        <phase>post-site</phase>
+                                        <goals>
+                                            <goal>deploy</goal>
+                                        </goals>
+                                    </execution>
+                                </executions>
+                            </plugin>
+                        </plugins>
+                        <pluginManagement>
+                            <plugins>
+                                <plugin>
+                                    <groupId>org.apache.maven.plugins</groupId>
+                                    
<artifactId>maven-compiler-plugin</artifactId>
+                                    <version>3.11.0</version>
+                                    <executions>
+                                        <execution>
+                                            <id>pre-clean-compile</id>
+                                            <phase>pre-clean</phase>
+                                            <goals>
+                                                <goal>compile</goal>
+                                            </goals>
+                                        </execution>
+                                    </executions>
+                                </plugin>
+                            </plugins>
+                        </pluginManagement>
+                    </build>
+                    <profiles>
+                        <profile>
+                            <id>test-profile</id>
+                            <build>
+                                <plugins>
+                                    <plugin>
+                                        
<groupId>org.apache.maven.plugins</groupId>
+                                        
<artifactId>maven-antrun-plugin</artifactId>
+                                        <version>3.1.0</version>
+                                        <executions>
+                                            <execution>
+                                                
<id>profile-pre-integration-test</id>
+                                                
<phase>pre-integration-test</phase>
+                                                <goals>
+                                                    <goal>run</goal>
+                                                </goals>
+                                            </execution>
+                                        </executions>
+                                    </plugin>
+                                </plugins>
+                            </build>
+                        </profile>
+                    </profiles>
+                </project>
+                """;
+
+            return saxBuilder.build(new StringReader(pomXml));
+        }
+
+        private void verifyCleanPluginPhases(Document document) {
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element build = root.getChild("build", namespace);
+            Element plugins = build.getChild("plugins", namespace);
+
+            Element cleanPlugin = plugins.getChildren("plugin", 
namespace).stream()
+                    .filter(p -> "maven-clean-plugin"
+                            .equals(p.getChild("artifactId", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(cleanPlugin);
+
+            Element cleanExecutions = cleanPlugin.getChild("executions", 
namespace);
+            Element preCleanExecution = 
cleanExecutions.getChildren("execution", namespace).stream()
+                    .filter(e ->
+                            "pre-clean-test".equals(e.getChild("id", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(preCleanExecution);
+            assertEquals(
+                    "before:clean",
+                    preCleanExecution.getChild("phase", namespace).getText());
+
+            Element postCleanExecution = 
cleanExecutions.getChildren("execution", namespace).stream()
+                    .filter(e ->
+                            "post-clean-test".equals(e.getChild("id", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(postCleanExecution);
+            assertEquals(
+                    "after:clean",
+                    postCleanExecution.getChild("phase", namespace).getText());
+        }
+
+        private void verifyFailsafePluginPhases(Document document) {
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element build = root.getChild("build", namespace);
+            Element plugins = build.getChild("plugins", namespace);
+
+            Element failsafePlugin = plugins.getChildren("plugin", 
namespace).stream()
+                    .filter(p -> "maven-failsafe-plugin"
+                            .equals(p.getChild("artifactId", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(failsafePlugin);
+
+            Element failsafeExecutions = failsafePlugin.getChild("executions", 
namespace);
+            Element preIntegrationExecution = 
failsafeExecutions.getChildren("execution", namespace).stream()
+                    .filter(e -> "pre-integration-test-setup"
+                            .equals(e.getChild("id", namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(preIntegrationExecution);
+            assertEquals(
+                    "before:integration-test",
+                    preIntegrationExecution.getChild("phase", 
namespace).getText());
+
+            Element postIntegrationExecution = 
failsafeExecutions.getChildren("execution", namespace).stream()
+                    .filter(e -> "post-integration-test-cleanup"
+                            .equals(e.getChild("id", namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(postIntegrationExecution);
+            assertEquals(
+                    "after:integration-test",
+                    postIntegrationExecution.getChild("phase", 
namespace).getText());
+        }
+
+        private void verifySitePluginPhases(Document document) {
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element build = root.getChild("build", namespace);
+            Element plugins = build.getChild("plugins", namespace);
+
+            Element sitePlugin = plugins.getChildren("plugin", 
namespace).stream()
+                    .filter(p -> "maven-site-plugin"
+                            .equals(p.getChild("artifactId", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(sitePlugin);
+
+            Element siteExecutions = sitePlugin.getChild("executions", 
namespace);
+            Element preSiteExecution = siteExecutions.getChildren("execution", 
namespace).stream()
+                    .filter(e ->
+                            "pre-site-setup".equals(e.getChild("id", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(preSiteExecution);
+            assertEquals(
+                    "before:site", preSiteExecution.getChild("phase", 
namespace).getText());
+
+            Element postSiteExecution = 
siteExecutions.getChildren("execution", namespace).stream()
+                    .filter(e -> "post-site-cleanup"
+                            .equals(e.getChild("id", namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(postSiteExecution);
+            assertEquals(
+                    "after:site", postSiteExecution.getChild("phase", 
namespace).getText());
+        }
+
+        private void verifyPluginManagementPhases(Document document) {
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element build = root.getChild("build", namespace);
+            Element pluginManagement = build.getChild("pluginManagement", 
namespace);
+            Element managedPlugins = pluginManagement.getChild("plugins", 
namespace);
+            Element compilerPlugin = managedPlugins.getChildren("plugin", 
namespace).stream()
+                    .filter(p -> "maven-compiler-plugin"
+                            .equals(p.getChild("artifactId", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(compilerPlugin);
+
+            Element compilerExecutions = compilerPlugin.getChild("executions", 
namespace);
+            Element preCleanCompileExecution = 
compilerExecutions.getChildren("execution", namespace).stream()
+                    .filter(e -> "pre-clean-compile"
+                            .equals(e.getChild("id", namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(preCleanCompileExecution);
+            assertEquals(
+                    "before:clean",
+                    preCleanCompileExecution.getChild("phase", 
namespace).getText());
+        }
+
+        private void verifyProfilePhases(Document document) {
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element profiles = root.getChild("profiles", namespace);
+            Element profile = profiles.getChild("profile", namespace);
+            Element profileBuild = profile.getChild("build", namespace);
+            Element profilePlugins = profileBuild.getChild("plugins", 
namespace);
+            Element antrunPlugin = profilePlugins.getChildren("plugin", 
namespace).stream()
+                    .filter(p -> "maven-antrun-plugin"
+                            .equals(p.getChild("artifactId", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(antrunPlugin);
+
+            Element antrunExecutions = antrunPlugin.getChild("executions", 
namespace);
+            Element profilePreIntegrationExecution = 
antrunExecutions.getChildren("execution", namespace).stream()
+                    .filter(e -> "profile-pre-integration-test"
+                            .equals(e.getChild("id", namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(profilePreIntegrationExecution);
+            assertEquals(
+                    "before:integration-test",
+                    profilePreIntegrationExecution.getChild("phase", 
namespace).getText());
+        }
+
+        @Test
+        @DisplayName("should not upgrade phases when upgrading to 4.0.0")
+        void shouldNotUpgradePhasesWhenUpgradingTo400() throws Exception {
+            String pomXml =
+                    """
+                <?xml version="1.0" encoding="UTF-8"?>
+                <project xmlns="http://maven.apache.org/POM/4.0.0";>
+                    <modelVersion>4.0.0</modelVersion>
+                    <groupId>com.example</groupId>
+                    <artifactId>test-project</artifactId>
+                    <version>1.0.0</version>
+                    <build>
+                        <plugins>
+                            <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-clean-plugin</artifactId>
+                                <version>3.2.0</version>
+                                <executions>
+                                    <execution>
+                                        <id>pre-clean-test</id>
+                                        <phase>pre-clean</phase>
+                                        <goals>
+                                            <goal>clean</goal>
+                                        </goals>
+                                    </execution>
+                                </executions>
+                            </plugin>
+                        </plugins>
+                    </build>
+                </project>
+                """;
+
+            Document document = saxBuilder.build(new StringReader(pomXml));
+            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), 
document);
+
+            // Create context with --model-version=4.0.0 option (no phase 
upgrade)
+            UpgradeOptions options = mock(UpgradeOptions.class);
+            when(options.modelVersion()).thenReturn(Optional.of("4.0.0"));
+            when(options.all()).thenReturn(Optional.empty());
+            UpgradeContext context = createMockContext(options);
+
+            UpgradeResult result = strategy.apply(context, pomMap);
+
+            assertTrue(result.success(), "Model upgrade should succeed");
+
+            // Verify phases were NOT upgraded (should remain as pre-clean)
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element build = root.getChild("build", namespace);
+            Element plugins = build.getChild("plugins", namespace);
+            Element cleanPlugin = plugins.getChild("plugin", namespace);
+            Element executions = cleanPlugin.getChild("executions", namespace);
+            Element execution = executions.getChild("execution", namespace);
+            Element phase = execution.getChild("phase", namespace);
+
+            assertEquals("pre-clean", phase.getText(), "Phase should remain as 
pre-clean for 4.0.0");
+        }
+
+        @Test
+        @DisplayName("should preserve non-deprecated phases")
+        void shouldPreserveNonDeprecatedPhases() throws Exception {
+            String pomXml =
+                    """
+                <?xml version="1.0" encoding="UTF-8"?>
+                <project xmlns="http://maven.apache.org/POM/4.0.0";>
+                    <modelVersion>4.0.0</modelVersion>
+                    <groupId>com.example</groupId>
+                    <artifactId>test-project</artifactId>
+                    <version>1.0.0</version>
+                    <build>
+                        <plugins>
+                            <plugin>
+                                <groupId>org.apache.maven.plugins</groupId>
+                                <artifactId>maven-compiler-plugin</artifactId>
+                                <version>3.11.0</version>
+                                <executions>
+                                    <execution>
+                                        <id>compile-test</id>
+                                        <phase>compile</phase>
+                                        <goals>
+                                            <goal>compile</goal>
+                                        </goals>
+                                    </execution>
+                                    <execution>
+                                        <id>test-compile-test</id>
+                                        <phase>test-compile</phase>
+                                        <goals>
+                                            <goal>testCompile</goal>
+                                        </goals>
+                                    </execution>
+                                    <execution>
+                                        <id>package-test</id>
+                                        <phase>package</phase>
+                                        <goals>
+                                            <goal>compile</goal>
+                                        </goals>
+                                    </execution>
+                                </executions>
+                            </plugin>
+                        </plugins>
+                    </build>
+                </project>
+                """;
+
+            Document document = saxBuilder.build(new StringReader(pomXml));
+            Map<Path, Document> pomMap = Map.of(Paths.get("pom.xml"), 
document);
+
+            // Create context with --model-version=4.1.0 option
+            UpgradeOptions options = mock(UpgradeOptions.class);
+            when(options.modelVersion()).thenReturn(Optional.of("4.1.0"));
+            when(options.all()).thenReturn(Optional.empty());
+            UpgradeContext context = createMockContext(options);
+
+            UpgradeResult result = strategy.apply(context, pomMap);
+
+            assertTrue(result.success(), "Model upgrade should succeed");
+
+            // Verify non-deprecated phases were preserved
+            Element root = document.getRootElement();
+            Namespace namespace = root.getNamespace();
+            Element build = root.getChild("build", namespace);
+            Element plugins = build.getChild("plugins", namespace);
+            Element compilerPlugin = plugins.getChild("plugin", namespace);
+            Element executions = compilerPlugin.getChild("executions", 
namespace);
+
+            Element compileExecution = executions.getChildren("execution", 
namespace).stream()
+                    .filter(e ->
+                            "compile-test".equals(e.getChild("id", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(compileExecution);
+            assertEquals(
+                    "compile", compileExecution.getChild("phase", 
namespace).getText());
+
+            Element testCompileExecution = executions.getChildren("execution", 
namespace).stream()
+                    .filter(e -> "test-compile-test"
+                            .equals(e.getChild("id", namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(testCompileExecution);
+            assertEquals(
+                    "test-compile",
+                    testCompileExecution.getChild("phase", 
namespace).getText());
+
+            Element packageExecution = executions.getChildren("execution", 
namespace).stream()
+                    .filter(e ->
+                            "package-test".equals(e.getChild("id", 
namespace).getText()))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(packageExecution);
+            assertEquals(
+                    "package", packageExecution.getChild("phase", 
namespace).getText());
+        }
+    }
+
     @Nested
     @DisplayName("Downgrade Handling")
     class DowngradeHandlingTests {

Reply via email to