gitarsenal-cli 1.3.4 โ†’ 1.3.5

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitarsenal-cli",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -3372,7 +3372,6 @@ if __name__ == "__main__":
3372
3372
  parser.add_argument('--timeout', type=int, default=60, help='Container timeout in minutes (default: 60)')
3373
3373
  parser.add_argument('--ssh-password', type=str, help='SSH password (random if not provided)')
3374
3374
  parser.add_argument('--use-api', action='store_true', help='Fetch setup commands from API')
3375
- parser.add_argument('--interactive', action='store_true', help='Run in interactive mode with prompts')
3376
3375
  parser.add_argument('--show-examples', action='store_true', help='Show usage examples')
3377
3376
 
3378
3377
  args = parser.parse_args()
@@ -3381,101 +3380,124 @@ if __name__ == "__main__":
3381
3380
  if len(sys.argv) == 1 or args.show_examples:
3382
3381
  show_usage_examples()
3383
3382
  sys.exit(0)
3384
-
3385
- # Get setup commands from file if specified
3386
- setup_commands = args.setup_commands or []
3387
-
3388
- # If --use-api flag is set and repo_url is provided, fetch setup commands from API
3389
-
3390
- # If --use-api flag is set and repo_url is provided, fetch setup commands from API
3391
- if args.use_api and args.repo_url:
3392
- print("๐Ÿ”„ Using API to fetch setup commands")
3393
- api_commands = fetch_setup_commands_from_api(args.repo_url)
3394
- if api_commands:
3395
- setup_commands = api_commands
3396
- print(f"๐Ÿ“‹ Using {len(setup_commands)} commands from API")
3397
- else:
3398
- print("โš ๏ธ Failed to get commands from API, no fallback commands will be used")
3399
- # Do not fall back to basic setup commands
3400
- setup_commands = []
3401
3383
 
3402
- # Parse setup commands from JSON if provided
3403
- if args.setup_commands_json:
3404
- try:
3405
- json_commands = json.loads(args.setup_commands_json)
3406
- if isinstance(json_commands, list):
3407
- setup_commands = json_commands
3408
- print(f"๐Ÿ“‹ Parsed {len(setup_commands)} commands from JSON:")
3409
- for i, cmd in enumerate(setup_commands, 1):
3410
- print(f" {i}. {cmd}")
3384
+ try:
3385
+ # Get setup commands from file if specified
3386
+ setup_commands = args.setup_commands or []
3387
+
3388
+ # If --use-api flag is set and repo_url is provided, fetch setup commands from API
3389
+
3390
+ # If --use-api flag is set and repo_url is provided, fetch setup commands from API
3391
+ if args.use_api and args.repo_url:
3392
+ print("๐Ÿ”„ Using API to fetch setup commands")
3393
+ api_commands = fetch_setup_commands_from_api(args.repo_url)
3394
+ if api_commands:
3395
+ setup_commands = api_commands
3396
+ print(f"๐Ÿ“‹ Using {len(setup_commands)} commands from API")
3411
3397
  else:
3412
- print(f"โš ๏ธ Invalid JSON format for setup commands: not a list")
3413
- except json.JSONDecodeError as e:
3414
- print(f"โš ๏ธ Error parsing JSON setup commands: {e}")
3415
- print(f"Received JSON string: {args.setup_commands_json}")
3416
-
3417
- # Print received setup commands for debugging
3418
- if setup_commands:
3419
- print(f"๐Ÿ“‹ Using {len(setup_commands)} setup commands:")
3420
- for i, cmd in enumerate(setup_commands, 1):
3421
- print(f" {i}. {cmd}")
3422
-
3423
- # Load commands from file if specified
3424
- if args.commands_file and os.path.exists(args.commands_file):
3425
- try:
3426
- with open(args.commands_file, 'r') as f:
3427
- # Check if the file contains JSON or line-by-line commands
3428
- content = f.read().strip()
3398
+ print("โš ๏ธ Failed to get commands from API, no fallback commands will be used")
3399
+ # Do not fall back to basic setup commands
3400
+ setup_commands = []
3401
+
3402
+ # Parse setup commands from JSON if provided
3403
+ if args.setup_commands_json:
3404
+ try:
3405
+ json_commands = json.loads(args.setup_commands_json)
3406
+ if isinstance(json_commands, list):
3407
+ setup_commands = json_commands
3408
+ print(f"๐Ÿ“‹ Parsed {len(setup_commands)} commands from JSON:")
3409
+ for i, cmd in enumerate(setup_commands, 1):
3410
+ print(f" {i}. {cmd}")
3411
+ else:
3412
+ print(f"โš ๏ธ Invalid JSON format for setup commands: not a list")
3413
+ except json.JSONDecodeError as e:
3414
+ print(f"โš ๏ธ Error parsing JSON setup commands: {e}")
3415
+ print(f"Received JSON string: {args.setup_commands_json}")
3416
+
3417
+ # Print received setup commands for debugging
3418
+ if setup_commands:
3419
+ print(f"๐Ÿ“‹ Using {len(setup_commands)} setup commands:")
3420
+ for i, cmd in enumerate(setup_commands, 1):
3421
+ print(f" {i}. {cmd}")
3429
3422
 
