toolshed 0.0.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,106 @@
1
+ module Toolshed
2
+ module TicketTracking
3
+ class Jira
4
+ extend TicketTracking
5
+ include HTTParty
6
+
7
+ USE_PROJECT_NAME = true
8
+
9
+ attr_accessor :project, :client, :owner, :ticket
10
+
11
+ def initialize(options={})
12
+ username = (options[:username].nil?) ? Toolshed::Client::ticket_tracker_username : options[:username]
13
+ password = (options[:password].nil?) ? Toolshed::Client::ticket_tracker_password : options[:password]
14
+
15
+ self.owner = Toolshed::Client::ticket_tracker_owner
16
+
17
+ self.client = JIRA::Client.new({
18
+ username: username,
19
+ password: password,
20
+ site: "https://#{self.owner}.atlassian.net",
21
+ context_path: '',
22
+ auth_type: :basic,
23
+ use_ssl: true,
24
+ })
25
+
26
+ self.project = self.client.Project.find(options[:project])
27
+ self.ticket = self.client.Issue.find(options[:ticket_id])
28
+ end
29
+
30
+ #
31
+ # Instance methods
32
+ #
33
+ def add_note(note_text)
34
+ issue = self.ticket.comments.build
35
+ issue.save({ 'body' => note_text })
36
+ end
37
+
38
+ def update_ticket_status(status, options={})
39
+ available_statuses
40
+
41
+ transition = self.ticket.transitions.build
42
+ transition.save({ 'transition' => { "id" => transition_status_id_by_status(status) } })
43
+ end
44
+
45
+ def available_statuses
46
+ self.client.Transition.all(issue: self.ticket)
47
+ end
48
+
49
+ def transition_status_id_by_status(status)
50
+ self.available_statuses.each do |transition_status|
51
+ if (status == transition_status.name)
52
+ return transition_status.id
53
+ end
54
+ end
55
+
56
+ raise "Unable to find available status"
57
+ end
58
+
59
+ def title
60
+ self.ticket.summary
61
+ end
62
+
63
+ def url
64
+ "https://#{self.owner}.atlassian.net/browse/#{self.ticket.key}"
65
+ end
66
+
67
+ #
68
+ # Class methods
69
+ #
70
+ def self.username
71
+ return Toolshed::Client::ticket_tracker_username unless Toolshed::Client::ticket_tracker_username.nil?
72
+
73
+ # prompt to ask for username
74
+ puts "Jira username? "
75
+ username = $stdin.gets.chomp.strip
76
+ end
77
+
78
+ def self.password
79
+ return Toolshed::Client::ticket_tracker_password unless Toolshed::Client::ticket_tracker_password.nil?
80
+
81
+ # prompt to ask for password
82
+ system "stty -echo"
83
+ puts "Jira password? "
84
+ password = $stdin.gets.chomp.strip
85
+ system "stty echo"
86
+ end
87
+
88
+ def self.create_instance(options={})
89
+ unless (options.has_key?(:project))
90
+ raise 'Unable to use Jira as project name was not supplied'
91
+ end
92
+
93
+ unless (options.has_key?(:ticket_id))
94
+ raise 'Unable to use Jira as ticket id was not supplied'
95
+ end
96
+
97
+ jira = Toolshed::TicketTracking::Jira.new({
98
+ project: options[:project],
99
+ username: Toolshed::TicketTracking::Jira.username,
100
+ password: Toolshed::TicketTracking::Jira.password,
101
+ ticket_id: options[:ticket_id]
102
+ })
103
+ end
104
+ end
105
+ end
106
+ end
@@ -7,7 +7,7 @@ module Toolshed
7
7
  DEFAULT_COMPLETED_STATUS = 'finished'
8
8
  USE_PROJECT_ID = true
9
9
 
10
- attr_accessor :project_id, :token
10
+ attr_accessor :project_id, :token, :story
11
11
 
12
12
  def initialize(options={})
13
13
  username = Toolshed::Client::pivotal_tracker_username
@@ -25,21 +25,18 @@ module Toolshed
25
25
 
26
26
  self.project_id = (options[:project_id].nil?) ? Toolshed::Client.default_pivotal_tracker_project_id : options[:project_id]
27
27
  @pt_project = ::PivotalTracker::Project.find(self.project_id)
28
+ self.story = @pt_project.stories.find(options[:ticket_id])
28
29
  end
29
30
 
