shapeup-cli 0.3.2 → 0.3.4
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.
- checksums.yaml +4 -4
- data/lib/shapeup_cli/commands/base.rb +16 -0
- data/lib/shapeup_cli/commands/checklist.rb +122 -0
- data/lib/shapeup_cli/commands/issues.rb +56 -20
- data/lib/shapeup_cli/commands/pitches.rb +11 -3
- data/lib/shapeup_cli/commands/tags.rb +85 -0
- data/lib/shapeup_cli/commands.rb +24 -1
- data/lib/shapeup_cli.rb +17 -13
- data/skills/shapeup/SKILL.md +15 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 167d55101c1c27e4ce1bd6dc8e6f52599937489e4a6218c248f901a150282273
|
|
4
|
+
data.tar.gz: d511b7da6d77e6437ee431951dd591f59b6ed70807be55618564c79b2e9a828b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6cc0fc54f960c09e7338a5ca49ed2eb61820b9246438c2533ce1f1686f5dd4e4b053aed3f63a79e5855a046bff5b859efcf137b1f8db0bdceb8a014220a2c0aa
|
|
7
|
+
data.tar.gz: f4dbcbd90cd4ac33b2d9096fb683b08e76f71f042184faee5a4b91bd7a88802655a593c5b4a60ade0925ad14d07c5c8e7d37991dd31327a6f8c6adef598c403f
|
|
@@ -108,6 +108,22 @@ module ShapeupCli
|
|
|
108
108
|
def positional_args
|
|
109
109
|
@remaining.reject { |a| a.start_with?("--") }
|
|
110
110
|
end
|
|
111
|
+
|
|
112
|
+
# Presence-only boolean flag. Returns true if present, removes from @remaining.
|
|
113
|
+
def consume_flag(flag)
|
|
114
|
+
!!@remaining.delete(flag)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Parse --comments/--no-comments + --comments-limit N into MCP args.
|
|
118
|
+
def comment_flags
|
|
119
|
+
args = {}
|
|
120
|
+
args[:include_comments] = false if consume_flag("--no-comments")
|
|
121
|
+
consume_flag("--comments") # explicit opt-in, no-op since default is true
|
|
122
|
+
if (limit = extract_option("--comments-limit"))
|
|
123
|
+
args[:comments_limit] = limit.to_i
|
|
124
|
+
end
|
|
125
|
+
args
|
|
126
|
+
end
|
|
111
127
|
end
|
|
112
128
|
end
|
|
113
129
|
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShapeupCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Checklist < Base
|
|
6
|
+
def self.metadata
|
|
7
|
+
{
|
|
8
|
+
command: "checklist",
|
|
9
|
+
path: "shapeup checklist",
|
|
10
|
+
short: "Manage the checklist on a pitch or issue",
|
|
11
|
+
subcommands: [
|
|
12
|
+
{ name: "list", short: "List items (default)", path: "shapeup checklist --pitch <id>" },
|
|
13
|
+
{ name: "add", short: "Add an item", path: 'shapeup checklist add --pitch <id> "Item text"' },
|
|
14
|
+
{ name: "tick", short: "Mark an item complete", path: "shapeup checklist tick <item_id>" },
|
|
15
|
+
{ name: "untick", short: "Mark an item incomplete", path: "shapeup checklist untick <item_id>" },
|
|
16
|
+
{ name: "edit", short: "Rename an item", path: 'shapeup checklist edit <item_id> "New text"' },
|
|
17
|
+
{ name: "remove", short: "Delete an item", path: "shapeup checklist remove <item_id>" }
|
|
18
|
+
],
|
|
19
|
+
flags: [
|
|
20
|
+
{ name: "pitch", type: "string", usage: "Pitch ID (for list/add)" },
|
|
21
|
+
{ name: "issue", type: "string", usage: "Issue ID (for list/add)" }
|
|
22
|
+
],
|
|
23
|
+
examples: [
|
|
24
|
+
"shapeup checklist --pitch 42",
|
|
25
|
+
"shapeup checklist --issue 7",
|
|
26
|
+
'shapeup checklist add --pitch 42 "Confirm Slack webhook"',
|
|
27
|
+
"shapeup checklist tick 18",
|
|
28
|
+
"shapeup checklist untick 18",
|
|
29
|
+
'shapeup checklist edit 18 "Confirm Slack webhook secret rotation"',
|
|
30
|
+
"shapeup checklist remove 18"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def execute
|
|
36
|
+
subcommand = positional_arg(0)
|
|
37
|
+
|
|
38
|
+
case subcommand
|
|
39
|
+
when "add" then add
|
|
40
|
+
when "tick" then tick
|
|
41
|
+
when "untick" then untick
|
|
42
|
+
when "edit" then edit
|
|
43
|
+
when "remove" then remove
|
|
44
|
+
when "list", nil then list
|
|
45
|
+
else list
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
def list
|
|
51
|
+
type, id = resolve_target
|
|
52
|
+
result = call_tool("list_checklist_items", checklistable_type: type, checklistable_id: id.to_s)
|
|
53
|
+
|
|
54
|
+
render result,
|
|
55
|
+
summary: "Checklist on #{type} ##{id}",
|
|
56
|
+
breadcrumbs: [
|
|
57
|
+
{ cmd: "shapeup checklist add --#{type.downcase == 'package' ? 'pitch' : 'issue'} #{id} \"Item\"", description: "Add an item" },
|
|
58
|
+
{ cmd: "shapeup checklist tick <item_id>", description: "Tick an item" }
|
|
59
|
+
]
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def add
|
|
63
|
+
type, id = resolve_target
|
|
64
|
+
text = positional_arg(1) || abort('Usage: shapeup checklist add --pitch <id> "Item text"')
|
|
65
|
+
|
|
66
|
+
result = call_tool("create_checklist_item", checklistable_type: type, checklistable_id: id.to_s, content: text)
|
|
67
|
+
|
|
68
|
+
render result,
|
|
69
|
+
summary: "Item added to #{type} ##{id}",
|
|
70
|
+
breadcrumbs: [
|
|
71
|
+
{ cmd: "shapeup checklist --#{type.downcase == 'package' ? 'pitch' : 'issue'} #{id}", description: "View checklist" }
|
|
72
|
+
]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def tick
|
|
76
|
+
item_id = positional_arg(1) || abort("Usage: shapeup checklist tick <item_id>")
|
|
77
|
+
|
|
78
|
+
result = call_tool("update_checklist_item", checklist_item: item_id.to_s, completed: true)
|
|
79
|
+
|
|
80
|
+
render result, summary: "Item ##{item_id} ticked"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def untick
|
|
84
|
+
item_id = positional_arg(1) || abort("Usage: shapeup checklist untick <item_id>")
|
|
85
|
+
|
|
86
|
+
result = call_tool("update_checklist_item", checklist_item: item_id.to_s, completed: false)
|
|
87
|
+
|
|
88
|
+
render result, summary: "Item ##{item_id} unticked"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def edit
|
|
92
|
+
item_id = positional_arg(1) || abort('Usage: shapeup checklist edit <item_id> "New text"')
|
|
93
|
+
text = positional_arg(2) || abort('Usage: shapeup checklist edit <item_id> "New text"')
|
|
94
|
+
|
|
95
|
+
result = call_tool("update_checklist_item", checklist_item: item_id.to_s, content: text)
|
|
96
|
+
|
|
97
|
+
render result, summary: "Item ##{item_id} updated"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def remove
|
|
101
|
+
item_id = positional_arg(1) || abort("Usage: shapeup checklist remove <item_id>")
|
|
102
|
+
|
|
103
|
+
result = call_tool("delete_checklist_item", checklist_item: item_id.to_s)
|
|
104
|
+
|
|
105
|
+
render result, summary: "Item ##{item_id} removed"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def resolve_target
|
|
109
|
+
pitch = extract_option("--pitch")
|
|
110
|
+
issue = extract_option("--issue")
|
|
111
|
+
|
|
112
|
+
if pitch
|
|
113
|
+
[ "Package", pitch ]
|
|
114
|
+
elsif issue
|
|
115
|
+
[ "Issue", issue ]
|
|
116
|
+
else
|
|
117
|
+
abort("Specify a target: --pitch <id> or --issue <id>")
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -25,6 +25,8 @@ module ShapeupCli
|
|
|
25
25
|
{ name: "watch", short: "Watch an issue", path: "shapeup issues watch <id>" },
|
|
26
26
|
{ name: "unwatch", short: "Stop watching an issue", path: "shapeup issues unwatch <id>" },
|
|
27
27
|
{ name: "watching", short: "List issues you are watching", path: "shapeup watching" },
|
|
28
|
+
{ name: "convert", short: "Convert issue into a new pitch", path: "shapeup issues convert <id>" },
|
|
29
|
+
{ name: "add-to-pitch", short: "Fold issue content into an existing pitch", path: "shapeup issues add-to-pitch <id> --pitch <pitch_id>" },
|
|
28
30
|
{ name: "delete", short: "Delete an issue", path: "shapeup issues delete <id>" }
|
|
29
31
|
],
|
|
30
32
|
flags: [
|
|
@@ -37,7 +39,10 @@ module ShapeupCli
|
|
|
37
39
|
{ name: "all", type: "bool", usage: "Include done/closed issues (hidden by default)" },
|
|
38
40
|
{ name: "content", type: "string", usage: "Issue content/description" },
|
|
39
41
|
{ name: "title", type: "string", usage: "Issue title (for update)" },
|
|
40
|
-
{ name: "
|
|
42
|
+
{ name: "pitch", type: "string", usage: "Pitch ID (for add-to-pitch)" },
|
|
43
|
+
{ name: "archived", type: "bool", usage: "Include iceboxed issues in list" },
|
|
44
|
+
{ name: "no-comments", type: "bool", usage: "Hide embedded comments on show (default: show)" },
|
|
45
|
+
{ name: "comments-limit", type: "integer", usage: "Max comments to embed on show (default: 10, max: 50)" }
|
|
41
46
|
],
|
|
42
47
|
examples: [
|
|
43
48
|
"shapeup issues",
|
|
@@ -58,7 +63,9 @@ module ShapeupCli
|
|
|
58
63
|
"shapeup issues assign 42 --user 7",
|
|
59
64
|
"shapeup issues unassign 42",
|
|
60
65
|
"shapeup issues watch 42",
|
|
61
|
-
"shapeup watching"
|
|
66
|
+
"shapeup watching",
|
|
67
|
+
"shapeup issues convert 42",
|
|
68
|
+
"shapeup issues add-to-pitch 42 --pitch 10"
|
|
62
69
|
]
|
|
63
70
|
}
|
|
64
71
|
end
|
|
@@ -67,22 +74,24 @@ module ShapeupCli
|
|
|
67
74
|
subcommand = positional_arg(0)
|
|
68
75
|
|
|
69
76
|
case subcommand
|
|
70
|
-
when "show"
|
|
71
|
-
when "create"
|
|
72
|
-
when "update"
|
|
73
|
-
when "move"
|
|
74
|
-
when "done"
|
|
75
|
-
when "close"
|
|
76
|
-
when "reopen"
|
|
77
|
-
when "icebox"
|
|
78
|
-
when "defrost"
|
|
79
|
-
when "assign"
|
|
80
|
-
when "unassign"
|
|
81
|
-
when "watch"
|
|
82
|
-
when "unwatch"
|
|
83
|
-
when "watching"
|
|
84
|
-
when "
|
|
85
|
-
when "
|
|
77
|
+
when "show" then show
|
|
78
|
+
when "create" then create
|
|
79
|
+
when "update" then update
|
|
80
|
+
when "move" then move
|
|
81
|
+
when "done" then mark_done
|
|
82
|
+
when "close" then close
|
|
83
|
+
when "reopen" then reopen
|
|
84
|
+
when "icebox" then icebox
|
|
85
|
+
when "defrost" then defrost
|
|
86
|
+
when "assign" then assign
|
|
87
|
+
when "unassign" then unassign
|
|
88
|
+
when "watch" then watch
|
|
89
|
+
when "unwatch" then unwatch
|
|
90
|
+
when "watching" then watching
|
|
91
|
+
when "convert" then convert
|
|
92
|
+
when "add-to-pitch" then add_to_pitch
|
|
93
|
+
when "delete" then delete
|
|
94
|
+
when "list", nil then list
|
|
86
95
|
else
|
|
87
96
|
# Bare numeric arg = show
|
|
88
97
|
if subcommand&.match?(/\A\d+\z/)
|
|
@@ -125,14 +134,15 @@ module ShapeupCli
|
|
|
125
134
|
|
|
126
135
|
def show
|
|
127
136
|
id = positional_arg(1) || positional_arg(0) || abort("Usage: shapeup issue <id>")
|
|
128
|
-
result = call_tool("show_issue", issue: id.to_s)
|
|
137
|
+
result = call_tool("show_issue", issue: id.to_s, **comment_flags)
|
|
129
138
|
|
|
130
139
|
render result,
|
|
131
140
|
summary: "Issue ##{id}",
|
|
132
141
|
breadcrumbs: [
|
|
133
142
|
{ cmd: "shapeup issues move #{id} --column <id>", description: "Move to column" },
|
|
134
143
|
{ cmd: "shapeup issues icebox #{id}", description: "Move to icebox" },
|
|
135
|
-
{ cmd: "shapeup issues watch #{id}", description: "Watch this issue" }
|
|
144
|
+
{ cmd: "shapeup issues watch #{id}", description: "Watch this issue" },
|
|
145
|
+
{ cmd: "shapeup issue #{id} --no-comments", description: "Hide embedded comments" }
|
|
136
146
|
]
|
|
137
147
|
end
|
|
138
148
|
|
|
@@ -331,6 +341,32 @@ module ShapeupCli
|
|
|
331
341
|
{ cmd: "shapeup issues", description: "List remaining issues" }
|
|
332
342
|
]
|
|
333
343
|
end
|
|
344
|
+
|
|
345
|
+
def convert
|
|
346
|
+
id = positional_arg(1) || abort("Usage: shapeup issues convert <id>")
|
|
347
|
+
|
|
348
|
+
result = call_tool("convert_issue_to_pitch", issue: id.to_s)
|
|
349
|
+
|
|
350
|
+
render result,
|
|
351
|
+
summary: "Issue ##{id} converted to a pitch",
|
|
352
|
+
breadcrumbs: [
|
|
353
|
+
{ cmd: "shapeup pitches", description: "List pitches" },
|
|
354
|
+
{ cmd: "shapeup pitch <id>", description: "Open the new pitch" }
|
|
355
|
+
]
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def add_to_pitch
|
|
359
|
+
id = positional_arg(1) || abort('Usage: shapeup issues add-to-pitch <id> --pitch <pitch_id>')
|
|
360
|
+
pitch_id = extract_option("--pitch") || abort('Usage: shapeup issues add-to-pitch <id> --pitch <pitch_id>')
|
|
361
|
+
|
|
362
|
+
result = call_tool("add_issue_to_pitch", issue: id.to_s, package: pitch_id.to_s)
|
|
363
|
+
|
|
364
|
+
render result,
|
|
365
|
+
summary: "Issue ##{id} folded into pitch ##{pitch_id}",
|
|
366
|
+
breadcrumbs: [
|
|
367
|
+
{ cmd: "shapeup pitch #{pitch_id}", description: "Open the pitch" }
|
|
368
|
+
]
|
|
369
|
+
end
|
|
334
370
|
end
|
|
335
371
|
end
|
|
336
372
|
end
|
|
@@ -17,15 +17,19 @@ module ShapeupCli
|
|
|
17
17
|
flags: [
|
|
18
18
|
{ name: "status", type: "string", usage: "Filter by status: idea, framed, shaped" },
|
|
19
19
|
{ name: "cycle", type: "string", usage: "Filter by cycle ID" },
|
|
20
|
+
{ name: "tag", type: "string", usage: "Filter by tag name" },
|
|
20
21
|
{ name: "limit", type: "integer", usage: "Limit number of results" },
|
|
21
22
|
{ name: "stream", type: "string", usage: "Stream name or ID (for create)" },
|
|
22
23
|
{ name: "appetite", type: "string", usage: "Appetite: unknown, small_batch, big_batch (for create, default: big_batch)" },
|
|
23
|
-
{ name: "cycle-id", type: "string", usage: "Assign to cycle ID (for create)" }
|
|
24
|
+
{ name: "cycle-id", type: "string", usage: "Assign to cycle ID (for create)" },
|
|
25
|
+
{ name: "no-comments", type: "bool", usage: "Hide embedded comments on show (default: show)" },
|
|
26
|
+
{ name: "comments-limit", type: "integer", usage: "Max comments to embed on show (default: 10, max: 50)" }
|
|
24
27
|
],
|
|
25
28
|
examples: [
|
|
26
29
|
"shapeup pitches list",
|
|
27
30
|
"shapeup pitches list --status shaped",
|
|
28
31
|
"shapeup pitches list --cycle 5",
|
|
32
|
+
"shapeup pitches list --tag q3-plan",
|
|
29
33
|
"shapeup pitch 42",
|
|
30
34
|
"shapeup pitch 42 --json",
|
|
31
35
|
"shapeup pitches create \"Redesign Search\" --stream \"Platform\"",
|
|
@@ -51,9 +55,11 @@ module ShapeupCli
|
|
|
51
55
|
def list
|
|
52
56
|
cycle_id = extract_option("--cycle")
|
|
53
57
|
status = extract_option("--status")
|
|
58
|
+
tag = extract_option("--tag")
|
|
54
59
|
limit = extract_option("--limit")&.to_i
|
|
55
60
|
args = {}
|
|
56
61
|
args[:cycle] = cycle_id if cycle_id
|
|
62
|
+
args[:tag] = tag if tag
|
|
57
63
|
|
|
58
64
|
result = call_tool("list_packages", **args)
|
|
59
65
|
data = Output.extract_data(result)
|
|
@@ -66,6 +72,7 @@ module ShapeupCli
|
|
|
66
72
|
summary = "Pitches"
|
|
67
73
|
summary += " (#{status})" if status
|
|
68
74
|
summary += " in cycle #{cycle_id}" if cycle_id
|
|
75
|
+
summary += " tagged #{tag}" if tag
|
|
69
76
|
summary += " — #{packages.length} results"
|
|
70
77
|
|
|
71
78
|
render_list(packages, summary)
|
|
@@ -74,7 +81,7 @@ module ShapeupCli
|
|
|
74
81
|
def show(id = nil)
|
|
75
82
|
id ||= positional_arg(1) || abort("Usage: shapeup pitches show <id>")
|
|
76
83
|
|
|
77
|
-
result = call_tool("show_package", package: id.to_s)
|
|
84
|
+
result = call_tool("show_package", package: id.to_s, **comment_flags)
|
|
78
85
|
|
|
79
86
|
render result,
|
|
80
87
|
summary: "Pitch ##{id}",
|
|
@@ -82,7 +89,8 @@ module ShapeupCli
|
|
|
82
89
|
{ cmd: "shapeup scopes list --pitch #{id}", description: "List scopes" },
|
|
83
90
|
{ cmd: "shapeup scopes create --pitch #{id} \"Title\"", description: "Add a scope" },
|
|
84
91
|
{ cmd: "shapeup todo \"Task\" --pitch #{id}", description: "Add a task" },
|
|
85
|
-
{ cmd: "shapeup tasks list --pitch #{id}", description: "List all tasks" }
|
|
92
|
+
{ cmd: "shapeup tasks list --pitch #{id}", description: "List all tasks" },
|
|
93
|
+
{ cmd: "shapeup pitch #{id} --no-comments", description: "Hide embedded comments" }
|
|
86
94
|
]
|
|
87
95
|
end
|
|
88
96
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShapeupCli
|
|
4
|
+
module Commands
|
|
5
|
+
class Tags < Base
|
|
6
|
+
def self.metadata
|
|
7
|
+
{
|
|
8
|
+
command: "tags",
|
|
9
|
+
path: "shapeup tags",
|
|
10
|
+
short: "List, add, and remove tags on pitches and issues",
|
|
11
|
+
subcommands: [
|
|
12
|
+
{ name: "list", short: "List the org's tag vocabulary (default)", path: "shapeup tags" },
|
|
13
|
+
{ name: "add", short: "Tag a pitch or issue", path: "shapeup tags add --pitch <id> <name>" },
|
|
14
|
+
{ name: "remove", short: "Untag a pitch or issue", path: "shapeup tags remove --pitch <id> <name>" }
|
|
15
|
+
],
|
|
16
|
+
flags: [
|
|
17
|
+
{ name: "pitch", type: "string", usage: "Pitch ID (for add/remove)" },
|
|
18
|
+
{ name: "issue", type: "string", usage: "Issue ID (for add/remove)" }
|
|
19
|
+
],
|
|
20
|
+
examples: [
|
|
21
|
+
"shapeup tags",
|
|
22
|
+
"shapeup tags add --pitch 42 q3-plan",
|
|
23
|
+
"shapeup tags add --issue 7 needs-design",
|
|
24
|
+
"shapeup tags remove --pitch 42 q3-plan",
|
|
25
|
+
"shapeup pitches list --tag q3-plan"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def execute
|
|
31
|
+
subcommand = positional_arg(0)
|
|
32
|
+
|
|
33
|
+
case subcommand
|
|
34
|
+
when "add" then add
|
|
35
|
+
when "remove" then remove
|
|
36
|
+
when "list", nil then list
|
|
37
|
+
else list
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
def list
|
|
43
|
+
result = call_tool("list_tags")
|
|
44
|
+
|
|
45
|
+
render result,
|
|
46
|
+
summary: "Tags",
|
|
47
|
+
breadcrumbs: [
|
|
48
|
+
{ cmd: "shapeup tags add --pitch <id> <name>", description: "Tag a pitch" },
|
|
49
|
+
{ cmd: "shapeup pitches list --tag <name>", description: "Filter pitches by tag" }
|
|
50
|
+
]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def add
|
|
54
|
+
type, id = resolve_target
|
|
55
|
+
name = positional_arg(1) || abort("Usage: shapeup tags add --pitch <id> <name>")
|
|
56
|
+
|
|
57
|
+
result = call_tool("add_tag", taggable_type: type, taggable_id: id.to_s, name: name)
|
|
58
|
+
|
|
59
|
+
render result, summary: "Tagged #{type} ##{id}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def remove
|
|
63
|
+
type, id = resolve_target
|
|
64
|
+
name = positional_arg(1) || abort("Usage: shapeup tags remove --pitch <id> <name>")
|
|
65
|
+
|
|
66
|
+
result = call_tool("remove_tag", taggable_type: type, taggable_id: id.to_s, name: name)
|
|
67
|
+
|
|
68
|
+
render result, summary: "Untagged #{type} ##{id}"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def resolve_target
|
|
72
|
+
pitch = extract_option("--pitch")
|
|
73
|
+
issue = extract_option("--issue")
|
|
74
|
+
|
|
75
|
+
if pitch
|
|
76
|
+
[ "Package", pitch ]
|
|
77
|
+
elsif issue
|
|
78
|
+
[ "Issue", issue ]
|
|
79
|
+
else
|
|
80
|
+
abort("Specify a target: --pitch <id> or --issue <id>")
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/shapeup_cli/commands.rb
CHANGED
|
@@ -62,6 +62,9 @@ module ShapeupCli
|
|
|
62
62
|
issues unwatch <id> Stop watching
|
|
63
63
|
watching List issues you are watching
|
|
64
64
|
issues delete <id> Delete an issue
|
|
65
|
+
issues convert <id> Convert issue to a new pitch
|
|
66
|
+
issues add-to-pitch <id> --pitch <pid>
|
|
67
|
+
Fold issue into an existing pitch
|
|
65
68
|
|
|
66
69
|
Comments:
|
|
67
70
|
comments list --issue <id> List comments on an issue
|
|
@@ -69,6 +72,22 @@ module ShapeupCli
|
|
|
69
72
|
comments add --issue <id> "Text" Add a comment to an issue
|
|
70
73
|
comments add --pitch <id> "Text" Add a comment to a pitch
|
|
71
74
|
|
|
75
|
+
Checklist:
|
|
76
|
+
checklist --pitch <id> List the checklist on a pitch
|
|
77
|
+
checklist --issue <id> List the checklist on an issue
|
|
78
|
+
checklist add --pitch <id> "Text" Add an item
|
|
79
|
+
checklist tick <item_id> Mark an item complete
|
|
80
|
+
checklist untick <item_id> Mark an item incomplete
|
|
81
|
+
checklist edit <item_id> "Text" Rename an item
|
|
82
|
+
checklist remove <item_id> Delete an item
|
|
83
|
+
|
|
84
|
+
Tags:
|
|
85
|
+
tags List the org's tag vocabulary
|
|
86
|
+
tags add --pitch <id> <name> Tag a pitch
|
|
87
|
+
tags add --issue <id> <name> Tag an issue
|
|
88
|
+
tags remove --pitch <id> <name> Untag a pitch
|
|
89
|
+
tags remove --issue <id> <name> Untag an issue
|
|
90
|
+
|
|
72
91
|
My Work:
|
|
73
92
|
my-work, me Show everything assigned to me
|
|
74
93
|
|
|
@@ -128,10 +147,12 @@ module ShapeupCli
|
|
|
128
147
|
tasks Manage tasks (list, create, complete)
|
|
129
148
|
todo Create a task (shortcut)
|
|
130
149
|
done Complete task(s) (shortcut)
|
|
131
|
-
issues Manage issues (list, show, create, move, icebox, watch)
|
|
150
|
+
issues Manage issues (list, show, create, move, icebox, watch, convert, add-to-pitch)
|
|
132
151
|
issue Show an issue (shortcut)
|
|
133
152
|
watching List watched issues (shortcut)
|
|
134
153
|
comments List and add comments (list, add)
|
|
154
|
+
checklist Manage checklist items on pitches/issues (list, add, tick, untick, edit, remove)
|
|
155
|
+
tags List/add/remove tags on pitches and issues
|
|
135
156
|
my-work / me Show my assigned work
|
|
136
157
|
search Search everything
|
|
137
158
|
config Show/set config (set, show, init)
|
|
@@ -159,3 +180,5 @@ require_relative "commands/auth"
|
|
|
159
180
|
require_relative "commands/config_cmd"
|
|
160
181
|
require_relative "commands/setup"
|
|
161
182
|
require_relative "commands/comments"
|
|
183
|
+
require_relative "commands/checklist"
|
|
184
|
+
require_relative "commands/tags"
|
data/lib/shapeup_cli.rb
CHANGED
|
@@ -16,7 +16,7 @@ require_relative "shapeup_cli/output"
|
|
|
16
16
|
require_relative "shapeup_cli/commands"
|
|
17
17
|
|
|
18
18
|
module ShapeupCli
|
|
19
|
-
VERSION = "0.3.
|
|
19
|
+
VERSION = "0.3.4"
|
|
20
20
|
DEFAULT_HOST = "https://shapeup.cc"
|
|
21
21
|
|
|
22
22
|
# Exit codes
|
|
@@ -30,18 +30,20 @@ module ShapeupCli
|
|
|
30
30
|
EXIT_INTERRUPTED = 130
|
|
31
31
|
|
|
32
32
|
COMMAND_MAP = {
|
|
33
|
-
"orgs"
|
|
34
|
-
"pitches"
|
|
35
|
-
"cycle"
|
|
36
|
-
"scopes"
|
|
37
|
-
"tasks"
|
|
38
|
-
"issues"
|
|
39
|
-
"my-work"
|
|
40
|
-
"search"
|
|
41
|
-
"auth"
|
|
42
|
-
"config"
|
|
43
|
-
"setup"
|
|
44
|
-
"comments"
|
|
33
|
+
"orgs" => Commands::Orgs,
|
|
34
|
+
"pitches" => Commands::Pitches,
|
|
35
|
+
"cycle" => Commands::Cycle,
|
|
36
|
+
"scopes" => Commands::Scopes,
|
|
37
|
+
"tasks" => Commands::Tasks,
|
|
38
|
+
"issues" => Commands::Issues,
|
|
39
|
+
"my-work" => Commands::MyWork,
|
|
40
|
+
"search" => Commands::Search,
|
|
41
|
+
"auth" => Commands::Auth,
|
|
42
|
+
"config" => Commands::ConfigCmd,
|
|
43
|
+
"setup" => Commands::Setup,
|
|
44
|
+
"comments" => Commands::Comments,
|
|
45
|
+
"checklist" => Commands::Checklist,
|
|
46
|
+
"tags" => Commands::Tags
|
|
45
47
|
}.freeze
|
|
46
48
|
|
|
47
49
|
def self.run(argv)
|
|
@@ -77,6 +79,8 @@ module ShapeupCli
|
|
|
77
79
|
when "issue" then Commands::Issues.run(["show"] + args)
|
|
78
80
|
when "watching" then Commands::Issues.run(["watching"] + args)
|
|
79
81
|
when "comments" then Commands::Comments.run(args)
|
|
82
|
+
when "checklist" then Commands::Checklist.run(args)
|
|
83
|
+
when "tags" then Commands::Tags.run(args)
|
|
80
84
|
when "my-work", "me" then Commands::MyWork.run(args)
|
|
81
85
|
when "search" then Commands::Search.run(args)
|
|
82
86
|
when "config" then Commands::ConfigCmd.run(args)
|
data/skills/shapeup/SKILL.md
CHANGED
|
@@ -133,11 +133,26 @@ Manage pitches, scopes, tasks, issues, and cycles via the ShapeUp CLI. Columns a
|
|
|
133
133
|
| Unassign from issue | `shapeup issues unassign <id>` (self) / `--user <id>` |
|
|
134
134
|
| Watch / unwatch | `shapeup issues watch <id>` / `unwatch <id>` |
|
|
135
135
|
| My watched issues | `shapeup watching --json` |
|
|
136
|
+
| Convert issue to pitch | `shapeup issues convert <id>` |
|
|
137
|
+
| Fold issue into pitch | `shapeup issues add-to-pitch <id> --pitch <pitch_id>` |
|
|
136
138
|
| **Comments** | |
|
|
137
139
|
| List comments on issue | `shapeup comments list --issue <id> --json` |
|
|
138
140
|
| List comments on pitch | `shapeup comments list --pitch <id> --json` |
|
|
139
141
|
| Add comment to issue | `shapeup comments add --issue <id> "Comment text"` |
|
|
140
142
|
| Add comment to pitch | `shapeup comments add --pitch <id> "Comment text"` |
|
|
143
|
+
| **Checklist** | |
|
|
144
|
+
| List checklist on pitch | `shapeup checklist --pitch <id>` |
|
|
145
|
+
| List checklist on issue | `shapeup checklist --issue <id>` |
|
|
146
|
+
| Add an item | `shapeup checklist add --pitch <id> "Item text"` |
|
|
147
|
+
| Tick / untick an item | `shapeup checklist tick <item_id>` / `untick <item_id>` |
|
|
148
|
+
| Rename an item | `shapeup checklist edit <item_id> "New text"` |
|
|
149
|
+
| Remove an item | `shapeup checklist remove <item_id>` |
|
|
150
|
+
| **Tags** | |
|
|
151
|
+
| List tag vocabulary | `shapeup tags` |
|
|
152
|
+
| Tag a pitch | `shapeup tags add --pitch <id> <name>` |
|
|
153
|
+
| Tag an issue | `shapeup tags add --issue <id> <name>` |
|
|
154
|
+
| Untag | `shapeup tags remove --pitch <id> <name>` |
|
|
155
|
+
| Filter pitches by tag | `shapeup pitches list --tag <name>` |
|
|
141
156
|
| **Pitches** | |
|
|
142
157
|
| List pitches | `shapeup pitches list --json` |
|
|
143
158
|
| List shaped only | `shapeup pitches list --status shaped --json` |
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shapeup-cli
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ShapeUp
|
|
@@ -27,6 +27,7 @@ files:
|
|
|
27
27
|
- lib/shapeup_cli/commands.rb
|
|
28
28
|
- lib/shapeup_cli/commands/auth.rb
|
|
29
29
|
- lib/shapeup_cli/commands/base.rb
|
|
30
|
+
- lib/shapeup_cli/commands/checklist.rb
|
|
30
31
|
- lib/shapeup_cli/commands/comments.rb
|
|
31
32
|
- lib/shapeup_cli/commands/config_cmd.rb
|
|
32
33
|
- lib/shapeup_cli/commands/cycle.rb
|
|
@@ -39,6 +40,7 @@ files:
|
|
|
39
40
|
- lib/shapeup_cli/commands/scopes.rb
|
|
40
41
|
- lib/shapeup_cli/commands/search.rb
|
|
41
42
|
- lib/shapeup_cli/commands/setup.rb
|
|
43
|
+
- lib/shapeup_cli/commands/tags.rb
|
|
42
44
|
- lib/shapeup_cli/commands/tasks.rb
|
|
43
45
|
- lib/shapeup_cli/config.rb
|
|
44
46
|
- lib/shapeup_cli/output.rb
|
|
@@ -64,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
64
66
|
- !ruby/object:Gem::Version
|
|
65
67
|
version: '0'
|
|
66
68
|
requirements: []
|
|
67
|
-
rubygems_version:
|
|
69
|
+
rubygems_version: 4.0.6
|
|
68
70
|
specification_version: 4
|
|
69
71
|
summary: ShapeUp CLI — manage pitches, scopes, tasks, and cycles from the terminal
|
|
70
72
|
test_files: []
|