Posts an annotation to Grafana after each successful deploy, tagged with "deploy" and the service name. Annotations appear as vertical markers on dashboards, making it easy to correlate deploys with metric changes. Uses GRAFANA_SERVICE_TOKEN from SOPS secrets — must be added via sops infrastructure/secrets.infra.env. Gracefully skips if the token is not configured. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
122 lines
4.1 KiB
YAML
122 lines
4.1 KiB
YAML
name: CD Apps
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- "apps/**"
|
|
- "packages/**"
|
|
- "pnpm-lock.yaml"
|
|
workflow_dispatch: {}
|
|
|
|
concurrency:
|
|
group: deploy-apps
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build-images:
|
|
name: Build & Push Docker Images
|
|
runs-on: ubuntu-latest
|
|
environment: production
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
matrix:
|
|
app: [journal, planner]
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- uses: docker/login-action@v4
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Decrypt Sentry auth token
|
|
run: |
|
|
curl -sLO https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64
|
|
chmod +x sops-v3.9.4.linux.amd64
|
|
SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.app.env > /tmp/secrets.env
|
|
grep SENTRY_AUTH_TOKEN /tmp/secrets.env | cut -d= -f2- | tr -d '\n' > /tmp/sentry_token
|
|
|
|
- uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
file: apps/${{ matrix.app }}/Dockerfile
|
|
push: true
|
|
tags: |
|
|
ghcr.io/trails-cool/${{ matrix.app }}:latest
|
|
ghcr.io/trails-cool/${{ matrix.app }}:${{ github.sha }}
|
|
build-args: |
|
|
SENTRY_RELEASE=${{ github.sha }}
|
|
secrets: |
|
|
SENTRY_AUTH_TOKEN=/tmp/sentry_token
|
|
|
|
deploy:
|
|
name: Deploy Apps
|
|
needs: [build-images]
|
|
runs-on: ubuntu-latest
|
|
environment: production
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- name: Decrypt secrets
|
|
run: |
|
|
curl -sLO https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64
|
|
chmod +x sops-v3.9.4.linux.amd64
|
|
SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.app.env > infrastructure/app.env
|
|
echo "SENTRY_RELEASE=${{ github.sha }}" >> infrastructure/app.env
|
|
echo "DOMAIN=trails.cool" >> infrastructure/app.env
|
|
|
|
- name: Copy files to server
|
|
uses: appleboy/scp-action@v1
|
|
with:
|
|
host: ${{ secrets.DEPLOY_HOST }}
|
|
username: root
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
source: "infrastructure/docker-compose.yml,infrastructure/Caddyfile"
|
|
target: /opt/trails-cool
|
|
strip_components: 1
|
|
|
|
- name: Copy secrets to server
|
|
uses: appleboy/scp-action@v1
|
|
with:
|
|
host: ${{ secrets.DEPLOY_HOST }}
|
|
username: root
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
source: "infrastructure/app.env"
|
|
target: /opt/trails-cool
|
|
strip_components: 1
|
|
|
|
- name: Deploy via SSH
|
|
uses: appleboy/ssh-action@v1
|
|
with:
|
|
host: ${{ secrets.DEPLOY_HOST }}
|
|
username: root
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
script: |
|
|
cd /opt/trails-cool
|
|
|
|
# Login to ghcr.io
|
|
GHCR_TOKEN=$(grep DEPLOY_GHCR_TOKEN app.env | cut -d= -f2-)
|
|
echo "$GHCR_TOKEN" | docker login ghcr.io -u stigi --password-stdin
|
|
|
|
# Pull and deploy app containers
|
|
docker compose --env-file app.env pull journal planner
|
|
docker compose --env-file app.env run --rm journal npx drizzle-kit push --config /app/packages/db/drizzle.config.ts --force
|
|
docker compose --env-file app.env up -d journal planner
|
|
|
|
# Clean up
|
|
docker image prune -af
|
|
docker compose ps
|
|
|
|
# Annotate deploy in Grafana
|
|
GRAFANA_TOKEN=$(grep GRAFANA_SERVICE_TOKEN app.env | cut -d= -f2-)
|
|
if [ -n "$GRAFANA_TOKEN" ]; then
|
|
docker compose exec -T grafana wget -q -O /dev/null \
|
|
--header="Authorization: Bearer $GRAFANA_TOKEN" \
|
|
--header="Content-Type: application/json" \
|
|
--post-data='{"text":"Deploy '${{ github.sha }}'","tags":["deploy","apps"]}' \
|
|
http://localhost:3000/api/annotations || true
|
|
fi
|