Files
stack/.woodpecker/deploy.yml
kert cc6e389996 fix container registry push: publish gitea port 3000, use homelab/ org prefix
Push steps were failing because (1) gitea port 3000 wasn't published to
the host — docker daemon couldn't reach localhost:3000, and (2) the
fhirworx/ namespace doesn't exist in Gitea — images must go under
homelab/ to match the org.
2026-03-13 11:59:15 -04:00

225 lines
8.2 KiB
YAML

# ── Deploy ───────────────────────────────────────────────────────
# Builds the Python package, pushes it to Gitea's PyPI registry,
# builds, scans, and pushes container images, then updates the
# host working copy and restarts all changed services.
# Only runs on pushes to main (i.e. after PR merge).
#
# Image naming:
# fhirworx/<service>:<short-sha> (local tag, used by compose)
# localhost:3000/homelab/<service>:* (registry push only)
#
# The deploy step writes COMMIT_SHA=<short-sha> into .env so
# compose.yml resolves fhirworx/<svc>:${COMMIT_SHA:-latest} to
# the exact image just built.
when:
- event: push
branch: main
steps:
# ── Python package ──────────────────────────────────────────
- name: build-package
image: ghcr.io/astral-sh/uv:python3.13-bookworm-slim
commands:
- BASE=$(grep '^version' pyproject.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
- uv version "$BASE.dev${CI_PIPELINE_NUMBER}" --no-sync
- uv build --out-dir dist/
- ls -lh dist/
- name: publish-package
image: ghcr.io/astral-sh/uv:python3.13-bookworm-slim
environment:
REGISTRY_USER:
from_secret: registry_user
REGISTRY_PASS:
from_secret: registry_pass
commands:
- uv publish --publish-url http://gitea:3000/api/packages/homelab/pypi --username "$REGISTRY_USER" --password "$REGISTRY_PASS" dist/*
depends_on:
- build-package
# ── Notebooks image ─────────────────────────────────────────
- name: build-notebooks
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- docker build -t fhirworx/notebooks:$TAG ./notebooks
- docker tag fhirworx/notebooks:$TAG fhirworx/notebooks:latest
- name: scan-notebooks
image: aquasec/trivy:latest
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- trivy image --severity HIGH,CRITICAL --exit-code 0 --format table fhirworx/notebooks:$TAG
- trivy image --severity HIGH,CRITICAL --format json -o notebooks-scan.json fhirworx/notebooks:$TAG
depends_on:
- build-notebooks
- name: push-notebooks
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
environment:
REGISTRY_USER:
from_secret: registry_user
REGISTRY_PASS:
from_secret: registry_pass
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- echo "$REGISTRY_PASS" | docker login localhost:3000 -u "$REGISTRY_USER" --password-stdin
- docker tag fhirworx/notebooks:$TAG localhost:3000/homelab/notebooks:$TAG
- docker push localhost:3000/homelab/notebooks:$TAG
- docker tag fhirworx/notebooks:latest localhost:3000/homelab/notebooks:latest
- docker push localhost:3000/homelab/notebooks:latest
depends_on:
- scan-notebooks
# ── Zotero image ────────────────────────────────────────────
- name: build-zotero
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- docker build -t fhirworx/zotero:$TAG ./zotero
- docker tag fhirworx/zotero:$TAG fhirworx/zotero:latest
- name: scan-zotero
image: aquasec/trivy:latest
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- trivy image --severity HIGH,CRITICAL --exit-code 0 --format table fhirworx/zotero:$TAG
- trivy image --severity HIGH,CRITICAL --format json -o zotero-scan.json fhirworx/zotero:$TAG
depends_on:
- build-zotero
- name: push-zotero
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
environment:
REGISTRY_USER:
from_secret: registry_user
REGISTRY_PASS:
from_secret: registry_pass
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- echo "$REGISTRY_PASS" | docker login localhost:3000 -u "$REGISTRY_USER" --password-stdin
- docker tag fhirworx/zotero:$TAG localhost:3000/homelab/zotero:$TAG
- docker push localhost:3000/homelab/zotero:$TAG
- docker tag fhirworx/zotero:latest localhost:3000/homelab/zotero:latest
- docker push localhost:3000/homelab/zotero:latest
depends_on:
- scan-zotero
# ── Docs image ─────────────────────────────────────────────
# No path filter — docstrings and bib data change with any src/ edit.
# Host data dir is mounted so bib.sqlite is available for library export.
- name: build-docs
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
- /home/kert/stack/data:/host-data:ro
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- mkdir -p data
- cp /host-data/bib.sqlite data/ 2>/dev/null || true
- docker build -t fhirworx/docs:$TAG -f docs/Dockerfile .
- docker tag fhirworx/docs:$TAG fhirworx/docs:latest
- name: push-docs
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
environment:
REGISTRY_USER:
from_secret: registry_user
REGISTRY_PASS:
from_secret: registry_pass
commands:
- TAG=${CI_COMMIT_SHA:0:8}
- echo "$REGISTRY_PASS" | docker login localhost:3000 -u "$REGISTRY_USER" --password-stdin
- docker tag fhirworx/docs:$TAG localhost:3000/homelab/docs:$TAG
- docker push localhost:3000/homelab/docs:$TAG
- docker tag fhirworx/docs:latest localhost:3000/homelab/docs:latest
- docker push localhost:3000/homelab/docs:latest
depends_on:
- build-docs
# ── Upload scan results ─────────────────────────────────────
- name: upload-notebooks-scan
image: woodpeckerci/plugin-s3
settings:
endpoint: http://rustfs:9000
bucket: gitea
access_key:
from_secret: s3_access_key
secret_key:
from_secret: s3_secret_key
source: "notebooks-scan.json"
target: /ci/${CI_REPO}/${CI_COMMIT_SHA:0:8}/
path_style: true
depends_on:
- scan-notebooks
- name: upload-zotero-scan
image: woodpeckerci/plugin-s3
settings:
endpoint: http://rustfs:9000
bucket: gitea
access_key:
from_secret: s3_access_key
secret_key:
from_secret: s3_secret_key
source: "zotero-scan.json"
target: /ci/${CI_REPO}/${CI_COMMIT_SHA:0:8}/
path_style: true
depends_on:
- scan-zotero
# ── Deploy: pull latest code + restart services ────────────────
- name: deploy
image: docker:cli
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
- /home/kert/stack:/home/kert/stack
commands:
- apk add --no-cache git
- cd /home/kert/stack
- cp .env .env.bak 2>/dev/null || true
- git fetch http://gitea:3000/homelab/stack.git main
- git reset --hard FETCH_HEAD
- cp .env.bak .env 2>/dev/null || true
# Pin compose to the exact images just built
- TAG=${CI_COMMIT_SHA:0:8}
- sed -i "s/^COMMIT_SHA=.*/COMMIT_SHA=$TAG/" .env 2>/dev/null || echo "COMMIT_SHA=$TAG" >> .env
- docker compose up -d --remove-orphans
depends_on:
- publish-package
- push-notebooks
- upload-notebooks-scan
- push-zotero
- upload-zotero-scan
- push-docs
# ── Provision: derive credentials and rotate backends ────────
- name: provision
image: ghcr.io/astral-sh/uv:python3.13-bookworm-slim
volumes:
- /run/user/1000/docker.sock:/var/run/docker.sock
- /home/kert/stack:/home/kert/stack
environment:
ROOT_KEY:
from_secret: root_key
commands:
- cd /home/kert/stack
- uv run python -m api.auth provision ${CI_COMMIT_SHA}
depends_on:
- deploy