Maven构建并发布多个相互依赖的项目

时间:2014-05-02 10:22:52

标签: java maven release

我有一些现有的Maven项目。

他们是:

  1. aaa(插件)
  2. bbb(jar)
  3. ccc(jar)
  4. ddd(战争)
  5. eee(战争)
  6. 项目ddd适用于客户,eee适用于其他

    它们位于磁盘上workspace/文件夹下的扁平结构中,并且svn repo中的结构完全相同。

    这是项目的依赖层次结构:

    ddd (war)        
        aaa (plugin)
        bbb (jar)
        ccc (jar)
            bbb (jar)
    
    eee (war)
        ccc (jar)
            bbb (jar)
    

    当只有war s SNAPSHOT s时,构建和发布没有问题

    否则,即

    ddd       1.1-SNAPSHOT (war)        
      aaa     2.0          (plugin)
      bbb     2.1-SNAPSHOT (jar)
      ccc     1.3-SNAPSHOT (jar)
        bbb   2.1-SNAPSHOT (jar)
    

    我必须这样做,以建立:

    1. bbb> mvn install
    2. ccc> mvn install
    3. ddd> mvn compile
    4. 和发布:

      1. bbb> mvn release:prepare release:perform
      2. ccc> mvn versions:use-releases
      3. ccc> svn ci -m "updated SNAPSHOT dependencies"
      4. ccc> mvn release:prepare release:perform
      5. ddd> mvn versions:use-releases
      6. ddd> svn ci -m "updated SNAPSHOT dependencies"
      7. ddd> mvn release:prepare release:perform
      8. 我尝试使用聚合器,但

        • 在构建时,它编译非SNAPSHOT依赖项(aaa 2.0 - >编译aaa 2.1-SNAPSHOT)
        • 在发布时,它抱怨scm,但我不希望聚合器在svn中

        这就是我需要的:

        • 单命令构建
          • 订购SNAPSHOT dependecies
          • 安装(或部署)每个SNAPSHOT依赖
          • 构建(编译或打包或安装...)根工件
        • 单一命令发布
          • 订购SNAPSHOT依赖项
          • 释放每个SNAPSHOT依赖
          • 发布根工件

        这是我想要的:

        • 批量构建/发布脚本
        • 将聚合器放入svn
        • 项目间的版本共享
        • parent也成为聚合器

        这可能吗?

        替代最佳做法? (也许詹金斯会帮忙?)

        我应该切换到Gradle ??


        更新

        我发现大多数人将聚合器混淆,所以我将其从此问题中删除了。然而,

          

        [...]您经常会看到父项和聚合器都是项目。 [...]然而,尽管POM项目,聚合器项目和父项目都不是同一个项目,但不应混淆。 POM项目可以从 - 但不一定 - 继承 - 它聚合的任何模块。相反,POM项目可能会聚合不从中继承的项目。

        来自A final note on Inheritance v. Aggregation

6 个答案:

答案 0 :(得分:1)

您可以切换到Gradle,但通过一些小修改可能更容易继续使用Maven:

  • 在您指定所有子模块的<modules> pom中添加parent
  • 将子poms中的父版本设置为与父版本相同,例如1.0.0-SNAPSHOT
  • 将其他版本中包含的项目(即bbbccc)添加到父pom的<dependencyManagement>部分,将其版本设置为${project.version},并在dddeee
  • 中删除其特定版本
  • 同样,将aaa插件添加到父pom的<pluginsManagement>部分,将其版本设置为${project.version},然后从其他项目中删除特定版本。

现在,您可以一次性构建和发布所有构建版本,例如使用maven-release-plugin

答案 1 :(得分:1)

来自barchart的人创建了一个Jenkins插件:“Maven Cascade Release Plugin”

https://github.com/barchart/barchart-jenkins-cascade-plugin/wiki/User-Manual

这要求您创建一个单独的“布局”项目来管理其他项目的发布顺序:

Root layout:
<project>
  <modules>
    <module>a</module>
    <module>ant</module>
    <module>fish</module>
    <module>fish/salmon</module>
    <module>fish/shark</module>
</modules>

这个项目似乎仍然需要在Subversion中,但您可以将它放在一个单独的存储库中,并将实际项目与svn:externals链接起来。然后Jenkins的插件将发布一个模块,它需要首先释放哪些模块。

要发布fish/shark -> 1.0,可能需要发布:

  • a - &gt; 1.1
  • 鱼/鲑鱼 - &gt; 1.2
  • fish / shark - &gt; 1.0

答案 2 :(得分:1)

只是以一种愚蠢的方式得到它...但我满意。

如果有人会提供更好的方法在maven上执行自定义递归发布过程,我会很高兴改变我的接受度!

