assisted_workflow 0.1.0

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,2 @@
1
+ pkg/
2
+ .awconfig
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in assisted_workflow.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ assisted_workflow (0.1.0)
5
+ hashie (~> 2.0.5)
6
+ octokit (~> 2.0)
7
+ pivotal-tracker (~> 0.5.12)
8
+ thor (~> 0.18.1)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.3.5)
14
+ builder (3.2.2)
15
+ crack (0.4.1)
16
+ safe_yaml (~> 0.9.0)
17
+ faraday (0.8.8)
18
+ multipart-post (~> 1.2.0)
19
+ happymapper (0.4.1)
20
+ libxml-ruby (~> 2.0)
21
+ hashie (2.0.5)
22
+ libxml-ruby (2.7.0)
23
+ mime-types (2.0)
24
+ mini_portile (0.5.2)
25
+ multipart-post (1.2.0)
26
+ nokogiri (1.6.1)
27
+ mini_portile (~> 0.5.0)
28
+ nokogiri-happymapper (0.5.8)
29
+ nokogiri (~> 1.5)
30
+ octokit (2.7.0)
31
+ sawyer (~> 0.5.2)
32
+ pivotal-tracker (0.5.12)
33
+ builder
34
+ builder
35
+ crack
36
+ happymapper (>= 0.3.2)
37
+ nokogiri (>= 1.4.3)
38
+ nokogiri (>= 1.5.5)
39
+ nokogiri-happymapper (>= 0.5.4)
40
+ rest-client (~> 1.6.0)
41
+ rest-client (~> 1.6.0)
42
+ rest-client (1.6.7)
43
+ mime-types (>= 1.16)
44
+ safe_yaml (0.9.7)
45
+ sawyer (0.5.2)
46
+ addressable (~> 2.3.5)
47
+ faraday (~> 0.8, < 0.10)
48
+ thor (0.18.1)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ assisted_workflow!
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Flavio Granero
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ # Assisted Workflow (aw)
2
+
3
+ AW is a CLI tool to automate software development workflows based on github pull requests.
4
+
5
+ * [Github Workflow](http://scottchacon.com/2011/08/31/github-flow.html)
6
+
7
+ Here in [Inaka](http://inaka.net) we have the following workflow steps:
8
+
9
+ 1. Start a pivotal task, moving to a new git branch for the new feature/bug fix
10
+ 2. Commit the changes, pushing to a new remote branch
11
+ 3. Submit a pull-request, allowing other team member to review the code, and merge into master if everything is ok
12
+ 4. Finish the pivotal task, removing both local and remote feature branches
13
+ 5. Deploy master branch.
14
+
15
+ For more details, please read more about the [Inaka Workflow](https://github.com/inaka/inaka_corp/wiki/Inaka-Workflow).
16
+
17
+ This gem provides a command line tool to automate tasks related with `start`, `submit` and `finish` steps.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'assisted_workflow'
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install assisted_workflow
32
+
33
+ Or, if you are using homebrew and want to make `aw` system wide available, use brew-gem:
34
+
35
+ $ brew install brew-gem
36
+ $ brew gem assisted_workflow
37
+
38
+ ## Initial Setup
39
+
40
+ TODO: Write initial setup instructions here
41
+
42
+ ## Usage
43
+
44
+ TODO: Write usage instructions here
45
+
46
+ ##Requirements
47
+
48
+ `aw` assumes you're using an 'origin' remote. If you are not,
49
+ either add an 'origin' remote that points to the GitHub repository you want to submit pull requests.
50
+
51
+ ##Private repositories
52
+
53
+ To submit pull requests for your private repositories you have set up your `aw` config for github
54
+
55
+ $ aw config github.token=your_githubtoken123456789 --global
56
+
57
+ You must generate your OAuth token for command line use, see how to [generate oauth token](https://help.github.com/articles/creating-an-oauth-token-for-command-line-use).
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
66
+
67
+ ## To-do
68
+
69
+ 1. test coverage, travis-ci and codeclimate setup.
70
+ 2. add github issues support
71
+ 3. allow individual add-ons tasks like pivotal:start, github:submit, freckle:log
72
+
73
+ #### Inspiration
74
+
75
+ 1. https://github.com/ddollar/foreman
76
+ 2. https://github.com/github/hub
77
+ 3. https://github.com/schacon/git-pulls
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,97 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'assisted_workflow/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "assisted_workflow"
8
+ gem.version = AssistedWorkflow::VERSION
9
+ gem.authors = ["Flavio Granero"]
10
+ gem.email = ["maltempe@gmail.com"]
11
+ gem.summary = %q{AW is a CLI tool to automate software development workflows based on github pull requests}
12
+ gem.homepage = ""
13
+ gem.license = "MIT"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+ gem.executables = %w( aw )
20
+
21
+ gem.add_dependency "thor", "~> 0.18.1"
22
+ gem.add_dependency "pivotal-tracker", "~> 0.5.12"
23
+ gem.add_dependency "octokit", "~> 2.0"
24
+ gem.add_dependency "hashie", "~> 2.0.5"
25
+
26
+ gem.description = <<desc
27
+ `aw` is a command line tool to automate software development workflows based on github pull requests.
28
+
29
+ Initial Setup:
30
+
31
+ $ aw setup
32
+
33
+ Usage:
34
+
35
+ $ aw start
36
+
37
+ $ aw submit
38
+
39
+ $ aw finish
40
+
41
+ desc
42
+
43
+ gem.post_install_message = <<-message
44
+
45
+ `..::/++ooooooooo+/::--`
46
+ `-:://:---....```......--::///:-.`
47
+ `..-:::---.``` ```...----::-..`
48
+ `.:///-````` .-:++::-`
49
+ `///::` :/+oo:.` -:/+/-
50
+ ..-//. ....` `.-/+/`
51
+ :+/.` .-://.
52
+ ``/+: `.//-``
53
+ `::-.` `.---` ``` .-://`
54
+ `++` `:sso++/+hmy-.` .//-.`
55
+ `.-//` -++---:/+o/` ` ``:+:
56
+ .---- .:::-.````` .--::. :+/`
57
+ -::.. .:::-` `.-++-` :+/.`
58
+ -/:`` -++-.` `:/::- -/:-.
59
+ :/:` -oo-.` ``.--.` ``.-. -:-..
60
+ :/:` -++-.` ``.+ooo+/:+so. -:-..
61
+ :/:` -++:-` `.+o+++++oso. -:-..
62
+ -/:.` .::/+- `//:--//++/` -/:..
63
+ .---- `.+s/.` `-:. :+/.`
64
+ `.//` -:+ss:-. ``.:/oso++-` :+:
65
+ `//.`` .-:+++///++++///++++/:--`` ``:/:
66
+ .-::- ``--:::+ss+/:::----.`` `----.
67
+ `/+/` ../s+-.``` -//.``
68
+ .--++- .::.`.:/:-. .-+ys.
69
+ ``:hds++:::/:` .++-` .:/oo+//::-
70
+ ``+oo////+yds+/-.-//. .--/++++/:-``:/:``
71
+ `.oso--://sho+////+/-` ```...::/++++/::. -::--
72
+ ``.--:/:--:+/.`.:/shyss+:-..``````````.---::/+oso++/..-:://. .++.`
73
+ `:/:``:++++/-- -:/++++ooooooooooooooooo++:-.`` `-:/+/` --::-
74
+ `--`` `sdy/:. -:::-. ````````` -:/++-` `/o/`
75
+ `-. .-+o/`` .--//. .:///:.` -::..`
76
+ ``...` `:///- `.-++- `.:++::- .--:-.
77
+ .......:ss-`` `++:.` `.-+o/:- ./+-
78
+ `.::.`.:/.`` `.:o+.`` ``./++o+-`` `//-``
79
+ `+o. `-:+++//:::/++++:-.` -----
80
+ `++` ``--------::---.` `.-::
81
+ `//. `.....`` ``-++
82
+ `.//-...----------------..............----------------------------..---/oo
83
+
84
+
85
+ AW, Thanks!
86
+ ===========
87
+
88
+ Use the provided `aw` command-line tool to start a task creating a feature branch, submit a pull request with the changes and finish a task, keeping your repository clean. For more details, search for Inaka Workflow description.
89
+
90
+ Cheers,
91
+ Flavio
92
+
93
+ --------------------------------------------------------------------------------
94
+
95
+ message
96
+
97
+ end
data/bin/aw ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # resolve bin path, ignoring symlinks
5
+ require "pathname"
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ $:.unshift File.expand_path("../../lib", bin_file)
9
+
10
+ require "assisted_workflow/cli"
11
+
12
+ AssistedWorkflow::CLI.start
@@ -0,0 +1,158 @@
1
+ require "assisted_workflow"
2
+ require "yaml"
3
+ require "thor"
4
+
5
+ class AssistedWorkflow::CLI < Thor
6
+ include Thor::Actions
7
+ GLOBAL_CONFIG = File.expand_path(".awconfig", ENV["HOME"])
8
+ LOCAL_CONFIG = ".awconfig"
9
+ source_root(File.expand_path(File.join(__FILE__, "..", "templates")))
10
+
11
+ map ["-v", "--version"] => :version
12
+
13
+ desc "setup", "Setup initial configuration in current project directory"
14
+ def setup
15
+ copy_file "awconfig.global.tt", GLOBAL_CONFIG
16
+ copy_file "awconfig.local.tt", LOCAL_CONFIG
17
+ if File.exists?(".git")
18
+ copy_file "commit-msg.tt", ".git/hooks/commit-msg"
19
+ else
20
+ raise AssistedWorkflow::Error, ".git folder not found"
21
+ end
22
+ say "set your own configuration editing the .awconfig files or running:", :green
23
+ say "\t$ aw config pivotal.fullname='Flavio Granero' --global"
24
+ say "\t$ aw config pivotal.token=MYPIVOTALTOKEN --global"
25
+ say "\t$ aw config github.token=MYGITHUBOAUTHTOKEN --global"
26
+ say "\t$ aw config pivotal.project_id=00001"
27
+ end
28
+
29
+ desc "start [STORY_ID]", "Start the pivotal story and create a new branch to receive the changes"
30
+ def start(story_id=nil)
31
+ check_awfile!
32
+ story = pivotal.find_story(story_id)
33
+ if story.nil?
34
+ stories = pivotal.pending_stories
35
+ print_title "pending stories"
36
+ print_table(pivotal.display_values(stories))
37
+ say "start a story using:", :green
38
+ say "\t$ aw start [STORY_ID]"
39
+ else
40
+ say "creating the feature branch"
41
+ git.create_story_branch(story)
42
+ say "starting story: #{story.name}"
43
+ pivotal.start_story(story)
44
+ say "after commiting your changes, submit a pull request using:", :green
45
+ say "\t$ aw submit"
46
+ end
47
+ end
48
+
49
+ desc "submit", "Submits the current story creating a new pull request"
50
+ def submit
51
+ check_awfile!
52
+ story_id = git.current_story_id
53
+ say "loading story info"
54
+ story = pivotal.find_story(story_id)
55
+ if story
56
+ say "preparing local branch"
57
+ git.rebase_and_push
58
+ say "submiting the new pull request"
59
+ pr = github.create_pull_request(git.repository, git.current_branch, story)
60
+ say "finishing the story"
61
+ pivotal.finish_story(story)
62
+ say "new pull request: #{pr._links.html.href}", :yellow
63
+ say "after pull request approval, remove the feature branch using:", :green
64
+ say "\t$aw finish"
65
+ else
66
+ raise AssistedWorkflow::Error, "story not found, make sure a feature branch in active"
67
+ end
68
+ end
69
+
70
+ desc "finish", "Check if the changes are merged into master, removing the current feature branch"
71
+ def finish
72
+ check_awfile!
73
+ story_id = git.current_story_id
74
+ if story_id.to_i > 0
75
+ if git.is_merged?
76
+ say "removing local and remote feature branches"
77
+ git.remove_branch
78
+ say "well done! check your next stories using:", :green
79
+ say "\t$ aw start"
80
+ else
81
+ say "this branch is not merged into master yet", :yellow
82
+ end
83
+ else
84
+ raise AssistedWorkflow::Error, "story not found, make sure a feature branch in active"
85
+ end
86
+ end
87
+
88
+ desc "version", "Display assisted_workflow gem version"
89
+ def version
90
+ say AssistedWorkflow::VERSION
91
+ end
92
+
93
+ desc "config group.key=value", "Set configuration keys in local config file"
94
+ method_option :global, :type => :boolean, :aliases => "-g", :desc => "Set configuration key in global configuration file (for all projects)"
95
+ def config(*args)
96
+ if args.empty?
97
+ print_table configuration.to_hash
98
+ else
99
+ config_file.parse(args).save!
100
+ end
101
+ end
102
+
103
+ no_tasks do
104
+ def pivotal
105
+ @pivotal ||= AssistedWorkflow::Pivotal.new(configuration[:pivotal])
106
+ end
107
+
108
+ def git
109
+ @git ||= AssistedWorkflow::Git.new
110
+ end
111
+
112
+ def github
113
+ @github ||= AssistedWorkflow::Github.new(configuration[:github])
114
+ end
115
+
116
+ def config_file
117
+ @config_file ||= AssistedWorkflow::ConfigFile.new(awfile)
118
+ end
119
+
120
+ # loads all configuration, merging global and local values
121
+ def configuration
122
+ @configuration ||= begin
123
+ AssistedWorkflow::ConfigFile.new(GLOBAL_CONFIG).merge_file(LOCAL_CONFIG)
124
+ rescue TypeError
125
+ raise AssistedWorkflow::Error, "Error on loading .awconfig files. Please check the content format."
126
+ end
127
+ end
128
+ end
129
+
130
+ class << self
131
+ def start(given_args=ARGV, config={})
132
+ super
133
+ rescue AssistedWorkflow::Error => e
134
+ config[:shell].say e.message, :red
135
+ exit(1)
136
+ end
137
+ end
138
+
139
+ private ######################################################################
140
+
141
+ def print_title(title)
142
+ say "-" * title.length, :green
143
+ say title.upcase, :green
144
+ say "-" * title.length, :green
145
+ end
146
+
147
+ def check_awfile!
148
+ raise AssistedWorkflow::Error, "#{awfile} does not exist.\nmake sure you run `$ aw setup` in your project folder." unless File.exist?(awfile)
149
+ end
150
+
151
+ def awfile
152
+ case
153
+ when options[:awfile] then options[:awfile]
154
+ when options[:global] then GLOBAL_CONFIG
155
+ else LOCAL_CONFIG
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,60 @@
1
+ require "hashie"
2
+ require "yaml"
3
+
4
+ module AssistedWorkflow
5
+ # special hash class to allow configuration management
6
+ class ConfigHash < Hash
7
+ include Hashie::Extensions::MergeInitializer
8
+ include Hashie::Extensions::IndifferentAccess
9
+ include Hashie::Extensions::DeepMerge
10
+ end
11
+
12
+ # class providing methods to load, manage and save configuration files
13
+ class ConfigFile
14
+ # parse a command line arguments into configuration keys
15
+ # Example:
16
+ # pivotal.token=mypivotaltoken
17
+ # => {:pivotal => {:token => "mypivotaltoken"}}
18
+ def parse(args)
19
+ Array(args).each do |values|
20
+ keys, value = values.split("=")
21
+ keys.split(".").reverse.each do |k|
22
+ value = {k => value}
23
+ end
24
+ @hash.deep_merge!(value)
25
+ end
26
+ self
27
+ end
28
+
29
+ # dumps the configuration values to a file in yaml format
30
+ def save!
31
+ content = @hash.to_yaml
32
+ content.gsub! " !ruby/hash:AssistedWorkflow::ConfigHash", ""
33
+ File.open(@awfile, 'w'){ |f| f.write(content) }
34
+ end
35
+
36
+ def [](key)
37
+ @hash[key]
38
+ end
39
+
40
+ def to_hash
41
+ @hash.dup
42
+ end
43
+
44
+ # merges other config file into the current one
45
+ def merge_file(file)
46
+ other_config = ConfigFile.new(file)
47
+ @hash.deep_merge!(other_config.to_hash)
48
+ self
49
+ end
50
+
51
+ def initialize(awfile)
52
+ @awfile = awfile
53
+ @hash = if File.exists?(@awfile)
54
+ ConfigHash.new(::YAML::load_file(@awfile) || {})
55
+ else
56
+ ConfigHash.new
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ module AssistedWorkflow
2
+ class Error < StandardError
3
+ end
4
+ end
@@ -0,0 +1,93 @@
1
+ require "assisted_workflow/exceptions"
2
+
3
+ module AssistedWorkflow
4
+
5
+ class GitError < Error; end
6
+
7
+ class Git
8
+
9
+ DESCRIPTION_LIMIT = 30
10
+
11
+ # creates a new git branch based on story attributes
12
+ # the branch name format is:
13
+ # => story_onwer_username.story_id.story_name
14
+
15
+ def create_story_branch(story)
16
+ branch = branch_name(story)
17
+ git "checkout -b #{branch}"
18
+ # git "push --set-upstream origin #{branch}"
19
+ end
20
+
21
+ # run all the git steps required for a clean pull request
22
+ def rebase_and_push
23
+ check_everything_commited!
24
+ branch = current_branch
25
+ git "checkout master"
26
+ git "pull --rebase"
27
+ git "checkout #{branch}"
28
+ git "rebase master"
29
+ git "push -u -f origin #{branch}"
30
+ end
31
+
32
+ # returns the current story id based on branch name
33
+ def current_story_id
34
+ current_branch.split(".")[1]
35
+ end
36
+
37
+ # returns the current local branch name
38
+ def current_branch
39
+ git("rev-parse --abbrev-ref HEAD", :silent => true)
40
+ end
41
+
42
+ # returns the repository name assigned to origin following the format:
43
+ # owner/project
44
+ def repository
45
+ url = git("config --get remote.origin.url", :error => "cannot find 'origin' remote repository url")
46
+ url.gsub("git@github.com:", "").gsub("https://github.com/", "").gsub(/\.git$/, "").chomp
47
+ end
48
+
49
+ # check if current branch is merged into master
50
+ def is_merged?
51
+ check_everything_commited!
52
+ branch = current_branch
53
+ git "checkout master"
54
+ git "pull --rebase"
55
+ merged = git("branch --merged").include?(branch)
56
+ git "checkout #{branch}"
57
+ merged
58
+ end
59
+
60
+ # removes current branch and his remote version
61
+ def remove_branch
62
+ branch = current_branch
63
+ git "push origin :#{branch}"
64
+ git "checkout master"
65
+ git "branch -D #{branch}"
66
+ end
67
+
68
+ private
69
+
70
+ def git(command, options = {})
71
+ puts "git #{command}" unless options[:silent] == true
72
+ result = %x{git #{command}}.chomp
73
+ unless $? == 0
74
+ msg = ["git command error", options[:error]].compact.join(": ")
75
+ raise GitError, msg
76
+ end
77
+ result
78
+ end
79
+
80
+ def branch_name(story)
81
+ description = story.name.to_s.downcase.gsub(/\W/, "_").slice(0, DESCRIPTION_LIMIT)
82
+ [story.other_id, story.id, description].join(".").downcase
83
+ end
84
+
85
+ def not_commited_changes
86
+ git("status --porcelain", :silent => true).split("\n")
87
+ end
88
+
89
+ def check_everything_commited!
90
+ raise AssistedWorkflow::Error, "git: there are not commited changes" unless not_commited_changes.empty?
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,37 @@
1
+ require "assisted_workflow/exceptions"
2
+ require "octokit"
3
+
4
+ module AssistedWorkflow
5
+
6
+ class Github
7
+ def initialize(options)
8
+ validate_options!(options)
9
+ @client = Octokit::Client.new(:access_token => options["token"])
10
+ end
11
+
12
+ # creates a pull request using current branch changes
13
+ def create_pull_request(repo, branch, story)
14
+ base = "master"
15
+ title = "[##{story.id}] #{story.name}"
16
+ pull_request = @client.create_pull_request(repo, base, branch, title, story.description)
17
+ if pull_request.nil?
18
+ raise AssistedWorkflow::Error, "error on submiting the pull request"
19
+ else
20
+ pull_request
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def validate_options!(options)
27
+ if options.nil? || options.empty?
28
+ raise AssistedWorkflow::Error, "github missing configuration"
29
+ end
30
+ required_keys = %w(token)
31
+ missing_keys = required_keys - options.keys
32
+ if missing_keys.size > 0
33
+ raise AssistedWorkflow::Error, "github missing configuration: #{missing_keys.inspect}"
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,73 @@
1
+ require "assisted_workflow/exceptions"
2
+ require 'pivotal_tracker'
3
+
4
+ # wrapper class to pivotal api client
5
+ module AssistedWorkflow
6
+ class Pivotal
7
+
8
+ def initialize(options)
9
+ validate_options!(options)
10
+
11
+ PivotalTracker::Client.token = options["token"]
12
+ begin
13
+ @project = PivotalTracker::Project.find(options["project_id"])
14
+ rescue
15
+ raise AssistedWorkflow::Error, "pivotal project #{options["project_id"]} not found."
16
+ end
17
+ @fullname = options["fullname"]
18
+ @username = options["username"]
19
+ end
20
+
21
+ def find_story(story_id)
22
+ if story_id.to_i > 0
23
+ story = @project.stories.find(story_id)
24
+ story.other_id = @username || @fullname
25
+ story.other_id = story.other_id.to_s.downcase.split.join
26
+ story
27
+ end
28
+ end
29
+
30
+ def start_story(story)
31
+ story.update(:current_state => "started") if story
32
+ end
33
+
34
+ def finish_story(story)
35
+ story.update(:current_state => finished_state(story)) if story
36
+ end
37
+
38
+ def pending_stories
39
+ @project.stories.all(:state => "unstarted", :owned_by => @username, :limit => 5)
40
+ end
41
+
42
+ def display_values(stories)
43
+ stories.map do |story|
44
+ [story.id, story.name]
45
+ end
46
+ end
47
+
48
+ def valid?
49
+ @project.present?
50
+ end
51
+
52
+ private
53
+
54
+ def validate_options!(options)
55
+ if options.nil? || options.empty?
56
+ raise AssistedWorkflow::Error, "pivotal missing configuration"
57
+ end
58
+ required_keys = %w(fullname token project_id)
59
+ missing_keys = required_keys - options.keys
60
+ if missing_keys.size > 0
61
+ raise AssistedWorkflow::Error, "pivotal missing configuration: #{missing_keys.inspect}"
62
+ end
63
+ end
64
+
65
+ def finished_state(story)
66
+ if story.story_type == "chore"
67
+ "accepted"
68
+ else
69
+ "finished"
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,7 @@
1
+ ---
2
+ pivotal:
3
+ username:
4
+ fullname:
5
+ token:
6
+ github:
7
+ token:
@@ -0,0 +1,3 @@
1
+ ---
2
+ pivotal:
3
+ project_id:
@@ -0,0 +1,36 @@
1
+ #!/bin/sh
2
+ #
3
+ # This hook script will automatically add the Pivotal Tracker ID
4
+ # to the beginning of the git commit message (in the format of
5
+ # [#12345678]) if it is not already there.
6
+ #
7
+ # The script pulls the ID from the beginning of the branch name. If
8
+ # the branch name does not start with the Pivotal Tracker ID, then
9
+ # this script will do nothing.
10
+ #
11
+ # Specifying the Pivotal Tracker ID in the git commit message allows
12
+ # Pivotal to list all commits associated with a story when the
13
+ # story is viewed.
14
+ #
15
+ # To enable this script, copy it into your repo's .git/hooks directory.
16
+ #
17
+
18
+ COMMIT_MSG_FILE=$1
19
+ CURRENT_BRANCH=`git rev-parse --abbrev-ref HEAD`
20
+ TRACKER_ID=`echo $CURRENT_BRANCH | awk -F\. '{print $2}'`
21
+
22
+ # Make sure the branch name starts with what looks like a tracker ID
23
+ if [ "$TRACKER_ID" != "" ]; then
24
+
25
+ # If we could not find the tracker ID in the commit message in the
26
+ # proper format, then add it.
27
+ grep -q "\[#$TRACKER_ID\]" $COMMIT_MSG_FILE
28
+ if [ $? -eq 1 ]; then
29
+ sed "1s/^/[#$TRACKER_ID] /" $COMMIT_MSG_FILE > /tmp/tracker_git_commit_msg
30
+ mv /tmp/tracker_git_commit_msg $COMMIT_MSG_FILE
31
+ fi
32
+ fi
33
+
34
+ # Explicitly exit 0 to make sure we don't accidentally abort the commit
35
+ exit 0
36
+
@@ -0,0 +1,3 @@
1
+ module AssistedWorkflow
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require "assisted_workflow/version"
2
+ require "assisted_workflow/exceptions"
3
+
4
+ module AssistedWorkflow
5
+ autoload :Pivotal, "assisted_workflow/pivotal"
6
+ autoload :Git, "assisted_workflow/git"
7
+ autoload :Github, "assisted_workflow/github"
8
+ autoload :ConfigFile, "assisted_workflow/config_file"
9
+ end
metadata ADDED
@@ -0,0 +1,173 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: assisted_workflow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Flavio Granero
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.18.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 0.18.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: pivotal-tracker
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.5.12
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.5.12
46
+ - !ruby/object:Gem::Dependency
47
+ name: octokit
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: hashie
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 2.0.5
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.0.5
78
+ description: ! " `aw` is a command line tool to automate software development workflows
79
+ based on github pull requests.\n \n Initial Setup:\n \n $ aw setup\n\n Usage:\n\n
80
+ \ $ aw start\n \n $ aw submit\n \n $ aw finish\n \n"
81
+ email:
82
+ - maltempe@gmail.com
83
+ executables:
84
+ - aw
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - .gitignore
89
+ - Gemfile
90
+ - Gemfile.lock
91
+ - LICENSE.txt
92
+ - README.md
93
+ - Rakefile
94
+ - assisted_workflow.gemspec
95
+ - bin/aw
96
+ - lib/assisted_workflow.rb
97
+ - lib/assisted_workflow/cli.rb
98
+ - lib/assisted_workflow/config_file.rb
99
+ - lib/assisted_workflow/exceptions.rb
100
+ - lib/assisted_workflow/git.rb
101
+ - lib/assisted_workflow/github.rb
102
+ - lib/assisted_workflow/pivotal.rb
103
+ - lib/assisted_workflow/templates/awconfig.global.tt
104
+ - lib/assisted_workflow/templates/awconfig.local.tt
105
+ - lib/assisted_workflow/templates/commit-msg.tt
106
+ - lib/assisted_workflow/version.rb
107
+ homepage: ''
108
+ licenses:
109
+ - MIT
110
+ post_install_message: ! "\n `..::/++ooooooooo+/::--` \n
111
+ \ `-:://:---....```......--::///:-.` \n
112
+ \ `..-:::---.``` ```...----::-..` \n
113
+ \ `.:///-````` .-:++::-` \n
114
+ \ `///::` :/+oo:.` -:/+/- \n
115
+ \ ..-//. ....` `.-/+/` \n
116
+ \ :+/.` .-://. \n
117
+ \ ``/+: `.//-`` \n
118
+ \ `::-.` `.---` ``` .-://` \n
119
+ \ `++` `:sso++/+hmy-.` .//-.` \n
120
+ \ `.-//` -++---:/+o/` ` ``:+: \n
121
+ \ .---- .:::-.````` .--::. :+/` \n
122
+ \ -::.. .:::-` `.-++-` :+/.` \n
123
+ \ -/:`` -++-.` `:/::- -/:-. \n
124
+ \ :/:` -oo-.` ``.--.` ``.-. -:-.. \n
125
+ \ :/:` -++-.` ``.+ooo+/:+so. -:-.. \n
126
+ \ :/:` -++:-` `.+o+++++oso. -:-.. \n
127
+ \ -/:.` .::/+- `//:--//++/` -/:.. \n
128
+ \ .---- `.+s/.` `-:. :+/.` \n
129
+ \ `.//` -:+ss:-. ``.:/oso++-` :+: \n
130
+ \ `//.`` .-:+++///++++///++++/:--`` ``:/: \n
131
+ \ .-::- ``--:::+ss+/:::----.`` `----. \n
132
+ \ `/+/` ../s+-.``` -//.`` \n
133
+ \ .--++- .::.`.:/:-. .-+ys. \n
134
+ \ ``:hds++:::/:` .++-` .:/oo+//::- \n
135
+ \ ``+oo////+yds+/-.-//. .--/++++/:-``:/:`` \n
136
+ \ `.oso--://sho+////+/-` ```...::/++++/::. -::-- \n
137
+ \ ``.--:/:--:+/.`.:/shyss+:-..``````````.---::/+oso++/..-:://. .++.` \n
138
+ \ `:/:``:++++/-- -:/++++ooooooooooooooooo++:-.`` `-:/+/` --::- \n
139
+ \ `--`` `sdy/:. -:::-. ````````` -:/++-` `/o/` \n
140
+ \ `-. .-+o/`` .--//. .:///:.` -::..` \n``...`
141
+ `:///- `.-++- `.:++::- .--:-. \n.......:ss-``
142
+ \ `++:.` `.-+o/:- ./+- \n `.::.`.:/.``
143
+ \ `.:o+.`` ``./++o+-`` `//-``\n `+o.
144
+ \ `-:+++//:::/++++:-.` -----\n `++`
145
+ \ ``--------::---.` `.-::\n `//.
146
+ \ `.....`` ``-++\n `.//-...----------------..............----------------------------..---/oo\n\n\n
147
+ \ AW, Thanks!\n ===========\n\n Use the provided `aw` command-line
148
+ tool to start a task creating a feature branch, submit a pull request with the changes
149
+ and finish a task, keeping your repository clean. For more details, search for Inaka
150
+ Workflow description.\n\n Cheers,\n Flavio\n\n--------------------------------------------------------------------------------\n\n"
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 1.8.24
169
+ signing_key:
170
+ specification_version: 3
171
+ summary: AW is a CLI tool to automate software development workflows based on github
172
+ pull requests
173
+ test_files: []