git_reflow 0.8.6 → 0.8.7

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.
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