On 15 December 2014 at 01:29, Jason van Zyl <ja...@takari.io> wrote:
Hi,
The discussion keeps resurfacing about how we deal with failed releases
so
I'll summarize how I think it should ultimately be done as a starting
point.
I'll go over the cases we've encountered thus far:
1) The user case prefers non-disjunct sets of releases, or from our PoV
re-used versions. I believe people are confused by missing versions and
will always result in questions like "What happened to version X?",
where X
is a non-viable build. Not many people read release notes, will not
self-serve and it will just be a lot of questions and confusion. The
typical user doesn't care about the question of whether a particular
build
is viable or not. I think they naturally expect contiguous, increasing
versions when they update to new versions of a product.
I have not seen anyone asking what happened to 3.2.0
Similarly I have not seen anyone asking what happened to 3.1.2, 3.1.3,
3.1.4, 3.1.5, 3.1.6, 3.1.7, 3.1.8 or 3.1.9
And also nobody was visible to me about what exactly happened to
3.0.6-3.0.9 inclusive or the vast range of continuous numbers we skipped
before 3.0.0
I seem to recall a few questions about what da f*ck exactly was 2.0.10
and
was it newer than 2.0.4 but, you know what, our users are by and large
reasonably smart people, they can read an answer if we provide one, and
the
user community itself can probably sort out explaining where any missing
versions went, especially if we put the explanation on a page on our
website...
So this use case is, to my mind, not really relevant. I think we can
divide
our users into two large groups:
a. Those users who have a mandated version of maven that they must use
b. Those users who are happy to use the latest version of maven whatever
that is
There are other groups out there, but I believe that the above two groups
covers at least 80% of our users
A final point on the user community... if we treat our users like idiots,
then that's the kind of users we will get.
I don't know how the rest of you feel about our users, but I know that
our
users are by and large a reasonably smart group of people.
I just plain do not buy this argument about users expecting contiguous
increasing versions.
I think users expect us to actually cut releases on a reasonably frequent
basis and to fix things and generally not make things worse... and that
we
will have a page somewhere that is easy to find (probably called release
history) that will let them track down when the thing they care about
right
now changed so that they can either fix or roll-back to Get Things Done™
2) The tester case prefers new versions but has tolerated re-used
versions. Testers for core only really have to deal with the binary
distribution and if it gets thrown away there's not much chance of local
repository inconsistency because the typical tester, who is not an
integrator, isn't going to depend on the new core release for anything.
Running 3.2.4 doesn't put anything related to 3.2.4 in your local
repository.
This applies to core... but not so for testing plugins. We are not just a
project about core. If we decide on a policy it should be a policy that
works for both core and plugins.
One thing we always complain about is the lack of testing in areas where
our automated tests are weak.
To combat that we need to grow our pool of testers to include people from
the user community right now.
Those users may not be as comfortable ensuring that they have cleared out
their local repo of any side artifacts pulled in when testing a staged
release...
If they know that the artifact version number will never be re-used it
gives them a bit more confidence.
And this is not just about testing on your local machine, you might push
the changes to your CI server via a pull request and a pull request
builder
to get even better test coverage. Then you have to worry that the CI
server
will have some build slaves with old pre-release versions.
If we want to grow testing then I see re-use of versions a complete
no-no.
3) The integrator case prefers new versions. Different content with the
same version is a violation of our immutability philosophy and can cause
issues. Even though this is very much contained at the moment let's be
optimistic and believe we will have many integrators that will test
pre-released versions. Igor is right in that it's not fun to keep track
of
this and why should the burden be placed on the integrator. The answer
is
it shouldn't.
Again, from this use case I see re-use of versions as a complete no-no
also.
4) The release manager case prefers new versions.
When something is found wrong in 3.2.4 during voting, a user will create
an
issue in JIRA... found in 3.2.4... so we go and fix it... in 3.2.4...
that
just feels messy to me. I much rather say that an issue found in 3.2.4 is
fixed in a later version...
And before anyone asks, if the regression/issue was found in
3.2.4-SNAPSHOT
and we don't want to have -SNAPSHOT versions in JIRA then the
regression/issue gets fixed before the actual 3.2.4 gets released and the
JIRA issue needs to be reclassified...
* if it was a regression and we fix that before the regression gets
released, that's not a bug, and the issue should be marked as such and
should not show up on the release notes
* it it was something else then we should be documenting the new feature
via a JIRA
A final issue.
When you are running a release build, release:perform does not produce
idempotent artifacts.
Just take a look at virtually any random artifact produced by Maven:
$ unzip -c ~/Downloads/maven-dependency-tree-2.2.jar
META-INF/maven/org.apache.maven.shared/maven-dependency-tree/pom.properties
Archive: /Users/stephenc/Downloads/maven-dependency-tree-2.2.jar
inflating:
META-INF/maven/org.apache.maven.shared/maven-dependency-tree/pom.properties
#Generated by Maven
#Sun Sep 14 20:07:30 CEST 2014
version=2.2
groupId=org.apache.maven.shared
artifactId=maven-dependency-tree
Now that is just one file where the content is dependent on the date of
creation. We also have timestamps of different files that are in there
and
make each .jar file different... And that is before we even get as far as
which JDK was used to compile, etc.
A long long time ago I remember a project I was working on where we would
touch all the compiled binaries to have the last modified time of the
newest source that contributed to them (and the Makefile was one of those
sources too BTW) the result of this was that you could check out the code
on any machine (which would apply the source file timestamps) and rebuild
the artifact using the same toolchain and end up with the *exact same*
(bit
for bit) binary.
The JDK does not give us the tools to have that luxury, so I am not
saying
that we should try and reverse engineer a similar effect... rather
When I am releasing stuff and the release:perform goes wrong, as a
release
manager, I really just want to burn that version number and use a new
one.
Yes the staging repo is helpful, but I need to worry about my own local
repo having mixed builds... and this same worry crops up for those broken
builds that need `clean install` as preparationGoals... in fact its worse
for them because if they need `clean install` then likely they are
pulling
things out of order from the local repo and thus within my release
artifacts I may indeed have *equivalent* artifacts claiming to be the
same
release but not having a checksum match to the actual released artifacts.
I don't think a release manager only "prefers" new versions... I think a
much stronger word is needed ;-)
I have typically reused versions because I believe 1) is true. It's a
PITA
to erase tags, shuffle issues around in JIRA, and reset the POMs. I
would
prefer to just move forward, but I have done it because the user
confusion
is not worth the small effort it takes me to clean up a few resources.
One
hour for me versus thousands of hours of confusion for all users. It's
an
easy calculation.
Well I can agree with that calculation on the assumption that 1) is true.
I, however, believe 1) is actually false... and thus the trade-off to my
way of thinking is completely useless.
Taking all these cases into consideration so that all participants are
satisfied I think we ultimately want increasing and contiguous versions
for
users, testers and integrators while the release manager does not have
to
shuffle a bunch of resources around in the event of a non-viable build.
What we want is a form of continuous delivery where a version like
3.2.4 is
the version that we call it to the outside world (some refer to it as
the
marketing version) and the qualifier changes from build to build so we
have:
3.2.4-qualifier
And for simplicity's sake let's just say the qualifier is a build number
so we end up with:
3.2.4-01
3.2.4-02
...
3.2.4-NN
WHY WHY WHY
why don't we just use buildnumber? (other than users getting confused
about
is 3.2.6-12 before or after 3.2.6-7) we have it in our version spec
anyway
(i.e. if no leading 0 then it's a build number, if leading 0 then its a
qualifier)...
oh and any users that are confused by the missing 3.2.4 will be just as
confused by 3.2.6-03 with a missing 3.2.6-01 and 3.2.6-02
Every build is a complete build that can be released, and in the stream
of
builds that are produced we decide that one is good enough for public
consumption. Nothing in the issue tracking or documentation needs to
change
as it's still referred to as 3.2.4. People who download the distribution
aren't going to care what the exact versions say on the JARs but some
education might be required to tell people that something like 3.2.4 is
actually 3.2.4-05 if they want to refer to an artifact from 3.2.4. I
don't
think making aliases to the marketing versions are a good idea and
wouldn't
want to duplicate artifacts so that they can be referred to by the
marketing version.
Ahh, perhaps here is the argument for being able to skip version 3.2.4
only
now being applied to excuse skipping 3.2.6-01 and 3.2.6-02
People will just become accustom to knowing a qualifier is necessary to
find the actual version.
Or similarly people could just become accustomed to knowing that we skip
versions if we think they are no good... and we stick with our 3 part
version numbers
This is more how things work at Eclipse where if you look at something
from Jetty:
http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.eclipse.jetty%22%20AND%20a%3A%22jetty-servlet%22
You'll see that something like jetty-servlet 9.2.3 is actually referred
to
as 9.2.3.v20140905. Jetty seems somewhat inconsistent with respect to
milestones but you get the idea. I think this works for all parties but
especially users where say we all happen to write blog entries about
3.2.4
and it fails twice and we actually release 3.2.6. This is just so
confusing
as anything that referred to 3.2.4 now really means 3.2.6 which is
totally
inconsistent.
Seriously? Anyone who reads that something is available from 3.2.4 will
expect that to be present in 3.2.6... and who's going to pick up 3.2.4
when
3.2.6 is available (and should have more bug fixes, and the feature
should
be bedded down more, etc)
"People will just become accustomed to knowing" that if we say it's going
to be in 3.2.4 and then we release 3.2.6 then it's in 3.2.6
I think skipping failed versions from the users perspective like we are
currently doing is just a recipe for a massive amount of confusion and
wasted time.
Or maybe "People will just become accustomed"
Moving toward a stream based approach with a marketing version and
qualifiers for actual versions is really the only way it can work for
everyone.
Thanks,
Jason
----------------------------------------------------------
Jason van Zyl
Founder, Apache Maven
http://twitter.com/jvanzyl
http://twitter.com/takari_io
---------------------------------------------------------
To think is easy. To act is hard. But the hardest thing in the world is
to
act in accordance with your thinking.
-- Johann von Goethe