30
- #
31
- # Instance methods
32
- #
33
- def story_information(story_id)
34
- return @pt_project.stories.find(story_id)
31
+ def ticket
32
+ self.story
35
33
  end
36
34
 
37
- def add_note(story_id, note_text)
38
- story = @pt_project.stories.find(story_id)
39
- results = story.notes.create(text: note_text)
35
+ def add_note(note_text)
36
+ results = self.story.notes.create(text: note_text)
40
37
  end
41
38
 
42
- def update_ticket_status(story_id, current_state, options={})
39
+ def update_ticket_status(current_state, options={})
43
40
  options.merge!({
44
41
  :headers => {
45
42
  "X-TrackerToken" => self.token,
@@ -51,7 +48,7 @@ module Toolshed
51
48
  }.to_json
52
49
  })
53
50
 
54
- response = HTTParty.put("#{Toolshed::Client::PIVOTAL_TRACKER_BASE_API_URL}projects/#{self.project_id}/stories/#{story_id}", options).response
51
+ response = HTTParty.put("#{Toolshed::Client::PIVOTAL_TRACKER_BASE_API_URL}projects/#{self.project_id}/stories/#{self.story.id}", options).response
55
52
  response = JSON.parse(response.body)
56
53
 
57
54
  if (response["error"].nil?)
@@ -61,50 +58,55 @@ module Toolshed
61
58
  end
62
59
  end
63
60
 
64
- #
65
- # Class methods
66
- #
67
- def self.story_id_from_branch_name(branch_name)
68
- story_id = branch_name.split("_")[0]
61
+ def title
62
+ self.clean(self.story.name)
69
63
  end
70
64
 
71
- def self.username
72
- username = Toolshed::Client::pivotal_tracker_username
73
- if (username.nil?)
74
- # prompt to ask for username
75
- puts "PivotalTracker username? "
76
- username = $stdin.gets.chomp.strip
77
- end
78
-
79
- return username
65
+ def url(ticket_id)
66
+ self.story.url
80
67
  end
81
68
 
82
- def self.password
83
- password = Toolshed::Client::pivotal_tracker_password
84
- if (password.nil?)
85
- # prompt to ask for password
86
- system "stty -echo"
87
- puts "PivotalTracker password? "
88
- password = $stdin.gets.chomp.strip
89
- system "stty echo"
90
- end
91
-
92
- return password
93
- end
69
+ class << self
70
+ def username
71
+ username = Toolshed::Client::pivotal_tracker_username
72
+ if (username.nil?)
73
+ # prompt to ask for username
74
+ puts "PivotalTracker username? "
75
+ username = $stdin.gets.chomp.strip
76
+ end
94
77
 
95
- #
96
- # Get the pivotal tracker object based off of the project_id
97
- #
98
- def self.create_instance(options={})
99
- unless (options.has_key?(:project_id))
100
- raise 'Unable to use PivotalTracker as project id was not supplied'
78
+ return username
101
79
  end
102
80
 
103
- pivotal_tracker = Toolshed::TicketTracking::PivotalTracker.new({ project_id: options[:project_id], username: Toolshed::TicketTracking::PivotalTracker.username, password: Toolshed::TicketTracking::PivotalTracker.password })
104
- end
81
+ def password
82
+ password = Toolshed::Client::pivotal_tracker_password
83
+ if (password.nil?)
84
+ # prompt to ask for password
85
+ system "stty -echo"
86
+ puts "PivotalTracker password? "
87
+ password = $stdin.gets.chomp.strip
88
+ system "stty echo"
89
+ end
90
+
91
+ return password
92
+ end
105
93
 
106
- def self.clean(title)
107
- title.gsub("'", "").gsub("\"", "")
94
+ def create_instance(options={})
95
+ unless (options.has_key?(:project_id))
96
+ raise 'Unable to use PivotalTracker as project id was not supplied'
97
+ end
98
+
99
+ unless (options.has_key?(:ticket_id))
100
+ raise 'Unable to use PivotalTracker as story id was not supplied'
101
+ end
102
+
103
+ Toolshed::TicketTracking::PivotalTracker.new({
104
+ project_id: options[:project_id],
105
+ username: Toolshed::TicketTracking::PivotalTracker.username,
106
+ password: Toolshed::TicketTracking::PivotalTracker.password,
107
+ ticket_id: options[:ticket_id],
108
+ })
109
+ end
108
110
  end
109
111
  end
110
112
  end
@@ -2,5 +2,15 @@ module Toolshed
2
2
  module TicketTracking
3
3
  def initialize(options={})
