git_reflow 0.8.6 → 0.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +348 -348
  4. data/Gemfile.lock +13 -15
  5. data/LICENSE +20 -20
  6. data/README.rdoc +461 -461
  7. data/Rakefile +8 -8
  8. data/bin/console +7 -7
  9. data/bin/setup +6 -6
  10. data/circle.yml +5 -5
  11. data/exe/git-reflow +36 -36
  12. data/git_reflow.gemspec +1 -1
  13. data/lib/git_reflow/commands/deliver.rb +10 -10
  14. data/lib/git_reflow/commands/refresh.rb +20 -20
  15. data/lib/git_reflow/commands/review.rb +13 -13
  16. data/lib/git_reflow/commands/setup.rb +11 -11
  17. data/lib/git_reflow/commands/stage.rb +9 -9
  18. data/lib/git_reflow/commands/start.rb +22 -22
  19. data/lib/git_reflow/commands/status.rb +7 -7
  20. data/lib/git_reflow/config.rb +9 -9
  21. data/lib/git_reflow/git_server/base.rb +68 -68
  22. data/lib/git_reflow/git_server/bit_bucket/pull_request.rb +84 -84
  23. data/lib/git_reflow/git_server/bit_bucket.rb +101 -101
  24. data/lib/git_reflow/git_server/git_hub/pull_request.rb +4 -1
  25. data/lib/git_reflow/git_server/pull_request.rb +11 -2
  26. data/lib/git_reflow/git_server.rb +63 -63
  27. data/lib/git_reflow/logger.rb +49 -0
  28. data/lib/git_reflow/merge_error.rb +9 -9
  29. data/lib/git_reflow/os_detector.rb +23 -23
  30. data/lib/git_reflow/rspec/command_line_helpers.rb +12 -8
  31. data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
  32. data/lib/git_reflow/rspec.rb +2 -2
  33. data/lib/git_reflow/sandbox.rb +11 -6
  34. data/lib/git_reflow/version.rb +1 -1
  35. data/lib/git_reflow/workflow.rb +59 -59
  36. data/lib/git_reflow/workflows/core.rb +238 -238
  37. data/lib/git_reflow/workflows/flat_merge.rb +10 -10
  38. data/lib/git_reflow.rb +11 -0
  39. data/spec/fixtures/awesome_workflow.rb +7 -0
  40. data/spec/fixtures/git/git_config +7 -0
  41. data/spec/fixtures/issues/comment.json.erb +27 -0
  42. data/spec/fixtures/issues/comments.json +29 -0
  43. data/spec/fixtures/issues/comments.json.erb +15 -0
  44. data/spec/fixtures/pull_requests/comment.json.erb +45 -0
  45. data/spec/fixtures/pull_requests/comments.json +47 -0
  46. data/spec/fixtures/pull_requests/comments.json.erb +15 -0
  47. data/spec/fixtures/pull_requests/commits.json +29 -0
  48. data/spec/fixtures/pull_requests/external_pull_request.json +145 -0
  49. data/spec/fixtures/pull_requests/pull_request.json +142 -0
  50. data/spec/fixtures/pull_requests/pull_request.json.erb +142 -0
  51. data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -0
  52. data/spec/fixtures/pull_requests/pull_requests.json +136 -0
  53. data/spec/fixtures/repositories/commit.json +53 -0
  54. data/spec/fixtures/repositories/commit.json.erb +53 -0
  55. data/spec/fixtures/repositories/commits.json.erb +13 -0
  56. data/spec/fixtures/repositories/statuses.json +31 -0
  57. data/spec/fixtures/workflow_with_super.rb +8 -0
  58. data/spec/lib/git_reflow/config_spec.rb +74 -0
  59. data/spec/lib/git_reflow/git_helpers_spec.rb +182 -0
  60. data/spec/lib/git_reflow/git_server/bit_bucket_spec.rb +81 -0
  61. data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +587 -0
  62. data/spec/lib/git_reflow/git_server/git_hub_spec.rb +221 -0
  63. data/spec/lib/git_reflow/git_server/pull_request_spec.rb +524 -0
  64. data/spec/lib/git_reflow/git_server_spec.rb +101 -0
  65. data/spec/lib/git_reflow/logger_spec.rb +18 -0
  66. data/spec/lib/git_reflow/sandbox_spec.rb +15 -0
  67. data/spec/lib/git_reflow/workflow_spec.rb +59 -0
  68. data/spec/lib/git_reflow/workflows/core_spec.rb +665 -0
  69. data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +59 -0
  70. data/spec/lib/git_reflow_spec.rb +75 -0
  71. data/spec/spec_helper.rb +38 -0
  72. data/spec/support/fake_github.rb +128 -0
  73. data/spec/support/fixtures.rb +54 -0
  74. data/spec/support/github_helpers.rb +109 -0
  75. data/spec/support/mock_pull_request.rb +17 -0
  76. data/spec/support/web_mocks.rb +39 -0
  77. metadata +83 -6