3430
- if content.startswith('[') and content.endswith(']'):
3431
- # JSON format
3432
- try:
3433
- json_commands = json.loads(content)
3434
- if isinstance(json_commands, list):
3435
- setup_commands.extend(json_commands)
3436
- print(f"๐Ÿ“‹ Loaded {len(json_commands)} commands from JSON file {args.commands_file}")
3437
- else:
3438
- print(f"โš ๏ธ Invalid JSON format in commands file: not a list")
3439
- except json.JSONDecodeError as json_err:
3440
- print(f"โš ๏ธ Error parsing JSON commands file: {json_err}")
3441
- # Fall back to line-by-line parsing
3423
+ # Load commands from file if specified
3424
+ if args.commands_file and os.path.exists(args.commands_file):
3425
+ try:
3426
+ with open(args.commands_file, 'r') as f:
3427
+ # Check if the file contains JSON or line-by-line commands
3428
+ content = f.read().strip()
3429
+
3430
+ if content.startswith('[') and content.endswith(']'):
3431
+ # JSON format
3432
+ try:
3433
+ json_commands = json.loads(content)
3434
+ if isinstance(json_commands, list):
3435
+ setup_commands.extend(json_commands)
3436
+ print(f"๐Ÿ“‹ Loaded {len(json_commands)} commands from JSON file {args.commands_file}")
3437
+ else:
3438
+ print(f"โš ๏ธ Invalid JSON format in commands file: not a list")
3439
+ except json.JSONDecodeError as json_err:
3440
+ print(f"โš ๏ธ Error parsing JSON commands file: {json_err}")
3441
+ # Fall back to line-by-line parsing
3442
+ file_commands = [line.strip() for line in content.split('\n') if line.strip()]
3443
+ setup_commands.extend(file_commands)
3444
+ print(f"๐Ÿ“‹ Loaded {len(file_commands)} commands from file (line-by-line fallback)")
3445
+ else:
3446
+ # Line-by-line format
3442
3447
  file_commands = [line.strip() for line in content.split('\n') if line.strip()]
3443
3448
  setup_commands.extend(file_commands)
3444
- print(f"๐Ÿ“‹ Loaded {len(file_commands)} commands from file (line-by-line fallback)")
3445
- else:
3446
- # Line-by-line format
3447
- file_commands = [line.strip() for line in content.split('\n') if line.strip()]
3448
- setup_commands.extend(file_commands)
3449
- print(f"๐Ÿ“‹ Loaded {len(file_commands)} commands from file (line-by-line format)")
3450
-
3451
- except Exception as e:
3452
- print(f"โš ๏ธ Error reading commands file: {e}")
3453
-
3454
- try:
3455
- result = create_modal_ssh_container(
3456
- args.gpu,
3457
- args.repo_url,
3458
- args.repo_name,
3459
- setup_commands,
3460
- getattr(args, 'volume_name', None),
3461
- args.timeout,
3462
- args.ssh_password
3463
- )
3449
+ print(f"๐Ÿ“‹ Loaded {len(file_commands)} commands from file (line-by-line format)")
3450
+ except Exception as e:
3451
+ print(f"โš ๏ธ Error loading commands from file: {e}")
3464
3452
 
3465
- print("\nโณ Keeping the SSH container alive. Press Ctrl+C to exit (container will continue running)...")
3466
- try:
3467
- while True:
3468
- time.sleep(90)
3469
- print(".", end="", flush=True)
3470
- except KeyboardInterrupt:
3471
- print("\n๐Ÿ‘‹ Script exited. The SSH container will continue running.")
3472
- sys.exit(0)
3473
-
3453
+ # Load commands from setup script if specified
3454
+ if args.setup_script and os.path.exists(args.setup_script):
3455
+ try:
3456
+ with open(args.setup_script, 'r') as f:
3457
+ script_content = f.read().strip()
3458
+ # Convert script to individual commands
3459
+ script_commands = [line.strip() for line in script_content.split('\n')
3460
+ if line.strip() and not line.strip().startswith('#')]
3461
+ setup_commands.extend(script_commands)
3462
+ print(f"๐Ÿ“‹ Loaded {len(script_commands)} commands from script {args.setup_script}")
3463
+ except Exception as e:
3464
+ print(f"โš ๏ธ Error loading commands from script: {e}")
3465
+
3466
+ # Create the container with the specified options
3467
+ if args.ssh_password:
3468
+ print(f"๐Ÿ”‘ Using provided SSH password")
3469
+ ssh_password = args.ssh_password
3470
+ else:
3471
+ ssh_password = generate_random_password()
3472
+ print(f"๐Ÿ”‘ Generated random SSH password: {ssh_password}")
3473
+
3474
+ # Extract repository name from URL if not provided
3475
+ repo_name = args.repo_name
3476
+ if not repo_name and args.repo_url:
3477
+ # Try to extract repo name from URL
3478
+ url_parts = args.repo_url.rstrip('/').split('/')
3479
+ if url_parts:
3480
+ repo_name = url_parts[-1]
3481
+ if repo_name.endswith('.git'):
3482
+ repo_name = repo_name[:-4]
3483
+
3484
+ # Create the container
3485
+ create_modal_ssh_container(
3486
+ gpu_type=args.gpu,
3487
+ repo_url=args.repo_url,
3488
+ repo_name=repo_name,
3489
+ setup_commands=setup_commands,
3490
+ volume_name=args.volume_name,
3491
+ timeout_minutes=args.timeout,
3492
+ ssh_password=ssh_password
3493
+ )
3474
3494
  except KeyboardInterrupt:
3475
- # Handle Ctrl+C during container creation
3476
- print("\n๐Ÿ‘‹ Script interrupted during container creation.")
3477
- print("๐Ÿ“ You may need to check if a container was created with: modal container list")
3478
- sys.exit(0)
3495
+ print("\n\n๐Ÿ›‘ Execution interrupted")
3496
+ print("๐Ÿงน Cleaning up resources...")
3497
+ cleanup_modal_token()
3498
+ sys.exit(1)
3479
3499
  except Exception as e:
3480
- print(f"โŒ Error: {e}")
3500
+ print(f"\nโŒ Error: {e}")
3501
+ print("๐Ÿงน Cleaning up resources...")
3502
+ cleanup_modal_token()
3481
3503
  sys.exit(1)