git_pivotal_tracker 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create ruby-1.9.2-p180@git_pivotal_tracker
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in alder.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Ben Lindsey
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,101 @@
1
+ git-tracker
2
+ ===========
3
+
4
+ Inspired by [Hashrocket's blend of git and Pivotal Tracker](http://reinh.com/blog/2009/03/02/a-git-workflow-for-agile-teams.html) and [a popular article on effective git workflows](http://blog.carbonfive.com/2010/11/01/integrating-topic-branches-in-git/), I wanted to build a tool to simplify the workflow between the two.
5
+
6
+ It also includes a git prepare-commit-msg hook that appends the story id to all your commit messages from a topic branch:
7
+ [https://www.pivotaltracker.com/help/api?version=v3#github_hooks](https://www.pivotaltracker.com/help/api?version=v3#github_hooks)
8
+
9
+ Features
10
+ --------
11
+
12
+ * `git-story`
13
+ * `git-feature`
14
+ * `git-bug`
15
+ * `git-chore`
16
+
17
+ These commands collect the first available story from your Pivotal Tracker project and create a topic branch for it.
18
+
19
+ * `git-finish`
20
+
21
+ When on a topic branch, this command will fetch the latest integration branch ('master' by default), rebase your topic branch from it, merge the branch into the integration branch with no-fast-forword and push the integration branch to origin.
22
+
23
+ * `git-info`
24
+
25
+ Print out the Pivotal Tracker story information for the current topic branch
26
+
27
+ Examples
28
+ --------
29
+
30
+ FIXME (code sample of usage)
31
+
32
+ Requirements
33
+ ------------
34
+
35
+ * github
36
+ * tracker project
37
+ * github to tracker api integration turned on
38
+
39
+ Install
40
+ -------
41
+
42
+ * gem install git_pivotal_tracker
43
+
44
+ Once installed, git pivotal needs two bits of info: your Pivotal Tracker API Token and your Pivotal Tracker project id:
45
+
46
+ git config --global pivotal.api-token 123a456b
47
+
48
+ The project id is best placed within your project's git config:
49
+
50
+ git config -f .git/config pivotal.project-id 88888
51
+
52
+ If you prefer to merge back to a branch other than master when you've finished a story, you can configure that:
53
+
54
+ git config --global pivotal.integration-branch develop
55
+
56
+ If you prefer to fetch and rebase from origin before merging (default is no):
57
+
58
+ git config --global pivotal.rebase 1
59
+
60
+ If you prefer to fast-forward your merges into the integration branch (default is --no-ff):
61
+
62
+ git config --global pivotal.fast-forward 1
63
+
64
+ If your Pivotal Tracker user name is different than your git user name:
65
+
66
+ git config --global pivotal.full-name 'Ben Lindsey'
67
+
68
+ Author
69
+ ------
70
+
71
+ * Ben Lindsey <ben@carbonfive.com>
72
+
73
+ Acknowledgements
74
+ ------
75
+ * Inspired by [trydionel](https://github.com/trydionel/git-pivotal)
76
+
77
+ License
78
+ -------
79
+
80
+ (The MIT License)
81
+
82
+ Copyright (c) 2011 Ben Lindsey
83
+
84
+ Permission is hereby granted, free of charge, to any person obtaining
85
+ a copy of this software and associated documentation files (the
86
+ 'Software'), to deal in the Software without restriction, including
87
+ without limitation the rights to use, copy, modify, merge, publish,
88
+ distribute, sublicense, and/or sell copies of the Software, and to
89
+ permit persons to whom the Software is furnished to do so, subject to
90
+ the following conditions:
91
+
92
+ The above copyright notice and this permission notice shall be
93
+ included in all copies or substantial portions of the Software.
94
+
95
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
96
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
97
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
98
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
99
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
100
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
101
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/bin/git-bug ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'git_pivotal_tracker'
6
+
7
+ exit GitPivotalTracker::Bug.new(*ARGV).run!
data/bin/git-chore ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'git_pivotal_tracker'
6
+
7
+ exit GitPivotalTracker::Chore.new(*ARGV).run!
data/bin/git-feature ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'git_pivotal_tracker'
6
+
7
+ exit GitPivotalTracker::Feature.new(*ARGV).run!
data/bin/git-finish ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'git_pivotal_tracker'
6
+
7
+ exit GitPivotalTracker::Finish.new(*ARGV).run!
data/bin/git-info ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'git_pivotal_tracker'
6
+
7
+ exit GitPivotalTracker::Info.new(*ARGV).run!
data/bin/git-story ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
+
5
+ require 'git_pivotal_tracker'
6
+
7
+ exit GitPivotalTracker::Story.new(*ARGV).run!
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # vim: set syntax=ruby
3
+
4
+ branch = `git branch 2> /dev/null | grep -e ^* | awk '{print $2}'`
5
+ if branch =~ /-(\d{7,})-/
6
+ commit_msg = IO.read(ARGV[0])
7
+ unless commit_msg.include?($1)
8
+ File.open(ARGV[0], 'w') do |file|
9
+ file.print commit_msg
10
+ file.print "[##{$1}]"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib/', __FILE__)
3
+ $:.unshift lib unless $:.include?(lib)
4
+
5
+ require 'git_pivotal_tracker/version'
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "git_pivotal_tracker"
9
+ s.version = GitPivotalTracker::VERSION
10
+ s.platform = Gem::Platform::RUBY
11
+ s.authors = ["Ben Lindsey"]
12
+ s.email = ["ben@carbonfive.com"]
13
+ s.homepage = "https://github.com/blindsey/git_pivotal_tracker"
14
+ s.summary = "A git workflow integrated with Pivotal Tracker"
15
+ s.description = "git_pivotal_tracker provides a set of scripts that integrates directly with git to start and finish Pivotal Tracker stories on topic branches"
16
+
17
+ s.required_rubygems_version = ">= 1.3.6"
18
+
19
+ s.add_development_dependency "rspec"
20
+ s.add_runtime_dependency "grit"
21
+ s.add_runtime_dependency "pivotal-tracker"
22
+
23
+ s.files = `git ls-files`.split("\n")
24
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
25
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
26
+ s.require_paths = ['lib']
27
+ end
@@ -0,0 +1,92 @@
1
+ module GitPivotalTracker
2
+ class Base
3
+ GIT_DIR = ENV['GIT_DIR'] || '.git'
4
+
5
+ attr_reader :options, :repository
6
+
7
+ def initialize(*args)
8
+ directories = Dir.pwd.split(::File::SEPARATOR)
9
+ begin
10
+ break if File.directory?(File.join(*directories, GIT_DIR))
11
+ end while directories.pop
12
+
13
+ raise "No #{GIT_DIR} directory found" if directories.empty?
14
+ root = File.join(*directories, GIT_DIR)
15
+ @repository = Grit::Repo.new(root)
16
+
17
+ new_hook_path = File.join(*directories, GIT_DIR, 'hooks', 'prepare-commit-msg')
18
+ unless File.executable?(new_hook_path)
19
+ puts "Installing prepare-commit-msg hook..."
20
+ old_hook_path = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'prepare-commit-msg')
21
+ FileUtils.cp(old_hook_path, new_hook_path, :preserve => true)
22
+ end
23
+
24
+ @options = {}
25
+ parse_gitconfig
26
+ parse_argv(*args)
27
+ end
28
+
29
+ def run!
30
+ unless options[:api_token] && options[:project_id]
31
+ puts "Pivotal Tracker API Token and Project ID are required"
32
+ return 1
33
+ end
34
+
35
+ PivotalTracker::Client.token = options[:api_token]
36
+ nil
37
+ end
38
+
39
+ protected
40
+
41
+ def integration_branch
42
+ options[:integration_branch] || 'master'
43
+ end
44
+
45
+ def current_branch
46
+ @current_branch ||= repository.head.name
47
+ end
48
+
49
+ def story_id
50
+ @story_id ||= current_branch[/\d+/].to_i
51
+ end
52
+
53
+ def project
54
+ @project ||= PivotalTracker::Project.find(options[:project_id])
55
+ end
56
+
57
+ def story
58
+ @story ||= project.stories.find(story_id)
59
+ end
60
+
61
+ def log(message)
62
+ puts message if options[:verbose]
63
+ end
64
+
65
+ private
66
+
67
+ def parse_gitconfig
68
+ options[:api_token] = repository.config['pivotal.api-token']
69
+ options[:project_id] = repository.config['pivotal.project-id']
70
+ options[:integration_branch] = repository.config['pivotal.integration-branch']
71
+ options[:fast_forward] = repository.config['pivotal.fast-forward']
72
+ options[:rebase] = repository.config['pivotal.rebase']
73
+ options[:full_name] = repository.config['pivotal.full-name'] || repository.config['user.name']
74
+ options[:verbose] = repository.config['pivotal.verbose']
75
+ end
76
+
77
+ def parse_argv(*args)
78
+ OptionParser.new do |opts|
79
+ opts.banner = "Usage: git <feature|chore|bug> [options]"
80
+ opts.on("-k", "--api-key=", "Pivotal Tracker API key") { |k| options[:api_token] = k }
81
+ opts.on("-p", "--project-id=", "Pivotal Tracker project id") { |p| options[:project_id] = p }
82
+ opts.on("-b", "--integration-branch=", "The branch to merge finished stories back down onto") { |b| options[:integration_branch] = b }
83
+ opts.on("-f", "--fast-forward=", "Merge topic branch with fast forward") { |f| options[:fast_foward] = f }
84
+ opts.on("-n", "--full-name=", "Your Pivotal Tracker full name") { |n| options[:full_name] = n }
85
+ opts.on("-r", "--rebase=", "Fetch and rebase the integration branch before merging") { |r| options[:rebase] = r }
86
+ opts.on("-v", "--verbose=", "Verbose command logging") { |v| options[:verbose] = v }
87
+ opts.on_tail("-h", "--help", "This usage guide") { put opts.to_s; exit 0 }
88
+ end.parse!(args)
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,43 @@
1
+ module GitPivotalTracker
2
+ class Finish < Base
3
+
4
+ def run!
5
+ return 1 if super
6
+
7
+ unless story_id
8
+ put "Branch name must contain a Pivotal Tracker story id"
9
+ return 1
10
+ end
11
+
12
+ if options[:rebase]
13
+ puts "Fetching origin and rebasing #{current_branch}"
14
+ log repository.git.fetch({:raise => true}, "origin")
15
+ log repository.git.rebase({:raise => true}, "origin/#{integration_branch}")
16
+ end
17
+
18
+ puts "Merging #{current_branch} into #{integration_branch}"
19
+ log repository.git.checkout({:raise => true}, integration_branch)
20
+
21
+ flags = options[:fast_forward] ? {} : {:'no-ff' => true}
22
+ log repository.git.merge({:raise => true}.merge(flags), current_branch)
23
+
24
+ puts "Pushing #{integration_branch} to origin"
25
+ log repository.git.push({:raise => true}, "origin", integration_branch)
26
+
27
+ puts "Marking Story #{story_id} as finished..."
28
+ if story.update(:current_state => finished_state)
29
+ puts "Success"
30
+ return 0
31
+ else
32
+ puts "Unable to mark Story #{story_id} as finished"
33
+ return 1
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def finished_state
40
+ story.story_type == "chore" ? "accepted" : "finished"
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ module GitPivotalTracker
2
+ class Info < Base
3
+
4
+ def run!
5
+ return 1 if super
6
+
7
+ unless story_id
8
+ put "Branch name must contain a Pivotal Tracker story id"
9
+ return 1
10
+ end
11
+
12
+ puts "URL: #{story.url}"
13
+ puts "Story: #{story.name}"
14
+ puts "Description: #{story.description}"
15
+
16
+ return 0
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ module GitPivotalTracker
2
+ class Story < Base
3
+
4
+ def run!
5
+ return 1 if super
6
+
7
+ puts "Retrieving latest #{type} from Pivotal Tracker"
8
+
9
+ unless story = fetch_story
10
+ puts "No #{type} available!"
11
+ return 1
12
+ end
13
+
14
+ puts "URL: #{story.url}"
15
+ puts "Story: #{story.name}"
16
+
17
+ default_suffix = story.name.downcase.gsub(/\W+/, '_')
18
+ print "Enter branch name [#{default_suffix}]: "
19
+ suffix = gets.chomp
20
+ suffix = default_suffix if suffix == ""
21
+
22
+ branch = "#{story.story_type}-#{story.id}-#{suffix}"
23
+ puts "Checking out a new branch '#{branch}'"
24
+ log repository.git.checkout({:b => true, :raise => true}, branch)
25
+
26
+ puts "Updating #{type} status in Pivotal Tracker..."
27
+ if story.update(:owned_by => options[:name], :current_state => :started)
28
+ puts "Success"
29
+ return 0
30
+ else
31
+ puts "Unable to mark #{type} as started"
32
+ return 1
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def type
39
+ self.class.name.downcase.split(/::/).last
40
+ end
41
+
42
+ def fetch_story
43
+ # TODO: check for rejected stories as well
44
+ conditions = { :current_state => "unstarted", :limit => 1, :offset => 0 }
45
+ conditions[:story_type] = type unless type == 'story'
46
+ project.stories.all(conditions).first
47
+ end
48
+ end
49
+
50
+ class Bug < Story; end
51
+
52
+ class Feature < Story; end
53
+
54
+ class Chore < Story; end
55
+ end
@@ -0,0 +1,3 @@
1
+ module GitPivotalTracker
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'grit'
2
+ require 'pivotal-tracker'
3
+ require 'optparse'
4
+ require 'fileutils'
5
+
6
+ require 'git_pivotal_tracker/base'
7
+ require 'git_pivotal_tracker/story'
8
+ require 'git_pivotal_tracker/info'
9
+ require 'git_pivotal_tracker/finish'
@@ -0,0 +1,4 @@
1
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
2
+
3
+ describe GitPivotalTracker do
4
+ end
@@ -0,0 +1,12 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib git_pivotal_tracker]))
2
+
3
+ Spec::Runner.configure do |config|
4
+ # == Mock Framework
5
+ #
6
+ # RSpec uses it's own mocking framework by default. If you prefer to
7
+ # use mocha, flexmock or RR, uncomment the appropriate line:
8
+ #
9
+ # config.mock_with :mocha
10
+ # config.mock_with :flexmock
11
+ # config.mock_with :rr
12
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git_pivotal_tracker
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Ben Lindsey
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-07-13 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: grit
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: pivotal-tracker
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id003
49
+ description: git_pivotal_tracker provides a set of scripts that integrates directly with git to start and finish Pivotal Tracker stories on topic branches
50
+ email:
51
+ - ben@carbonfive.com
52
+ executables:
53
+ - git-bug
54
+ - git-chore
55
+ - git-feature
56
+ - git-finish
57
+ - git-info
58
+ - git-story
59
+ - prepare-commit-msg
60
+ extensions: []
61
+
62
+ extra_rdoc_files: []
63
+
64
+ files:
65
+ - .gitignore
66
+ - .rvmrc
67
+ - Gemfile
68
+ - LICENSE
69
+ - README.md
70
+ - Rakefile
71
+ - bin/git-bug
72
+ - bin/git-chore
73
+ - bin/git-feature
74
+ - bin/git-finish
75
+ - bin/git-info
76
+ - bin/git-story
77
+ - bin/prepare-commit-msg
78
+ - git_pivotal_tracker.gemspec
79
+ - lib/git_pivotal_tracker.rb
80
+ - lib/git_pivotal_tracker/base.rb
81
+ - lib/git_pivotal_tracker/finish.rb
82
+ - lib/git_pivotal_tracker/info.rb
83
+ - lib/git_pivotal_tracker/story.rb
84
+ - lib/git_pivotal_tracker/version.rb
85
+ - spec/git_pivotal_tracker_spec.rb
86
+ - spec/spec_helper.rb
87
+ has_rdoc: true
88
+ homepage: https://github.com/blindsey/git_pivotal_tracker
89
+ licenses: []
90
+
91
+ post_install_message:
92
+ rdoc_options: []
93
+
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: "0"
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 1.3.6
108
+ requirements: []
109
+
110
+ rubyforge_project:
111
+ rubygems_version: 1.6.2
112
+ signing_key:
113
+ specification_version: 3
114
+ summary: A git workflow integrated with Pivotal Tracker
115
+ test_files:
116
+ - spec/git_pivotal_tracker_spec.rb
117
+ - spec/spec_helper.rb