emerge 0.7.0 → 0.7.1
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/lib/commands/build/distribution/install.rb +53 -8
- data/lib/commands/reaper/reaper.rb +2 -2
- data/lib/commands/upload/snapshots/snapshots.rb +84 -0
- data/lib/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 409fec8581e499747b3c9ca5cd80e0f9c9e491ca0d94688bc1e0d299a974a95b
|
4
|
+
data.tar.gz: 64863c523c84b25f5ff21a9bbda0863f13ef7a5165d5437aeb66d60211e7fe84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a6dc2be9e2ad1f3078c9f6703d35c2f1e70d5630d14a2f682216fb949c1111b7bc236702e2e9698714f4662e5e7a70bcb67118c510542b61d1b58c00f13dc1e
|
7
|
+
data.tar.gz: 76f622ef6797a7c420d1406e9f43ddceb9f075180641ae6e5b78cbb63a3a18489d883d63346d973f9ff8e6b225281d2d0671e6ad33d5ff667b5c7d347c8ba769
|
@@ -3,6 +3,7 @@ require 'cfpropertylist'
|
|
3
3
|
require 'zip'
|
4
4
|
require 'rbconfig'
|
5
5
|
require 'tmpdir'
|
6
|
+
require 'tty-prompt'
|
6
7
|
|
7
8
|
module EmergeCLI
|
8
9
|
module Commands
|
@@ -13,7 +14,7 @@ module EmergeCLI
|
|
13
14
|
|
14
15
|
option :api_token, type: :string, required: false,
|
15
16
|
desc: 'API token for authentication, defaults to ENV[EMERGE_API_TOKEN]'
|
16
|
-
option :
|
17
|
+
option :id, type: :string, required: true, desc: 'Emerge build ID to download'
|
17
18
|
option :install, type: :boolean, default: true, required: false, desc: 'Install the build on the device'
|
18
19
|
option :device_id, type: :string, desc: 'Specific device ID to target'
|
19
20
|
option :device_type, type: :string, enum: %w[virtual physical any], default: 'any',
|
@@ -32,7 +33,7 @@ module EmergeCLI
|
|
32
33
|
api_token = @options[:api_token] || ENV.fetch('EMERGE_API_TOKEN', nil)
|
33
34
|
raise 'API token is required' unless api_token
|
34
35
|
|
35
|
-
raise 'Build ID is required' unless @options[:
|
36
|
+
raise 'Build ID is required' unless @options[:id]
|
36
37
|
|
37
38
|
output_name = nil
|
38
39
|
app_id = nil
|
@@ -41,7 +42,7 @@ module EmergeCLI
|
|
41
42
|
@network ||= EmergeCLI::Network.new(api_token:)
|
42
43
|
|
43
44
|
Logger.info 'Getting build URL...'
|
44
|
-
request = get_build_url(@options[:
|
45
|
+
request = get_build_url(@options[:id])
|
45
46
|
response = parse_response(request)
|
46
47
|
|
47
48
|
platform = response['platform']
|
@@ -49,10 +50,32 @@ module EmergeCLI
|
|
49
50
|
app_id = response['appId']
|
50
51
|
|
51
52
|
extension = platform == 'ios' ? 'ipa' : 'apk'
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
output_name = @options[:output] || "#{@options[:id]}.#{extension}"
|
54
|
+
|
55
|
+
if File.exist?(output_name)
|
56
|
+
Logger.info "Build file already exists at #{output_name}"
|
57
|
+
prompt = TTY::Prompt.new
|
58
|
+
choice = prompt.select('What would you like to do?', {
|
59
|
+
'Install existing file' => :install,
|
60
|
+
'Overwrite with new download' => :overwrite,
|
61
|
+
'Cancel' => :cancel
|
62
|
+
})
|
63
|
+
|
64
|
+
case choice
|
65
|
+
when :install
|
66
|
+
Logger.info 'Proceeding with existing file...'
|
67
|
+
when :overwrite
|
68
|
+
Logger.info 'Downloading new build...'
|
69
|
+
`curl --progress-bar -L '#{download_url}' -o #{output_name}`
|
70
|
+
Logger.info "✅ Build downloaded to #{output_name}"
|
71
|
+
when :cancel
|
72
|
+
raise 'Operation cancelled by user'
|
73
|
+
end
|
74
|
+
else
|
75
|
+
Logger.info 'Downloading build...'
|
76
|
+
`curl --progress-bar -L '#{download_url}' -o #{output_name}`
|
77
|
+
Logger.info "✅ Build downloaded to #{output_name}"
|
78
|
+
end
|
56
79
|
rescue StandardError => e
|
57
80
|
Logger.error "❌ Failed to download build: #{e.message}"
|
58
81
|
raise e
|
@@ -128,12 +151,34 @@ module EmergeCLI
|
|
128
151
|
end
|
129
152
|
|
130
153
|
def install_android_build(build_path)
|
131
|
-
|
154
|
+
device_id = @options[:device_id] || select_android_device
|
155
|
+
raise 'No Android devices found' unless device_id
|
156
|
+
|
157
|
+
command = "adb -s #{device_id} install #{build_path}"
|
132
158
|
Logger.debug "Running command: #{command}"
|
133
159
|
`#{command}`
|
134
160
|
|
135
161
|
Logger.info '✅ Build installed'
|
136
162
|
end
|
163
|
+
|
164
|
+
def select_android_device
|
165
|
+
devices = get_android_devices
|
166
|
+
return nil if devices.empty?
|
167
|
+
return devices.first if devices.length == 1
|
168
|
+
|
169
|
+
prompt = TTY::Prompt.new
|
170
|
+
Logger.info 'Multiple Android devices found.'
|
171
|
+
prompt.select('Choose a device:', devices)
|
172
|
+
end
|
173
|
+
|
174
|
+
def get_android_devices
|
175
|
+
output = `adb devices`
|
176
|
+
# Split output into lines, remove first line (header), and extract device IDs
|
177
|
+
output.split("\n")[1..]
|
178
|
+
.map(&:strip)
|
179
|
+
.reject(&:empty?)
|
180
|
+
.map { |line| line.split("\t").first }
|
181
|
+
end
|
137
182
|
end
|
138
183
|
end
|
139
184
|
end
|
@@ -7,7 +7,7 @@ module EmergeCLI
|
|
7
7
|
class Reaper < EmergeCLI::Commands::GlobalOptions
|
8
8
|
desc 'Analyze dead code from an Emerge upload'
|
9
9
|
|
10
|
-
option :
|
10
|
+
option :id, type: :string, required: true, desc: 'Emerge build ID to analyze'
|
11
11
|
option :project_root, type: :string, required: true,
|
12
12
|
desc: 'Root directory of the project, defaults to current directory'
|
13
13
|
|
@@ -38,7 +38,7 @@ module EmergeCLI
|
|
38
38
|
project_root = @options[:project_root] || Dir.pwd
|
39
39
|
|
40
40
|
Sync do
|
41
|
-
all_data = @profiler.measure('fetch_dead_code') { fetch_all_dead_code(@options[:
|
41
|
+
all_data = @profiler.measure('fetch_dead_code') { fetch_all_dead_code(@options[:id]) }
|
42
42
|
result = @profiler.measure('parse_dead_code') { DeadCodeResult.new(all_data) }
|
43
43
|
|
44
44
|
Logger.info result.to_s
|
@@ -6,6 +6,8 @@ require 'async'
|
|
6
6
|
require 'async/barrier'
|
7
7
|
require 'async/semaphore'
|
8
8
|
require 'async/http/internet/instance'
|
9
|
+
require 'zip'
|
10
|
+
require 'tempfile'
|
9
11
|
|
10
12
|
module EmergeCLI
|
11
13
|
module Commands
|
@@ -33,6 +35,8 @@ module EmergeCLI
|
|
33
35
|
|
34
36
|
option :profile, type: :boolean, default: false, desc: 'Enable performance profiling metrics'
|
35
37
|
|
38
|
+
option :batch, type: :boolean, default: false, desc: 'Upload images in batch using zip file'
|
39
|
+
|
36
40
|
argument :image_paths, type: :array, required: false, desc: 'Paths to folders containing images'
|
37
41
|
|
38
42
|
def initialize(network: nil, git_info_provider: nil)
|
@@ -178,6 +182,86 @@ module EmergeCLI
|
|
178
182
|
def upload_images(run_id, concurrency, image_files, client)
|
179
183
|
Logger.info 'Uploading images...'
|
180
184
|
|
185
|
+
if @options[:batch]
|
186
|
+
batch_upload_images(run_id, image_files, client)
|
187
|
+
else
|
188
|
+
individual_upload_images(run_id, concurrency, image_files, client)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def batch_upload_images(run_id, image_files, client)
|
193
|
+
Logger.info 'Preparing batch upload...'
|
194
|
+
|
195
|
+
metadata_barrier = Async::Barrier.new
|
196
|
+
metadata_semaphore = Async::Semaphore.new(10, parent: metadata_barrier)
|
197
|
+
|
198
|
+
image_metadata = {
|
199
|
+
manifestVersion: 1,
|
200
|
+
images: {},
|
201
|
+
errors: []
|
202
|
+
}
|
203
|
+
|
204
|
+
@profiler.measure('process_image_metadata') do
|
205
|
+
image_files.each do |image_path|
|
206
|
+
metadata_semaphore.async do
|
207
|
+
file_info = client.parse_file_info(image_path)
|
208
|
+
|
209
|
+
dimensions = @profiler.measure('chunky_png_processing') do
|
210
|
+
datastream = ChunkyPNG::Datastream.from_file(image_path)
|
211
|
+
{
|
212
|
+
width: datastream.header_chunk.width,
|
213
|
+
height: datastream.header_chunk.height
|
214
|
+
}
|
215
|
+
end
|
216
|
+
|
217
|
+
metadata = {
|
218
|
+
fileName: file_info[:file_name],
|
219
|
+
groupName: file_info[:group_name],
|
220
|
+
displayName: file_info[:variant_name],
|
221
|
+
width: dimensions[:width],
|
222
|
+
height: dimensions[:height]
|
223
|
+
}
|
224
|
+
|
225
|
+
image_name = File.basename(image_path, '.*')
|
226
|
+
image_metadata[:images][image_name] = metadata
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
metadata_barrier.wait
|
231
|
+
end
|
232
|
+
|
233
|
+
Tempfile.create(['snapshot_batch', '.zip']) do |zip_file|
|
234
|
+
@profiler.measure('create_zip_file') do
|
235
|
+
Zip::File.open(zip_file.path, Zip::File::CREATE) do |zipfile|
|
236
|
+
zipfile.get_output_stream('manifest.json') { |f| f.write(JSON.generate(image_metadata)) }
|
237
|
+
|
238
|
+
image_files.each do |image_path|
|
239
|
+
image_name = File.basename(image_path)
|
240
|
+
zipfile.add(image_name, image_path)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
upload_url = @profiler.measure('create_batch_upload_url') do
|
246
|
+
response = @network.post(path: '/v1/snapshots/run/batch-image', body: { run_id: run_id })
|
247
|
+
JSON.parse(response.read).fetch('zip_url')
|
248
|
+
end
|
249
|
+
|
250
|
+
Logger.info 'Uploading images...'
|
251
|
+
Logger.debug "Uploading batch zip file to #{upload_url}"
|
252
|
+
@profiler.measure('upload_batch_zip') do
|
253
|
+
@network.put(
|
254
|
+
path: upload_url,
|
255
|
+
headers: { 'Content-Type' => 'application/zip' },
|
256
|
+
body: File.read(zip_file.path)
|
257
|
+
)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
ensure
|
261
|
+
metadata_barrier&.stop
|
262
|
+
end
|
263
|
+
|
264
|
+
def individual_upload_images(run_id, concurrency, image_files, client)
|
181
265
|
post_image_barrier = Async::Barrier.new
|
182
266
|
post_image_semaphore = Async::Semaphore.new(concurrency, parent: post_image_barrier)
|
183
267
|
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: emerge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emerge Tools
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async-http
|