父母:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>test-release-parent</artifactId>
    <version>1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>test-release-parent</name>
    <description>This is the parent pom to test release procedure</description>
    <inceptionYear>2014</inceptionYear>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <svn.repository>http://svn.mycompany.com/repo1</svn.repository>
        <web.projects>http://www2.mycompany.com/projects</web.projects>
    </properties>

    <scm>
        <developerConnection>scm:svn:${svn.repository}/${project.artifactId}</developerConnection>
        <url>${svn.repository}/${project.artifactId}</url>
    </scm>

    <distributionManagement>
        <repository>
            <id>ftp.mycompany.com</id>
            <name>mycompany Maven Repository</name>
            <url>ftp://ftp.mycompany.com/maven-repo</url>
        </repository>
    </distributionManagement>

    <repositories>
        <repository>
            <id>www2.mycompany.com</id>
            <name>mycompany Maven Repository</name>
            <url>http://www2.mycompany.com/maven-repo</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>www2.mycompany.com</id>
            <name>mycompany Maven Repository</name>
            <url>http://www2.mycompany.com/maven-repo</url>
        </pluginRepository>
    </pluginRepositories>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.4</version>
            </dependency>
            <dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.9</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-scm-plugin</artifactId>
                    <version>1.9</version>
                </plugin>

                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>versions-maven-plugin</artifactId>
                    <version>2.1</version>
                    <configuration>
                        <excludes>
                            <exclude>javax:javaee-api:*:*</exclude>
                            <exclude>org.eclipse.persistence:*:*:*</exclude>
                            <exclude>org.hibernate:hibernate-validator:*:*</exclude>
                        </excludes>
                        <rulesUri>http://www.mycompany.com/ruleset.xml</rulesUri>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.codehaus.gmaven</groupId>
                    <artifactId>gmaven-plugin</artifactId>
                    <version>1.5</version>
                </plugin>
            </plugins>
        </pluginManagement>

        <plugins>
            <plugin>
                <groupId>org.codehaus.gmaven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <configuration>
                    <source>
                        String releaseVersion = project.version.substring(0, project.version.indexOf("-"));

                        String nextVersion;
                        int index = releaseVersion.lastIndexOf(".");
                        if(index == -1) nextVersion = (releaseVersion.toInteger() + 1) + "-SNAPSHOT";
                        else
                        {
                            String prefix = releaseVersion.substring(0, index);
                            String suffix = releaseVersion.substring(index + 1);

                            nextVersion = prefix + "." + (suffix.toInteger() + 1) + "-SNAPSHOT";
                        }

                        ant.exec(failonerror: "true", dir: "${basedir}", executable: "cmd")
                        {
                            arg(value: "/c")
                            arg(value: "mvn")
                            arg(value: "validate")
                            arg(value: "-Prelease-align")
                            arg(value: "-Dversion.release=" + releaseVersion)
                            arg(value: "-Dversion.next=" + nextVersion)
                        }

                        ant.exec(failonerror: "true", dir: "${basedir}", executable: "cmd")
                        {
                            arg(value: "/c")
                            arg(value: "mvn")
                            arg(value: "initialize")
                            arg(value: "-Prelease-prepare")
                            arg(value: "-Dversion.release=" + releaseVersion)
                            arg(value: "-Dversion.next=" + nextVersion)
                        }

                        ant.exec(failonerror: "true", dir: "${basedir}", executable: "cmd")
                        {
                            arg(value: "/c")
                            arg(value: "mvn")
                            arg(value: "deploy")
                            arg(value: "-Prelease-perform")
                            arg(value: "-Dversion.release=" + releaseVersion)
                            arg(value: "-Dversion.next=" + nextVersion)
                        }
                    </source>
                </configuration>
            </plugin>
        </plugins>

        <extensions>
            <extension>
                <groupId>org.apache.maven.wagon</groupId>
                <artifactId>wagon-ftp</artifactId>
                <version>2.6</version>
            </extension>
        </extensions>
    </build>

    <profiles>
        <profile>
            <id>buildall</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.gmaven</groupId>
                        <artifactId>gmaven-plugin</artifactId>
                        <executions>
                            <execution>
                                <phase>validate</phase>
                                <goals>
                                    <goal>execute</goal>
                                </goals>
                                <configuration>
                                    <source>
                                        for(d in project.dependencies)
                                        {
                                            if(d.groupId == "com.mycompany" &amp;&amp; d.version.endsWith("-SNAPSHOT"))
                                            {
                                                println "installing " + d
                                                ant.exec(failonerror: "true", dir: "${basedir}/../" + d.artifactId, executable: "cmd")
                                                {
                                                    arg(value: "/c")
                                                    arg(value: "mvn")
                                                    arg(value: "install")
                                                    arg(value: "-Pbuildall")
                                                }
                                            }
                                        }
                                    </source>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>release-align</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>versions-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>initial-updates</id>
                                <phase>validate</phase>
                                <goals>
                                    <goal>update-parent</goal>
                                    <goal>use-releases</goal>
                                    <goal>commit</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>release-prepare</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.gmaven</groupId>
                        <artifactId>gmaven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>release-snapshots</id>
                                <phase>validate</phase>
                                <goals>
                                    <goal>execute</goal>
                                </goals>
                                <configuration>
                                    <source>
                                        if(project.parent != null &amp;&amp; project.parent.groupId == "com.mycompany" &amp;&amp; project.parent.version.endsWith("-SNAPSHOT"))
                                        {
                                            println "releasing " + project.parent

                                            String releaseVersion = project.parent.version.substring(0, project.parent.version.indexOf("-"));

                                            String nextVersion;
                                            int index = releaseVersion.lastIndexOf(".");
                                            if(index == -1) nextVersion = (releaseVersion.toInteger() + 1) + "-SNAPSHOT";
                                            else
                                            {
                                                String prefix = releaseVersion.substring(0, index);
                                                String suffix = releaseVersion.substring(index + 1);

                                                nextVersion = prefix + "." + (suffix.toInteger() + 1) + "-SNAPSHOT";
                                            }

                                            ant.exec(failonerror: "true", dir: "${basedir}/../" + project.parent.artifactId, executable: "cmd")
                                            {
                                                arg(value: "/c")
                                                arg(value: "mvn")
                                                arg(value: "validate")
                                                arg(value: "-Prelease-align")
                                                arg(value: "-Dversion.release=" + releaseVersion)
                                                arg(value: "-Dversion.next=" + nextVersion)
                                            }

                                            ant.exec(failonerror: "true", dir: "${basedir}/../" + project.parent.artifactId, executable: "cmd")
                                            {
                                                arg(value: "/c")
                                                arg(value: "mvn")
                                                arg(value: "initialize")
                                                arg(value: "-Prelease-prepare")
                                                arg(value: "-Dversion.release=" + releaseVersion)
                                                arg(value: "-Dversion.next=" + nextVersion)
                                            }

                                            ant.exec(failonerror: "true", dir: "${basedir}/../" + project.parent.artifactId, executable: "cmd")
                                            {
                                                arg(value: "/c")
                                                arg(value: "mvn")
                                                arg(value: "deploy")
                                                arg(value: "-Prelease-perform")
                                                arg(value: "-Dversion.release=" + releaseVersion)
                                                arg(value: "-Dversion.next=" + nextVersion)
                                            }
                                        }

                                        for(d in project.dependencies)
                                        {
                                            if(d.groupId == "com.mycompany" &amp;&amp; d.version.endsWith("-SNAPSHOT"))
                                            {
                                                println "releasing " + d

                                                String releaseVersion = d.version.substring(0, d.version.indexOf("-"));

                                                String nextVersion;
                                                int index = releaseVersion.lastIndexOf(".");
                                                if(index == -1) nextVersion = (releaseVersion.toInteger() + 1) + "-SNAPSHOT";
                                                else
                                                {
                                                    String prefix = releaseVersion.substring(0, index);
                                                    String suffix = releaseVersion.substring(index + 1);

                                                    nextVersion = prefix + "." + (suffix.toInteger() + 1) + "-SNAPSHOT";
                                                }

                                                ant.exec(failonerror: "true", dir: "${basedir}/../" + d.artifactId, executable: "cmd")
                                                {
                                                    arg(value: "/c")
                                                    arg(value: "mvn")
                                                    arg(value: "validate")
                                                    arg(value: "-Prelease-align")
                                                    arg(value: "-Dversion.release=" + releaseVersion)
                                                    arg(value: "-Dversion.next=" + nextVersion)
                                                }

                                                ant.exec(failonerror: "true", dir: "${basedir}/../" + d.artifactId, executable: "cmd")
                                                {
                                                    arg(value: "/c")
                                                    arg(value: "mvn")
                                                    arg(value: "initialize")
                                                    arg(value: "-Prelease-prepare")
                                                    arg(value: "-Dversion.release=" + releaseVersion)
                                                    arg(value: "-Dversion.next=" + nextVersion)
                                                }

                                                ant.exec(failonerror: "true", dir: "${basedir}/../" + d.artifactId, executable: "cmd")
                                                {
                                                    arg(value: "/c")
                                                    arg(value: "mvn")
                                                    arg(value: "deploy")
                                                    arg(value: "-Prelease-perform")
                                                    arg(value: "-Dversion.release=" + releaseVersion)
                                                    arg(value: "-Dversion.next=" + nextVersion)
                                                }
                                            }
                                        }
                                    </source>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>versions-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>final-updates</id>
                                <phase>initialize</phase>
                                <goals>
                                    <goal>update-parent</goal>
                                    <goal>use-releases</goal>
                                    <goal>set</goal>
                                    <goal>commit</goal>
                                </goals>
                                <configuration>
                                    <newVersion>${version.release}</newVersion>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>release-perform</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-deploy-plugin</artifactId>
                    </plugin>

                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>versions-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>set-next-snapshot</id>
                                <phase>deploy</phase>
                                <goals>
                                    <goal>set</goal>
                                    <goal>commit</goal>
                                </goals>
                                <configuration>
                                    <newVersion>${version.next}</newVersion>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-scm-plugin</artifactId>
                        <executions>
                            <execution>
                                <id>checkin-release</id>
                                <phase>verify</phase>
                                <goals>
                                    <goal>checkin</goal>
                                    <goal>tag</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>checkin-snapshot</id>
                                <phase>deploy</phase>
                                <goals>
                                    <goal>checkin</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <tag>${project.version}</tag>
                            <message>auto-generated by release process</message>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
