Author: toulmean
Date: Wed Jul 21 07:09:26 2010
New Revision: 966111
URL: http://svn.apache.org/viewvc?rev=966111&view=rev
Log:
fix for BUILDR-438, thanks to Alexis Midon
Added:
buildr/trunk/doc/releasing.textile
Modified:
buildr/trunk/CHANGELOG
buildr/trunk/doc/_layouts/default.html
buildr/trunk/lib/buildr/core/build.rb
buildr/trunk/spec/core/build_spec.rb
Modified: buildr/trunk/CHANGELOG
URL:
http://svn.apache.org/viewvc/buildr/trunk/CHANGELOG?rev=966111&r1=966110&r2=966111&view=diff
==============================================================================
--- buildr/trunk/CHANGELOG (original)
+++ buildr/trunk/CHANGELOG Wed Jul 21 07:09:26 2010
@@ -15,6 +15,7 @@
* Fixed: BUILDR-326 follow up: binary safe untarring on Windows (Sam Hendley)
* Fixed: BUILDR-342 The jruby gem installer invokes the removed
Gem.manage_gems function (Rhett Sutphin)
* Fixed: BUILDR-436 release task should only replace "-SNAPSHOT" (spec from
Jean-Philippe Caruana)
+* Fixed: BUILDR-438 Release Task: customizable version numbers (Alexis Midon)
* Fixed: BUILDR-464 Improve the versioning of Buildr (Rhett Sutphin)
* Fixed: BUILDR-466 Rendering issue with IE on the website (Shane Witbeck)
* Fixed: BUILDR-468 test:failed does not respect test.exclude
Modified: buildr/trunk/doc/_layouts/default.html
URL:
http://svn.apache.org/viewvc/buildr/trunk/doc/_layouts/default.html?rev=966111&r1=966110&r2=966111&view=diff
==============================================================================
--- buildr/trunk/doc/_layouts/default.html (original)
+++ buildr/trunk/doc/_layouts/default.html Wed Jul 21 07:09:26 2010
@@ -36,6 +36,7 @@
<li><a href='artifacts.html'>Artifacts</a></li>
<li><a href='packaging.html'>Packaging</a></li>
<li><a href='testing.html'>Testing</a></li>
+ <li><a href='releasing.html'>Releasing</a></li>
<li><a href='settings_profiles.html'>Settings/Profiles</a></li>
<li><a href='languages.html'>Languages</a></li>
<li><a href='more_stuff.html'>More Stuff</a></li>
Added: buildr/trunk/doc/releasing.textile
URL:
http://svn.apache.org/viewvc/buildr/trunk/doc/releasing.textile?rev=966111&view=auto
==============================================================================
--- buildr/trunk/doc/releasing.textile (added)
+++ buildr/trunk/doc/releasing.textile Wed Jul 21 07:09:26 2010
@@ -0,0 +1,116 @@
+---
+layout: default
+title: Releasing
+---
+
+Now that we built and test awesome software, let's the world know and release
it.
+
+
+Each buildile can specify the current version with a constant named
VERSION_NUMBER or THIS_VERSION.
+
+{% highlight ruby %}
+THIS_VERSION = "1.0.0-SNAPSHOT"
+
+define 'killer-app' do
+
+ project.version = THIS_VERSION
+
+ # ...
+end
+{% endhighlight %}
+
+
+h2(#default). What does a release do?
+
+The default behavior of the Release task is the following:
+# Check that the version to be released and the next version are different
+# Check that the project is being tracked by Git or Subversion
+# Package, test and deploy the artifacts using THIS_VERSION value minus the
'-SNAPSHOT' suffix (if any)
+# Tag the repository with the released version number
+# Update the value of THIS_VERSION in the buildfile with the next version
number
+
+Buildr will increment the last digit of the 3-digit versioni number if
THIS_VERSION contains '-SNAPSHOT'.
+So, at the end of a release, the buildfile now looks like this:
+
+{% highlight ruby %}
+THIS_VERSION = "1.0.1-SNAPSHOT"
+
+define 'killer-app' do
+
+ project.version = THIS_VERSION
+
+ # ...
+end
+{% endhighlight %}
+
+And the Git repository now contains two new commits and a new tag.
+
+{% highlight sh %}
+~/w/killer-app[master]$git ol -4
+c1af3d5 (HEAD, origin/master, master) Changed version number to 1.0.1-SNAPSHOT
+dd35015 (tag: 1.0.0) Changed version number to 1.0.0
+76c96e7 Last fix before the release
+{% endhighlight %}
+
+
+h2(#custom_version). How to specify my own version number scheme?
+
+If THIS_VERSION does not contain '-SNAPSHOT', Buildr delegates the resolution
of the next version number to the user which has 2 differents ways to express
her wishes: Release.next_version or the environment variable NEXT_VERSION.
+
+h3(#next_version_proc). Using Release.next_version
+
+The Release class can receive the next version of the buildfile. This could be
a string or a proc that would receive the current version and return the next
version.
+
+{% highlight ruby %}
+THIS_VERSION = "1.0.0-SNAPSHOT"
+
+# a string
+Release.next_version = "2.0.0-SNAPSHOT"
+
+# or a proc
+Release.next_version = lambda do |this_version| # 1.0.0-SNAPSHOT
+ new_version = this_version.split(/\./)
+ new_version[0] = new_version[0] + 1
+ new_version
+end
+
+define 'killer-app' do
+
+ project.version = THIS_VERSION
+
+ # ...
+end
+{% endhighlight %}
+
+
+h3(#next_version_envvar). Using the environment variable NEXT_VERSION
+
+If the environment variable NEXT_VERSION is set, Buildr will use this value to
update THIS_VERSION at the end of the release.
+
+For conveniency, this variable is case insensitive.
+
+So, all 3 following commands would generate the buildfile below:
+{% highlight sh %}
+$ buildr release next_version="1.0.0-rc1"
+$ env next_version="1.0.0-rc1" buildr release
+$ env NEXT_VERSION="1.0.0-rc1" buildr release
+{% endhighlight %}
+
+{% highlight ruby %}
+THIS_VERSION = "1.0.0-rc1"
+
+define 'killer-app' do
+
+ project.version = THIS_VERSION
+
+ # ...
+end
+{% endhighlight %}
+
+The environment variable NEXT_VERSION has precedence over Release.next_version.
+
+
+h2(#custom_tag_and_msg). How to specify my own tag name and commit message?
+
+As explained earlier, Buildr will create two new commits and a new tag in the
version control system. Similarly to Release.next_version, the commit message
and the tag name can be customized with Release.message and Release.tag_name.
Both could be strings or procs that would receive the released version i.i
THIS_VERSION without '-SNAPSHOT'.
+
Modified: buildr/trunk/lib/buildr/core/build.rb
URL:
http://svn.apache.org/viewvc/buildr/trunk/lib/buildr/core/build.rb?rev=966111&r1=966110&r2=966111&view=diff
==============================================================================
--- buildr/trunk/lib/buildr/core/build.rb (original)
+++ buildr/trunk/lib/buildr/core/build.rb Wed Jul 21 07:09:26 2010
@@ -239,6 +239,19 @@ module Buildr
# Release.commit_message = lambda { |ver| "Changed version number to
#{ver}" }
attr_accessor :commit_message
+ # Use this to specify the next version number to replace VERSION_NUMBER
with in the buildfile.
+ # You can set the next version or a proc that will be called with the
current version number.
+ # For example, with the following buildfile:
+ # THIS_VERSION = "1.0.0-rc1"
+ # Release.next_version = lambda { |version|
+ # version[-1] = version[-1].to_i + 1
+ # version
+ # }
+ #
+ # Release.next_version will return "1.0.0-rc2", so at the end of the
release, the buildfile will contain VERSION_NUMBER = "1.0.0-rc2"
+ #
+ attr_accessor :next_version
+
# :call-seq:
# add(MyReleaseClass)
#
@@ -270,6 +283,7 @@ module Buildr
#
# Make a release.
def make
+ @this_version = extract_version
check
with_release_candidate_version do |release_candidate_buildfile|
args = '-S', 'buildr', "_#{Buildr::VERSION}_", '--buildfile',
release_candidate_buildfile
@@ -278,11 +292,17 @@ module Buildr
ruby *args
end
tag_release resolve_tag
- update_version_to_next if @this_version != @new_version
+ update_version_to_next if this_version !=
resolve_next_version(this_version)
+ end
+
+ def check
+ if this_version == resolve_next_version(this_version) &&
this_version.match(/-SNAPSHOT$/)
+ fail "The next version can't be equal to the current version
#{this_version}.\nUpdate THIS_VERSION/VERSION_NUMBER, specify
Release.next_version or use NEXT_VERSION env var"
+ end
end
# :call-seq:
- # extract_version() => this_versin
+ # extract_version() => this_version
#
# Extract the current version number from the buildfile.
# Raise an error if not found.
@@ -304,8 +324,9 @@ module Buildr
end
protected
-
- attr_accessor :no_snapshot
+
+ # the initial value of THIS_VERSION
+ attr_accessor :this_version
# :call-seq:
# with_release_candidate_version() { |filename| ... }
@@ -325,9 +346,9 @@ module Buildr
def with_release_candidate_version
release_candidate_buildfile = Buildr.application.buildfile.to_s + '.next'
- release_candidate_buildfile_contents = change_version { |version|
- @no_snapshot = !version[-1].match(/-SNAPSHOT$/)
- version[-1] = version[-1].sub(/-SNAPSHOT$/, '') }
+ release_candidate_buildfile_contents = change_version { |version|
+ version.gsub(/-SNAPSHOT$/, "")
+ }
File.open(release_candidate_buildfile, 'w') { |file| file.write
release_candidate_buildfile_contents }
begin
yield release_candidate_buildfile
@@ -343,15 +364,13 @@ module Buildr
# Change version number in the current Buildfile, but without writing a
new file (yet).
# Returns the contents of the Buildfile with the modified version number.
#
- # This method yields to the block with the current (this) version number
as an array and expects
- # the block to update it.
+ # This method yields to the block with the current (this) version number
and expects
+ # the block to return the updated version.
def change_version
- @this_version = extract_version
- new_version = @this_version.split('.')
- yield(new_version)
- @new_version = new_version.join('.')
+ current_version = extract_version
+ new_version = yield(current_version)
buildfile = File.read(Buildr.application.buildfile.to_s)
- buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/,
%Q{"#...@new_version}"}) }
+ buildfile.gsub(THIS_VERSION_PATTERN) { |ver| ver.sub(/(["']).*\1/,
%Q{"#{new_version}"}) }
end
# Return the name of the tag to tag the release with.
@@ -362,17 +381,34 @@ module Buildr
tag
end
+ # Return the new value of THIS_VERSION based on the version passed.
+ #
+ # This method receives the existing value of THIS_VERSION
+ def resolve_next_version(current_version)
+ next_version = Release.next_version
+ next_version ||= lambda { |v|
+ snapshot = v.match(/-SNAPSHOT$/)
+ version = v.gsub(/-SNAPSHOT$/, "").split(/\./)
+ if snapshot
+ version[-1] = sprintf("%0#{version[-1].size}d", version[-1].to_i +
1) + '-SNAPSHOT'
+ end
+ version.join('.')
+ }
+ next_version = ENV['NEXT_VERSION'] if ENV['NEXT_VERSION']
+ next_version = ENV['next_version'] if ENV['next_version']
+ next_version = next_version.call(current_version) if Proc ===
next_version
+ next_version
+ end
+
# Move the version to next and save the updated buildfile
def update_buildfile
- buildfile = change_version { |version|
- unless no_snapshot
- version[-1] = sprintf("%0#{version[-1].size}d", version[-1].to_i +
1) + '-SNAPSHOT'
- end
+ buildfile = change_version { |version| # THIS_VERSION minus SNAPSHOT
+ resolve_next_version(this_version) # THIS_VERSION
}
File.open(Buildr.application.buildfile.to_s, 'w') { |file| file.write
buildfile }
end
- # Return the message to use to cimmit the buildfile with the next version
+ # Return the message to use to commit the buildfile with the next version
def message
version = extract_version
msg = Release.commit_message || "Changed version number to #{version}"
@@ -405,6 +441,7 @@ module Buildr
# 1. the repository is clean: no content staged or unstaged
# 2. some remote repositories are defined but the current branch does
not track any
def check
+ super
uncommitted = Git.uncommitted_files
fail "Uncommitted files violate the First Principle Of
Release!\n#{uncommitted.join("\n")}" unless uncommitted.empty?
fail "You are releasing from a local branch that does not track a
remote!" unless Git.remote
@@ -413,9 +450,11 @@ module Buildr
# Add a tag reference in .git/refs/tags and push it to the remote if any.
# If a tag with the same name already exists it will get deleted (in both
local and remote repositories).
def tag_release(tag)
- info "Committing buildfile with version number #{extract_version}"
- Git.commit File.basename(Buildr.application.buildfile.to_s), message
- Git.push if Git.remote
+ unless this_version == extract_version
+ info "Committing buildfile with version number #{extract_version}"
+ Git.commit File.basename(Buildr.application.buildfile.to_s), message
+ Git.push if Git.remote
+ end
info "Tagging release #{tag}"
Git.git 'tag', '-d', tag rescue nil
Git.git 'push', Git.remote, ":refs/tags/#{tag}" rescue nil if Git.remote
@@ -440,11 +479,14 @@ module Buildr
end
def check
+ super
fail "Uncommitted files violate the First Principle Of
Release!\n"+Svn.uncommitted_files.join("\n") unless Svn.uncommitted_files.empty?
fail "SVN URL must contain 'trunk' or 'branches/...'" unless
Svn.repo_url =~ /(trunk)|(branches.*)$/
end
def tag_release(tag)
+ # Unlike Git, committing the buildfile with the released version is not
necessary.
+ # svn tag does commit & tag.
info "Tagging release #{tag}"
Svn.tag tag
end
@@ -471,4 +513,4 @@ end
class Buildr::Project
include Buildr::Build
-end
+end
\ No newline at end of file
Modified: buildr/trunk/spec/core/build_spec.rb
URL:
http://svn.apache.org/viewvc/buildr/trunk/spec/core/build_spec.rb?rev=966111&r1=966110&r2=966111&view=diff
==============================================================================
--- buildr/trunk/spec/core/build_spec.rb (original)
+++ buildr/trunk/spec/core/build_spec.rb Wed Jul 21 07:09:26 2010
@@ -429,6 +429,138 @@ describe 'a release process', :shared=>t
end
end
+ describe '#resolve_next_version' do
+
+ it 'should increment the version number if SNAPSHOT' do
+ @release.send(:resolve_next_version, "1.0.0-SNAPSHOT").should ==
'1.0.1-SNAPSHOT'
+ end
+
+ it 'should NOT increment the version number if no SNAPSHOT' do
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0'
+ end
+
+ it 'should return the version specified by NEXT_VERSION env var' do
+ ENV['NEXT_VERSION'] = "version_from_env"
+ @release.send(:resolve_next_version, "1.0.0").should ==
'version_from_env'
+ end
+
+ it 'should return the version specified by next_version' do
+ Release.next_version = "ze_next_version"
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_next_version'
+ end
+
+ it 'should return the version specified by next_version if next_version is
a proc' do
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0++'
+ end
+
+ it "should return the version specified by 'NEXT_VERSION' env var even if
next_version is non nil" do
+ ENV['NEXT_VERSION'] = "ze_version_from_env"
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should ==
'ze_version_from_env'
+ end
+
+ it "should return the version specified by 'next_version' env var even if
next_version is non nil" do
+ ENV['NEXT_VERSION'] = nil
+ ENV['next_version'] = "ze_version_from_env_lowercase"
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should ==
'ze_version_from_env_lowercase'
+ end
+ after {
+ Release.next_version = nil
+ ENV['NEXT_VERSION'] = nil
+ ENV['next_version'] = nil
+ }
+ end
+
+ describe '#resolve_next_version' do
+
+ it 'should increment the version number if SNAPSHOT' do
+ @release.send(:resolve_next_version, "1.0.0-SNAPSHOT").should ==
'1.0.1-SNAPSHOT'
+ end
+
+ it 'should NOT increment the version number if no SNAPSHOT' do
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0'
+ end
+
+ it 'should return the version specified by NEXT_VERSION env var' do
+ ENV['NEXT_VERSION'] = "version_from_env"
+ @release.send(:resolve_next_version, "1.0.0").should ==
'version_from_env'
+ end
+
+ it 'should return the version specified by next_version' do
+ Release.next_version = "ze_next_version"
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_next_version'
+ end
+
+ it 'should return the version specified by next_version if next_version is
a proc' do
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0++'
+ end
+
+ it "should return the version specified by 'NEXT_VERSION' env var even if
next_version is non nil" do
+ ENV['NEXT_VERSION'] = "ze_version_from_env"
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should ==
'ze_version_from_env'
+ end
+
+ it "should return the version specified by 'next_version' env var even if
next_version is non nil" do
+ ENV['NEXT_VERSION'] = nil
+ ENV['next_version'] = "ze_version_from_env_lowercase"
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should ==
'ze_version_from_env_lowercase'
+ end
+ after {
+ Release.next_version = nil
+ ENV['NEXT_VERSION'] = nil
+ ENV['next_version'] = nil
+ }
+ end
+
+ describe '#resolve_next_version' do
+
+ it 'should increment the version number if SNAPSHOT' do
+ @release.send(:resolve_next_version, "1.0.0-SNAPSHOT").should ==
'1.0.1-SNAPSHOT'
+ end
+
+ it 'should NOT increment the version number if no SNAPSHOT' do
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0'
+ end
+
+ it 'should return the version specified by NEXT_VERSION env var' do
+ ENV['NEXT_VERSION'] = "version_from_env"
+ @release.send(:resolve_next_version, "1.0.0").should ==
'version_from_env'
+ end
+
+ it 'should return the version specified by next_version' do
+ Release.next_version = "ze_next_version"
+ @release.send(:resolve_next_version, "1.0.0").should == 'ze_next_version'
+ end
+
+ it 'should return the version specified by next_version if next_version is
a proc' do
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should == '1.0.0++'
+ end
+
+ it "should return the version specified by 'NEXT_VERSION' env var even if
next_version is non nil" do
+ ENV['NEXT_VERSION'] = "ze_version_from_env"
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should ==
'ze_version_from_env'
+ end
+
+ it "should return the version specified by 'next_version' env var even if
next_version is non nil" do
+ ENV['NEXT_VERSION'] = nil
+ ENV['next_version'] = "ze_version_from_env_lowercase"
+ Release.next_version = lambda {|version| "#{version}++"}
+ @release.send(:resolve_next_version, "1.0.0").should ==
'ze_version_from_env_lowercase'
+ end
+ after {
+ Release.next_version = nil
+ ENV['NEXT_VERSION'] = nil
+ ENV['next_version'] = nil
+ }
+ end
+
describe '#resolve_tag' do
before do
@release.stub!(:extract_version).and_return('1.0.0')
@@ -501,12 +633,14 @@ describe 'a release process', :shared=>t
describe '#update_version_to_next' do
before do
- write 'buildfile', 'THIS_VERSION = "1.0.0"'
+ write 'buildfile', "VERSION_NUMBER = '1.0.5-SNAPSHOT'"
+ @release.send(:this_version=, "1.0.5-SNAPSHOT")
end
it 'should update the buildfile with a new version number' do
@release.send :update_version_to_next
- file('buildfile').should contain('THIS_VERSION = "1.0.1-SNAPSHOT"')
+ `cp buildfile /tmp/out`
+ file('buildfile').should contain('VERSION_NUMBER = "1.0.6-SNAPSHOT"')
end
it 'should commit the new buildfile on the trunk' do
@@ -530,11 +664,19 @@ describe 'a release process', :shared=>t
end
it 'should inform the user of the new version' do
- lambda { @release.update_version_to_next }.should show_info('Current
version is now 1.0.1-SNAPSHOT')
+ lambda { @release.update_version_to_next }.should show_info('Current
version is now 1.0.6-SNAPSHOT')
end
after { Release.commit_message = nil }
end
+
+ describe '#check' do
+ before { @release.send(:this_version=, "1.0.0-SNAPSHOT") }
+ it 'should fail if THIS_VERSION equals the next_version' do
+ @release.stub!(:resolve_next_version).and_return('1.0.0-SNAPSHOT')
+ lambda { @release.check }.should raise_error("The next version can't be
equal to the current version 1.0.0-SNAPSHOT.\nUpdate
THIS_VERSION/VERSION_NUMBER, specify Release.next_version or use NEXT_VERSION
env var")
+ end
+ end
end
@@ -542,6 +684,7 @@ describe GitRelease do
it_should_behave_like 'a release process'
before do
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
@release = GitRelease.new
Git.stub!(:git)
Git.stub!(:current_branch).and_return('master')
@@ -561,9 +704,10 @@ describe GitRelease do
end
end
- describe '#release_check' do
+ describe '#check' do
before do
@release = GitRelease.new
+ @release.send(:this_version=, '1.0.0-SNAPSHOT')
end
it 'should accept a clean repository' do
@@ -638,6 +782,7 @@ describe SvnRelease do
it_should_behave_like 'a release process'
before do
+ write 'buildfile', "VERSION_NUMBER = '1.0.0-SNAPSHOT'"
@release = SvnRelease.new
Svn.stub!(:svn)
Svn.stub!(:repo_url).and_return('http://my.repo.org/foo/trunk')
@@ -659,6 +804,7 @@ describe SvnRelease do
before do
Svn.stub!(:uncommitted_files).and_return([])
@release = SvnRelease.new
+ @release.send(:this_version=, "1.0.0-SNAPSHOT")
end
it 'should accept to release from the trunk' do