• Stefy Lanza (nextime / spora )'s avatar
    packaging: hourly unattended upgrade that will not interrupt a request (v0.2.89) · 3cbea24f
    Stefy Lanza (nextime / spora ) authored
    Two production installs now follow this repo: zeiss (nexlab) and the Digesta
    host in Aruba. The Aruba one should track `production` without anyone logging
    in, so this adds coderai-autoupgrade plus a systemd user service and an hourly
    timer.
    
    It skips the upgrade outright while CoderAI is serving -- checked BEFORE the
    image is touched, not merely before the restart, so a busy host never reaches
    the state where new code waits in the image. Two probes and the higher count
    wins: the front's coderai_engine_inflight (every request in flight, pod-served
    ones included) and the pods' own summary.inflight from /v1/runpod/status. The
    RunPod one carries the weight on an orchestrator where every model is remote:
    the local engines are idle by definition, so the pods' count is the only sign
    work is happening, and killing a pod-served request loses the work AND keeps
    paying for the pod that was doing it. The check fails CLOSED -- no token, wrong
    URL or an unreachable endpoint skips the run, because an unreadable probe is
    nearly always a misconfiguration rather than an idle server.
    
    It decides by reading the image, not by an exit code: run_oci.sh exits 0 both
    when it upgraded and when the image was already current (the rc==10 branch
    prints its message and falls through to the same exit), so an exit-code-driven
    loop would have restarted the service every hour forever. The script compares
    __version__ baked in the image before and after, and a change is the only thing
    that triggers a restart. By default MAX_DEFERRALS=0, so a request in flight is
    never interrupted: the new code waits and every run says so.
    
    And it rolls back -- the pre-upgrade image is tagged first, and a service that
    is not healthy within HEALTH_TIMEOUT gets the old tag back, another restart and
    a non-zero exit that says whether it recovered.
    
    Writing the example config surfaced a trap worth the test that now guards it:
    the file is sourced, so `RESTART_CMD=systemctl --user restart coderai.service`
    unquoted assigns "systemctl" and RUNS the rest -- restarting nothing, failing
    the health check and rolling back a good upgrade. Everything in the example is
    quoted and each run echoes the restart command it resolved.
    
    Verified against the live server on zeiss: already-current does nothing; an
    overlapping run is a no-op; a missing token skips; three in-flight engine
    requests skip; and engines idle with a pod serving two still skips.
    Co-Authored-By: 's avatarClaude Opus 5 <noreply@anthropic.com>
    3cbea24f
coderai-autoupgrade.service 1.18 KB