检查Ivy

时间:2016-01-14 11:54:22

标签: ant dependency-management ivy

我们使用Ivy进行依赖管理。为了保证稳定性和可跟踪性,我们修复了常春藤文件中所有依赖项的版本号,另外我们使用transitive=false来避免依赖树不受控制地增长。第二个只有缺点,可能需要一些测试来完成常春藤文件。

由于我们修复了版本号,因此我们无法获得有关更高版本软件包的更新信息。我们不想要的是在构建时获取最新版本的依赖项。 我们想要的是定期检查可用的更新,然后决定是否以及要更新的软件包。

作为一个例子,这是我们从2016年1月14日起的Spring依赖项

    <dependency org="org.springframework"               name="spring-core"                      rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-aop"                       rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-beans"                     rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-context"                   rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-context-support"           rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-expression"                rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-jdbc"                      rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-orm"                       rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-tx"                        rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-web"                       rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-webmvc"                    rev="4.2.4.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework"               name="spring-test"                      rev="4.2.4.RELEASE"     transitive="false"          conf="test->*"/>
    <dependency org="org.springframework.plugin"        name="spring-plugin-core"               rev="1.2.0.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework.plugin"        name="spring-plugin-metadata"           rev="1.2.0.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework.batch"         name="spring-batch-core"                rev="3.0.6.RELEASE"     transitive="false"          conf="runtime->*"/>
    <dependency org="org.springframework.batch"         name="spring-batch-infrastructure"      rev="3.0.6.RELEASE"     transitive="false"          conf="runtime->*"/>

但我们还有更多。所以我问是否有更聪明的方法来检查所有包的可能更新(我们现在有101个包)。

Ant的ivy:report不会显示更高版本的可用性。手动检查Maven上的101个软件包很无聊。

我们还有一个本地Artifactory装置,我说如果它可以证明是有用的。

有什么想法吗?我希望看到的是一个包含Ivy文件中当前和最新版本包数的报告

1 个答案:

答案 0 :(得分:2)

我刚刚找到了一个旨在解决问题的常春藤任务checkdepsupdate

<target name="resolve" description="Use ivy to resolve classpaths">
    <ivy:resolve/>
    <ivy:checkdepsupdate showTransitive="false" revisionToCheck="latest.release"/>
</target>

在下面的示例中使用常春藤文件,它会打印以下报告详细说明,第三方依赖项的最新版本。

[ivy:checkdepsupdate] Dependencies updates available :
[ivy:checkdepsupdate]   org.slf4j#slf4j-api 1.7.5 -> 1.7.13
[ivy:checkdepsupdate]   org.slf4j#slf4j-log4j12 1.7.5 -> 1.7.13
[ivy:checkdepsupdate]   junit#junit 4.11 -> 4.12

我认为这可能就是你要找的东西。

冒着说明显而易见的风险,通过设置transitive = false,你将自己承担管理整个依赖树的工作。对于那些没问题的简单项目,你现在发现了这种方法的缺点。像Spring这样的项目故意将他们的可交付成果分成多个罐子以增加灵活性。它允许您只下载您需要的东西,并避免包含一个非常大的单片弹簧罐。

