assisted_workflow 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +7 -1
- data/README.md +41 -19
- data/Rakefile +7 -1
- data/assisted_workflow.gemspec +4 -0
- data/lib/assisted_workflow/cli.rb +22 -2
- data/lib/assisted_workflow/git.rb +16 -5
- data/lib/assisted_workflow/github.rb +10 -1
- data/lib/assisted_workflow/pivotal.rb +10 -20
- data/lib/assisted_workflow/version.rb +1 -1
- data/spec/assisted_workflow/config_file_spec.rb +42 -0
- data/spec/assisted_workflow/git_spec.rb +85 -0
- data/spec/assisted_workflow/github_spec.rb +48 -0
- data/spec/assisted_workflow/pivotal_spec.rb +104 -0
- data/spec/spec_helper.rb +31 -0
- metadata +68 -3
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
assisted_workflow (0.1.
|
4
|
+
assisted_workflow (0.1.3)
|
5
5
|
hashie (~> 2.0.5)
|
6
6
|
octokit (~> 2.0)
|
7
7
|
pivotal-tracker (~> 0.5.12)
|
@@ -14,6 +14,7 @@ GEM
|
|
14
14
|
builder (3.2.2)
|
15
15
|
crack (0.4.1)
|
16
16
|
safe_yaml (~> 0.9.0)
|
17
|
+
fakefs (0.5.0)
|
17
18
|
faraday (0.8.8)
|
18
19
|
multipart-post (~> 1.2.0)
|
19
20
|
happymapper (0.4.1)
|
@@ -39,8 +40,10 @@ GEM
|
|
39
40
|
nokogiri-happymapper (>= 0.5.4)
|
40
41
|
rest-client (~> 1.6.0)
|
41
42
|
rest-client (~> 1.6.0)
|
43
|
+
rake (10.1.1)
|
42
44
|
rest-client (1.6.7)
|
43
45
|
mime-types (>= 1.16)
|
46
|
+
rr (1.1.2)
|
44
47
|
safe_yaml (0.9.7)
|
45
48
|
sawyer (0.5.2)
|
46
49
|
addressable (~> 2.3.5)
|
@@ -52,3 +55,6 @@ PLATFORMS
|
|
52
55
|
|
53
56
|
DEPENDENCIES
|
54
57
|
assisted_workflow!
|
58
|
+
fakefs
|
59
|
+
rake
|
60
|
+
rr
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Assisted Workflow (aw)
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/assisted_workflow.png)](http://badge.fury.io/rb/assisted_workflow) [![Code Climate](https://codeclimate.com/github/flaviogranero/assisted_workflow.png)](https://codeclimate.com/github/flaviogranero/assisted_workflow)
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/assisted_workflow.png)](http://badge.fury.io/rb/assisted_workflow) [![Build Status](https://travis-ci.org/flaviogranero/assisted_workflow.png?branch=master)](https://travis-ci.org/flaviogranero/assisted_workflow) [![Code Climate](https://codeclimate.com/github/flaviogranero/assisted_workflow.png)](https://codeclimate.com/github/flaviogranero/assisted_workflow)
|
4
4
|
|
5
5
|
AW is a CLI tool to automate software development workflows based on github pull requests.
|
6
6
|
|
@@ -34,24 +34,53 @@ Or install it yourself as:
|
|
34
34
|
|
35
35
|
## Initial Setup
|
36
36
|
|
37
|
-
|
37
|
+
`assisted_worflow` uses `.awconfig` files to store your credentials and settings. When running the `setup` command, it will create a global config file placed in your home folder, and one config file specific for a project, inside the project folder. In order to start using it, go to your project folder and run:
|
38
|
+
|
39
|
+
$ aw setup
|
40
|
+
|
41
|
+
You need to run this command for all projects you want to use `assisted_worflow`.
|
42
|
+
|
43
|
+
If this is your initial setup, you need to inform your pivotal and github keys to allow api access. Do this using the config command:
|
44
|
+
|
45
|
+
$ aw config pivotal.fullname='Flavio Granero' --global
|
46
|
+
$ aw config pivotal.username='flavio' --global
|
47
|
+
$ aw config pivotal.token=MYPIVOTALTOKEN --global
|
48
|
+
$ aw config github.token=MYGITHUBOAUTHTOKEN --global
|
49
|
+
|
50
|
+
Note we're using the --global flag, to store this info in the global config file, valid for all projects. You can get your pivotal Api Token in your [profile page](https://www.pivotaltracker.com/profile) and the github api key [following the instructions to generate an oauth token](https://help.github.com/articles/creating-an-access-token-for-command-line-use).
|
51
|
+
|
52
|
+
After the global setup, you need to inform the pivotal project_id, storing it in the project .awconfig file:
|
53
|
+
|
54
|
+
$ aw config pivotal.project_id=00001
|
55
|
+
|
56
|
+
You may want to store the local .awconfig file into the project repository, preventing other users to run this setup step for every project.
|
38
57
|
|
39
58
|
## Usage
|
40
59
|
|
41
|
-
|
60
|
+
Having the setup step done, you are able to use the following commands to automate your workflow:
|
42
61
|
|
43
|
-
|
62
|
+
* __$ aw start__
|
44
63
|
|
45
|
-
|
46
|
-
|
64
|
+
List your next 5 pending stories in pivotal, showing a table with each story id, estimate and title. In order to include the already started stories in the list, run it with the `-a` flag.
|
65
|
+
|
66
|
+
* __$ aw start STORY_ID__
|
67
|
+
|
68
|
+
Find and mark a pivotal story as `started`, moving to a new git branch named with your pivotal username, story id and title. If the story is not estimated yet, you'll see an error message. You can set the estimate before starting it using the option `-e 3`, for instance.
|
69
|
+
|
70
|
+
* __$ aw submit__
|
47
71
|
|
48
|
-
|
72
|
+
Submit the current story branch, creating a new github pull request. Once you're done with the story changes and everything is commited, run submit command to rebase the feature branch with master and submit it, creating a new pull request. The pull request url will be added as a note in the pivotal story, marking it as `finished`.
|
73
|
+
|
74
|
+
* __$ aw finish__
|
49
75
|
|
50
|
-
|
76
|
+
Run finish command from a feature branch to check if the pull request has been merged into master, and to remove the local and remote branches safety.
|
77
|
+
|
78
|
+
There are shortcuts for these 3 main commands. Use __$ aw s__ to start, __$ aw u__ to submit and __$ aw f__ to finish a story.
|
51
79
|
|
52
|
-
|
80
|
+
##Requirements
|
53
81
|
|
54
|
-
|
82
|
+
`assisted_workflow` assumes you're using an 'origin' remote. If you are not,
|
83
|
+
either add an 'origin' remote that points to the GitHub repository you want to submit pull requests.
|
55
84
|
|
56
85
|
## Contributing
|
57
86
|
|
@@ -63,12 +92,5 @@ You must generate your OAuth token for command line use, see how to [generate oa
|
|
63
92
|
|
64
93
|
## To-do
|
65
94
|
|
66
|
-
1.
|
67
|
-
2.
|
68
|
-
3. allow individual add-ons tasks like pivotal:start, github:submit, freckle:log
|
69
|
-
|
70
|
-
#### Inspiration
|
71
|
-
|
72
|
-
1. https://github.com/ddollar/foreman
|
73
|
-
2. https://github.com/github/hub
|
74
|
-
3. https://github.com/schacon/git-pulls
|
95
|
+
1. add github issues support
|
96
|
+
2. refactor addons to a base class, with access to a shell output wrapper.
|
data/Rakefile
CHANGED
data/assisted_workflow.gemspec
CHANGED
@@ -18,6 +18,10 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
gem.executables = %w( aw )
|
20
20
|
|
21
|
+
gem.add_development_dependency "rake"
|
22
|
+
gem.add_development_dependency "rr"
|
23
|
+
gem.add_development_dependency "fakefs"
|
24
|
+
|
21
25
|
gem.add_dependency "thor", "~> 0.18.1"
|
22
26
|
gem.add_dependency "pivotal-tracker", "~> 0.5.12"
|
23
27
|
gem.add_dependency "octokit", "~> 2.0"
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require "assisted_workflow"
|
2
|
-
require "yaml"
|
3
2
|
require "thor"
|
4
3
|
|
5
4
|
class AssistedWorkflow::CLI < Thor
|
@@ -8,7 +7,11 @@ class AssistedWorkflow::CLI < Thor
|
|
8
7
|
LOCAL_CONFIG = ".awconfig"
|
9
8
|
source_root(File.expand_path(File.join(__FILE__, "..", "templates")))
|
10
9
|
|
10
|
+
# tasks shortcuts
|
11
11
|
map ["-v", "--version"] => :version
|
12
|
+
map "s" => :start
|
13
|
+
map "u" => :submit
|
14
|
+
map "f" => :finish
|
12
15
|
|
13
16
|
desc "setup", "Setup initial configuration in current project directory"
|
14
17
|
def setup
|
@@ -36,7 +39,7 @@ class AssistedWorkflow::CLI < Thor
|
|
36
39
|
if story.nil?
|
37
40
|
stories = pivotal.pending_stories(:include_started => options[:all])
|
38
41
|
print_title "pending stories"
|
39
|
-
|
42
|
+
print_stories(stories)
|
40
43
|
say "start a story using:", :green
|
41
44
|
say_command "$ aw start [STORY_ID]"
|
42
45
|
else
|
@@ -104,6 +107,12 @@ class AssistedWorkflow::CLI < Thor
|
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
110
|
+
desc "thanks", "Aw, Thanks!", :hide => true
|
111
|
+
def thanks
|
112
|
+
say "you're welcome!", :on_magenta
|
113
|
+
end
|
114
|
+
|
115
|
+
|
107
116
|
no_tasks do
|
108
117
|
def pivotal
|
109
118
|
@pivotal ||= AssistedWorkflow::Pivotal.new(configuration[:pivotal])
|
@@ -148,6 +157,17 @@ class AssistedWorkflow::CLI < Thor
|
|
148
157
|
say "-" * title.length, :green
|
149
158
|
end
|
150
159
|
|
160
|
+
def print_stories(stories)
|
161
|
+
rows = stories.map do |story|
|
162
|
+
if options[:all]
|
163
|
+
[story.id, story.current_state, story.name]
|
164
|
+
else
|
165
|
+
[story.id, story.estimate, story.name]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
print_table(rows)
|
169
|
+
end
|
170
|
+
|
151
171
|
def say_command(command)
|
152
172
|
with_padding do
|
153
173
|
say command
|
@@ -8,10 +8,13 @@ module AssistedWorkflow
|
|
8
8
|
|
9
9
|
DESCRIPTION_LIMIT = 30
|
10
10
|
|
11
|
+
def initialize(options = {})
|
12
|
+
@command_options = {:raise_error => true}.merge(options)
|
13
|
+
end
|
14
|
+
|
11
15
|
# creates a new git branch based on story attributes
|
12
16
|
# the branch name format is:
|
13
17
|
# => story_onwer_username.story_id.story_name
|
14
|
-
|
15
18
|
def create_story_branch(story)
|
16
19
|
branch = branch_name(story)
|
17
20
|
git "checkout -b #{branch}"
|
@@ -57,7 +60,7 @@ module AssistedWorkflow
|
|
57
60
|
merged
|
58
61
|
end
|
59
62
|
|
60
|
-
# removes current branch and
|
63
|
+
# removes current branch and its remote version
|
61
64
|
def remove_branch
|
62
65
|
branch = current_branch
|
63
66
|
git "push origin :#{branch}", :raise_error => false
|
@@ -68,16 +71,24 @@ module AssistedWorkflow
|
|
68
71
|
private
|
69
72
|
|
70
73
|
def git(command, options = {})
|
71
|
-
options =
|
74
|
+
options = @command_options.merge(options)
|
72
75
|
puts "git #{command}" unless options[:silent] == true
|
73
|
-
result =
|
74
|
-
if
|
76
|
+
result = system("git #{command}")
|
77
|
+
if system_error? && options[:raise_error]
|
75
78
|
msg = ["git command error", options[:error]].compact.join(": ")
|
76
79
|
raise GitError, msg
|
77
80
|
end
|
78
81
|
result
|
79
82
|
end
|
80
83
|
|
84
|
+
def system(command)
|
85
|
+
%x{command}.chomp
|
86
|
+
end
|
87
|
+
|
88
|
+
def system_error?
|
89
|
+
$? != 0
|
90
|
+
end
|
91
|
+
|
81
92
|
def branch_name(story)
|
82
93
|
description = story.name.to_s.downcase.gsub(/\W/, "_").slice(0, DESCRIPTION_LIMIT)
|
83
94
|
[story.other_id, story.id, description].join(".").downcase
|
@@ -9,7 +9,12 @@ module AssistedWorkflow
|
|
9
9
|
@client = Octokit::Client.new(:access_token => options["token"])
|
10
10
|
end
|
11
11
|
|
12
|
-
#
|
12
|
+
# Creates a pull request using current branch changes
|
13
|
+
#
|
14
|
+
# @param repo [String] Repository name. flaviogranero/assisted_workflow
|
15
|
+
# @param branch [String] Branch name. flavio.0001.new_feature
|
16
|
+
# @param story [Story] Pivotal story object
|
17
|
+
# @return [Sawyer::Resource] The newly created pull request
|
13
18
|
def create_pull_request(repo, branch, story)
|
14
19
|
base = "master"
|
15
20
|
title = "[##{story.id}] #{story.name}"
|
@@ -21,6 +26,10 @@ module AssistedWorkflow
|
|
21
26
|
end
|
22
27
|
end
|
23
28
|
|
29
|
+
def valid?
|
30
|
+
@client.user_authenticated?
|
31
|
+
end
|
32
|
+
|
24
33
|
private
|
25
34
|
|
26
35
|
def validate_options!(options)
|
@@ -40,29 +40,11 @@ module AssistedWorkflow
|
|
40
40
|
def pending_stories(options = {})
|
41
41
|
states = ["unstarted"]
|
42
42
|
states << "started" if options[:include_started]
|
43
|
-
@project.stories.all(:state => states, :owned_by => @
|
43
|
+
@project.stories.all(:state => states, :owned_by => @fullname, :limit => 5)
|
44
44
|
end
|
45
45
|
|
46
|
-
def update_story!(story, attributes)
|
47
|
-
if story
|
48
|
-
story.update(attributes)
|
49
|
-
raise AssistedWorkflow::Error, story.errors.first.to_s if story.errors.any?
|
50
|
-
true
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def display_values(stories, options = {})
|
55
|
-
stories.map do |story|
|
56
|
-
if options[:show_state]
|
57
|
-
[story.id, story.current_state, story.name]
|
58
|
-
else
|
59
|
-
[story.id, story.estimate, story.name]
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
46
|
def valid?
|
65
|
-
|
47
|
+
!@project.nil?
|
66
48
|
end
|
67
49
|
|
68
50
|
private
|
@@ -85,5 +67,13 @@ module AssistedWorkflow
|
|
85
67
|
"finished"
|
86
68
|
end
|
87
69
|
end
|
70
|
+
|
71
|
+
def update_story!(story, attributes)
|
72
|
+
if story
|
73
|
+
story.update(attributes)
|
74
|
+
raise AssistedWorkflow::Error, story.errors.first.to_s if story.errors.any?
|
75
|
+
true
|
76
|
+
end
|
77
|
+
end
|
88
78
|
end
|
89
79
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'assisted_workflow/config_file'
|
3
|
+
|
4
|
+
describe AssistedWorkflow::ConfigFile do
|
5
|
+
|
6
|
+
before do
|
7
|
+
FakeFS.activate!
|
8
|
+
FakeFS::FileSystem.clear
|
9
|
+
@config_file = AssistedWorkflow::ConfigFile.new(".awconfig")
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
FakeFS.deactivate!
|
14
|
+
FakeFS::FileSystem.clear
|
15
|
+
end
|
16
|
+
|
17
|
+
it "parses new configuration" do
|
18
|
+
@config_file.parse ["pivotal.token=mypivotaltoken",
|
19
|
+
"github.user=flaviogranero"]
|
20
|
+
@config_file[:pivotal][:token].must_match /mypivotaltoken/
|
21
|
+
@config_file[:github][:user].must_match /flaviogranero/
|
22
|
+
end
|
23
|
+
|
24
|
+
it "stores and loads config values" do
|
25
|
+
@config_file.parse "pivotal.token=mypivotaltoken"
|
26
|
+
@config_file.save!
|
27
|
+
config = AssistedWorkflow::ConfigFile.new(".awconfig")
|
28
|
+
config[:pivotal][:token].must_match /mypivotaltoken/
|
29
|
+
end
|
30
|
+
|
31
|
+
it "merges 2 configuration files" do
|
32
|
+
@config_file.parse "pivotal.token=mypivotaltoken"
|
33
|
+
@config_file.save!
|
34
|
+
|
35
|
+
config = AssistedWorkflow::ConfigFile.new(".awconfig2")
|
36
|
+
config.parse "github.user=flaviogranero"
|
37
|
+
config.merge_file(".awconfig")
|
38
|
+
|
39
|
+
config[:pivotal][:token].must_match /mypivotaltoken/
|
40
|
+
config[:github][:user].must_match /flaviogranero/
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'assisted_workflow/git'
|
3
|
+
|
4
|
+
describe AssistedWorkflow::Git do
|
5
|
+
before do
|
6
|
+
@git = AssistedWorkflow::Git.new(:silent => true)
|
7
|
+
stub(@git).system_error?{ false }
|
8
|
+
stub(@git).system("git rev-parse --abbrev-ref HEAD"){ "flavio.00001.new_feature"}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "creates a story branch" do
|
12
|
+
mock(@git).system("git checkout -b flavio.00001.new_feature")
|
13
|
+
@git.create_story_branch(story)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "raises a git error when git command does not exit with success" do
|
17
|
+
mock(@git).system_error?{ true }
|
18
|
+
mock(@git).system("git checkout -b flavio.00001.new_feature")
|
19
|
+
proc { @git.create_story_branch(story) }.must_raise AssistedWorkflow::GitError, "git command error"
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
it "rebases and push a feature branch" do
|
24
|
+
mock(@git).system("git status --porcelain"){ "" }
|
25
|
+
mock(@git).system("git checkout master")
|
26
|
+
mock(@git).system("git pull --rebase")
|
27
|
+
mock(@git).system("git checkout flavio.00001.new_feature")
|
28
|
+
mock(@git).system("git rebase master")
|
29
|
+
mock(@git).system("git push -u -f origin flavio.00001.new_feature")
|
30
|
+
@git.rebase_and_push
|
31
|
+
end
|
32
|
+
|
33
|
+
it "raises when rebasing if there are not commited changes" do
|
34
|
+
mock(@git).system("git status --porcelain"){ "changed_file.rb" }
|
35
|
+
proc {
|
36
|
+
@git.rebase_and_push
|
37
|
+
}.must_raise AssistedWorkflow::Error, "git: there are not commited changes"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the story_id from branch name" do
|
41
|
+
@git.current_story_id.must_equal "00001"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "return the current branch name" do
|
45
|
+
@git.current_branch.must_equal "flavio.00001.new_feature"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns the repository name assigned to origin" do
|
49
|
+
mock(@git).system("git config --get remote.origin.url"){ "git@github.com:flaviogranero/assisted_workflow.git"}
|
50
|
+
@git.repository.must_equal "flaviogranero/assisted_workflow"
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#is_merged?" do
|
54
|
+
|
55
|
+
before do
|
56
|
+
mock(@git).system("git status --porcelain"){ "" }
|
57
|
+
mock(@git).system("git checkout flavio.00001.new_feature")
|
58
|
+
mock(@git).system("git checkout master")
|
59
|
+
mock(@git).system("git pull --rebase")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "returns true if current branch is merged into master" do
|
63
|
+
mock(@git).system("git branch --merged"){ "flavio.00001.new_feature" }
|
64
|
+
@git.is_merged?.must_equal true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns false if current branch is not merged into master" do
|
68
|
+
mock(@git).system("git branch --merged"){ "flavio.00002.other_feature" }
|
69
|
+
@git.is_merged?.must_equal false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
it "removes current branch and its remote version" do
|
74
|
+
mock(@git).system("git push origin :flavio.00001.new_feature")
|
75
|
+
mock(@git).system("git checkout master")
|
76
|
+
mock(@git).system("git branch -D flavio.00001.new_feature")
|
77
|
+
@git.remove_branch
|
78
|
+
end
|
79
|
+
|
80
|
+
private #==================================================================
|
81
|
+
|
82
|
+
def story
|
83
|
+
@story ||= PivotalTracker::Story.new(:id => "00001", :name => "New Feature", :description => "Feature description", :other_id => "flavio")
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'assisted_workflow/github'
|
3
|
+
|
4
|
+
describe AssistedWorkflow::Github do
|
5
|
+
before do
|
6
|
+
@configuration = {
|
7
|
+
"token" => "mygithubtoken",
|
8
|
+
}
|
9
|
+
# stubs
|
10
|
+
@client = Object.new
|
11
|
+
stub(@client).user_authenticated?{ true }
|
12
|
+
stub(Octokit::Client).new{ @client }
|
13
|
+
|
14
|
+
@github = AssistedWorkflow::Github.new(@configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "initializes a valid github wrapper" do
|
18
|
+
assert @github.valid?
|
19
|
+
end
|
20
|
+
|
21
|
+
it "requires token" do
|
22
|
+
proc {
|
23
|
+
AssistedWorkflow::Github.new({})
|
24
|
+
}.must_raise AssistedWorkflow::Error, "github missing configuration:[token]"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "creates a new valid pull request" do
|
28
|
+
mock(@client).create_pull_request("flaviogranero/assisted_workflow", "master", "flavio.00001.new_feature", "[#00001] New Feature", "Feature description"){ true }
|
29
|
+
@github.create_pull_request(
|
30
|
+
"flaviogranero/assisted_workflow", "flavio.00001.new_feature", story
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "raises on creating an invalid pull request" do
|
35
|
+
mock(@client).create_pull_request("flaviogranero/invalid_repo", "master", "flavio.00001.new_feature", "[#00001] New Feature", "Feature description"){ nil }
|
36
|
+
proc {
|
37
|
+
@github.create_pull_request(
|
38
|
+
"flaviogranero/invalid_repo", "flavio.00001.new_feature", story
|
39
|
+
)
|
40
|
+
}.must_raise AssistedWorkflow::Error, "error on submiting the pull request"
|
41
|
+
end
|
42
|
+
|
43
|
+
private #==================================================================
|
44
|
+
|
45
|
+
def story
|
46
|
+
@story ||= PivotalTracker::Story.new(:id => "00001", :name => "New Feature", :description => "Feature description")
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'assisted_workflow/pivotal'
|
3
|
+
|
4
|
+
describe AssistedWorkflow::Pivotal do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@configuration = {
|
8
|
+
"token" => "mypivotaltoken",
|
9
|
+
"project_id" => "1",
|
10
|
+
"username" => "flavio",
|
11
|
+
"fullname" => "Flavio Granero"
|
12
|
+
}
|
13
|
+
# stubs
|
14
|
+
@project = PivotalTracker::Project.new(:id => "1")
|
15
|
+
stub(PivotalTracker::Project).find(@configuration["project_id"]){ @project }
|
16
|
+
|
17
|
+
@pivotal = AssistedWorkflow::Pivotal.new(@configuration)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "initializes a valid pivotal wrapper" do
|
21
|
+
assert @pivotal.valid?
|
22
|
+
end
|
23
|
+
|
24
|
+
it "requires fullname" do
|
25
|
+
proc {
|
26
|
+
AssistedWorkflow::Pivotal.new(
|
27
|
+
@configuration.reject{|k,v| k == "fullname"}
|
28
|
+
)
|
29
|
+
}.must_raise AssistedWorkflow::Error, "pivotal missing configuration:[fullname]"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "requires token" do
|
33
|
+
proc {
|
34
|
+
AssistedWorkflow::Pivotal.new(
|
35
|
+
@configuration.reject{|k,v| k == "token"}
|
36
|
+
)
|
37
|
+
}.must_raise AssistedWorkflow::Error, "pivotal missing configuration:[token]"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "requires project_id" do
|
41
|
+
proc {
|
42
|
+
AssistedWorkflow::Pivotal.new(
|
43
|
+
@configuration.reject{|k,v| k == "project_id"}
|
44
|
+
)
|
45
|
+
}.must_raise AssistedWorkflow::Error, "pivotal missing configuration:[project_id]"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "finds a story by id" do
|
49
|
+
mock(PivotalTracker::Story).find("100001", @project.id) do |story_id, project_id|
|
50
|
+
story_stub(:id => story_id, :project_id => project_id)
|
51
|
+
end
|
52
|
+
|
53
|
+
story = @pivotal.find_story("100001")
|
54
|
+
story.id.must_equal "100001"
|
55
|
+
story.other_id.must_match /flavio/
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns pending stories" do
|
59
|
+
mock(PivotalTracker::Story).all(@project, :state => ["unstarted", "started"], :owned_by => @configuration["fullname"], :limit => 5) do |project|
|
60
|
+
[
|
61
|
+
story_stub(:id => "100001", :project_id => project.id),
|
62
|
+
story_stub(:id => "100002", :project_id => project.id)
|
63
|
+
]
|
64
|
+
end
|
65
|
+
|
66
|
+
stories = @pivotal.pending_stories(:include_started => true)
|
67
|
+
stories.size.must_equal 2
|
68
|
+
end
|
69
|
+
|
70
|
+
it "starts a story" do
|
71
|
+
story = story_stub(:id => "100001", :project_id => @project.id)
|
72
|
+
@pivotal.start_story(story, :estimate => "3")
|
73
|
+
story.current_state.must_match /started/
|
74
|
+
story.estimate.must_equal "3"
|
75
|
+
story.errors.must_be_empty
|
76
|
+
end
|
77
|
+
|
78
|
+
it "finishes a story" do
|
79
|
+
story = story_stub(:id => "100001", :project_id => @project.id)
|
80
|
+
any_instance_of(PivotalTracker::Note) do |klass|
|
81
|
+
stub(klass).create{ true }
|
82
|
+
end
|
83
|
+
|
84
|
+
@pivotal.finish_story(story, :note => "pull_request_url")
|
85
|
+
story.current_state.must_match /finished/
|
86
|
+
story.errors.must_be_empty
|
87
|
+
end
|
88
|
+
|
89
|
+
it "returns arrays to be printed" do
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
private #===================================================================
|
94
|
+
|
95
|
+
def story_stub(attributes = {})
|
96
|
+
story = PivotalTracker::Story.new(attributes)
|
97
|
+
stub(story).update do |attrs|
|
98
|
+
story.send(:update_attributes, attrs)
|
99
|
+
story
|
100
|
+
end
|
101
|
+
|
102
|
+
story
|
103
|
+
end
|
104
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#require 'simplecov'
|
2
|
+
#SimpleCov.start if ENV["COVERAGE"]
|
3
|
+
|
4
|
+
require 'minitest/autorun'
|
5
|
+
require 'rr'
|
6
|
+
require 'fakefs/safe'
|
7
|
+
|
8
|
+
|
9
|
+
def file_content(file)
|
10
|
+
File.read(File.expand_path("files/"+file, File.dirname(__FILE__)))
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'thor'
|
14
|
+
# This is to silence the 'task' warning for the mocks.
|
15
|
+
#
|
16
|
+
class Thor
|
17
|
+
class << self
|
18
|
+
def create_task(meth) #:nodoc:
|
19
|
+
if @usage && @desc
|
20
|
+
base_class = @hide ? Thor::HiddenTask : Thor::Task
|
21
|
+
tasks[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
|
22
|
+
@usage, @desc, @long_desc, @method_options, @hide = nil
|
23
|
+
true
|
24
|
+
elsif self.all_tasks[meth] || meth == "method_missing"
|
25
|
+
true
|
26
|
+
else
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: assisted_workflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,56 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-02-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rr
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: fakefs
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
14
62
|
- !ruby/object:Gem::Dependency
|
15
63
|
name: thor
|
16
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -87,6 +135,7 @@ extensions: []
|
|
87
135
|
extra_rdoc_files: []
|
88
136
|
files:
|
89
137
|
- .gitignore
|
138
|
+
- .travis.yml
|
90
139
|
- Gemfile
|
91
140
|
- Gemfile.lock
|
92
141
|
- LICENSE.txt
|
@@ -105,6 +154,11 @@ files:
|
|
105
154
|
- lib/assisted_workflow/templates/awconfig.local.tt
|
106
155
|
- lib/assisted_workflow/templates/commit-msg.tt
|
107
156
|
- lib/assisted_workflow/version.rb
|
157
|
+
- spec/assisted_workflow/config_file_spec.rb
|
158
|
+
- spec/assisted_workflow/git_spec.rb
|
159
|
+
- spec/assisted_workflow/github_spec.rb
|
160
|
+
- spec/assisted_workflow/pivotal_spec.rb
|
161
|
+
- spec/spec_helper.rb
|
108
162
|
homepage: https://github.com/flaviogranero/assisted_workflow
|
109
163
|
licenses:
|
110
164
|
- MIT
|
@@ -160,12 +214,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
214
|
- - ! '>='
|
161
215
|
- !ruby/object:Gem::Version
|
162
216
|
version: '0'
|
217
|
+
segments:
|
218
|
+
- 0
|
219
|
+
hash: 4022122617277847943
|
163
220
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
221
|
none: false
|
165
222
|
requirements:
|
166
223
|
- - ! '>='
|
167
224
|
- !ruby/object:Gem::Version
|
168
225
|
version: '0'
|
226
|
+
segments:
|
227
|
+
- 0
|
228
|
+
hash: 4022122617277847943
|
169
229
|
requirements: []
|
170
230
|
rubyforge_project:
|
171
231
|
rubygems_version: 1.8.24
|
@@ -173,4 +233,9 @@ signing_key:
|
|
173
233
|
specification_version: 3
|
174
234
|
summary: AW is a CLI tool to automate software development workflows based on github
|
175
235
|
pull requests
|
176
|
-
test_files:
|
236
|
+
test_files:
|
237
|
+
- spec/assisted_workflow/config_file_spec.rb
|
238
|
+
- spec/assisted_workflow/git_spec.rb
|
239
|
+
- spec/assisted_workflow/github_spec.rb
|
240
|
+
- spec/assisted_workflow/pivotal_spec.rb
|
241
|
+
- spec/spec_helper.rb
|