expo-flubber 0.0.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 +7 -0
- data/bin/flubber +5 -0
- data/lib/api_token.rb +23 -0
- data/lib/api_url.rb +3 -0
- data/lib/app.rb +44 -0
- data/lib/aws_file_upload.rb +71 -0
- data/lib/aws_folder_upload.rb +37 -0
- data/lib/cli.rb +20 -0
- data/lib/deploy.rb +165 -0
- data/lib/login.rb +66 -0
- metadata +164 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f9ca5325df420e5023e9d2a4d0a4b39551a65521c46c29b3af02d71b3c014122
|
4
|
+
data.tar.gz: 292c84899d1be9d0aeab512e97fd571a2bfde750e6e077ac7105a5a586e7c8fb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d63da0917757d2ff3f16448059b0fee2eddbbae66b6df84ed1c8fbe4c993897c1e160ce7cf3c1990dc19b3ce19d346141226deae12f9ac737d30eb84c8cc1718
|
7
|
+
data.tar.gz: 45b4c088837d516346dcb24daaf72d779913ae1bb91e17335ca32f57ab79b1a8b503e91463f99a579d6e303132631b1654197bf15b55bc180f38bcbebbf946bc
|
data/bin/flubber
ADDED
data/lib/api_token.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Flubber
|
2
|
+
module ApiToken
|
3
|
+
API_TOKEN_LOCATION = "#{ENV["HOME"]}/.flubber"
|
4
|
+
|
5
|
+
def self.set(api_token)
|
6
|
+
File.open(API_TOKEN_LOCATION, "w") do |file|
|
7
|
+
file.puts "#{api_token}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.get
|
12
|
+
return unless api_token_exists?
|
13
|
+
file = File.open(API_TOKEN_LOCATION)
|
14
|
+
api_token = file.readlines[0].chomp
|
15
|
+
file.close
|
16
|
+
api_token
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.api_token_exists?
|
20
|
+
File.exists?(API_TOKEN_LOCATION)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/api_url.rb
ADDED
data/lib/app.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module Flubber
|
2
|
+
module App
|
3
|
+
S3_BUCKET_NAME = "expo-flubber"
|
4
|
+
APP_INFO_LOCATION = ".flubber"
|
5
|
+
|
6
|
+
def self.set(flubber_app)
|
7
|
+
file = File.open(APP_INFO_LOCATION, "w+")
|
8
|
+
file.puts "#{flubber_app["id"]}"
|
9
|
+
file.puts "#{flubber_app["name"].downcase.gsub(" ", "-").gsub(/\s+/, "")}"
|
10
|
+
file.puts "#{flubber_app["uuid"]}"
|
11
|
+
file.close
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.set?
|
15
|
+
File.exists?(APP_INFO_LOCATION)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.id
|
19
|
+
file = File.open(APP_INFO_LOCATION)
|
20
|
+
lines = file.readlines.map(&:chomp)
|
21
|
+
file.close
|
22
|
+
lines[0]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.name
|
26
|
+
file = File.open(APP_INFO_LOCATION)
|
27
|
+
lines = file.readlines.map(&:chomp)
|
28
|
+
file.close
|
29
|
+
lines[1]
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.uuid
|
33
|
+
file = File.open(APP_INFO_LOCATION)
|
34
|
+
lines = file.readlines.map(&:chomp)
|
35
|
+
file.close
|
36
|
+
lines[2]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.bundles_public_url
|
40
|
+
@bundles_public_url ||= \
|
41
|
+
"https://#{S3_BUCKET_NAME}.s3.amazonaws.com/#{uuid}/#{name}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "JSON"
|
3
|
+
require "mimemagic"
|
4
|
+
|
5
|
+
require "app"
|
6
|
+
require "api_url"
|
7
|
+
|
8
|
+
module Flubber
|
9
|
+
class AwsFileUpload
|
10
|
+
def self.upload(file_path:, aws_destination:)
|
11
|
+
new(file_path, aws_destination).upload
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(file_path, aws_destination)
|
15
|
+
@file_path = file_path
|
16
|
+
@aws_destination = aws_destination
|
17
|
+
end
|
18
|
+
|
19
|
+
def upload
|
20
|
+
connection.post("/", payload)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
attr_reader :file_path, :aws_destination
|
26
|
+
|
27
|
+
def connection
|
28
|
+
@connection ||= Faraday.new(presigned_post["url"]) do |f|
|
29
|
+
f.request :multipart
|
30
|
+
f.request :url_encoded
|
31
|
+
f.adapter :net_http
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def payload
|
36
|
+
@payload ||= presigned_post["fields"].merge(
|
37
|
+
:file => Faraday::UploadIO.new(file_path, content_type),
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def presigned_post
|
42
|
+
@presigned_post ||= JSON.parse(Faraday.post(
|
43
|
+
"#{API_URL}/presigned_posts",
|
44
|
+
{
|
45
|
+
"app_uuid": app_uuid,
|
46
|
+
"aws_directory": aws_destination,
|
47
|
+
"content_type": content_type,
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"Authorization" => "Bearer #{api_token}"
|
51
|
+
}
|
52
|
+
).body)
|
53
|
+
end
|
54
|
+
|
55
|
+
def api_token
|
56
|
+
@api_token ||= ApiToken.get
|
57
|
+
end
|
58
|
+
|
59
|
+
def app_uuid
|
60
|
+
@app_uuid ||= App.uuid
|
61
|
+
end
|
62
|
+
|
63
|
+
def content_type
|
64
|
+
@content_type ||= begin
|
65
|
+
MimeMagic.by_path(file_path).type
|
66
|
+
rescue
|
67
|
+
"binary/octet-stream"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "aws_file_upload"
|
2
|
+
|
3
|
+
module Flubber
|
4
|
+
class AwsFolderUpload
|
5
|
+
IGNORED_FILES = [".DS_Store"]
|
6
|
+
|
7
|
+
def self.upload(folder_name:, aws_destination:)
|
8
|
+
new(folder_name, aws_destination).upload
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(folder_name, aws_destination)
|
12
|
+
@folder_name = folder_name
|
13
|
+
@aws_destination = aws_destination
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload
|
17
|
+
file_paths.each do |file_path|
|
18
|
+
AwsFileUpload.upload(
|
19
|
+
file_path: file_path,
|
20
|
+
aws_destination: aws_destination,
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :folder_name, :aws_destination
|
28
|
+
|
29
|
+
def file_paths
|
30
|
+
@file_paths ||= Dir
|
31
|
+
.children("./#{folder_name}")
|
32
|
+
.filter { |file| !IGNORED_FILES.include?(file) }
|
33
|
+
.map { |file| File.expand_path("#{folder_name}/#{file}") }
|
34
|
+
.filter { |file| !File.directory?(file) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/cli.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
require "login"
|
4
|
+
require "deploy"
|
5
|
+
|
6
|
+
module Flubber
|
7
|
+
class CLI < Thor
|
8
|
+
|
9
|
+
desc "login", "login to flubber"
|
10
|
+
def login
|
11
|
+
Login.login
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "deploy", "deploy an over the air update"
|
15
|
+
def deploy
|
16
|
+
Login.login
|
17
|
+
Deploy.deploy
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/deploy.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
require "git"
|
2
|
+
require "tty-spinner"
|
3
|
+
require "active_support"
|
4
|
+
require "active_support/core_ext"
|
5
|
+
|
6
|
+
require "app"
|
7
|
+
require "api_url"
|
8
|
+
require "api_token"
|
9
|
+
require "aws_folder_upload"
|
10
|
+
|
11
|
+
module Flubber
|
12
|
+
class Deploy
|
13
|
+
FILE_ALL_EXPO_APPS_HAVE = ".expo"
|
14
|
+
FOLDERS_TO_UPLOAD = [{
|
15
|
+
name: "dist",
|
16
|
+
aws_destination: "/",
|
17
|
+
}, {
|
18
|
+
name: "dist/assets",
|
19
|
+
aws_destination: "assets",
|
20
|
+
}, {
|
21
|
+
name: "dist/bundles",
|
22
|
+
aws_destination: "bundles",
|
23
|
+
}]
|
24
|
+
|
25
|
+
def self.deploy
|
26
|
+
new.deploy
|
27
|
+
end
|
28
|
+
|
29
|
+
def deploy
|
30
|
+
unless working_directory_is_an_expo_project?
|
31
|
+
puts "Failed. Run me in an expo project."
|
32
|
+
return
|
33
|
+
end
|
34
|
+
remove_bundle
|
35
|
+
set_flubber_app
|
36
|
+
puts "Using app #{App.name}"
|
37
|
+
generate_bundle
|
38
|
+
upload_bundle
|
39
|
+
remove_bundle
|
40
|
+
log_deploy
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
attr_reader :selection
|
46
|
+
|
47
|
+
def working_directory_is_an_expo_project?
|
48
|
+
@working_directory_is_an_expo_project ||= \
|
49
|
+
File.exist?(FILE_ALL_EXPO_APPS_HAVE)
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_flubber_app
|
53
|
+
return if flubber_app_is_set?
|
54
|
+
ask_for_which_flubber_app_to_use
|
55
|
+
end
|
56
|
+
|
57
|
+
def flubber_app_is_set?
|
58
|
+
App.set?
|
59
|
+
end
|
60
|
+
|
61
|
+
def flubber_apps
|
62
|
+
@flubber_apps ||= JSON.parse(Faraday.get(
|
63
|
+
"#{API_URL}/apps",
|
64
|
+
{},
|
65
|
+
{ "Authorization" => "Bearer #{api_token}" },
|
66
|
+
).body)
|
67
|
+
end
|
68
|
+
|
69
|
+
def print_existing_app_options
|
70
|
+
flubber_apps.each_with_index do |app, index|
|
71
|
+
puts "#{index + 1}. #{app["name"]}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def print_new_app_option
|
76
|
+
puts "#{flubber_apps.count + 1}. Create A New Flubber App"
|
77
|
+
end
|
78
|
+
|
79
|
+
def existing_app_selected?
|
80
|
+
selection >= 1 && selection <= flubber_apps.count
|
81
|
+
end
|
82
|
+
|
83
|
+
def new_app_selected?
|
84
|
+
selection == flubber_apps.count + 1
|
85
|
+
end
|
86
|
+
|
87
|
+
def use_existing_app_selection
|
88
|
+
flubber_app_index = selection - 1
|
89
|
+
App.set(flubber_apps[flubber_app_index])
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_new_app
|
93
|
+
print "Name your app: "
|
94
|
+
name = STDIN.gets.chomp
|
95
|
+
app = JSON.parse(Faraday.post(
|
96
|
+
"#{API_URL}/apps",
|
97
|
+
{ "name": name },
|
98
|
+
{ "Authorization" => "Bearer #{api_token}" },
|
99
|
+
).body)
|
100
|
+
App.set(app)
|
101
|
+
end
|
102
|
+
|
103
|
+
def ask_for_which_flubber_app_to_use
|
104
|
+
print_existing_app_options
|
105
|
+
print_new_app_option
|
106
|
+
loop do
|
107
|
+
print "Which app? "
|
108
|
+
@selection = STDIN.gets.chomp.to_i
|
109
|
+
if existing_app_selected?
|
110
|
+
use_existing_app_selection
|
111
|
+
break
|
112
|
+
elsif new_app_selected?
|
113
|
+
create_new_app
|
114
|
+
break
|
115
|
+
end
|
116
|
+
puts "Not an option"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def generate_bundle
|
121
|
+
bundling_spinner = TTY::Spinner.new(
|
122
|
+
"[:spinner] Bundling ...",
|
123
|
+
format: :dots,
|
124
|
+
)
|
125
|
+
bundling_spinner.auto_spin
|
126
|
+
`expo export --public-url #{App.bundles_public_url}`
|
127
|
+
bundling_spinner.stop('Done!')
|
128
|
+
end
|
129
|
+
|
130
|
+
def upload_bundle
|
131
|
+
uploading_spinner = TTY::Spinner.new(
|
132
|
+
"[:spinner] Uploading ...",
|
133
|
+
format: :dots,
|
134
|
+
)
|
135
|
+
uploading_spinner.auto_spin
|
136
|
+
FOLDERS_TO_UPLOAD.each do |folder|
|
137
|
+
AwsFolderUpload.upload(
|
138
|
+
folder_name: folder[:name],
|
139
|
+
aws_destination: folder[:aws_destination],
|
140
|
+
)
|
141
|
+
end
|
142
|
+
uploading_spinner.stop('Done!')
|
143
|
+
end
|
144
|
+
|
145
|
+
def log_deploy
|
146
|
+
Faraday.post(
|
147
|
+
"#{API_URL}/apps/#{App.id}/updates",
|
148
|
+
{ "commit_sha": sha },
|
149
|
+
{ "Authorization" => "Bearer #{api_token}" },
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
def sha
|
154
|
+
@sha ||= Git.open(".").log.first.sha
|
155
|
+
end
|
156
|
+
|
157
|
+
def api_token
|
158
|
+
@api_token ||= ApiToken.get
|
159
|
+
end
|
160
|
+
|
161
|
+
def remove_bundle
|
162
|
+
`rm -rf dist`
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/login.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "io/console"
|
2
|
+
require "faraday"
|
3
|
+
require "JSON"
|
4
|
+
require "active_support"
|
5
|
+
require "active_support/core_ext"
|
6
|
+
|
7
|
+
require "api_url"
|
8
|
+
require "api_token"
|
9
|
+
|
10
|
+
module Flubber
|
11
|
+
class Login
|
12
|
+
def self.login
|
13
|
+
new.login
|
14
|
+
end
|
15
|
+
|
16
|
+
def login
|
17
|
+
if logged_in?
|
18
|
+
puts "Already logged in."
|
19
|
+
else
|
20
|
+
get_credentials
|
21
|
+
get_api_token
|
22
|
+
save_api_token
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :phone_number, :password, :api_token
|
29
|
+
|
30
|
+
def get_credentials
|
31
|
+
print "Phone Number: "
|
32
|
+
@phone_number = STDIN.gets.chomp
|
33
|
+
print "Password: "
|
34
|
+
@password = IO::console.getpass
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_api_token
|
38
|
+
if api_token_response.status == 201
|
39
|
+
@api_token = JSON.parse(api_token_response.body)["api_token"]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_api_token
|
44
|
+
if api_token.present?
|
45
|
+
ApiToken.set(api_token)
|
46
|
+
puts "Success"
|
47
|
+
else
|
48
|
+
puts "Incorrect credentials"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def api_token_response
|
53
|
+
@api_token_response ||= Faraday.post(
|
54
|
+
"#{API_URL}/user_token",
|
55
|
+
{
|
56
|
+
"phone_number": phone_number,
|
57
|
+
"password": password,
|
58
|
+
},
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
def logged_in?
|
63
|
+
@logged_in ||= ApiToken.get.present?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: expo-flubber
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nicholas Pachulski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-08-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: git
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.7.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 6.0.3.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 6.0.3.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-spinner
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.9.3
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.9.3
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.1
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: json
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.3.1
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 2.3.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mimemagic
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.3.5
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.3.5
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: io
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.0.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.0.1
|
125
|
+
description: Update your react native expo apps Over-The-Air without size restriction
|
126
|
+
email: nick@pachulski.me
|
127
|
+
executables:
|
128
|
+
- flubber
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- bin/flubber
|
133
|
+
- lib/api_token.rb
|
134
|
+
- lib/api_url.rb
|
135
|
+
- lib/app.rb
|
136
|
+
- lib/aws_file_upload.rb
|
137
|
+
- lib/aws_folder_upload.rb
|
138
|
+
- lib/cli.rb
|
139
|
+
- lib/deploy.rb
|
140
|
+
- lib/login.rb
|
141
|
+
homepage: http://pachulski.me
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
148
|
+
- lib
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubygems_version: 3.0.3
|
161
|
+
signing_key:
|
162
|
+
specification_version: 4
|
163
|
+
summary: OTA Updates Without Size Restriction
|
164
|
+
test_files: []
|