我会建议一些改善常春藤体验的事情

  1. 拥抱常春藤对传递依赖的管理
  2. 使用dynamic revisions
  3. 发布到存储库,以便创建发布记录
  4. 传递依赖和类路径管理

    在我的常春藤文件中,我通常只包含包含我正在使用的类的模块,让常春藤处理其他依赖项。我还使用ivy configurations按功能对依赖项进行分组。我的最终目标是使用配置来填充java类路径,因此我的一些依赖项在编译时是必需的,其他的在运行时,最后经常测试需要的jar文件永远不会随版本一起提供。

    示例常春藤文件:

    <ivy-module version="2.0">
        <info organisation="com.myspotontheweb" module="demo"/>
    
        <configurations>
            <conf name="compile" description="Required to compile application"/>
            <conf name="runtime" description="Additional run-time dependencies" extends="compile"/>
            <conf name="test"    description="Required for test only" extends="runtime"/>
        </configurations>
    
        <dependencies>
            <!-- compile dependencies -->
            <dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->default"/>
    
            <!-- runtime dependencies -->
            <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.7.5" conf="runtime->default"/>
    
            <!-- test dependencies -->
            <dependency org="junit" name="junit" rev="4.11" conf="test->default"/>
        </dependencies>
    
    </ivy-module>
    

    SLFJ项目是一个很好的例子,说明如何使用标准编程API,但在运行时根据类路径中包含的jar确定特定实现。在上面的例子中,我告诉我的构建在运行时使用log4j实现jar,这将反过来拉下log4j的兼容版本及其依赖的所有内容。

    最后,请注意每个配置如何扩展另一个?这意味着测试配置将包括编译和运行时配置中的jar。正是在使用junit运行单元测试时我需要的。

    这是我在ANT中的标准解决任务:

    <target name="resolve" depends="install-ivy" description="Use ivy to resolve classpaths">
        <ivy:resolve/>
    
        <ivy:report todir='${build.dir}/ivy-reports' graph='false' xml='false'/>
    
        <ivy:cachepath pathid="compile.path" conf="compile"/>
        <ivy:cachepath pathid="test.path"    conf="test"/>
    </target>
    

    现在,编译和测试类路径已自动填充,可以作为参考使用:

    <target name="compile" depends="resolve" description="Compile code">
        <mkdir dir="${build.dir}/classes"/>
        <javac srcdir="${src.dir}" destdir="${build.dir}/classes" includeantruntime="false" debug="true" classpathref="compile.path"/>
    </target>
    
    <target name="test" depends="compile" description="Run unit tests">
        <mkdir dir="${build.dir}/test-reports"/>
        <junit printsummary="yes" haltonfailure="yes">
            <classpath>
                <path refid="test.path"/>
                <pathelement path="${build.dir}/classes"/>
            </classpath>
            ..
            ..
        </junit>
    </target>
    

    解决任务已创建由构建维护的每个类路径的记录。

    动态修订

    当您发布到ivy存储库时,您可以指定发布类型。这允许常春藤自动确定特定版本类型的最新发布版本。默认情况下,支持两种类型的发布:

    1. 集成
    2. 释放
    3. 前者对应于Snven版本的Maven概念。在您组织内的另一个团队的控制下构建二进制文件,但尚未准备好发布。后者当然是完全批准和发布的二进制文件,非常适合第三方依赖。

      以下是显示两个dynamic revisions

      的理论用法的示例
      <dependencies>
          <!-- compile dependencies -->
          <dependency org="myorg" name="teamA" rev="latest.integration" conf="compile->default"/>
          <dependency org="myorg" name="teamB" rev="latest.integration" conf="compile->default"/>
          <dependency org="myorg" name="teamC" rev="latest.integration" conf="compile->default"/>
          <dependency org="org.slf4j" name="slf4j-api" rev="latest.release" conf="compile->default"/>
      
          <!-- runtime dependencies -->
          <dependency org="org.slf4j" name="slf4j-log4j12" rev="latest.release" conf="runtime->default"/>
      
          <!-- test dependencies -->
          <dependency org="junit" name="junit" rev="latest.release" conf="test->default"/>
      </dependencies>
      

      所以这会实现你的愿望。您的构建将自动注册来自第三方项目的新依赖项。

      发布到存储库,以便创建发布记录

      时间不会停滞不前,也不是项目的依赖树。由于现代Java程序可能具有大量直接依赖性,因此解决依赖关系会变得非常混乱。

      但....如何重现旧版本?我们可能会标记我们的源代码,但是如何在那个时间点跟踪的依赖关系

      我决定将每个版本发布到Maven存储库中:

      这是一个片段

      <target name="prepare" description="Generate POM">
          <!-- Optional: Intermediate file containing resolved version numbers -->
          <ivy:deliver deliverpattern="${build.dir}/ivy.xml" pubrevision="${publish.revision}" status="release"/>
      
          <!-- Generate the Maven POM -->
          <ivy:makepom ivyfile="${build.dir}/ivy.xml" pomfile="${build.dir}/donaldduck.pom"/>
      </target>
      
      <target name="publish" depends="init,prepare" description="Upload to Nexus">
          <ivy:publish resolver="nexus-deploy" pubrevision="${publish.revision}" overwrite="true" publishivy="false" >
              <artifacts pattern="${build.dir}/[artifact](-[classifier]).[ext]"/>
          </ivy:publish>
      </target>
      

      由于我正在使用Nexus,我需要为我的模块生成Maven POM文件。请注意使用任务delivermakepom?第一个将创建一个临时常春藤文件,其中包含每个依赖项的已解析版本号。这意味着Maven中生成的POM文件包含我用来构建代码的真实版本。

      您可以扩展这个想法,并在发布的二进制文件旁边另外发布以下内容:

      • Javadocs jar
      • 源代码jar
      • 常春藤报告jar
      • Junit报告jar

      在我看来,发布存储库应该是您发布的不变记录和对源代码存储库的重要补充。实际上,在大型企业组织中,这种基于文件的发布记录可能比您的源代码存储库技术(Clearcase - &gt; Subversion - &gt; Git - &gt; ??)更长。