Skip to content

docs(claude): add no-silent-errors rule to development rules #383

docs(claude): add no-silent-errors rule to development rules

docs(claude): add no-silent-errors rule to development rules #383

Workflow file for this run

name: Build and Deploy
on:
push:
branches: [main]
workflow_dispatch:
env:
REGISTRY: ghcr.io
BACKEND_IMAGE: ghcr.io/${{ github.repository }}/backend
FRONTEND_IMAGE: ghcr.io/${{ github.repository }}/frontend
WHATSAPP_SIDECAR_IMAGE: ghcr.io/${{ github.repository }}/whatsapp-sidecar
jobs:
lint-file-length:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check file length limits
run: bash .github/scripts/check-file-length.sh
lint-exception-handling:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check except Exception without logging (soft-fail)
run: bash .github/scripts/check-exception-handling.sh
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Validate Alembic migrations
run: |
cd backend
pip install alembic sqlalchemy asyncpg --quiet
HEAD_COUNT=$(alembic heads 2>/dev/null | grep -c "(head)" || echo "0")
if [ "$HEAD_COUNT" -gt 1 ]; then
echo "❌ Multiple Alembic heads detected!"
alembic heads
exit 1
fi
echo "✅ Single migration head confirmed"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push backend
uses: docker/build-push-action@v5
with:
context: ./backend
push: true
tags: ${{ env.BACKEND_IMAGE }}:latest,${{ env.BACKEND_IMAGE }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and push frontend
uses: docker/build-push-action@v5
with:
context: ./frontend
push: true
tags: ${{ env.FRONTEND_IMAGE }}:latest,${{ env.FRONTEND_IMAGE }}:${{ github.sha }}
build-args: |
NEXT_PUBLIC_API_URL=https://pingcrm.sawinyh.com/api
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and push whatsapp-sidecar
uses: docker/build-push-action@v5
with:
context: ./whatsapp-sidecar
push: true
tags: ${{ env.WHATSAPP_SIDECAR_IMAGE }}:latest,${{ env.WHATSAPP_SIDECAR_IMAGE }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Sync docker-compose.prod.yml to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
# NOTE: a 'deploy' user with Docker access must be set up on the server
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "docker-compose.prod.yml"
target: "/opt/pingcrm/"
overwrite: true
- name: Deploy to server
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SERVER_HOST }}
# NOTE: a 'deploy' user with Docker access must be set up on the server
username: deploy
key: ${{ secrets.SSH_PRIVATE_KEY }}
envs: GITHUB_TOKEN,GITHUB_ACTOR,BIRD_AUTH_TOKEN,BIRD_CT0
script: |
cd /opt/pingcrm
# Login to GHCR
echo "$GITHUB_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin
# Update bird CLI credentials
grep -q "^AUTH_TOKEN=" .env && sed -i "s/^AUTH_TOKEN=.*/AUTH_TOKEN=$BIRD_AUTH_TOKEN/" .env || echo "AUTH_TOKEN=$BIRD_AUTH_TOKEN" >> .env
grep -q "^CT0=" .env && sed -i "s/^CT0=.*/CT0=$BIRD_CT0/" .env || echo "CT0=$BIRD_CT0" >> .env
# Pull latest images
docker compose -f docker-compose.prod.yml pull
# Restart services
docker compose -f docker-compose.prod.yml up -d --remove-orphans
# Cleanup old images
docker image prune -f
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_ACTOR: ${{ github.actor }}
BIRD_AUTH_TOKEN: ${{ secrets.BIRD_AUTH_TOKEN }}
BIRD_CT0: ${{ secrets.BIRD_CT0 }}