#!/usr/bin/env python3 """Force-recreate the manager container after a build that didn't swap. Why this exists: `docker compose up -d --build` rebuilds the image but won't recreate the running container if compose decides the spec hasn't changed. On the Azure VM we've hit cases where the smoke test shows the old container is still up. This script: 1. Inspects current container start time 2. Runs `compose up -d --force-recreate --build` 3. Confirms new start time """ import os import sys import paramiko HOST = os.environ.get("MGR_HOST", "20.24.50.121") USER = os.environ.get("MGR_USER", "heicode") PASS = os.environ.get("MGR_PASS", "") if not PASS: print("MGR_PASS not set", file=sys.stderr) sys.exit(2) def run(client, cmd, timeout=900): print(f"\n$ {cmd}", flush=True) stdin, stdout, stderr = client.exec_command(cmd, timeout=timeout, get_pty=True) out_chunks = [] for raw in iter(stdout.readline, ""): if not raw: break # Strip non-ASCII to dodge Windows cp936 encoding errors. clean = raw.encode("ascii", "replace").decode("ascii") out_chunks.append(clean) sys.stdout.write(clean) sys.stdout.flush() rc = stdout.channel.recv_exit_status() return rc, "".join(out_chunks) def main(): client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect( hostname=HOST, port=22, username=USER, password=PASS, look_for_keys=False, allow_agent=False, timeout=30, ) # Locate repo + compose file rc, repo_out = run(client, "for p in ~/heicode-mananger ~/heicode ~/heicode-mananger/heicode " "/opt/heicode-mananger /home/heicode/heicode-mananger; do " " if [ -d $p/.git ]; then echo FOUND=$p; break; fi; done") repo = None for line in repo_out.splitlines(): if "FOUND=" in line: repo = line.split("=", 1)[1].strip() break if not repo: print("repo not found", file=sys.stderr); sys.exit(3) run(client, "sudo docker ps --filter name=heicode --format 'table {{.Names}}\\t{{.Status}}\\t{{.Image}}\\t{{.CreatedAt}}'") run(client, f"cd {repo} && git log --oneline -1") # Pin to latest commit + force recreate. run(client, f"cd {repo}/heicode && sudo docker compose -f docker-compose.azure-vm.yml up -d --force-recreate --build heicode 2>&1", timeout=1800) run(client, "sleep 8") run(client, "sudo docker ps --filter name=heicode --format 'table {{.Names}}\\t{{.Status}}\\t{{.Image}}\\t{{.CreatedAt}}'") run(client, "sudo docker image prune -f") client.close() print("\nFORCE RECREATE DONE") if __name__ == "__main__": main()