tractive 1.0.1 → 1.0.5
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/Gemfile.lock +1 -1
- data/README.adoc +69 -20
- data/config.example.yaml +41 -10
- data/exe/tractive +3 -2
- data/lib/tractive/github_api/client/labels.rb +33 -0
- data/lib/tractive/github_api/client.rb +2 -0
- data/lib/tractive/info.rb +4 -4
- data/lib/tractive/migrator/converter/trac_to_github.rb +25 -6
- data/lib/tractive/migrator/engine.rb +1 -1
- data/lib/tractive/models/ticket.rb +4 -1
- data/lib/tractive/revmap_generator.rb +22 -9
- data/lib/tractive/utilities.rb +7 -0
- data/lib/tractive/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db1fec86bca93ac81ac4ce8c4f1e6fb99f0983743c55fc3275a95188c8178e0e
|
4
|
+
data.tar.gz: f2907430c9a64b4cd5e0004050c1d7eddf11a18f94a4a007bf5315706a73e23b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1828a51469e9418188cd72195b51b245bb47921b7fbc883287bd089f9b2da58d18fbf08411c9f5cc33ed4a4a92259e365931afe281e1cf810a16c97a0632fa1a
|
7
|
+
data.tar.gz: f898f265b58c41ca3ae59ee20cf52ec50ced92045a1595f23ea50e66bb4b0bd911a8695cfdc34b3a41a248a8b11bcb3a20be70eb8193aba8a7867c3f9ba4cc1e
|
data/Gemfile.lock
CHANGED
data/README.adoc
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
= Tractive: migrating from Trac to GitHub
|
2
|
-
|
3
2
|
== Purpose
|
4
3
|
|
5
4
|
Tractive is a tool that helps you migrate Trac instances to GitHub.
|
@@ -194,15 +193,17 @@ user interface.
|
|
194
193
|
|
195
194
|
| `--svn-url`
|
196
195
|
|
|
197
|
-
(required
|
198
|
-
|
199
|
-
prefix).
|
196
|
+
(required unless `--svn-local-path` set)
|
197
|
+
SVN repository URL that should be used in RevMap generation. The URL must start
|
198
|
+
with the `http://` or `https://` prefix (not the `svn://` prefix).
|
200
199
|
| String
|
201
200
|
|
202
201
|
| `--svn-local-path`
|
203
|
-
|
|
204
|
-
|
205
|
-
|
202
|
+
|
|
203
|
+
(required unless `-svn-url` set)
|
204
|
+
SVN local repository path that should be used in RevMap generation. You can
|
205
|
+
clone the svn repo locally and provide its local path if the svn repository is
|
206
|
+
offline.
|
206
207
|
| String
|
207
208
|
|
208
209
|
| `--rev-timestamp-file`
|
@@ -384,25 +385,55 @@ The pattern of a mapping is like:
|
|
384
385
|
+
|
385
386
|
[source,yaml]
|
386
387
|
----
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
388
|
+
trivial:
|
389
|
+
name: trivial
|
390
|
+
color: ff0000
|
391
|
+
major:
|
392
|
+
name: major
|
393
|
+
color: b44647
|
394
|
+
minor:
|
395
|
+
name: minor
|
396
|
+
color: f7347a
|
397
|
+
medium:
|
398
|
+
name: medium
|
399
|
+
color: f3c77c
|
395
400
|
----
|
396
401
|
|
397
402
|
`priority:`::: Priority of the Trac ticket.
|
398
403
|
+
|
399
404
|
[source,yaml]
|
400
405
|
----
|
401
|
-
Low:
|
402
|
-
|
406
|
+
Low:
|
407
|
+
name: low
|
408
|
+
color: 22dd00
|
409
|
+
High:
|
410
|
+
name: high
|
411
|
+
color: ff0000
|
412
|
+
----
|
413
|
+
|
414
|
+
|
415
|
+
`tracstate:`::: Status of the Trac ticket.
|
416
|
+
+
|
417
|
+
[source,yaml]
|
418
|
+
----
|
419
|
+
accepted:
|
420
|
+
name: accepted
|
421
|
+
color: 22dd00
|
422
|
+
assigned:
|
423
|
+
name: assigned
|
424
|
+
color: aadd88
|
425
|
+
closed:
|
426
|
+
name: closed
|
427
|
+
color: ee00aa
|
428
|
+
new:
|
429
|
+
name: new
|
430
|
+
color:
|
403
431
|
----
|
404
432
|
|
405
433
|
|
434
|
+
NOTE: As `severity`, `priority` and `tracstate` are converted into `labels` on github so there is an option to specify the `color` for those labels.
|
435
|
+
|
436
|
+
|
406
437
|
==== User mapping
|
407
438
|
|
408
439
|
`users:`:: a one-to-one mapping between Trac usernames or email addresses to
|
@@ -411,7 +442,10 @@ GitHub usernames for users, in the following pattern:
|
|
411
442
|
[source,yaml]
|
412
443
|
----
|
413
444
|
users:
|
414
|
-
{Trac email or username}:
|
445
|
+
{Trac email or username}:
|
446
|
+
email: {Github email}
|
447
|
+
name: {name of the person}
|
448
|
+
username: {username on GitHub}
|
415
449
|
...
|
416
450
|
----
|
417
451
|
|
@@ -420,8 +454,23 @@ EXAMPLE:
|
|
420
454
|
[source,yaml]
|
421
455
|
----
|
422
456
|
users:
|
423
|
-
matthew@
|
424
|
-
|
457
|
+
matthew@gmail.org:
|
458
|
+
email: matthew@example.org
|
459
|
+
name: Matthew
|
460
|
+
username: example-matt
|
461
|
+
valencia:
|
462
|
+
email: valencia
|
463
|
+
name: Valencia
|
464
|
+
username: example-vale
|
465
|
+
----
|
466
|
+
|
467
|
+
If you don't want to map a user, you can just leave the `username` empty like below:
|
468
|
+
----
|
469
|
+
users:
|
470
|
+
matthew@gmail.org:
|
471
|
+
email: matthew@example.org
|
472
|
+
name: Matthew
|
473
|
+
username:
|
425
474
|
----
|
426
475
|
|
427
476
|
==== Milestone mapping
|
data/config.example.yaml
CHANGED
@@ -24,9 +24,16 @@ revmap_path: ./example-revmap.txt
|
|
24
24
|
# the issue migration process will fail if the GitHub user specified as owner
|
25
25
|
# (assignee) does not exist.
|
26
26
|
users:
|
27
|
-
# <Trac email or username
|
28
|
-
|
29
|
-
|
27
|
+
# email: <Trac email or username>
|
28
|
+
# name: <Name of the person (optional)>
|
29
|
+
# username: <username on GitHub>
|
30
|
+
- email: matthew@example.org
|
31
|
+
name: Matthew
|
32
|
+
username: example-matt
|
33
|
+
|
34
|
+
- email: valencia
|
35
|
+
name: Valencia
|
36
|
+
username: example-vale
|
30
37
|
|
31
38
|
# Label mapping from Trac ticket to GitHub label
|
32
39
|
labels:
|
@@ -47,14 +54,38 @@ labels:
|
|
47
54
|
|
48
55
|
# less useful, but also possible:
|
49
56
|
priority:
|
50
|
-
Low:
|
51
|
-
|
57
|
+
Low:
|
58
|
+
name: low
|
59
|
+
color: 22dd00
|
60
|
+
High:
|
61
|
+
name: high
|
62
|
+
color: ff0000
|
52
63
|
severity:
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
64
|
+
trivial:
|
65
|
+
name: trivial
|
66
|
+
color: ff0000
|
67
|
+
major:
|
68
|
+
name: major
|
69
|
+
color: b44647
|
70
|
+
minor:
|
71
|
+
name: minor
|
72
|
+
color: f7347a
|
73
|
+
medium:
|
74
|
+
name: medium
|
75
|
+
color: f3c77c
|
76
|
+
tracstate:
|
77
|
+
accepted:
|
78
|
+
name: accepted
|
79
|
+
color: 22dd00
|
80
|
+
assigned:
|
81
|
+
name: assigned
|
82
|
+
color: aadd88
|
83
|
+
closed:
|
84
|
+
name: closed
|
85
|
+
color: ee00aa
|
86
|
+
new:
|
87
|
+
name: new
|
88
|
+
color:
|
58
89
|
version:
|
59
90
|
'1.3': v1.3
|
60
91
|
'1.4': v1.4
|
data/exe/tractive
CHANGED
@@ -5,6 +5,8 @@ require_relative "../lib/tractive"
|
|
5
5
|
|
6
6
|
class TractiveCommand < Thor
|
7
7
|
default_command :migrate
|
8
|
+
class_option "logfile", type: :string, aliases: ["-L", "--log-file"],
|
9
|
+
desc: "Name of the logfile to output logs to."
|
8
10
|
|
9
11
|
desc "<OPTIONS>", "Migrate Trac instances to modern Git management platforms like GitHub and GitLab"
|
10
12
|
method_option "attachmentexporter", type: :string, aliases: ["-A", "--attachment-exporter"],
|
@@ -33,8 +35,6 @@ class TractiveCommand < Thor
|
|
33
35
|
desc: "Import issues from a json file"
|
34
36
|
method_option "info", type: :boolean, aliases: ["-i", "--info"],
|
35
37
|
desc: "Reports existing labels and users in the database"
|
36
|
-
method_option "logfile", type: :string, aliases: ["-L", "--log-file"],
|
37
|
-
desc: "Name of the logfile to output logs to."
|
38
38
|
method_option "mockdeleted", type: :boolean, aliases: ["-M", "--mockup"],
|
39
39
|
desc: "Import from 0 and mocking tickets deleted on trac"
|
40
40
|
method_option "openedonly", type: :boolean, aliases: ["-o", "--opened-only"],
|
@@ -64,6 +64,7 @@ class TractiveCommand < Thor
|
|
64
64
|
def generate_revmap
|
65
65
|
verify_revmap_generator_options!(options)
|
66
66
|
|
67
|
+
Tractive::Utilities.setup_logger(output_stream: options[:log_file] || $stderr, verbose: options[:verbose])
|
67
68
|
Tractive::RevmapGenerator.new(
|
68
69
|
options["revtimestampfile"],
|
69
70
|
options["svnurl"],
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GithubApi
|
4
|
+
class Client
|
5
|
+
module Labels
|
6
|
+
def list_labels(repo, params = {})
|
7
|
+
JSON.parse(
|
8
|
+
RestClient.get(
|
9
|
+
"https://api.github.com/repos/#{repo}/labels",
|
10
|
+
{
|
11
|
+
"Authorization" => "token #{@token}",
|
12
|
+
params: params
|
13
|
+
}
|
14
|
+
)
|
15
|
+
)
|
16
|
+
end
|
17
|
+
alias labels list_labels
|
18
|
+
|
19
|
+
def create_label(repo, params)
|
20
|
+
JSON.parse(
|
21
|
+
RestClient.post(
|
22
|
+
"https://api.github.com/repos/#{repo}/labels",
|
23
|
+
params.to_json,
|
24
|
+
{
|
25
|
+
"Authorization" => "token #{@token}",
|
26
|
+
"Accept" => "application/vnd.github.v3+json"
|
27
|
+
}
|
28
|
+
)
|
29
|
+
)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "client/issues"
|
4
|
+
require_relative "client/labels"
|
4
5
|
require_relative "client/milestones"
|
5
6
|
|
6
7
|
# Service to perform github actions
|
7
8
|
module GithubApi
|
8
9
|
class Client
|
9
10
|
include GithubApi::Client::Issues
|
11
|
+
include GithubApi::Client::Labels
|
10
12
|
include GithubApi::Client::Milestones
|
11
13
|
|
12
14
|
def initialize(options = {})
|
data/lib/tractive/info.rb
CHANGED
@@ -30,15 +30,15 @@ module Tractive
|
|
30
30
|
tracstates = Ticket.distinct.select(:status).select_map(:status).compact
|
31
31
|
|
32
32
|
{
|
33
|
-
"users" => Utilities.
|
33
|
+
"users" => Utilities.make_each_hash(users, %w[email name username]),
|
34
34
|
"milestones" => milestones,
|
35
35
|
"labels" => {
|
36
36
|
"type" => Utilities.make_hash("type_", types),
|
37
37
|
"component" => Utilities.make_hash("component_", components),
|
38
38
|
"resolution" => Utilities.make_hash("resolution_", resolutions),
|
39
|
-
"severity" => Utilities.
|
40
|
-
"priority" => Utilities.
|
41
|
-
"tracstate" => Utilities.
|
39
|
+
"severity" => Utilities.make_each_hash(severity, %w[name color]),
|
40
|
+
"priority" => Utilities.make_each_hash(priorities, %w[name color]),
|
41
|
+
"tracstate" => Utilities.make_each_hash(tracstates, %w[name color])
|
42
42
|
}
|
43
43
|
}
|
44
44
|
end
|
@@ -17,6 +17,9 @@ module Migrator
|
|
17
17
|
@wiki_attachments_url = args[:cfg]["trac"]["wiki_attachments_url"]
|
18
18
|
|
19
19
|
load_milestone_map
|
20
|
+
create_labels_on_github(@labels_cfg["severity"].values)
|
21
|
+
create_labels_on_github(@labels_cfg["priority"].values)
|
22
|
+
create_labels_on_github(@labels_cfg["tracstate"].values)
|
20
23
|
|
21
24
|
@uri_parser = URI::Parser.new
|
22
25
|
@twf_to_markdown = Migrator::Converter::TwfToMarkdown.new(@tracticketbaseurl, @attachurl, @changeset_base_url, @wiki_attachments_url)
|
@@ -116,7 +119,8 @@ module Migrator
|
|
116
119
|
# compose body
|
117
120
|
body = [badgetable, body, footer].join("\n\n___\n")
|
118
121
|
|
119
|
-
labels.add("owner:#{github_assignee}")
|
122
|
+
labels.add("name" => "owner:#{github_assignee}") unless github_assignee.nil? || github_assignee.empty?
|
123
|
+
labels = labels.map { |label| label["name"] }
|
120
124
|
|
121
125
|
issue = {
|
122
126
|
"title" => ticket[:summary],
|
@@ -129,7 +133,7 @@ module Migrator
|
|
129
133
|
|
130
134
|
if @users.key?(ticket[:owner])
|
131
135
|
owner = trac_mail(ticket[:owner])
|
132
|
-
github_owner = @users[owner]
|
136
|
+
github_owner = @users[owner]["username"]
|
133
137
|
$logger.debug("..owner in trac: #{owner}")
|
134
138
|
$logger.debug("..assignee in GitHub: #{github_owner}")
|
135
139
|
issue["assignee"] = github_owner
|
@@ -155,11 +159,11 @@ module Migrator
|
|
155
159
|
private
|
156
160
|
|
157
161
|
def map_user(user)
|
158
|
-
@users[
|
162
|
+
@users.fetch(user, {})["email"] || user
|
159
163
|
end
|
160
164
|
|
161
165
|
def map_assignee(user)
|
162
|
-
@users[
|
166
|
+
@users.fetch(user, {})["email"]
|
163
167
|
end
|
164
168
|
|
165
169
|
def load_milestone_map
|
@@ -168,9 +172,9 @@ module Migrator
|
|
168
172
|
newmilestonekeys = @milestonesfromtrac.keys - @milestonemap.keys
|
169
173
|
|
170
174
|
newmilestonekeys.each do |milestonelabel|
|
171
|
-
milestone
|
175
|
+
milestone = {
|
172
176
|
"title" => milestonelabel.to_s,
|
173
|
-
"state" => @milestonesfromtrac[milestonelabel][:completed].
|
177
|
+
"state" => @milestonesfromtrac[milestonelabel][:completed].to_i.zero? ? "open" : "closed",
|
174
178
|
"description" => @milestonesfromtrac[milestonelabel][:description] || "no description in trac",
|
175
179
|
"due_on" => "2012-10-09T23:39:01Z"
|
176
180
|
}
|
@@ -194,6 +198,21 @@ module Migrator
|
|
194
198
|
nil
|
195
199
|
end
|
196
200
|
|
201
|
+
def create_labels_on_github(labels)
|
202
|
+
return if labels.nil? || labels.empty?
|
203
|
+
|
204
|
+
existing_labels = @client.labels(@repo, per_page: 100).map { |label| label["name"] }
|
205
|
+
new_labels = labels.reject { |label| existing_labels.include?(label["name"]) }
|
206
|
+
|
207
|
+
new_labels.each do |label|
|
208
|
+
params = { name: label["name"] }
|
209
|
+
params["color"] = label["color"] unless label["color"].nil?
|
210
|
+
|
211
|
+
@client.create_label(@repo, params)
|
212
|
+
$logger.info("Created label: #{label["name"]}")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
197
216
|
def ticket_change(append, meta)
|
198
217
|
# kind
|
199
218
|
kind = if meta[:ticket]
|
@@ -58,7 +58,7 @@ module Migrator
|
|
58
58
|
@dry_run = args[:opts][:dryrun]
|
59
59
|
@output_file = File.new(dry_run_output_file, "w+")
|
60
60
|
@delimiter = "{"
|
61
|
-
@revmap = load_revmap_file(args[:opts][:revmapfile] || args[:cfg]["
|
61
|
+
@revmap = load_revmap_file(args[:opts][:revmapfile] || args[:cfg]["revmap_path"])
|
62
62
|
@safetychecks = safetychecks
|
63
63
|
@start_ticket = (start_ticket || (@last_created_issue + 1)).to_i
|
64
64
|
@filter_closed = filter_closed
|
@@ -19,8 +19,11 @@ module Tractive
|
|
19
19
|
def filter_column(options)
|
20
20
|
return self if options.nil? || options.values.compact.empty?
|
21
21
|
|
22
|
-
|
22
|
+
case options[:operator].downcase
|
23
|
+
when "like"
|
23
24
|
where { Sequel.like(options[:column_name].to_sym, options[:column_value]) }
|
25
|
+
when "not like"
|
26
|
+
where { ~Sequel.like(options[:column_name].to_sym, options[:column_value]) }
|
24
27
|
else
|
25
28
|
where { Sequel.lit("#{options[:column_name]} #{options[:operator]} '#{options[:column_value]}'") }
|
26
29
|
end
|
@@ -11,6 +11,7 @@ module Tractive
|
|
11
11
|
@duplicate_message_commits = {}
|
12
12
|
@last_revision = nil
|
13
13
|
@pinwheel = %w[| / - \\]
|
14
|
+
@skipped = []
|
14
15
|
@output_file = output_file
|
15
16
|
end
|
16
17
|
|
@@ -20,6 +21,7 @@ module Tractive
|
|
20
21
|
|
21
22
|
File.open(@output_file, "w+") do |file|
|
22
23
|
File.foreach(@input_file) do |line|
|
24
|
+
i += 1
|
23
25
|
info = extract_info_from_line(line)
|
24
26
|
next if @last_revision == info[:revision]
|
25
27
|
|
@@ -29,9 +31,10 @@ module Tractive
|
|
29
31
|
percent = ((i.to_f / line_count) * 100).round(2)
|
30
32
|
progress = "=" * (percent.to_i / 2) unless i < 2
|
31
33
|
printf("\rProgress: [%<progress>-50s] %<percent>.2f%% %<spinner>s", progress: progress, percent: percent, spinner: @pinwheel.rotate!.first)
|
32
|
-
i += 1
|
33
34
|
end
|
34
35
|
end
|
36
|
+
|
37
|
+
$logger.info "\n\nFollowing revisions are skipped because they don't have a corresponding git commit. #{@skipped}"
|
35
38
|
end
|
36
39
|
|
37
40
|
private
|
@@ -52,11 +55,13 @@ module Tractive
|
|
52
55
|
# get sha from git api
|
53
56
|
commits = git_commits(info)
|
54
57
|
|
55
|
-
if commits.
|
56
|
-
|
58
|
+
if commits.empty?
|
59
|
+
@skipped << info[:revision]
|
60
|
+
elsif commits.count == 1
|
61
|
+
file.puts "#{info[:revision]} | #{commits.values[0]&.join(",")}"
|
57
62
|
else
|
58
63
|
message = commit_message_from_svn(info[:revision])
|
59
|
-
file.puts "#{info[:revision]} | #{@duplicate_commits[info[:timestamp]][message]
|
64
|
+
file.puts "#{info[:revision]} | #{@duplicate_commits[info[:timestamp]][message]&.join(",")}"
|
60
65
|
end
|
61
66
|
end
|
62
67
|
|
@@ -91,16 +96,24 @@ module Tractive
|
|
91
96
|
end
|
92
97
|
|
93
98
|
def commits_from_git_repo(info)
|
94
|
-
|
99
|
+
shas_command = "git rev-list --after=#{info[:timestamp]} --until=#{info[:timestamp]} --committer=#{info[:author]} --all"
|
100
|
+
shas = Dir.chdir(@git_local_repo_path) do
|
101
|
+
`#{shas_command}`
|
102
|
+
end
|
103
|
+
|
104
|
+
commits_command = "git rev-list --after=#{info[:timestamp]} --until=#{info[:timestamp]} --committer=#{info[:author]} --all --format='medium'"
|
95
105
|
commits = Dir.chdir(@git_local_repo_path) do
|
96
|
-
`#{
|
106
|
+
`#{commits_command}`
|
97
107
|
end
|
98
108
|
|
109
|
+
regex = /#{shas.split("\n").map { |sha| "(?=commit #{sha})" }.join "|"}/
|
110
|
+
|
99
111
|
commits_arr = []
|
100
|
-
commits.split(
|
112
|
+
commits.split(regex).each do |commit_info|
|
101
113
|
commit_hash = {}
|
102
|
-
|
103
|
-
commit_hash[:
|
114
|
+
info = commit_info.split("\n", 4)
|
115
|
+
commit_hash[:sha] = info[0].split.last
|
116
|
+
commit_hash[:message] = info.last.strip.gsub("\n", "").gsub(/\s+/, " ")
|
104
117
|
|
105
118
|
commits_arr << commit_hash
|
106
119
|
end
|
data/lib/tractive/utilities.rb
CHANGED
@@ -7,6 +7,13 @@ module Tractive
|
|
7
7
|
array.map { |i| [i, "#{prefix}#{i}"] }.to_h
|
8
8
|
end
|
9
9
|
|
10
|
+
def make_each_hash(values, keys)
|
11
|
+
values.map do |value|
|
12
|
+
value = [value] unless value.is_a?(Array)
|
13
|
+
[value[0], keys.zip(value).to_h]
|
14
|
+
end.to_h
|
15
|
+
end
|
16
|
+
|
10
17
|
def setup_db!(db_url)
|
11
18
|
files_to_load = [
|
12
19
|
"lib/tractive/models/attachment.rb",
|
data/lib/tractive/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tractive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mysql2
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- lib/tractive/github_api.rb
|
141
141
|
- lib/tractive/github_api/client.rb
|
142
142
|
- lib/tractive/github_api/client/issues.rb
|
143
|
+
- lib/tractive/github_api/client/labels.rb
|
143
144
|
- lib/tractive/github_api/client/milestones.rb
|
144
145
|
- lib/tractive/graceful_quit.rb
|
145
146
|
- lib/tractive/info.rb
|