gradesfirst 0.2.1 → 0.3.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.
- data/.gitignore +1 -0
- data/Gemfile +1 -2
- data/Gemfile.lock +2 -6
- data/gradesfirst.gemspec +2 -2
- data/lib/gradesfirst.rb +1 -0
- data/lib/gradesfirst/cli.rb +7 -29
- data/lib/gradesfirst/cli_helper.rb +33 -0
- data/lib/gradesfirst/command.rb +7 -0
- data/lib/gradesfirst/commit_message_command.rb +1 -1
- data/lib/gradesfirst/task_add_command.rb +51 -0
- data/lib/gradesfirst/task_cli.rb +48 -0
- data/lib/gradesfirst/task_command.rb +38 -30
- data/lib/gradesfirst/task_delete_command.rb +64 -0
- data/lib/gradesfirst/task_list_command.rb +40 -0
- data/lib/gradesfirst/task_move_command.rb +64 -0
- data/lib/gradesfirst/task_toggle_command.rb +65 -0
- data/lib/http_magic.rb +2 -258
- data/lib/http_magic/api.rb +233 -0
- data/lib/http_magic/request.rb +93 -0
- data/lib/http_magic/uri.rb +74 -0
- data/lib/pivotal_tracker.rb +1 -1
- data/test/branch_command_test.rb +8 -21
- data/test/cli_test.rb +51 -34
- data/test/command_test.rb +5 -7
- data/test/commit_message_command_test.rb +37 -45
- data/test/fixtures/task.json +10 -0
- data/test/fixtures/task_added.txt +6 -0
- data/test/fixtures/task_deleted.txt +6 -0
- data/test/fixtures/task_moved.txt +6 -0
- data/test/fixtures/task_toggled.txt +6 -0
- data/test/fixtures/tasks.txt +2 -2
- data/test/http_magic/{get_test.rb → api/get_test.rb} +1 -1
- data/test/http_magic/api/post_test.rb +34 -0
- data/test/http_magic/request_test.rb +63 -0
- data/test/http_magic/uri_test.rb +28 -55
- data/test/support/pivotal_test_helper.rb +110 -0
- data/test/support/request_expectation.rb +33 -0
- data/test/task_add_command_test.rb +54 -0
- data/test/task_delete_command_test.rb +57 -0
- data/test/task_list_command_test.rb +18 -0
- data/test/task_move_command_test.rb +66 -0
- data/test/task_toggle_command_test.rb +58 -0
- data/test/test_helper.rb +35 -19
- metadata +29 -7
- data/test/pivotal_tracker_test.rb +0 -46
- data/test/task_command_test.rb +0 -52
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -12,11 +12,8 @@ GEM
|
|
12
12
|
debugger-ruby_core_source (~> 1.2.4)
|
13
13
|
debugger-linecache (1.2.0)
|
14
14
|
debugger-ruby_core_source (1.2.4)
|
15
|
-
metaclass (0.0.1)
|
16
15
|
method_source (0.8.2)
|
17
16
|
minitest (4.7.5)
|
18
|
-
mocha (0.14.0)
|
19
|
-
metaclass (~> 0.0.1)
|
20
17
|
pry (0.9.12.4)
|
21
18
|
coderay (~> 1.0)
|
22
19
|
method_source (~> 0.8)
|
@@ -27,7 +24,7 @@ GEM
|
|
27
24
|
rake (10.0.2)
|
28
25
|
safe_yaml (0.9.7)
|
29
26
|
slop (3.4.7)
|
30
|
-
thor (0.
|
27
|
+
thor (0.18.1)
|
31
28
|
webmock (1.16.0)
|
32
29
|
addressable (>= 2.2.7)
|
33
30
|
crack (>= 0.3.2)
|
@@ -37,9 +34,8 @@ PLATFORMS
|
|
37
34
|
|
38
35
|
DEPENDENCIES
|
39
36
|
minitest (~> 4.7.0)
|
40
|
-
mocha
|
41
37
|
pry
|
42
38
|
pry-debugger
|
43
39
|
rake
|
44
|
-
thor (~> 0.
|
40
|
+
thor (~> 0.18.1)
|
45
41
|
webmock (~> 1.16.0)
|
data/gradesfirst.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.platform = Gem::Platform::RUBY
|
3
3
|
s.name = "gradesfirst"
|
4
|
-
s.version = "0.
|
4
|
+
s.version = "0.3.0"
|
5
5
|
s.summary = "GradesFirst command line utility for developers."
|
6
6
|
s.description = "This utility will help manage the various tasks developers need to do on their workstation such as database updates."
|
7
7
|
s.license = "MIT"
|
@@ -22,6 +22,6 @@ Gem::Specification.new do |s|
|
|
22
22
|
|
23
23
|
s.require_paths = ['lib']
|
24
24
|
|
25
|
-
s.add_dependency('thor', '~> 0.
|
25
|
+
s.add_dependency('thor', '~> 0.18.1')
|
26
26
|
s.add_development_dependency('minitest', '~> 4.7.0')
|
27
27
|
end
|
data/lib/gradesfirst.rb
CHANGED
data/lib/gradesfirst/cli.rb
CHANGED
@@ -1,53 +1,31 @@
|
|
1
1
|
require 'thor'
|
2
2
|
|
3
|
+
require 'gradesfirst/cli_helper'
|
3
4
|
require 'gradesfirst/command'
|
4
5
|
require 'gradesfirst/branch_command'
|
5
6
|
require 'gradesfirst/commit_message_command'
|
6
|
-
require 'gradesfirst/
|
7
|
+
require 'gradesfirst/task_cli'
|
7
8
|
|
8
9
|
require 'pivotal_tracker'
|
9
10
|
|
10
11
|
module GradesFirst
|
11
12
|
class CLI < Thor
|
13
|
+
include GradesFirst::CliHelper
|
12
14
|
|
13
15
|
desc 'branch', GradesFirst::BranchCommand.description
|
14
16
|
def branch
|
15
17
|
set_pivotal_tracker_api_token
|
16
|
-
execute(GradesFirst::BranchCommand
|
18
|
+
execute(GradesFirst::BranchCommand)
|
17
19
|
end
|
18
20
|
|
19
21
|
desc 'commit-message', GradesFirst::CommitMessageCommand.description
|
20
22
|
def commit_message
|
21
23
|
set_pivotal_tracker_api_token
|
22
|
-
execute(GradesFirst::CommitMessageCommand
|
24
|
+
execute(GradesFirst::CommitMessageCommand)
|
23
25
|
end
|
24
26
|
|
25
|
-
desc 'task',
|
26
|
-
|
27
|
-
set_pivotal_tracker_api_token
|
28
|
-
execute(GradesFirst::TaskCommand.new)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def execute(command)
|
34
|
-
command.execute
|
35
|
-
say command.response
|
36
|
-
end
|
37
|
-
|
38
|
-
def set_pivotal_tracker_api_token
|
39
|
-
file_name = "#{Dir.home}/.pivotal_tracker_api_key"
|
40
|
-
if File.exists?(file_name)
|
41
|
-
api_token = File.read(file_name)
|
42
|
-
else
|
43
|
-
api_token = ask('Enter your PivotalTracker API token:')
|
44
|
-
File.open(file_name, 'w') do |file|
|
45
|
-
file.write(api_token)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
PivotalTracker.api_token = api_token
|
50
|
-
end
|
27
|
+
desc 'task COMMAND', 'Manage tasks related to a PivotalTracker story.'
|
28
|
+
subcommand 'task', GradesFirst::TaskCLI
|
51
29
|
|
52
30
|
Signal.trap('SIGINT') do
|
53
31
|
print "\n"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module GradesFirst
|
2
|
+
|
3
|
+
# Helper methods used across multiple Thor CLI commands and subcommands.
|
4
|
+
module CliHelper
|
5
|
+
private
|
6
|
+
|
7
|
+
# Executes a command that conforms to the GradesFirst Command pattern
|
8
|
+
# interface.
|
9
|
+
def execute(klass, *args)
|
10
|
+
command = klass.new
|
11
|
+
command.execute(*args)
|
12
|
+
say command.response
|
13
|
+
end
|
14
|
+
|
15
|
+
# Set the PivotalTracker api token to authenticate the current user.
|
16
|
+
# If the user is access PivotalTracker for the first time then they will
|
17
|
+
# be prompted to enter their api token and it will be saved for later use.
|
18
|
+
def set_pivotal_tracker_api_token
|
19
|
+
file_name = "#{Dir.home}/.pivotal_tracker_api_key"
|
20
|
+
if File.exists?(file_name)
|
21
|
+
api_token = File.read(file_name)
|
22
|
+
else
|
23
|
+
api_token = ask('Enter your PivotalTracker API token:')
|
24
|
+
File.open(file_name, 'w') do |file|
|
25
|
+
file.write(api_token)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
PivotalTracker.api_token = api_token
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
data/lib/gradesfirst/command.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'gradesfirst'
|
2
|
+
|
1
3
|
module GradesFirst
|
2
4
|
|
3
5
|
# Base class for all command objects.
|
@@ -10,6 +12,11 @@ module GradesFirst
|
|
10
12
|
`git rev-parse --abbrev-ref HEAD`
|
11
13
|
end
|
12
14
|
|
15
|
+
# Retrieves the current story
|
16
|
+
def current_story
|
17
|
+
PivotalTracker.stories[story_id].get
|
18
|
+
end
|
19
|
+
|
13
20
|
# Extracts a PivotalTracker story id from a branch if one is present.
|
14
21
|
def story_id(branch = current_branch)
|
15
22
|
if branch =~ /[0-9]+$/
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'gradesfirst/task_command'
|
2
|
+
|
3
|
+
module GradesFirst
|
4
|
+
|
5
|
+
# Implementation of a Thor command for adding tasks to PivotalTracker stories.
|
6
|
+
class TaskAddCommand < GradesFirst::TaskCommand
|
7
|
+
# Description of the "gf task add" Thor command that will be used in
|
8
|
+
# the commandline help.
|
9
|
+
def self.description
|
10
|
+
'Add a task to a PivotalTracker story.'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Performs the gf task add Thor command.
|
14
|
+
def execute(description)
|
15
|
+
@story = current_story
|
16
|
+
if @story
|
17
|
+
@success = task_add(@story, description)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Generates the command line output response. The output of the task add
|
22
|
+
# command is a completion status message which may be followed by the new
|
23
|
+
# list of tasks if the task was added successfully.
|
24
|
+
def response
|
25
|
+
task_action_response(@story, @success)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def story_error_message
|
31
|
+
'Tasks cannot be created for this branch.'
|
32
|
+
end
|
33
|
+
|
34
|
+
def task_add(story, description)
|
35
|
+
PivotalTracker.
|
36
|
+
projects[story['project_id']].
|
37
|
+
stories[story['id']].
|
38
|
+
tasks.
|
39
|
+
post(description: description)
|
40
|
+
end
|
41
|
+
|
42
|
+
def task_error_message
|
43
|
+
'Creation of the task failed.'
|
44
|
+
end
|
45
|
+
|
46
|
+
def task_success_message
|
47
|
+
'Task was successfully added.'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'gradesfirst/cli_helper'
|
2
|
+
require 'gradesfirst/task_add_command'
|
3
|
+
require 'gradesfirst/task_delete_command'
|
4
|
+
require 'gradesfirst/task_list_command'
|
5
|
+
require 'gradesfirst/task_move_command'
|
6
|
+
require 'gradesfirst/task_toggle_command'
|
7
|
+
|
8
|
+
module GradesFirst
|
9
|
+
class TaskCLI < Thor
|
10
|
+
include GradesFirst::CliHelper
|
11
|
+
|
12
|
+
namespace :task
|
13
|
+
# Waiting on fix for subcommands with default command.
|
14
|
+
# https://github.com/erikhuda/thor/pull/374
|
15
|
+
#default_command :list
|
16
|
+
|
17
|
+
desc 'add DESCRIPTION', GradesFirst::TaskAddCommand.description
|
18
|
+
def add(description)
|
19
|
+
set_pivotal_tracker_api_token
|
20
|
+
execute(GradesFirst::TaskAddCommand, description)
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'delete POSITION', GradesFirst::TaskDeleteCommand.description
|
24
|
+
def delete(position)
|
25
|
+
set_pivotal_tracker_api_token
|
26
|
+
execute(GradesFirst::TaskDeleteCommand, position)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'list', GradesFirst::TaskListCommand.description
|
30
|
+
def list
|
31
|
+
set_pivotal_tracker_api_token
|
32
|
+
execute(GradesFirst::TaskListCommand)
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'move FROM TO', GradesFirst::TaskMoveCommand.description
|
36
|
+
def move(from, to)
|
37
|
+
set_pivotal_tracker_api_token
|
38
|
+
execute(GradesFirst::TaskMoveCommand, from , to)
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'toggle POSITION', GradesFirst::TaskToggleCommand.description
|
42
|
+
def toggle(position)
|
43
|
+
set_pivotal_tracker_api_token
|
44
|
+
execute(GradesFirst::TaskToggleCommand, position)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -1,47 +1,55 @@
|
|
1
1
|
require 'gradesfirst/command'
|
2
2
|
|
3
3
|
module GradesFirst
|
4
|
-
|
5
|
-
# Implementation of a Thor command for managing tasks related to a story.
|
6
4
|
class TaskCommand < GradesFirst::Command
|
5
|
+
private
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
'List the tasks related to a PivotalTracker story.'
|
7
|
+
def get_task_id_by_position(story, position)
|
8
|
+
task = get_task_by_position(story, position)
|
9
|
+
task['id'] if task
|
12
10
|
end
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
@story = PivotalTracker.stories[story_id].get
|
17
|
-
if @story
|
18
|
-
project_id = @story['project_id']
|
19
|
-
@tasks = PivotalTracker.projects[project_id].stories[story_id].tasks.get
|
20
|
-
end
|
12
|
+
def get_task_by_position(story, position)
|
13
|
+
get_tasks(story).find { |t| t['position'] == position.to_i }
|
21
14
|
end
|
22
15
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
else
|
30
|
-
task_list = @tasks.map do |t|
|
31
|
-
" [#{t["complete"] ? 'X' : ' '}] #{t["description"]}"
|
32
|
-
end
|
33
|
-
story_line + task_list.join("\n") + "\n"
|
34
|
-
end
|
16
|
+
def get_tasks(story)
|
17
|
+
PivotalTracker.
|
18
|
+
projects[story['project_id']].
|
19
|
+
stories[story['id']].
|
20
|
+
tasks.
|
21
|
+
get
|
35
22
|
end
|
36
23
|
|
37
|
-
|
24
|
+
def position(task)
|
25
|
+
task['position'].to_s.rjust(2)
|
26
|
+
end
|
27
|
+
|
28
|
+
def story_line(story)
|
29
|
+
"#{TAB}#{story['name']} (#{story['url']})\n\n"
|
30
|
+
end
|
38
31
|
|
39
|
-
|
40
|
-
|
32
|
+
# Generates the commandline output response for actions taken on tasks like
|
33
|
+
# add and delete.
|
34
|
+
def task_action_response(story, success)
|
35
|
+
if story.nil?
|
36
|
+
story_error_message
|
37
|
+
elsif !success
|
38
|
+
task_error_message
|
39
|
+
else
|
40
|
+
tasks = get_tasks(story)
|
41
|
+
[
|
42
|
+
TAB + task_success_message,
|
43
|
+
task_list_response(story, tasks)
|
44
|
+
].join("\n\n")
|
45
|
+
end
|
41
46
|
end
|
42
47
|
|
43
|
-
def
|
44
|
-
|
48
|
+
def task_list_response(story, tasks)
|
49
|
+
task_list = tasks.map do |t|
|
50
|
+
"#{TAB}#{position(t)}. [#{t["complete"] ? 'X' : ' '}] #{t["description"]}"
|
51
|
+
end
|
52
|
+
story_line(story) + task_list.join("\n") + "\n"
|
45
53
|
end
|
46
54
|
end
|
47
55
|
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'gradesfirst/task_command'
|
2
|
+
|
3
|
+
module GradesFirst
|
4
|
+
|
5
|
+
# Implementation of a Thor command for deleting tasks from PivotalTracker
|
6
|
+
# stories.
|
7
|
+
class TaskDeleteCommand < GradesFirst::TaskCommand
|
8
|
+
# Description of the "gf task delete" Thor command that will be used in
|
9
|
+
# the commandline help.
|
10
|
+
def self.description
|
11
|
+
'Delete a task from a PivotalTracker story.'
|
12
|
+
end
|
13
|
+
|
14
|
+
# Performs the gf task delete POSITION Thor command.
|
15
|
+
def execute(position)
|
16
|
+
@story = current_story
|
17
|
+
if @story
|
18
|
+
task_id = get_task_id_by_position(@story, position)
|
19
|
+
if task_id
|
20
|
+
@success = task_delete(@story, task_id)
|
21
|
+
else
|
22
|
+
@task_position_invalid = true
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generates the command line output response. The output of the task delete
|
28
|
+
# command is a completion status message which may be followed by the new
|
29
|
+
# list of tasks if the task was deleted successfully.
|
30
|
+
def response
|
31
|
+
if @task_position_invalid
|
32
|
+
position_invalid_message
|
33
|
+
else
|
34
|
+
task_action_response(@story, @success)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def position_invalid_message
|
41
|
+
'Task position given does not exist.'
|
42
|
+
end
|
43
|
+
|
44
|
+
def story_error_message
|
45
|
+
'Tasks cannot be deleted for this branch.'
|
46
|
+
end
|
47
|
+
|
48
|
+
def task_delete(story, task_id)
|
49
|
+
PivotalTracker.
|
50
|
+
projects[story['project_id']].
|
51
|
+
stories[story['id']].
|
52
|
+
tasks[task_id].
|
53
|
+
delete
|
54
|
+
end
|
55
|
+
|
56
|
+
def task_error_message
|
57
|
+
'Deletion of the task failed.'
|
58
|
+
end
|
59
|
+
|
60
|
+
def task_success_message
|
61
|
+
'Task was successfully deleted.'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|