From 5c7a93d6afdb4926431a67eef2755cf5134d4b4c Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Sat, 21 May 2016 17:44:51 +0530 Subject: [PATCH 01/20] Take title and description on cmdline for milestone just like open Now `ghi milestone sample_title -m sample_description` will create a milestone with title as sample_title and description as sample_description. Fixes #303 --- ghi | 3 +++ lib/ghi/commands/milestone.rb | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ghi b/ghi index c41c2c7..7a394c9 100755 --- a/ghi +++ b/ghi @@ -2743,6 +2743,9 @@ EOF if web Web.new(repo).open 'issues/milestones/new' else + unless args.empty? + assigns[:title], assigns[:description] = args.join(' '), assigns[:title] + end if assigns[:title].nil? e = Editor.new 'GHI_MILESTONE.md' message = e.gets format_milestone_editor diff --git a/lib/ghi/commands/milestone.rb b/lib/ghi/commands/milestone.rb index 65956ae..88a9366 100644 --- a/lib/ghi/commands/milestone.rb +++ b/lib/ghi/commands/milestone.rb @@ -139,6 +139,9 @@ def execute if web Web.new(repo).open 'issues/milestones/new' else + unless args.empty? + assigns[:title], assigns[:description] = args.join(' '), assigns[:title] + end if assigns[:title].nil? e = Editor.new 'GHI_MILESTONE.md' message = e.gets format_milestone_editor From 8c0b64d11adf36605ebf84885d5dfdc6ca65a78e Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Sun, 22 May 2016 15:40:17 +0530 Subject: [PATCH 02/20] Take title and description on cmdline for edit just like open --- ghi | 3 +++ lib/ghi/commands/edit.rb | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ghi b/ghi index 7a394c9..d05e778 100755 --- a/ghi +++ b/ghi @@ -1997,6 +1997,9 @@ EOF case action when 'edit' begin + unless args.empty? + assigns[:title], assigns[:body] = args.join(' '), assigns[:title] + end if editor || assigns.empty? i = throb { api.get "/repos/#{repo}/issues/#{issue}" }.body e = Editor.new "GHI_ISSUE_#{issue}.md" diff --git a/lib/ghi/commands/edit.rb b/lib/ghi/commands/edit.rb index 4f46569..fa88e04 100644 --- a/lib/ghi/commands/edit.rb +++ b/lib/ghi/commands/edit.rb @@ -68,6 +68,9 @@ def execute case action when 'edit' begin + unless args.empty? + assigns[:title], assigns[:body] = args.join(' '), assigns[:title] + end if editor || assigns.empty? i = throb { api.get "/repos/#{repo}/issues/#{issue}" }.body e = Editor.new "GHI_ISSUE_#{issue}.md" From 3dde9eb2ab55849fc7bd4d369ef3d96f853215aa Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 17:58:48 +0530 Subject: [PATCH 03/20] Add .editorconfig to maintain project's coding style --- .editorconfig | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..d82157d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.rb] +indent_style = tab +tab_width = 2 From b55c072d63867ca2ac8f17a8aeaf47d28da3a7ae Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 19:11:52 +0530 Subject: [PATCH 04/20] Setup framework for travis-ci and local testing --- .travis.yml | 4 ++++ Rakefile | 2 ++ ghi.gemspec | 1 + 3 files changed, 7 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2d4a1b4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: ruby +rvm: +- 2.2 +script: rake test:one_by_one diff --git a/Rakefile b/Rakefile index 45efe62..c0ab85d 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +require 'single_test/tasks' + desc 'Build the standalone script' task :build do manifest = %w( diff --git a/ghi.gemspec b/ghi.gemspec index df62be9..d2f30c1 100644 --- a/ghi.gemspec +++ b/ghi.gemspec @@ -23,4 +23,5 @@ EOF s.add_development_dependency 'rake' s.add_development_dependency 'ronn' + s.add_development_dependency 'single_test' end From 143c3107d65c18ddfe68ff151b7b9febfc6400cd Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:02:56 +0530 Subject: [PATCH 05/20] Add --just_print_token option to ghi config --auth Helpful while doing local testing. We don't want to mess with the user's original ~/.gitconfig. User will want to use a different github account for testing(Don't want to mess up the original account). --- ghi | 19 +++++++++++++------ lib/ghi/authorization.rb | 14 +++++++++----- lib/ghi/commands/config.rb | 5 ++++- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ghi b/ghi index d05e778..ecb55a8 100755 --- a/ghi +++ b/ghi @@ -1085,7 +1085,7 @@ module GHI @token = GHI.config 'ghi.token' end - def authorize! user = username, pass = password, local = true + def authorize! user = username, pass = password, local = true, just_print_token = false return false unless user && pass code ||= nil # 2fa args = code ? [] : [54, "✔\r"] @@ -1106,11 +1106,15 @@ module GHI } @token = res.body['token'] - unless username - system "git config#{' --global' unless local} github.user #{user}" - end + if just_print_token + puts token + else + unless username + system "git config#{' --global' unless local} github.user #{user}" + end - store_token! user, token, local + store_token! user, token, local + end rescue Client::Error => e if e.response['X-GitHub-OTP'] =~ /required/ puts "Bad code." if code @@ -1882,6 +1886,9 @@ EOF opts.on '--local', 'set for local repo only' do assigns[:local] = true end + opts.on '--just_print_token', "Just print the token don't add it to ~/.gitconfig(Useful while testing)" do + assigns[:just_print_token] = true + end opts.on '--auth []' do |username| self.action = 'auth' assigns[:username] = username || Authorization.username @@ -1899,7 +1906,7 @@ EOF if action == 'auth' assigns[:password] = Authorization.password || get_password Authorization.authorize!( - assigns[:username], assigns[:password], assigns[:local] + assigns[:username], assigns[:password], assigns[:local], assigns[:just_print_token] ) end end diff --git a/lib/ghi/authorization.rb b/lib/ghi/authorization.rb index ae6a65c..31595de 100644 --- a/lib/ghi/authorization.rb +++ b/lib/ghi/authorization.rb @@ -15,7 +15,7 @@ def token @token = GHI.config 'ghi.token' end - def authorize! user = username, pass = password, local = true + def authorize! user = username, pass = password, local = true, just_print_token = false return false unless user && pass code ||= nil # 2fa args = code ? [] : [54, "✔\r"] @@ -36,11 +36,15 @@ def authorize! user = username, pass = password, local = true } @token = res.body['token'] - unless username - system "git config#{' --global' unless local} github.user #{user}" - end + if just_print_token + puts token + else + unless username + system "git config#{' --global' unless local} github.user #{user}" + end - store_token! user, token, local + store_token! user, token, local + end rescue Client::Error => e if e.response['X-GitHub-OTP'] =~ /required/ puts "Bad code." if code diff --git a/lib/ghi/commands/config.rb b/lib/ghi/commands/config.rb index 5864ce2..b559313 100644 --- a/lib/ghi/commands/config.rb +++ b/lib/ghi/commands/config.rb @@ -10,6 +10,9 @@ def options opts.on '--local', 'set for local repo only' do assigns[:local] = true end + opts.on '--just_print_token', "Just print the token don't add it to ~/.gitconfig(Useful while testing)" do + assigns[:just_print_token] = true + end opts.on '--auth []' do |username| self.action = 'auth' assigns[:username] = username || Authorization.username @@ -27,7 +30,7 @@ def execute if action == 'auth' assigns[:password] = Authorization.password || get_password Authorization.authorize!( - assigns[:username], assigns[:password], assigns[:local] + assigns[:username], assigns[:password], assigns[:local], assigns[:just_print_token] ) end end From e5e4e14f285aaf5250482d6d1b5c34bb598923ed Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:22:57 +0530 Subject: [PATCH 06/20] Setup communication with github --- ghi.gemspec | 1 + test/helper.rb | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 test/helper.rb diff --git a/ghi.gemspec b/ghi.gemspec index d2f30c1..83eec9f 100644 --- a/ghi.gemspec +++ b/ghi.gemspec @@ -23,5 +23,6 @@ EOF s.add_development_dependency 'rake' s.add_development_dependency 'ronn' + s.add_development_dependency 'typhoeus' s.add_development_dependency 'single_test' end diff --git a/test/helper.rb b/test/helper.rb new file mode 100644 index 0000000..fad5527 --- /dev/null +++ b/test/helper.rb @@ -0,0 +1,54 @@ +require "typhoeus" +require "json" +require "pp" + +def append_token headers + headers.merge(:Authorization=>"token #{ENV["GHI_TOKEN"]}") +end + +def get_url path + "https://api.github.com/#{path}" +end + +def request path, method, options={}, use_basic_auth=true + if options[:params].nil? + options.merge!(:params=>{}) + end + if options[:headers].nil? + options.merge!(:headers=>{}) + end + if options[:body].nil? + options.merge!(:body=>{}) + end + + Typhoeus::Request.new(get_url(path), + method: method, + body: JSON.dump(options[:body]), + params: options[:params], + username: (if use_basic_auth then ENV["GITHUB_USER"] else nil end), + password: (if use_basic_auth then ENV["GITHUB_PASSWORD"] else nil end), + headers: (if use_basic_auth then options[:headers] else append_token(options[:headers]) end) + ).run +end + +def head path, options={} + request(path,:head,options) +end + +def get path, options ={} + request(path,:get,options) +end + +def post path, options ={} + request(path,:post,options) +end + +def delete path, options ={} + request(path,:delete,options) +end + +def get_body path, err_msg="" + response=get(path) + assert_equal(200,response.code,err_msg) + JSON.load(response.body) +end From 07db9a8faab4352614ef252359b9576912d88404 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:27:26 +0530 Subject: [PATCH 07/20] Setup mock data and its helper functions --- test/helper.rb | 28 +++++++++++++++++++ test/mock_data.rb | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 test/mock_data.rb diff --git a/test/helper.rb b/test/helper.rb index fad5527..f8d3bf2 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -1,6 +1,8 @@ require "typhoeus" require "json" +require "shellwords" require "pp" +require "mock_data" def append_token headers headers.merge(:Authorization=>"token #{ENV["GHI_TOKEN"]}") @@ -47,6 +49,32 @@ def delete path, options ={} request(path,:delete,options) end +def get_attr index, attr + Shellwords.escape(issues[index][attr]) +end + +def get_issue index=0 + if index == -1 + tmp_issues=issues + else + tmp_issues=[issues[index]] + end + for i in 0..(tmp_issues.length-1) + tmp_issues[i][:des].gsub!(/\n/,"
") + # http://stackoverflow.com/questions/12700218/how-do-i-escape-a-single-quote-in-ruby + tmp_issues[i][:des].gsub!(/'/){"\\'"} + end + return (index != -1)?tmp_issues[0]:tmp_issues +end + +def get_comment index=0 + comments[index] +end + +def get_milestone index=0 + milestones[index] +end + def get_body path, err_msg="" response=get(path) assert_equal(200,response.code,err_msg) diff --git a/test/mock_data.rb b/test/mock_data.rb new file mode 100644 index 0000000..b0a7fce --- /dev/null +++ b/test/mock_data.rb @@ -0,0 +1,70 @@ +def issues + [ + { + title: "Test Issue 1", + des: < Date: Fri, 17 Jun 2016 18:31:29 +0530 Subject: [PATCH 08/20] Setup repo and token creation/deletion --- test/helper.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/helper.rb b/test/helper.rb index f8d3bf2..36fd988 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -2,7 +2,9 @@ require "json" require "shellwords" require "pp" +require "securerandom" require "mock_data" +require "test/unit" def append_token headers headers.merge(:Authorization=>"token #{ENV["GHI_TOKEN"]}") @@ -49,10 +51,43 @@ def delete path, options ={} request(path,:delete,options) end +def delete_repo repo_name + unless ENV["NO_DELETE_REPO"]=="1" + delete("repos/#{repo_name}") + end +end + +def ghi_exec + File.expand_path('../ghi', File.dirname(__FILE__)) +end + def get_attr index, attr Shellwords.escape(issues[index][attr]) end +def gen_token + ENV["GHI_TOKEN"]=`#{ghi_exec} config --auth --just_print_token`.chop + response=request("users/#{ENV['GITHUB_USER']}",:head,{},false) + + assert_equal('public_repo, repo',response.headers["X-OAuth-Scopes"]) +end + +def delete_token + unless ENV["NO_DELETE_TOKEN"]=="1" + token_info=get_body("authorizations","Impossible api error").detect {|token| token["token_last_eight"] == ENV["GHI_TOKEN"][-8..-1]} + assert_not_equal(nil,token_info,"Token with hash: #{ENV["GHI_TOKEN"]} does not exist") + delete("authorizations/#{token_info["id"]}") + end +end + +def create_repo + repo_name=SecureRandom.uuid + response=post("user/repos",{body:{'name':repo_name}}) + response_body=JSON.load(response.response_body) + assert_not_equal(nil,response_body["name"],"Could not create repo #{repo_name}") + response_body["full_name"] +end + def get_issue index=0 if index == -1 tmp_issues=issues From 8a18d52662165d3dd0f02ec8bc5beb2840ce629a Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:34:56 +0530 Subject: [PATCH 09/20] Test opening issue --- test/helper.rb | 59 +++++++++++++++++++++++++++++++++++++++++++++++ test/open_test.rb | 20 ++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 test/open_test.rb diff --git a/test/helper.rb b/test/helper.rb index 36fd988..08ea0e3 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -5,6 +5,7 @@ require "securerandom" require "mock_data" require "test/unit" +require "date" def append_token headers headers.merge(:Authorization=>"token #{ENV["GHI_TOKEN"]}") @@ -110,8 +111,66 @@ def get_milestone index=0 milestones[index] end +def extract_labels response_issue + tmp_labels=[] + response_issue["labels"].each do |label| + tmp_labels< Date: Fri, 17 Jun 2016 18:38:19 +0530 Subject: [PATCH 10/20] Test comment creation/ammend/deletion --- test/comment_test.rb | 45 ++++++++++++++++++++++++++++++++++++++++++++ test/helper.rb | 11 +++++++++++ 2 files changed, 56 insertions(+) create mode 100644 test/comment_test.rb diff --git a/test/comment_test.rb b/test/comment_test.rb new file mode 100644 index 0000000..5e11bd9 --- /dev/null +++ b/test/comment_test.rb @@ -0,0 +1,45 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_comment < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_comment + open_issue @repo_name + create_comment @repo_name + end + + def test_comment_amend + open_issue @repo_name + create_comment @repo_name + + comment=get_comment 1 + + `#{ghi_exec} comment --amend "#{comment}" 1 -- #{@repo_name}` + + response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") + + assert_equal(1,response_body.length,"Comment does not exist") + assert_equal(comment,response_body[-1]["body"],"Comment text not proper") + end + + def test_comment_delete + open_issue @repo_name + create_comment @repo_name + + `#{ghi_exec} comment -D 1 -- #{@repo_name}` + + response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") + + assert_equal(0,response_body.length,"Comment not deleted") + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end diff --git a/test/helper.rb b/test/helper.rb index 08ea0e3..67c4f85 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -125,6 +125,17 @@ def get_body path, err_msg="" JSON.load(response.body) end +def create_comment repo_name, issue_no=1, index=0 + comment=get_comment index + + `#{ghi_exec} comment -m "#{comment}" #{issue_no} -- #{repo_name}` + + response_body=get_body("repos/#{repo_name}/issues/#{issue_no}/comments","Issue does not exist") + + assert_operator(1,:<=,response_body.length,"No comments exist") + assert_equal(comment,response_body[-1]["body"],"Comment text not proper") +end + def create_milestone repo_name, index=0 milestone=get_milestone index From 91e338f1d6f8e349dc4975a58930d43e17f9875a Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:42:12 +0530 Subject: [PATCH 11/20] Test milestone creation --- test/milestone_test.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 test/milestone_test.rb diff --git a/test/milestone_test.rb b/test/milestone_test.rb new file mode 100644 index 0000000..ad65cbd --- /dev/null +++ b/test/milestone_test.rb @@ -0,0 +1,19 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_milestone < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_milestone_create + create_milestone @repo_name + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From 082c583bcae8b29259d9c2cb604a921a6be37132 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:43:24 +0530 Subject: [PATCH 12/20] Test [un-]assigning user to the issue --- test/assign_test.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 test/assign_test.rb diff --git a/test/assign_test.rb b/test/assign_test.rb new file mode 100644 index 0000000..be3b193 --- /dev/null +++ b/test/assign_test.rb @@ -0,0 +1,42 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_assign < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def un_assign issue_no=1 + `#{ghi_exec} assign -d #{issue_no} -- #{@repo_name}` + + response_issue = get_body("repos/#{@repo_name}/issues/#{issue_no}","Issue does not exist") + + assert_equal(nil,response_issue["assignee"],"User not unassigned") + end + + def test_un_assign + open_issue @repo_name + + un_assign + end + + def test_assign + open_issue @repo_name + + un_assign + + `#{ghi_exec} assign -u "#{ENV['GITHUB_USER']}" 1 -- #{@repo_name}` + + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + + assert_not_equal(nil,response_issue["assignee"],"No user assigned") + assert_equal(ENV['GITHUB_USER'],response_issue["assignee"]["login"],"Not assigned to proper user") + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From 130995052504a8b5791f44b3a52ac8598d5f83b2 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:43:52 +0530 Subject: [PATCH 13/20] Test editing issue --- test/edit_test.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 test/edit_test.rb diff --git a/test/edit_test.rb b/test/edit_test.rb new file mode 100644 index 0000000..be27575 --- /dev/null +++ b/test/edit_test.rb @@ -0,0 +1,35 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_edit < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_edit_issue + open_issue @repo_name + + issue=get_issue 1 + + create_milestone @repo_name, 1 + + `#{ghi_exec} edit 1 "#{issue[:title]}" -m "#{issue[:des]}" -L "#{issue[:labels].join(",")}" -M 2 -s open -u "#{ENV['GITHUB_USER']}" -- #{@repo_name}` + + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + + assert_equal(issue[:title],response_issue["title"],"Title not proper") + assert_equal(issue[:des],response_issue["body"],"Descreption not proper") + assert_equal(issue[:labels].uniq.sort,extract_labels(response_issue),"Labels do not match") + assert_equal("open",response_issue["state"],"Issue state not changed") + assert_equal(2,response_issue["milestone"]["number"],"Milestone not proper") + assert_not_equal(nil,response_issue["assignee"],"No user assigned") + assert_equal(ENV['GITHUB_USER'],response_issue["assignee"]["login"],"Not assigned to proper user") + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From 17154f81f5c622d6a073c26d81b10d902d64b12e Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:44:35 +0530 Subject: [PATCH 14/20] Test adding/deleting/replacing labels from issue --- test/labels_test.rb | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 test/labels_test.rb diff --git a/test/labels_test.rb b/test/labels_test.rb new file mode 100644 index 0000000..8ce4341 --- /dev/null +++ b/test/labels_test.rb @@ -0,0 +1,53 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_labels < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_delete_labels + open_issue @repo_name + + tmp_labels=get_issue[:labels] + + `#{ghi_exec} label 1 -d "#{tmp_labels.join(",")}" -- #{@repo_name}` + + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + + assert_equal([],response_issue["labels"],"Labels not deleted properly") + end + + def test_add_labels + open_issue @repo_name + + tmp_labels=get_issue(1)[:labels] + + `#{ghi_exec} label 1 -a "#{tmp_labels.join(",")}" -- #{@repo_name}` + + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + + tmp=tmp_labels+get_issue[:labels] + + assert_equal(tmp.uniq.sort,extract_labels(response_issue),"Labels not added properly") + end + + def test_replace_labels + open_issue @repo_name + + tmp_labels=get_issue(1)[:labels] + + `#{ghi_exec} label 1 -f "#{tmp_labels.join(",")}" -- #{@repo_name}` + + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + + assert_equal(tmp_labels.uniq.sort,extract_labels(response_issue),"Labels not replaced properly") + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From 985c3f2b341f73ee5d6240aa3454c4b459680de7 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:44:56 +0530 Subject: [PATCH 15/20] Test closing issue --- test/close_test.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/close_test.rb diff --git a/test/close_test.rb b/test/close_test.rb new file mode 100644 index 0000000..20b7c2b --- /dev/null +++ b/test/close_test.rb @@ -0,0 +1,30 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_close < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_close_issue + open_issue @repo_name + comment=get_comment + + `#{ghi_exec} close -m "#{comment}" 1 -- #{@repo_name}` + + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + + assert_equal("closed",response_issue["state"],"Issue not closed") + + response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") + + assert_equal(comment,response_body[-1]["body"],"Close comment text not proper") + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From 614be1d78e4e26815bf4d9b23f4b605d4dc3e941 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:45:12 +0530 Subject: [PATCH 16/20] Test showing issue --- test/show_test.rb | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/show_test.rb diff --git a/test/show_test.rb b/test/show_test.rb new file mode 100644 index 0000000..ae99330 --- /dev/null +++ b/test/show_test.rb @@ -0,0 +1,41 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_show < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_show + issue=get_issue + milestone=get_milestone + comment=get_comment + + open_issue @repo_name + create_comment @repo_name + + show_output = `#{ghi_exec} show 1 -- #{@repo_name}` + + assert_match(/\A#1: #{issue[:title]}\n/,show_output,"Title not proper") + assert_match(/^@#{ENV["GITHUB_USER"]} opened this issue/,show_output,"Opening user not proper") + assert_match(/^@#{ENV["GITHUB_USER"]} is assigned/,show_output,"Assigned user not proper") + + labels_str="" + issue[:labels].sort.each do |tmp| + labels_str+="\\[#{tmp}\\] " + end + labels_str.strip! + + assert_match(/#{labels_str}/,show_output,"labels not present") + assert_match(/Milestone #1: #{milestone[:title]}/,show_output,"Milestone not proper") + assert_match(/@#{ENV["GITHUB_USER"]} commented/,show_output,"Comment creator not proper") + assert_match(/#{comment}/,show_output,"Comment not proper") + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From 7a336de464964e3f8d76df8f7fb2c5f41b7e3763 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:45:25 +0530 Subject: [PATCH 17/20] Test listing issue --- test/list_test.rb | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 test/list_test.rb diff --git a/test/list_test.rb b/test/list_test.rb new file mode 100644 index 0000000..901c850 --- /dev/null +++ b/test/list_test.rb @@ -0,0 +1,42 @@ +require "test/unit" +require "helper" +require "pp" + +class Test_list < Test::Unit::TestCase + def setup + gen_token + @repo_name=create_repo + end + + def test_list + tmp_issues=get_issue(-1) + for i in 0..(tmp_issues.length-1) + open_issue @repo_name, i + end + list_output=`#{ghi_exec} list -- "#{@repo_name}"` + + list_lines=list_output.lines + + assert_equal(tmp_issues.length+1,list_lines.length,"Not enough lines in output") + assert_match(/^# #{@repo_name} open issues$/,list_lines[0],"Heading not proper") + + tmp_issues.length.downto(1) do |i| + issue_title=tmp_issues[i-1][:title] + milestone_title=get_milestone(tmp_issues[i-1][:milestone]-1)[:title] + tmp_line=list_lines[-i].strip + + labels_str="" + tmp_issues[i-1][:labels].sort.each do |tmp| + labels_str+="\\[#{tmp}\\] " + end + labels_str.strip! + + assert_match(/^#{i} #{issue_title} #{labels_str} #{milestone_title} @#{ENV["GITHUB_USER"]}/,tmp_line,"Issue no #{i} not proper") + end + end + + def teardown + delete_repo(@repo_name) + delete_token + end +end From ed7086a5a9e6cb1c292f671dbcba763200cdaa68 Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:46:21 +0530 Subject: [PATCH 18/20] A helper script for cleaning up(deleting all repos) --- test/delete_all_repos.rb | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/delete_all_repos.rb diff --git a/test/delete_all_repos.rb b/test/delete_all_repos.rb new file mode 100644 index 0000000..ade7203 --- /dev/null +++ b/test/delete_all_repos.rb @@ -0,0 +1,30 @@ +require "helper" +require "json" +require "pp" + +# This is helpful if your account(fake) gets littered with repos. +# You need to run ruby -I. delete_all_repos.rb. If you are executing from a +# different directory then you need to change the parameter of -I +# appropriately. + +puts "Warning this will delete ALL repositories from the account pointed by GITHUB_USER environment variable" +puts "The account name(login) is #{ENV["GITHUB_USER"]}" +puts "Do you want to continue [N/y]" +option = gets +if option.chop == "y" + puts "Deleting" + while true + response=request("users/#{ENV["GITHUB_USER"]}/repos",:get,{},true) + repos=JSON.load(response.body) + if repos.length == 0 + puts "Exiting" + break + end + repos.each do |repo| + puts "Deleting #{repo["full_name"]}" + delete_repo(repo["full_name"]) + end + end +else + puts 'Not deleting' +end From afb75ef2b495b6cf10aab6a133792380b2ce89cc Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Fri, 17 Jun 2016 18:54:53 +0530 Subject: [PATCH 19/20] Update Readme --- README.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/README.md b/README.md index de088bb..b9cbe10 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # ghi +[![Build Status](https://travis-ci.org/shubhamshuklaer/ghi.svg?branch=travis-ci)](https://travis-ci.org/shubhamshuklaer/ghi) + GitHub Issues on the command line. Use your `$EDITOR`, not your browser. `ghi` was originally created by [Stephen Celis](https://github.com/stephencelis), and is now maintained by [Alex Chesters](https://github.com/alexchesters). @@ -69,3 +71,47 @@ FAQs can be found in the [wiki](https://github.com/stephencelis/ghi/wiki/FAQ) ## Screenshot ![Example](images/example.png) + +## Testing Guidlines +* You are encouraged to add tests if you are adding new feature or solving some +problem which do not have a test. +* A test file should be named as `something_test.rb` and should be kept in the +`test` folder. A test class should be named `Test_something` and a test +function `test_something`. Helper functions must not start with `test`. +* Before running tests `GITHUB_USER` and `GITHUB_PASSWORD` environment +variables must be exported. It is best to use a fake account as a bug can mess +up your original account. You can either export these 2 environment variables +through `~/.bashrc`(As ghi only uses these while generating its token, so after +you generate the token for your original account(for regular use), fake account +details can be exported) or you can pass it on command line, eg. `rake +test:one_by_one GITHUB_USER='abc' GITHUB_PASSWORD='xyz'`. +* Run `rake test:one_by_one` to run all the tests +* Check [Single Test](https://github.com/grosser/single_test) for better +control over which test to run. Eg. `rake test:assign:un_assign` will run a +test function matching `/un_assign/` in file `assign_test.rb`. One more eg. +`rake test:edit test:assign` will run tests `edit_test.rb` and +`assign_test.rb`. Or you can also use `ruby -I"lib:test" test/file_name.rb -n +method_name` +* By default, the repo and token created while testing will be deleted. But if +you want to see the state of repo and tokens after the test has run, then add +`NO_DELETE_REPO=1` and `NO_DELETE_TOKEN=1` to the command. For eg. `rake +test:assign NO_DELETE_REPO=1 NO_DELETE_TOKEN=1`. +* If you don't wanna run the tests locally use travis-ci. See section below. + +## Enable Travis CI in fork + +* Open a Travis CI account and activate travis-ci for the fork +* Create a fake github account for testing. The username, password and token +will be available to the tests and if by mistake the test prints it, it will be +available in public log. So its best to create a fake account and use a +password you are not using for anything else. Apart from security reasons, +bugs in tests or software can also mess up your original account, so to be +on safe side use a fake account. +* At Travis-CI, on the settings page for the fork, add environment variables +`GITHUB_USER` and `GITHUB_PASSWORD`. Ensure that the "Display value in build +log" is set to false. It is possible to add these in ".travis.yml", but don't +as all forks as well as original repo will be using different accounts(We cannot +provide the details of a common account for testing because of security reasons) for +testing, so it will cause problems during merge. +* Note that the build status badge in the README points to the travis-ci page +for this repo, not the fork. From 072bd1eb1ab30129668fc6d69b7830ebdf49903e Mon Sep 17 00:00:00 2001 From: Shubham Shukla Date: Sat, 18 Jun 2016 22:26:14 +0530 Subject: [PATCH 20/20] Convert tabs to spaces. The project uses spaces --- .editorconfig | 4 +- test/assign_test.rb | 50 ++++----- test/close_test.rb | 34 +++--- test/comment_test.rb | 56 +++++----- test/delete_all_repos.rb | 28 ++--- test/edit_test.rb | 44 ++++---- test/helper.rb | 216 +++++++++++++++++++-------------------- test/labels_test.rb | 60 +++++------ test/list_test.rb | 72 ++++++------- test/milestone_test.rb | 22 ++-- test/mock_data.rb | 94 ++++++++--------- test/open_test.rb | 22 ++-- test/show_test.rb | 70 ++++++------- 13 files changed, 386 insertions(+), 386 deletions(-) diff --git a/.editorconfig b/.editorconfig index d82157d..d1fa1b6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,5 +8,5 @@ insert_final_newline = true trim_trailing_whitespace = true [*.rb] -indent_style = tab -tab_width = 2 +indent_style = space +indent_size = 2 diff --git a/test/assign_test.rb b/test/assign_test.rb index be3b193..cd71330 100644 --- a/test/assign_test.rb +++ b/test/assign_test.rb @@ -3,40 +3,40 @@ require "pp" class Test_assign < Test::Unit::TestCase - def setup - gen_token - @repo_name=create_repo - end + def setup + gen_token + @repo_name=create_repo + end - def un_assign issue_no=1 - `#{ghi_exec} assign -d #{issue_no} -- #{@repo_name}` + def un_assign issue_no=1 + `#{ghi_exec} assign -d #{issue_no} -- #{@repo_name}` - response_issue = get_body("repos/#{@repo_name}/issues/#{issue_no}","Issue does not exist") + response_issue = get_body("repos/#{@repo_name}/issues/#{issue_no}","Issue does not exist") - assert_equal(nil,response_issue["assignee"],"User not unassigned") - end + assert_equal(nil,response_issue["assignee"],"User not unassigned") + end - def test_un_assign - open_issue @repo_name + def test_un_assign + open_issue @repo_name - un_assign - end + un_assign + end - def test_assign - open_issue @repo_name + def test_assign + open_issue @repo_name - un_assign + un_assign - `#{ghi_exec} assign -u "#{ENV['GITHUB_USER']}" 1 -- #{@repo_name}` + `#{ghi_exec} assign -u "#{ENV['GITHUB_USER']}" 1 -- #{@repo_name}` - response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") - assert_not_equal(nil,response_issue["assignee"],"No user assigned") - assert_equal(ENV['GITHUB_USER'],response_issue["assignee"]["login"],"Not assigned to proper user") - end + assert_not_equal(nil,response_issue["assignee"],"No user assigned") + assert_equal(ENV['GITHUB_USER'],response_issue["assignee"]["login"],"Not assigned to proper user") + end - def teardown - delete_repo(@repo_name) - delete_token - end + def teardown + delete_repo(@repo_name) + delete_token + end end diff --git a/test/close_test.rb b/test/close_test.rb index 20b7c2b..4441b6e 100644 --- a/test/close_test.rb +++ b/test/close_test.rb @@ -3,28 +3,28 @@ require "pp" class Test_close < Test::Unit::TestCase - def setup - gen_token - @repo_name=create_repo - end + def setup + gen_token + @repo_name=create_repo + end - def test_close_issue - open_issue @repo_name - comment=get_comment + def test_close_issue + open_issue @repo_name + comment=get_comment - `#{ghi_exec} close -m "#{comment}" 1 -- #{@repo_name}` + `#{ghi_exec} close -m "#{comment}" 1 -- #{@repo_name}` - response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") - assert_equal("closed",response_issue["state"],"Issue not closed") + assert_equal("closed",response_issue["state"],"Issue not closed") - response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") + response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") - assert_equal(comment,response_body[-1]["body"],"Close comment text not proper") - end + assert_equal(comment,response_body[-1]["body"],"Close comment text not proper") + end - def teardown - delete_repo(@repo_name) - delete_token - end + def teardown + delete_repo(@repo_name) + delete_token + end end diff --git a/test/comment_test.rb b/test/comment_test.rb index 5e11bd9..29e2c82 100644 --- a/test/comment_test.rb +++ b/test/comment_test.rb @@ -3,43 +3,43 @@ require "pp" class Test_comment < Test::Unit::TestCase - def setup - gen_token - @repo_name=create_repo - end + def setup + gen_token + @repo_name=create_repo + end - def test_comment - open_issue @repo_name - create_comment @repo_name - end + def test_comment + open_issue @repo_name + create_comment @repo_name + end - def test_comment_amend - open_issue @repo_name - create_comment @repo_name + def test_comment_amend + open_issue @repo_name + create_comment @repo_name - comment=get_comment 1 + comment=get_comment 1 - `#{ghi_exec} comment --amend "#{comment}" 1 -- #{@repo_name}` + `#{ghi_exec} comment --amend "#{comment}" 1 -- #{@repo_name}` - response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") + response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") - assert_equal(1,response_body.length,"Comment does not exist") - assert_equal(comment,response_body[-1]["body"],"Comment text not proper") - end + assert_equal(1,response_body.length,"Comment does not exist") + assert_equal(comment,response_body[-1]["body"],"Comment text not proper") + end - def test_comment_delete - open_issue @repo_name - create_comment @repo_name + def test_comment_delete + open_issue @repo_name + create_comment @repo_name - `#{ghi_exec} comment -D 1 -- #{@repo_name}` + `#{ghi_exec} comment -D 1 -- #{@repo_name}` - response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") + response_body=get_body("repos/#{@repo_name}/issues/1/comments","Issue does not exist") - assert_equal(0,response_body.length,"Comment not deleted") - end + assert_equal(0,response_body.length,"Comment not deleted") + end - def teardown - delete_repo(@repo_name) - delete_token - end + def teardown + delete_repo(@repo_name) + delete_token + end end diff --git a/test/delete_all_repos.rb b/test/delete_all_repos.rb index ade7203..30a5056 100644 --- a/test/delete_all_repos.rb +++ b/test/delete_all_repos.rb @@ -12,19 +12,19 @@ puts "Do you want to continue [N/y]" option = gets if option.chop == "y" - puts "Deleting" - while true - response=request("users/#{ENV["GITHUB_USER"]}/repos",:get,{},true) - repos=JSON.load(response.body) - if repos.length == 0 - puts "Exiting" - break - end - repos.each do |repo| - puts "Deleting #{repo["full_name"]}" - delete_repo(repo["full_name"]) - end - end + puts "Deleting" + while true + response=request("users/#{ENV["GITHUB_USER"]}/repos",:get,{},true) + repos=JSON.load(response.body) + if repos.length == 0 + puts "Exiting" + break + end + repos.each do |repo| + puts "Deleting #{repo["full_name"]}" + delete_repo(repo["full_name"]) + end + end else - puts 'Not deleting' + puts 'Not deleting' end diff --git a/test/edit_test.rb b/test/edit_test.rb index be27575..706c41b 100644 --- a/test/edit_test.rb +++ b/test/edit_test.rb @@ -3,33 +3,33 @@ require "pp" class Test_edit < Test::Unit::TestCase - def setup - gen_token - @repo_name=create_repo - end + def setup + gen_token + @repo_name=create_repo + end - def test_edit_issue - open_issue @repo_name + def test_edit_issue + open_issue @repo_name - issue=get_issue 1 + issue=get_issue 1 - create_milestone @repo_name, 1 + create_milestone @repo_name, 1 - `#{ghi_exec} edit 1 "#{issue[:title]}" -m "#{issue[:des]}" -L "#{issue[:labels].join(",")}" -M 2 -s open -u "#{ENV['GITHUB_USER']}" -- #{@repo_name}` + `#{ghi_exec} edit 1 "#{issue[:title]}" -m "#{issue[:des]}" -L "#{issue[:labels].join(",")}" -M 2 -s open -u "#{ENV['GITHUB_USER']}" -- #{@repo_name}` - response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") + response_issue=get_body("repos/#{@repo_name}/issues/1","Issue does not exist") - assert_equal(issue[:title],response_issue["title"],"Title not proper") - assert_equal(issue[:des],response_issue["body"],"Descreption not proper") - assert_equal(issue[:labels].uniq.sort,extract_labels(response_issue),"Labels do not match") - assert_equal("open",response_issue["state"],"Issue state not changed") - assert_equal(2,response_issue["milestone"]["number"],"Milestone not proper") - assert_not_equal(nil,response_issue["assignee"],"No user assigned") - assert_equal(ENV['GITHUB_USER'],response_issue["assignee"]["login"],"Not assigned to proper user") - end + assert_equal(issue[:title],response_issue["title"],"Title not proper") + assert_equal(issue[:des],response_issue["body"],"Descreption not proper") + assert_equal(issue[:labels].uniq.sort,extract_labels(response_issue),"Labels do not match") + assert_equal("open",response_issue["state"],"Issue state not changed") + assert_equal(2,response_issue["milestone"]["number"],"Milestone not proper") + assert_not_equal(nil,response_issue["assignee"],"No user assigned") + assert_equal(ENV['GITHUB_USER'],response_issue["assignee"]["login"],"Not assigned to proper user") + end - def teardown - delete_repo(@repo_name) - delete_token - end + def teardown + delete_repo(@repo_name) + delete_token + end end diff --git a/test/helper.rb b/test/helper.rb index 67c4f85..e8e664c 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -8,180 +8,180 @@ require "date" def append_token headers - headers.merge(:Authorization=>"token #{ENV["GHI_TOKEN"]}") + headers.merge(:Authorization=>"token #{ENV["GHI_TOKEN"]}") end def get_url path - "https://api.github.com/#{path}" + "https://api.github.com/#{path}" end def request path, method, options={}, use_basic_auth=true - if options[:params].nil? - options.merge!(:params=>{}) - end - if options[:headers].nil? - options.merge!(:headers=>{}) - end - if options[:body].nil? - options.merge!(:body=>{}) - end - - Typhoeus::Request.new(get_url(path), - method: method, - body: JSON.dump(options[:body]), - params: options[:params], - username: (if use_basic_auth then ENV["GITHUB_USER"] else nil end), - password: (if use_basic_auth then ENV["GITHUB_PASSWORD"] else nil end), - headers: (if use_basic_auth then options[:headers] else append_token(options[:headers]) end) - ).run + if options[:params].nil? + options.merge!(:params=>{}) + end + if options[:headers].nil? + options.merge!(:headers=>{}) + end + if options[:body].nil? + options.merge!(:body=>{}) + end + + Typhoeus::Request.new(get_url(path), + method: method, + body: JSON.dump(options[:body]), + params: options[:params], + username: (if use_basic_auth then ENV["GITHUB_USER"] else nil end), + password: (if use_basic_auth then ENV["GITHUB_PASSWORD"] else nil end), + headers: (if use_basic_auth then options[:headers] else append_token(options[:headers]) end) + ).run end def head path, options={} - request(path,:head,options) + request(path,:head,options) end def get path, options ={} - request(path,:get,options) + request(path,:get,options) end def post path, options ={} - request(path,:post,options) + request(path,:post,options) end def delete path, options ={} - request(path,:delete,options) + request(path,:delete,options) end def delete_repo repo_name - unless ENV["NO_DELETE_REPO"]=="1" - delete("repos/#{repo_name}") - end + unless ENV["NO_DELETE_REPO"]=="1" + delete("repos/#{repo_name}") + end end def ghi_exec - File.expand_path('../ghi', File.dirname(__FILE__)) + File.expand_path('../ghi', File.dirname(__FILE__)) end def get_attr index, attr - Shellwords.escape(issues[index][attr]) + Shellwords.escape(issues[index][attr]) end def gen_token - ENV["GHI_TOKEN"]=`#{ghi_exec} config --auth --just_print_token`.chop - response=request("users/#{ENV['GITHUB_USER']}",:head,{},false) + ENV["GHI_TOKEN"]=`#{ghi_exec} config --auth --just_print_token`.chop + response=request("users/#{ENV['GITHUB_USER']}",:head,{},false) - assert_equal('public_repo, repo',response.headers["X-OAuth-Scopes"]) + assert_equal('public_repo, repo',response.headers["X-OAuth-Scopes"]) end def delete_token - unless ENV["NO_DELETE_TOKEN"]=="1" - token_info=get_body("authorizations","Impossible api error").detect {|token| token["token_last_eight"] == ENV["GHI_TOKEN"][-8..-1]} - assert_not_equal(nil,token_info,"Token with hash: #{ENV["GHI_TOKEN"]} does not exist") - delete("authorizations/#{token_info["id"]}") - end + unless ENV["NO_DELETE_TOKEN"]=="1" + token_info=get_body("authorizations","Impossible api error").detect {|token| token["token_last_eight"] == ENV["GHI_TOKEN"][-8..-1]} + assert_not_equal(nil,token_info,"Token with hash: #{ENV["GHI_TOKEN"]} does not exist") + delete("authorizations/#{token_info["id"]}") + end end def create_repo - repo_name=SecureRandom.uuid - response=post("user/repos",{body:{'name':repo_name}}) - response_body=JSON.load(response.response_body) - assert_not_equal(nil,response_body["name"],"Could not create repo #{repo_name}") - response_body["full_name"] + repo_name=SecureRandom.uuid + response=post("user/repos",{body:{'name':repo_name}}) + response_body=JSON.load(response.response_body) + assert_not_equal(nil,response_body["name"],"Could not create repo #{repo_name}") + response_body["full_name"] end def get_issue index=0 - if index == -1 - tmp_issues=issues - else - tmp_issues=[issues[index]] - end - for i in 0..(tmp_issues.length-1) - tmp_issues[i][:des].gsub!(/\n/,"
") - # http://stackoverflow.com/questions/12700218/how-do-i-escape-a-single-quote-in-ruby - tmp_issues[i][:des].gsub!(/'/){"\\'"} - end - return (index != -1)?tmp_issues[0]:tmp_issues + if index == -1 + tmp_issues=issues + else + tmp_issues=[issues[index]] + end + for i in 0..(tmp_issues.length-1) + tmp_issues[i][:des].gsub!(/\n/,"
") + # http://stackoverflow.com/questions/12700218/how-do-i-escape-a-single-quote-in-ruby + tmp_issues[i][:des].gsub!(/'/){"\\'"} + end + return (index != -1)?tmp_issues[0]:tmp_issues end def get_comment index=0 - comments[index] + comments[index] end def get_milestone index=0 - milestones[index] + milestones[index] end def extract_labels response_issue - tmp_labels=[] - response_issue["labels"].each do |label| - tmp_labels<