|
| 1 | +# Rend Production Deploy Automation |
| 2 | + |
| 3 | +This workflow keeps the bare-metal control plane and edge hosts on the latest |
| 4 | +released binaries after a `main` build. |
| 5 | + |
| 6 | +The GitHub Actions workflow is `.github/workflows/release-deploy.yml`. |
| 7 | + |
| 8 | +## Flow |
| 9 | + |
| 10 | +1. Build `rend-api`, `rend-media-worker`, and `rend-edge` Docker targets. |
| 11 | +2. Push them to GHCR under `ghcr.io/<org>/rend/<service>`. |
| 12 | +3. Write a release manifest with immutable `@sha256:` image refs. |
| 13 | +4. Wait on the GitHub `Production` environment approval if that environment is |
| 14 | + configured with required reviewers. |
| 15 | +5. SSH to the control-plane host and run: |
| 16 | + - `scripts/preflight-control-plane-host.sh --skip-bind-port-check` |
| 17 | + - `scripts/deploy-control-plane-host.sh --dry-run` |
| 18 | + - `scripts/deploy-control-plane-host.sh` |
| 19 | + - local `rend-api` `/readyz` and `/healthz` |
| 20 | + The deploy helper waits for `rend-api` `/readyz` before starting |
| 21 | + `rend-media-worker`. |
| 22 | +6. SSH to each configured edge host, serially, and run: |
| 23 | + - `scripts/preflight-edge-host.sh --skip-bind-port-check` |
| 24 | + - `scripts/deploy-edge-host.sh --dry-run` |
| 25 | + - `scripts/deploy-edge-host.sh` |
| 26 | + - local `rend-edge` `/readyz` and `/healthz` |
| 27 | +7. Check public API `/readyz`. |
| 28 | +8. Run the synthetic playback readiness gate when the required readiness secrets |
| 29 | + and edge targets are configured. |
| 30 | + |
| 31 | +Preflight skips bind-port checks during automated updates because the existing |
| 32 | +service should already own the port. It still validates env files, registry |
| 33 | +pullability, image platform, host dependencies, managed dependency reachability, |
| 34 | +edge control-plane registration/heartbeat, and telemetry ingest. |
| 35 | + |
| 36 | +## Required GitHub Environment |
| 37 | + |
| 38 | +Create a GitHub Environment named `Production`. Configure required reviewers if |
| 39 | +production deploys should pause for human approval after the image release. |
| 40 | + |
| 41 | +## Required Secrets |
| 42 | + |
| 43 | +Set these as `Production` environment secrets unless noted otherwise: |
| 44 | + |
| 45 | +- `REND_SSH_PRIVATE_KEY`: private key with SSH access to the control-plane and |
| 46 | + edge hosts. |
| 47 | +- `REND_SSH_KNOWN_HOSTS`: pinned host key lines for all SSH targets. |
| 48 | +- `REND_CONTROL_PLANE_SSH_HOST` |
| 49 | +- `REND_CONTROL_PLANE_SSH_USER` |
| 50 | +- `REND_CONTROL_PLANE_SSH_PORT` (optional; defaults to `22`) |
| 51 | +- `REND_EDGE_ASH_SSH_HOST` |
| 52 | +- `REND_EDGE_ASH_SSH_USER` |
| 53 | +- `REND_EDGE_ASH_SSH_PORT` (optional; defaults to `22`) |
| 54 | +- `REND_EDGE_AMS_SSH_HOST` |
| 55 | +- `REND_EDGE_AMS_SSH_USER` |
| 56 | +- `REND_EDGE_AMS_SSH_PORT` (optional; defaults to `22`) |
| 57 | +- `REND_READINESS_API_KEY`: API key with upload, read, delete, and analytics |
| 58 | + scopes for synthetic readiness media. |
| 59 | +- `REND_EDGE_INTERNAL_TOKEN`: edge internal token for readiness warm, purge, and |
| 60 | + metrics checks. |
| 61 | + |
| 62 | +Generate known-hosts entries from a trusted operator machine, verify the |
| 63 | +fingerprints out of band, then paste the lines into `REND_SSH_KNOWN_HOSTS`: |
| 64 | + |
| 65 | +```sh |
| 66 | +ssh-keyscan -H api-internal.play.rend.so ash-1.play.rend.so ams-1.play.rend.so |
| 67 | +``` |
| 68 | + |
| 69 | +Each host must already be able to pull from GHCR in the Docker daemon context |
| 70 | +used by the SSH user: |
| 71 | + |
| 72 | +```sh |
| 73 | +docker login ghcr.io |
| 74 | +sudo docker login ghcr.io |
| 75 | +``` |
| 76 | + |
| 77 | +## Required Variables |
| 78 | + |
| 79 | +Set these as `Production` environment variables: |
| 80 | + |
| 81 | +- `REND_API_BASE_URL`: defaults to `https://api.rend.so` when omitted. |
| 82 | +- `REND_READINESS_EDGES`: comma-separated |
| 83 | + `edge_id=region=public_base[=private_base]` entries, for example: |
| 84 | + |
| 85 | +```text |
| 86 | +rend-edge-ash-1=us-east=https://ash-1.play.rend.so=https://ash-1-private.play.rend.so,rend-edge-ams-1=amsterdam=https://ams-1.play.rend.so=https://ams-1-private.play.rend.so |
| 87 | +``` |
| 88 | + |
| 89 | +The readiness gate needs `private_base` values that are reachable from the |
| 90 | +GitHub runner. If those private hosts are not publicly reachable, run this |
| 91 | +workflow on a self-hosted runner or provide VPN-accessible private bases. |
| 92 | + |
| 93 | +## Rollback |
| 94 | + |
| 95 | +Use the previous `rend-release-manifest` artifact from a successful workflow |
| 96 | +run, then run the same host deploy helper manually in this order: |
| 97 | + |
| 98 | +```sh |
| 99 | +scripts/deploy-release-over-ssh.sh --role edge --host <edge-host> --user <user> --manifest <previous-manifest> |
| 100 | +scripts/deploy-release-over-ssh.sh --role control-plane --host <control-host> --user <user> --manifest <previous-manifest> |
| 101 | +``` |
| 102 | + |
| 103 | +Roll back edges first, then the media worker/API control plane. Treat database |
| 104 | +migrations as forward-only unless a tested rollback migration exists. |
0 commit comments