This is an automated email from the ASF dual-hosted git repository.

kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-release.git


The following commit(s) were added to refs/heads/master by this push:
     new b5d5fb25 MRELEASE-1109 full support of CI Friendly expressions
b5d5fb25 is described below

commit b5d5fb25d0c9363dab1fc519748d2730089e7b0a
Author: Konrad Windszus <[email protected]>
AuthorDate: Tue Jul 29 08:49:03 2025 +0200

    MRELEASE-1109 full support of CI Friendly expressions
    
    
    ---------
    Co-authored-by: Mikhail Kolesnikov <[email protected]>
    Co-authored-by: mkolesnikov <[email protected]>
---
 .gitignore                                         |   4 +-
 .../release/config/ReleaseDescriptorBuilder.java   |   2 +-
 .../release/phase/AbstractCheckPomPhase.java       |   4 +-
 .../release/phase/AbstractMapVersionsPhase.java    |  30 +++++-
 .../release/phase/AbstractRewritePomsPhase.java    |  41 ++-----
 .../shared/release/transform/jdom2/JDomModel.java  |  27 ++---
 .../release/transform/jdom2/JDomModelETL.java      |   2 +-
 .../release/transform/jdom2/JDomProperties.java    |  23 +++-
 .../shared/release/util/CiFriendlyVersion.java     | 118 +++++++++++++++++++++
 .../maven/shared/release/util/MavenExpression.java |  61 +++++++++++
 .../shared/release/phase/MapVersionsPhaseTest.java |   4 +-
 .../phase/RewritePomsForDevelopmentPhaseTest.java  |  33 ++++++
 .../phase/RewritePomsForReleasePhaseTest.java      |  13 +++
 .../release/transform/jdom2/JDomModelTest.java     |  15 +--
 .../transform/jdom2/JDomPropertiesTest.java        |   9 +-
 .../shared/release/util/MavenExpressionTest.java   |  61 +++++++++++
 .../expected-pom.xml}                              |   7 +-
 .../pom.xml}                                       |   7 +-
 .../subproject1/expected-pom.xml                   |   2 +-
 .../subproject1/pom.xml                            |   2 +-
 .../expected-pom.xml                               |   2 +-
 .../pom.xml}                                       |   2 +-
 .../subproject1/expected-pom.xml                   |   0
 .../subproject1/pom.xml                            |   0
 .../expected-pom.xml                               |   6 +-
 .../pom.xml                                        |   6 +-
 .../subproject1/expected-pom.xml                   |   2 +-
 .../subproject1/pom.xml                            |   2 +-
 .../expected-pom.xml                               |   2 +-
 .../pom.xml                                        |   0
 .../subproject1/expected-pom.xml                   |   0
 .../subproject1/pom.xml                            |   0
 .../ci-friendly-multi-module/invoker.properties    |  19 ++++
 .../ci-friendly-multi-module/module-a/pom.xml      |  39 +++++++
 .../apache/maven/plugin/release/module/a/App.java  |  32 ++++++
 .../maven/plugin/release/module/a/AppTest.java     |  57 ++++++++++
 .../ci-friendly-multi-module/module-b/pom.xml      |  39 +++++++
 .../apache/maven/plugin/release/module/b/App.java  |  32 ++++++
 .../maven/plugin/release/module/b/AppTest.java     |  57 ++++++++++
 .../prepare/ci-friendly-multi-module/pom.xml       |  76 +++++++++++++
 .../prepare/ci-friendly-multi-module/verify.groovy |  52 +++++++++
 41 files changed, 806 insertions(+), 84 deletions(-)

diff --git a/.gitignore b/.gitignore
index 0e7c2b30..8937ec50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,6 @@ target
 build
 .checkstyle
 .DS_Store
