Subversion/Maven changes in snapshot since last release - maven

I expect this is a common issue, but one I am not aware of a sensible solution to.
We have adopted the procedure where all local dependent modules are moved straight back to SNAPSHOT once the release has been done. Time passes and we come to do a new release.
When we come to release we need to make a decision on whether a particular module has had any changes or not. If not, we dont need to update release the dependent snapshot and we can simply build against the previous release version as nothing has changed.
The difficulty in this process is establishing whether anything has actually changed since the last release or not. The only way I can imagine establishing this is to look in the subversion logs to see if any significant change has been checked in since the last release, and if it has then we need to release the dependent module. If it hasnt, we are ok to use the previous released version. This seems very labour intensive to me.
Is there a plugin or a better way to achieve this?

Related

What are the consequences of always using Maven Snapshots?

I work with a small team that manages a large number of very small applications (~100 Portlets). Each portlet has its own git repository. During some code I was reviewing today, someone made a small edit, and then updated their pom.xml version from 1.88-SNAPSHOT to 1.89-SNAPSHOT. I added a comment asking if this is the best way to do releases, but I don't really know the negative consequences of doing this.
Why not do this? I know snapshots are not supposed to be releases, but why not? What are the consequences of using only snapshots? I know maven will not cache snapshots the same as non-snapshots, and so it may download the artifact every time, but let's pretend the caching doesn't matter. From a release-management perspective, why is using a SNAPSHOT version every time and just bumping the number a bad idea?
UPDATE:
Each of these projects results in a war file that will never be available on a maven repo outside of our team, so there are no downstream users.
The main reason for not wanting to do this is that the whole Maven eco-system relies on a specific definition of what a snapshot version is. And this definition is not the one you're setting in your question: it is only supposed to represent a version currently in active development, and it is not suppose to be a stable version. The consequence is that a lot of the tools built around Maven assumes this definition by default:
The maven-release-plugin will not let you prepare a release with a snapshot version as released version. So you'll need to resort to tagging by hand on your version control, or make your own scripts. This also means that the users of those libraries won't be able to use this plugin with default configuration, they'll need to set allowTimestampedSnapshots.
The versions-maven-plugin which can be used to automatically update to the latest release version won't work properly as well, so your users won't be able to use it without configuration pain.
Repository managers, like Artifactory or Nexus, comes built-in with a clear distinction of repositories hosting snapshot dependencies and release dependencies. For example, if you use shared Nexus company-wide, it could be configured to purge old snapshots so this would break things for you... Imagine someone depends on 1.88-SNAPSHOT and it is completely removed: you'll have to go back in time and redeploy it, until the next removal... Also, certain Artifactory internal repositories can be configured not to accept any snapshots, so you won't be able to deploy it there; the users will be forced, again, to add more repository configuration to point at those that do allow snapshots, which they may not want to do.
Maven is about convention before configuration, meaning that all Maven projects should try to share the same semantics (directory layout, versioning...). New developers that would access your project will be confused and lose time trying to understand why your project is build the way it is.
In the end, doing this will just cause more pain on the users and will not simplify a single thing for you. Probably, you could make it somewhat work, but when something is going to break (because of company policy, or some other future change), don't act surprised...
Tunaki gave a lot of reasonable points why you break Maven best practices, and I fully support that view. But even if you don't care about "conventions of other companies", there are reasons:
If you are not doing CI (and consider every build as potential release), you need to distinguish between versions which should go productive and those who are just for testing. If everything is SNAPSHOT, this is hard to do.
If someone (accidentally) deploys a second 1.88-SNAPSHOT, it will be the new 1.88-SNAPSHOT, hiding the old one (which is available by a concrete timestamp, but this is messy). Release versions cannot be deployed twice.

Can you elevate build in Release Management client for VS 2013?

This might be the wrong place to ask this because there's no actual code involved but I am running out of places I could seek help regarding this.
Previously I've been using Octopus where you can create a build and later push it to other environments like QA, UAT, Production etc.
I'm using Release manager now and I can't find such option. I was told the only way is to either push immediately to all environments and leave them pending until I'm ready to approve them (which is dangerous in case someone else approves the release prematurely)
Or I was told I would have to revert my code back to an earlier state, push a release to the environment I want and then move the code forward again.
This all sounds wrong and tedious to me and the Release manager documentation does not offer a clear answer. Ideally I want to make a release to one environment and at a later date elevate it to another.
If someone knows how it could be done, I would be very grateful.
Release Management supports this scenario.
You create a release path that consists of the environments you want to release to and the order you want to release to them. It also captures who is responsible for promoting a release between stages.
You then create a release template for a given build definition that will travel along that path. When you create a release for that release template, you choose what build from that build definition will be used.
When you trigger a release, it will go to the first stage in the release path, wait for approvals, then move on to the second stage, and so on.

