【问题标题】:Changing Maven pom.xml <properties> values physically物理更改 Maven pom.xml <properties> 值
【发布时间】:2013-02-16 23:27:35
【问题描述】:

我正在为几个相互依赖的项目构建部署管道。每个构建都会生成一个具有唯一版本号的新发布构建,该版本会部署到 Maven 存储库。然后,管道中的下游项目将使用该新版本作为依赖项触发并以类似方式构建。

我需要在构建项目之前更改 pom.xml(或多模块项目中的所有 pom)中的属性值。例如,在以下代码中,“0.1.200”将更改为“0.1.345”(或任何最新的内部版本号)。使用系统属性不是一个选项,因为更新的 pom 将部署在 Maven 存储库中,因此更改必须是持久的。

<properties>
    <foo.version>0.1.200</foo.version>
</properties>

<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>foo</artifactId>
        <version>${foo.version}</version>
    </dependency>
</dependencies>

是否有一些 Maven 插件可以通过一个命令行指令来执行此操作? 否则我需要编写一个简短的脚本(例如在 Ruby 中)来解析和更改所有 pom.xml 文件项目。

【问题讨论】:

    标签: maven continuous-delivery build-pipeline


    【解决方案1】:

    是的,有一个maven-replacer-plugin 可以做到这一点。

    但是,如果您正在使用某些 CI 工具(显然您是),您也可以为此目的坚持使用自定义脚本。

    【讨论】:

      【解决方案2】:

      可用的 Maven 插件不符合我的目的,所以我最终编写了以下 Ruby 脚本,它完全符合我的需要:

      #!/usr/bin/env ruby
      require 'rexml/document'
      
      def change_property(pom, key, value)
        property = pom.elements["/project/properties/#{key}"]
        if property != nil
          puts "    #{key}: #{property.text} -> #{value}"
          property.text = value
        end
      end
      
      unless ARGV.length == 2
        puts "Usage: #{$0} KEY VALUE"
        exit 1
      end
      KEY = ARGV.shift
      VALUE = ARGV.shift
      
      Dir.glob("**/pom.xml") { |pom_path|
        puts pom_path
      
        pom = REXML::Document.new(File.new(pom_path))
        pom.context[:attribute_quote] = :quote
        change_property(pom, KEY, VALUE)
      
        File.open(pom_path, 'wb') { |file|
          pom.write(file)
        }
        puts
      }
      

      【讨论】:

        【解决方案3】:

        你试过这个吗?

        Version Maven Plugin

        【讨论】:

        • 该插件具有自动将依赖项更新到最新版本的操作,但我没有注意到有一种方法可以将单个属性更新为指定值。
        • versions-maven-plugin 能够处理此类属性。查看文档。
        • versions:update-properties 的问题在于它会自动尝试检测最新版本。在一个不好的部署管道中,因为它可能会不小心导致 Maven 找到一个太旧或太新的版本。为了避免不可重复的构建,我需要明确使用哪个版本。
        • mvn 版本:update-properties -Dproperties=[1] -DincludeProperties={foo.version}
        • @OhadR 您是否已确认使用该语法运行成功?它不适用于同事和我自己,我在输出中收到消息Property ${foo.version}: Leaving unchanged as 1.103.0,他没有得到任何输出。可能值得注意的是,我们正在尝试将值设置为无法根据服务器检查其有效性的任意版本。
        【解决方案4】:

        我也有类似的要求。除了更新 /project/properties 节点下的属性外,我还需要更新 /project/profiles/properties 节点下的属性,因此我修改了 Esko 的脚本以支持更新这两种情况。同时,它还支持在一个命令中更新多个属性,因此如果您需要更新同一个 pom.xml 中的多个属性,则无需多次运行。

        #!/usr/bin/env ruby
        require 'rexml/document'
        
        def change_profile_property(pom, profile_id, key, value)
          property = pom.elements["/project/profiles/profile[id='#{profile_id}']/properties/#{key}"]
          if property != nil
            puts "    #{profile_id}-#{key}: #{property.text} -> #{value}"
            property.text = value
          end
        end
        
        def change_property(pom, key, value)
          property = pom.elements["/project/properties/#{key}"]
          if property != nil
            puts "    #{key}: #{property.text} -> #{value}"
            property.text = value
          end
        end
        
        if ARGV.length == 0
          puts "Usage: #{$0} KEY=VALUE [-profile <profile id>] KEY=VALUE"
          exit 1
        end
        
        # parse the command line argument to get the key/value
        global_properties = Array.new
        profile_properties= Array.new
        
        profile = nil
        loop { case ARGV[0]
          when '-profile' then  ARGV.shift; profile=ARGV.shift
          when nil then break
          else 
            kv_str = ARGV.shift
            if profile == nil
              global_properties.push(kv_str)
            else
              profile_properties.push(kv_str)
            end
          end; 
        }
        
        Dir.glob("**/pom.xml") { |pom_path|
          puts pom_path
        
          pom = REXML::Document.new(File.new(pom_path))
          pom.context[:attribute_quote] = :quote
        
          # updating the global properties
          if global_properties.length != 0
            for kv in global_properties
              kv_array = kv.split('=')
                if kv_array.length == 2
                  change_property(pom, kv_array[0], kv_array[1])
                end
            end
          end
        
          # updating the properties in profile
          if profile_properties.length != 0
            for kv in profile_properties
              kv_array = kv.split('=')
              if kv_array.length == 2
                if profile != nil
                  change_profile_property(pom, profile, kv_array[0], kv_array[1])
                end
            end
            end
          end
        
          File.open(pom_path, 'wb') { |file|
            pom.write(file)
          }
          puts
        }
        

        【讨论】:

          【解决方案5】:

          Flatten Maven Plugin 可用于更新变量。让我用一个例子来解释。

          <groupId>groupid</groupId>
          <artifactId>artifactid</artifactId>
          <version>${ServiceVersion}</version>
          <packaging>pom</packaging>
          
          <properties>
              <foo.version>${ServiceVersion}</foo.version>
          </properties>
          

          在 pom.xml 中,我使用“ServiceVersion”在构建期间获取值。 foo.version 变量也将在构建期间更新。现在,foo.version 变量可以在任何依赖项中使用。

          <dependencies>
              <dependency>
                  <groupId>com.example</groupId>
                  <artifactId>foo</artifactId>
                  <version>${foo.version}</version>
              </dependency>
          </dependencies>
          

          所以,最后在 pom.xml 中包含 Flatten Maven 插件

          <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>flatten-maven-plugin</artifactId>
          <version>1.0.0</version>
          <configuration>
              <updatePomFile>true</updatePomFile>
          </configuration>
           <executions>
              <execution>
                  <id>flatten</id>
                  <phase>process-resources</phase>
                  <goals>
                      <goal>flatten</goal>
                  </goals>
              </execution>
              <execution>
                <id>flatten.clean</id>
                <phase>clean</phase>
                <goals>
                  <goal>clean</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          

          现在提供服务版本。

          clean install -DServiceVersion=0.1.345
          

          【讨论】:

            猜你喜欢
            • 2021-02-06
            • 2013-10-03
            • 2021-04-18
            • 2023-03-06
            • 2014-03-28
            • 1970-01-01
            • 2012-11-04
            • 1970-01-01
            • 2022-07-28
            相关资源
            最近更新 更多