4
4
  end
5
+
6
+ class << self
7
+ def story_id_from_branch_name(branch_name)
8
+ branch_name.split("_")[0]
9
+ end
10
+
11
+ def clean(title)
12
+ title.gsub("'", "").gsub("\"", "")
13
+ end
14
+ end
5
15
  end
6
16
  end
@@ -26,37 +26,27 @@ module Toolshed
26
26
  end
27
27
 
28
28
  self.harvest_client = ::Harvest.client(owner, username, password)
29
- self.project_id = self.get_project_id
29
+ self.project_id = options[:project_id] unless !options.has_key?(:project_id)
30
30
 
31
31
  # setup formatting
32
32
  formatter(options)
33
33
  end
34
34
 
35
- def previous(days_ago=1, options={})
35
+ def previous_time_entries(days_ago, options={})
36
+ entries = self.harvest_client.time.all((DateTime.now - days_ago), self.project_id)
36
37
 
37
- notes = "Previous:#{self.line_break}"
38
-
39
- time_entries = self.harvest_client.time.all((DateTime.now - days_ago), self.project_id)
40
- if (time_entries.size > 0 || days_ago == Toolshed::TimeTracking::Harvest::MAX_ATTEMPTS)
41
- notes = "#{notes}#{self.start_unorder_list}"
42
- time_entries.each do |time_entry|
43
- notes = "#{notes}#{self.start_list_item}#{time_entry.notes}#{self.end_list_item}"
44
- if (self.end_list_item == '')
45
- notes = "#{notes}#{self.line_break}"
46
- end
47
- end
48
- notes = "#{notes}#{self.end_unorder_list}"
38
+ if (entries.size > 0 || days_ago == Toolshed::TimeTracking::Harvest::MAX_ATTEMPTS)
39
+ entries
49
40
  else
50
- notes = self.previous(days_ago + 1)
41
+ entries = self.previous_time_entries(days_ago + 1)
51
42
  end
52
-
53
- notes
54
43
  end
55
44
 
56
- def today
57
- notes = "Today:#{self.line_break}"
45
+ def previous_notes(days_ago=1, options={})
46
+ notes = "Previous:#{self.line_break}"
47
+
48
+ time_entries = previous_time_entries(days_ago, options)
58
49
 
59
- time_entries = self.harvest_client.time.all(Time.now, self.project_id)
60
50
  notes = "#{notes}#{self.start_unorder_list}"
61
51
  time_entries.each do |time_entry|
62
52
  notes = "#{notes}#{self.start_list_item}#{time_entry.notes}#{self.end_list_item}"
@@ -69,14 +59,22 @@ module Toolshed
69
59
  notes
70
60
  end
71
61
 
72
- def get_project_id
73
- print "Project ID (Default: #{Toolshed::Client.time_tracking_default_project_id})? "
74
- project_id = $stdin.gets.chomp.strip
75
- if (project_id == '')
76
- project_id = Toolshed::Client.time_tracking_default_project_id
62
+ def todays_time_entries
63
+ self.harvest_client.time.all(Time.now, self.project_id)
64
+ end
65
+
66
+ def todays_notes
67
+ notes = "Today:#{self.line_break}"
68
+ notes = "#{notes}#{self.start_unorder_list}"
69
+ self.todays_time_entries.each do |time_entry|
70
+ notes = "#{notes}#{self.start_list_item}#{time_entry.notes}#{self.end_list_item}"
71
+ if (self.end_list_item == '')
72
+ notes = "#{notes}#{self.line_break}"
73
+ end
77
74
  end
75
+ notes = "#{notes}#{self.end_unorder_list}"
78
76
 
79
- project_id
77
+ notes
80
78
  end
81
79
 
82
80
  def brought_to_you_by_message
@@ -100,6 +98,29 @@ module Toolshed
100
98
  self.end_unorder_list = ""
101
99
  end
102
100
  end
101
+
102
+ def display
103
+ notes = self.previous_notes
104
+ notes = "#{notes}#{self.line_break}#{self.line_break}#{self.todays_notes}"
105
+ notes = "#{notes}#{self.brought_to_you_by_message}"
106
+
107
+ if (self.format == 'html')
108
+ FileUtils.rm_rf(Toolshed::TimeTracking::Harvest::GENERATED_HTML_FILE_LOCATION)
109
+ File.open(Toolshed::TimeTracking::Harvest::GENERATED_HTML_FILE_LOCATION, 'w') {|f| f.write(notes) }
110
+ Launchy.open( Toolshed::TimeTracking::Harvest::GENERATED_HTML_FILE_LOCATION ) do |exception|
111
+ puts "Attempted to open #{uri} and failed because #{exception}"
112
+ end
113
+ puts "Checkout out your default or open browser!"
114
+ else
115
+ puts notes
116
+ end
117
+
118
+ return
119
+ end
120
+
121
+ def self.create_instance(options={})
122
+ Toolshed::TimeTracking::Harvest.new(options)
123
+ end
103
124
  end
