github_issue_exporter 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.
- checksums.yaml +4 -4
- data/README.md +10 -0
- data/bin/bundle +105 -0
- data/bin/export-github-issues +12 -5
- data/bin/htmldiff +21 -0
- data/bin/ldiff +21 -0
- data/bin/rake +21 -0
- data/bin/rspec +21 -0
- data/bin/safe_yaml +21 -0
- data/github_issue_exporter.gemspec +3 -2
- data/lib/issue_exporter/export.rb +14 -3
- data/lib/issue_exporter/github.rb +1 -3
- data/lib/issue_exporter/outputter.rb +41 -10
- data/lib/issue_exporter/version.rb +1 -1
- data/lib/issue_exporter.rb +1 -0
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90da13ded1c07b94331081e6d4ec102e9e275355
|
4
|
+
data.tar.gz: 236daac34abdab9894117684c9a84f5fcd573585
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 862a0f788bdbe2226a0bc26d3e727f2ddf2c2bba2ad41f17eb6e739cdb02ae99c4e824af8b45da884398217ecca1550c899b2e4e8db082e9c004782b2f15b130
|
7
|
+
data.tar.gz: 99a81d39d3ff687721134e82d6f92d2f81c2a12b6a76d8fe7d8067a2d1b841fcb1d86bdc585d6c830d6128ee2d642bd1bf1f87551437d8d4f6a5c1b5fd871c9d
|
data/README.md
CHANGED
@@ -31,6 +31,8 @@ The Exporter has a couple of options.
|
|
31
31
|
|
32
32
|
`--output` Set the directory to store the issues in. By default it is the current directory.
|
33
33
|
|
34
|
+
`--output-type` Sets the filetype to output. Current options are `file` (the default) and `csv`. The `multiple-files` flag will only work with `file`.
|
35
|
+
|
34
36
|
`--closed` By default, only Open issues are exported. Adding this flag will include Closed ones as well.
|
35
37
|
|
36
38
|
The issues will be exported into either a single `issues.json` file or multiple `issue-[NUMBER].json` files.
|
@@ -43,6 +45,8 @@ export-github-issues tallwave github_issue_exporter [TOKEN]
|
|
43
45
|
export-github-issues --closed tallwave github_issue_exporter [TOKEN]
|
44
46
|
|
45
47
|
export-github-issues --multiple-files --output ~/issues tallwave github_issue_exporter [TOKEN]
|
48
|
+
|
49
|
+
export-github-issues --output-type csv tallwave github_issue_exporter [TOKEN]
|
46
50
|
```
|
47
51
|
|
48
52
|
### import-github-issues
|
@@ -62,6 +66,12 @@ import-github-issues --directory ~/issues tallwave github_issue_exporter [TOKEN]
|
|
62
66
|
* Issues will be added to the repository as if they were brand new, so old issue numbers will not be used.
|
63
67
|
* If your user does not have push access to the repository, assignees, milestones, and labels will not be set. Read more in the [GitHub documentation](https://developer.github.com/v3/issues/#create-an-issue).
|
64
68
|
|
69
|
+
# Development
|
70
|
+
This sees sporadic development but here's some info if you're interested:
|
71
|
+
|
72
|
+
## Testing
|
73
|
+
You'll need [bundler](http://bundler.io) installed. Run `bundle install --binstubs` to install dependencies and test binaries. You can then execute the specs with `bin/rspec` from the root folder.
|
74
|
+
|
65
75
|
## Roadmap
|
66
76
|
|
67
77
|
* Better error handling.
|
data/bin/bundle
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1 || ">= 0.a"
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../../Gemfile", __FILE__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_version
|
64
|
+
@bundler_version ||= begin
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
lockfile_version || "#{Gem::Requirement.default}.a"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def load_bundler!
|
71
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
72
|
+
|
73
|
+
# must dup string for RG < 1.8 compatibility
|
74
|
+
activate_bundler(bundler_version.dup)
|
75
|
+
end
|
76
|
+
|
77
|
+
def activate_bundler(bundler_version)
|
78
|
+
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
|
79
|
+
bundler_version = "< 2"
|
80
|
+
end
|
81
|
+
gem_error = activation_error_handling do
|
82
|
+
gem "bundler", bundler_version
|
83
|
+
end
|
84
|
+
return if gem_error.nil?
|
85
|
+
require_error = activation_error_handling do
|
86
|
+
require "bundler/version"
|
87
|
+
end
|
88
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
89
|
+
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
|
90
|
+
exit 42
|
91
|
+
end
|
92
|
+
|
93
|
+
def activation_error_handling
|
94
|
+
yield
|
95
|
+
nil
|
96
|
+
rescue StandardError, LoadError => e
|
97
|
+
e
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
m.load_bundler!
|
102
|
+
|
103
|
+
if m.invoked_as_script?
|
104
|
+
load Gem.bin_path("bundler", "bundle")
|
105
|
+
end
|
data/bin/export-github-issues
CHANGED
@@ -21,14 +21,18 @@ Usage: #{$PROGRAM_NAME} [OPTION]... [OWNER] [REPO] [TOKEN]
|
|
21
21
|
|
22
22
|
Example: #{$PROGRAM_NAME} swilliams issue_exporter abcdef
|
23
23
|
|
24
|
-
|
25
|
-
set output path
|
26
|
-
(default: current working directory)
|
24
|
+
--closed include closed issues (default: false)
|
27
25
|
|
28
26
|
--multiple-files Use a separate file for each issue
|
29
27
|
(default: one single file)
|
30
28
|
|
31
|
-
|
29
|
+
-o, --output DIRECTORY
|
30
|
+
set output path
|
31
|
+
(default: current working directory)
|
32
|
+
|
33
|
+
--output-type TYPE
|
34
|
+
sets the filetype (csv or file)
|
35
|
+
(default: file)
|
32
36
|
|
33
37
|
-h, --help display this help and exit
|
34
38
|
--version display the version
|
@@ -42,6 +46,7 @@ HERE
|
|
42
46
|
@output = nil
|
43
47
|
@multiple_files = false
|
44
48
|
@include_closed_issues = false
|
49
|
+
@output_type = 'file'
|
45
50
|
end
|
46
51
|
|
47
52
|
def correct_number_of_args(arg_count)
|
@@ -52,6 +57,7 @@ HERE
|
|
52
57
|
opts.on("-o", "--output ARG") { |arg| @output = arg }
|
53
58
|
opts.on("--multiple-files") { @multiple_files = true }
|
54
59
|
opts.on("--closed") { @include_closed_issues = true }
|
60
|
+
opts.on("--output-type ARG") { |arg| @output_type = arg }
|
55
61
|
end
|
56
62
|
|
57
63
|
def process_input(arg, index)
|
@@ -68,7 +74,8 @@ HERE
|
|
68
74
|
def perform_action
|
69
75
|
options = { path: @output,
|
70
76
|
multiple_files: @multiple_files,
|
71
|
-
include_closed_issues: @include_closed_issues
|
77
|
+
include_closed_issues: @include_closed_issues,
|
78
|
+
output_type: @output_type }
|
72
79
|
exporter = IssueExporting::Exporter.new(@owner, @repo, @token, options)
|
73
80
|
exporter.export
|
74
81
|
end
|
data/bin/htmldiff
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'htmldiff' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
12
|
+
load(bundle_binstub) if File.file?(bundle_binstub)
|
13
|
+
|
14
|
+
require "pathname"
|
15
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
16
|
+
Pathname.new(__FILE__).realpath)
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "bundler/setup"
|
20
|
+
|
21
|
+
load Gem.bin_path("diff-lcs", "htmldiff")
|
data/bin/ldiff
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'ldiff' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
12
|
+
load(bundle_binstub) if File.file?(bundle_binstub)
|
13
|
+
|
14
|
+
require "pathname"
|
15
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
16
|
+
Pathname.new(__FILE__).realpath)
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "bundler/setup"
|
20
|
+
|
21
|
+
load Gem.bin_path("diff-lcs", "ldiff")
|
data/bin/rake
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
12
|
+
load(bundle_binstub) if File.file?(bundle_binstub)
|
13
|
+
|
14
|
+
require "pathname"
|
15
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
16
|
+
Pathname.new(__FILE__).realpath)
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "bundler/setup"
|
20
|
+
|
21
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
12
|
+
load(bundle_binstub) if File.file?(bundle_binstub)
|
13
|
+
|
14
|
+
require "pathname"
|
15
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
16
|
+
Pathname.new(__FILE__).realpath)
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "bundler/setup"
|
20
|
+
|
21
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/safe_yaml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'safe_yaml' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
12
|
+
load(bundle_binstub) if File.file?(bundle_binstub)
|
13
|
+
|
14
|
+
require "pathname"
|
15
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
16
|
+
Pathname.new(__FILE__).realpath)
|
17
|
+
|
18
|
+
require "rubygems"
|
19
|
+
require "bundler/setup"
|
20
|
+
|
21
|
+
load Gem.bin_path("safe_yaml", "safe_yaml")
|
@@ -6,12 +6,13 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = 'github_issue_exporter'
|
7
7
|
s.version = IssueExporting::VERSION
|
8
8
|
s.required_ruby_version = '>= 2.0'
|
9
|
+
s.date = '2017-12-04'
|
9
10
|
s.summary = 'Tools to export GitHub Issues'
|
10
11
|
s.description = <<-HERE
|
11
|
-
|
12
|
+
Export or Import issues from a GitHub repository.
|
12
13
|
HERE
|
13
14
|
s.license = 'MIT'
|
14
|
-
s.
|
15
|
+
s.authors = ['Scott Williams']
|
15
16
|
s.email = 'scott@swilliams.me'
|
16
17
|
s.homepage = 'https://github.com/Tallwave/github_issue_exporter'
|
17
18
|
s.files = Dir['{bin,lib}/**/*'] + ['github_issue_exporter.gemspec']
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# Copyright (c) 2015 Scott Williams
|
2
2
|
|
3
|
-
require "net/http"
|
4
3
|
require "json"
|
5
4
|
|
6
5
|
module IssueExporting
|
@@ -13,8 +12,9 @@ module IssueExporting
|
|
13
12
|
@repo = repo
|
14
13
|
@token = token
|
15
14
|
@options = options
|
16
|
-
|
17
|
-
|
15
|
+
valid_option_keys = [:path, :multiple_files, :output_type]
|
16
|
+
outputter_options = options.select { |k,v| valid_option_keys.include? k }
|
17
|
+
@outputter = build_outputter outputter_options
|
18
18
|
end
|
19
19
|
|
20
20
|
def export
|
@@ -27,6 +27,17 @@ module IssueExporting
|
|
27
27
|
outputter.write response
|
28
28
|
end
|
29
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def build_outputter(outputter_options)
|
33
|
+
output_type = outputter_options[:output_type] || 'file'
|
34
|
+
case output_type
|
35
|
+
when 'csv'
|
36
|
+
return CsvOutputter.new(outputter_options)
|
37
|
+
else
|
38
|
+
return FileOutputter.new(outputter_options)
|
39
|
+
end
|
40
|
+
end
|
30
41
|
end
|
31
42
|
end
|
32
43
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "open-uri"
|
2
|
-
|
3
1
|
module IssueExporting
|
4
2
|
def self.api_url
|
5
3
|
"https://api.github.com/repos/%s/%s/issues?access_token=%s"
|
@@ -13,7 +11,7 @@ module IssueExporting
|
|
13
11
|
end
|
14
12
|
|
15
13
|
def self.make_uri(owner, repo, token, options = {})
|
16
|
-
URI
|
14
|
+
URI(IssueExporting.make_url(owner, repo, token, options))
|
17
15
|
end
|
18
16
|
|
19
17
|
def self.turn_options_into_querystring(options)
|
@@ -1,21 +1,17 @@
|
|
1
1
|
# Copyright (c) 2015 Scott Williams
|
2
2
|
|
3
|
+
require 'csv'
|
4
|
+
|
3
5
|
module IssueExporting
|
4
|
-
class
|
6
|
+
class BaseOutputter
|
5
7
|
def initialize(options = {})
|
6
8
|
@options = options
|
7
9
|
end
|
8
10
|
|
9
11
|
def write(response_text)
|
10
|
-
path = @options[:path] || default_path
|
11
|
-
if @options[:multiple_files]
|
12
|
-
write_multi_file path, response_text
|
13
|
-
else
|
14
|
-
write_single_file path, response_text
|
15
|
-
end
|
16
12
|
end
|
17
13
|
|
18
|
-
|
14
|
+
protected
|
19
15
|
def default_path
|
20
16
|
Dir.pwd
|
21
17
|
end
|
@@ -24,11 +20,46 @@ module IssueExporting
|
|
24
20
|
"issues.json"
|
25
21
|
end
|
26
22
|
|
27
|
-
def
|
23
|
+
def write_file(dir, text)
|
28
24
|
path = "#{dir}/#{default_filename}"
|
29
|
-
File.open(path, 'w') { |f| f.write
|
25
|
+
File.open(path, 'w') { |f| f.write text }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class CsvOutputter < BaseOutputter
|
30
|
+
def write(response_text)
|
31
|
+
path = @options[:path] || default_path
|
32
|
+
array_of_issues = JSON.parse response_text
|
33
|
+
keys = ["number", "title", "state", "user.login", "created_at", "updated_at", "closed_at", "url"]
|
34
|
+
text = "Issue #,Title,State,Created By,Created At,Last Updated At,Closed At,GitHub URL\n"
|
35
|
+
mapped_values = array_of_issues.map do |issue|
|
36
|
+
values = keys.map do |key|
|
37
|
+
args = key.split '.'
|
38
|
+
issue.dig(*args)
|
39
|
+
end
|
40
|
+
values.to_csv
|
41
|
+
end
|
42
|
+
csv_text = text + mapped_values.join("")
|
43
|
+
write_file path, csv_text
|
30
44
|
end
|
31
45
|
|
46
|
+
protected
|
47
|
+
def default_filename
|
48
|
+
"issues.csv"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class FileOutputter < BaseOutputter
|
53
|
+
def write(response_text)
|
54
|
+
path = @options[:path] || default_path
|
55
|
+
if @options[:multiple_files]
|
56
|
+
write_multi_file path, response_text
|
57
|
+
else
|
58
|
+
write_file path, response_text
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
32
63
|
def write_multi_file(dir, response_text)
|
33
64
|
array_of_issues = JSON.parse response_text
|
34
65
|
array_of_issues.each do |issue|
|
data/lib/issue_exporter.rb
CHANGED
metadata
CHANGED
@@ -1,17 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: github_issue_exporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
14
|
-
Download Issues from a GitHub repository.
|
13
|
+
description: " Export or Import issues from a GitHub repository.\n"
|
15
14
|
email: scott@swilliams.me
|
16
15
|
executables:
|
17
16
|
- export-github-issues
|
@@ -23,8 +22,14 @@ extra_rdoc_files:
|
|
23
22
|
files:
|
24
23
|
- LICENSE
|
25
24
|
- README.md
|
25
|
+
- bin/bundle
|
26
26
|
- bin/export-github-issues
|
27
|
+
- bin/htmldiff
|
27
28
|
- bin/import-github-issues
|
29
|
+
- bin/ldiff
|
30
|
+
- bin/rake
|
31
|
+
- bin/rspec
|
32
|
+
- bin/safe_yaml
|
28
33
|
- github_issue_exporter.gemspec
|
29
34
|
- lib/issue_exporter.rb
|
30
35
|
- lib/issue_exporter/cli.rb
|
@@ -56,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
56
61
|
version: '0'
|
57
62
|
requirements: []
|
58
63
|
rubyforge_project:
|
59
|
-
rubygems_version: 2.
|
64
|
+
rubygems_version: 2.6.11
|
60
65
|
signing_key:
|
61
66
|
specification_version: 4
|
62
67
|
summary: Tools to export GitHub Issues
|