Should I increase the version number in my project if a dependency changes?

Let's suppose I have a project called myLib-1.1.0. This project has a dependency on lib-dependency-1.2.3.
If there's a new version for this dependency and I need to use it, should I change my project version as well? No other modifications are made to myLib.
At the same time myLib is a dependency for various other projects. My main concern is the impact of a small change in a dependency might have upstream.
Yes. In maven, released versions are immutable. If you release 1.1.0 with a dependency to lib-dependency-1.2.3 then that's it.
If you change to depend on lib-dependency-1.2.4 then that's a new version. You should not redeploy 1.1.0 since some people might have already pulled that (supposedly immutable) 1.1.0.
So that means you need a different version, even if it's a just a new qualifier (myLib-1.1.0-RC-2 for example, but better just 1.1.1)
Maven doesn't recheck remote repos for release versions once it has it in the local repo, so if someone has 1.1.0 already locally, they will not get the new, fixed 1.1.0.
And about your rippling problem. Upstream projects should depend on the lowest acceptable released version. i.e. if the upstream project itself is ok with myLib-1.1.0 because it doesn't need (indirectly) lib-dependency-1.2.4 then it should stay with 1.1.0
Any code change that potentially affects the behavior should be given a new version number, in other words: anything that's not an absolute trivial change should be given a new version number. A changed dependency would definitely qualify for that because, unless you do a thorough code inspection of the dependency, you have no reason to assume that they only made absolute trivial changes.
Changes are often advertised as "small" (similar to being absolutely trivial as I call it above), but they hardly ever are. They may be negligible in someone's use case, but not in someone else's use case. I've even seen circumstances where there were only changes to Javadocs in a project that would break things down the line. (You could argue about how smart it is for someone to depend that strongly on Javadoc, but that's besides the point, isn't it?)
That is not to say that you can't accumulate changes and release a bunch of them as a single release. While accumulating, your project is in flux, and should have a ...-SNAPSHOT version. There should be no two versions of myLib-1.1.0 (without the -SNAPSHOT) that have even the least little change.
The fact that you're re-releasing your project also makes explicit the fact that regression testing and such should be redone to validate that it's still working with the changes in its dependency.

Is it possible to use the maven-release-plugin with a specific revision?

I am thinking about a deployment pipeline using SVN, Jenkins and Maven. At the moment I'm stuck at the point where I usually would call mvn release:perform on a working copy.
When thinking in deployment pipelines, I want to create a pipeline where every commit could be used to release a software to test/production. Let's say I have 5 builds, and I decide to release build 3 (with revision 3) to production. There will already be 2 new commits to trunk (which is now at revision 5).
Is it possible to use the maven-release-plugin to checkout/build/tag/commit a release at revision 3? When the maven-release-plugin finishes the release it usually commits the modified POMs to trunk.
I'm happy about any kind of information or advice here, so feel free to point me to books (like http://www.amazon.com/Continuous-Delivery-Deployment-Automation-Addison-Wesley/dp/0321601912), blog posts, Jenkins documentation... Maybe I'm completely on the wrong track.
By default, the release plugin creates the release based on the contents of your working copy, it just ensures that you don't have any uncommitted content before doing so. AFAIK it doesn't force an update of the sources, as that's usually the job of the Continuous Integration system (Jenkins in your case). So whatever is checked out by Jenkins will be released.
What you're trying to do sounds more like a configuration change on the Jenkins side, pointing it to the right revision.
On the other hand, if the POM files are modified as part of the release, but have been changed in SVN in the meantime, you will run into a conflict when Maven wants to check in the modified POM files. That's a situation that might happen, depending on how for back you want to go with the release.
Based on this, it might make more sense to always create a branch before doing a release. So you would create a branch based on revision 3 and then create your release in that branch. This way, you wouldn't run into issues with committing resources that have changed in more recent revisions.
Creating the branch and checking it out could probably be automated through Jenkins and Maven as well.
As far as I tested it, it is not possible.
More explicitely, as nwinler said, when you release, maven try to commit the modified pom. But, if it's an older revision than the current one, SVN will complain that your sources are not up to date. So it won't work. ... as far as I know.
You may read docs about promotion build. I don't find any one clear enough to be pointed out (in th few minutes of the writing of this message).