104
125
  end
105
126
  end
@@ -1,3 +1,3 @@
1
1
  module Toolshed
2
- VERSION = "0.0.9"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/toolshed.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "toolshed/version"
2
2
  require 'httparty'
3
3
  require 'pivotal-tracker'
4
+ require 'jira'
4
5
  require 'harvested'
5
6
  require 'veto'
6
7
  require 'launchy'
@@ -28,6 +29,7 @@ require 'toolshed/git/git'
28
29
  require 'toolshed/git/github'
29
30
  require 'toolshed/ticket_tracking/ticket_tracking'
30
31
  require 'toolshed/ticket_tracking/pivotal_tracker'
32
+ require 'toolshed/ticket_tracking/jira'
31
33
  require 'toolshed/time_tracking/time_tracking'
32
34
  require 'toolshed/time_tracking/harvest'
33
35
  require 'toolshed/error'
@@ -41,4 +41,24 @@ class CreateBranchTest < Test::Unit::TestCase
41
41
  Toolshed::Git::Base.checkout(current_branch)
42
42
  delete_branch(new_branch_name)
43
43
  end
44
+
45
+ def test_create_new_branch_without_passing_in_branch_from
46
+ Toolshed::Client.pull_from_remote_name = 'origin'
47
+ Toolshed::Client.push_to_remote_name = 'origin'
48
+
49
+ current_branch = Toolshed::Git::Base.branch_name
50
+ new_branch_name = ::Faker::Lorem.word.downcase
51
+
52
+ # stub the possible input
53
+ Toolshed::Commands::CreateBranch.any_instance.stubs(:read_user_input_branch_name).returns(new_branch_name)
54
+
55
+ output = capture_stdout { Toolshed::Commands::CreateBranch.new.execute({}, { branch_name: new_branch_name }) }
56
+
57
+ assert_match /Branch #{new_branch_name} has been created/, output
58
+ assert_equal new_branch_name, Toolshed::Git::Base.branch_name
59
+ assert_equal 'master', Toolshed::Git::Base.branched_from
60
+
61
+ Toolshed::Git::Base.checkout(current_branch)
62
+ delete_branch(new_branch_name)
63
+ end
44
64
  end
@@ -86,7 +86,6 @@ class CreatePullRequestTest < Test::Unit::TestCase
86
86
  with("#{Toolshed::Client::GITHUB_BASE_API_URL}repos/#{Toolshed::Client.pull_from_repository_user}/#{Toolshed::Client.pull_from_repository_name}/pulls", github_default_options).
87
87
  returns(http_party_mock)
88
88
 
89
-
90
89
  # mock up the pivotal_tracker stuff
91
90
  PivotalTracker::Client.expects(:token).
92
91
  with(Toolshed::TicketTracking::PivotalTracker.username, Toolshed::TicketTracking::PivotalTracker.password).
@@ -104,10 +103,19 @@ class CreatePullRequestTest < Test::Unit::TestCase
104
103
  pivotal_tracker_story_mock = mock('PivotalTracker::Story')
105
104
  pivotal_tracker_story_mock.stubs(:url => 'http://www.example.com', :id => '1', :name => "Test Title")
106
105
 
107
- Toolshed::TicketTracking::PivotalTracker.any_instance.expects(:story_information).
106
+ pivotal_tracker_mock.expects(:stories).
107
+ returns(pivotal_tracker_story_mock)
108
+
109
+ pivotal_tracker_story_mock.expects(:find).
108
110
  with('1').
109
111
  returns(pivotal_tracker_story_mock)
110
112
 
113
+ Toolshed::TicketTracking::PivotalTracker.any_instance.expects(:title).
114
+ returns("Sample")
115
+
116
+ Toolshed::TicketTracking::PivotalTracker.any_instance.expects(:url).
117
+ returns("github.com/pulls/1")
118
+
111
119
  # stub the possible input
112
120
  Toolshed::Commands::CreatePullRequest.any_instance.stubs(:read_user_input_ticket_tracker_ticket_id).returns('1')
