github_issue_exporter 0.2.1 → 0.3.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 +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
|