chipfoundry-cli 2.2.2__tar.gz → 2.3.1__tar.gz
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.
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/PKG-INFO +1 -1
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/chipfoundry_cli/main.py +95 -32
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/pyproject.toml +1 -1
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/LICENSE +0 -0
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/README.md +0 -0
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/chipfoundry_cli/__init__.py +0 -0
- {chipfoundry_cli-2.2.2 → chipfoundry_cli-2.3.1}/chipfoundry_cli/utils.py +0 -0
|
@@ -323,7 +323,16 @@ def init(project_root, shuttle, description):
|
|
|
323
323
|
config = load_user_config()
|
|
324
324
|
username = config.get("sftp_username")
|
|
325
325
|
if not username:
|
|
326
|
-
|
|
326
|
+
try:
|
|
327
|
+
me = _api_get("/auth/cli/whoami")
|
|
328
|
+
username = me.get("sftp_username")
|
|
329
|
+
if username:
|
|
330
|
+
config["sftp_username"] = username
|
|
331
|
+
save_user_config(config)
|
|
332
|
+
except SystemExit:
|
|
333
|
+
pass
|
|
334
|
+
if not username:
|
|
335
|
+
console.print("[bold red]No SFTP account linked to your platform account. Please run 'cf login' first.[/bold red]")
|
|
327
336
|
raise click.Abort()
|
|
328
337
|
|
|
329
338
|
gds_dir = Path(project_root) / 'gds'
|
|
@@ -1313,10 +1322,14 @@ def push(project_root, sftp_host, sftp_username, sftp_key, project_id, project_n
|
|
|
1313
1322
|
console.print("Run [bold]cf login[/bold] to authenticate before pushing.")
|
|
1314
1323
|
raise click.Abort()
|
|
1315
1324
|
if not sftp_username:
|
|
1316
|
-
|
|
1325
|
+
me = _api_get("/auth/cli/whoami")
|
|
1326
|
+
sftp_username = me.get("sftp_username")
|
|
1317
1327
|
if not sftp_username:
|
|
1318
|
-
console.print("[bold red]No SFTP
|
|
1328
|
+
console.print("[bold red]No SFTP account linked to your platform account.[/bold red]")
|
|
1329
|
+
console.print("Contact support or provide --sftp-username.")
|
|
1319
1330
|
raise click.Abort()
|
|
1331
|
+
config["sftp_username"] = sftp_username
|
|
1332
|
+
save_user_config(config)
|
|
1320
1333
|
if not sftp_key:
|
|
1321
1334
|
sftp_key = config.get("sftp_key")
|
|
1322
1335
|
|
|
@@ -1495,10 +1508,14 @@ def pull(project_name, output_dir, sftp_host, sftp_username, sftp_key):
|
|
|
1495
1508
|
console.print("Run [bold]cf login[/bold] to authenticate before pulling.")
|
|
1496
1509
|
raise click.Abort()
|
|
1497
1510
|
if not sftp_username:
|
|
1498
|
-
|
|
1511
|
+
me = _api_get("/auth/cli/whoami")
|
|
1512
|
+
sftp_username = me.get("sftp_username")
|
|
1499
1513
|
if not sftp_username:
|
|
1500
|
-
console.print("[bold red]No SFTP
|
|
1514
|
+
console.print("[bold red]No SFTP account linked to your platform account.[/bold red]")
|
|
1515
|
+
console.print("Contact support or provide --sftp-username.")
|
|
1501
1516
|
raise click.Abort()
|
|
1517
|
+
config["sftp_username"] = sftp_username
|
|
1518
|
+
save_user_config(config)
|
|
1502
1519
|
if not sftp_key:
|
|
1503
1520
|
sftp_key = config.get("sftp_key")
|
|
1504
1521
|
|
|
@@ -1751,10 +1768,14 @@ def status(sftp_host, sftp_username, sftp_key, json_output, show_all):
|
|
|
1751
1768
|
if not platform_id:
|
|
1752
1769
|
console.print("[dim]Tip: Run [bold]cf link[/bold] to connect this project to the platform.[/dim]\n")
|
|
1753
1770
|
if not sftp_username:
|
|
1754
|
-
|
|
1771
|
+
me = _api_get("/auth/cli/whoami")
|
|
1772
|
+
sftp_username = me.get("sftp_username")
|
|
1755
1773
|
if not sftp_username:
|
|
1756
|
-
console.print("[red]No SFTP
|
|
1774
|
+
console.print("[red]No SFTP account linked to your platform account.[/red]")
|
|
1775
|
+
console.print("Contact support or provide --sftp-username.")
|
|
1757
1776
|
raise click.Abort()
|
|
1777
|
+
config["sftp_username"] = sftp_username
|
|
1778
|
+
save_user_config(config)
|
|
1758
1779
|
if not sftp_key:
|
|
1759
1780
|
sftp_key = config.get("sftp_key")
|
|
1760
1781
|
|
|
@@ -1885,10 +1906,14 @@ def tapeouts(sftp_host, sftp_username, sftp_key, limit, days):
|
|
|
1885
1906
|
"""Show all tapeout runs (archived projects) with their timestamps."""
|
|
1886
1907
|
config = load_user_config()
|
|
1887
1908
|
if not sftp_username:
|
|
1888
|
-
|
|
1909
|
+
me = _api_get("/auth/cli/whoami")
|
|
1910
|
+
sftp_username = me.get("sftp_username")
|
|
1889
1911
|
if not sftp_username:
|
|
1890
|
-
console.print("[red]No SFTP
|
|
1912
|
+
console.print("[red]No SFTP account linked to your platform account.[/red]")
|
|
1913
|
+
console.print("Contact support or provide --sftp-username.")
|
|
1891
1914
|
raise click.Abort()
|
|
1915
|
+
config["sftp_username"] = sftp_username
|
|
1916
|
+
save_user_config(config)
|
|
1892
1917
|
if not sftp_key:
|
|
1893
1918
|
sftp_key = config.get("sftp_key")
|
|
1894
1919
|
|
|
@@ -2071,10 +2096,14 @@ def confirm(project_root, sftp_host, sftp_username, sftp_key, project_name):
|
|
|
2071
2096
|
# Load user config for defaults
|
|
2072
2097
|
config = load_user_config()
|
|
2073
2098
|
if not sftp_username:
|
|
2074
|
-
|
|
2099
|
+
me = _api_get("/auth/cli/whoami")
|
|
2100
|
+
sftp_username = me.get("sftp_username")
|
|
2075
2101
|
if not sftp_username:
|
|
2076
|
-
console.print("[bold red]No SFTP
|
|
2102
|
+
console.print("[bold red]No SFTP account linked to your platform account.[/bold red]")
|
|
2103
|
+
console.print("Contact support or provide --sftp-username.")
|
|
2077
2104
|
raise click.Abort()
|
|
2105
|
+
config["sftp_username"] = sftp_username
|
|
2106
|
+
save_user_config(config)
|
|
2078
2107
|
if not sftp_key:
|
|
2079
2108
|
sftp_key = config.get("sftp_key")
|
|
2080
2109
|
|
|
@@ -3191,6 +3220,28 @@ def repo_update(project_root, repo_owner, repo_name, branch, dry_run):
|
|
|
3191
3220
|
raise click.Abort()
|
|
3192
3221
|
|
|
3193
3222
|
|
|
3223
|
+
def _upload_precheck_results(project_json_path: Path):
|
|
3224
|
+
"""Upload precheck results to the platform (best-effort, never fatal)."""
|
|
3225
|
+
try:
|
|
3226
|
+
with open(project_json_path, "r") as f:
|
|
3227
|
+
pj = json.load(f)
|
|
3228
|
+
precheck_blob = pj.get("precheck")
|
|
3229
|
+
if not precheck_blob:
|
|
3230
|
+
return
|
|
3231
|
+
platform_id = pj.get("project", {}).get("platform_project_id")
|
|
3232
|
+
if not platform_id:
|
|
3233
|
+
return
|
|
3234
|
+
config = load_user_config()
|
|
3235
|
+
if not config.get("api_key"):
|
|
3236
|
+
return
|
|
3237
|
+
_api_put(f"/projects/{platform_id}", {"precheck_results": precheck_blob})
|
|
3238
|
+
console.print("[green]✓ Precheck results synced to platform[/green]")
|
|
3239
|
+
except SystemExit:
|
|
3240
|
+
console.print("[yellow]⚠ Precheck results could not be synced to platform[/yellow]")
|
|
3241
|
+
except Exception:
|
|
3242
|
+
console.print("[yellow]⚠ Precheck results could not be synced to platform[/yellow]")
|
|
3243
|
+
|
|
3244
|
+
|
|
3194
3245
|
@main.command('precheck')
|
|
3195
3246
|
@click.option('--project-root', type=click.Path(exists=True, file_okay=False), help='Path to the project directory (defaults to current directory)')
|
|
3196
3247
|
@click.option('--skip-checks', multiple=True, help='Checks to skip (can be specified multiple times)')
|
|
@@ -3275,10 +3326,11 @@ def precheck(project_root, skip_checks, magic_drc, checks, dry_run):
|
|
|
3275
3326
|
if checks:
|
|
3276
3327
|
precheck_args.extend(list(checks))
|
|
3277
3328
|
|
|
3278
|
-
inner_cmd = 'pip3 install --upgrade -q --root-user-action=ignore cf-precheck 2>/dev/null && cf-precheck ' + ' '.join(precheck_args)
|
|
3329
|
+
inner_cmd = 'pip3 install --upgrade -q --root-user-action=ignore cf-precheck 2>/dev/null && exec cf-precheck ' + ' '.join(precheck_args)
|
|
3279
3330
|
|
|
3280
3331
|
docker_cmd = [
|
|
3281
|
-
'docker', 'run', '--rm',
|
|
3332
|
+
'docker', 'run', '--rm', '--init',
|
|
3333
|
+
'--platform', 'linux/amd64',
|
|
3282
3334
|
'-v', f'{project_root_path}:{project_root_path}',
|
|
3283
3335
|
'-v', f'{pdk_root}:{pdk_root}',
|
|
3284
3336
|
'-e', f'PDK_ROOT={pdk_root}',
|
|
@@ -3309,7 +3361,7 @@ def precheck(project_root, skip_checks, magic_drc, checks, dry_run):
|
|
|
3309
3361
|
console.print(f"[cyan]Checking for Docker image updates...[/cyan]")
|
|
3310
3362
|
try:
|
|
3311
3363
|
subprocess.run(
|
|
3312
|
-
['docker', 'pull', docker_image],
|
|
3364
|
+
['docker', 'pull', '--platform', 'linux/amd64', docker_image],
|
|
3313
3365
|
check=True,
|
|
3314
3366
|
capture_output=True,
|
|
3315
3367
|
)
|
|
@@ -3328,11 +3380,7 @@ def precheck(project_root, skip_checks, magic_drc, checks, dry_run):
|
|
|
3328
3380
|
console.print("[cyan]Running cf-precheck...[/cyan]\n")
|
|
3329
3381
|
|
|
3330
3382
|
try:
|
|
3331
|
-
process = subprocess.Popen(
|
|
3332
|
-
docker_cmd,
|
|
3333
|
-
preexec_fn=os.setsid if os.name != 'nt' else None
|
|
3334
|
-
)
|
|
3335
|
-
|
|
3383
|
+
process = subprocess.Popen(docker_cmd)
|
|
3336
3384
|
returncode = process.wait()
|
|
3337
3385
|
|
|
3338
3386
|
console.print("")
|
|
@@ -3343,22 +3391,20 @@ def precheck(project_root, skip_checks, magic_drc, checks, dry_run):
|
|
|
3343
3391
|
sys.exit(130)
|
|
3344
3392
|
else:
|
|
3345
3393
|
console.print(f"[red]✗[/red] Precheck failed (exit code {returncode})")
|
|
3394
|
+
|
|
3395
|
+
_upload_precheck_results(project_json_path)
|
|
3396
|
+
|
|
3397
|
+
if returncode != 0:
|
|
3346
3398
|
sys.exit(returncode)
|
|
3347
3399
|
|
|
3348
3400
|
except KeyboardInterrupt:
|
|
3349
3401
|
console.print("\n[yellow]⚠[/yellow] Precheck interrupted by user")
|
|
3350
3402
|
try:
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
process.wait(timeout=5)
|
|
3357
|
-
except Exception:
|
|
3358
|
-
if os.name != 'nt':
|
|
3359
|
-
os.killpg(os.getpgid(process.pid), signal.SIGKILL)
|
|
3360
|
-
else:
|
|
3361
|
-
process.kill()
|
|
3403
|
+
process.terminate()
|
|
3404
|
+
process.wait(timeout=10)
|
|
3405
|
+
except (subprocess.TimeoutExpired, Exception):
|
|
3406
|
+
process.kill()
|
|
3407
|
+
sys.exit(130)
|
|
3362
3408
|
except Exception as e:
|
|
3363
3409
|
console.print(f"\n[red]✗[/red] Error running precheck: {e}")
|
|
3364
3410
|
|
|
@@ -3708,7 +3754,7 @@ def _api_put(path: str, json_data: dict):
|
|
|
3708
3754
|
client.close()
|
|
3709
3755
|
|
|
3710
3756
|
|
|
3711
|
-
_SYNC_KEEP_KEYS = {"project", "tapeout"}
|
|
3757
|
+
_SYNC_KEEP_KEYS = {"project", "tapeout", "precheck"}
|
|
3712
3758
|
|
|
3713
3759
|
|
|
3714
3760
|
def _slim_project_json(pj: dict) -> dict:
|
|
@@ -3843,13 +3889,25 @@ def unlink_cmd():
|
|
|
3843
3889
|
console.print("[green]✓ Platform link removed.[/green] The remote project is not deleted.")
|
|
3844
3890
|
|
|
3845
3891
|
|
|
3892
|
+
DEV_API_URL = 'https://dev-api.chipfoundry.io'
|
|
3893
|
+
|
|
3894
|
+
|
|
3846
3895
|
@main.command('login')
|
|
3847
|
-
|
|
3896
|
+
@click.option('--test', is_flag=True, help='Authenticate against the dev/test platform')
|
|
3897
|
+
def login_cmd(test):
|
|
3848
3898
|
"""Authenticate with ChipFoundry platform via browser."""
|
|
3849
3899
|
import httpx
|
|
3850
3900
|
import webbrowser
|
|
3851
3901
|
import time
|
|
3852
3902
|
|
|
3903
|
+
config = load_user_config()
|
|
3904
|
+
if test:
|
|
3905
|
+
config['api_url'] = DEV_API_URL
|
|
3906
|
+
save_user_config(config)
|
|
3907
|
+
elif config.get('api_url') == DEV_API_URL:
|
|
3908
|
+
del config['api_url']
|
|
3909
|
+
save_user_config(config)
|
|
3910
|
+
|
|
3853
3911
|
api_url = _get_api_url()
|
|
3854
3912
|
console.print("[bold cyan]ChipFoundry CLI Login[/bold cyan]")
|
|
3855
3913
|
console.print(f"Opening browser to authenticate with [bold]{api_url}[/bold]...\n")
|
|
@@ -3896,9 +3954,14 @@ def login_cmd():
|
|
|
3896
3954
|
config['api_key'] = api_key
|
|
3897
3955
|
if user_email:
|
|
3898
3956
|
config['user_email'] = user_email
|
|
3957
|
+
sftp_username = poll_data.get('sftp_username')
|
|
3958
|
+
if sftp_username:
|
|
3959
|
+
config['sftp_username'] = sftp_username
|
|
3899
3960
|
save_user_config(config)
|
|
3900
3961
|
|
|
3901
3962
|
console.print(f"\n[green]✓ Logged in as {user_email or 'authenticated user'}[/green]")
|
|
3963
|
+
if sftp_username:
|
|
3964
|
+
console.print(f" SFTP account: {sftp_username}")
|
|
3902
3965
|
console.print(f" API key saved to {get_config_path()}")
|
|
3903
3966
|
return
|
|
3904
3967
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|