113
121
  Toolshed::Commands::CreatePullRequest.any_instance.stubs(:read_user_input_add_note_to_ticket).returns(false)
@@ -0,0 +1,60 @@
1
+ require 'commands/commands_helper'
2
+ require 'toolshed/commands/get_daily_time_update'
3
+
4
+ class GetDailyTimeUpdateTest < Test::Unit::TestCase
5
+ def self.startup
6
+ Toolshed::Client.time_tracking_tool = 'harvest'
7
+ Toolshed::Client.time_tracking_default_project_id = '1234'
8
+ Toolshed::Client.time_tracking_username = 'sample_username'
9
+ Toolshed::Client.time_tracking_password = 'sample1234'
10
+ Toolshed::Client.time_tracking_owner = 'me'
11
+ end
12
+
13
+ def test_get_daily_time_update_with_defaults
14
+ ::Harvest.expects(:client).
15
+ with(Toolshed::Client.time_tracking_owner, Toolshed::Client.time_tracking_username, Toolshed::Client.time_tracking_password).
16
+ returns('')
17
+
18
+ harvest_mock = mock('Harvest::TimeEntry')
19
+ harvest_mock.stubs(:notes => 'Worked on this yesterday')
20
+
21
+ Toolshed::TimeTracking::Harvest.any_instance.stubs(:previous_time_entries).
22
+ returns([harvest_mock])
23
+
24
+ harvest_mock = mock('Harvest::TimeEntry')
25
+ harvest_mock.stubs(:notes => 'Worked on this')
26
+
27
+ Toolshed::TimeTracking::Harvest.any_instance.stubs(:todays_time_entries).
28
+ returns([harvest_mock])
29
+
30
+ output = capture_stdout { Toolshed::Commands::GetDailyTimeUpdate.new.execute({}, { project_id: '1111' }) }
31
+ assert_match /Worked on this yesterday/, output
32
+ assert_match /Worked on this/, output
33
+ end
34
+
35
+ def test_get_daily_time_update_with_use_defaults_on
36
+ Toolshed::Client.use_defaults = true
37
+
38
+ ::Harvest.expects(:client).
39
+ with(Toolshed::Client.time_tracking_owner, Toolshed::Client.time_tracking_username, Toolshed::Client.time_tracking_password).
40
+ returns('')
41
+
42
+ harvest_mock = mock('Harvest::TimeEntry')
43
+ harvest_mock.stubs(:notes => 'Worked on this yesterday')
44
+
45
+ Toolshed::TimeTracking::Harvest.any_instance.stubs(:previous_time_entries).
46
+ returns([harvest_mock])
47
+
48
+ harvest_mock = mock('Harvest::TimeEntry')
49
+ harvest_mock.stubs(:notes => 'Worked on this')
50
+
51
+ Toolshed::TimeTracking::Harvest.any_instance.stubs(:todays_time_entries).
52
+ returns([harvest_mock])
53
+
54
+ output = capture_stdout { Toolshed::Commands::GetDailyTimeUpdate.new.execute({}, {}) }
55
+ assert_match /Previous:/, output
56
+ assert_match /Today:/, output
57
+ assert_match /Worked on this yesterday/, output
58
+ assert_match /Worked on this/, output
59
+ end
60
+ end
@@ -21,7 +21,7 @@ def save_stash
21
21
  end
22
22
 
23
23
  def delete_branch(branch_name)
24
- until system("git branch -D #{branch_name} --quiet")
24
+ until system("git branch -D #{branch_name} #{Toolshed::Client.git_quiet}")
25
25
  sleep 1
26
26
  end
27
27
  end
data/test/helper.rb CHANGED
@@ -7,6 +7,9 @@ if (ENV["COVERAGE"])
7
7
  end
8
8
  end
9
9
 
10
+ require "codeclimate-test-reporter"
11
+ CodeClimate::TestReporter.start
12
+
10
13
  require 'test/unit'
11
14
  require 'mocha/test_unit'
12
15
  require 'faker'
@@ -19,6 +22,7 @@ require 'toolshed'
19
22
  Test::Unit.at_start do
20
23
  Toolshed::Client.use_git_submodules = false
21
24
  #Toolshed::Client.git_quiet = '&> /dev/null' unless ENV['RUNNING_ON_CI']
25
+ Toolshed::Client.git_quiet = ''
22
26
 
23
27
  I18n.config.enforce_available_locales = true
24
28