From aafc0efaab6848c59253a109baedebe20d0db0d2 Mon Sep 17 00:00:00 2001 From: Spencer Twaddle <7374698+stwaddle@users.noreply.github.com> Date: Sat, 20 Jun 2026 22:04:54 -0500 Subject: [PATCH] Add production deploy workflow --- .gitea/workflows/deploy.yaml | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .gitea/workflows/deploy.yaml diff --git a/.gitea/workflows/deploy.yaml b/.gitea/workflows/deploy.yaml new file mode 100644 index 0000000..3962dfc --- /dev/null +++ b/.gitea/workflows/deploy.yaml @@ -0,0 +1,38 @@ +name: Deploy to Production + +on: + workflow_dispatch: + inputs: + image_tag: + description: 'Image tag to deploy (e.g. v1.2.3, or "latest")' + required: true + default: 'latest' + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Deploy via SSH + uses: appleboy/ssh-action@0ff4204d59e8e51228ff73bce53f80d53301dee2 # v1.2.5 + env: + # Pass the user-supplied tag as an env var (not interpolated into the + # remote script body). The remote script runs as the deploy user, which + # has docker access == root on prod, so the tag is validated before use. + IMAGE_TAG: ${{ inputs.image_tag }} + with: + host: ${{ secrets.PROD_SSH_HOST }} + username: ${{ secrets.PROD_SSH_USER }} + key: ${{ secrets.PROD_SSH_KEY }} + envs: IMAGE_TAG + script: | + set -eu + case "$IMAGE_TAG" in + latest|v[0-9]*) : ;; + *) echo "Refusing to deploy invalid tag: $IMAGE_TAG" >&2; exit 1 ;; + esac + IMAGE="gitea.stwaddle.com/stwaddle/budget" + cd /srv/stwaddlecom + docker pull "${IMAGE}:${IMAGE_TAG}" + # Re-tag as :latest so the compose definition (which references :latest) picks it up. + docker tag "${IMAGE}:${IMAGE_TAG}" "${IMAGE}:latest" + docker compose up -d budget