From 75c047e0fda94c1f54a71d422a7f4b71455fd2a5 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 14:19:17 -0600 Subject: [PATCH 01/24] introduce separate createpr and assignpr actions --- .gitignore | 1 + lib/socialcast-git-extensions/cli.rb | 58 ++++++++++++++++++------- lib/socialcast-git-extensions/github.rb | 40 +++++++++++++---- socialcast-git-extensions.gemspec | 1 + spec/cli_spec.rb | 54 ++++++++++++++++------- spec/spec_helper.rb | 2 +- 6 files changed, 116 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 6a5f884..bf9ebe9 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ tmtags coverage rdoc pkg +.byebug_history #bundler Gemfile.lock diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index 3f17512..b95e7ee 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -28,14 +28,24 @@ def initialize(*args) RestClient.log = Logger.new(STDOUT) if options[:trace] end - desc "reviewrequest", "Create a pull request on github" + desc "createpr", "Create a pull request on github" method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description' - method_option :additional_reviewers, :type => :string, :aliases => '-a', :desc => 'add additional reviewers to mention automatically, and skips the prompt' - method_option :skip_additional_reviewers, :type => :string, :aliases => '-s', :desc => 'Skips adding additional reviewers' # @see http://developer.github.com/v3/pulls/ - def reviewrequest(*additional_reviewers) + def createpr update + description = options[:description] || editor_input(PULL_REQUEST_DESCRIPTION) + branch = current_branch + repo = current_repo + url = create_pull_request(branch, repo, description)['html_url'] + say "Pull request created: #{url}" + end + + desc "assignpr", "Assign the pull request on github for review" + method_option :additional_reviewers, :type => :string, :aliases => '-a', :desc => 'add additional reviewers to mention automatically, and skips the prompt' + method_option :skip_additional_reviewers, :type => :string, :aliases => '-s', :desc => 'Skips adding additional reviewers' + # @see http://developer.github.com/v3/pulls/ + def assignpr(*additional_reviewers) primary_mention = if buddy = socialcast_review_buddy(current_user) "assigned to @#{buddy}" end @@ -58,18 +68,31 @@ def reviewrequest(*additional_reviewers) end end - assignee = github_review_buddy(current_user) - - description = options[:description] || editor_input(PULL_REQUEST_DESCRIPTION) branch = current_branch repo = current_repo - url = create_pull_request branch, repo, description, assignee - say "Pull request created: #{url}" + current_pr = current_pr_for_branch(repo, branch) + issue_url = current_pr['issue_url'] + url = current_pr['html_url'] + + assign_pull_request(assignee, issue_url) if assignee = github_review_buddy(current_user) - review_message = ["#reviewrequest for #{branch} in #{current_repo}", "PR #{url} #{primary_mention}", '', description, '', secondary_mention, "/cc @#{developer_group} #scgitx", '', changelog_summary(branch)].compact.join("\n").gsub(/\n{2,}/, "\n\n") + issue_message = ['#reviewrequest', primary_mention, secondary_mention, "\n/cc @#{developer_group} #scgitx"].compact.join(' ') + comment_on_issue(issue_url, issue_message) + + review_message = ["#reviewrequest for #{branch} in #{current_repo}", "PR #{url} #{primary_mention}", '', current_pr['body'], '', secondary_mention, "/cc @#{developer_group} #scgitx", '', changelog_summary(branch)].compact.join("\n").gsub(/\n{2,}/, "\n\n") post review_message, :message_type => 'review_request' end + desc "reviewrequest", "Create and assign a pull request on github" + method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description' + method_option :additional_reviewers, :type => :string, :aliases => '-a', :desc => 'add additional reviewers to mention automatically, and skips the prompt' + method_option :skip_additional_reviewers, :type => :string, :aliases => '-s', :desc => 'Skips adding additional reviewers' + # @see http://developer.github.com/v3/pulls/ + def reviewrequest(*additional_reviewers) + createpr + assignpr(*additional_reviewers) + end + desc "findpr", "Find pull requests including a given commit" def findpr(commit_hash) repo = current_repo @@ -104,14 +127,19 @@ def backportpr(pull_request_num, maintenance_branch) maintenance_branch_url = "https://github.com/#{repo}/tree/#{maintenance_branch}" description = "Backport ##{pull_request_num} to #{maintenance_branch_url}\n***\n#{pull_request_data['body']}" - pull_request_url = create_pull_request(backport_branch, repo, description, assignee) + pr_hash = create_pull_request(backport_branch, repo, description) + assign_pull_request(assignee, pr_hash['issue_url']) if assignee + + reviewer_mention = "@#{socialcast_reviwer}" if socialcast_reviewer + issue_message = ['#reviewrequest backport', reviewer_mention, "/cc @#{developer_group} #scgitx"].compact.join(' ') + comment_on_issue(pr_hash['issue_url'], issue_message) review_message = ["#reviewrequest backport ##{pull_request_num} to #{maintenance_branch} in #{current_repo} #scgitx"] if socialcast_reviewer - review_message << "/cc @#{socialcast_reviewer} for #backport track" + review_message << "/cc #{reviewer_mention} for #backport track" end review_message << "/cc @#{developer_group}" - post review_message.join("\n\n"), :url => pull_request_url, :message_type => 'review_request' + post review_message.join("\n\n"), :url => pr_hash['html_url'], :message_type => 'review_request' ensure ENV['BASE_BRANCH'] = original_base_branch end @@ -283,9 +311,9 @@ def enforce_staging_before_release? end # post a message in socialcast - # skip sharing message if CLI quiet option is present + # skip sharing message if CLI quiet option is present or config quiet option is 'true' def post(message, params = {}) - return if options[:quiet] + return if options[:quiet] || config['quiet'] == 'true' ActiveResource::Base.logger = Logger.new(STDOUT) if options[:trace] Socialcast::CommandLine::Message.configure_from_credentials response = Socialcast::CommandLine::Message.create params.merge(:body => message) diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index 615da9b..aa5b46e 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -31,9 +31,8 @@ def authorization_token throw e end - # returns the url of the created pull request # @see http://developer.github.com/v3/pulls/ - def create_pull_request(branch, repo, body, assignee) + def create_pull_request(branch, repo, body) payload = {:title => branch, :base => base_branch, :head => branch, :body => body}.to_json say "Creating pull request for " say "#{branch} ", :green @@ -41,11 +40,7 @@ def create_pull_request(branch, repo, body, assignee) say "#{base_branch} ", :green say "in " say repo, :green - data = github_api_request("POST", "repos/#{repo}/pulls", payload) - assign_pull_request(branch, assignee, data) if assignee ## Unfortunately this needs to be done in a seperate request. - - url = data['html_url'] - url + github_api_request("POST", "repos/#{repo}/pulls", payload) end # find the PRs matching the given commit hash @@ -56,13 +51,40 @@ def pull_requests_for_commit(repo, commit_hash) github_api_request "GET", "search/issues?q=#{query}" end - def assign_pull_request(branch, assignee, data) + # find the PRs for a given branch + # https://developer.github.com/v3/pulls/#list-pull-requests + def pull_requests_for_branch(branch, repo, options = {}) + query = "base=#{branch}" + query = "#{query}&state=#{options[:state]}" if options[:state] + github_api_request "GET", "repos/#{repo}/pulls?base=branch" + end + + # find the current PR for a given branch + def current_pr_for_branch(repo, branch) + prs = pull_requests_for_branch(repo, branch) + raise "Multiple (#{prs.size}) open PRs for #{branch} found in #{repo}, unable to proceed" if prs.size > 1 + prs.first + end + + # returns the issue_url for the PR + def assign_pull_request(branch, repo, assignee) issue_payload = { :title => branch, :assignee => assignee }.to_json - github_api_request "PATCH", data['issue_url'], issue_payload + issue_url = current_pr_for_branch(repo, branch)['issue_url'] + raise "Unable to determine issue_url for branch #{branch} in #{repo}" unless issue_url + github_api_request "PATCH", issue_url, issue_payload + issue_url rescue => e say "Failed to assign pull request: #{e.message}", :red end + # post a comment on an issue + # https://developer.github.com/v3/issues/comments/#create-a-comment + def comment_on_issue(issue_url, comment_body) + github_api_request 'POST', "#{issue_url}/comments", { :body => comment_body }.to_json + end + + # https://developer.github.com/v3/issues/comments/#create-a-comment + # @returns [String] socialcast username to assign the review to # @returns [nil] when no buddy system configured or user not found def socialcast_review_buddy(current_user) diff --git a/socialcast-git-extensions.gemspec b/socialcast-git-extensions.gemspec index 445b988..c391c11 100644 --- a/socialcast-git-extensions.gemspec +++ b/socialcast-git-extensions.gemspec @@ -23,6 +23,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'rspec', '~> 3.0' s.add_development_dependency 'pry', '~> 0.9.12.6' s.add_development_dependency 'webmock', '~> 1.21' + s.add_development_dependency 'byebug' s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 5df5890..aa7224f 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -875,9 +875,19 @@ def stub_message(message_body, params = {}) stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). with(:body => "{\"title\":\"backport_59_to_v1.x\",\"base\":\"v1.x\",\"head\":\"backport_59_to_v1.x\",\"body\":\"Backport #59 to https://github.com/socialcast/socialcast-git-extensions/tree/v1.x\\n***\\nsimply testing this out\"}", :headers => { 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip, deflate', 'Authorization' => /token\s\w+/, 'Content-Type' => 'application/json', 'User-Agent'=>'socialcast-git-extensions' }). - to_return(:status => 200, :body => '{"html_url": "https://github.com/socialcast/socialcast-git-extensions/pulls/60"}', :headers => { 'Content-Type' => 'application/json' }) + to_return(:status => 200, :body => '{"html_url": "https://github.com/socialcast/socialcast-git-extensions/pulls/60", "issue_url": "https://api.github.com/repos/repo/project/issues/60"}', :headers => { 'Content-Type' => 'application/json' }) - stub_message "#reviewrequest backport #59 to v1.x in socialcast/socialcast-git-extensions #scgitx\n\n/cc @SocialcastDevelopers", :url => 'https://github.com/socialcast/socialcast-git-extensions/pulls/60', :message_type => 'review_request' + stub_request(:post, "https://api.github.com/repos/repo/project/issues/60/comments") + .with( + :body => "{\"body\":\"#reviewrequest backport /cc @SocialcastDevelopers #scgitx\"}", + :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=>'68', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} + ).to_return(:status => 200, :body => "{}", :headers => {}) + + stub_request(:post, "https://testuser:testpassword@testdomain/api/messages.json") + .with( + :body => "{\"message\":{\"url\":\"https://github.com/socialcast/socialcast-git-extensions/pulls/60\",\"message_type\":\"review_request\",\"body\":\"#reviewrequest backport #59 to v1.x in socialcast/socialcast-git-extensions #scgitx\\n\\n/cc @SocialcastDevelopers\"}}", + :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'} + ).to_return(:status => 200, :body => "", :headers => {}) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:backportpr).and_call_original Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] @@ -956,17 +966,23 @@ def stub_message(message_body, params = {}) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) end context 'when description != nil' do - before do + it do stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). - to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1"}), :headers => {}) + to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with( + :body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}", + :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=>'61', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} + ).to_return(:status => 200, :body => "{}", :headers => {}) stub_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] - end - it 'should create github pull request' do end # see expectations - it 'should post socialcast message' do end # see expectations - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ "git pull origin FOO", "git pull origin master", @@ -979,20 +995,26 @@ def stub_message(message_body, params = {}) context 'when review_buddies are specified via a /config YML file' do before do stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). - to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://github.com/repos/repo/project/issues/1"}), :headers => {}) + to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with( + :body => pr_comment_body, + :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=> pr_comment_body.length, 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} + ).to_return(:status => 200, :body => "{}", :headers => {}) + stub_request(:patch, "http://github.com/repos/repo/project/issues/1").to_return(:status => 200) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') - end + end context 'and additional reviewers are specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\nAssigned additionally to @JohnSmith for API review\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } - before do + let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\nAssigned additionally to @JohnSmith for API review \\n/cc @SocialcastDevelopers #scgitx\"}" } + it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') stub_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-a', 'a'] - end - it 'should create github pull request' do end # see expectations - it 'should post socialcast message' do end # see expectations - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ "git pull origin FOO", "git pull origin master", @@ -1002,6 +1024,7 @@ def stub_message(message_body, params = {}) end context 'and a developer group is specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @#{another_group} #scgitx\n\n1 file changed" } + let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @#{another_group} #scgitx\"}" } let(:another_group) { 'AnotherDeveloperGroup' } before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') @@ -1013,6 +1036,7 @@ def stub_message(message_body, params = {}) end context 'and additional reviewers are not specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } + let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @SocialcastDevelopers #scgitx\"}" } before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') stub_message message_body, :message_type => 'review_request' diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 1070a31..f7a0308 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,7 +4,7 @@ require 'rspec/mocks' require 'webmock/rspec' require 'pry' - +require 'byebug' require 'socialcast-git-extensions/cli' ENV['SCGITX_TEST'] = 'true' From c7acb1d70cb97f663e82cf3b32b0de5ec615558e Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 14:36:54 -0600 Subject: [PATCH 02/24] add specs for cli createpr and assignpr --- lib/socialcast-git-extensions/cli.rb | 7 +- spec/cli_spec.rb | 104 +++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 6 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index b95e7ee..1072130 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -32,8 +32,7 @@ def initialize(*args) method_option :description, :type => :string, :aliases => '-d', :desc => 'pull request description' # @see http://developer.github.com/v3/pulls/ def createpr - update - + update unless @skip_update description = options[:description] || editor_input(PULL_REQUEST_DESCRIPTION) branch = current_branch repo = current_repo @@ -46,6 +45,8 @@ def createpr method_option :skip_additional_reviewers, :type => :string, :aliases => '-s', :desc => 'Skips adding additional reviewers' # @see http://developer.github.com/v3/pulls/ def assignpr(*additional_reviewers) + update unless @skip_update + primary_mention = if buddy = socialcast_review_buddy(current_user) "assigned to @#{buddy}" end @@ -89,6 +90,8 @@ def assignpr(*additional_reviewers) method_option :skip_additional_reviewers, :type => :string, :aliases => '-s', :desc => 'Skips adding additional reviewers' # @see http://developer.github.com/v3/pulls/ def reviewrequest(*additional_reviewers) + update + @skip_update = true createpr assignpr(*additional_reviewers) end diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index aa7224f..96216ef 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -1026,23 +1026,119 @@ def stub_message(message_body, params = {}) let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @#{another_group} #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @#{another_group} #scgitx\"}" } let(:another_group) { 'AnotherDeveloperGroup' } - before do + it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({'developer_group' => another_group}) stub_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] end - it 'should create github pull request with a different group mentioned' do end # see expectations end context 'and additional reviewers are not specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @SocialcastDevelopers #scgitx\"}" } - before do + it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') stub_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] end - it 'should create github pull request' do end # see expectations + end + end + end + + describe '#createpr' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) + end + context 'when description != nil' do + it do + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). + to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + + Socialcast::Gitx::CLI.start ['createpr', '--description', 'testing'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD" + ]) + end + end + end + + describe '#assignpr' do + context 'when there are no review_buddies specified' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) + end + it do + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with( + :body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}", + :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=>'61', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} + ).to_return(:status => 200, :body => "{}", :headers => {}) + + stub_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD" + ]) + end + end + + context 'when review_buddies are specified via a /config YML file' do + before do + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with( + :body => pr_comment_body, + :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=> pr_comment_body.length, 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} + ).to_return(:status => 200, :body => "{}", :headers => {}) + + stub_request(:patch, "http://github.com/repos/repo/project/issues/1").to_return(:status => 200) + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') + end + context 'and additional reviewers are specified' do + let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\nAssigned additionally to @JohnSmith for API review\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } + let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\nAssigned additionally to @JohnSmith for API review \\n/cc @SocialcastDevelopers #scgitx\"}" } + it do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + stub_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-a', 'a'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD" + ]) + end + end + context 'and a developer group is specified' do + let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @#{another_group} #scgitx\n\n1 file changed" } + let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @#{another_group} #scgitx\"}" } + let(:another_group) { 'AnotherDeveloperGroup' } + it do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({'developer_group' => another_group}) + stub_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + end + end + context 'and additional reviewers are not specified' do + let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } + let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @SocialcastDevelopers #scgitx\"}" } + it do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + stub_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + end end end end From f87a3d0928ff80db7129abf78c735a54ad7bbf0f Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 15:10:50 -0600 Subject: [PATCH 03/24] post a pr comment when integrating and a pr exists --- lib/socialcast-git-extensions/cli.rb | 18 +- spec/cli_spec.rb | 241 +++++++++++++++------------ 2 files changed, 147 insertions(+), 112 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index 1072130..af03b18 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -223,12 +223,26 @@ def integrate(target_branch = prototype_branch) integrate_branch(target_branch, prototype_branch) if target_branch == staging_branch run_cmd "git checkout #{branch}" + current_pr = begin + current_pr_for_branch(current_repo, current_branch) + rescue => e + say e.message.to_s + nil + end + + say("WARNING: Unable to find current pull request. Use `git createpr` to create one.", :red) unless current_pr + + if current_pr && !options[:quiet] + issue_message = "Integrated into #{target_branch} /cc @#{developer_group} #scgitx" + comment_on_issue(current_pr['issue_url'], issue_message) + end + message = <<-EOS.strip_heredoc #worklog integrating #{branch} into #{target_branch} in #{current_repo} #scgitx /cc @#{developer_group} EOS - post message.strip + post message.strip, :force_post => (!current_pr && !options[:quiet]) end desc 'promote', '(DEPRECATED) promote the current branch into staging' @@ -316,7 +330,7 @@ def enforce_staging_before_release? # post a message in socialcast # skip sharing message if CLI quiet option is present or config quiet option is 'true' def post(message, params = {}) - return if options[:quiet] || config['quiet'] == 'true' + return if (options[:quiet] || config['quiet'] == 'true') && !options[:force_post] ActiveResource::Base.logger = Logger.new(STDOUT) if options[:trace] Socialcast::CommandLine::Message.configure_from_credentials response = Socialcast::CommandLine::Message.create params.merge(:body => message) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 96216ef..e5a35fd 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -25,12 +25,10 @@ def stub_message(message_body, params = {}) end describe '#update' do - before do + it do expect_any_instance_of(Socialcast::Gitx::CLI).not_to receive(:post) Socialcast::Gitx::CLI.start ['update'] - end - it 'should not post message to socialcast' do end # see expectations - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ 'git pull origin FOO', 'git pull origin master', @@ -40,107 +38,135 @@ def stub_message(message_body, params = {}) end describe '#integrate' do - context 'when target branch is ommitted' do + context 'with no existing pull request' do before do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - - Socialcast::Gitx::CLI.start ['integrate'] + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch") + .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) + .to_return(:status => 200, :body => "[]", :headers => {}) end - it 'should post message to socialcast' do end # see expectations - it 'should default to prototype' do - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + context 'when target branch is omitted' do + it 'defaults to prototype' do + stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + + Socialcast::Gitx::CLI.start ['integrate'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) + end end - end - context 'when target branch is ommitted with custom prototype branch' do - before do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:prototype_branch).and_return('special-prototype') + context 'when target branch is omitted with custom prototype branch' do + it 'defaults to the custom prototype branch' do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:prototype_branch).and_return('special-prototype') - stub_message "#worklog integrating FOO into special-prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + stub_message "#worklog integrating FOO into special-prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true - Socialcast::Gitx::CLI.start ['integrate'] + Socialcast::Gitx::CLI.start ['integrate'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D special-prototype", + "git fetch origin", + "git checkout special-prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) + end end - it 'should post message to socialcast' do end # see expectations - it 'should default to prototype' do - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D special-prototype", - "git fetch origin", - "git checkout special-prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + context 'when target branch == prototype' do + it do + stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + + Socialcast::Gitx::CLI.start ['integrate', 'prototype'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) + end end - end - context 'when target branch == prototype' do - before do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + context 'when target branch == staging' do + it do + stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + + Socialcast::Gitx::CLI.start ['integrate', 'staging'] - Socialcast::Gitx::CLI.start ['integrate', 'prototype'] + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D staging", + "git fetch origin", + "git checkout staging", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . staging", + "git push origin HEAD", + "git checkout staging", + "git checkout FOO" + ]) + end end - it 'should post message to socialcast' do end # see expectations - it 'should run expected commands' do - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + context 'when target branch != staging || prototype' do + it do + expect { + Socialcast::Gitx::CLI.start ['integrate', 'asdfasdfasdf'] + }.to raise_error(/Only aggregate branches are allowed for integration/) + end end end - context 'when target branch == staging' do + context 'with an existing pull request' do before do - stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - - Socialcast::Gitx::CLI.start ['integrate', 'staging'] + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}])) end - it 'should post message to socialcast' do end # see expectations - it 'should also integrate into prototype and run expected commands' do - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D staging", - "git fetch origin", - "git checkout staging", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . staging", - "git push origin HEAD", - "git checkout staging", - "git checkout FOO" - ]) - end - end - context 'when target branch != staging || prototype' do - it 'should raise an error' do - expect { - Socialcast::Gitx::CLI.start ['integrate', 'asdfasdfasdf'] - }.to raise_error(/Only aggregate branches are allowed for integration/) + it 'comments on the PR and does not force a post' do + stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => false + + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with( + :body => "{\"body\":\"Integrated into prototype /cc @SocialcastDevelopers #scgitx\"}", + ).to_return(:status => 200, :body => "{}", :headers => {}) + + Socialcast::Gitx::CLI.start ['integrate'] + + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) end end end @@ -162,15 +188,13 @@ def stub_message(message_body, params = {}) end end context 'when user confirms release' do - before do + it do stub_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) Socialcast::Gitx::CLI.start ['release'] - end - it 'should post message to socialcast' do end # see expectations - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ "git branch -D last_known_good_staging", "git fetch origin", @@ -248,19 +272,16 @@ def stub_message(message_body, params = {}) end context 'with alternative base branch via config file' do - before do + it do stub_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return( { 'base_branch' => 'special-master' }) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) Socialcast::Gitx::CLI.start ['release'] - end - it 'should post message to socialcast' do end # see expectations - it "treats the alternative base branch as reserved" do + expect(Socialcast::Gitx::CLI.new.send(:reserved_branches)).to include 'special-master' - end - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ "git branch -D last_known_good_staging", "git fetch origin", @@ -296,11 +317,9 @@ def stub_message(message_body, params = {}) after do ENV.delete('BASE_BRANCH') end - it "treats the alternative base branch as reserved" do + it do expect(Socialcast::Gitx::CLI.new.send(:reserved_branches)).to include 'special-master' - end - it 'should post message to socialcast' do end # see expectations - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ "git branch -D last_known_good_staging", "git fetch origin", @@ -339,9 +358,7 @@ def stub_message(message_body, params = {}) it "treats the alternative base branch as reserved" do expect(Socialcast::Gitx::CLI.new.send(:reserved_branches)).to include 'special-master' expect(Socialcast::Gitx::CLI.new.send(:reserved_branches)).to include 'extra-special-master' - end - it 'should post message to socialcast' do end # see expectations - it 'should run expected commands' do + expect(stubbed_executed_commands).to eq([ "git branch -D last_known_good_staging", "git fetch origin", @@ -1145,7 +1162,11 @@ def stub_message(message_body, params = {}) describe '#promote' do before do - stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch") + .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) + .to_return(:status => 200, :body => "[]", :headers => {}) + + stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true Socialcast::Gitx::CLI.start ['promote'] end it 'should integrate into staging' do From 4fb5a666517ad9874df79590f006d2754439c869 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 15:20:40 -0600 Subject: [PATCH 04/24] add bins for assignpr and creatpr, and update readme --- README.md | 10 +++++++++- bin/git-assignpr | 4 ++++ bin/git-createpr | 4 ++++ lib/socialcast-git-extensions/version.rb | 2 +- socialcast-git-extensions.gemspec | 2 +- 5 files changed, 19 insertions(+), 3 deletions(-) create mode 100755 bin/git-assignpr create mode 100755 bin/git-createpr diff --git a/README.md b/README.md index 804f4d5..6045fcd 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,17 @@ Find pull requests on github including a given commit List branches merged into remote origin/`branch` and not also merged into origin/`base_branch` +## git createpr + +create a pull request on github for the current branch, without assigning it for review. + ## git reviewrequest -create a pull request on github for peer review of the current branch. +create and assign a pull request on github for peer review of the current branch. See `assignpr` for additional options. + +## git assignpr + +assign the pull request on github for the current branch for peer review. ### Optional: Specify a Review Buddy mapping that will reference the local Github username and @mention a pre-assigned review buddy in the Socialcast Review Request message. Specify the mapping by creating a .scgitx YML file relative to the Repo Root: config/scgitx.yml with the following format: diff --git a/bin/git-assignpr b/bin/git-assignpr new file mode 100755 index 0000000..fe1dc88 --- /dev/null +++ b/bin/git-assignpr @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby + +require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb') +Socialcast::Gitx::CLI.start (['assignpr'] + ARGV) diff --git a/bin/git-createpr b/bin/git-createpr new file mode 100755 index 0000000..23ee63c --- /dev/null +++ b/bin/git-createpr @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby + +require File.join(File.dirname(__FILE__), '..', 'lib', 'socialcast-git-extensions', 'cli.rb') +Socialcast::Gitx::CLI.start (['createpr'] + ARGV) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index 46d9b20..faf699f 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "3.3" + VERSION = "4.0.beta2" end end diff --git a/socialcast-git-extensions.gemspec b/socialcast-git-extensions.gemspec index c391c11..5d562d1 100644 --- a/socialcast-git-extensions.gemspec +++ b/socialcast-git-extensions.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.add_runtime_dependency 'rugged', '>= 0.23' s.add_runtime_dependency 'socialcast', '~> 1.3.0' - s.add_runtime_dependency 'activesupport', '~> 4.0' + s.add_runtime_dependency 'activesupport', '>= 4.0' s.add_runtime_dependency 'rest-client', '~> 1.7' s.add_runtime_dependency 'thor', '~> 0.19.1' s.add_runtime_dependency 'rake', '~> 10.3' From bdb116cf3ddcecda233a8c2f1c7762bcdbf095c4 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 15:48:07 -0600 Subject: [PATCH 05/24] fix pull_requests_for_branch --- lib/socialcast-git-extensions/github.rb | 4 ++-- spec/cli_spec.rb | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index aa5b46e..616dca8 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -53,10 +53,10 @@ def pull_requests_for_commit(repo, commit_hash) # find the PRs for a given branch # https://developer.github.com/v3/pulls/#list-pull-requests - def pull_requests_for_branch(branch, repo, options = {}) + def pull_requests_for_branch(repo, branch, options = {}) query = "base=#{branch}" query = "#{query}&state=#{options[:state]}" if options[:state] - github_api_request "GET", "repos/#{repo}/pulls?base=branch" + github_api_request "GET", "repos/#{repo}/pulls?base=#{branch}" end # find the current PR for a given branch diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index e5a35fd..5518f1f 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -40,7 +40,7 @@ def stub_message(message_body, params = {}) describe '#integrate' do context 'with no existing pull request' do before do - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch") + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO") .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) .to_return(:status => 200, :body => "[]", :headers => {}) end @@ -142,7 +142,7 @@ def stub_message(message_body, params = {}) end context 'with an existing pull request' do before do - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch") + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO") .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}])) end it 'comments on the PR and does not force a post' do @@ -987,7 +987,7 @@ def stub_message(message_body, params = {}) stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") @@ -1013,7 +1013,7 @@ def stub_message(message_body, params = {}) before do stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") .with( @@ -1088,7 +1088,7 @@ def stub_message(message_body, params = {}) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) end it do - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") @@ -1111,7 +1111,7 @@ def stub_message(message_body, params = {}) context 'when review_buddies are specified via a /config YML file' do before do - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") .with( @@ -1162,7 +1162,7 @@ def stub_message(message_body, params = {}) describe '#promote' do before do - stub_request(:get, "https://api.github.com/repos/FOO/pulls?base=branch") + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO") .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) .to_return(:status => 200, :body => "[]", :headers => {}) From b48d21bc2e9cefb89ab7c907af989ab68386b9cc Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 15:48:28 -0600 Subject: [PATCH 06/24] bump version --- lib/socialcast-git-extensions/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index faf699f..aa8f4ca 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta2" + VERSION = "4.0.beta3" end end From 36145479c5e281159be76187123aea05775747c6 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:23:54 -0600 Subject: [PATCH 07/24] fix prs-for-branch lookup --- lib/socialcast-git-extensions/github.rb | 3 ++- spec/cli_spec.rb | 14 +++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index 616dca8..30bb3a8 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -56,7 +56,8 @@ def pull_requests_for_commit(repo, commit_hash) def pull_requests_for_branch(repo, branch, options = {}) query = "base=#{branch}" query = "#{query}&state=#{options[:state]}" if options[:state] - github_api_request "GET", "repos/#{repo}/pulls?base=#{branch}" + head_name = "#{repo.split('/').first}:#{branch}" + github_api_request "GET", "repos/#{repo}/pulls?head=#{head_name}" end # find the current PR for a given branch diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 5518f1f..683f617 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -40,7 +40,7 @@ def stub_message(message_body, params = {}) describe '#integrate' do context 'with no existing pull request' do before do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO") + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) .to_return(:status => 200, :body => "[]", :headers => {}) end @@ -142,7 +142,7 @@ def stub_message(message_body, params = {}) end context 'with an existing pull request' do before do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO") + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}])) end it 'comments on the PR and does not force a post' do @@ -987,7 +987,7 @@ def stub_message(message_body, params = {}) stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") @@ -1013,7 +1013,7 @@ def stub_message(message_body, params = {}) before do stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") .with( @@ -1088,7 +1088,7 @@ def stub_message(message_body, params = {}) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) end it do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") @@ -1111,7 +1111,7 @@ def stub_message(message_body, params = {}) context 'when review_buddies are specified via a /config YML file' do before do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO"). + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") .with( @@ -1162,7 +1162,7 @@ def stub_message(message_body, params = {}) describe '#promote' do before do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?base=FOO") + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) .to_return(:status => 200, :body => "[]", :headers => {}) From 56f5465e8a45aee9795fb0c3273a6561c6b590cc Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:24:07 -0600 Subject: [PATCH 08/24] bump version --- lib/socialcast-git-extensions/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index aa8f4ca..f7a8dc4 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta3" + VERSION = "4.0.beta4" end end From 4dba2375b65ae993aa0a4d970f779a62e8e9d61b Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:30:49 -0600 Subject: [PATCH 09/24] fix config-quiet option check --- lib/socialcast-git-extensions/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index af03b18..7e94286 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -330,7 +330,7 @@ def enforce_staging_before_release? # post a message in socialcast # skip sharing message if CLI quiet option is present or config quiet option is 'true' def post(message, params = {}) - return if (options[:quiet] || config['quiet'] == 'true') && !options[:force_post] + return if (options[:quiet] || config['quiet'] == true) && !options[:force_post] ActiveResource::Base.logger = Logger.new(STDOUT) if options[:trace] Socialcast::CommandLine::Message.configure_from_credentials response = Socialcast::CommandLine::Message.create params.merge(:body => message) From df27616bd0ee0882f14e08a194fd90d754e0b71a Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:31:08 -0600 Subject: [PATCH 10/24] bump version --- lib/socialcast-git-extensions/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index f7a8dc4..2d04bf9 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta4" + VERSION = "4.0.beta5" end end From 3e893fafbea7b9e0c37aaf0e1708ed90d358ac73 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:36:56 -0600 Subject: [PATCH 11/24] fix assignee check --- lib/socialcast-git-extensions/cli.rb | 3 ++- lib/socialcast-git-extensions/version.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index 7e94286..a1a38f5 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -75,7 +75,8 @@ def assignpr(*additional_reviewers) issue_url = current_pr['issue_url'] url = current_pr['html_url'] - assign_pull_request(assignee, issue_url) if assignee = github_review_buddy(current_user) + assignee = github_review_buddy(current_user) + assign_pull_request(assignee, issue_url) if assignee issue_message = ['#reviewrequest', primary_mention, secondary_mention, "\n/cc @#{developer_group} #scgitx"].compact.join(' ') comment_on_issue(issue_url, issue_message) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index 2d04bf9..184d89f 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta5" + VERSION = "4.0.beta6" end end From e55bc8b807d9916fe778c51e94aa9c5f92be62e1 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:42:18 -0600 Subject: [PATCH 12/24] fix assign_pull_request moar --- lib/socialcast-git-extensions/github.rb | 6 +----- lib/socialcast-git-extensions/version.rb | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index 30bb3a8..397b518 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -67,13 +67,9 @@ def current_pr_for_branch(repo, branch) prs.first end - # returns the issue_url for the PR - def assign_pull_request(branch, repo, assignee) + def assign_pull_request(assignee, issue_url) issue_payload = { :title => branch, :assignee => assignee }.to_json - issue_url = current_pr_for_branch(repo, branch)['issue_url'] - raise "Unable to determine issue_url for branch #{branch} in #{repo}" unless issue_url github_api_request "PATCH", issue_url, issue_payload - issue_url rescue => e say "Failed to assign pull request: #{e.message}", :red end diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index 184d89f..92d8c7d 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta6" + VERSION = "4.0.beta7" end end From f48a0cafbf4b32a4f4beac9ef14df866099574b2 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:46:49 -0600 Subject: [PATCH 13/24] moar fixt --- lib/socialcast-git-extensions/github.rb | 2 +- lib/socialcast-git-extensions/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index 397b518..524e011 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -68,7 +68,7 @@ def current_pr_for_branch(repo, branch) end def assign_pull_request(assignee, issue_url) - issue_payload = { :title => branch, :assignee => assignee }.to_json + issue_payload = { :assignee => assignee }.to_json github_api_request "PATCH", issue_url, issue_payload rescue => e say "Failed to assign pull request: #{e.message}", :red diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index 92d8c7d..07a85f2 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta7" + VERSION = "4.0.beta8" end end From 826c33b29215208c536b6499dac0afad353d2b42 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:52:06 -0600 Subject: [PATCH 14/24] skip ccing the group on integrate messages --- lib/socialcast-git-extensions/cli.rb | 2 +- spec/cli_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index a1a38f5..d425bf1 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -234,7 +234,7 @@ def integrate(target_branch = prototype_branch) say("WARNING: Unable to find current pull request. Use `git createpr` to create one.", :red) unless current_pr if current_pr && !options[:quiet] - issue_message = "Integrated into #{target_branch} /cc @#{developer_group} #scgitx" + issue_message = "Integrated into #{target_branch}" comment_on_issue(current_pr['issue_url'], issue_message) end diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 683f617..7640573 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -150,7 +150,7 @@ def stub_message(message_body, params = {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") .with( - :body => "{\"body\":\"Integrated into prototype /cc @SocialcastDevelopers #scgitx\"}", + :body => "{\"body\":\"Integrated into prototype\"}", ).to_return(:status => 200, :body => "{}", :headers => {}) Socialcast::Gitx::CLI.start ['integrate'] From 853ad9ce3206fe7a500138792fbe32c95652ff23 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Fri, 19 Feb 2016 16:52:23 -0600 Subject: [PATCH 15/24] bump vesion --- lib/socialcast-git-extensions/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index 07a85f2..bf8ae6c 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta8" + VERSION = "4.0.beta9" end end From 522538c0b1e70a2c27da8eea00376e315056be00 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 09:01:06 -0600 Subject: [PATCH 16/24] do not always suppress sc posts, only in pr-relevant actions --- lib/socialcast-git-extensions/cli.rb | 54 ++++++++------ spec/cli_spec.rb | 105 +++++++++++---------------- 2 files changed, 74 insertions(+), 85 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index d425bf1..c3ec65d 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -78,11 +78,13 @@ def assignpr(*additional_reviewers) assignee = github_review_buddy(current_user) assign_pull_request(assignee, issue_url) if assignee - issue_message = ['#reviewrequest', primary_mention, secondary_mention, "\n/cc @#{developer_group} #scgitx"].compact.join(' ') - comment_on_issue(issue_url, issue_message) - - review_message = ["#reviewrequest for #{branch} in #{current_repo}", "PR #{url} #{primary_mention}", '', current_pr['body'], '', secondary_mention, "/cc @#{developer_group} #scgitx", '', changelog_summary(branch)].compact.join("\n").gsub(/\n{2,}/, "\n\n") - post review_message, :message_type => 'review_request' + if use_pr_comments? + issue_message = ['#reviewrequest', primary_mention, secondary_mention, "\n/cc @#{developer_group} #scgitx"].compact.join(' ') + comment_on_issue(issue_url, issue_message) + else + review_message = ["#reviewrequest for #{branch} in #{current_repo}", "PR #{url} #{primary_mention}", '', current_pr['body'], '', secondary_mention, "/cc @#{developer_group} #scgitx", '', changelog_summary(branch)].compact.join("\n").gsub(/\n{2,}/, "\n\n") + post review_message, :message_type => 'review_request' + end end desc "reviewrequest", "Create and assign a pull request on github" @@ -135,15 +137,17 @@ def backportpr(pull_request_num, maintenance_branch) assign_pull_request(assignee, pr_hash['issue_url']) if assignee reviewer_mention = "@#{socialcast_reviwer}" if socialcast_reviewer - issue_message = ['#reviewrequest backport', reviewer_mention, "/cc @#{developer_group} #scgitx"].compact.join(' ') - comment_on_issue(pr_hash['issue_url'], issue_message) - - review_message = ["#reviewrequest backport ##{pull_request_num} to #{maintenance_branch} in #{current_repo} #scgitx"] - if socialcast_reviewer - review_message << "/cc #{reviewer_mention} for #backport track" + if use_pr_comments? + issue_message = ['#reviewrequest backport', reviewer_mention, "/cc @#{developer_group} #scgitx"].compact.join(' ') + comment_on_issue(pr_hash['issue_url'], issue_message) + else + review_message = ["#reviewrequest backport ##{pull_request_num} to #{maintenance_branch} in #{current_repo} #scgitx"] + if socialcast_reviewer + review_message << "/cc #{reviewer_mention} for #backport track" + end + review_message << "/cc @#{developer_group}" + post review_message.join("\n\n"), :url => pr_hash['html_url'], :message_type => 'review_request' end - review_message << "/cc @#{developer_group}" - post review_message.join("\n\n"), :url => pr_hash['html_url'], :message_type => 'review_request' ensure ENV['BASE_BRANCH'] = original_base_branch end @@ -233,17 +237,17 @@ def integrate(target_branch = prototype_branch) say("WARNING: Unable to find current pull request. Use `git createpr` to create one.", :red) unless current_pr - if current_pr && !options[:quiet] + if use_pr_comments? && current_pr issue_message = "Integrated into #{target_branch}" - comment_on_issue(current_pr['issue_url'], issue_message) - end - - message = <<-EOS.strip_heredoc - #worklog integrating #{branch} into #{target_branch} in #{current_repo} #scgitx - /cc @#{developer_group} - EOS + comment_on_issue(current_pr['issue_url'], issue_message) unless options[:quiet] + else + message = <<-EOS.strip_heredoc + #worklog integrating #{branch} into #{target_branch} in #{current_repo} #scgitx + /cc @#{developer_group} + EOS - post message.strip, :force_post => (!current_pr && !options[:quiet]) + post message.strip + end end desc 'promote', '(DEPRECATED) promote the current branch into staging' @@ -328,10 +332,14 @@ def enforce_staging_before_release? !!config['enforce_staging_before_release'] end + def use_pr_comments? + config['comment_via_pull_request'] == true + end + # post a message in socialcast # skip sharing message if CLI quiet option is present or config quiet option is 'true' def post(message, params = {}) - return if (options[:quiet] || config['quiet'] == true) && !options[:force_post] + return if options[:quiet] ActiveResource::Base.logger = Logger.new(STDOUT) if options[:trace] Socialcast::CommandLine::Message.configure_from_credentials response = Socialcast::CommandLine::Message.create params.merge(:body => message) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 7640573..fb38c61 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -41,12 +41,11 @@ def stub_message(message_body, params = {}) context 'with no existing pull request' do before do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") - .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) .to_return(:status => 200, :body => "[]", :headers => {}) end context 'when target branch is omitted' do it 'defaults to prototype' do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate'] @@ -68,7 +67,7 @@ def stub_message(message_body, params = {}) it 'defaults to the custom prototype branch' do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:prototype_branch).and_return('special-prototype') - stub_message "#worklog integrating FOO into special-prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + stub_message "#worklog integrating FOO into special-prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate'] @@ -88,7 +87,7 @@ def stub_message(message_body, params = {}) end context 'when target branch == prototype' do it do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate', 'prototype'] @@ -108,7 +107,7 @@ def stub_message(message_body, params = {}) end context 'when target branch == staging' do it do - stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate', 'staging'] @@ -146,12 +145,11 @@ def stub_message(message_body, params = {}) .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}])) end it 'comments on the PR and does not force a post' do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => false + stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with( - :body => "{\"body\":\"Integrated into prototype\"}", - ).to_return(:status => 200, :body => "{}", :headers => {}) + .with(:body => "{\"body\":\"Integrated into prototype\"}") + .to_return(:status => 200, :body => "{}", :headers => {}) Socialcast::Gitx::CLI.start ['integrate'] @@ -883,28 +881,21 @@ def stub_message(message_body, params = {}) } ] - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59"). - with(:headers => { 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip, deflate', 'Authorization' => /token\s\w+/, 'Content-Type' => 'application/json', 'User-Agent' => 'socialcast-git-extensions' }). - to_return(:status => 200, :body => pr_response.to_json, :headers => {}) - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59/commits"). - with(:headers => { 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip, deflate', 'Authorization' => /token\s\w+/, 'Content-Type' => 'application/json', 'User-Agent' => 'socialcast-git-extensions' }). - to_return(:status => 200, :body => commits_response.to_json, :headers => {}) - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). - with(:body => "{\"title\":\"backport_59_to_v1.x\",\"base\":\"v1.x\",\"head\":\"backport_59_to_v1.x\",\"body\":\"Backport #59 to https://github.com/socialcast/socialcast-git-extensions/tree/v1.x\\n***\\nsimply testing this out\"}", - :headers => { 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip, deflate', 'Authorization' => /token\s\w+/, 'Content-Type' => 'application/json', 'User-Agent'=>'socialcast-git-extensions' }). - to_return(:status => 200, :body => '{"html_url": "https://github.com/socialcast/socialcast-git-extensions/pulls/60", "issue_url": "https://api.github.com/repos/repo/project/issues/60"}', :headers => { 'Content-Type' => 'application/json' }) + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59") + .to_return(:status => 200, :body => pr_response.to_json, :headers => {}) + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59/commits") + .to_return(:status => 200, :body => commits_response.to_json, :headers => {}) + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") + .with(:body => "{\"title\":\"backport_59_to_v1.x\",\"base\":\"v1.x\",\"head\":\"backport_59_to_v1.x\",\"body\":\"Backport #59 to https://github.com/socialcast/socialcast-git-extensions/tree/v1.x\\n***\\nsimply testing this out\"}") + .to_return(:status => 200, :body => '{"html_url": "https://github.com/socialcast/socialcast-git-extensions/pulls/60", "issue_url": "https://api.github.com/repos/repo/project/issues/60"}', :headers => { 'Content-Type' => 'application/json' }) stub_request(:post, "https://api.github.com/repos/repo/project/issues/60/comments") - .with( - :body => "{\"body\":\"#reviewrequest backport /cc @SocialcastDevelopers #scgitx\"}", - :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=>'68', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} - ).to_return(:status => 200, :body => "{}", :headers => {}) + .with(:body => "{\"body\":\"#reviewrequest backport /cc @SocialcastDevelopers #scgitx\"}") + .to_return(:status => 200, :body => "{}", :headers => {}) stub_request(:post, "https://testuser:testpassword@testdomain/api/messages.json") - .with( - :body => "{\"message\":{\"url\":\"https://github.com/socialcast/socialcast-git-extensions/pulls/60\",\"message_type\":\"review_request\",\"body\":\"#reviewrequest backport #59 to v1.x in socialcast/socialcast-git-extensions #scgitx\\n\\n/cc @SocialcastDevelopers\"}}", - :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/json', 'User-Agent'=>'Ruby'} - ).to_return(:status => 200, :body => "", :headers => {}) + .with(:body => "{\"message\":{\"url\":\"https://github.com/socialcast/socialcast-git-extensions/pulls/60\",\"message_type\":\"review_request\",\"body\":\"#reviewrequest backport #59 to v1.x in socialcast/socialcast-git-extensions #scgitx\\n\\n/cc @SocialcastDevelopers\"}}") + .to_return(:status => 200, :body => "", :headers => {}) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:backportpr).and_call_original Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] @@ -966,9 +957,8 @@ def stub_message(message_body, params = {}) }] } - stub_request(:get, "https://api.github.com/search/issues?q=abc123%20type:pr%20repo:socialcast/socialcast-git-extensions"). - with(:headers => { 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip, deflate', 'Authorization' => /token\s\w+/, 'Content-Type' => 'application/json', 'User-Agent' => 'socialcast-git-extensions'}). - to_return(:status => 200, :body => stub_response.to_json, :headers => {}) + stub_request(:get, "https://api.github.com/search/issues?q=abc123%20type:pr%20repo:socialcast/socialcast-git-extensions") + .to_return(:status => 200, :body => stub_response.to_json, :headers => {}) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:findpr).and_call_original allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:say).with("Searching github pull requests for abc123") allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:say).with("\nhttps://github.com/batterseapower/pinyin-toolkit/issues/132\n\tLine Number Indexes Beyond 20 Not Displayed\n\tNick3C 2009-07-12T20:10:41Z") @@ -984,17 +974,15 @@ def stub_message(message_body, params = {}) end context 'when description != nil' do it do - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). - to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") + .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). - to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with( - :body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}", - :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=>'61', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} - ).to_return(:status => 200, :body => "{}", :headers => {}) + .with(:body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}") + .to_return(:status => 200, :body => "{}", :headers => {}) stub_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') @@ -1011,15 +999,13 @@ def stub_message(message_body, params = {}) context 'when review_buddies are specified via a /config YML file' do before do - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). - to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). - to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") + .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with( - :body => pr_comment_body, - :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=> pr_comment_body.length, 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} - ).to_return(:status => 200, :body => "{}", :headers => {}) + .with(:body => pr_comment_body) + .to_return(:status => 200, :body => "{}", :headers => {}) stub_request(:patch, "http://github.com/repos/repo/project/issues/1").to_return(:status => 200) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') @@ -1068,8 +1054,8 @@ def stub_message(message_body, params = {}) end context 'when description != nil' do it do - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls"). - to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") + .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) Socialcast::Gitx::CLI.start ['createpr', '--description', 'testing'] @@ -1088,14 +1074,12 @@ def stub_message(message_body, params = {}) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) end it do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). - to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with( - :body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}", - :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=>'61', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} - ).to_return(:status => 200, :body => "{}", :headers => {}) + .with(:body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}") + .to_return(:status => 200, :body => "{}", :headers => {}) stub_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') @@ -1111,13 +1095,11 @@ def stub_message(message_body, params = {}) context 'when review_buddies are specified via a /config YML file' do before do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO"). - to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with( - :body => pr_comment_body, - :headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Length'=> pr_comment_body.length, 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'} - ).to_return(:status => 200, :body => "{}", :headers => {}) + .with(:body => pr_comment_body) + .to_return(:status => 200, :body => "{}", :headers => {}) stub_request(:patch, "http://github.com/repos/repo/project/issues/1").to_return(:status => 200) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') @@ -1163,10 +1145,9 @@ def stub_message(message_body, params = {}) describe '#promote' do before do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") - .with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'Authorization'=>'token faketoken', 'Content-Type'=>'application/json', 'User-Agent'=>'socialcast-git-extensions'}) .to_return(:status => 200, :body => "[]", :headers => {}) - stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers", :force_post => true + stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['promote'] end it 'should integrate into staging' do From d83e236647d4982c4f543f354fe904a70e09a698 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 10:16:34 -0600 Subject: [PATCH 17/24] tighten up specs --- lib/socialcast-git-extensions/cli.rb | 12 +- spec/cli_spec.rb | 389 ++++++++++++++++++--------- 2 files changed, 271 insertions(+), 130 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index c3ec65d..fa57a22 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -314,12 +314,14 @@ def release integrate_branch(base_branch, staging_branch) cleanup - message = <<-EOS.strip_heredoc - #worklog releasing #{branch} to #{base_branch} in #{current_repo} #scgitx - /cc @#{developer_group} - EOS + unless use_pr_comments? + message = <<-EOS.strip_heredoc + #worklog releasing #{branch} to #{base_branch} in #{current_repo} #scgitx + /cc @#{developer_group} + EOS - post message.strip + post message.strip + end end private diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index fb38c61..397f354 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -3,7 +3,7 @@ describe Socialcast::Gitx::CLI do let(:stubbed_executed_commands) { [] } - def stub_message(message_body, params = {}) + def expect_message(message_body, params = {}) expect(Socialcast::CommandLine::Message).to receive(:create).with(params.merge(:body => message_body)).and_return(double(:permalink_url => 'https://community.socialcast.com/messages/1234')) end @@ -39,13 +39,13 @@ def stub_message(message_body, params = {}) describe '#integrate' do context 'with no existing pull request' do - before do + let!(:github_api_pulls_list) do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .to_return(:status => 200, :body => "[]", :headers => {}) end context 'when target branch is omitted' do it 'defaults to prototype' do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate'] @@ -61,13 +61,14 @@ def stub_message(message_body, params = {}) "git checkout FOO", "git checkout FOO" ]) + expect(github_api_pulls_list).to have_been_requested end end context 'when target branch is omitted with custom prototype branch' do it 'defaults to the custom prototype branch' do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:prototype_branch).and_return('special-prototype') - stub_message "#worklog integrating FOO into special-prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog integrating FOO into special-prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate'] @@ -87,7 +88,7 @@ def stub_message(message_body, params = {}) end context 'when target branch == prototype' do it do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate', 'prototype'] @@ -107,7 +108,7 @@ def stub_message(message_body, params = {}) end context 'when target branch == staging' do it do - stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate', 'staging'] @@ -140,31 +141,61 @@ def stub_message(message_body, params = {}) end end context 'with an existing pull request' do - before do + let!(:github_api_pulls_list) do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}])) end - it 'comments on the PR and does not force a post' do - stub_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - + let!(:github_api_comments_create) do stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") .with(:body => "{\"body\":\"Integrated into prototype\"}") .to_return(:status => 200, :body => "{}", :headers => {}) + end + context 'when use_pr_comments? is false' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(false) + end + it 'does not comment on the PR posts a message' do + expect_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + Socialcast::Gitx::CLI.start ['integrate'] + expect(stubbed_executed_commands).to eq([ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) + expect(github_api_pulls_list).to have_been_requested + expect(github_api_comments_create).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(true) + end + it 'comments on the PR and does not post a message' do Socialcast::Gitx::CLI.start ['integrate'] expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) + expect(github_api_pulls_list).to have_been_requested + expect(github_api_comments_create).to have_been_requested + end end end end @@ -186,37 +217,53 @@ def stub_message(message_body, params = {}) end end context 'when user confirms release' do - it do - stub_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - + before do expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) - Socialcast::Gitx::CLI.start ['release'] - - expect(stubbed_executed_commands).to eq([ - "git branch -D last_known_good_staging", - "git fetch origin", - "git checkout last_known_good_staging", - "git checkout FOO", - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git checkout master", - "git pull origin master", - "git pull . FOO", - "git push origin HEAD", - "git branch -D staging", - "git fetch origin", - "git checkout staging", - "git pull . master", - "git push origin HEAD", - "git checkout master" - ]) + end + shared_examples_for 'releasing the branch' do + it do + expect(stubbed_executed_commands).to eq([ + "git branch -D last_known_good_staging", + "git fetch origin", + "git checkout last_known_good_staging", + "git checkout FOO", + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git checkout master", + "git pull origin master", + "git pull . FOO", + "git push origin HEAD", + "git branch -D staging", + "git fetch origin", + "git checkout staging", + "git pull . master", + "git push origin HEAD", + "git checkout master" + ]) + end + end + context 'when use_pr_comments? is false' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(false) + expect_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + Socialcast::Gitx::CLI.start ['release'] + end + it_behaves_like 'releasing the branch' + end + context 'when use_pr_comments? is true' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(true) + Socialcast::Gitx::CLI.start ['release'] + end + # does not post a message nor a pr comment (github reports "merged" event via webhook)' + it_behaves_like 'releasing the branch' end end context 'when the branch is not in last_known_good_staging' do - context 'and enforce_staging_before_release = true' do + context 'when enforce_staging_before_release = true' do let(:branches_in_last_known_good_staging) { ['another-branch'] } before do expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:enforce_staging_before_release?).and_return(true) @@ -226,16 +273,16 @@ def stub_message(message_body, params = {}) expect { Socialcast::Gitx::CLI.start ['release'] }.to raise_error(RuntimeError, 'Cannot release FOO unless it has already been promoted separately to staging and the build has passed.') end end - context 'and enforce_staging_before_release = false' do + context 'when enforce_staging_before_release = false' do let(:branches_in_last_known_good_staging) { ['another-branch'] } before do - stub_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:enforce_staging_before_release?).and_return(false) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) Socialcast::Gitx::CLI.start ['release'] end - it 'should run expected commands' do + it do expect(stubbed_executed_commands).to eq([ "git pull origin FOO", "git pull origin master", @@ -257,9 +304,9 @@ def stub_message(message_body, params = {}) context 'with reserved_branches via config file' do before do - stub_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog releasing FOO to master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return( { 'reserved_branches' => ['dont-del-me','dont-del-me-2'] }) + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return('reserved_branches' => ['dont-del-me', 'dont-del-me-2']) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) Socialcast::Gitx::CLI.start ['release'] end @@ -271,10 +318,10 @@ def stub_message(message_body, params = {}) context 'with alternative base branch via config file' do it do - stub_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return( { 'base_branch' => 'special-master' }) + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return('base_branch' => 'special-master') expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) Socialcast::Gitx::CLI.start ['release'] @@ -304,7 +351,7 @@ def stub_message(message_body, params = {}) context 'with alternative base branch via environment variable' do before do - stub_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({}) @@ -342,10 +389,10 @@ def stub_message(message_body, params = {}) context 'with alternative base branch via environment variable overriding base branch in config' do before do - stub_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog releasing FOO to special-master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:yes?).and_return(true) - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({ 'base_branch' => 'extra-special-master' }) + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return('base_branch' => 'extra-special-master') expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:cleanup) ENV['BASE_BRANCH'] = 'special-master' Socialcast::Gitx::CLI.start ['release'] @@ -425,10 +472,10 @@ def stub_message(message_body, params = {}) before { allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:branches).and_return([]) } context 'when target branch == staging and --destination == last_known_good_staging' do before do - stub_message "#worklog resetting staging branch to last_known_good_staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog resetting staging branch to last_known_good_staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['nuke', 'staging', '--destination', 'last_known_good_staging'] end - it 'should run expected commands' do + it do expect(stubbed_executed_commands).to eq([ "git checkout master", "git branch -D last_known_good_staging", @@ -445,12 +492,12 @@ def stub_message(message_body, params = {}) end context 'when target branch == qa and destination prompt == nil and using custom aggregate_branches config' do before do - stub_message "#worklog resetting qa branch to last_known_good_qa in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return( { 'aggregate_branches' => ['staging', 'qa'] }) + expect_message "#worklog resetting qa branch to last_known_good_qa in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return('aggregate_branches' => ['staging', 'qa']) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:ask).and_return('') Socialcast::Gitx::CLI.start ['nuke', 'qa'] end - it 'defaults to last_known_good_qa and should run expected commands' do + it 'defaults to last_known_good_qa' do expect(stubbed_executed_commands).to eq([ "git checkout master", "git branch -D last_known_good_qa", @@ -467,12 +514,12 @@ def stub_message(message_body, params = {}) end context 'when target branch == qa and destination prompt = master and using custom aggregate_branches config' do before do - stub_message "#worklog resetting qa branch to last_known_good_master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return( { 'aggregate_branches' => ['staging', 'qa'] }) + expect_message "#worklog resetting qa branch to last_known_good_master in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return('aggregate_branches' => ['staging', 'qa']) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:ask).and_return('master') Socialcast::Gitx::CLI.start ['nuke', 'qa'] end - it 'should run expected commands' do + it do expect(stubbed_executed_commands).to eq([ "git checkout master", "git branch -D last_known_good_master", @@ -498,17 +545,17 @@ def stub_message(message_body, params = {}) end end it 'raises an error when target branch is not an aggregate branch' do + expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:ask).and_return('master') expect { - expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:ask).and_return('master') Socialcast::Gitx::CLI.start ['nuke', 'asdfasdf'] }.to raise_error(/Only aggregate branches are allowed to be reset/) end end describe '#backportpr' do - before do + let(:pr_response) do # https://developer.github.com/v3/search/#search-issues - pr_response = { + { "url" => "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59", "id" => 13712197, "html_url" => "https://github.com/socialcast/socialcast-git-extensions/pull/59", @@ -807,8 +854,9 @@ def stub_message(message_body, params = {}) "deletions" => 2, "changed_files" => 2 } - - commits_response = [ + end + let(:commits_response) do + [ { "sha" => "5e30d5af3f4d1bb3a34cc97568299be028b65f6f", "commit" => { @@ -880,33 +928,63 @@ def stub_message(message_body, params = {}) ] } ] - + end + let!(:github_pr_show) do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59") .to_return(:status => 200, :body => pr_response.to_json, :headers => {}) + end + let!(:github_pr_commits_list) do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls/59/commits") .to_return(:status => 200, :body => commits_response.to_json, :headers => {}) + end + let!(:github_pr_create) do stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") .with(:body => "{\"title\":\"backport_59_to_v1.x\",\"base\":\"v1.x\",\"head\":\"backport_59_to_v1.x\",\"body\":\"Backport #59 to https://github.com/socialcast/socialcast-git-extensions/tree/v1.x\\n***\\nsimply testing this out\"}") .to_return(:status => 200, :body => '{"html_url": "https://github.com/socialcast/socialcast-git-extensions/pulls/60", "issue_url": "https://api.github.com/repos/repo/project/issues/60"}', :headers => { 'Content-Type' => 'application/json' }) - + end + let!(:github_pr_comment_create) do stub_request(:post, "https://api.github.com/repos/repo/project/issues/60/comments") .with(:body => "{\"body\":\"#reviewrequest backport /cc @SocialcastDevelopers #scgitx\"}") .to_return(:status => 200, :body => "{}", :headers => {}) - + end + let!(:socialcast_message_create) do stub_request(:post, "https://testuser:testpassword@testdomain/api/messages.json") .with(:body => "{\"message\":{\"url\":\"https://github.com/socialcast/socialcast-git-extensions/pulls/60\",\"message_type\":\"review_request\",\"body\":\"#reviewrequest backport #59 to v1.x in socialcast/socialcast-git-extensions #scgitx\\n\\n/cc @SocialcastDevelopers\"}}") .to_return(:status => 200, :body => "", :headers => {}) - + end + before do expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:backportpr).and_call_original + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(use_pr_comments) Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] end - it 'creates a branch based on v1.x and cherry-picks in PR 59' do end + context 'when use_pr_comments? is false' do + let(:use_pr_comments) { false } + it 'creates a branch based on v1.x and cherry-picks in PR 59' do + expect(github_pr_show).to have_been_requested + expect(github_pr_commits_list).to have_been_requested + expect(github_pr_create).to have_been_requested + + expect(github_pr_comment_create).to_not have_been_requested + expect(socialcast_message_create).to have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it 'posts a pr comment instead of posting a socialcast message' do + expect(github_pr_show).to have_been_requested + expect(github_pr_commits_list).to have_been_requested + expect(github_pr_create).to have_been_requested + + expect(github_pr_comment_create).to have_been_requested + expect(socialcast_message_create).to_not have_been_requested + end + end end describe '#findpr' do - before do + let(:issue_response) do # https://developer.github.com/v3/search/#search-issues - stub_response = { + { "total_count"=> 280, "items"=> [{ "url" => "https://api.github.com/repos/batterseapower/pinyin-toolkit/issues/132", @@ -956,93 +1034,154 @@ def stub_message(message_body, params = {}) "score" => 1.3859273 }] } - + end + let!(:github_issue_search) do stub_request(:get, "https://api.github.com/search/issues?q=abc123%20type:pr%20repo:socialcast/socialcast-git-extensions") - .to_return(:status => 200, :body => stub_response.to_json, :headers => {}) + .to_return(:status => 200, :body => issue_response.to_json, :headers => {}) + end + it do expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:findpr).and_call_original allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:say).with("Searching github pull requests for abc123") allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:say).with("\nhttps://github.com/batterseapower/pinyin-toolkit/issues/132\n\tLine Number Indexes Beyond 20 Not Displayed\n\tNick3C 2009-07-12T20:10:41Z") Socialcast::Gitx::CLI.start ['findpr', 'abc123'] + expect(github_issue_search).to have_been_requested end - it 'fetches the data from github and prints it out' do end end describe '#reviewrequest' do + let(:git_update_commands) do + [ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD" + ] + end + let!(:github_create_pr) do + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") + .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) + end + let!(:github_find_pr_for_branch) do + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + end + let(:stub_github_create_pr_comment) do + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with(:body => pr_comment_body) + .to_return(:status => 200, :body => "{}", :headers => {}) + end + let(:use_pr_comments) { false } + before do + stub_github_create_pr_comment + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(use_pr_comments) + end context 'when there are no review_buddies specified' do before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) end - context 'when description != nil' do + let(:pr_comment_body) { "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}" } + context 'when use_pr_comments? is false' do it do - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") - .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") - .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + expect_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] - stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with(:body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}") - .to_return(:status => 200, :body => "{}", :headers => {}) + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_create_pr).to have_been_requested + expect(github_find_pr_for_branch).to have_been_requested - stub_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD" - ]) + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_create_pr).to have_been_requested + expect(github_find_pr_for_branch).to have_been_requested + + expect(stub_github_create_pr_comment).to have_been_requested end end end context 'when review_buddies are specified via a /config YML file' do + let!(:github_assign_pr) { stub_request(:patch, "http://api.github.com/repos/repo/project/issues/1").to_return(:status => 200) } before do - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") - .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") - .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) - stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with(:body => pr_comment_body) - .to_return(:status => 200, :body => "{}", :headers => {}) - - stub_request(:patch, "http://github.com/repos/repo/project/issues/1").to_return(:status => 200) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:github_review_buddy).and_return('janedoe') + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') end context 'and additional reviewers are specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\nAssigned additionally to @JohnSmith for API review\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\nAssigned additionally to @JohnSmith for API review \\n/cc @SocialcastDevelopers #scgitx\"}" } - it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - stub_message message_body, :message_type => 'review_request' - Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-a', 'a'] + context 'when use_pr_comments? is false' do + it do + expect_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-a', 'a'] - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD" - ]) + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_assign_pr).to have_been_requested + + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-a', 'a'] + + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_assign_pr).to have_been_requested + + expect(stub_github_create_pr_comment).to have_been_requested + end end end context 'and a developer group is specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @#{another_group} #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @#{another_group} #scgitx\"}" } let(:another_group) { 'AnotherDeveloperGroup' } - it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({'developer_group' => another_group}) - stub_message message_body, :message_type => 'review_request' - Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + end + context 'when use_pr_comments? is false' do + it do + expect_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to have_been_requested + end end end context 'and additional reviewers are not specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @SocialcastDevelopers #scgitx\"}" } - it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - stub_message message_body, :message_type => 'review_request' - Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + context 'when use_pr_comments? is false' do + it do + expect_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to have_been_requested + end end end end @@ -1081,7 +1220,7 @@ def stub_message(message_body, params = {}) .with(:body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}") .to_return(:status => 200, :body => "{}", :headers => {}) - stub_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' + expect_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') Socialcast::Gitx::CLI.start ['assignpr', '-s'] @@ -1109,7 +1248,7 @@ def stub_message(message_body, params = {}) let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\nAssigned additionally to @JohnSmith for API review \\n/cc @SocialcastDevelopers #scgitx\"}" } it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - stub_message message_body, :message_type => 'review_request' + expect_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['assignpr', '-a', 'a'] expect(stubbed_executed_commands).to eq([ @@ -1126,7 +1265,7 @@ def stub_message(message_body, params = {}) it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({'developer_group' => another_group}) - stub_message message_body, :message_type => 'review_request' + expect_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['assignpr', '-s'] end end @@ -1135,7 +1274,7 @@ def stub_message(message_body, params = {}) let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @SocialcastDevelopers #scgitx\"}" } it do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - stub_message message_body, :message_type => 'review_request' + expect_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['assignpr', '-s'] end end @@ -1147,7 +1286,7 @@ def stub_message(message_body, params = {}) stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .to_return(:status => 200, :body => "[]", :headers => {}) - stub_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + expect_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['promote'] end it 'should integrate into staging' do From a85d3b815df6ac5b7bf1c6c285451632fedd883e Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 10:42:23 -0600 Subject: [PATCH 18/24] tighten up specs some more --- spec/cli_spec.rb | 197 +++++++++++++++++++++++++++++------------------ 1 file changed, 123 insertions(+), 74 deletions(-) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 397f354..e3e0781 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -7,6 +7,14 @@ def expect_message(message_body, params = {}) expect(Socialcast::CommandLine::Message).to receive(:create).with(params.merge(:body => message_body)).and_return(double(:permalink_url => 'https://community.socialcast.com/messages/1234')) end + let(:git_update_commands) do + [ + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD" + ] + end + before do Socialcast::Gitx::CLI.instance_eval do # to supress warning from stubbing ldap_config @no_tasks = @no_commands = true @@ -150,10 +158,11 @@ def expect_message(message_body, params = {}) .with(:body => "{\"body\":\"Integrated into prototype\"}") .to_return(:status => 200, :body => "{}", :headers => {}) end + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(use_pr_comments) + end context 'when use_pr_comments? is false' do - before do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(false) - end + let(:use_pr_comments) { false } it 'does not comment on the PR posts a message' do expect_message "#worklog integrating FOO into prototype in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" Socialcast::Gitx::CLI.start ['integrate'] @@ -175,9 +184,7 @@ def expect_message(message_body, params = {}) end end context 'when use_pr_comments? is true' do - before do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(true) - end + let(:use_pr_comments) { true } it 'comments on the PR and does not post a message' do Socialcast::Gitx::CLI.start ['integrate'] @@ -1049,13 +1056,6 @@ def expect_message(message_body, params = {}) end describe '#reviewrequest' do - let(:git_update_commands) do - [ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD" - ] - end let!(:github_create_pr) do stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) @@ -1073,6 +1073,7 @@ def expect_message(message_body, params = {}) before do stub_github_create_pr_comment allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(use_pr_comments) + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') end context 'when there are no review_buddies specified' do before do @@ -1082,7 +1083,6 @@ def expect_message(message_body, params = {}) context 'when use_pr_comments? is false' do it do expect_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] expect(stubbed_executed_commands).to eq(git_update_commands) @@ -1095,7 +1095,6 @@ def expect_message(message_body, params = {}) context 'when use_pr_comments? is true' do let(:use_pr_comments) { true } it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] expect(stubbed_executed_commands).to eq(git_update_commands) @@ -1112,7 +1111,6 @@ def expect_message(message_body, params = {}) before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:github_review_buddy).and_return('janedoe') - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') end context 'and additional reviewers are specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\nAssigned additionally to @JohnSmith for API review\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } @@ -1123,6 +1121,7 @@ def expect_message(message_body, params = {}) Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-a', 'a'] expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_create_pr).to have_been_requested expect(github_assign_pr).to have_been_requested expect(stub_github_create_pr_comment).to_not have_been_requested @@ -1134,6 +1133,7 @@ def expect_message(message_body, params = {}) Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-a', 'a'] expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_create_pr).to have_been_requested expect(github_assign_pr).to have_been_requested expect(stub_github_create_pr_comment).to have_been_requested @@ -1151,6 +1151,7 @@ def expect_message(message_body, params = {}) it do expect_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_create_pr).to have_been_requested expect(github_assign_pr).to have_been_requested expect(stub_github_create_pr_comment).to_not have_been_requested end @@ -1159,6 +1160,7 @@ def expect_message(message_body, params = {}) let(:use_pr_comments) { true } it do Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_create_pr).to have_been_requested expect(github_assign_pr).to have_been_requested expect(stub_github_create_pr_comment).to have_been_requested end @@ -1171,6 +1173,7 @@ def expect_message(message_body, params = {}) it do expect_message message_body, :message_type => 'review_request' Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_create_pr).to have_been_requested expect(github_assign_pr).to have_been_requested expect(stub_github_create_pr_comment).to_not have_been_requested end @@ -1179,6 +1182,7 @@ def expect_message(message_body, params = {}) let(:use_pr_comments) { true } it do Socialcast::Gitx::CLI.start ['reviewrequest', '--description', 'testing', '-s'] + expect(github_create_pr).to have_been_requested expect(github_assign_pr).to have_been_requested expect(stub_github_create_pr_comment).to have_been_requested end @@ -1188,94 +1192,137 @@ def expect_message(message_body, params = {}) end describe '#createpr' do - before do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) + let!(:github_pr_create) do + stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") + .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) end - context 'when description != nil' do - it do - stub_request(:post, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls") - .to_return(:status => 200, :body => %q({"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1"}), :headers => {}) - - Socialcast::Gitx::CLI.start ['createpr', '--description', 'testing'] + it do + Socialcast::Gitx::CLI.start ['createpr', '--description', 'testing'] - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD" - ]) - end + expect(stubbed_executed_commands).to eq git_update_commands + expect(github_pr_create).to have_been_requested end end describe '#assignpr' do + let!(:github_find_pr_for_branch) do + stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") + .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + end + let(:stub_github_create_pr_comment) do + stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") + .with(:body => pr_comment_body) + .to_return(:status => 200, :body => "{}", :headers => {}) + end + let(:use_pr_comments) { false } + before do + stub_github_create_pr_comment + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(use_pr_comments) + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + end context 'when there are no review_buddies specified' do before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config_file).and_return(Pathname('')) end - it do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") - .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) + let(:pr_comment_body) { "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}" } + context 'when use_pr_comments? is false' do + it do + expect_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-s'] - stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with(:body => "{\"body\":\"#reviewrequest \\n/cc @SocialcastDevelopers #scgitx\"}") - .to_return(:status => 200, :body => "{}", :headers => {}) + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_find_pr_for_branch).to have_been_requested - expect_message "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 \n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed", :message_type => 'review_request' - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - Socialcast::Gitx::CLI.start ['assignpr', '-s'] + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['assignpr', '-s'] - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD" - ]) + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_find_pr_for_branch).to have_been_requested + + expect(stub_github_create_pr_comment).to have_been_requested + end end end context 'when review_buddies are specified via a /config YML file' do + let!(:github_assign_pr) { stub_request(:patch, "http://api.github.com/repos/repo/project/issues/1").to_return(:status => 200) } before do - stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") - .to_return(:status => 200, :body => %q([{"html_url": "http://github.com/repo/project/pulls/1", "issue_url": "http://api.github.com/repos/repo/project/issues/1", "body":"testing"}]), :headers => {}) - stub_request(:post, "http://api.github.com/repos/repo/project/issues/1/comments") - .with(:body => pr_comment_body) - .to_return(:status => 200, :body => "{}", :headers => {}) - - stub_request(:patch, "http://github.com/repos/repo/project/issues/1").to_return(:status => 200) allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_review_buddy).and_return('JaneDoe') + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:github_review_buddy).and_return('janedoe') end context 'and additional reviewers are specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\nAssigned additionally to @JohnSmith for API review\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\nAssigned additionally to @JohnSmith for API review \\n/cc @SocialcastDevelopers #scgitx\"}" } - it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - expect_message message_body, :message_type => 'review_request' - Socialcast::Gitx::CLI.start ['assignpr', '-a', 'a'] + context 'when use_pr_comments? is false' do + it do + expect_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-a', 'a'] - expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD" - ]) + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_assign_pr).to have_been_requested + + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['assignpr', '-a', 'a'] + + expect(stubbed_executed_commands).to eq(git_update_commands) + expect(github_assign_pr).to have_been_requested + + expect(stub_github_create_pr_comment).to have_been_requested + end end end context 'and a developer group is specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @#{another_group} #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @#{another_group} #scgitx\"}" } let(:another_group) { 'AnotherDeveloperGroup' } - it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') + before do allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:config).and_return({'developer_group' => another_group}) - expect_message message_body, :message_type => 'review_request' - Socialcast::Gitx::CLI.start ['assignpr', '-s'] + end + context 'when use_pr_comments? is false' do + it do + expect_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to have_been_requested + end end end context 'and additional reviewers are not specified' do let(:message_body) { "#reviewrequest for FOO in socialcast/socialcast-git-extensions\nPR http://github.com/repo/project/pulls/1 assigned to @JaneDoe\n\ntesting\n\n/cc @SocialcastDevelopers #scgitx\n\n1 file changed" } let(:pr_comment_body) { "{\"body\":\"#reviewrequest assigned to @JaneDoe \\n/cc @SocialcastDevelopers #scgitx\"}" } - it do - allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:changelog_summary).and_return('1 file changed') - expect_message message_body, :message_type => 'review_request' - Socialcast::Gitx::CLI.start ['assignpr', '-s'] + context 'when use_pr_comments? is false' do + it do + expect_message message_body, :message_type => 'review_request' + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to_not have_been_requested + end + end + context 'when use_pr_comments? is true' do + let(:use_pr_comments) { true } + it do + Socialcast::Gitx::CLI.start ['assignpr', '-s'] + expect(github_assign_pr).to have_been_requested + expect(stub_github_create_pr_comment).to have_been_requested + end end end end @@ -1285,12 +1332,9 @@ def expect_message(message_body, params = {}) before do stub_request(:get, "https://api.github.com/repos/socialcast/socialcast-git-extensions/pulls?head=socialcast:FOO") .to_return(:status => 200, :body => "[]", :headers => {}) - - expect_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" - Socialcast::Gitx::CLI.start ['promote'] end - it 'should integrate into staging' do - expect(stubbed_executed_commands).to eq([ + let(:staging_integration_commands) do + [ "git pull origin FOO", "git pull origin master", "git push origin HEAD", @@ -1307,7 +1351,12 @@ def expect_message(message_body, params = {}) "git push origin HEAD", "git checkout staging", "git checkout FOO" - ]) + ] + end + it do + expect_message "#worklog integrating FOO into staging in socialcast/socialcast-git-extensions #scgitx\n/cc @SocialcastDevelopers" + Socialcast::Gitx::CLI.start ['promote'] + expect(stubbed_executed_commands).to eq staging_integration_commands end end From ef265ee5a628e263f35a5ddf058649aab310bcc8 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 11:09:20 -0600 Subject: [PATCH 19/24] add spec coverage for github lib changes --- lib/socialcast-git-extensions/github.rb | 4 +- spec/github_spec.rb | 98 +++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 spec/github_spec.rb diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index 524e011..748579a 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -53,9 +53,7 @@ def pull_requests_for_commit(repo, commit_hash) # find the PRs for a given branch # https://developer.github.com/v3/pulls/#list-pull-requests - def pull_requests_for_branch(repo, branch, options = {}) - query = "base=#{branch}" - query = "#{query}&state=#{options[:state]}" if options[:state] + def pull_requests_for_branch(repo, branch) head_name = "#{repo.split('/').first}:#{branch}" github_api_request "GET", "repos/#{repo}/pulls?head=#{head_name}" end diff --git a/spec/github_spec.rb b/spec/github_spec.rb new file mode 100644 index 0000000..e386b4e --- /dev/null +++ b/spec/github_spec.rb @@ -0,0 +1,98 @@ +require 'spec_helper' + +describe Socialcast::Gitx::Github do + let(:test_class) do + Class.new do |k| + include Socialcast::Gitx::Github + + def say(message); end + end + end + let(:said_messages) { [] } + before do + stub_const('TestClass', test_class) + allow_any_instance_of(TestClass).to receive(:'`') do |_instance, _cmd| + raise 'Unstubbed backticks detected' + end + allow_any_instance_of(TestClass).to receive(:say) do |_instance, message| + said_messages << message + end + end + let(:test_instance) { TestClass.new } + let(:branch) { 'my-branch' } + let(:base_branch) { 'master' } + let(:repo) { 'ownername/projectname' } + + describe '#create_pull_request' do + subject { test_instance.send(:create_pull_request, branch, repo, body) } + let(:create_pr_payload) do + { + :title => branch, + :base => base_branch, + :head => branch, + :body => body + } + end + let(:dummy_pr_created_response) { { :dummy => :response } } + let(:body) { 'This is my pull request.' } + before do + allow(test_instance).to receive(:base_branch).and_return(base_branch) + expect(test_instance).to receive(:github_api_request).with('POST', 'repos/ownername/projectname/pulls', create_pr_payload.to_json).and_return(dummy_pr_created_response) + end + it { is_expected.to eq dummy_pr_created_response } + end + + describe '#pull_requests_for_branch' do + subject { test_instance.send(:pull_requests_for_branch, repo, branch) } + let(:dummy_pr_list_response) { [{ :dummy => :response }] } + before do + expect(test_instance).to receive(:github_api_request).with('GET', 'repos/ownername/projectname/pulls?head=ownername:my-branch').and_return(dummy_pr_list_response) + end + it { is_expected.to eq dummy_pr_list_response } + end + + describe '#current_pr_for_branch' do + subject(:current_pr) { test_instance.send(:current_pr_for_branch, repo, branch) } + let(:dummy_pr_one) { { :dummy => :pr1 } } + let(:dummy_pr_two) { { :dummy => :pr2 } } + before do + expect(test_instance).to receive(:pull_requests_for_branch).with(repo, branch).and_return(dummy_pr_list_response) + end + context 'when an empty pr list is returned' do + let(:dummy_pr_list_response) { [] } + it { is_expected.to be_nil } + end + context 'when a single pr is returned' do + let(:dummy_pr_list_response) { [dummy_pr_one] } + it { is_expected.to eq dummy_pr_one } + end + context 'when multiple prs are returned' do + let(:dummy_pr_list_response) { [dummy_pr_one, dummy_pr_two] } + it { expect { current_pr }.to raise_error 'Multiple (2) open PRs for my-branch found in ownername/projectname, unable to proceed' } + end + end + + describe '#assign_pull_request' do + subject { test_instance.send(:assign_pull_request, assignee, issue_url) } + let(:assignee) { 'janedoe' } + let(:issue_url) { 'repos/ownername/projectname/issues/1' } + let(:dummy_assignment_response) { [{ :dummy => :response }] } + let(:assign_payload) { { :assignee => assignee } } + before do + expect(test_instance).to receive(:github_api_request).with('PATCH', 'repos/ownername/projectname/issues/1', assign_payload.to_json).and_return(dummy_assignment_response) + end + it { is_expected.to eq dummy_assignment_response } + end + + describe '#comment_on_issue' do + subject { test_instance.send(:comment_on_issue, issue_url, comment_body) } + let(:issue_url) { 'repos/ownername/projectname/issues/1' } + let(:dummy_comment_response) { { :dummy => :response } } + let(:comment_payload) { { :body => comment_body } } + let(:comment_body) { 'Integrating into staging' } + before do + expect(test_instance).to receive(:github_api_request).with('POST', 'repos/ownername/projectname/issues/1/comments', comment_payload.to_json).and_return(dummy_comment_response) + end + it { is_expected.to eq dummy_comment_response } + end +end From 0fdb0b55168c0cf0a627d0c7710611c314377605 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 11:17:21 -0600 Subject: [PATCH 20/24] update and document config flag as share_via_pr_comments --- README.md | 2 ++ lib/socialcast-git-extensions/cli.rb | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6045fcd..40d8571 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ Test the token with the [`git findpr`](https://github.com/socialcast/socialcast- ### Options * ```--quiet```: suppress posting message in Socialcast +* config/scgitx.yml option `share_via_pr_comments`: Set to `true` to post reviewrequest and integration messages +as pull request comments instead of Socialcast posts. ## git start diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index fa57a22..24a9b7a 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -335,11 +335,11 @@ def enforce_staging_before_release? end def use_pr_comments? - config['comment_via_pull_request'] == true + config['share_via_pr_comments'] == true end # post a message in socialcast - # skip sharing message if CLI quiet option is present or config quiet option is 'true' + # skip sharing message if CLI quiet option is present def post(message, params = {}) return if options[:quiet] ActiveResource::Base.logger = Logger.new(STDOUT) if options[:trace] From ecf8763a428257df5b53f7614ad6ec79b3c81d25 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 11:18:01 -0600 Subject: [PATCH 21/24] bump version to rc --- lib/socialcast-git-extensions/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index bf8ae6c..d04c55d 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.beta9" + VERSION = "4.0.rc1" end end From 587ece311b964171f976b2bf5e785ebff1f8cd6a Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 11:52:30 -0600 Subject: [PATCH 22/24] fakerubocop --- spec/cli_spec.rb | 100 +++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index e3e0781..303b03a 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -58,17 +58,17 @@ def expect_message(message_body, params = {}) Socialcast::Gitx::CLI.start ['integrate'] expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) expect(github_api_pulls_list).to have_been_requested end end @@ -81,17 +81,17 @@ def expect_message(message_body, params = {}) Socialcast::Gitx::CLI.start ['integrate'] expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D special-prototype", - "git fetch origin", - "git checkout special-prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D special-prototype", + "git fetch origin", + "git checkout special-prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) end end context 'when target branch == prototype' do @@ -101,17 +101,17 @@ def expect_message(message_body, params = {}) Socialcast::Gitx::CLI.start ['integrate', 'prototype'] expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git checkout FOO" - ]) + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git checkout FOO" + ]) end end context 'when target branch == staging' do @@ -121,23 +121,23 @@ def expect_message(message_body, params = {}) Socialcast::Gitx::CLI.start ['integrate', 'staging'] expect(stubbed_executed_commands).to eq([ - "git pull origin FOO", - "git pull origin master", - "git push origin HEAD", - "git branch -D staging", - "git fetch origin", - "git checkout staging", - "git pull . FOO", - "git push origin HEAD", - "git checkout FOO", - "git branch -D prototype", - "git fetch origin", - "git checkout prototype", - "git pull . staging", - "git push origin HEAD", - "git checkout staging", - "git checkout FOO" - ]) + "git pull origin FOO", + "git pull origin master", + "git push origin HEAD", + "git branch -D staging", + "git fetch origin", + "git checkout staging", + "git pull . FOO", + "git push origin HEAD", + "git checkout FOO", + "git branch -D prototype", + "git fetch origin", + "git checkout prototype", + "git pull . staging", + "git push origin HEAD", + "git checkout staging", + "git checkout FOO" + ]) end end context 'when target branch != staging || prototype' do From 6e7cc30db6ac94351e3f7ce7513aa33d08a73e04 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sat, 20 Feb 2016 12:00:33 -0600 Subject: [PATCH 23/24] text cleanup --- lib/socialcast-git-extensions/github.rb | 2 -- spec/cli_spec.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/socialcast-git-extensions/github.rb b/lib/socialcast-git-extensions/github.rb index 748579a..9d6c764 100644 --- a/lib/socialcast-git-extensions/github.rb +++ b/lib/socialcast-git-extensions/github.rb @@ -78,8 +78,6 @@ def comment_on_issue(issue_url, comment_body) github_api_request 'POST', "#{issue_url}/comments", { :body => comment_body }.to_json end - # https://developer.github.com/v3/issues/comments/#create-a-comment - # @returns [String] socialcast username to assign the review to # @returns [nil] when no buddy system configured or user not found def socialcast_review_buddy(current_user) diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 303b03a..958df0a 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -1366,7 +1366,7 @@ def expect_message(message_body, params = {}) expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:branches).with(:merged => true).and_return(['staging', 'bazquux', 'last_known_good_prototype']) Socialcast::Gitx::CLI.start ['cleanup'] end - it 'should only cleanup non-reserved branches' do + it 'only cleans up non-reserved branches' do expect(stubbed_executed_commands).to eq([ "git checkout master", "git pull", From 188144ec47c2d047b5f121b9b3bce055147e44e1 Mon Sep 17 00:00:00 2001 From: Sean Walbran Date: Sun, 21 Feb 2016 19:27:49 -0600 Subject: [PATCH 24/24] add spec for and fix typo and bump version for release --- lib/socialcast-git-extensions/cli.rb | 2 +- lib/socialcast-git-extensions/version.rb | 2 +- spec/cli_spec.rb | 26 +++++++++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/socialcast-git-extensions/cli.rb b/lib/socialcast-git-extensions/cli.rb index 24a9b7a..3425294 100644 --- a/lib/socialcast-git-extensions/cli.rb +++ b/lib/socialcast-git-extensions/cli.rb @@ -136,7 +136,7 @@ def backportpr(pull_request_num, maintenance_branch) pr_hash = create_pull_request(backport_branch, repo, description) assign_pull_request(assignee, pr_hash['issue_url']) if assignee - reviewer_mention = "@#{socialcast_reviwer}" if socialcast_reviewer + reviewer_mention = "@#{socialcast_reviewer}" if socialcast_reviewer if use_pr_comments? issue_message = ['#reviewrequest backport', reviewer_mention, "/cc @#{developer_group} #scgitx"].compact.join(' ') comment_on_issue(pr_hash['issue_url'], issue_message) diff --git a/lib/socialcast-git-extensions/version.rb b/lib/socialcast-git-extensions/version.rb index d04c55d..b69da6a 100644 --- a/lib/socialcast-git-extensions/version.rb +++ b/lib/socialcast-git-extensions/version.rb @@ -1,5 +1,5 @@ module Socialcast module Gitx - VERSION = "4.0.rc1" + VERSION = "4.0" end end diff --git a/spec/cli_spec.rb b/spec/cli_spec.rb index 958df0a..e964f9d 100644 --- a/spec/cli_spec.rb +++ b/spec/cli_spec.rb @@ -962,11 +962,11 @@ def expect_message(message_body, params = {}) before do expect_any_instance_of(Socialcast::Gitx::CLI).to receive(:backportpr).and_call_original allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:use_pr_comments?).and_return(use_pr_comments) - Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] end context 'when use_pr_comments? is false' do let(:use_pr_comments) { false } it 'creates a branch based on v1.x and cherry-picks in PR 59' do + Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] expect(github_pr_show).to have_been_requested expect(github_pr_commits_list).to have_been_requested expect(github_pr_create).to have_been_requested @@ -978,10 +978,34 @@ def expect_message(message_body, params = {}) context 'when use_pr_comments? is true' do let(:use_pr_comments) { true } it 'posts a pr comment instead of posting a socialcast message' do + Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] expect(github_pr_show).to have_been_requested expect(github_pr_commits_list).to have_been_requested expect(github_pr_create).to have_been_requested + expect(github_pr_comment_create).to have_been_requested + expect(socialcast_message_create).to_not have_been_requested + end + end + context 'when a backport reviewer is configured' do + before do + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:github_track_reviewer).with('Backport').and_return('janedoe') + allow_any_instance_of(Socialcast::Gitx::CLI).to receive(:socialcast_track_reviewer).with('Backport').and_return('JaneDoe') + end + let(:use_pr_comments) { true } + let!(:github_pr_comment_create) do + stub_request(:post, "https://api.github.com/repos/repo/project/issues/60/comments") + .with(:body => "{\"body\":\"#reviewrequest backport @JaneDoe /cc @SocialcastDevelopers #scgitx\"}") + .to_return(:status => 200, :body => "{}", :headers => {}) + end + let!(:github_assign_pr) { stub_request(:patch, "https://api.github.com/repos/repo/project/issues/60").to_return(:status => 200) } + it 'mentions the track reviewer' do + Socialcast::Gitx::CLI.start ['backportpr', '59', 'v1.x'] + expect(github_pr_show).to have_been_requested + expect(github_pr_commits_list).to have_been_requested + expect(github_pr_create).to have_been_requested + expect(github_assign_pr).to have_been_requested + expect(github_pr_comment_create).to have_been_requested expect(socialcast_message_create).to_not have_been_requested end