-.factorypath
\ No newline at end of file
+.factorypath
+.mvn/
+mvnw
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/config/ReleaseDescriptorBuilder.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/config/ReleaseDescriptorBuilder.java
index a2afc729..6a04f2b7 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/config/ReleaseDescriptorBuilder.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/config/ReleaseDescriptorBuilder.java
@@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
  * @since 3.0.0-M5
  */
 public class ReleaseDescriptorBuilder {
-    private static final Pattern PROPERTY_PATTERN = 
Pattern.compile("\\$\\{[^}]+}");
+    private static final Pattern PROPERTY_PATTERN = 
Pattern.compile("\\$\\{[^}]+?}");
 
     private final Logger logger;
 
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractCheckPomPhase.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractCheckPomPhase.java
index fed38504..7b24d39a 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractCheckPomPhase.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractCheckPomPhase.java
@@ -31,6 +31,7 @@ import 
org.apache.maven.shared.release.config.ReleaseDescriptor;
 import org.apache.maven.shared.release.env.ReleaseEnvironment;
 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
+import org.apache.maven.shared.release.util.MavenExpression;
 import org.codehaus.plexus.util.StringUtils;
 
 import static java.util.Objects.requireNonNull;
@@ -89,7 +90,8 @@ public abstract class AbstractCheckPomPhase extends 
AbstractReleasePhase {
         boolean containsSnapshotProjects = false;
 
         for (MavenProject project : reactorProjects) {
-            if (ArtifactUtils.isSnapshot(project.getVersion())) {
+            String projectVersion = 
MavenExpression.evaluate(project.getVersion(), project.getProperties());
+            if (ArtifactUtils.isSnapshot(projectVersion)) {
                 containsSnapshotProjects = true;
 
                 break;
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractMapVersionsPhase.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractMapVersionsPhase.java
index 1615d1bf..ff3fcfe4 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractMapVersionsPhase.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractMapVersionsPhase.java
@@ -39,6 +39,7 @@ import org.apache.maven.shared.release.policy.PolicyException;
 import org.apache.maven.shared.release.policy.version.VersionPolicy;
 import org.apache.maven.shared.release.policy.version.VersionPolicyRequest;
 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
+import org.apache.maven.shared.release.util.CiFriendlyVersion;
 import org.apache.maven.shared.release.util.ReleaseUtil;
 import org.apache.maven.shared.release.versions.VersionParseException;
 import org.codehaus.plexus.components.interactivity.Prompter;
@@ -259,12 +260,12 @@ public abstract class AbstractMapVersionsPhase extends 
AbstractReleasePhase {
 
                     try {
                         try {
-                            suggestedVersion =
-                                    resolveSuggestedVersion(baseVersion, 
releaseDescriptor, releaseEnvironment);
+                            suggestedVersion = resolveSuggestedVersion(
+                                    project, baseVersion, releaseDescriptor, 
releaseEnvironment);
                         } catch (VersionParseException e) {
                             if (releaseDescriptor.isInteractive()) {
                                 suggestedVersion =
-                                        resolveSuggestedVersion("1.0", 
releaseDescriptor, releaseEnvironment);
+                                        resolveSuggestedVersion(project, 
"1.0", releaseDescriptor, releaseEnvironment);
                             } else {
                                 throw new ReleaseExecutionException(
                                         "Error parsing version, cannot 
determine next " + "version: " + e.getMessage(),
@@ -313,7 +314,10 @@ public abstract class AbstractMapVersionsPhase extends 
AbstractReleasePhase {
     }
 
     private String resolveSuggestedVersion(
-            String baseVersion, ReleaseDescriptor releaseDescriptor, 
ReleaseEnvironment releaseEnvironment)
+            MavenProject project,
+            String baseVersion,
+            ReleaseDescriptor releaseDescriptor,
+            ReleaseEnvironment releaseEnvironment)
             throws PolicyException, VersionParseException {
         String policyId = releaseDescriptor.getProjectVersionPolicyId();
         VersionPolicy policy = versionPolicies.get(policyId);
@@ -328,6 +332,11 @@ public abstract class AbstractMapVersionsPhase extends 
AbstractReleasePhase {
         }
         request.setWorkingDirectory(releaseDescriptor.getWorkingDirectory());
 
+        if 
(CiFriendlyVersion.isCiFriendlyVersion(getOriginalVersion(project))) {
+            String sha1 = 
CiFriendlyVersion.resolveSha1Property(project.getProperties(), 
releaseDescriptor);
+            request.setVersion(baseVersion.replace(sha1, ""));
+        }
+
         if (scmRepositoryConfigurator != null && 
releaseDescriptor.getScmSourceUrl() != null) {
             try {
                 ScmRepository repository = 
scmRepositoryConfigurator.getConfiguredRepository(
@@ -353,6 +362,19 @@ public abstract class AbstractMapVersionsPhase extends 
AbstractReleasePhase {
                 : policy.getReleaseVersion(request).getVersion();
     }
 
+    private static String getOriginalVersion(MavenProject project) {
+        String version = null;
+        while (version == null && project != null) {
+            if (project.getOriginalModel() != null) {
+                version = project.getOriginalModel().getVersion();
+            } else {
+                version = project.getVersion();
+            }
+            project = project.getParent();
+        }
+        return version;
+    }
+
     private String getDevelopmentVersion(String projectId, ReleaseDescriptor 
releaseDescriptor) {
         String projectVersion = 
releaseDescriptor.getProjectDevelopmentVersion(projectId);
 
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractRewritePomsPhase.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractRewritePomsPhase.java
index 7e799f30..4f180ee2 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractRewritePomsPhase.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/phase/AbstractRewritePomsPhase.java
@@ -24,7 +24,6 @@ import java.nio.file.Paths;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Date;
 import java.util.HashSet;
@@ -33,8 +32,6 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 import java.util.TimeZone;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.ArtifactUtils;
@@ -66,6 +63,8 @@ import org.apache.maven.shared.release.transform.ModelETL;
 import org.apache.maven.shared.release.transform.ModelETLFactory;
 import org.apache.maven.shared.release.transform.ModelETLRequest;
 import org.apache.maven.shared.release.transform.jdom2.JDomModelETLFactory;
+import org.apache.maven.shared.release.util.CiFriendlyVersion;
+import org.apache.maven.shared.release.util.MavenExpression;
 import org.apache.maven.shared.release.util.ReleaseUtil;
 import org.codehaus.plexus.util.StringUtils;
 
@@ -95,18 +94,6 @@ public abstract class AbstractRewritePomsPhase extends 
AbstractReleasePhase impl
      */
     private String modelETL = JDomModelETLFactory.NAME;
 
-    /**
-     * Regular expression pattern matching Maven expressions (i.e. references 
to Maven properties).
-     * The first group selects the property name the expression refers to.
-     */
-    private static final Pattern EXPRESSION_PATTERN = 
Pattern.compile("\\$\\{(.+)\\}");
-
-    /**
-     * All Maven properties allowed to be referenced in parent versions via 
expressions
-     * @see <a 
href="https://maven.apache.org/maven-ci-friendly.html";>CI-Friendly Versions</a>
-     */
-    private static final List<String> CI_FRIENDLY_PROPERTIES = 
Arrays.asList("revision", "sha1", "changelist");
-
     private long startTime = -1 * 1000;
 
     private final Set<String> exclusionPatterns = new HashSet<>();
@@ -468,23 +455,6 @@ public abstract class AbstractRewritePomsPhase extends 
AbstractReleasePhase impl
         modelTarget.setVersion(version);
     }
 
-    /**
-     * Extracts the Maven property name from a given expression.
-     * @param expression the expression
-     * @return either {@code null} if value is no expression otherwise the 
property referenced in the expression
-     */
-    public static String extractPropertyFromExpression(String expression) {
-        Matcher matcher = EXPRESSION_PATTERN.matcher(expression);
-        if (!matcher.matches()) {
-            return null;
-        }
-        return matcher.group(1);
-    }
-
-    public static boolean isCiFriendlyVersion(String version) {
-        return 
CI_FRIENDLY_PROPERTIES.contains(extractPropertyFromExpression(version));
-    }
-
     private void rewriteParent(
             MavenProject project,
             Model targetModel,
@@ -506,7 +476,8 @@ public abstract class AbstractRewritePomsPhase extends 
AbstractReleasePhase impl
                     throw new ReleaseFailureException("Version for parent '" + 
parent.getName() + "' was not mapped");
                 }
             } else {
-                if 
(!isCiFriendlyVersion(targetModel.getParent().getVersion())) {
+                if (!CiFriendlyVersion.isCiFriendlyVersion(
+                        targetModel.getParent().getVersion())) {
                     targetModel.getParent().setVersion(parentVersion);
                 } else {
                     logInfo(
@@ -587,7 +558,7 @@ public abstract class AbstractRewritePomsPhase extends 
AbstractReleasePhase impl
                 logInfo(result, "  Updating " + key + " to " + mappedVersion);
                 artifact.setVersion(mappedVersion);
             } else {
-                String property = extractPropertyFromExpression(rawVersion);
+                String property = 
MavenExpression.extractPropertyFromExpression(rawVersion);
                 if (property != null) {
                     if (property.startsWith("project.") || 
property.startsWith("pom.") || "version".equals(property)) {
                         // those properties are read-only, replace with 
literal version in case it is supposed to be
@@ -688,7 +659,7 @@ public abstract class AbstractRewritePomsPhase extends 
AbstractReleasePhase impl
                 }
             }
         } else {
-            if (CI_FRIENDLY_PROPERTIES.contains(property)) {
+            if (CiFriendlyVersion.isCiFriendlyProperty(property)) {
                 logInfo(result, "  Ignoring artifact version update for CI 
friendly expression " + rawVersion);
             } else {
                 // the expression used to define the version of this artifact 
may be inherited
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModel.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModel.java
index 6198ee73..c460ccc2 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModel.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModel.java
@@ -31,7 +31,8 @@ import org.apache.maven.model.Parent;
 import org.apache.maven.model.Profile;
 import org.apache.maven.model.Reporting;
 import org.apache.maven.model.Scm;
-import org.apache.maven.shared.release.phase.AbstractRewritePomsPhase;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.util.CiFriendlyVersion;
 import org.jdom2.Document;
 import org.jdom2.Element;
 import org.jdom2.Text;
@@ -47,13 +48,19 @@ public class JDomModel extends Model {
 
     private final JDomModelBase modelBase;
 
+    /**
+     * The ReleaseDescriptor after a commit performed
+     *
+     */
+    private final ReleaseDescriptor releaseDescriptor;
+
     /**
      * <p>Constructor for JDomModel.</p>
      *
      * @param document a {@link org.jdom2.Document} object
      */
-    public JDomModel(Document document) {
-        this(document.getRootElement());
+    public JDomModel(Document document, ReleaseDescriptor releaseDescriptor) {
+        this(document.getRootElement(), releaseDescriptor);
     }
 
     /**
@@ -61,8 +68,9 @@ public class JDomModel extends Model {
      *
      * @param project a {@link org.jdom2.Element} object
      */
-    public JDomModel(Element project) {
+    public JDomModel(Element project, ReleaseDescriptor releaseDescriptor) {
         this.project = project;
+        this.releaseDescriptor = releaseDescriptor;
         this.modelBase = new JDomModelBase(project);
     }
 
@@ -180,7 +188,7 @@ public class JDomModel extends Model {
 
         if (versionElement == null) {
             // never add version when parent references CI friendly property
-            if (!(parentVersion != null && 
AbstractRewritePomsPhase.isCiFriendlyVersion(parentVersion))
+            if (!(parentVersion != null && 
CiFriendlyVersion.isCiFriendlyVersion(parentVersion))
                     && !version.equals(parentVersion)) {
                 // we will add this after artifactId, since it was missing but 
different from the inherited version
                 Element artifactIdElement = project.getChild("artifactId", 
project.getNamespace());
@@ -192,14 +200,9 @@ public class JDomModel extends Model {
                 project.addContent(index + 2, versionElement);
             }
         } else {
-            if 
(AbstractRewritePomsPhase.isCiFriendlyVersion(versionElement.getTextNormalize()))
 {
+            if 
(CiFriendlyVersion.isCiFriendlyVersion(versionElement.getTextNormalize())) {
                 // try to rewrite property if CI friendly expression is used
-                String ciFriendlyPropertyName =
-                        
AbstractRewritePomsPhase.extractPropertyFromExpression(versionElement.getTextNormalize());
-                Properties properties = getProperties();
-                if (properties != null) {
-                    properties.computeIfPresent(ciFriendlyPropertyName, (k, v) 
-> version);
-                }
+                CiFriendlyVersion.rewriteCiFriendlyProperties(version, 
getProperties(), releaseDescriptor);
             } else {
                 JDomUtils.rewriteValue(versionElement, version);
             }
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModelETL.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModelETL.java
index 86bf8e27..640f574e 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModelETL.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomModelETL.java
@@ -159,7 +159,7 @@ public class JDomModelETL implements ModelETL {
 
     @Override
     public Model getModel() {
-        return new JDomModel(document);
+        return new JDomModel(document, releaseDescriptor);
     }
 
     private void normaliseLineEndings(Document document) {
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomProperties.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomProperties.java
index b2c314f3..bb6f5908 100644
--- 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomProperties.java
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/transform/jdom2/JDomProperties.java
@@ -34,6 +34,7 @@ import org.jdom2.Element;
 
 /**
  * JDOM2 implementation of poms PROPERTIES element
+ * Only few methods are properly implemented as the underlying data structure 
of {@link java.util.Hashtable} is never populated.
  *
  * @author Robert Scholte
  * @since 3.0
@@ -51,10 +52,13 @@ public class JDomProperties extends Properties {
     }
 
     @Override
-    public synchronized Object setProperty(String key, String value) {
-        Element property = properties.getChild(key, properties.getNamespace());
+    public synchronized Object put(Object key, Object value) {
+        Element property = properties.getChild((String) key, 
properties.getNamespace());
 
-        JDomUtils.rewriteValue(property, value);
+        if (property == null) {
+            property = new Element((String) key, properties.getNamespace());
+        }
+        JDomUtils.rewriteValue(property, (String) value);
 
         // todo follow specs of Hashtable.put
         return null;
@@ -112,9 +116,20 @@ public class JDomProperties extends Properties {
         }
     }
 
+    @Override
+    public boolean containsKey(Object key) {
+        if (key instanceof String) {
+            Element property = properties.getChild((String) key, 
properties.getNamespace());
+            return property != null;
+        }
+        return false;
+    }
+
     @Override
     public String getProperty(String key, String defaultValue) {
-        throw new UnsupportedOperationException();
+        String property = getProperty(key);
+
+        return property == null ? defaultValue : property;
     }
 
     @Override
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/util/CiFriendlyVersion.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/util/CiFriendlyVersion.java
new file mode 100644
index 00000000..8526da41
--- /dev/null
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/util/CiFriendlyVersion.java
@@ -0,0 +1,118 @@
+/*
+ * 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.shared.release.util;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.maven.artifact.ArtifactUtils;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CiFriendlyVersion {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(CiFriendlyVersion.class);
+
+    /**
+     * All Maven properties allowed to be referenced in parent versions via 
expressions
+     * @see <a 
href="https://maven.apache.org/maven-ci-friendly.html";>CI-Friendly Versions</a>
+     */
+    public static final String REVISION = "revision";
+
+    public static final String SHA1 = "sha1";
+    public static final String CHANGELIST = "changelist";
+
+    private static final Set<String> CI_FRIENDLY_PROPERTIES = new 
HashSet<>(Arrays.asList(REVISION, SHA1, CHANGELIST));
+
+    private static final String SNAPSHOT = "-SNAPSHOT";
+
+    private CiFriendlyVersion() {}
+
+    public static boolean isCiFriendlyVersion(String version) {
+        if (StringUtils.isEmpty(version)) {
+            return false;
+        }
+        return 
isCiFriendlyProperty(MavenExpression.extractPropertyFromExpression(version));
+    }
+
+    public static boolean isCiFriendlyProperty(String property) {
+        return CI_FRIENDLY_PROPERTIES.contains(property);
+    }
+
+    /**
+     * Rewrites the CI friendly properties in the given properties object 
based on the provided version and release descriptor.
+     * @param version
+     * @param properties
+     * @param releaseDescriptor
+     */
+    public static void rewriteCiFriendlyProperties(
+            String version, Properties properties, ReleaseDescriptor 
releaseDescriptor) {
+        // try to rewrite property if CI friendly expression is used
+        if (properties != null) {
+            String sha1 = resolveSha1Property(properties, releaseDescriptor);
+            // assume that everybody follows the example and properties are 
simply chained
+            //  and the changelist can only be '-SNAPSHOT'
+            if (ArtifactUtils.isSnapshot(version)) {
+                if (properties.containsKey(CHANGELIST)) {
+                    String revision = version.replace(sha1, 
"").replace(SNAPSHOT, "");
+                    setAndLogPropertyChange(properties, REVISION, revision);
+                    setAndLogPropertyChange(properties, CHANGELIST, SNAPSHOT);
+                } else {
+                    String revision = version.replace(sha1, "");
+                    setAndLogPropertyChange(properties, REVISION, revision);
+                }
+                if (properties.containsKey(SHA1)) {
+                    // drop the value for the next version
+                    setAndLogPropertyChange(properties, SHA1, "");
+                }
+            } else {
+                properties.setProperty(REVISION, version.replace(sha1, ""));
+                if (properties.containsKey(CHANGELIST)) {
+                    setAndLogPropertyChange(properties, CHANGELIST, "");
+                }
+                if (properties.containsKey(SHA1) && !sha1.isEmpty()) {
+                    // we need this to restore the revision for the next 
development
+                    // or release:prepare should provide sha1 after a commit
+                    // or a user should provide it as an additional 
`arguments` in plugin configuration
+                    // see 
maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module
+                    setAndLogPropertyChange(properties, SHA1, sha1);
+                }
+            }
+        }
+    }
+
+    private static void setAndLogPropertyChange(Properties properties, String 
key, String value) {
+        LOGGER.info("Updating CI friendly property {} to {}", key, value);
+        properties.setProperty(key, value);
+    }
+
+    public static String resolveSha1Property(Properties properties, 
ReleaseDescriptor releaseDescriptor) {
+        String sha1 = properties.getProperty(SHA1);
+        String scmVersion = releaseDescriptor.getScmReleasedPomRevision();
+        String systemSha1 = System.getProperty(SHA1);
+        String result = StringUtils.isNotEmpty(systemSha1)
+                ? systemSha1
+                : StringUtils.isNotEmpty(sha1) ? sha1 : scmVersion != null ? 
scmVersion : "";
+        LOGGER.info("Resolved SHA1 property value {}", result);
+        return result;
+    }
+}
diff --git 
a/maven-release-manager/src/main/java/org/apache/maven/shared/release/util/MavenExpression.java
 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/util/MavenExpression.java
new file mode 100644
index 00000000..f832c092
--- /dev/null
+++ 
b/maven-release-manager/src/main/java/org/apache/maven/shared/release/util/MavenExpression.java
@@ -0,0 +1,61 @@
+/*
+ * 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.shared.release.util;
+
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author <a href="mailto:[email protected]";>Mikhail 
Kolesnikov</a>
+ */
+public class MavenExpression {
+    /**
+     * Regular expression pattern matching Maven expressions (i.e. references 
to Maven properties).
+     * The first group selects the property name the expression refers to.
+     */
+    private static final Pattern EXPRESSION_PATTERN = 
Pattern.compile("\\$\\{(.+?)}");
+
+    private MavenExpression() {}
+
+    public static String evaluate(String expression, Map<?, ?> properties) {
+        StringBuilder result = new StringBuilder(expression);
+        Matcher matcher = EXPRESSION_PATTERN.matcher(result);
+        while (matcher.find()) {
+            String propertyName = matcher.group(1);
+            Object propertyValue = properties.get(propertyName);
+            result.replace(matcher.start(), matcher.end(), 
String.valueOf(propertyValue));
+            matcher.reset();
+        }
+        return result.toString();
+    }
+
+    /**
+     * Extracts the Maven property name from a given expression.
+     * @param expression the expression
+     * @return either {@code null} if value is no expression otherwise the 
property referenced in the expression
+     */
+    public static String extractPropertyFromExpression(String expression) {
+        Matcher matcher = EXPRESSION_PATTERN.matcher(expression);
+        if (!matcher.find()) {
+            return null;
+        }
+        return matcher.group(1);
+    }
+}
diff --git 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/MapVersionsPhaseTest.java
 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/MapVersionsPhaseTest.java
index 75f41215..4fb8b527 100644
--- 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/MapVersionsPhaseTest.java
+++ 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/MapVersionsPhaseTest.java
@@ -2502,7 +2502,9 @@ public class MapVersionsPhaseTest extends 
PlexusJUnit4TestCase {
         model.setGroupId("groupId");
         model.setArtifactId(artifactId);
         model.setVersion(version);
-        return new MavenProject(model);
+        MavenProject mavenProject = new MavenProject(model);
+        mavenProject.setOriginalModel(model);
+        return mavenProject;
     }
 
     private static MavenProject createProjectWithPomFile(String artifactId, 
String version, String pathName) {
diff --git 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForDevelopmentPhaseTest.java
 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForDevelopmentPhaseTest.java
index b303a514..366d04f4 100644
--- 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForDevelopmentPhaseTest.java
+++ 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForDevelopmentPhaseTest.java
@@ -398,4 +398,37 @@ public class RewritePomsForDevelopmentPhaseTest extends 
AbstractEditModeRewritin
 
         assertTrue(comparePomFiles(reactorProjects));
     }
+
+    @Test
+    public void testRewritePomWithCiFriendlyReactor() throws Exception {
+        List<MavenProject> reactorProjects = 
createReactorProjects("pom-with-parent-and-cifriendly-expressions");
+
+        ReleaseDescriptorBuilder builder =
+                createDescriptorFromProjects(reactorProjects, 
"pom-with-parent-and-cifriendly-expressions");
+        builder.addReleaseVersion("groupId:artifactId", RELEASE_VERSION);
+        builder.addDevelopmentVersion("groupId:artifactId", NEXT_VERSION);
+        builder.addReleaseVersion("groupId:subproject1", RELEASE_VERSION);
+        builder.addDevelopmentVersion("groupId:subproject1", NEXT_VERSION);
+
+        mapScm(builder);
+
+        phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new 
DefaultReleaseEnvironment(), reactorProjects);
+
+        assertTrue(comparePomFiles(reactorProjects));
+    }
+
+    @Test
+    public void testRewritePomWithCiFriendlyReactorWithOnlyRevision() throws 
Exception {
+        List<MavenProject> reactorProjects = 
createReactorProjects("pom-with-parent-and-cifriendly-revision");
+
+        ReleaseDescriptorBuilder builder =
+                createDescriptorFromProjects(reactorProjects, 
"pom-with-parent-and-cifriendly-revision");
+        builder.addReleaseVersion("groupId:artifactId", RELEASE_VERSION);
+        builder.addDevelopmentVersion("groupId:artifactId", NEXT_VERSION);
+        builder.addReleaseVersion("groupId:subproject1", RELEASE_VERSION);
+        builder.addDevelopmentVersion("groupId:subproject1", NEXT_VERSION);
+        phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new 
DefaultReleaseEnvironment(), reactorProjects);
+
+        assertTrue(comparePomFiles(reactorProjects));
+    }
 }
diff --git 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForReleasePhaseTest.java
 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForReleasePhaseTest.java
index ee71ff20..7813605b 100644
--- 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForReleasePhaseTest.java
+++ 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/phase/RewritePomsForReleasePhaseTest.java
@@ -335,6 +335,19 @@ public class RewritePomsForReleasePhaseTest extends 
AbstractEditModeRewritingRel
         assertTrue(comparePomFiles(reactorProjects));
     }
 
+    @Test
+    public void testRewritePomWithCiFriendlyReactorWithOnlyRevision() throws 
Exception {
+        List<MavenProject> reactorProjects = 
createReactorProjects("pom-with-parent-and-cifriendly-revision");
+
+        ReleaseDescriptorBuilder builder =
+                createDescriptorFromProjects(reactorProjects, 
"pom-with-parent-and-cifriendly-revision");
+        builder.addReleaseVersion("groupId:artifactId", NEXT_VERSION);
+        builder.addReleaseVersion("groupId:subproject1", NEXT_VERSION);
+        phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new 
DefaultReleaseEnvironment(), reactorProjects);
+
+        assertTrue(comparePomFiles(reactorProjects));
+    }
+
     // MRELEASE-311
     @Test
     public void testRewritePomWithDependencyPropertyCoordinate() throws 
Exception {
diff --git 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomModelTest.java
 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomModelTest.java
index ebd0ec28..3967274b 100644
--- 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomModelTest.java
+++ 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomModelTest.java
@@ -22,6 +22,8 @@ import java.io.StringReader;
 
 import org.apache.maven.model.Model;
 import org.apache.maven.model.Scm;
+import org.apache.maven.shared.release.config.ReleaseDescriptor;
+import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
 import org.jdom2.Document;
 import org.jdom2.Element;
 import org.jdom2.input.SAXBuilder;
@@ -33,19 +35,20 @@ import static org.junit.Assert.assertNull;
 
 public class JDomModelTest {
     private SAXBuilder builder = new SAXBuilder();
+    private ReleaseDescriptor releaseDescriptor = new 
ReleaseDescriptorBuilder().build();
 
     @Test
     public void testGetScm() throws Exception {
         String content = "<project></project>";
         Document document = builder.build(new StringReader(content));
-        assertNull(new JDomModel(document).getScm());
+        assertNull(new JDomModel(document, releaseDescriptor).getScm());
     }
 
     @Test
     public void testSetScm() throws Exception {
         String content = "<project></project>";
         Document document = builder.build(new StringReader(content));
-        Model model = new JDomModel(document);
+        Model model = new JDomModel(document, releaseDescriptor);
         assertNull(model.getScm());
 
         model.setScm(new Scm());
@@ -59,7 +62,7 @@ public class JDomModelTest {
     public void testSetVersion() throws Exception {
         String content = "<project></project>";
         Element projectElm = builder.build(new 
StringReader(content)).getRootElement();
-        Model model = new JDomModel(projectElm);
+        Model model = new JDomModel(projectElm, releaseDescriptor);
         assertNull(model.getVersion());
 
         model.setVersion("VERSION");
@@ -69,9 +72,9 @@ public class JDomModelTest {
         assertNull(model.getVersion());
 
         // inherit from parent via CI friendly
-        content = 
"<project><parent><version>${revision}</version></parent></project>";
+        content = 
"<project><parent><version>${revision}${changelist}</version></parent></project>";
         projectElm = builder.build(new StringReader(content)).getRootElement();
-        model = new JDomModel(projectElm);
+        model = new JDomModel(projectElm, releaseDescriptor);
         assertNull(model.getVersion());
         model.setVersion("PARENT_VERSION");
         assertNull(getVersion(projectElm));
@@ -79,7 +82,7 @@ public class JDomModelTest {
         // this business logic might need to moved.
         content = 
"<project><parent><version>PARENT_VERSION</version></parent></project>";
         projectElm = builder.build(new StringReader(content)).getRootElement();
-        model = new JDomModel(projectElm);
+        model = new JDomModel(projectElm, releaseDescriptor);
         assertNull(model.getVersion());
 
         model.setVersion("PARENT_VERSION");
diff --git 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomPropertiesTest.java
 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomPropertiesTest.java
index fa9f48d9..0335a116 100644
--- 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomPropertiesTest.java
+++ 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/transform/jdom2/JDomPropertiesTest.java
@@ -101,9 +101,12 @@ public class JDomPropertiesTest {
         assertEquals("VALUE", new 
JDomProperties(propertiesElm).getProperty("KEY"));
     }
 
-    @Test(expected = UnsupportedOperationException.class)
-    public void testGetPropertyDefault() {
-        new JDomProperties(null).getProperty(null, null);
+    @Test
+    public void testGetPropertyDefault() throws Exception {
+        String content = "<properties></properties>";
+        Element propertiesElm = builder.build(new 
StringReader(content)).getRootElement();
+        assertNull(new JDomProperties(propertiesElm).getProperty("KEY", null));
+        assertEquals("", new JDomProperties(propertiesElm).getProperty("KEY", 
""));
     }
 
     @Test(expected = UnsupportedOperationException.class)
diff --git 
a/maven-release-manager/src/test/java/org/apache/maven/shared/release/util/MavenExpressionTest.java
 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/util/MavenExpressionTest.java
new file mode 100644
index 00000000..12c1b2d4
--- /dev/null
+++ 
b/maven-release-manager/src/test/java/org/apache/maven/shared/release/util/MavenExpressionTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.shared.release.util;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * @author <a href="mailto:[email protected]";>Mikhail 
Kolesnikov</a>
+ */
+@RunWith(Parameterized.class)
+public class MavenExpressionTest extends TestCase {
+
+    private final String expected;
+    private final String expression;
+    private final Properties properties = new Properties();
+
+    public MavenExpressionTest(String expected, String expression) {
+        this.expected = expected;
+        this.expression = expression;
+        properties.setProperty("revision", "12");
+        properties.setProperty("sha1", "34");
+        properties.setProperty("changelist", "56");
+    }
+
+    @Parameters(name = "expected result {0} for expression {1}")
+    public static Collection<Object[]> parameters() {
+        return Arrays.asList(
+                new Object[] {"123456", "${revision}${sha1}${changelist}"},
+                new Object[] {"12-34-56", "${revision}-${sha1}-${changelist}"},
+                new Object[] {"12-null-56", 
"${revision}-${unknown}-${changelist}"});
+    }
+
+    @Test
+    public void testEvaluate() {
+        assertEquals(expected, MavenExpression.evaluate(expression, 
properties));
+    }
+}
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
similarity index 80%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
index 0c9bd8b2..60b7355b 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
@@ -20,7 +20,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>groupId</groupId>
   <artifactId>artifactId</artifactId>
-  <version>${revision}</version>
+  <version>${revision}${sha1}${changelist}</version>
   <packaging>pom</packaging>
 
   <scm>
@@ -30,7 +30,10 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.1</revision>
+    <!-- usually the sha1 is passed as command-line option, the 
release:perform will store it in released pom and will remove it for the next 
dev pom-->
+    <sha1 />
+    <changelist>-SNAPSHOT</changelist>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/pom.xml
similarity index 81%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/pom.xml
index c7504063..8b16adc1 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/pom.xml
@@ -20,7 +20,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>groupId</groupId>
   <artifactId>artifactId</artifactId>
-  <version>${revision}</version>
+  <version>${revision}${sha1}${changelist}</version>
   <packaging>pom</packaging>
 
   <scm>
@@ -30,7 +30,10 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.0</revision>
+    <!-- usually the sha1 is passed as command-line option, the 
release:perform will store it in released pom and will remove it for the next 
dev pom-->
+    <sha1/>
+    <changelist/>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
similarity index 94%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
index 7b2fa88c..a025619d 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>groupId</groupId>
     <artifactId>artifactId</artifactId>
-    <version>${revision}</version>
+    <version>${revision}${sha1}${changelist}</version>
   </parent>
 
   <artifactId>subproject1</artifactId>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
similarity index 94%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
index 7b2fa88c..a025619d 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>groupId</groupId>
     <artifactId>artifactId</artifactId>
-    <version>${revision}</version>
+    <version>${revision}${sha1}${changelist}</version>
   </parent>
 
   <artifactId>subproject1</artifactId>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/expected-pom.xml
similarity index 97%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/expected-pom.xml
index c7504063..04e6e68f 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/expected-pom.xml
@@ -30,7 +30,7 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.1-SNAPSHOT</revision>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/pom.xml
similarity index 97%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/pom.xml
index c7504063..b4326d54 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/pom.xml
@@ -30,7 +30,7 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.0</revision>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/subproject1/expected-pom.xml
similarity index 100%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/subproject1/expected-pom.xml
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/subproject1/pom.xml
similarity index 100%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-development/pom-with-parent-and-cifriendly-revision/subproject1/pom.xml
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
index c7504063..30e536cd 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
@@ -20,7 +20,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>groupId</groupId>
   <artifactId>artifactId</artifactId>
-  <version>${revision}</version>
+  <version>${revision}${sha1}${changelist}</version>
   <packaging>pom</packaging>
 
   <scm>
@@ -30,7 +30,9 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.0</revision>
+    <sha1>.123</sha1>
+    <changelist></changelist>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
index 0c9bd8b2..d428097d 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
@@ -20,7 +20,7 @@
   <modelVersion>4.0.0</modelVersion>
   <groupId>groupId</groupId>
   <artifactId>artifactId</artifactId>
-  <version>${revision}</version>
+  <version>${revision}${sha1}${changelist}</version>
   <packaging>pom</packaging>
 
   <scm>
@@ -30,7 +30,9 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.0</revision>
+    <sha1>.123</sha1>
+    <changelist>-SNAPSHOT</changelist>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
index 7b2fa88c..a025619d 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>groupId</groupId>
     <artifactId>artifactId</artifactId>
-    <version>${revision}</version>
+    <version>${revision}${sha1}${changelist}</version>
   </parent>
 
   <artifactId>subproject1</artifactId>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
index 7b2fa88c..a025619d 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>groupId</groupId>
     <artifactId>artifactId</artifactId>
-    <version>${revision}</version>
+    <version>${revision}${sha1}${changelist}</version>
   </parent>
 
   <artifactId>subproject1</artifactId>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/expected-pom.xml
similarity index 97%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/expected-pom.xml
index c7504063..b4326d54 100644
--- 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/expected-pom.xml
+++ 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/expected-pom.xml
@@ -30,7 +30,7 @@
   </scm>
 
   <properties>
-    <revision>1.0-SNAPSHOT</revision>
+    <revision>1.0</revision>
   </properties>
 
   <modules>
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/pom.xml
similarity index 100%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/pom.xml
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/subproject1/expected-pom.xml
similarity index 100%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/expected-pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/subproject1/expected-pom.xml
diff --git 
a/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
 
b/maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/subproject1/pom.xml
similarity index 100%
copy from 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-expressions/subproject1/pom.xml
copy to 
maven-release-manager/src/test/resources/projects/rewrite-for-release/pom-with-parent-and-cifriendly-revision/subproject1/pom.xml
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/invoker.properties
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/invoker.properties
new file mode 100644
index 00000000..50eda560
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/invoker.properties
@@ -0,0 +1,19 @@
+# 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.
+
+invoker.goals=release:clean release:prepare -Dsha1=-abcdef12
+#invoker.mavenOpts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005
\ No newline at end of file
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/pom.xml
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/pom.xml
new file mode 100644
index 00000000..14c54172
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!--
+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.
+-->
+<project>
+  <parent>
+    <artifactId>ci-friendly-multi-module-project</artifactId>
+    <groupId>org.apache.maven.plugin.release</groupId>
+    <version>${revision}${sha1}${changelist}</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.plugin.release</groupId>
+  <artifactId>module-a</artifactId>
+  <name>module-a</name>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>@junitVersion@</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/src/main/java/org/apache/maven/plugin/release/module/a/App.java
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/src/main/java/org/apache/maven/plugin/release/module/a/App.java
new file mode 100644
index 00000000..05ca6eca
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/src/main/java/org/apache/maven/plugin/release/module/a/App.java
@@ -0,0 +1,32 @@
+package org.apache.maven.plugin.release.module.a;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/src/test/java/org/apache/maven/plugin/release/module/a/AppTest.java
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/src/test/java/org/apache/maven/plugin/release/module/a/AppTest.java
new file mode 100644
index 00000000..ca41b5f5
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-a/src/test/java/org/apache/maven/plugin/release/module/a/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.maven.plugin.release.module.a;
+
+/*
+ * 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.
+ */
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/pom.xml
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/pom.xml
new file mode 100644
index 00000000..e4430454
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0"?>
+<!--
+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.
+-->
+<project>
+  <parent>
+    <artifactId>ci-friendly-multi-module-project</artifactId>
+    <groupId>org.apache.maven.plugin.release</groupId>
+    <version>${revision}${sha1}${changelist}</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.plugin.release</groupId>
+  <artifactId>module-b</artifactId>
+  <name>module-b</name>
+  <url>http://maven.apache.org</url>
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>@junitVersion@</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/src/main/java/org/apache/maven/plugin/release/module/b/App.java
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/src/main/java/org/apache/maven/plugin/release/module/b/App.java
new file mode 100644
index 00000000..8d4d841d
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/src/main/java/org/apache/maven/plugin/release/module/b/App.java
@@ -0,0 +1,32 @@
+package org.apache.maven.plugin.release.module.b;
+
+/*
+ * 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.
+ */
+
+/**
+ * Hello world!
+ *
+ */
+public class App 
+{
+    public static void main( String[] args )
+    {
+        System.out.println( "Hello World!" );
+    }
+}
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/src/test/java/org/apache/maven/plugin/release/module/b/AppTest.java
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/src/test/java/org/apache/maven/plugin/release/module/b/AppTest.java
new file mode 100644
index 00000000..c1a903ec
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/module-b/src/test/java/org/apache/maven/plugin/release/module/b/AppTest.java
@@ -0,0 +1,57 @@
+package org.apache.maven.plugin.release.module.b;
+
+/*
+ * 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.
+ */
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Unit test for simple App.
+ */
+public class AppTest 
+    extends TestCase
+{
+    /**
+     * Create the test case
+     *
+     * @param testName name of the test case
+     */
+    public AppTest( String testName )
+    {
+        super( testName );
+    }
+
+    /**
+     * @return the suite of tests being tested
+     */
+    public static Test suite()
+    {
+        return new TestSuite( AppTest.class );
+    }
+
+    /**
+     * Rigourous Test :-)
+     */
+    public void testApp()
+    {
+        assertTrue( true );
+    }
+}
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/pom.xml 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/pom.xml
new file mode 100644
index 00000000..e6c05b91
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/pom.xml
@@ -0,0 +1,76 @@
+<?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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
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.plugin.release</groupId>
+  <artifactId>ci-friendly-multi-module-project</artifactId>
+  <packaging>pom</packaging>
+  <version>${revision}${sha1}${changelist}</version>
+  <name>parent-project</name>
+  <url>http://maven.apache.org</url>
+  <scm>
+    <connection>scm:stub|</connection>
+    <developerConnection>scm:stub|</developerConnection>
+    <tag>HEAD</tag>
+  </scm>
+  
+  <properties>
+    <revision>1.0.0</revision>
+    <sha1></sha1>
+    <changelist>-SNAPSHOT</changelist>
+    <maven.compiler.source>@maven.compiler.source@</maven.compiler.source>
+    <maven.compiler.target>@maven.compiler.target@</maven.compiler.target>
+  </properties>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-release-plugin</artifactId>
+          <version>@project.version@</version>
+          <configuration>
+            <arguments>-Dsha1=${sha1}</arguments>
+          </configuration>
+          <dependencies>
+            <dependency>
+              <groupId>org.apache.maven.its.release</groupId>
+              <artifactId>maven-scm-provider-stub</artifactId>
+              <version>1.0</version>
+            </dependency>
+          </dependencies>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>@junitVersion@</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+  <modules>
+    <module>module-a</module>
+    <module>module-b</module>
+  </modules>
+</project>
diff --git 
a/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/verify.groovy
 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/verify.groovy
new file mode 100644
index 00000000..2b83f5f9
--- /dev/null
+++ 
b/maven-release-plugin/src/it/projects/prepare/ci-friendly-multi-module/verify.groovy
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+import groovy.xml.XmlSlurper
+
+File buildLog = new File( basedir, 'build.log' )
+assert buildLog.exists()
+
+// tag versions
+def projectRootTag = new XmlSlurper().parse( new File( basedir, 'pom.xml.tag' 
) )
+assert projectRootTag.version.text() == '${revision}${sha1}${changelist}'
+assert projectRootTag.properties.revision.text() == "1.0.0"
+assert projectRootTag.properties.sha1.text() == "-abcdef12"
+assert projectRootTag.properties.changelist.text() == ""
+
+def projectATag = new XmlSlurper().parse( new File( basedir, 
'module-a/pom.xml.tag' ) )
+assert projectATag.parent.version.text() == '${revision}${sha1}${changelist}'
+
+def projectBTag = new XmlSlurper().parse( new File( basedir, 
'module-b/pom.xml.tag' ) )
+assert projectBTag.parent.version.text() == '${revision}${sha1}${changelist}'
+
+
+// next development versions
+def projectRoot = new XmlSlurper().parse( new File( basedir, 'pom.xml.next' ) )
+assert projectRoot.version.text() == '${revision}${sha1}${changelist}'
+assert projectRoot.properties.revision.text() == "1.0.1"
+assert projectRoot.properties.sha1.text() == ""
+assert projectRoot.properties.changelist.text() == "-SNAPSHOT"
+
+def projectA = new XmlSlurper().parse( new File( basedir, 
'module-a/pom.xml.next' ) )
+assert projectA.parent.version.text() == '${revision}${sha1}${changelist}'
+
+def projectB = new XmlSlurper().parse( new File( basedir, 
'module-b/pom.xml.next' ) )
+assert projectB.parent.version.text() == '${revision}${sha1}${changelist}'
+
+return true

Reply via email to