appydave-tools 0.16.0 → 0.17.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/.rubocop.yml +6 -0
- data/AGENTS.md +22 -0
- data/CHANGELOG.md +12 -0
- data/CLAUDE.md +206 -51
- data/README.md +144 -11
- data/bin/archive_project.rb +249 -0
- data/bin/configuration.rb +21 -1
- data/bin/generate_manifest.rb +357 -0
- data/bin/sync_from_ssd.rb +236 -0
- data/bin/vat +623 -0
- data/docs/README.md +169 -0
- data/docs/configuration/.env.example +19 -0
- data/docs/configuration/README.md +394 -0
- data/docs/configuration/channels.example.json +26 -0
- data/docs/configuration/settings.example.json +6 -0
- data/docs/development/CODEX-recommendations.md +123 -0
- data/docs/development/README.md +100 -0
- data/docs/development/cli-architecture-patterns.md +1604 -0
- data/docs/development/pattern-comparison.md +284 -0
- data/docs/prd-unified-brands-configuration.md +792 -0
- data/docs/project-brand-systems-analysis.md +934 -0
- data/docs/vat/dam-vision.md +123 -0
- data/docs/vat/session-summary-2025-11-09.md +297 -0
- data/docs/vat/usage.md +508 -0
- data/docs/vat/vat-testing-plan.md +801 -0
- data/lib/appydave/tools/configuration/models/brands_config.rb +238 -0
- data/lib/appydave/tools/configuration/models/config_base.rb +7 -0
- data/lib/appydave/tools/configuration/models/settings_config.rb +4 -0
- data/lib/appydave/tools/vat/config.rb +153 -0
- data/lib/appydave/tools/vat/config_loader.rb +91 -0
- data/lib/appydave/tools/vat/manifest_generator.rb +239 -0
- data/lib/appydave/tools/vat/project_listing.rb +198 -0
- data/lib/appydave/tools/vat/project_resolver.rb +132 -0
- data/lib/appydave/tools/vat/s3_operations.rb +560 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +9 -1
- data/package.json +1 -1
- metadata +57 -3
- data/docs/dam/overview.md +0 -28
data/bin/vat
ADDED
|
@@ -0,0 +1,623 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'optparse'
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
7
|
+
|
|
8
|
+
require 'appydave/tools'
|
|
9
|
+
|
|
10
|
+
# VAT (Video Asset Tools) - CLI for video project management
|
|
11
|
+
class VatCLI
|
|
12
|
+
def initialize
|
|
13
|
+
@commands = {
|
|
14
|
+
'help' => method(:help_command),
|
|
15
|
+
'list' => method(:list_command),
|
|
16
|
+
's3-up' => method(:s3_up_command),
|
|
17
|
+
's3-down' => method(:s3_down_command),
|
|
18
|
+
's3-status' => method(:s3_status_command),
|
|
19
|
+
's3-cleanup-remote' => method(:s3_cleanup_remote_command),
|
|
20
|
+
's3-cleanup-local' => method(:s3_cleanup_local_command),
|
|
21
|
+
'archive' => method(:archive_command),
|
|
22
|
+
'manifest' => method(:manifest_command),
|
|
23
|
+
# Deprecated aliases (for backward compatibility)
|
|
24
|
+
's3-cleanup' => method(:s3_cleanup_remote_command),
|
|
25
|
+
'cleanup-local' => method(:s3_cleanup_local_command)
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def run
|
|
30
|
+
command, *args = ARGV
|
|
31
|
+
|
|
32
|
+
if command.nil?
|
|
33
|
+
puts 'VAT - Video Asset Tools'
|
|
34
|
+
puts 'Usage: vat [command] [options]'
|
|
35
|
+
puts "Run 'vat help' for more information."
|
|
36
|
+
exit
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if @commands.key?(command)
|
|
40
|
+
@commands[command].call(args)
|
|
41
|
+
else
|
|
42
|
+
puts "Unknown command: #{command}"
|
|
43
|
+
puts "Run 'vat help' for available commands."
|
|
44
|
+
exit 1
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
# Show help information
|
|
51
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
52
|
+
def help_command(args)
|
|
53
|
+
topic = args[0]
|
|
54
|
+
|
|
55
|
+
case topic
|
|
56
|
+
when 'brands'
|
|
57
|
+
show_brands_help
|
|
58
|
+
when 'workflows'
|
|
59
|
+
show_workflows_help
|
|
60
|
+
when 'config'
|
|
61
|
+
show_config_help
|
|
62
|
+
when 'list'
|
|
63
|
+
show_list_help
|
|
64
|
+
when 's3-up', 's3-down', 's3-status', 's3-cleanup-remote', 's3-cleanup-local', 'archive', 'manifest'
|
|
65
|
+
show_s3_help(topic)
|
|
66
|
+
when 's3-cleanup', 'cleanup-local'
|
|
67
|
+
# Deprecated command names - show deprecation notice and new help
|
|
68
|
+
puts "⚠️ '#{topic}' is deprecated. Use the new command name instead:\n\n"
|
|
69
|
+
new_name = topic == 's3-cleanup' ? 's3-cleanup-remote' : 's3-cleanup-local'
|
|
70
|
+
show_s3_help(new_name)
|
|
71
|
+
else
|
|
72
|
+
show_main_help
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
76
|
+
|
|
77
|
+
# List brands and projects
|
|
78
|
+
def list_command(args)
|
|
79
|
+
args = args.reject { |arg| arg.start_with?('--') || arg.start_with?('-') }
|
|
80
|
+
|
|
81
|
+
brand_arg = args[0]
|
|
82
|
+
pattern_arg = args[1]
|
|
83
|
+
|
|
84
|
+
if brand_arg.nil?
|
|
85
|
+
# List all brands with summary
|
|
86
|
+
Appydave::Tools::Vat::ProjectListing.list_brands_with_counts
|
|
87
|
+
elsif pattern_arg
|
|
88
|
+
# Pattern matching
|
|
89
|
+
Appydave::Tools::Vat::ProjectListing.list_with_pattern(brand_arg, pattern_arg)
|
|
90
|
+
else
|
|
91
|
+
# Specific brand
|
|
92
|
+
Appydave::Tools::Vat::ProjectListing.list_brand_projects(brand_arg)
|
|
93
|
+
end
|
|
94
|
+
rescue StandardError => e
|
|
95
|
+
puts "❌ Error: #{e.message}"
|
|
96
|
+
exit 1
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# S3 Upload
|
|
100
|
+
def s3_up_command(args)
|
|
101
|
+
options = parse_s3_args(args, 's3-up')
|
|
102
|
+
s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
|
|
103
|
+
s3_ops.upload(dry_run: options[:dry_run])
|
|
104
|
+
rescue StandardError => e
|
|
105
|
+
puts "❌ Error: #{e.message}"
|
|
106
|
+
exit 1
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# S3 Download
|
|
110
|
+
def s3_down_command(args)
|
|
111
|
+
options = parse_s3_args(args, 's3-down')
|
|
112
|
+
s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
|
|
113
|
+
s3_ops.download(dry_run: options[:dry_run])
|
|
114
|
+
rescue StandardError => e
|
|
115
|
+
puts "❌ Error: #{e.message}"
|
|
116
|
+
exit 1
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# S3 Status
|
|
120
|
+
def s3_status_command(args)
|
|
121
|
+
options = parse_s3_args(args, 's3-status')
|
|
122
|
+
s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
|
|
123
|
+
s3_ops.status
|
|
124
|
+
rescue StandardError => e
|
|
125
|
+
puts "❌ Error: #{e.message}"
|
|
126
|
+
exit 1
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# S3 Cleanup Remote
|
|
130
|
+
def s3_cleanup_remote_command(args)
|
|
131
|
+
options = parse_s3_args(args, 's3-cleanup-remote')
|
|
132
|
+
s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
|
|
133
|
+
s3_ops.cleanup(force: options[:force], dry_run: options[:dry_run])
|
|
134
|
+
rescue StandardError => e
|
|
135
|
+
puts "❌ Error: #{e.message}"
|
|
136
|
+
exit 1
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# S3 Cleanup Local
|
|
140
|
+
def s3_cleanup_local_command(args)
|
|
141
|
+
options = parse_s3_args(args, 's3-cleanup-local')
|
|
142
|
+
s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
|
|
143
|
+
s3_ops.cleanup_local(force: options[:force], dry_run: options[:dry_run])
|
|
144
|
+
rescue StandardError => e
|
|
145
|
+
puts "❌ Error: #{e.message}"
|
|
146
|
+
exit 1
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Archive project to SSD
|
|
150
|
+
def archive_command(args)
|
|
151
|
+
options = parse_s3_args(args, 'archive')
|
|
152
|
+
s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
|
|
153
|
+
s3_ops.archive(force: options[:force], dry_run: options[:dry_run])
|
|
154
|
+
rescue StandardError => e
|
|
155
|
+
puts "❌ Error: #{e.message}"
|
|
156
|
+
exit 1
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Generate manifest
|
|
160
|
+
# rubocop:disable Metrics/MethodLength
|
|
161
|
+
def manifest_command(args)
|
|
162
|
+
all_brands = args.include?('--all')
|
|
163
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
164
|
+
brand_arg = args[0]
|
|
165
|
+
|
|
166
|
+
if all_brands
|
|
167
|
+
# Generate manifest for all brands
|
|
168
|
+
Appydave::Tools::Configuration::Config.configure
|
|
169
|
+
brands_config = Appydave::Tools::Configuration::Config.brands
|
|
170
|
+
|
|
171
|
+
brands_config.brands.each do |brand_info|
|
|
172
|
+
brand_key = brand_info.key
|
|
173
|
+
puts ''
|
|
174
|
+
puts '=' * 60
|
|
175
|
+
|
|
176
|
+
generator = Appydave::Tools::Vat::ManifestGenerator.new(brand_key)
|
|
177
|
+
generator.generate
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
puts ''
|
|
181
|
+
puts '=' * 60
|
|
182
|
+
puts '✅ All brand manifests generated!'
|
|
183
|
+
elsif brand_arg
|
|
184
|
+
# Generate manifest for specific brand
|
|
185
|
+
brand = Appydave::Tools::Vat::Config.expand_brand(brand_arg)
|
|
186
|
+
ENV['BRAND_PATH'] = Appydave::Tools::Vat::Config.brand_path(brand)
|
|
187
|
+
|
|
188
|
+
generator = Appydave::Tools::Vat::ManifestGenerator.new(brand_arg)
|
|
189
|
+
generator.generate
|
|
190
|
+
else
|
|
191
|
+
puts 'Usage: vat manifest <brand> [--all]'
|
|
192
|
+
puts ''
|
|
193
|
+
puts 'Examples:'
|
|
194
|
+
puts ' vat manifest appydave # Generate manifest for AppyDave brand'
|
|
195
|
+
puts ' vat manifest --all # Generate manifests for all brands'
|
|
196
|
+
exit 1
|
|
197
|
+
end
|
|
198
|
+
rescue StandardError => e
|
|
199
|
+
puts "❌ Error: #{e.message}"
|
|
200
|
+
exit 1
|
|
201
|
+
end
|
|
202
|
+
# rubocop:enable Metrics/MethodLength
|
|
203
|
+
|
|
204
|
+
# Parse S3 command arguments
|
|
205
|
+
def parse_s3_args(args, command)
|
|
206
|
+
dry_run = args.include?('--dry-run')
|
|
207
|
+
force = args.include?('--force')
|
|
208
|
+
args = args.reject { |arg| arg.start_with?('--') }
|
|
209
|
+
|
|
210
|
+
brand_arg = args[0]
|
|
211
|
+
project_arg = args[1]
|
|
212
|
+
|
|
213
|
+
if brand_arg.nil?
|
|
214
|
+
# Auto-detect from PWD
|
|
215
|
+
brand, project_id = Appydave::Tools::Vat::ProjectResolver.detect_from_pwd
|
|
216
|
+
if brand.nil? || project_id.nil?
|
|
217
|
+
puts '❌ Could not auto-detect brand/project from current directory'
|
|
218
|
+
puts "Usage: vat #{command} <brand> <project> [--dry-run]"
|
|
219
|
+
exit 1
|
|
220
|
+
end
|
|
221
|
+
brand_key = brand # Already detected, use as-is
|
|
222
|
+
else
|
|
223
|
+
brand_key = brand_arg # Use the shortcut/key (e.g., 'appydave')
|
|
224
|
+
brand = Appydave::Tools::Vat::Config.expand_brand(brand_arg) # Expand for path resolution
|
|
225
|
+
project_id = Appydave::Tools::Vat::ProjectResolver.resolve(brand_arg, project_arg)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Set ENV for compatibility with ConfigLoader
|
|
229
|
+
ENV['BRAND_PATH'] = Appydave::Tools::Vat::Config.brand_path(brand)
|
|
230
|
+
|
|
231
|
+
{ brand: brand_key, project: project_id, dry_run: dry_run, force: force }
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Help text methods
|
|
235
|
+
# rubocop:disable Metrics/MethodLength
|
|
236
|
+
def show_main_help
|
|
237
|
+
puts <<~HELP
|
|
238
|
+
VAT (Video Asset Tools) - Unified CLI for video project management
|
|
239
|
+
|
|
240
|
+
Usage: vat [command] [options]
|
|
241
|
+
|
|
242
|
+
Available Commands:
|
|
243
|
+
help [command] Show help information
|
|
244
|
+
list [brand] [pattern] List brands/projects
|
|
245
|
+
|
|
246
|
+
S3 Sync Commands:
|
|
247
|
+
s3-up <brand> <project> Upload to S3 staging
|
|
248
|
+
s3-down <brand> <project> Download from S3 staging
|
|
249
|
+
s3-status <brand> [project] Check sync status
|
|
250
|
+
s3-cleanup-remote <brand> <project> Delete S3 files
|
|
251
|
+
s3-cleanup-local <brand> <project> Delete local s3-staging files
|
|
252
|
+
|
|
253
|
+
Archive Commands:
|
|
254
|
+
archive <brand> <project> Copy project to SSD backup
|
|
255
|
+
manifest <brand> [--all] Generate project manifest
|
|
256
|
+
|
|
257
|
+
List Modes:
|
|
258
|
+
vat list All brands with counts/sizes
|
|
259
|
+
vat list appydave All projects for brand
|
|
260
|
+
vat list appydave 'b6*' Pattern matching
|
|
261
|
+
|
|
262
|
+
Help Topics:
|
|
263
|
+
vat help brands List available brands
|
|
264
|
+
vat help workflows Explain FliVideo vs Storyline workflows
|
|
265
|
+
vat help config Configuration file details
|
|
266
|
+
|
|
267
|
+
Examples:
|
|
268
|
+
vat list
|
|
269
|
+
vat s3-up appydave b65
|
|
270
|
+
vat s3-down voz boy-baker --dry-run
|
|
271
|
+
vat s3-status appydave b65
|
|
272
|
+
vat s3-cleanup appydave b65 --force
|
|
273
|
+
|
|
274
|
+
For more information: https://github.com/appydave/appydave-tools
|
|
275
|
+
HELP
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
def show_brands_help
|
|
279
|
+
puts <<~HELP
|
|
280
|
+
Available Brands
|
|
281
|
+
|
|
282
|
+
VAT supports multi-tenant video project management with brand shortcuts:
|
|
283
|
+
|
|
284
|
+
Brand Shortcuts:
|
|
285
|
+
appydave → v-appydave (AppyDave brand videos)
|
|
286
|
+
voz → v-voz (VOZ client videos)
|
|
287
|
+
aitldr → v-aitldr (AITLDR brand videos)
|
|
288
|
+
kiros → v-kiros (Kiros client videos)
|
|
289
|
+
joy → v-beauty-and-joy (Beauty & Joy brand)
|
|
290
|
+
ss → v-supportsignal (SupportSignal client)
|
|
291
|
+
|
|
292
|
+
Usage:
|
|
293
|
+
vat list # Show all brands
|
|
294
|
+
vat list --summary # Show brands with project counts
|
|
295
|
+
vat list appydave # List all AppyDave projects
|
|
296
|
+
vat s3-up voz boy-baker # Upload VOZ project
|
|
297
|
+
HELP
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def show_workflows_help
|
|
301
|
+
puts <<~HELP
|
|
302
|
+
Video Workflows
|
|
303
|
+
|
|
304
|
+
VAT supports two primary video content workflows:
|
|
305
|
+
|
|
306
|
+
1. FliVideo Workflow (AppyDave)
|
|
307
|
+
- Sequential chapter-based recording
|
|
308
|
+
- Projects follow pattern: [letter][number]-[name]
|
|
309
|
+
- Example: b65-guy-monroe-marketing-plan
|
|
310
|
+
- Short name support: b65 → b65-guy-monroe-marketing-plan
|
|
311
|
+
- Pattern matching: b6* → all projects b60-b69
|
|
312
|
+
|
|
313
|
+
2. Storyline Workflow (VOZ, AITLDR)
|
|
314
|
+
- Script-first content creation
|
|
315
|
+
- Projects use full descriptive names
|
|
316
|
+
- Example: boy-baker, the-point
|
|
317
|
+
- No short name expansion (exact match required)
|
|
318
|
+
|
|
319
|
+
Project Organization:
|
|
320
|
+
v-appydave/
|
|
321
|
+
├── b40-project-name/ # FliVideo pattern
|
|
322
|
+
├── b65-another-project/
|
|
323
|
+
└── archived/ # Completed projects
|
|
324
|
+
|
|
325
|
+
v-voz/
|
|
326
|
+
├── boy-baker/ # Storyline pattern
|
|
327
|
+
└── the-point/
|
|
328
|
+
|
|
329
|
+
Storage Strategy:
|
|
330
|
+
Local → S3 (90-day collaboration) → SSD (long-term archive)
|
|
331
|
+
HELP
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def show_config_help
|
|
335
|
+
puts <<~HELP
|
|
336
|
+
Configuration
|
|
337
|
+
|
|
338
|
+
VAT uses two configuration levels:
|
|
339
|
+
|
|
340
|
+
1. System Configuration (settings.json)
|
|
341
|
+
Location: ~/.config/appydave/settings.json
|
|
342
|
+
Purpose: Define root directory for all video projects
|
|
343
|
+
Format:
|
|
344
|
+
{
|
|
345
|
+
"video-projects-root": "/Users/yourname/dev/video-projects"
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
Setup:
|
|
349
|
+
ad_config -c # Create configuration
|
|
350
|
+
ad_config -e # Edit configuration
|
|
351
|
+
|
|
352
|
+
2. Brand Configuration (.video-tools.env)
|
|
353
|
+
Location: <brand-dir>/.video-tools.env
|
|
354
|
+
Purpose: AWS credentials and S3 settings per brand
|
|
355
|
+
Required Keys:
|
|
356
|
+
AWS_ACCESS_KEY_ID=xxx
|
|
357
|
+
AWS_SECRET_ACCESS_KEY=xxx
|
|
358
|
+
AWS_REGION=us-east-1
|
|
359
|
+
S3_BUCKET=your-bucket-name
|
|
360
|
+
SSD_BASE=/path/to/external/drive
|
|
361
|
+
|
|
362
|
+
Example:
|
|
363
|
+
v-appydave/.video-tools.env
|
|
364
|
+
v-voz/.video-tools.env
|
|
365
|
+
|
|
366
|
+
Directory Structure:
|
|
367
|
+
~/.config/appydave/
|
|
368
|
+
└── settings.json # System config
|
|
369
|
+
|
|
370
|
+
/Users/yourname/dev/video-projects/
|
|
371
|
+
├── v-appydave/
|
|
372
|
+
│ ├── .video-tools.env # Brand-specific config
|
|
373
|
+
│ └── b65-project/
|
|
374
|
+
└── v-voz/
|
|
375
|
+
├── .video-tools.env
|
|
376
|
+
└── boy-baker/
|
|
377
|
+
HELP
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
def show_list_help
|
|
381
|
+
puts <<~HELP
|
|
382
|
+
List Command
|
|
383
|
+
|
|
384
|
+
Usage: vat list [brand] [pattern]
|
|
385
|
+
|
|
386
|
+
Modes:
|
|
387
|
+
1. List all brands with summary:
|
|
388
|
+
vat list
|
|
389
|
+
|
|
390
|
+
2. List projects for specific brand:
|
|
391
|
+
vat list appydave
|
|
392
|
+
|
|
393
|
+
3. Pattern matching:
|
|
394
|
+
vat list appydave 'b6*' # All projects b60-b69
|
|
395
|
+
vat list appydave 'b4*' # All projects b40-b49
|
|
396
|
+
|
|
397
|
+
Examples:
|
|
398
|
+
vat list # Tabular: brand, project count, size, modified
|
|
399
|
+
vat list voz # Tabular: all VOZ projects with size/date
|
|
400
|
+
vat list appydave 'b6*' # Tabular: b60-b69 projects with size/date
|
|
401
|
+
HELP
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
405
|
+
def show_s3_help(command)
|
|
406
|
+
case command
|
|
407
|
+
when 's3-up'
|
|
408
|
+
puts <<~HELP
|
|
409
|
+
S3 Upload Command
|
|
410
|
+
|
|
411
|
+
Upload files from local s3-staging/ directory to S3 for collaboration.
|
|
412
|
+
|
|
413
|
+
Usage: vat s3-up <brand> <project> [--dry-run]
|
|
414
|
+
|
|
415
|
+
Features:
|
|
416
|
+
- Smart sync: Skips unchanged files (MD5 comparison)
|
|
417
|
+
- Progress tracking: Shows uploaded/skipped/failed counts
|
|
418
|
+
- Dry-run support: Preview changes without uploading
|
|
419
|
+
|
|
420
|
+
Examples:
|
|
421
|
+
vat s3-up appydave b65 # Upload b65 project
|
|
422
|
+
vat s3-up voz boy-baker --dry-run # Preview upload
|
|
423
|
+
vat s3-up # Auto-detect from PWD
|
|
424
|
+
|
|
425
|
+
Notes:
|
|
426
|
+
- Files must be in project's s3-staging/ directory
|
|
427
|
+
- Requires AWS credentials in .video-tools.env
|
|
428
|
+
- S3 path: staging/<brand>/<project>/
|
|
429
|
+
HELP
|
|
430
|
+
when 's3-down'
|
|
431
|
+
puts <<~HELP
|
|
432
|
+
S3 Download Command
|
|
433
|
+
|
|
434
|
+
Download files from S3 to local s3-staging/ directory.
|
|
435
|
+
|
|
436
|
+
Usage: vat s3-down <brand> <project> [--dry-run]
|
|
437
|
+
|
|
438
|
+
Features:
|
|
439
|
+
- Smart sync: Skips unchanged files (MD5 comparison)
|
|
440
|
+
- Progress tracking: Shows downloaded/skipped/failed counts
|
|
441
|
+
- Dry-run support: Preview changes without downloading
|
|
442
|
+
|
|
443
|
+
Examples:
|
|
444
|
+
vat s3-down appydave b65 # Download b65 project
|
|
445
|
+
vat s3-down voz boy-baker --dry-run # Preview download
|
|
446
|
+
vat s3-down # Auto-detect from PWD
|
|
447
|
+
|
|
448
|
+
Notes:
|
|
449
|
+
- Creates s3-staging/ directory if needed
|
|
450
|
+
- Requires AWS credentials in .video-tools.env
|
|
451
|
+
HELP
|
|
452
|
+
when 's3-status'
|
|
453
|
+
puts <<~HELP
|
|
454
|
+
S3 Status Command
|
|
455
|
+
|
|
456
|
+
Check sync status between local and S3 files.
|
|
457
|
+
|
|
458
|
+
Usage: vat s3-status <brand> [project]
|
|
459
|
+
|
|
460
|
+
Features:
|
|
461
|
+
- Shows all files (S3 and local)
|
|
462
|
+
- Indicates sync status: [synced], [modified], [S3 only], [local only]
|
|
463
|
+
- Displays file sizes and totals
|
|
464
|
+
- Shows file counts for both S3 and local
|
|
465
|
+
|
|
466
|
+
Examples:
|
|
467
|
+
vat s3-status appydave b65 # Check b65 status
|
|
468
|
+
vat s3-status # Auto-detect from PWD
|
|
469
|
+
|
|
470
|
+
Status Indicators:
|
|
471
|
+
✓ [synced] - Local and S3 match (MD5)
|
|
472
|
+
⚠️ [modified] - Files differ between local and S3
|
|
473
|
+
☁️ [S3 only] - File only in S3, not present locally
|
|
474
|
+
📁 [local only] - File only local, not uploaded to S3
|
|
475
|
+
HELP
|
|
476
|
+
when 's3-cleanup-remote'
|
|
477
|
+
puts <<~HELP
|
|
478
|
+
S3 Cleanup Remote Command
|
|
479
|
+
|
|
480
|
+
Delete all S3 files for a project (use with caution).
|
|
481
|
+
|
|
482
|
+
Usage: vat s3-cleanup-remote <brand> <project> --force [--dry-run]
|
|
483
|
+
|
|
484
|
+
Features:
|
|
485
|
+
- Requires --force flag for safety
|
|
486
|
+
- Dry-run support: Preview deletions
|
|
487
|
+
- Shows deleted/failed counts
|
|
488
|
+
|
|
489
|
+
Examples:
|
|
490
|
+
vat s3-cleanup-remote appydave b65 --dry-run # Preview deletion
|
|
491
|
+
vat s3-cleanup-remote appydave b65 --force # Actually delete
|
|
492
|
+
vat s3-cleanup-remote --force # Auto-detect from PWD
|
|
493
|
+
|
|
494
|
+
⚠️ WARNING: This permanently deletes files from S3.
|
|
495
|
+
Ensure you have local backups before running.
|
|
496
|
+
|
|
497
|
+
Note: Old command 's3-cleanup' still works but is deprecated.
|
|
498
|
+
HELP
|
|
499
|
+
when 's3-cleanup-local'
|
|
500
|
+
puts <<~HELP
|
|
501
|
+
S3 Cleanup Local Command
|
|
502
|
+
|
|
503
|
+
Delete all local files in the s3-staging/ directory for a project.
|
|
504
|
+
|
|
505
|
+
Usage: vat s3-cleanup-local <brand> <project> --force [--dry-run]
|
|
506
|
+
|
|
507
|
+
Features:
|
|
508
|
+
- Requires --force flag for safety
|
|
509
|
+
- Dry-run support: Preview deletions
|
|
510
|
+
- Removes empty directories after cleanup
|
|
511
|
+
- Shows deleted/failed counts
|
|
512
|
+
|
|
513
|
+
Examples:
|
|
514
|
+
vat s3-cleanup-local appydave b65 --dry-run # Preview deletion
|
|
515
|
+
vat s3-cleanup-local appydave b65 --force # Actually delete
|
|
516
|
+
vat s3-cleanup-local --force # Auto-detect from PWD
|
|
517
|
+
|
|
518
|
+
Use Cases:
|
|
519
|
+
- Free up disk space after uploading to S3
|
|
520
|
+
- Clean up after completing collaboration
|
|
521
|
+
- Remove local staging files when project is archived
|
|
522
|
+
|
|
523
|
+
⚠️ NOTE: This only deletes LOCAL files in s3-staging/.
|
|
524
|
+
Files in S3 are NOT affected. Use 's3-cleanup-remote' for that.
|
|
525
|
+
|
|
526
|
+
Note: Old command 'cleanup-local' still works but is deprecated.
|
|
527
|
+
HELP
|
|
528
|
+
when 'archive'
|
|
529
|
+
puts <<~HELP
|
|
530
|
+
Archive Command
|
|
531
|
+
|
|
532
|
+
Copy completed video project to SSD for long-term backup.
|
|
533
|
+
|
|
534
|
+
Usage: vat archive <brand> <project> [--force] [--dry-run]
|
|
535
|
+
|
|
536
|
+
Features:
|
|
537
|
+
- Copies entire project directory to SSD backup location
|
|
538
|
+
- Verifies SSD is mounted before archiving
|
|
539
|
+
- Shows project size before copying
|
|
540
|
+
- Optional: Delete local copy after successful archive (--force)
|
|
541
|
+
- Dry-run support: Preview archive operation
|
|
542
|
+
|
|
543
|
+
Examples:
|
|
544
|
+
vat archive appydave b63 --dry-run # Preview archive
|
|
545
|
+
vat archive appydave b63 # Copy to SSD only
|
|
546
|
+
vat archive appydave b63 --force # Copy and delete local
|
|
547
|
+
vat archive # Auto-detect from PWD
|
|
548
|
+
|
|
549
|
+
Storage Strategy:
|
|
550
|
+
Local → S3 (90-day collaboration) → SSD (long-term archive)
|
|
551
|
+
|
|
552
|
+
Use Cases:
|
|
553
|
+
- Archive completed and published projects
|
|
554
|
+
- Free up local disk space for new projects
|
|
555
|
+
- Long-term backup before removing from S3
|
|
556
|
+
|
|
557
|
+
⚠️ NOTE: Without --force, the local project is NOT deleted.
|
|
558
|
+
Use --force only after verifying SSD copy is successful.
|
|
559
|
+
|
|
560
|
+
Configuration:
|
|
561
|
+
- SSD backup path configured per brand in brands.json
|
|
562
|
+
- Example: "ssd_backup": "/Volumes/T7/youtube-PUBLISHED/appydave"
|
|
563
|
+
HELP
|
|
564
|
+
when 'manifest'
|
|
565
|
+
puts <<~HELP
|
|
566
|
+
Manifest Command
|
|
567
|
+
|
|
568
|
+
Generate a JSON manifest of all video projects for a brand.
|
|
569
|
+
|
|
570
|
+
Usage: vat manifest <brand> [--all]
|
|
571
|
+
|
|
572
|
+
Features:
|
|
573
|
+
- Scans local and SSD storage locations
|
|
574
|
+
- Tracks project distribution (local, SSD, both)
|
|
575
|
+
- Identifies heavy files (video) vs light files (subtitles, images)
|
|
576
|
+
- Calculates disk usage statistics
|
|
577
|
+
- Validates project ID formats
|
|
578
|
+
- Outputs projects.json in brand directory
|
|
579
|
+
|
|
580
|
+
Examples:
|
|
581
|
+
vat manifest appydave # Generate manifest for AppyDave
|
|
582
|
+
vat manifest voz # Generate manifest for VOZ
|
|
583
|
+
vat manifest --all # Generate manifests for all brands
|
|
584
|
+
|
|
585
|
+
Output Location:
|
|
586
|
+
- Single brand: <brand-path>/projects.json
|
|
587
|
+
- All brands: Each brand gets its own manifest file
|
|
588
|
+
|
|
589
|
+
Manifest Structure:
|
|
590
|
+
{
|
|
591
|
+
"config": {
|
|
592
|
+
"brand": "appydave",
|
|
593
|
+
"local_base": "/path/to/v-appydave",
|
|
594
|
+
"ssd_base": "/Volumes/T7/youtube-PUBLISHED/appydave",
|
|
595
|
+
"last_updated": "2025-11-09T23:00:00Z",
|
|
596
|
+
"disk_usage": { ... }
|
|
597
|
+
},
|
|
598
|
+
"projects": [
|
|
599
|
+
{
|
|
600
|
+
"id": "b65-guy-monroe-marketing-plan",
|
|
601
|
+
"storage": {
|
|
602
|
+
"ssd": { "exists": true, "path": "b65-guy-monroe-marketing-plan" },
|
|
603
|
+
"local": { "exists": true, "has_heavy_files": true, "has_light_files": true }
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
]
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
Use Cases:
|
|
610
|
+
- Track which projects are archived to SSD
|
|
611
|
+
- Identify projects with only light files (archived locally)
|
|
612
|
+
- Generate disk usage reports
|
|
613
|
+
- Validate project naming conventions
|
|
614
|
+
- Prepare for sync-ssd operations
|
|
615
|
+
HELP
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
619
|
+
# rubocop:enable Metrics/MethodLength
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
# Run CLI
|
|
623
|
+
VatCLI.new.run if $PROGRAM_NAME == __FILE__
|