|
we'll discuss this week, its already on the list. Thanks for putting in a tracking JIRA
just jotting down some more notes.
What if you were to checkout a mix bag of source code from CVS, with a subproject at HEAD and the main project at a tagged version. Now, if you run a build, you'll get the new subproject but it'll be VERSIONED in the repo as the tagged version. I'm starting design work for this one, and I'd like to put forth the things I can remember from the meeting after JavaOne (brett, jason) and have people (anyone) comment on the viability/correctness of my approach. This is going to have to happen kind of fast in order to keep it from monopolizing the -beta-1 release, but we need to get this straight...
NOTE: This is just a first-pass, from some notes I've been working on this morning. I'm not going to start implementation until we hash some of this out better... ====================================================== As a starting use case, I've chosen to look at an EAR file:
Goal: Maintain application version information in only one place. Requirements
Implementation Notes 1. Child pom (WARs, EJB) will specify a parent WITHOUT a version 2. Child pom WILL NOT specify a version for themselves (this version is provided by the parent) 3. It is assumed that the child's parent-pom will live in the parent directory (parent-pom == ../pom.xml) (see questions/notes below) 4. If #'s 1, 2 hold, and ../pom.xml is non-existent or doesn't match the parent specification, throw an exception and stop the build. Questions/Notes
Just for the record. Above structure for EAR module is not flexible. I actually ended up with multiple ears on a same project, they may include different modules, depends in the need. For example:
Project
The major difference is that root project doesn't build/deploy/publish anything except its own pom.xml It is also possible that paren pom also inherited, so resolving should work all the way up to root and should not be limeted to one level of hierarchy. If I'm not mistaken I've seen such project hierarchy in Geronimo or ActiveMQ. I regards to 3rd note. I think that you should be resolve dependencies just by their names and no need to specify relative path. So, it should be possible to scan local project structure (in assumption that entrire project is avaliable locally) and collect all locally available artifacts. Also, it would be nice if m2 would fall down to repository if it can resolve dependencies locally (e.g. if project is not comletely present locally), but maybe you can just disable release goal in this case. With that last comment, I assume you're talking about resolving the parent-pom's version from the repository if it's not present. If we do that, what metadata will we use to resolve this? SNAPSHOT (and if so, which XX for XX-SNAPSHOT?), or RELEASE?
The problem I can see with this is that it could lead to inconsistent builds, which isn't only a problem with releases, but with integration tests, test deployments resulting from these builds, and even developer builds. If a developer builds one of these subprojects using dependencies resolved from the last RELEASE of a parent-pom, and there is a newer version of the parent-pom in SCM which is meant to be used, it could lead to strange runtime errors in the resulting artifact. If we go down the path of allowing the parent-pom to set all version information for the entire hierarchy, then this becomes even more suspect, since we'd be setting the entire build's version information based on a parent-pom we resolved from the repository. I do think I'm in the minority on this side, but I am emphatically against using the repository for the parent-pom. If it's missing, it's dangerous to do anything but fail and prompt the user to checkout the whole project hierarchy. Inconsistencies like this will lead m2 to be misused and seen as low quality as a result of this abuse (it's unfair, but it's true). Is it really that onerous to say that the whole project hierarchy has to be in your work directory if you're using this type of multi-project? Is there a compelling reason to go to the repository for this information, or is this just an effort to go that extra mile and help users do weird things? Please keep in mind that Eclipse does not allow nesting projects. It is possible to have a signle Eclipse project containg a whole Maven project hierarchy with multiple Java source folders. Kind of weird and counterintuitive to Eclipse user but works. At the same time, Eclipse WTP (Web Standard Tools) project developers were discussing lately wether to allow multiple J2EE modules per Eclipse project or not, and the consensus was 1 module - 1 project, along with no project nesting principle. Therefore making nested project structure a requirement for version inheritance would make it incompatible with WTP.
From Eclipse perspective, the "natural" organization of project folders looks like that: <workspace>
If we assume that projects directory names in the workspace correspond to project's artifactId, a project's descriptor can be reached from workspace by following ${proj.artifactId}/pom.xml, and the workspace directory can be reached from project's $basedir by following ${basedir}/../ path. 3) adding CI into the mix <workspace>
I think introducing information about relative path betwen workspace directory and project descriptor solves the problem or reaching parent pom because it gives a lot of flexibility both in workspace and project organization. Of course the user can still shoot himself in the foot by checking out the parent project from different branch than the child modules If I can add my two cents:
It is not really required "to have single place that will have global version number, which then used for submodules." I belive that the correctly stated requirment should be: It's important that common version number for multiple modules can be easily changed. What if there were gui tool or maven plugin which will do the job for you? say you will do something like: m2 project:upgrade-version -Dversion=1.2 and maven will recursively upgrade the current version and parent's version in multiple POMs. Wouldn't it be simple enough? I would really prefer to change it manually in a single file, than ask a plugin (or whatever) to roam my workspace and update the poms.
I had bad experience with automated pom rewriting - last time I tried to use release plugin it messed up my pom beyound recognition. So unless a tool is written that can update pom selectively, while preserving element ordering and whitespace, I say: no thanks. having a plugin or gui tool is not really equivalent.
1. it needs to update the version plus the interdependencies as well 2. It assumes one always uses the tool to do the update of version. If one changes the version manually, then it breaks. That's not the case with version in one central place. ... but IMHO it's good enough. Heh. Somebody should teach those Eclipse guys... I usually have 3..5 ears at least on each J2EE application. I still don't think it would be a good idea to allow to specify relative paths. From other hand nothing stops you to create all Eclipse projects outside of default workspace and have them to use a common parent pom, which Eclipse won't see.
I'm also against the idea of having version rename tool. It will touch actually unchanged poms, which we are trying to avoid.
I want to mention that this proposed feature doesn't preclude doing exactly that with versions - maintaining a separate version for each subproject, and using a plugin to upgrade the version when you want.
However, I personally (and I think a few will agree) feel that falling back to tool support is sort of a crutch...that is, if this is a use case that we determine to be reasonably common, then the build should support it natively. In the case of an EAR, where the EAR is the distribution atom, that is where the versioning is applied, and versions of subprojects don't really have much meaning. If you're going to develop and release an EAR on a single cycle, then it also makes sense to version it all at once. If you're going to version the entire EAR at once, then it simply doesn't make sense to have multiple version specifications inside that EAR...it is duplication of a single piece of information, and will lead to synchronicity problems (one being updated but not another). WRT the the ../pom.xml file-path thing:
I can't believe I've missed this for so long, but there should be no reason that we cannot use the pom cache to lookup the groupId:artifactId from anywhere inside the scanned hierarchy (the reactorized project structure) and pull the version from the first ancestor that specifies it. If that parent doesn't exist in the scanned cache, then we fail with an error to checkout the rest of the project... This would help the Eclipse guys, since you could put your parent-pom in a project that is a sibling of the child-projects, and execute the build from the commen parent directory... HOWEVER, it seems that this whole approach of resolving the version without using a repository may cause problems for Continuum. In some cases, it might be desirable to add pieces of this type of project hierarchy to Continuum. If it doesn't checkout the whole project hierarchy, it cannot resolve the version of the parent - or the current project, I guess... my suggestions here:
This facilitates both the inherited and specified versions in subprojects in all scenarios, and the only possible inconsistency is checking out a project in isolation where it expects a POM from HEAD which is not in the repository. I would expect in this case to have CI taking care of publishing snapshots anyway. Note we are using SNAPSHOT, not RELEASE as this matches the "latest source code" more closely. The problem we will encounter is that this doesn't support branched development very well. I think we should work on that separately, and must come back to specifying an actual branch name rather than using the version to indicate it. We can do this in the 2.1 timeframe. When it comes time to produce a release, the release is run from the top level and everything is released together (the top level being the common base for tagging). If subprojects have their own release schedule then they will have their own trunk and tags and they will be released individually first (eg plugins). The release mojo needs to work in an aggregated fashion, so when run from the top it only tags once and then processes each subproject to update the POM (resolving the empty SNAPSHOT parent version to the published version which is shared, as well as any dependency references that match other projects in the reactor). Each subproject would then end up with the new version. The perform of the release would run its set of goals over each project in order from the tag as it does now. tweak last comment
For consistency will require that you specify the parent version and let the tools take care of updating it at release time. The matching version will still be located using the reactor and USD though. So: <parent> where parent has <version>1.2-SNAPSHOT</version> This facilitates branch development in the fashion that we have it now, though I still don't think it is sophisticated enough to do too much concurrent development. I'm thinking that you either version everything the same, or you release each independantly ok, where we got to with this:
I'm opening a new issue related to the release plugin refactor.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
However, for all the J2EE developers we support through Maven, I think it's worth talking about now.