</project>

这是一个项目pom,它使用另一个项目(工作区中的展平结构)作为依赖

<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/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.mycompany</groupId>
        <artifactId>test-release-parent</artifactId>
        <version>1-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>test-release-project</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>${project.artifactId}</name>
    <description>maven project to test a release process</description>
    <inceptionYear>2014</inceptionYear>
    <url>${web.projects}/${project.artifactId}</url>

    <repositories>
        <repository>
            <id>www2.mycompany.com</id>
            <name>mycompany Maven Repository</name>
            <url>http://www2.mycompany.com/maven-repo</url>
        </repository>
    </repositories>

    <scm>
        <developerConnection>scm:svn:${svn.repository}/${project.artifactId}/trunk</developerConnection>
        <url>${svn.repository}/${project.artifactId}/trunk</url>
    </scm>

    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mycompany</groupId>
            <artifactId>test-release-dependency</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

运行

mvn <some-phase> -Pbuildall

在当前项目上执行<some-phase>,在所有拥有和引用的快照(父级和依赖项)上执行install

mvn groovy:execute

执行发布所有拥有和引用的快照

背后的想法:

  • 程序发布:
    1. 更新父版本(如果存在)
    2. 更新快照依赖项(如果存在)
    3. 如果父拥有并拥有快照
      • 释放(父)
    4. 表示每个拥有和快照依赖项
      • 释放(依赖性)
    5. 更新父版(现在必须存在)
    6. 更新拥有和快照依赖项(现在必须存在)
    7. 设置项目发布版本(即从1.0.0-SNAPSHOT到1.0.0)
    8. 将更改提交到scm
    9. 标签冻结scm
    10. 执行所有maven生命周期阶段直到部署
    11. 设置项目下一个版本(即从1.0.0到1.0.1-SNAPSHOT)
    12. 再次向scm提交更改

