primedia-qa_release_tasks 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 PRIMEDIA
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ ==Summary
2
+
3
+ QA Release Management Workflow for Git
4
+
5
+ ==Authors
6
+
7
+ Jason Noble, Rein Henrichs
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rubygems/specification'
4
+ require 'date'
5
+ require 'spec/rake/spectask'
6
+
7
+ require 'lib/qa_release_tasks'
8
+
9
+ GEM = "qa_release_tasks"
10
+ GEM_VERSION = "0.1.1"
11
+ AUTHORS = "Jason Noble", "Rein Henrichs"
12
+ SUMMARY = "A gem that provides workflow driven rake tasks for git QA branch management"
13
+
14
+ spec = Gem::Specification.new do |s|
15
+ s.name = GEM
16
+ s.version = GEM_VERSION
17
+ s.platform = Gem::Platform::RUBY
18
+ s.has_rdoc = true
19
+ s.extra_rdoc_files = ["README.rdoc", "LICENSE"]
20
+ s.summary = SUMMARY
21
+ s.description = s.summary
22
+ s.authors = AUTHORS
23
+
24
+ s.require_path = 'lib'
25
+ s.autorequire = GEM
26
+ s.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("{lib,spec}/**/*")
27
+ end
28
+
29
+ task :default => :spec
30
+
31
+ desc "Run specs"
32
+ Spec::Rake::SpecTask.new do |t|
33
+ t.spec_files = FileList['spec/**/*_spec.rb']
34
+ t.spec_opts = %w(-fs --color)
35
+ end
36
+
37
+ Rake::GemPackageTask.new(spec) do |pkg|
38
+ pkg.gem_spec = spec
39
+ end
40
+
41
+ desc "install the gem locally"
42
+ task :install => [:package] do
43
+ sh %{sudo gem install pkg/#{GEM}-#{GEM_VERSION}}
44
+ end
45
+
46
+ desc "create a gemspec file"
47
+ task :make_spec do
48
+ File.open("#{GEM}.gemspec", "w") do |file|
49
+ file.puts spec.to_ruby
50
+ end
51
+ end
data/lib/cli.rb ADDED
@@ -0,0 +1,43 @@
1
+ module CLI
2
+ def warn(message)
3
+ STDERR.puts "*" * 50
4
+ STDERR.puts "Warning: #{message}"
5
+ STDERR.puts "*" * 50
6
+ end
7
+
8
+ def error(message)
9
+ STDERR.puts "*" * 50
10
+ STDERR.puts "Error: #{message}"
11
+ STDERR.puts "*" * 50
12
+ exit 1
13
+ end
14
+
15
+ def ask(question, default=nil, valid_response=nil, invalid_message=nil)
16
+ loop do
17
+ print "#{question}"
18
+ print " [#{default}]" if default
19
+ print ": "
20
+ answer = STDIN.gets.chomp
21
+ answer = default if default && answer.empty?
22
+ valid = false
23
+ valid = true if valid_response.nil?
24
+ valid = true if valid_response.respond_to?(:include?) && valid_response.include?(answer)
25
+ valid = true if valid_response.respond_to?(:match) && valid_response.match(answer)
26
+ if valid
27
+ return answer
28
+ else
29
+ if valid_response.is_a?(Array)
30
+ puts invalid_message || begin
31
+ print "Invalid answer, please try again."
32
+ print " Valid answers include:\n"
33
+ puts valid_response
34
+ end
35
+ elsif valid_response.is_a?(Regexp)
36
+ puts invalid_message || "Invalid format for answer, please try again."
37
+ else
38
+ puts invalid_message || "Invalid answer, please try again."
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,74 @@
1
+ module Git
2
+ module Commands
3
+
4
+ def assert_is_git_repo
5
+ error "Not a git repository" unless is_git_repo?
6
+ end
7
+
8
+ def is_git_repo?
9
+ File.directory?('.git')
10
+ end
11
+
12
+ # figure out what branch the pwd's repo is on
13
+ def get_branch
14
+ match = Regexp.new("^# On branch (.*)").match(`git status`)
15
+ match && match[1]
16
+ end
17
+
18
+ # e.g. v1.4.3
19
+ def valid_version_regexp
20
+ /^v\d+\.\d+\.\d+/
21
+ end
22
+
23
+ # Find all version tags
24
+ def get_tags
25
+ version_regexp = valid_version_regexp
26
+ %x{git tag}.split.grep(version_regexp).sort_by{|v| v.split('.').map{|nbr| nbr[/\d+/].to_i}}.map{|tag| tag.strip}
27
+ end
28
+
29
+ def next_version(options={})
30
+ latest_tag = get_tags.last
31
+ return 'v0.0.1' unless latest_tag
32
+
33
+ unless latest_tag.match valid_version_regexp
34
+ warn "invalid version number"
35
+ return latest_tag
36
+ end
37
+
38
+ major, minor, point = latest_tag.split('.')
39
+ major = major[1..-1]
40
+ if options[:major]
41
+ major.succ!
42
+ minor, point = '0', '0'
43
+ elsif options[:minor]
44
+ minor.succ!
45
+ point = '0'
46
+ elsif options[:point]
47
+ point.succ!
48
+ else
49
+ warn "unable to increment version number."
50
+ end
51
+
52
+ 'v' + [major, minor, point].join('.')
53
+ end
54
+
55
+ # based on 'git status' output, does this repo contain changes that need to be committed?
56
+ # optional second argument is a specific file (or directory) in the repo.
57
+ def needs_commit?(dir = Dir.pwd, file = nil)
58
+ rval = false
59
+ Dir.chdir(dir) do
60
+ status = %x{git status}
61
+ if file.nil?
62
+ rval = true unless status =~ /nothing to commit \(working directory clean\)|nothing added to commit but untracked files present/
63
+ if status =~ /nothing added to commit but untracked files present/
64
+ warn "untracked files present in #{dir}"
65
+ show_changed_files(status)
66
+ end
67
+ else
68
+ rval = true if status =~ /^#\t.*modified: #{file}/
69
+ end
70
+ end
71
+ rval
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,33 @@
1
+ module Git
2
+ class ReleaseNotes
3
+ require 'enumerator'
4
+ include CLI
5
+ include Commands
6
+
7
+ def annotate!
8
+ assert_is_git_repo
9
+ tags = get_tags.reverse
10
+ error "No version tags available." if tags.empty?
11
+
12
+ start_tag = ask "Start at which tag?", tags[0], tags
13
+ start_index = tags.index(start_tag)
14
+ end_tag = ask "End at which tag?", tags[start_index + 1] || tags[start_index], tags
15
+ puts
16
+ end_index = tags.index(end_tag) + 1 # include end tag
17
+
18
+ start_index.upto(end_index-1) do |i|
19
+ start = tags[i]
20
+ finish = tags[i+1]
21
+ range = ''
22
+ range << "refs/tags/#{finish}.." if finish # log until end tag if there is an end tag
23
+ range << "refs/tags/#{start}"
24
+ log = `git log --no-merges --pretty=format:"%h %s" #{range}`.strip
25
+ next if log.empty?
26
+ puts "#{start}"
27
+ puts "=" * start.length
28
+ puts log
29
+ puts
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/git/tagger.rb ADDED
@@ -0,0 +1,63 @@
1
+ module Git
2
+ class Tagger
3
+ include CLI
4
+ include Commands
5
+
6
+ attr_reader :options
7
+ def initialize(options)
8
+ @options = options
9
+ end
10
+
11
+ def tag!
12
+ assert_is_git_repo
13
+ begin
14
+ assert_on_qa_branch
15
+ assert_no_local_modifications
16
+ update_qa if options[:update]
17
+ tag_next_version(options)
18
+ git_push_tags
19
+ ensure
20
+ system 'git checkout qa_branch' unless get_branch == 'qa_branch'
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def assert_no_local_modifications
27
+ if needs_commit?
28
+ error "You have local modifications. Use git commit or git stash to fix that."
29
+ end
30
+ end
31
+
32
+ def assert_on_qa_branch
33
+ unless get_branch == 'qa_branch'
34
+ error "You have to be in the qa_branch to do a release."
35
+ end
36
+ end
37
+
38
+ def update_qa
39
+ system("git checkout master") &&
40
+ system("git pull") &&
41
+ system("git checkout qa_branch") &&
42
+ system("git pull") &&
43
+ response = %x(git merge master)
44
+
45
+ unless response.include?("Fast forward") || response.include?('Already up-to-date.')
46
+ warn "There are outstanding changes in qa_branch that may need to be merged into master"
47
+ end
48
+ end
49
+
50
+ def tag_next_version(options={})
51
+ tag = next_version(options)
52
+ if options[:update]
53
+ invalid_message = "Invalid version. Version must be in the format: \"v1.2.3\""
54
+ tag = ask "Name of new version tag ", tag, valid_version_regexp, invalid_message
55
+ end
56
+ system "git tag #{tag}"
57
+ end
58
+
59
+ def git_push_tags
60
+ system "git push --tags"
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,6 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ require 'cli'
3
+ require 'git/commands'
4
+ require 'git/release_notes'
5
+ require 'git/tagger'
6
+ require 'tasks/qa_release'
@@ -0,0 +1,18 @@
1
+ namespace :qa do
2
+ namespace :release do
3
+ desc "Create a new minor version release from master."
4
+ task :new do
5
+ Git::Tagger.new(:minor => true, :update => true).tag!
6
+ end
7
+
8
+ desc "Create a new point version release from qa branch."
9
+ task :update do
10
+ Git::Tagger.new(:point => true).tag!
11
+ end
12
+
13
+ desc "Add release notes for a given tag based on commit summaries"
14
+ task :notes do
15
+ Git::ReleaseNotes.new.annotate!
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ # Load rake file
5
+ import "#{File.dirname(__FILE__)}/qa_release.rake"
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "qa_release_tasks" do
4
+ it "should do nothing" do
5
+ true.should == true
6
+ end
7
+ end
@@ -0,0 +1,2 @@
1
+ $TESTING=true
2
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: primedia-qa_release_tasks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Jason Noble
8
+ - Rein Henrichs
9
+ autorequire: qa_release_tasks
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-04-01 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: A gem that provides workflow driven rake tasks for git QA branch management
18
+ email:
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README.rdoc
25
+ - LICENSE
26
+ files:
27
+ - LICENSE
28
+ - README.rdoc
29
+ - Rakefile
30
+ - lib/cli.rb
31
+ - lib/git
32
+ - lib/git/commands.rb
33
+ - lib/git/release_notes.rb
34
+ - lib/git/tagger.rb
35
+ - lib/qa_release_tasks.rb
36
+ - lib/tasks
37
+ - lib/tasks/qa_release.rake
38
+ - lib/tasks/qa_release.rb
39
+ - spec/qa_release_tasks_spec.rb
40
+ - spec/spec_helper.rb
41
+ has_rdoc: true
42
+ homepage:
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.2.0
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: A gem that provides workflow driven rake tasks for git QA branch management
67
+ test_files: []
68
+