zz-export-pull-requests 0.3.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.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/Changes +58 -0
  3. data/README.md +98 -0
  4. data/bin/epr +385 -0
  5. metadata +106 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4fac5c505982f4e25b9dd2ac9cbeac689c0ba84cc1e0f90e3980f8dc8641a922
4
+ data.tar.gz: 53cde9d89cf8026a46ddd8c8de6c72d583cc00a445aef2f02a5e0f0ee6ae3e7e
5
+ SHA512:
6
+ metadata.gz: f8b2fd94abe182a4151c077cc8717f9feaca7f848c82bc8ce306d7d9557ee5ea0af2b6d07f7bb9c8fe1d6df200c73ae7c4581e48758a67ab235a6e73e2ff79b7
7
+ data.tar.gz: cbb6dd165e062e1367a2d53a801c9ada34ba6811bd289c9d14f1003aca25e6804bc27bbba9f82ca43195cdb221d427961b4ab86d67e4f1e021519ab47eb02dfd
data/Changes ADDED
@@ -0,0 +1,58 @@
1
+ v0.3.3 2019-05-01
2
+ --------------------
3
+ Bug Fixes:
4
+ * GitHub PR only exports were output as an "issue" instead of "PR"
5
+
6
+ v0.3.2 2019-02-09
7
+ --------------------
8
+ Bug Fixes:
9
+ * Don't supply assignee or milestone for GitHub if nil
10
+
11
+ --------------------
12
+ v0.3.1 2019-01-28
13
+ --------------------
14
+ Enhancements:
15
+ * Add support for filtering on milestones and labels to GitLab
16
+
17
+ --------------------
18
+ v0.3.0 2019-01-10
19
+ --------------------
20
+ Enhancements:
21
+ * Add support for filtering on milestones and labels (GitHub only)
22
+ * Add support for filtering on assignees (GitHub only, thanks Caroline Boyden)
23
+
24
+ --------------------
25
+ v0.2.2 2018-11-30
26
+ --------------------
27
+ Enhancements:
28
+ * Add support for exporting issue body (GitHub only)
29
+
30
+ --------------------
31
+ v0.2.1 2018-06-05
32
+ --------------------
33
+ Enhancements:
34
+ * Add support for custom endpoints
35
+
36
+ --------------------
37
+ v0.2.0 2017-09-21
38
+ --------------------
39
+ Enhancements:
40
+ * Add support for issues
41
+
42
+ Changes:
43
+ * Always show Repository column (was excluded if only 1 repo was given)
44
+
45
+ --------------------
46
+ v0.1.1 2017-07-23
47
+ --------------------
48
+ Enhancements:
49
+ * Add support for Bitbucket
50
+
51
+ --------------------
52
+ v0.1.0 2017-07-23
53
+ --------------------
54
+ Enhancements:
55
+ * Add support for GitLab
56
+
57
+ Changes:
58
+ * Do not require a token
data/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # Export Pull Requests
2
+
3
+ Export pull requests/merge requests and/or issues to a CSV file.
4
+
5
+ Supports GitHub, GitLab, and Bitbucket.
6
+
7
+ ## Installation
8
+
9
+ [Ruby](https://www.ruby-lang.org/en/documentation/installation/) is required.
10
+
11
+ With Ruby installed run:
12
+
13
+ gem install zz-export-pull-requests
14
+
15
+ This installs the `epr` executable.
16
+
17
+ ## Usage
18
+
19
+ usage: epr [options] user/repo1 [user/repo2...]
20
+ -b, --body Include the issue/pr body description in the output (GitHub only)
21
+ -c, --creator=USER1,USER2,... Export PRs created by given username(s); prepend `!' to exclude user
22
+ -e, --endpoint=URL Endpoint URL for 'enterprise', etc... repositories
23
+ -m, --milestone=WHAT Export items assigned to the given milestone (GitHub/GitLab only)
24
+ -a, --assignee=USER Export items assigned to the given user (GitHub/GitLab only)
25
+ -l, --labels=LABEL(S) Export items with the given label(s) (GitHub/GitLab only)
26
+ -h, --help Show this message
27
+ -p, --provider=NAME Service provider: bitbucket, github, or gitlab; defaults to github
28
+ -s, --state=STATE Export items in the given state, defaults to open
29
+ -t, --token=TOKEN API token
30
+ -x, --export=WHAT What to export: pr, pr_comments (BitBucket only), issues, or all; defaults to all
31
+ -v, --version epr version
32
+
33
+ ### Config
34
+
35
+ These can all be set by one of the below methods or [via the command line](#usage).
36
+
37
+ #### Token
38
+
39
+ The API token can be set by:
40
+
41
+ - `EPR_TOKEN` environment variable
42
+ - `epr.token` setting in `.gitconfig` (add via `git config --add epr.token <your API token>`)
43
+ - `github.oauth-token` setting in `.gitconfig`
44
+
45
+ #### Default Service
46
+
47
+ github is the default. You can set a new default via `EPR_SERVICE`.
48
+
49
+ ### Examples
50
+
51
+ Export open PRs and issues in `sshaw/git-link` and `sshaw/itunes_store_transporter`:
52
+
53
+ epr sshaw/git-link sshaw/itunes_store_transporter > pr.csv
54
+
55
+ Export open pull request not created by `sshaw` in `padrino/padrino-framework`:
56
+
57
+ epr -x pr -c '!sshaw' padrino/padrino-framework > pr.csv
58
+
59
+ Export open merge requests from a GitLab project:
60
+
61
+ epr -x pr -p gitlab gitlab-org/gitlab-ce > pr.csv
62
+
63
+ Export all issues from a GitLab project:
64
+
65
+ epr -x issues -p gitlab gitlab-org/gitlab-ce > pr.csv
66
+
67
+ ## Service Notes
68
+
69
+ To connect to a custom/"Enterprise" installation of any of the supported services use the endpoint option (`-e`)
70
+
71
+ ### Bitbucket
72
+
73
+ You can use [app passwords](https://confluence.atlassian.com/bitbucket/app-passwords-828781300.html) for the API token.
74
+ Just provide your token info in `bitbucket_username:app_password` format:
75
+
76
+ epr -p bitbucket -t bitbucket_username:app_password user/repo1
77
+
78
+ ### GitLab
79
+
80
+ Authentication can be done via a [personal access token](https://gitlab.com/profile/personal_access_tokens).
81
+
82
+ Enterprise editions of GitLab have an [issue export feature](https://docs.gitlab.com/ee/user/project/issues/csv_export.html).
83
+
84
+ ## See Also
85
+
86
+ - [Batch Labels](https://github.com/sshaw/batchlabels) - Add/remove labels in batches to/from GitHub issues and pull requests.
87
+
88
+ ## Author
89
+
90
+ Skye Shaw [skye.shaw AT gmail]
91
+
92
+ ## License
93
+
94
+ Released under the MIT License: www.opensource.org/licenses/MIT
95
+
96
+ ---
97
+
98
+ Made by [ScreenStaring](http://screenstaring.com)
data/bin/epr ADDED
@@ -0,0 +1,385 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "csv"
4
+ require "optparse"
5
+ require "time"
6
+ require "logger"
7
+
8
+ require "github_api"
9
+ require "gitlab"
10
+ require "bitbucket_rest_api"
11
+
12
+ VERSION = "0.3.5"
13
+ SERVICES = %w[github gitlab bitbucket]
14
+ GIT_CONFIGS = %w[epr.token github.oauth-token]
15
+
16
+ TYPE_ISSUE = "Issue"
17
+ TYPE_PR = "PR"
18
+ TYPE_PR_COMMENT = "PR Comment"
19
+
20
+ EXPORT_ISSUES = "issues"
21
+ EXPORT_PRS = "pr"
22
+ EXPORT_PR_COMMENTS = "pr_comments"
23
+
24
+ DEFAULT_BODY_LENGTH = 2 ** 32 - 1
25
+
26
+ def localtime(t)
27
+ # MM/DD/YY HH:MM:SS
28
+ # Time.parse(t).localtime.strftime("%x %X")
29
+
30
+ # Epoch
31
+ Time.parse(t).localtime.to_i
32
+ end
33
+
34
+ def parse_repos(repos)
35
+ repos.map do |r|
36
+ abort "invalid repository #{r}" unless r =~ %r{\A(\S+)/(\S+)\z}
37
+ [ $1, $2 ]
38
+ end
39
+ end
40
+
41
+ def skip_user?(user)
42
+ $exclude_users.include?(user) || $include_users.any? && !$include_users.include?(user)
43
+ end
44
+
45
+ def lookup_token
46
+ return ENV["EPR_TOKEN"] unless ENV["EPR_TOKEN"].to_s.strip.empty?
47
+
48
+ begin
49
+ GIT_CONFIGS.each do |setting|
50
+ token = `git config #{setting}`.chomp
51
+ return token unless token.empty?
52
+ end
53
+ rescue Errno::ENOENT
54
+ # git not found, ignore
55
+ end
56
+ end
57
+
58
+ def bitbucket(user, repo)
59
+ # TODO: make sure no need to translate any states
60
+ # https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Busername%7D/%7Brepo_slug%7D/pullrequests
61
+
62
+ options = { :basic_auth => $token }
63
+ options[:endpoint] = $endpoint if $endpoint
64
+
65
+ $bitbucket ||= BitBucket.new(options)
66
+
67
+ rows = []
68
+ no_user = "Anonymous"
69
+ repo_name = "#{repo}"
70
+
71
+ pull_requests = lambda do
72
+ page = 0
73
+
74
+ loop do
75
+ page += 1
76
+
77
+ prs = $bitbucket.repos.pull_request.all(user, repo, :page => page, :state => $filter.upcase)
78
+ prs["values"].each do |pr|
79
+ next if pr.author && skip_user?(pr.author.display_name)
80
+
81
+ rows << [
82
+ repo_name,
83
+ TYPE_PR,
84
+ pr.id,
85
+ pr.author ? pr.author.display_name : no_user,
86
+ pr.title,
87
+ pr.state,
88
+ localtime(pr.created_on),
89
+ localtime(pr.updated_on),
90
+ pr["links"].html.href,
91
+ pr.summary.raw,
92
+ pr.summary.html,
93
+ !pr.source.commit.nil? ? pr.source.commit["hash"] : "",
94
+ !pr.destination.commit.nil? ? pr.destination.commit["hash"] : "",
95
+ !pr.source.branch.nil? ? pr.source.branch.name : "",
96
+ !pr.destination.branch.nil? ? pr.destination.branch.name : "",
97
+ !pr.reason.nil? ? pr.reason : "",
98
+ !pr.merge_commit.nil? ? pr.merge_commit["hash"] : ""
99
+ ]
100
+ end
101
+
102
+ break unless prs["next"]
103
+ end
104
+ end
105
+
106
+ pull_request_comments = lambda do
107
+ pr_page = 0
108
+
109
+ loop do
110
+ pr_page += 1
111
+ prs = $bitbucket.repos.pull_request.all(user, repo, :page => pr_page, :state => $filter.upcase)
112
+
113
+ prs["values"].each do |pr|
114
+ comment_page = 0
115
+ loop do
116
+ comment_page += 1
117
+ comments = $bitbucket.repos.pull_request.comments(user, repo, pr.id, :page => comment_page)
118
+ comments["values"].each do |comment|
119
+ rows << [
120
+ repo_name,
121
+ TYPE_PR_COMMENT,
122
+ comment.pullrequest.id,
123
+ comment.user.display_name,
124
+ comment.inline? ? "inline" : "normal",
125
+ comment.content.raw,
126
+ comment.content.html,
127
+ localtime(comment.updated_on),
128
+ comment.deleted,
129
+ comment.inline? ? comment.inline.to : "",
130
+ comment.inline? ? comment.inline.from : "",
131
+ comment.inline? ? comment.inline.path : "",
132
+ comment["links"].code? ? comment["links"].code.href : ""
133
+ ]
134
+ end
135
+ break unless comments["next"]
136
+ end
137
+ end
138
+
139
+ break unless prs["next"]
140
+ end
141
+ end
142
+
143
+ issues = lambda do
144
+ start = 0
145
+
146
+ loop do
147
+ issues = $bitbucket.issues.list_repo(user, repo, :start => start, :status => $filter)
148
+ break unless issues.any?
149
+
150
+ issues.each do |issue|
151
+ next if issue["reported_by"] && skip_user?(issue["reported_by"]["username"])
152
+
153
+ rows << [
154
+ repo_name,
155
+ TYPE_ISSUE,
156
+ issue["local_id"],
157
+ issue["reported_by"] ? issue["reported_by"]["username"] : no_user,
158
+ issue["title"],
159
+ issue["status"],
160
+ localtime(issue["utc_created_on"]),
161
+ localtime(issue["utc_last_updated"]),
162
+ # Not in response
163
+ sprintf("https://bitbucket.org/%s/issues/%s", repo_name, issue["local_id"])
164
+ ]
165
+ end
166
+
167
+ start += issues.size
168
+ end
169
+ end
170
+
171
+ case $export
172
+ when EXPORT_PRS
173
+ pull_requests[]
174
+ when EXPORT_PR_COMMENTS
175
+ pull_request_comments[]
176
+ when EXPORT_ISSUES
177
+ issues[]
178
+ else
179
+ pull_requests[]
180
+ issues[]
181
+ end
182
+
183
+ rows
184
+ end
185
+
186
+ def github(user, repo)
187
+ rows = []
188
+ method = $export == EXPORT_PRS ? :pull_requests : :issues
189
+
190
+ options = { :oauth_token => $token, :auto_pagination => true }
191
+ options[:endpoint] = $endpoint if $endpoint
192
+
193
+ $gh ||= Github.new(options)
194
+
195
+ options = { :user => user, :repo => repo, :state => $filter, :labels => $labels }
196
+ options[:milestone] = $milestone if $milestone
197
+ options[:assignee] = $assignee if $assignee
198
+
199
+ $gh.public_send(method).list(options).each_page do |page|
200
+
201
+ next if page.size.zero? # Needed for auto_pagination
202
+
203
+ page.each do |item|
204
+ # issues method will return issues and PRs
205
+ next if $export == EXPORT_ISSUES && item.pull_request
206
+ next if skip_user?(item.user.login)
207
+
208
+ rows << [
209
+ "#{user}/#{repo}",
210
+ # If we're only retrieving PRs then item.pull_request will be nil
211
+ # It's only populated when retrieving both (issues method).
212
+ item.pull_request || method == :pull_requests ? TYPE_PR : TYPE_ISSUE,
213
+ item.number,
214
+ item.user.login,
215
+ item.title,
216
+ item.state,
217
+ localtime(item.created_at),
218
+ localtime(item.updated_at),
219
+ item.html_url,
220
+ ]
221
+
222
+ if $body
223
+ body = item.body
224
+ # -3 for "..."
225
+ body = body.slice(0, DEFAULT_BODY_LENGTH - 3) << "..." if body.size > DEFAULT_BODY_LENGTH unless body == nil
226
+ rows[-1].insert(4, body)
227
+ end
228
+ end
229
+ end
230
+
231
+ rows
232
+ end
233
+
234
+ def gitlab(user, repo)
235
+ rows = []
236
+
237
+ case $export
238
+ when EXPORT_PRS
239
+ methods = [:merge_requests]
240
+ when EXPORT_ISSUES
241
+ methods = [:issues]
242
+ else
243
+ methods = [:merge_requests, :issues]
244
+ end
245
+
246
+ # Do we care about this differing in output?
247
+ state = $filter == "open" ? "opened" : $filter
248
+ options = {
249
+ :milestone => $milestone,
250
+ :labels => $labels,
251
+ :state => state
252
+ }
253
+
254
+ # If assignee_id is nil an error is raised
255
+ options[:assignee_id] = $assignee if $assignee
256
+
257
+ $gitlab ||= Gitlab.client(:auth_token => $token, :endpoint => $endpoint || "https://gitlab.com/api/v4")
258
+ methods.each do |method|
259
+ $gitlab.public_send(method, "#{user}/#{repo}", options).auto_paginate do |item|
260
+ next if skip_user?(item.author.username)
261
+
262
+ rows << [
263
+ "#{user}/#{repo}",
264
+ method == :issues ? TYPE_ISSUE : TYPE_PR,
265
+ # Yes, it's called iid
266
+ item.iid,
267
+ item.author.username,
268
+ item.title,
269
+ item.state,
270
+ localtime(item.created_at),
271
+ localtime(item.updated_at),
272
+ item.web_url
273
+ ]
274
+ end
275
+ end
276
+
277
+ rows
278
+ end
279
+
280
+ def export_repos(argv)
281
+ rows = []
282
+
283
+ if $export == EXPORT_PR_COMMENTS
284
+ rows << %w[Repository Type PRNumber User CommentType BodyRaw BodyHTML CreatedAt IsDeleted ToLine FromLine FilePath Diff]
285
+ else
286
+ rows << %w[Repository Type # User Title State CreatedAt UpdatedAt URL BodyRaw BodyHTML SourceCommit DestinationCommit SourceBranch DestinationBranch DeclineReason MergeCommit]
287
+ end
288
+
289
+ rows[-1].insert(4, "Body") if $body
290
+ repos = parse_repos(argv)
291
+
292
+ repos.each do |user, repo|
293
+ case $provider
294
+ when "github"
295
+ rows.concat(github(user, repo))
296
+ when "gitlab"
297
+ rows.concat(gitlab(user, repo))
298
+ when "bitbucket"
299
+ rows.concat(bitbucket(user, repo))
300
+ else
301
+ abort "unknown service provider: #$provider"
302
+ end
303
+
304
+ rows.each { |r| puts r.to_csv }
305
+ rows.clear
306
+ end
307
+ end
308
+
309
+ # Hashie is used by Bitbucket, and it spews warnings to stdout. We stop that,
310
+ # specifically: https://github.com/bitbucket-rest-api/bitbucket/issues/87
311
+ Hashie.logger = Logger.new(File::NULL) if defined?(Hashie)
312
+
313
+ $exclude_users = []
314
+ $include_users = []
315
+ $export = "all"
316
+ $endpoint = nil
317
+ $milestone = $labels = $assignee = nil
318
+ $filter = "open"
319
+ $provider = ENV["EPR_SERVICE"] || SERVICES[0]
320
+ $token = lookup_token
321
+ $body = false
322
+
323
+ parser = OptionParser.new do |opts|
324
+ opts.banner = "usage: #{File.basename($0)} [options] user/repo1 [user/repo2...]"
325
+
326
+ opts.on "-b", "--body", "Include the issue/pr body description in the output (GitHub only)" do
327
+ $body = true
328
+ end
329
+
330
+ opts.on "-c", "--creator=USER1,USER2,...", Array, "Export PRs created by given username(s); prepend `!' to exclude user" do |u|
331
+ $exclude_users, $include_users = u.partition { |name| name.start_with?("!") }
332
+ $exclude_users.map! { |name| name[1..-1] } # remove "!"
333
+ end
334
+
335
+ opts.on "-e", "--endpoint=URL", "Endpoint URL for 'enterprise', etc... repositories" do |url|
336
+ $endpoint = url
337
+ end
338
+
339
+ opts.on "-m", "--milestone=WHAT", "Export items assigned to the given milestone (GitHub/GitLab only)" do |m|
340
+ $milestone = m
341
+ end
342
+
343
+ opts.on "-a", "--assignee=USER", "Export items assigned to the given user (GitHub/GitLab only)" do |a|
344
+ $assignee = a
345
+ end
346
+
347
+ opts.on "-l", "--labels=LABEL(S)", "Export items with the given label(s) (GitHub/GitLab only)" do |l|
348
+ $labels = l
349
+ end
350
+
351
+ opts.on "-h", "--help", "Show this message" do
352
+ puts opts
353
+ exit
354
+ end
355
+
356
+ opts.on "-p, --provider=NAME", SERVICES, "Service provider: bitbucket, github, or gitlab; defaults to github" do |name|
357
+ $provider = name
358
+ end
359
+
360
+ opts.on "-s", "--state=STATE", "Export items in the given state, defaults to open" do |f|
361
+ $filter = f
362
+ end
363
+
364
+ opts.on "-t", "--token=TOKEN", "API token" do |t|
365
+ $token = t
366
+ end
367
+
368
+ opts.on "-x", "--export=WHAT", %w[pr pr_comments issues all], "What to export: pr, pr_comments, issues, or all; defaults to all" do |x|
369
+ $export = x
370
+ end
371
+
372
+ opts.on "-v", "--version", "epr version" do
373
+ puts "v#{VERSION} (GitHub v#{Github::VERSION}, GitLab v#{Gitlab::VERSION}, Bitbucket v#{BitBucket::VERSION::STRING})"
374
+ exit
375
+ end
376
+ end
377
+
378
+ parser.parse!
379
+ abort parser.banner if ARGV.empty?
380
+
381
+ begin
382
+ export_repos(ARGV)
383
+ rescue => e
384
+ abort "Export failed: #{e}"
385
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zz-export-pull-requests
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.5
5
+ platform: ruby
6
+ authors:
7
+ - Zulhilmi Zainudin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-12-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: github_api
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.16'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gitlab
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: zz_bitbucket_rest_api
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.8
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.8
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.9'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.9'
69
+ description: Program to export GitHub, GitLab, or Bitbucket pull requests/merge requests
70
+ and issues to CSV a file. This is forked version of https://github.com/sshaw/export-pull-requests
71
+ project.
72
+ email: zulhfreelancer@gmail.com
73
+ executables:
74
+ - epr
75
+ extensions: []
76
+ extra_rdoc_files:
77
+ - README.md
78
+ - Changes
79
+ files:
80
+ - Changes
81
+ - README.md
82
+ - bin/epr
83
+ homepage: https://github.com/zulhfreelancer/export-pull-requests
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message: Use the `epr' command to export your pull requests.
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubygems_version: 3.0.3
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: Export pull requests and issues to a CSV file.
106
+ test_files: []