flux 0.0.3 → 0.0.5
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/.flux.local.rb.sample +3 -0
- data/.flux.rb.sample +4 -0
- data/Gemfile +2 -0
- data/README.md +52 -2
- data/VERSION +1 -1
- data/flux.gemspec +18 -11
- data/lib/flux.rb +27 -31
- data/lib/flux/cli.rb +3 -0
- data/lib/flux/cli/feature.rb +39 -0
- data/lib/flux/cli/pivotal_tracker.rb +72 -0
- data/lib/flux/cli/review.rb +190 -0
- data/lib/flux/git.rb +81 -0
- data/lib/flux/pivotal_tracker.rb +81 -0
- data/lib/flux/rcs.rb +1 -0
- data/lib/flux/rcs/git.rb +132 -15
- data/lib/flux/util.rb +0 -1
- data/lib/flux/workflows/mojotech.rb +23 -17
- data/spec/flux_spec.rb +17 -28
- metadata +51 -28
- data/.flux +0 -9
- data/.flux.local.sample +0 -3
- data/lib/flux/trackers/pivotal_tracker.rb +0 -146
- data/lib/flux/util/table.rb +0 -99
- data/spec/flux/rcs/git_spec.rb +0 -47
- data/spec/flux/trackers/pivotal_tracker_spec.rb +0 -164
- data/spec/flux/util/table_spec.rb +0 -47
- data/spec/support/matchers/print_table.rb +0 -46
data/spec/flux/rcs/git_spec.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
require 'flux/rcs/git'
|
4
|
-
|
5
|
-
describe Flux::RCS::Branches do
|
6
|
-
include Flux::Util::Output
|
7
|
-
|
8
|
-
it "displays the current branch" do
|
9
|
-
mock(mock_root(Grit::Repo)).head.mock!.name { 'zee_current_branch' }
|
10
|
-
|
11
|
-
retval = nil
|
12
|
-
capture { retval = subject.invoke('branches:current', []) }.
|
13
|
-
should == "zee_current_branch\n"
|
14
|
-
retval.should == 'zee_current_branch'
|
15
|
-
end
|
16
|
-
|
17
|
-
it "creates a branch" do
|
18
|
-
mock(mock_root(Grit::Git)).branch({}, 'new_branch')
|
19
|
-
|
20
|
-
subject.invoke 'branches:create', %w(new_branch)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "creates a public branch" do
|
24
|
-
git = mock_root(Grit::Git)
|
25
|
-
|
26
|
-
mock(git).branch({}, 'new_branch')
|
27
|
-
mock(git).push({}, 'origin', '+new_branch:new_branch')
|
28
|
-
mock(git).branch({:set_upstream => true}, 'new_branch', 'origin/new_branch')
|
29
|
-
|
30
|
-
subject.invoke 'branches:create', %w(new_branch), :public => true
|
31
|
-
end
|
32
|
-
|
33
|
-
it "checks out a branch" do
|
34
|
-
mock(mock_root(Grit::Git)).checkout({}, 'new_branch')
|
35
|
-
|
36
|
-
subject.invoke 'branches:checkout', %w(new_branch)
|
37
|
-
end
|
38
|
-
|
39
|
-
def mock_root(klass)
|
40
|
-
repo_path = File.expand_path(File.dirname(__FILE__) + '/../../../.git')
|
41
|
-
root = Object.new
|
42
|
-
|
43
|
-
mock(klass).new(repo_path) { root }
|
44
|
-
|
45
|
-
root
|
46
|
-
end
|
47
|
-
end
|
@@ -1,164 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
require 'flux/trackers/pivotal_tracker'
|
4
|
-
|
5
|
-
describe Flux::Trackers::PivotalTracker do
|
6
|
-
let(:environment) {
|
7
|
-
{'trackers' => {'project_id' => PROJECT.id,
|
8
|
-
'token' => PROJECT.token,
|
9
|
-
'email' => 'david@mojotech.com'}}
|
10
|
-
}
|
11
|
-
|
12
|
-
before { Flux.environment = environment }
|
13
|
-
|
14
|
-
it "lists stories by iteration" do
|
15
|
-
mock(PivotalTracker::Iteration).current_backlog(fake_project) {
|
16
|
-
[OpenStruct.new(:stories => [
|
17
|
-
OpenStruct.new(:id => 1,
|
18
|
-
:current_state => 'unstarted',
|
19
|
-
:owned_by => '',
|
20
|
-
:name => 'first story')]),
|
21
|
-
OpenStruct.new(:stories => [
|
22
|
-
OpenStruct.new(:id => 2,
|
23
|
-
:current_state => 'started',
|
24
|
-
:owned_by => 'David Leal',
|
25
|
-
:name => 'second story')])]
|
26
|
-
}
|
27
|
-
|
28
|
-
t = [['ID', 'STATE', 'ASSIGNEE', 'STORY'],
|
29
|
-
[1, 'unstarted', '', 'first story'],
|
30
|
-
[2, 'started', 'David Leal', 'second story']]
|
31
|
-
|
32
|
-
lambda { subject.invoke :list }.should print_table(t)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "grabs a story" do
|
36
|
-
prepare_myself
|
37
|
-
|
38
|
-
mock_update(123, 'owned_by' => 'David Leal')
|
39
|
-
|
40
|
-
subject.invoke :grab, [123]
|
41
|
-
end
|
42
|
-
|
43
|
-
it "grabs a story and estimates it" do
|
44
|
-
prepare_myself
|
45
|
-
|
46
|
-
mock_update(123, 'owned_by' => 'David Leal',
|
47
|
-
'estimate' => 2)
|
48
|
-
|
49
|
-
subject.invoke :grab, [123], :estimate => 2
|
50
|
-
end
|
51
|
-
|
52
|
-
[%w(starts started start),
|
53
|
-
%w(finishes finished finish)].each do |(action, state, task)|
|
54
|
-
it "#{action} a story that was already estimated" do
|
55
|
-
s = mock_update(123, 'current_state' => state)
|
56
|
-
s.estimate = 2
|
57
|
-
|
58
|
-
subject.invoke task, [123]
|
59
|
-
end
|
60
|
-
|
61
|
-
it "#{action} a story that needs to be estimated" do
|
62
|
-
mock_update(123, 'current_state' => state, 'estimate' => 2)
|
63
|
-
|
64
|
-
subject.invoke task, [123], :estimate => 2
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "attributes" do
|
69
|
-
it "updates custom attributes" do
|
70
|
-
attrs = {'branch' => 'blah', 'other' => 'yay'}
|
71
|
-
|
72
|
-
mock_find(123)
|
73
|
-
mock(PivotalTracker::Note).new(observe { |h|
|
74
|
-
h[:owner].id == 123 &&
|
75
|
-
h[:text] == YAML.dump(attrs)
|
76
|
-
}).mock!.create
|
77
|
-
|
78
|
-
subject.invoke :update, [123], :attributes => attrs
|
79
|
-
end
|
80
|
-
|
81
|
-
it "updates native attributes" do
|
82
|
-
attrs = {'owner' => 'David Leal',
|
83
|
-
'state' => 'started',
|
84
|
-
'estimate' => 2,
|
85
|
-
'name' => 'My story'}
|
86
|
-
|
87
|
-
mock_update(123,
|
88
|
-
'owned_by' => 'David Leal',
|
89
|
-
'current_state' => 'started',
|
90
|
-
'estimate' => 2,
|
91
|
-
'name' => 'My story')
|
92
|
-
|
93
|
-
subject.invoke :update, [123], :attributes => attrs
|
94
|
-
end
|
95
|
-
|
96
|
-
it "updates valid states only" do
|
97
|
-
attrs = {'state' => 'sitting'}
|
98
|
-
|
99
|
-
s = mock_find(123)
|
100
|
-
|
101
|
-
lambda { subject.invoke :update, [123], :attributes => attrs }.
|
102
|
-
should raise_error(Flux::TrackerError, /Invalid state/)
|
103
|
-
end
|
104
|
-
|
105
|
-
it "updates state when story has estimate" do
|
106
|
-
attrs = {'state' => 'started'}
|
107
|
-
|
108
|
-
s = mock_update(123, 'current_state' => 'started')
|
109
|
-
s.estimate = 2
|
110
|
-
|
111
|
-
subject.invoke :update, [123], :attributes => attrs
|
112
|
-
end
|
113
|
-
|
114
|
-
it "updates state when story estimate is given" do
|
115
|
-
attrs = {'state' => 'started', 'estimate' => 2}
|
116
|
-
|
117
|
-
s = mock_update(123, 'current_state' => 'started',
|
118
|
-
'estimate' => 2)
|
119
|
-
|
120
|
-
subject.invoke :update, [123], :attributes => attrs
|
121
|
-
end
|
122
|
-
|
123
|
-
Flux::Trackers::PivotalTracker::STATES_W_ESTIMATE.each do |state|
|
124
|
-
it "fails to update state `#{state}' if no estimate given" do
|
125
|
-
attrs = {'state' => state}
|
126
|
-
|
127
|
-
s = mock_find(123)
|
128
|
-
|
129
|
-
lambda { subject.invoke :update, [123], :attributes => attrs }.
|
130
|
-
should raise_error(Flux::TrackerError, /Need an estimate/)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def iteration(which, data)
|
136
|
-
mock(PivotalTracker::Iteration).__send__(which, fake_project) {
|
137
|
-
OpenStruct.new(:stories => data.map { |d| OpenStruct.new(d) })
|
138
|
-
}
|
139
|
-
end
|
140
|
-
|
141
|
-
def fake_project
|
142
|
-
OpenStruct.new(:id => PROJECT.id)
|
143
|
-
end
|
144
|
-
|
145
|
-
def fake_story(id)
|
146
|
-
PivotalTracker::Story.new(:id => id, :project_id => PROJECT.id)
|
147
|
-
end
|
148
|
-
|
149
|
-
def mock_find(story_id)
|
150
|
-
fake_story(story_id).tap { |s|
|
151
|
-
mock(PivotalTracker::Story).find(story_id, PROJECT.id) { s }
|
152
|
-
}
|
153
|
-
end
|
154
|
-
|
155
|
-
def mock_update(story_id, attrs)
|
156
|
-
mock_find(story_id).tap { |s| mock(s).update(attrs) }
|
157
|
-
end
|
158
|
-
|
159
|
-
def prepare_myself
|
160
|
-
mock(PivotalTracker::Membership).all(fake_project) {
|
161
|
-
[OpenStruct.new(:name => 'David Leal', :email => 'david@mojotech.com')]
|
162
|
-
}
|
163
|
-
end
|
164
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
describe Flux::Util::Table do
|
4
|
-
let(:body) {
|
5
|
-
[[123, 'unstarted', 'David Leal', 'First story'],
|
6
|
-
[456, 'unscheduled', '', 'Second story']]
|
7
|
-
}
|
8
|
-
|
9
|
-
it "is converted to a string" do
|
10
|
-
t = Flux::Util::Table.new(Thor::Shell::Basic.new,
|
11
|
-
[%w(ID STATE ASSIGNEE STORY)] + body,
|
12
|
-
' ',
|
13
|
-
nil)
|
14
|
-
|
15
|
-
t.to_s.should == <<EOT
|
16
|
-
ID STATE ASSIGNEE STORY
|
17
|
-
123 unstarted David Leal First story
|
18
|
-
456 unscheduled Second story
|
19
|
-
EOT
|
20
|
-
end
|
21
|
-
|
22
|
-
it "aligns its columns to the right" do
|
23
|
-
t = Flux::Util::Table.new(Thor::Shell::Basic.new,
|
24
|
-
[%w(>ID >STATE >ASSIGNEE >STORY)] + body,
|
25
|
-
' ',
|
26
|
-
nil)
|
27
|
-
|
28
|
-
t.to_s.should == <<EOT
|
29
|
-
ID STATE ASSIGNEE STORY
|
30
|
-
123 unstarted David Leal First story
|
31
|
-
456 unscheduled Second story
|
32
|
-
EOT
|
33
|
-
end
|
34
|
-
|
35
|
-
it "truncates lines to a given width" do
|
36
|
-
t = Flux::Util::Table.new(Thor::Shell::Basic.new,
|
37
|
-
[%w(ID STATE ASSIGNEE STORY)] + body,
|
38
|
-
' ',
|
39
|
-
7)
|
40
|
-
|
41
|
-
t.to_s.should == <<EOT
|
42
|
-
ID ...
|
43
|
-
123 ...
|
44
|
-
456 ...
|
45
|
-
EOT
|
46
|
-
end
|
47
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
RSpec::Matchers.define :print_table do |data|
|
2
|
-
class FakeStdout
|
3
|
-
attr_reader :table
|
4
|
-
|
5
|
-
def initialize(stdout)
|
6
|
-
@stdout = stdout
|
7
|
-
end
|
8
|
-
|
9
|
-
def puts(*args)
|
10
|
-
case args.first
|
11
|
-
when Flux::Util::Table
|
12
|
-
@table = args.first
|
13
|
-
else
|
14
|
-
@stdout.puts *args
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def write(data)
|
19
|
-
@stdout.write data
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
|
24
|
-
match do |block|
|
25
|
-
stdout = $stdout
|
26
|
-
$stdout = @stdout = FakeStdout.new(stdout)
|
27
|
-
|
28
|
-
begin
|
29
|
-
block.call
|
30
|
-
|
31
|
-
@stdout.table.should_not be_nil
|
32
|
-
@stdout.table.data.should == data
|
33
|
-
ensure
|
34
|
-
$stdout = stdout
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
failure_message_for_should do |block|
|
39
|
-
"Expected table:\n\n#{Flux::Util::Table.new(data, ' ', nil)}\n" <<
|
40
|
-
"but got:\n\n#{@stdout.table ? @stdout.table : 'nil'}"
|
41
|
-
end
|
42
|
-
|
43
|
-
failure_message_for_should_not do |block|
|
44
|
-
raise NotImplementedError
|
45
|
-
end
|
46
|
-
end
|