Avoiding maven repository version collision when using feature branches

前端 未结 4 1599
粉色の甜心
粉色の甜心 2021-02-04 07:54

Question: How do you handle feature branches for maven multi project builds?

Jenkins builds and deploys these branches to keep build overhead on develop

4条回答
  •  醉梦人生
    2021-02-04 08:32

    How about the following approach:

    • Use the buildnumber-maven-plugin to fetch information from git and populate specific Maven properties (we are interested specifically in the scmBranch property (that is, the current git branch)
    • Use the build-helper-maven-plugin to check whether we are in a feature branch or not (via a regex, excluding well-known branches like master, develop, etc.) and populate (or not) a new Maven property, say branch.classifier
    • Use the maven-jar-plugin to set a classifier on the generated artifacts, based on what the previous step set, that is, using the new branch.classifier property: if empty, no classifier will be applied (default behavior, applied to the develop branch, for example); otherwise a classifier named after the current branch will be dynamically applied.

    Here is a minimal example:

    
        
            
                org.codehaus.mojo
                buildnumber-maven-plugin
                1.4
                
                    
                        validate
                        
                            create
                        
                    
                
            
            
                org.codehaus.mojo
                build-helper-maven-plugin
                1.10
                
                    
                        regex-property
                        
                            regex-property
                        
                        
                            branch.classifier
                            ${scmBranch}
                            (^develop)|(^master)|(^release.*)
                            
                            false
                        
                    
                
            
            
                maven-jar-plugin
                3.0.2
                
                    ${branch.classifier}
                
            
        
    
    

    The snippet below is basically populating the scmBranch property dynamically, then setting the branch.classifier to its value only if different than develop, master or release*, then setting it as a classifier.

    Main advantages of this approach:

    • No pom changes will be applied, hence no merging issues at all
    • No clashes on Nexus working on the same version of the project but on different branches: the classified artifact will have different Maven coordinates, that is, the GAV (groupId, artifactId, version) becomes unique GAVC (+classifier)
    • That's actually a meaningful usage of the classifier attribute of an artifact:

      The classifier allows to distinguish artifacts that were built from the same POM but differ in their content.

    • The generated artifact will be dynamically different in Nexus, according to its source branch, hence having implicit traceability: no intervention from developers (no error prone, implicit convention), no intervention from CI job (easier maintenance), completely transparent
    • Using classifiers, will be easier to use the artifacts generated by a branch as a maven dependency (e.g. in case of library project): I want to use the dependency currently under development on branch xxx

    Examples
    Hence, you would have the following artifacts generated:

    • When working on develop: e.g. project-1.0.0-SNAPSHOT.jar (empty classifier, hence not applied, as handled by the regex)
    • When working on featureA: e.g. project-1.0.0-SNAPSHOT-featureA.jar
    • When working on hotfix-JIRA123: e.g. project-1.0.0-hotfix-JIRA123.jar
    • When working on release-sprint42: that's up to you, I added this case to not apply the branch name, simply because in these cases I prefer to esplicitely set a special classifier, RC, for release candidates, but that's a matter of conventions/taste/habits, you can apply the same approach on this branch as well, as long as no clashes will be created on Nexus. Also note: when using JIRA/Stash/Git integration, the release branch name is normally something like release/v0.1.0, where the / character may cause issues in some OS (still something fixeable via further regex replacing though, if really required).
    • When working on master: hey, no one should work on master :) the case is there just as a double check, but that's actually not required

    Warnings on this approach:

    • As explained in the discussion below via comments, if the concerned Maven project is already using classifiers and even more via inter-modules dependencies (e.g. dependendies on test scope classes from another module), then this approach should be carefully tested, since it might have some drawbacks
    • The publication of the .pom files containing branch classifier can get into conflicts with the mainline build (i.e. overriding it)

提交回复
热议问题