datapimp 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/Gemfile +6 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +4 -18
- data/README.md +199 -17
- data/Rakefile +24 -0
- data/bin/datapimp +18 -0
- data/datapimp.gemspec +27 -7
- data/lib/datapimp/cli/01_extensions.rb +25 -0
- data/lib/datapimp/cli/config.rb +24 -0
- data/lib/datapimp/cli/setup.rb +35 -0
- data/lib/datapimp/cli/sync.rb +29 -0
- data/lib/datapimp/cli.rb +49 -0
- data/lib/datapimp/clients/amazon.rb +172 -0
- data/lib/datapimp/clients/dropbox.rb +178 -0
- data/lib/datapimp/clients/github.rb +59 -0
- data/lib/datapimp/clients/google.rb +145 -0
- data/lib/datapimp/configuration.rb +210 -0
- data/lib/datapimp/core_ext.rb +5 -0
- data/lib/datapimp/data_sources/dropbox.rb +8 -0
- data/lib/datapimp/data_sources/excel.rb +5 -0
- data/lib/datapimp/data_sources/github.rb +5 -0
- data/lib/datapimp/data_sources/google.rb +5 -0
- data/lib/datapimp/data_sources/json.rb +5 -0
- data/lib/datapimp/data_sources/nokogiri.rb +5 -0
- data/lib/datapimp/data_sources.rb +10 -0
- data/lib/datapimp/sync/dropbox_delta.rb +67 -0
- data/lib/datapimp/sync/dropbox_folder.rb +10 -0
- data/lib/datapimp/sync/google_drive_folder.rb +5 -0
- data/lib/datapimp/sync.rb +30 -0
- data/lib/datapimp/version.rb +1 -1
- data/lib/datapimp.rb +30 -2
- data/packaging/wrapper.sh +32 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/test_helpers.rb +7 -0
- data/tasks/distribution/configuration.rb +15 -0
- data/tasks/distribution/executable.rb +28 -0
- data/tasks/distribution/package.rb +85 -0
- data/tasks/distribution/package_helpers.rb +12 -0
- data/tasks/distribution/release.rb +49 -0
- data/tasks/distribution/release_notes.erb +14 -0
- data/tasks/distribution/release_notes.rb +62 -0
- data/tasks/distribution/tarball.rb +47 -0
- data/tasks/distribution/travelling_ruby.rb +87 -0
- data/tasks/package.rake +41 -0
- data/tasks/upload.rake +40 -0
- metadata +300 -26
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Datapimp
|
5
|
+
class Configuration
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
DefaultSettings = {
|
9
|
+
manifest_filename: "datapimp.json",
|
10
|
+
|
11
|
+
github_username: '',
|
12
|
+
github_organization: '',
|
13
|
+
github_app_key: '',
|
14
|
+
github_app_secret: '',
|
15
|
+
github_access_token: '',
|
16
|
+
|
17
|
+
dnsimple_api_token: '',
|
18
|
+
dnsimple_username: '',
|
19
|
+
|
20
|
+
dropbox_app_key: '',
|
21
|
+
dropbox_app_secret: '',
|
22
|
+
dropbox_app_type: 'sandbox',
|
23
|
+
dropbox_client_token: '',
|
24
|
+
dropbox_client_secret: '',
|
25
|
+
|
26
|
+
aws_access_key_id: '',
|
27
|
+
aws_secret_access_key: '',
|
28
|
+
|
29
|
+
google_client_id: '',
|
30
|
+
google_client_secret: '',
|
31
|
+
google_refresh_token: '',
|
32
|
+
google_access_token: ''
|
33
|
+
}
|
34
|
+
|
35
|
+
def self.method_missing(meth, *args, &block)
|
36
|
+
if instance.respond_to?(meth)
|
37
|
+
return instance.send meth, *args, &block
|
38
|
+
end
|
39
|
+
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(meth, *args, &block)
|
44
|
+
if current.key?(meth.to_s)
|
45
|
+
return current.fetch(meth)
|
46
|
+
end
|
47
|
+
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize!(fresh=false)
|
52
|
+
return if home_config_path.exist? && !fresh
|
53
|
+
|
54
|
+
FileUtils.mkdir_p home_config_path.dirname
|
55
|
+
|
56
|
+
home_config_path.open("w+") do |fh|
|
57
|
+
fh.write(DefaultSettings.to_json)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def manifest_filename
|
62
|
+
"datapimp.json"
|
63
|
+
end
|
64
|
+
|
65
|
+
def dnsimple_setup?
|
66
|
+
dnsimple_api_token.to_s.length > 0 && dnsimple_username.to_s.length > 0
|
67
|
+
end
|
68
|
+
|
69
|
+
def dropbox_setup?
|
70
|
+
dropbox_app_key.to_s.length > 0 && dropbox_app_secret.to_s.length > 0
|
71
|
+
end
|
72
|
+
|
73
|
+
def google_setup?
|
74
|
+
google_client_secret.to_s.length > 0 && google_client_id.to_s.length > 0
|
75
|
+
end
|
76
|
+
|
77
|
+
def amazon_setup?
|
78
|
+
aws_access_key_id.to_s.length > 0 && aws_secret_access_key.to_s.length > 0
|
79
|
+
end
|
80
|
+
|
81
|
+
def show
|
82
|
+
current.each do |p|
|
83
|
+
key, value = p
|
84
|
+
|
85
|
+
unless key == 'sites_directory'
|
86
|
+
puts "#{key}: #{ value.inspect }"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def primary_config
|
92
|
+
cwd_config_path.exist? ? cwd_config : home_config
|
93
|
+
end
|
94
|
+
|
95
|
+
def get(setting)
|
96
|
+
setting = setting.to_s.downcase
|
97
|
+
primary_config[setting]
|
98
|
+
end
|
99
|
+
|
100
|
+
def set(setting, value, persist = true, options={})
|
101
|
+
setting = setting.to_s.downcase
|
102
|
+
primary_config[setting] = value
|
103
|
+
save! if persist == true
|
104
|
+
value
|
105
|
+
end
|
106
|
+
|
107
|
+
def apply_all(options={})
|
108
|
+
current.merge!(options)
|
109
|
+
end
|
110
|
+
|
111
|
+
def unset(setting, persist = true)
|
112
|
+
primary_config.delete(setting)
|
113
|
+
save! if persist == true
|
114
|
+
end
|
115
|
+
|
116
|
+
def defaults
|
117
|
+
DefaultSettings.dup
|
118
|
+
end
|
119
|
+
|
120
|
+
def current(using_environment = true)
|
121
|
+
@current ||= calculate_config(using_environment)
|
122
|
+
end
|
123
|
+
|
124
|
+
def calculate_config(using_environment = true)
|
125
|
+
@current = defaults.merge(home_config.merge(cwd_config.merge(applied_config))).to_mash
|
126
|
+
|
127
|
+
(defaults.keys + home_config.keys + cwd_config.keys).uniq.each do |key|
|
128
|
+
upper = key.to_s.upcase
|
129
|
+
if ENV[upper]
|
130
|
+
@current[key] = ENV[upper]
|
131
|
+
end
|
132
|
+
end if using_environment
|
133
|
+
|
134
|
+
@current
|
135
|
+
end
|
136
|
+
|
137
|
+
def apply_config(hash={})
|
138
|
+
applied_config.merge!(hash)
|
139
|
+
current.merge(applied_config)
|
140
|
+
end
|
141
|
+
|
142
|
+
def apply_config_from_path(path)
|
143
|
+
path = Pathname(path)
|
144
|
+
parsed = JSON.parse(path.read) rescue {}
|
145
|
+
applied_config.merge!(parsed)
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
|
149
|
+
def save!
|
150
|
+
save_home_config
|
151
|
+
save_cwd_config
|
152
|
+
@current = nil
|
153
|
+
true
|
154
|
+
end
|
155
|
+
|
156
|
+
def save_cwd_config
|
157
|
+
return nil unless cwd_config_path.exist?
|
158
|
+
|
159
|
+
File.open(cwd_config_path, 'w+') do |fh|
|
160
|
+
fh.write JSON.generate(cwd_config.to_hash)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def save_home_config
|
165
|
+
File.open(home_config_path, 'w+') do |fh|
|
166
|
+
fh.write JSON.generate(home_config.to_hash)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Applied config is configuration values passed in context
|
171
|
+
# usually from the cli, but also in the unit tests
|
172
|
+
def applied_config
|
173
|
+
@applied_config ||= {}
|
174
|
+
end
|
175
|
+
|
176
|
+
def cwd_config
|
177
|
+
@cwd_config ||= begin
|
178
|
+
(cwd_config_path.exist? rescue false) ? JSON.parse(cwd_config_path.read) : {}
|
179
|
+
rescue
|
180
|
+
{}
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def home_config
|
185
|
+
initialize! unless home_config_path.exist?
|
186
|
+
|
187
|
+
@home_config ||= begin
|
188
|
+
(home_config_path.exist? rescue false) ? JSON.parse(home_config_path.read) : {}
|
189
|
+
rescue
|
190
|
+
{}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def home_config_path= value
|
195
|
+
@home_config_path = Pathname(value)
|
196
|
+
end
|
197
|
+
|
198
|
+
def home_config_path
|
199
|
+
@home_config_path || Pathname(ENV['HOME']).join(".datapimp", manifest_filename)
|
200
|
+
end
|
201
|
+
|
202
|
+
def cwd_config_path= value
|
203
|
+
@cwd_config_path = Pathname(value)
|
204
|
+
end
|
205
|
+
|
206
|
+
def cwd_config_path
|
207
|
+
@cwd_config_path || Pathname(Datapimp.pwd).join(manifest_filename)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# The `Datapimp::Dataources` module houses the various
|
2
|
+
# types of remote data stores we are reading and converting into
|
3
|
+
# a JSON array of objects that gets cached on our filesystem.
|
4
|
+
module Datapimp
|
5
|
+
module DataSources
|
6
|
+
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
Dir[Datapimp.lib.join("datapimp/data_sources/**/*.rb")].each {|f| require(f) }
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Datapimp
|
2
|
+
module Sync
|
3
|
+
class DropboxDelta
|
4
|
+
|
5
|
+
attr_accessor :client,
|
6
|
+
:data,
|
7
|
+
:cursor,
|
8
|
+
:entries,
|
9
|
+
:path_prefix
|
10
|
+
|
11
|
+
def initialize(client, cursor, path_prefix=nil)
|
12
|
+
@client = client
|
13
|
+
@cursor = cursor
|
14
|
+
@path_prefix = path_prefix
|
15
|
+
end
|
16
|
+
|
17
|
+
def processed!
|
18
|
+
# TODO
|
19
|
+
# Should update cursor
|
20
|
+
end
|
21
|
+
|
22
|
+
def entries
|
23
|
+
return @entries if @entries
|
24
|
+
fetch
|
25
|
+
@entries
|
26
|
+
end
|
27
|
+
|
28
|
+
def _dropbox_delta at=nil
|
29
|
+
at ||= cursor
|
30
|
+
response = client.delta(at, path_prefix)
|
31
|
+
self.cursor = response["cursor"]
|
32
|
+
response
|
33
|
+
end
|
34
|
+
|
35
|
+
def data
|
36
|
+
@data ||= fetch
|
37
|
+
end
|
38
|
+
|
39
|
+
def on_reset path_prefix, cursor
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch
|
43
|
+
return @response if @response
|
44
|
+
|
45
|
+
response = _dropbox_delta
|
46
|
+
|
47
|
+
if response["reset"] == true
|
48
|
+
on_reset(path_prefix, cursor)
|
49
|
+
end
|
50
|
+
|
51
|
+
self.entries = {}.to_mash
|
52
|
+
|
53
|
+
response["entries"].each do |entry|
|
54
|
+
path, meta = entry
|
55
|
+
self.entries[path] = meta
|
56
|
+
end
|
57
|
+
|
58
|
+
if response["has_more"] == true
|
59
|
+
# TODO Implement
|
60
|
+
end
|
61
|
+
|
62
|
+
@response = response
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# The `Datapimp::Sync` module will delegate to the underlying service layer
|
2
|
+
# which we are pushing or pulling files and data from. It will wrap the client
|
3
|
+
# implementation we are using.
|
4
|
+
module Datapimp
|
5
|
+
module Sync
|
6
|
+
def self.data_source_types
|
7
|
+
%w(dropbox amazon github google json excel nokogiri)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.amazon(options={})
|
11
|
+
require 'datapimp/clients/amazon'
|
12
|
+
Datapimp::Clients::Amazon.client(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.dropbox(options={})
|
16
|
+
require 'datapimp/clients/dropbox'
|
17
|
+
Datapimp::Clients::Dropbox.client(options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.github(options={})
|
21
|
+
require 'datapimp/clients/github'
|
22
|
+
Datapimp::Clients::Github.client(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.google(options={})
|
26
|
+
require 'datapimp/clients/google'
|
27
|
+
Datapimp::Clients::Google.client(options)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/datapimp/version.rb
CHANGED
data/lib/datapimp.rb
CHANGED
@@ -1,5 +1,33 @@
|
|
1
|
-
require
|
1
|
+
require 'ostruct'
|
2
|
+
require 'set'
|
3
|
+
require 'pathname'
|
4
|
+
require 'hashie'
|
5
|
+
require 'datapimp/core_ext'
|
2
6
|
|
3
7
|
module Datapimp
|
4
|
-
|
8
|
+
def self.config
|
9
|
+
Datapimp::Configuration.instance
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.pwd
|
13
|
+
Pathname(ENV.fetch('DATAPIMP_PWD') { Dir.pwd })
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.lib
|
17
|
+
Pathname(File.dirname(__FILE__))
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.method_missing(meth, *args, &block)
|
21
|
+
case
|
22
|
+
when %w(dropbox amazon github google).include?(meth.to_s)
|
23
|
+
Datapimp::Sync.send(meth, *args, &block)
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
5
28
|
end
|
29
|
+
|
30
|
+
require 'datapimp/version'
|
31
|
+
require 'datapimp/configuration'
|
32
|
+
require 'datapimp/data_sources'
|
33
|
+
require 'datapimp/sync'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
export DATAPIMP_PWD=$PWD
|
4
|
+
set -e
|
5
|
+
|
6
|
+
TARGET_FILE=$0
|
7
|
+
|
8
|
+
cd `dirname $TARGET_FILE`
|
9
|
+
TARGET_FILE=`basename $TARGET_FILE`
|
10
|
+
|
11
|
+
# Iterate down a (possible) chain of symlinks
|
12
|
+
while [ -L "$TARGET_FILE" ]
|
13
|
+
do
|
14
|
+
TARGET_FILE=`readlink $TARGET_FILE`
|
15
|
+
cd `dirname $TARGET_FILE`
|
16
|
+
TARGET_FILE=`basename $TARGET_FILE`
|
17
|
+
done
|
18
|
+
|
19
|
+
# Compute the canonicalized name by finding the physical path
|
20
|
+
# for the directory we're in and appending the target file.
|
21
|
+
PHYS_DIR=`pwd -P`
|
22
|
+
RESULT=$PHYS_DIR/$TARGET_FILE
|
23
|
+
|
24
|
+
# Figure out where this script is located.
|
25
|
+
SELFDIR=$(dirname "$RESULT")
|
26
|
+
|
27
|
+
# Tell Bundler where the Gemfile and gems are.
|
28
|
+
export BUNDLE_GEMFILE="$SELFDIR/lib/app/Gemfile"
|
29
|
+
unset BUNDLE_IGNORE_CONFIG
|
30
|
+
|
31
|
+
# Run the actual app using the bundled Ruby interpreter.
|
32
|
+
exec "$SELFDIR/lib/ruby/bin/ruby" -rbundler/setup "$SELFDIR/lib/app/bin/datapimp" "$@"
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rack/test'
|
2
|
+
require 'pry'
|
3
|
+
require 'datapimp'
|
4
|
+
|
5
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
6
|
+
|
7
|
+
module Datapimp
|
8
|
+
def self.spec_root
|
9
|
+
Pathname(File.dirname(__FILE__))
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.dummy_path
|
13
|
+
spec_root.join("dummy")
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.fixtures_path
|
17
|
+
spec_root.join("support","fixtures")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Skypager::Site.directory = {}
|
22
|
+
|
23
|
+
RSpec.configure do |config|
|
24
|
+
config.mock_with :rspec
|
25
|
+
config.order = :random
|
26
|
+
|
27
|
+
config.include Rack::Test
|
28
|
+
config.include Requests::JsonHelpers, type: :request
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Distribution
|
2
|
+
class << self
|
3
|
+
attr_accessor :configuration
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
self.configuration ||= Configuration.new
|
8
|
+
yield configuration
|
9
|
+
end
|
10
|
+
|
11
|
+
class Configuration
|
12
|
+
attr_accessor :package_name, :packaging_dir, :version, :rb_version,
|
13
|
+
:native_extensions
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Dir[File.join(Dir.pwd, 'tasks', '**', '*.rb')].each { |f| require f }
|
2
|
+
|
3
|
+
module Distribution
|
4
|
+
class Executable
|
5
|
+
include PackageHelpers
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
attr_reader :package
|
9
|
+
|
10
|
+
def_delegators :@package, :dir, :package_name
|
11
|
+
|
12
|
+
def initialize(package)
|
13
|
+
@package = package
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.create(package)
|
17
|
+
executable = new(package)
|
18
|
+
executable.copy_wrapper
|
19
|
+
executable
|
20
|
+
end
|
21
|
+
|
22
|
+
def copy_wrapper
|
23
|
+
print_to_console 'Creating exexutable...'
|
24
|
+
|
25
|
+
FileUtils.cp 'packaging/wrapper.sh', "#{dir}/#{package_name}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
Dir[File.join(Dir.pwd, 'tasks', '**', '*.rb')].each { |f| require f }
|
5
|
+
|
6
|
+
module Distribution
|
7
|
+
class Package
|
8
|
+
extend Forwardable
|
9
|
+
include PackageHelpers
|
10
|
+
|
11
|
+
attr_reader :config, :dir, :tarball, :package, :arch, :root
|
12
|
+
|
13
|
+
def_delegators :@config, :version, :rb_version, :package_name,
|
14
|
+
:packaging_dir, :native_extensions
|
15
|
+
|
16
|
+
def initialize(arch)
|
17
|
+
abort 'Ruby 2.1.x required' if RUBY_VERSION !~ /^2\.1\./
|
18
|
+
|
19
|
+
@arch = arch
|
20
|
+
@config = ::Distribution.configuration
|
21
|
+
@dir = "#{package_name}-#{version}-#{arch}"
|
22
|
+
@package = self
|
23
|
+
@root = File.expand_path '.'
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.create(args)
|
27
|
+
new(*args).build
|
28
|
+
end
|
29
|
+
|
30
|
+
def build
|
31
|
+
initialize_install_dir
|
32
|
+
copy_datapimp
|
33
|
+
install_ruby_and_gems
|
34
|
+
create_executable
|
35
|
+
post_cleanup
|
36
|
+
@tarball = create_tarball
|
37
|
+
clean_dir
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def clean_dir
|
43
|
+
FileUtils.cd root do
|
44
|
+
FileUtils.remove_dir(dir, true) if Dir.exist? dir
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def post_cleanup
|
49
|
+
print_to_console 'Cleaning up...'
|
50
|
+
|
51
|
+
files = ["#{packaging_dir}/traveling-ruby-#{rb_version}-#{arch}.tar.gz"]
|
52
|
+
|
53
|
+
files.each { |file| FileUtils.rm file if File.exist? file }
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_tarball
|
57
|
+
Tarball.new self
|
58
|
+
end
|
59
|
+
|
60
|
+
def create_executable
|
61
|
+
Executable.create self
|
62
|
+
end
|
63
|
+
|
64
|
+
def install_ruby_and_gems
|
65
|
+
TravellingRuby.install self
|
66
|
+
end
|
67
|
+
|
68
|
+
def initialize_install_dir
|
69
|
+
clean_dir
|
70
|
+
|
71
|
+
FileUtils.cd root do
|
72
|
+
FileUtils.mkdir_p "#{dir}/lib/app"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def copy_datapimp
|
77
|
+
print_to_console 'Copying datapimp...'
|
78
|
+
|
79
|
+
%w(datapimp.gemspec Gemfile Gemfile.lock lib bin)
|
80
|
+
.each do |folder|
|
81
|
+
FileUtils.cp_r File.join(root, folder), "#{dir}/lib/app"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
Dir[File.join(Dir.pwd, 'tasks', '**', '*.rb')].each { |f| require f }
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
require 'octokit'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
module Distribution
|
8
|
+
class Release
|
9
|
+
extend Forwardable
|
10
|
+
include PackageHelpers
|
11
|
+
|
12
|
+
attr_reader :tarball, :github, :package
|
13
|
+
|
14
|
+
def_delegators :@tarball, :package, :version, :file
|
15
|
+
|
16
|
+
def initialize(tarball)
|
17
|
+
@tarball = tarball
|
18
|
+
@github = Octokit::Client.new access_token: ENV['OCTODOWN_TOKEN']
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.create(tarball)
|
22
|
+
release = new(tarball)
|
23
|
+
release.create_new_release
|
24
|
+
end
|
25
|
+
|
26
|
+
def create_new_release
|
27
|
+
print_to_console 'Publishing release to GitHub...'
|
28
|
+
github.create_release(
|
29
|
+
'datapimp/datapimp',
|
30
|
+
"v#{version}",
|
31
|
+
name: "v#{version}",
|
32
|
+
body: ReleaseNotes.new.content
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
def upload_asset
|
37
|
+
print_to_console 'Uploading to GitHub...'
|
38
|
+
github.upload_asset find_upload_url, file
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def find_upload_url
|
44
|
+
Octokit.releases('datapimp/datapimp').find do |n|
|
45
|
+
n.tag_name == "v#{version}"
|
46
|
+
end[:url]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|