diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index a8ee473..994533f 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -33,22 +33,6 @@ jobs: - name: Install PHP dependencies run: composer install --no-interaction --prefer-dist --optimize-autoloader - - name: Build frontend assets - run: | - set -euo pipefail - docker run --rm \ - -u "$(id -u):$(id -g)" \ - -e HOME=/tmp \ - -e VITE_APP_NAME=AndyTranscribe \ - -e VITE_REVERB_APP_KEY=andytranscribe-key \ - -e "VITE_REVERB_HOST=${VITE_REVERB_HOST}" \ - -e "VITE_REVERB_PORT=${VITE_REVERB_PORT}" \ - -e "VITE_REVERB_SCHEME=${VITE_REVERB_SCHEME}" \ - -v "$PWD:/app" \ - -w /app \ - node:22-alpine \ - sh -c "npm ci && npm run build" - - name: Run tests run: | set -euo pipefail @@ -87,7 +71,7 @@ jobs: TAG_SHA="${REGISTRY}/${REPO_LC}:${{ gitea.sha }}" TAG_LATEST="${REGISTRY}/${REPO_LC}:latest" echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${REGISTRY}" -u "${{ gitea.actor }}" --password-stdin - docker build \ + DOCKER_BUILDKIT=1 docker build \ --build-arg VITE_APP_NAME=AndyTranscribe \ --build-arg VITE_REVERB_APP_KEY=andytranscribe-key \ --build-arg "VITE_REVERB_HOST=${VITE_REVERB_HOST}" \ @@ -119,6 +103,7 @@ jobs: - name: Deploy production env: DEPLOY_PATHS: ${{ secrets.DEPLOY_PATHS }} + DEPLOY_SHA: ${{ gitea.sha }} run: | set -euo pipefail REPO_LC="$(echo "${{ gitea.repository }}" | tr '[:upper:]' '[:lower:]')" diff --git a/README.md b/README.md index f0a9d49..f924fe8 100644 --- a/README.md +++ b/README.md @@ -159,9 +159,11 @@ Open [http://localhost:8080](http://localhost:8080) as usual. After changing Com On push to `main`, Gitea Actions (host runner on z00): -1. Runs PHPUnit -2. Builds and pushes `gitea.z00.nu/ben/andytranscribe:` (+ `:latest`) -3. Deploys by pulling that image into `~/andyTranscibe` (`docker-compose.yml` + `compose.z00.yaml`) +1. Runs PHPUnit (+ compose config check) +2. Builds and pushes `gitea.z00.nu/ben/andytranscribe:` (+ `:latest`) — Vite assets are baked in the image build +3. Deploys by hard-resetting `~/andyTranscibe` to that SHA and pulling the image (`docker-compose.yml` + `compose.z00.yaml`) + +Do not hot-patch production containers or the deploy checkout. Fix in git and push to `main` so CI deploys. One-time server bootstrap (secrets + registry login): diff --git a/scripts/deploy-production.sh b/scripts/deploy-production.sh index 9ee1997..5363b3c 100755 --- a/scripts/deploy-production.sh +++ b/scripts/deploy-production.sh @@ -8,7 +8,8 @@ Deploy a pre-built APP_IMAGE to one or more AndyTranscribe directories. Environment: APP_IMAGE Required. e.g. gitea.z00.nu/ben/andytranscribe:abc1234 DEPLOY_PATHS Comma-separated instance directories (default: current directory) - GIT_PULL When 1 (default), run git pull --ff-only in each directory first + DEPLOY_SHA Optional git SHA to hard-reset each directory to (CI sets this) + GIT_PULL When 1 (default) and DEPLOY_SHA is empty, run git pull --ff-only Usage: APP_IMAGE=gitea.z00.nu/ben/andytranscribe:tag DEPLOY_PATHS=$HOME/andyTranscibe ./scripts/deploy-production.sh @@ -23,6 +24,7 @@ fi PATHS_CSV="${DEPLOY_PATHS:-${2:-.}}" GIT_PULL="${GIT_PULL:-1}" +DEPLOY_SHA="${DEPLOY_SHA:-}" IFS=',' read -r -a DIRS <<< "${PATHS_CSV}" for dir in "${DIRS[@]}"; do @@ -40,8 +42,20 @@ for dir in "${DIRS[@]}"; do ( cd "${dir}" - if [[ "${GIT_PULL}" == "1" ]] && git rev-parse --is-inside-work-tree >/dev/null 2>&1; then - git pull --ff-only + if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + if [[ -n "${DEPLOY_SHA}" ]]; then + git fetch --force origin "${DEPLOY_SHA}" + git checkout --force --detach "${DEPLOY_SHA}" + git reset --hard "${DEPLOY_SHA}" + # Drop local edits/hot-patches; keep runtime data and secrets. + git clean -fd \ + --exclude=database/ \ + --exclude=storage/ \ + --exclude=.env \ + --exclude=.env.* + elif [[ "${GIT_PULL}" == "1" ]]; then + git pull --ff-only + fi fi export APP_IMAGE="${IMAGE}" @@ -59,7 +73,7 @@ for dir in "${DIRS[@]}"; do fi docker compose "${compose_files[@]}" pull app queue reverb - docker compose "${compose_files[@]}" up -d + docker compose "${compose_files[@]}" up -d --remove-orphans docker compose "${compose_files[@]}" ps app_port="$(awk -F= '/^APP_HOST_PORT=/ {print $2; exit}' .env 2>/dev/null || true)" @@ -79,6 +93,13 @@ for dir in "${DIRS[@]}"; do echo "ERROR: health check failed for ${name}" >&2 exit 1 fi + + asset_scheme="$(curl -fsS "${health_url%/up}/login" | grep -oE 'https?://[^"'\'' ]+\.css' | head -1 || true)" + if [[ "${asset_scheme}" == http://* ]]; then + echo "ERROR: login page still emits http:// asset URLs (${asset_scheme})" >&2 + exit 1 + fi + echo "asset check ok: ${asset_scheme:-no absolute css url (relative/ok)}" ) done