Compare commits

..

4 Commits

Author SHA1 Message Date
Spencer Twaddle aafc0efaab Add production deploy workflow
Build and Push / build (push) Successful in 35s
2026-06-20 22:04:54 -05:00
Spencer Twaddle ecb1d92df3 Write registry auth without docker CLI
Build and Push / build (push) Successful in 1m0s
2026-06-20 17:57:26 -05:00
Spencer Twaddle 98a433f53f Disable builder cache since it can't connect and just slows things down
Build and Push / build (push) Failing after 10s
2026-06-20 17:26:18 -05:00
Spencer Twaddle 60e70f7acc Set up Docker Buildx in build workflow
Build and Push / build (push) Successful in 10m22s
2026-06-20 17:14:02 -05:00
2 changed files with 54 additions and 5 deletions
+16 -5
View File
@@ -15,6 +15,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
cache-binary: false
- name: Determine image name and tags
id: meta
env:
@@ -46,11 +51,17 @@ jobs:
- name: Log in to Gitea registry
if: steps.meta.outputs.is_release == 'true'
uses: docker/login-action@v3
with:
registry: ${{ vars.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
env:
# The job image (node:20-bullseye) has no docker CLI, so docker/login-action
# can't run. buildx reads ~/.docker/config.json directly, so write the auth
# there ourselves. Secrets via env keep them out of the templated script.
REGISTRY: ${{ vars.REGISTRY }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
run: |
mkdir -p "$HOME/.docker"
AUTH="$(printf '%s:%s' "$REGISTRY_USER" "$REGISTRY_PASSWORD" | base64 -w0)"
printf '{"auths":{"%s":{"auth":"%s"}}}' "$REGISTRY" "$AUTH" > "$HOME/.docker/config.json"
- name: Build and push release image
if: steps.meta.outputs.is_release == 'true'
+38
View File
@@ -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