"""Redeploy the patched templates/datasheet-exact.js only. Backs up the current AD2 copy as .bak-20260412b (different suffix from the main deploy earlier today) then overwrites. """ import base64, os, subprocess, yaml, paramiko HOST='192.168.0.6'; USER='sysadmin' LOCAL = r'D:\claudetools\projects\dataforth-dos\datasheet-pipeline\implementation\templates\datasheet-exact.js' REMOTE = 'C:/Shares/testdatadb/templates/datasheet-exact.js' BACKUP_SUFFIX = '.bak-20260412b' def pwd(): r = subprocess.run(['sops','-d','D:/vault/clients/dataforth/ad2.sops.yaml'], capture_output=True, text=True, timeout=30, check=True) return yaml.safe_load(r.stdout)['credentials']['password'].replace('\\','') c = paramiko.SSHClient() c.set_missing_host_key_policy(paramiko.AutoAddPolicy()) c.connect(HOST, username=USER, password=pwd(), timeout=30, banner_timeout=45, look_for_keys=False, allow_agent=False) try: sftp = c.open_sftp() # Verify remote exists try: sz = sftp.stat(REMOTE).st_size print(f'[OK] remote exists: {REMOTE} ({sz} bytes)') except IOError: raise SystemExit(f'[FAIL] remote missing: {REMOTE}') # Backup backup_path = REMOTE + BACKUP_SUFFIX with sftp.open(REMOTE, 'rb') as src: data = src.read() with sftp.open(backup_path, 'wb') as dst: dst.write(data) print(f'[OK] backup: {backup_path} ({len(data)} bytes)') # Upload new sftp.put(LOCAL, REMOTE) new_sz = os.path.getsize(LOCAL) print(f'[OK] uploaded: {LOCAL} -> {REMOTE} ({new_sz} bytes)') sftp.close() finally: c.close()