@@ -0,0 +1,221 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitReflow::GitServer::GitHub do
4
+ let(:user) { 'reenhanced' }
5
+ let(:password) { 'shazam' }
6
+ let(:repo) { 'repo' }
7
+ let(:oauth_token_hash) { Hashie::Mash.new({ token: 'a1b2c3d4e5f6g7h8i9j0'}) }
8
+ let(:hostname) { 'hostname.local' }
9
+ let(:github_site) { 'https://github.com' }
10
+ let(:github_api_endpoint) { 'https://api.github.com' }
11
+ let(:enterprise_site) { 'https://github.gittyup.com' }
12
+ let(:enterprise_api) { 'https://github.gittyup.com/api/v3' }
13
+ let(:github) { stub_github_with(pull: existing_pull_request) }
14
+ let!(:github_api) { github.connection }
15
+ let(:existing_pull_request) { Fixture.new('pull_requests/pull_request.json').to_json_hashie }
16
+ let(:existing_pull_requests) { Fixture.new('pull_requests/pull_requests.json').to_json_hashie }
17
+
18
+ before do
19
+ allow_any_instance_of(HighLine).to receive(:ask) do |terminal, question|
20
+ values = {
21
+ "Please enter your GitHub username: " => user,
22
+ "Please enter your GitHub password (we do NOT store this): " => password,
23
+ "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
24
+ "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api
25
+ }
26
+ return_value = values[question]
27
+ question = ""
28
+ return_value
29
+ end
30
+
31
+ allow(github.class).to receive(:remote_user).and_return(user)
32
+ allow(github.class).to receive(:remote_repo_name).and_return(repo)
33
+ end
34
+
35
+ describe '#initialize(options)' do
36
+ subject { GitReflow::GitServer::GitHub.new({}) }
37
+
38
+ it 'sets the reflow git server provider to GitHub in the git config' do
39
+ expect(GitReflow::Config).to receive(:set).once.with('github.site', github_site, local: false)
40
+ expect(GitReflow::Config).to receive(:set).once.with('github.endpoint', github_api_endpoint, local: false)
41
+ expect(GitReflow::Config).to receive(:set).once.with('reflow.git-server', 'GitHub', local: false)
42
+ subject
43
+ end
44
+
45
+ context 'using enterprise' do
46
+ subject { GitReflow::GitServer::GitHub.new(enterprise: true) }
47
+
48
+ it 'sets the enterprise site and api as the site and api endpoints for the GitHub provider in the git config' do
49
+ expect(GitReflow::Config).to receive(:set).once.with('github.site', enterprise_site, local: false)
50
+ expect(GitReflow::Config).to receive(:set).once.with('github.endpoint', enterprise_api, local: false)
51
+ expect(GitReflow::Config).to receive(:set).once.with('reflow.git-server', 'GitHub', local: false)
52
+ subject
53
+ end
54
+
55
+ end
56
+
57
+ context 'storing git config settings only for this project' do
58
+ subject { GitReflow::GitServer::GitHub.new(project_only: true) }
59
+
60
+ before do
61
+ expect(GitReflow::Config).to receive(:get).twice.with('reflow.local-projects', all: true).and_return("#{user}/#{repo}")
62
+ end
63
+
64
+ it 'sets the enterprise site and api as the site and api endpoints for the GitHub provider in the git config' do
65
+ expect(GitReflow::Config).to receive(:set).once.with('github.site', github_site, local: true).and_call_original
66
+ expect(GitReflow::Config).to receive(:set).once.with('github.endpoint', github_api_endpoint, local: true)
67
+ expect(GitReflow::Config).to receive(:set).once.with('reflow.git-server', 'GitHub', local: true)
68
+ subject
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ describe '#authenticate' do
75
+ let(:github) { GitReflow::GitServer::GitHub.new({}) }
76
+ let!(:github_api) { Github::Client.new }
77
+ let(:github_authorizations) { Github::Client::Authorizations.new }
78
+ subject { github.authenticate }
79
+
80
+ before do
81
+ allow(GitReflow::GitServer::GitHub).to receive(:user).and_return('reenhanced')
82
+ allow(github_api).to receive(:oauth).and_return(github_authorizations)
83
+ allow(github_api).to receive_message_chain(:oauth, :all).and_return([])
84
+ allow(github).to receive(:run).with('hostname', loud: false).and_return(hostname)
85
+ end
86
+
87
+ context 'not yet authenticated' do
88
+ context 'with valid GitHub credentials' do
89
+
90
+ before do
91
+ allow(Github::Client).to receive(:new).and_return(github_api)
92
+ allow(github_authorizations).to receive(:authenticated?).and_return(true)
93
+ allow(github_api.oauth).to receive(:create).with({ scopes: ['repo'], note: "git-reflow (#{hostname})" }).and_return(oauth_token_hash)
94
+ end
95
+
96
+ it "notifies the user of successful setup" do
97
+ expect { subject }.to have_said "Your GitHub account was successfully setup!", :success
98
+ end
99
+
100
+ it "creates a new GitHub oauth token" do
101
+ expect(github_api.oauth).to receive(:create).and_return(oauth_token_hash)
102
+ subject
103
+ end
104
+
105
+ it "creates git config keys for github connections" do
106
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.site \"#{GitReflow::GitServer::GitHub.site_url}\"", blocking: false
107
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.endpoint \"#{GitReflow::GitServer::GitHub.api_endpoint}\"", blocking: false
108
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.oauth-token \"#{oauth_token_hash[:token]}\"", blocking: false
109
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all reflow.git-server \"GitHub\"", blocking: false
110
+ end
111
+
112
+ context "exclusive to project" do
113
+ let(:github) do
114
+ allow(GitReflow::GitServer::GitHub).to receive(:project_only?).and_return(true)
115
+ allow(GitReflow::GitServer::GitHub).to receive(:remote_user).and_return(user)
116
+ allow(GitReflow::GitServer::GitHub).to receive(:remote_repo_name).and_return(repo)
117
+ GitReflow::GitServer::GitHub.new(project_only: true)
118
+ end
119
+
120
+ it "creates _local_ git config keys for github connections" do
121
+ expect{ subject }.to_not have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.site \"#{GitReflow::GitServer::GitHub.site_url}\"", blocking: false
122
+ expect{ subject }.to_not have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.endpoint \"#{GitReflow::GitServer::GitHub.api_endpoint}\"", blocking: false
123
+ expect{ subject }.to_not have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.oauth-token \"#{oauth_token_hash[:token]}\"", blocking: false
124
+ expect{ subject }.to_not have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all reflow.git-server \"GitHub\"", blocking: false
125
+
126
+ expect{ subject }.to have_run_command_silently "git config --replace-all github.site \"#{GitReflow::GitServer::GitHub.site_url}\"", blocking: false
127
+ expect{ subject }.to have_run_command_silently "git config --replace-all github.endpoint \"#{GitReflow::GitServer::GitHub.api_endpoint}\"", blocking: false
128
+ expect{ subject }.to have_run_command_silently "git config --replace-all github.oauth-token \"#{oauth_token_hash[:token]}\"", blocking: false
129
+ expect{ subject }.to have_run_command_silently "git config --replace-all reflow.git-server \"GitHub\"", blocking: false
130
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --add reflow.local-projects \"#{user}/#{repo}\"", blocking: false
131
+ end
132
+ end
133
+
134
+ context "use GitHub enterprise account" do
135
+ let(:github) { GitReflow::GitServer::GitHub.new(enterprise: true) }
136
+ before { allow(GitReflow::GitServer::GitHub).to receive(:@using_enterprise).and_return(true) }
137
+ it "creates git config keys for github connections" do
138
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.site \"#{enterprise_site}\"", blocking: false
139
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.endpoint \"#{enterprise_api}\"", blocking: false
140
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.oauth-token \"#{oauth_token_hash[:token]}\"", blocking: false
141
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all reflow.git-server \"GitHub\"", blocking: false
142
+ end
143
+ end
144
+ end
145
+
146
+ context "with invalid GitHub credentials" do
147
+ let(:unauthorized_error_response) {{
148
+ response_headers: {'content-type' => 'application/json; charset=utf-8', status: 'Unauthorized'},
149
+ method: 'GET',
150
+ status: '401',
151
+ body: { error: "GET https://api.github.com/authorizations: 401 Bad credentials" }
152
+ }}
153
+
154
+ before do
155
+ allow(Github::Client).to receive(:new).and_raise Github::Error::Unauthorized.new(unauthorized_error_response)
156
+ end
157
+
158
+ it "notifies user of invalid login details" do
159
+ expect { subject }.to have_said "Github Authentication Error: #{Github::Error::Unauthorized.new(unauthorized_error_response).inspect}", :error
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ describe '#create_pull_request(options)' do
166
+ let(:title) { 'Fresh title' }
167
+ let(:body) { 'Funky body' }
168
+ let(:current_branch) { 'new-feature' }
169
+
170
+ subject { github.create_pull_request({ title: title, body: body, base: 'master' }) }
171
+
172
+ before do
173
+ allow(github.class).to receive(:current_branch).and_return(current_branch)
174
+ allow(GitReflow).to receive(:git_server).and_return(github)
175
+ stub_request(:post, %r{/repos/#{user}/#{repo}/pulls}).
176
+ to_return(body: Fixture.new('pull_requests/pull_request.json').to_s, status: 201, headers: {content_type: "application/json; charset=utf-8"})
177
+ end
178
+
179
+ specify { expect(subject.class.to_s).to eq('GitReflow::GitServer::GitHub::PullRequest') }
180
+
181
+ it 'creates a pull request using the remote user and repo' do
182
+ allow(github_api).to receive(:pull_requests)
183
+ expect(github_api.pull_requests).to receive(:create).with(user, repo, title: title, body: body, head: "#{user}:#{current_branch}", base: 'master').and_return(existing_pull_request)
184
+ subject
185
+ end
186
+ end
187
+
188
+ describe '#find_open_pull_request(from, to)' do
189
+ subject { github.find_open_pull_request({ from: 'new-feature', to: 'master'}) }
190
+
191
+ it 'looks for an open pull request matching the remote user/repo' do
192
+ expect(subject.number).to eq(existing_pull_requests.first.number)
193
+ end
194
+
195
+ context 'no pull request exists' do
196
+ before do
197
+ allow(github_api).to receive(:pull_requests)
198
+ expect(github_api.pull_requests).to receive(:all).and_return([])
199
+ end
200
+ it { is_expected.to eq(nil) }
201
+ end
202
+ end
203
+
204
+ describe '#get_build_status(sha)' do
205
+ let(:sha) { '6dcb09b5b57875f334f61aebed695e2e4193db5e' }
206
+ subject { github.get_build_status(sha) }
207
+ before { allow(github_api).to receive_message_chain(:repos, :statuses) }
208
+
209
+ it 'gets the latest build status for the given commit hash' do
210
+ expect(github_api.repos.statuses).to receive(:all).with(user, repo, sha).and_return([{ state: 'success'}])
211
+ subject
212
+ end
213
+ end
214
+
215
+ describe '#comment_authors_for_pull_request(pull_request, options = {})' do
216
+ end
217
+
218
+ describe '#get_committed_time(commit_sha)' do
219
+ end
220
+
221
+ end