ci: GitHub Actions auto-deploy to production droplet on push to main
Workflow SSHes into the production droplet as `deploy` and runs
`/opt/hackerspace-ops/deploy.sh` which:
- git fetches and resets to origin/main
- rebuilds the app image with NEXT_PUBLIC_* baked in from .env.local
- applies any new scripts/0NN_*.sql migrations not in the
public._migrations_applied tracking table
- hot-swaps the app container with `docker compose up -d --no-deps app`
- prunes dangling images
Repo secrets DROPLET_HOST and DEPLOY_SSH_PRIVATE_KEY are configured.
Concurrency group `deploy-prod` with cancel-in-progress=false so two
pushes in quick succession queue rather than racing.
Also gitignores `secrets/` and `*.pem` so production credentials never
get committed.
This commit is contained in:
@@ -0,0 +1,28 @@
|
|||||||
|
name: Deploy to production
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: deploy-prod
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
steps:
|
||||||
|
- name: Run deploy script on the droplet
|
||||||
|
uses: appleboy/ssh-action@v1
|
||||||
|
with:
|
||||||
|
host: ${{ secrets.DROPLET_HOST }}
|
||||||
|
username: deploy
|
||||||
|
key: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }}
|
||||||
|
port: 22
|
||||||
|
# Strict host key checking would need us to pin a known_hosts;
|
||||||
|
# for now the droplet's host key is trusted on first use.
|
||||||
|
script_stop: true
|
||||||
|
script: |
|
||||||
|
/opt/hackerspace-ops/deploy.sh
|
||||||
@@ -26,3 +26,7 @@ playwright-report/
|
|||||||
# Supabase CLI local state
|
# Supabase CLI local state
|
||||||
supabase/.branches/
|
supabase/.branches/
|
||||||
supabase/.temp/
|
supabase/.temp/
|
||||||
|
|
||||||
|
# Production deployment secrets (never commit)
|
||||||
|
secrets/
|
||||||
|
*.pem
|
||||||
|
|||||||
Reference in New Issue
Block a user