skaldsong: scaffold compose stack + deploy playbook for ana-docker
Registry-pull pattern matching Worldtree: CI on vh/skaldsong builds and
pushes gitea.phasefinal.com/vh/skaldsong:<sha>, this playbook pulls +
recreates. SHA-pin only per current preference; no :latest moving-tag
advance yet (revisit once /health exercises Worldtree + Kokoro reach).
Host port 8300 (host) → 8000 (container). Persistent state under
/opt/docker/conf/skaldsong/{db,runs}.
Bifrost endpoint URL 10.250.50.70:8300 will need a paired
BIFROST_CLIENT_ALLOWED_HOSTS update on corviduo-dev Worldtree at first
deploy.
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
# Deploy skaldsong (https://gitea.phasefinal.com/vh/skaldsong) to a
|
||||
# Docker host following the PFI /opt/docker/ convention (ana-docker by
|
||||
# default, but the playbook works against any host with Docker in place).
|
||||
#
|
||||
# Registry-pull pattern, NOT build-on-host: vh/skaldsong's CI builds and
|
||||
# pushes `gitea.phasefinal.com/vh/skaldsong:<sha>` (+ :latest) to the
|
||||
# gitea registry; this playbook just pulls + recreates the container.
|
||||
# Differs from althing-chamber / asset-engine playbooks which build the
|
||||
# image on-host from a git clone — those are local-build stacks.
|
||||
#
|
||||
# Idempotent: rerunning is safe. Creates-gates skip work that's already
|
||||
# done; `docker compose up -d` is itself idempotent (no restart unless
|
||||
# compose content, env, or image SHA changed).
|
||||
#
|
||||
# Usage:
|
||||
# # CI passes the triggering commit SHA via --var ref=${{ github.sha }}:
|
||||
# scripts/elway ana-docker --playbook playbooks/deploy-skaldsong.yaml \
|
||||
# --var ref=<sha>
|
||||
#
|
||||
# # Manual runs can pass a branch or tag (will resolve to the registry
|
||||
# # tag of that name — CI publishes :main and :v0.1.0 tags alongside
|
||||
# # the SHA-pin):
|
||||
# scripts/elway ana-docker --playbook playbooks/deploy-skaldsong.yaml \
|
||||
# --var ref=main
|
||||
#
|
||||
# Prereqs on the target host:
|
||||
# - Docker + docker compose plugin
|
||||
# - Target user (lkraven) is in the `docker` group
|
||||
# - `docker login gitea.phasefinal.com` has been done at least once
|
||||
# (credentials persist in /home/lkraven/.docker/config.json). CI's
|
||||
# workflow runs its own `docker login` step from REGISTRY_USER /
|
||||
# REGISTRY_TOKEN secrets; manual runs assume the host's auth is
|
||||
# already established.
|
||||
|
||||
vars:
|
||||
registry_image: gitea.phasefinal.com/vh/skaldsong
|
||||
ref: latest
|
||||
compose_dir: /opt/docker/compose/skaldsong
|
||||
db_dir: /opt/docker/conf/skaldsong/db
|
||||
runs_dir: /opt/docker/conf/skaldsong/runs
|
||||
host_port: "8300"
|
||||
|
||||
steps:
|
||||
# ── compose + state dirs ────────────────────────────────────────────
|
||||
- name: Ensure compose dir exists
|
||||
shell: mkdir -p {{ compose_dir }}
|
||||
creates: "{{ compose_dir }}"
|
||||
|
||||
- name: Ensure DB dir exists
|
||||
# Created as lkraven (uid 1000 on these hosts), matching the
|
||||
# container's app user — no chown dance needed.
|
||||
shell: mkdir -p {{ db_dir }}
|
||||
creates: "{{ db_dir }}"
|
||||
|
||||
- name: Ensure runs dir exists
|
||||
# Separate from db_dir so runs/ can later move to a bigger volume
|
||||
# without touching DB state.
|
||||
shell: mkdir -p {{ runs_dir }}
|
||||
creates: "{{ runs_dir }}"
|
||||
|
||||
# ── deploy compose files ────────────────────────────────────────────
|
||||
- name: Upload compose.yaml
|
||||
upload:
|
||||
src: stacks/skaldsong/compose.yaml
|
||||
dest: "{{ compose_dir }}/compose.yaml"
|
||||
mode: "0644"
|
||||
|
||||
- name: Seed .env from template (only if absent)
|
||||
upload:
|
||||
src: stacks/skaldsong/.env.example
|
||||
dest: "{{ compose_dir }}/.env"
|
||||
mode: "0644"
|
||||
when: "[ ! -f {{ compose_dir }}/.env ]"
|
||||
|
||||
# ── pin SKALDSONG_IMAGE to the requested ref ────────────────────────
|
||||
- name: Set SKALDSONG_IMAGE pin to {{ ref }}
|
||||
# Idempotent: strip any existing SKALDSONG_IMAGE= line and append
|
||||
# the new one. CI passes --var ref=<sha>; manual runs pass branch /
|
||||
# tag names (CI publishes those as registry tags too).
|
||||
shell: |
|
||||
sed -i '/^SKALDSONG_IMAGE=/d' {{ compose_dir }}/.env
|
||||
echo "SKALDSONG_IMAGE={{ registry_image }}:{{ ref }}" >> {{ compose_dir }}/.env
|
||||
|
||||
# ── pull + bring up ─────────────────────────────────────────────────
|
||||
- name: Pull image {{ registry_image }}:{{ ref }}
|
||||
# Explicit pull step (rather than relying on compose up's pull) so
|
||||
# any auth failure surfaces here, not buried in compose output.
|
||||
shell: docker pull {{ registry_image }}:{{ ref }}
|
||||
|
||||
- name: docker compose up -d --force-recreate
|
||||
# --force-recreate picks up env changes even if the image SHA is
|
||||
# identical to what's running (rare but happens on env-only deploys).
|
||||
# --pull never: we just pulled explicitly above, so no need for
|
||||
# compose to re-check.
|
||||
shell: cd {{ compose_dir }} && docker compose up -d --force-recreate --pull never
|
||||
|
||||
- name: Wait for skaldsong /health to respond
|
||||
# Container's healthcheck is internal; this host-side poll confirms
|
||||
# the published port is reachable + the FastAPI app finished booting.
|
||||
# Generous retry budget — first-deploy bootstrapping (DB migrations,
|
||||
# SPA asset indexing) can take 30s+.
|
||||
shell: |
|
||||
for i in $(seq 1 30); do
|
||||
curl -sf -o /dev/null http://localhost:{{ host_port }}/health && exit 0
|
||||
sleep 2
|
||||
done
|
||||
exit 1
|
||||
changed_when: "false"
|
||||
|
||||
verify:
|
||||
- name: skaldsong /health returns 200
|
||||
shell: curl -sf -o /dev/null http://localhost:{{ host_port }}/health
|
||||
changed_when: "false"
|
||||
|
||||
- name: skaldsong container running + healthy
|
||||
shell: docker ps --filter name=^/skaldsong$ --format '{{.Status}}' | grep -q 'healthy'
|
||||
changed_when: "false"
|
||||
Reference in New Issue
Block a user