torque 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -1
- data/VERSION +2 -2
- data/bin/config +6 -5
- data/bin/torque +19 -0
- data/lib/torque.rb +12 -1
- data/lib/torque/date_settings.rb +2 -2
- data/lib/torque/pivotal.rb +9 -1
- data/lib/torque/record_pathname_settings.rb +3 -3
- data/lib/torque/settings.rb +48 -5
- data/lib/torque/story.rb +5 -5
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c7055b042760f90fba0fe791442b4ba857bec52
|
4
|
+
data.tar.gz: 2e386cca466678b01c5f3e8dc7b45606285c672b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eace72e27669cb57a907a3155a522d2159dcf12e592c4aa062ce89a4d053f3d7727c5483a322e020794d4235992584422044513c4eec863c0f0b6dac5e982443
|
7
|
+
data.tar.gz: a3c738c870d46ffbc8d84fb1fb7f09ffdcdc566de1ce9ac01ffa807fff82d49fa294be4d11918ff70c766274e3dbb21327dc2511e84bef330362df7b485196e8
|
data/README.md
CHANGED
@@ -25,6 +25,7 @@ Current Features
|
|
25
25
|
* Automatically compiles all Pivotal Tracker stories accepted between the current date and the last time Torque was run
|
26
26
|
* Compile stories accepted within a custom date range
|
27
27
|
* Stores a record of each document as it's generated
|
28
|
+
* Filtering stories by label, owner or story type
|
28
29
|
* Configuration script that automatically sets up a directory to use Torque
|
29
30
|
* Project script that automatically displays/switches between your Pivotal Tracker projects
|
30
31
|
* Ability to email the finished release notes from a personal email account to a pre-specified mailing list. (Currently can only send from accounts hosted by Gmail)
|
@@ -79,6 +80,12 @@ To compile release notes for stories within a custom date range:
|
|
79
80
|
|
80
81
|
If [from] is set, [to] will default to today. If [to] is set, [from] will default to 1/1/1900.
|
81
82
|
|
83
|
+
To filter your results by story label, owner or type:
|
84
|
+
|
85
|
+
# torque --label list,of,labels --owner "list, of, owners" --type "list,of,story types"
|
86
|
+
|
87
|
+
Note: The Pivotal Tracker API currently only supports "AND" searches for these fields. A search for multiple labels, for example, will turn up only the stories that match every label. ("OR" searches may or may not be added with the release of the PT API v5, which should arrive soon.)
|
88
|
+
|
82
89
|
To email the release notes from a personal email to Torque's mailing list:
|
83
90
|
|
84
91
|
# torque --email
|
@@ -89,7 +96,7 @@ To display all available Pivotal Tracker projects or change your current project
|
|
89
96
|
|
90
97
|
# torque project
|
91
98
|
|
92
|
-
To set up automatic emailing
|
99
|
+
To set up automatic emailing of the notes and add/remove from the mailing list:
|
93
100
|
|
94
101
|
# torque email
|
95
102
|
|
data/VERSION
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
major:0
|
2
|
-
minor:
|
3
|
-
patch:
|
2
|
+
minor:1
|
3
|
+
patch:0
|
data/bin/config
CHANGED
@@ -249,9 +249,10 @@ end
|
|
249
249
|
|
250
250
|
# Finishes
|
251
251
|
|
252
|
-
|
253
|
-
|
254
|
-
|
252
|
+
|
253
|
+
puts
|
254
|
+
puts "Configuration complete!"
|
255
|
+
if !options[:token] && !(options[:output_dir] && !should_setup_info)
|
255
256
|
puts "WARNING: Do not check .torqueinfo.yaml into your version control system! (Contains sensitive information)"
|
256
|
-
|
257
|
-
|
257
|
+
end
|
258
|
+
puts
|
data/bin/torque
CHANGED
@@ -52,6 +52,16 @@ option_parser = OptionParser.new do |opts|
|
|
52
52
|
options[:help] = arg
|
53
53
|
end
|
54
54
|
|
55
|
+
opts.on("--label LABELS", "Filters stories by a (comma-separated) list of labels") do
|
56
|
+
|arg|
|
57
|
+
options[:label] = arg
|
58
|
+
end
|
59
|
+
|
60
|
+
opts.on("--owner OWNERS", "Filters stories by a (comma-separated) list of owners") do
|
61
|
+
|arg|
|
62
|
+
options[:owner] = arg
|
63
|
+
end
|
64
|
+
|
55
65
|
opts.on("--root ROOT_DIR", "Set the root directory for the script (should contain a .torqueinfo.yaml file)") do
|
56
66
|
|arg|
|
57
67
|
options[:root_dir] = arg
|
@@ -67,6 +77,11 @@ option_parser = OptionParser.new do |opts|
|
|
67
77
|
options[:accept_to] = arg
|
68
78
|
end
|
69
79
|
|
80
|
+
opts.on("--type TYPES", "Filters stories by a (comma-separated) list of story types") do
|
81
|
+
|arg|
|
82
|
+
options[:type] = arg
|
83
|
+
end
|
84
|
+
|
70
85
|
opts.on("-v", "--verbose", "Run verbosely") do
|
71
86
|
|arg|
|
72
87
|
options[:verbose] = arg
|
@@ -147,4 +162,8 @@ rescue Torque::MissingOutputDirectoryError => e
|
|
147
162
|
puts e.message
|
148
163
|
puts "Run 'torque config -o [directory]' to create/change your output directory"
|
149
164
|
exit 8
|
165
|
+
rescue ArgumentError => e
|
166
|
+
puts "ABORTING"
|
167
|
+
puts e.message
|
168
|
+
exit 9
|
150
169
|
end
|
data/lib/torque.rb
CHANGED
@@ -42,11 +42,17 @@ class Torque
|
|
42
42
|
notes_string += Date.today.strftime(@date_format)+"\n"
|
43
43
|
notes_string += "Release Notes\n"
|
44
44
|
notes_string += "Project #{@settings.project} - '#{project_name}'\n"
|
45
|
+
|
46
|
+
if @settings.filters_on
|
47
|
+
notes_string += "Filter - '#{@settings.filter_string}'\n"
|
48
|
+
end
|
49
|
+
|
45
50
|
if @settings.custom_date_range
|
46
51
|
notes_string += "(custom "+@settings.accept_from.strftime(@date_format)+" - "+@settings.accept_to.strftime(@date_format)+")\n"
|
47
52
|
else
|
48
53
|
notes_string += "("+@settings.accept_from.strftime(@date_format)+" - "+@settings.accept_to.strftime(@date_format)+")\n"
|
49
54
|
end
|
55
|
+
|
50
56
|
notes_string += "\nThese notes were generated with Torque, a Pivotal Tracker command line utility"
|
51
57
|
notes_string += "\n"
|
52
58
|
notes_string += "\n"
|
@@ -136,13 +142,18 @@ class Torque
|
|
136
142
|
|
137
143
|
print_if_not_silent "Current project: #{@settings.project} - '#{project_name}'"
|
138
144
|
|
145
|
+
print_if_not_silent "Filter: '#{@settings.filter_string}'" if @settings.filters_on
|
146
|
+
|
139
147
|
print_if_not_silent "Generating release notes: " \
|
140
148
|
+ (@settings.custom_date_range ? "Custom " : "") \
|
141
149
|
+ @settings.accept_from.strftime(@date_format) + " - " \
|
142
150
|
+ @settings.accept_to.strftime(@date_format) \
|
143
151
|
+ "..."
|
144
152
|
|
145
|
-
|
153
|
+
pivotal = Pivotal.new(@settings.token)
|
154
|
+
@settings.filters_on \
|
155
|
+
? project_html = pivotal.get_project_stories(@settings.project, @settings.filter_string) \
|
156
|
+
: project_html = pivotal.get_project_stories(@settings.project)
|
146
157
|
notes_string = generate_notes(project_html, project_name)
|
147
158
|
|
148
159
|
# Writes the notes to file
|
data/lib/torque/date_settings.rb
CHANGED
@@ -66,13 +66,13 @@ class Torque
|
|
66
66
|
begin
|
67
67
|
@accept_from = Date.parse(@options[:accept_from].nil? ? "1900-01-01" : @options[:accept_from])
|
68
68
|
rescue ArgumentError
|
69
|
-
raise ArgumentError.new("Date #{@options[:accept_from]} could not be parsed")
|
69
|
+
raise ArgumentError.new("Date '#{@options[:accept_from]}' could not be parsed")
|
70
70
|
end
|
71
71
|
|
72
72
|
begin
|
73
73
|
@accept_to = (@options[:accept_to].nil? ? @current_date : Date.parse(@options[:accept_to]))
|
74
74
|
rescue ArgumentError
|
75
|
-
raise ArgumentError.new("Date #{@options[:accept_to]} could not be parsed")
|
75
|
+
raise ArgumentError.new("Date '#{@options[:accept_to]}' could not be parsed")
|
76
76
|
end
|
77
77
|
|
78
78
|
if @accept_from > @accept_to
|
data/lib/torque/pivotal.rb
CHANGED
@@ -35,10 +35,13 @@ class Torque
|
|
35
35
|
end
|
36
36
|
|
37
37
|
##
|
38
|
+
# @param project The ID of the Pivotal Tracker project from which to get data
|
39
|
+
# @param filter_string A string filter for the stories
|
40
|
+
#
|
38
41
|
# Sends a request through the Pivotal Tracker API
|
39
42
|
#
|
40
43
|
# Returns a string of html data from Pivotal Tracker with data on the stories for the given project
|
41
|
-
def get_project_stories(project)
|
44
|
+
def get_project_stories(project, filter_string=nil)
|
42
45
|
|
43
46
|
# Polls story data from pivotal tracker
|
44
47
|
host="pivotaltracker.com"
|
@@ -46,6 +49,9 @@ class Torque
|
|
46
49
|
url="http://www.pivotaltracker.com/services/v3/projects/#{project}/stories"
|
47
50
|
headers={'X-TrackerToken'=>@token}
|
48
51
|
|
52
|
+
url += "?filter=#{filter_string} includedone:true" if filter_string
|
53
|
+
url = URI.escape(url)
|
54
|
+
|
49
55
|
response=Net::HTTP.new(host, port).get(url, headers)
|
50
56
|
|
51
57
|
# Handles network errors
|
@@ -77,6 +83,8 @@ class Torque
|
|
77
83
|
url="http://www.pivotaltracker.com/services/v3/projects"
|
78
84
|
headers={'X-TrackerToken'=>@token}
|
79
85
|
|
86
|
+
url = URI.escape(url)
|
87
|
+
|
80
88
|
response=Net::HTTP.new(host, port).get(url, headers)
|
81
89
|
|
82
90
|
# Handles network errors
|
@@ -9,12 +9,12 @@ class Torque
|
|
9
9
|
##
|
10
10
|
# @param output_dir The path to the release notes output directory
|
11
11
|
# @param project The project id
|
12
|
-
# @param
|
12
|
+
# @param custom True if this is a run with custom settings, else false
|
13
13
|
# @param fs An instance of the FileSystem class
|
14
|
-
def initialize(output_dir, project,
|
14
|
+
def initialize(output_dir, project, custom, fs)
|
15
15
|
@output_dir = output_dir
|
16
16
|
@project = project
|
17
|
-
@custom =
|
17
|
+
@custom = custom
|
18
18
|
@fs = fs
|
19
19
|
end
|
20
20
|
|
data/lib/torque/settings.rb
CHANGED
@@ -25,6 +25,10 @@ class Torque
|
|
25
25
|
# The path to the most recently generated notes
|
26
26
|
attr_reader :current_notes_path
|
27
27
|
|
28
|
+
##
|
29
|
+
# True if should treat this run as a custom run, else false
|
30
|
+
attr_reader :custom
|
31
|
+
|
28
32
|
##
|
29
33
|
# True if a custom date range is being used (set manually through the command line), false if using the default one
|
30
34
|
attr_reader :custom_date_range
|
@@ -45,6 +49,18 @@ class Torque
|
|
45
49
|
# A list of email addresses to send the notes to
|
46
50
|
attr_reader :email_to
|
47
51
|
|
52
|
+
##
|
53
|
+
# True if filters are being used for the stories, else false
|
54
|
+
attr_reader :filter_string
|
55
|
+
|
56
|
+
##
|
57
|
+
# A hash (field => contents) of the filters being used
|
58
|
+
attr_reader :filters
|
59
|
+
|
60
|
+
##
|
61
|
+
# True if filters are being used for the stories, else false
|
62
|
+
attr_reader :filters_on
|
63
|
+
|
48
64
|
##
|
49
65
|
# The path to the .last-run file in the records directory
|
50
66
|
attr_reader :last_run_path
|
@@ -90,16 +106,39 @@ class Torque
|
|
90
106
|
@options = options
|
91
107
|
@fs = fs
|
92
108
|
|
93
|
-
#
|
109
|
+
# Initializes the root directory for Torque
|
110
|
+
|
111
|
+
@root_dir = @options[:root_dir] || "."
|
112
|
+
@root_dir = File.expand_path(@root_dir)
|
113
|
+
|
114
|
+
# Handles boolean options
|
94
115
|
|
95
116
|
@email = @options[:email] || false
|
96
117
|
@silent = @options[:silent] || false
|
97
118
|
@verbose = @options[:verbose] || false
|
98
119
|
|
99
|
-
#
|
120
|
+
# Parses story filters from the options
|
100
121
|
|
101
|
-
@
|
102
|
-
|
122
|
+
@filters = {}
|
123
|
+
|
124
|
+
@filters[:label] = @options[:label] if @options[:label]
|
125
|
+
@filters[:owner] = @options[:owner] if @options[:owner]
|
126
|
+
@filters[:type] = @options[:type] if @options[:type]
|
127
|
+
|
128
|
+
@filters_on = !@filters.empty?
|
129
|
+
|
130
|
+
# Generates a filter string from the story filters
|
131
|
+
|
132
|
+
@filter_string = ""
|
133
|
+
@filters.each do |field, args|
|
134
|
+
args.split(",").each do |arg|
|
135
|
+
arg.strip!
|
136
|
+
@filter_string += "#{field}:"
|
137
|
+
@filter_string += ( (arg.include? " ") ? "\"#{arg}\" " : "#{arg} " )
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
@filter_string.strip!
|
103
142
|
|
104
143
|
# Parses and processes data from .torqueinfo.yaml
|
105
144
|
|
@@ -153,9 +192,13 @@ class Torque
|
|
153
192
|
|
154
193
|
@current_notes_path = "#{output_dir}/release-notes.txt"
|
155
194
|
|
195
|
+
# Determines whether to treat this run as a custom or a default run
|
196
|
+
|
197
|
+
@custom = @custom_date_range || @filters_on
|
198
|
+
|
156
199
|
# Determines the path name to use for the record of the output file
|
157
200
|
|
158
|
-
record_pathname_settings = RecordPathnameSettings.new(@output_dir, @project, @
|
201
|
+
record_pathname_settings = RecordPathnameSettings.new(@output_dir, @project, @custom, @fs)
|
159
202
|
@record_path = record_pathname_settings.get_path
|
160
203
|
|
161
204
|
end
|
data/lib/torque/story.rb
CHANGED
@@ -38,7 +38,7 @@ class Torque
|
|
38
38
|
|
39
39
|
##
|
40
40
|
# The story's type (feature, chore, etc)
|
41
|
-
attr_reader :
|
41
|
+
attr_reader :type
|
42
42
|
|
43
43
|
##
|
44
44
|
# @param html_hash A hash (of html elements keyed by their tags) generated from Pivotal Tracker story html
|
@@ -49,7 +49,7 @@ class Torque
|
|
49
49
|
end
|
50
50
|
|
51
51
|
##
|
52
|
-
# html_hash
|
52
|
+
# @param html_hash A hash (of html elements keyed by their tags) generated from Pivotal Tracker story html
|
53
53
|
#
|
54
54
|
# Creates a new story without parsing its fields
|
55
55
|
def initialize(html_hash)
|
@@ -77,12 +77,12 @@ class Torque
|
|
77
77
|
@name = ""
|
78
78
|
@project_id = -1
|
79
79
|
@story_id = -1
|
80
|
-
@
|
80
|
+
@type = ""
|
81
81
|
|
82
82
|
@current_state = handle_nil(@current_state, html_hash["current_state"])
|
83
83
|
@description = handle_nil(@description, html_hash["description"])
|
84
84
|
@name = handle_nil(@name, html_hash["name"])
|
85
|
-
@
|
85
|
+
@type = handle_nil(@type, html_hash["story_type"])
|
86
86
|
|
87
87
|
@estimate = Integer(handle_nil(@estimate, html_hash["estimate"]))
|
88
88
|
@project_id = Integer(handle_nil(@project_id, html_hash["project_id"]))
|
@@ -100,7 +100,7 @@ class Torque
|
|
100
100
|
self
|
101
101
|
end
|
102
102
|
|
103
|
-
def to_s
|
103
|
+
def to_s
|
104
104
|
return "Story("+@name+", "+"#{@story_id}"+")"
|
105
105
|
end
|
106
106
|
|