答案 3 :(得分:0)

你还没有提到你父POM中你正在使用&#34; modules&#34;标签。我建议你应该使用它 - 这样你就可以为项目的构建过程指定一行。

要解决当前问题,请创建单独的模块/项目。在pom中指定配置文件以触发ant操作。这应该可以解决问题。

您可以在父目录上调用mvn命令,如下所示:

mvn clean install -Pdeploy

答案 4 :(得分:0)

根据您的依赖关系更改SVN中的结构:

在父级中,您必须定义模块列表,并且必须在相应的模块中定义模块之间的依赖关系。

parent (pom.xml)
 +-- aaa (plugin)
 +-- bbb (jar)
 +-- ccc (jar)
 +-- ddd (war)
 +-- eee (war)

对于所有模块(例如3.0-SNAPSHOT)的版本应该相同,之后您可以从根位置简单地发布/部署等。

如果这不是你要去的方式,你应该通过Jenkins分别发布所有这些项目。

答案 5 :(得分:0)

现在你的模块可能太精细了,但我个人认为单独的构建是构建系统的方法,这就是原因。

pom的主要工作是代表下一个版本。该版本可能是一个涉及多个内部模块的功能版本,也可能是一个错误修复版本,其中只有一个模块发生更改。

鉴于此,周期如下:

  1. 修改 pom的版本以对应下一个'版本'。
  2. 更新正在修改的模块版本作为发布的一部分。
  3. 更新模块以使用快照修改后的并进行更改。
  4. 将父级中的模块版本更新为其发布版本并发布父级
  5. 更新每个模块以使用已发布的 pom并释放模块。
  6. 这种方法的好处在于,在未修改模块的情况下,您使用之前发布的模块版本(从您的发布回购中获取,因此不是100%保证)而不进行重建(这可能发生在多个模块上) - 模块方法)减少回归测试开销。

    如果随每个版本更改的模块数量成为负担,可能是时候审查您的模块结构,但是这种方法的好处是 parent pom对齐您的所有模块版本系统允许减少回归测试工作并使快速小型发布变得容易。