What's the most efficient way for a developer to switch between tasks?

I'm looking for a workflow-type description of the series of steps you perform to switch from one software development task to another. If a step involves a tool, please specify which tool and how it's used. The goal of the workflow is to have the smoothest possible transition from task #1 to task #2 and back to task #1.
Consider this scenario...
You're implementing a new user story and, while you've made progress so far today, it's not quite done and you haven't implemented your tests yet.
Your lead comes to you with a high priority bug that's blocking your test team. You need to stop what you're doing and get the bug fixed. The bug is in a build from three days ago, which is the most recent build the test team has picked up.
You can fix the bug in a new version of the sources, but it has to be a stable version and can't include the incomplete feature you're currently working on.
Alt + Tab is how we do it.
Task switching is a thing of the brain. I don't think there is a tool to do that for you. If there is, I am also interested.
Each person has its own way of preparing, some don't prepare at all and are in another thing like a snap, some take more time etc. It depends on the man/woman.
Sure, you can try to create some mental milestones (taking a note, place a reminder etc) to return to it when getting back to the task, but this again depends on other factors (how long was the task switch, how quiet the office, familiarity with the task, moon phases etc).
The most efficient way for a developer to switch between tasks I think is subjective.
Meanwhile, have you read the Human Task Switches Considered Harmful from Joel Spolsky?
I would say the steps you need to take in the scenario you describe are 100% dependent on the development environment and tools you have set up.
Using Perforce for source code version control, we have set up a branching system where the releases are separate from development work and all development branches stem from a single "acceptance" branch. Each branch is used for a single issue, or for a set of very closely related issues. No other issues can be worked on in a branch until the changes have been integrated up to the acceptance branch.
Yes, it does mean we have a lot of branches. Yes, we do a lot of syncing (acceptance down to a work branch) and integrating (work branch up to acceptance). But its worth is incalculable when it comes to easily switching from one task to another, going back to a test-built, spotting two issues biting each other, etc.
After development has done its thing (including their own tests), an issue is tested by the QA team. First in isolation in its own branch. After that is is integrated into the acceptance branch and a regression test is done to find any problems with independent issues biting each other. When all issues for a release have thus been integrated into acceptance, a full regression and new functionality test is executed by the QA team.
So, the acceptance branch is always the "latest" state of development for the app.
In this set up the scenario you describe would play out as:
Leave my current task as it is, possibly check in any outstanding changes so as not to lose them when my computer crashes. If that means breaking a daily build of that branch, I wouldn't check in, unless it is easy to fix the compile errors. (Please note that we have many apps in our application suite and while my changes may compile in the app I am working on, they may still break the compilation of other apps in our suite) Our rule is: each submit may break functionality, but must not break the build process.
Find an "empty" branch - a branch that is not currently being used for any development work, or, if all branches are taken, create a new one.
Force sync the acceptance branch and the selected work branch so my machine is guaranteed to have the latest state for both branches.
Synchronize (forced if necessary) the latest state of the acceptance branch to the work branch, so the selected work branch is the same as the acceptance branch.
Open up that branch's application suite in the IDE, debug and solve. Submit to the work branch.
Tell QA to have a look at it in the work branch. If they are satisfied with it, integrate the changes up to acceptance so they can continue their test.
Switch the IDE back to work on the application suite in the branch I was working on before.
Rinse and repeat.
Considering your scenario,
you could check out the stable version of sources in another working copy, correct the bug, commit.
When you come back to your incomplete work, do an update and continue to work.
When you're working on something you usually have a few ideas, few things you're planning to do, some stuff that is not clear and has to be solved later. It tends to get lost when you switch to other task.
I found it useful to write them down somewhere - take a brain snapshot. Later it's easier to restore it and get back faster to your original task.
I make a note of every file I'm working on inside of a Task/Todo item with a reminder in approx. the amount of time I will be away from it. Then I save and close each of those files to prevent them from distracting me/eliminate the clutter/create room for the new task on my desktop. I have the memory of a flea, so I need all the help I can get.

Resources