managarten/maerchenzauber/.github/workflows/deploy-backend.yml
Till-JS e7f5f942f3 chore: initial commit - consolidate 4 projects into monorepo
Projects included:
- maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing)
- manacore (Expo mobile + SvelteKit web + Astro landing)
- manadeck (NestJS backend + Expo mobile + SvelteKit web)
- memoro (Expo mobile + SvelteKit web + Astro landing)

This commit preserves the current state before monorepo restructuring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 23:38:24 +01:00

208 lines
No EOL
7.7 KiB
YAML

name: Deploy Backend to Cloud Run
on:
push:
branches: [main]
paths:
- 'backend/**'
- 'packages/shared-types/**'
- '.github/workflows/deploy-backend.yml'
workflow_dispatch:
env:
PROJECT_ID: mana-core-453821
REGION: europe-west3
ARTIFACT_REGISTRY: europe-west3-docker.pkg.dev
NODE_VERSION: '20'
jobs:
test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Configure git for private packages
env:
GH_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
run: |
git config --global url."https://${GH_TOKEN}@github.com/".insteadOf ssh://git@github.com/
git config --global url."https://${GH_TOKEN}@github.com/".insteadOf git@github.com:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'
cache-dependency-path: 'backend/package-lock.json'
- name: Patch package-lock.json with authenticated URLs
env:
GH_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
working-directory: backend
run: |
# Handle both SSH and HTTPS URLs
if grep -q "git+ssh://git@github.com" package-lock.json; then
echo "⚠️ SSH URLs found - patching to HTTPS with token..."
sed -i "s|git+ssh://git@github.com/Memo-2023/|git+https://${GH_TOKEN}@github.com/Memo-2023/|g" package-lock.json
echo "✓ Lockfile patched successfully"
else
echo "⚠️ HTTPS URLs found - injecting token..."
sed -i "s|git+https://github.com/Memo-2023/|git+https://${GH_TOKEN}@github.com/Memo-2023/|g" package-lock.json
echo "✓ Token injected successfully"
fi
- name: Clear npm cache (if needed)
run: npm cache clean --force || true
- name: Install dependencies
run: |
cd backend
npm ci --loglevel verbose
- name: Run backend tests
run: cd backend && npm run test
env:
NODE_ENV: test
- name: Type check
run: cd backend && npm run build
build-and-deploy:
needs: test
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
env:
SERVICE_NAME: storyteller-backend
steps:
- uses: actions/checkout@v4
- name: Google Auth
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY_PROD }}
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v2
with:
version: 'latest'
- name: Configure Docker
run: |
gcloud auth configure-docker ${{ env.ARTIFACT_REGISTRY }}
- name: Build and Push Docker Image
env:
GH_TOKEN: ${{ secrets.GH_PERSONAL_TOKEN }}
DOCKER_BUILDKIT: 1
run: |
IMAGE_NAME="${{ env.ARTIFACT_REGISTRY }}/${{ env.PROJECT_ID }}/storyteller/${{ env.SERVICE_NAME }}"
IMAGE_TAG="${IMAGE_NAME}:${{ github.sha }}"
LATEST_TAG="${IMAGE_NAME}:latest"
echo "Building Docker image with BuildKit..."
docker build \
-f backend/Dockerfile \
-t ${IMAGE_TAG} \
-t ${LATEST_TAG} \
--secret id=github_token,env=GH_TOKEN \
--build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
--build-arg VCS_REF=${{ github.sha }} \
--build-arg VERSION=${{ github.sha }} \
.
echo "Pushing Docker image..."
docker push ${IMAGE_TAG}
docker push ${LATEST_TAG}
echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
- name: Deploy to Cloud Run
run: |
echo "Deploying to Cloud Run..."
gcloud run deploy ${{ env.SERVICE_NAME }} \
--image="${{ env.IMAGE_TAG }}" \
--project=${{ env.PROJECT_ID }} \
--region=${{ env.REGION }} \
--platform=managed \
--allow-unauthenticated \
--min-instances=1 \
--max-instances=3 \
--memory=2Gi \
--cpu=2 \
--timeout=1200 \
--concurrency=80 \
--port=8080 \
--service-account=${{ secrets.CLOUD_RUN_SERVICE_ACCOUNT }} \
--set-env-vars="NODE_ENV=production,GOOGLE_CLOUD_PROJECT=${{ env.PROJECT_ID }},GOOGLE_CLOUD_LOCATION=${{ env.REGION }}" \
--set-secrets="MANA_SERVICE_URL=MANA_SERVICE_URL:latest,APP_ID=MAERCHENZAUBER_APP_ID:latest,MANA_SUPABASE_SECRET_KEY=MANA_SUPABASE_SECRET_KEY:latest,MAERCHENZAUBER_SUPABASE_URL=MAERCHENZAUBER_SUPABASE_URL:latest,MAERCHENZAUBER_SUPABASE_ANON_KEY=MAERCHENZAUBER_SUPABASE_PUBLISHABLE_KEY:latest,MAERCHENZAUBER_SUPABASE_SERVICE_ROLE_KEY=MAERCHENZAUBER_SECRET_KEY:latest,MAERCHENZAUBER_GOOGLE_GENAI_API_KEY=MAERCHENZAUBER_GOOGLE_GENAI_API_KEY:latest,MAERCHENZAUBER_REPLICATE_API_KEY=MAERCHENZAUBER_REPLICATE_API_TOKEN:latest,MAERCHENZAUBER_AZURE_OPENAI_KEY=MAERCHENZAUBER_AZURE_OPENAI_KEY:latest,MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT=MAERCHENZAUBER_AZURE_OPENAI_ENDPOINT:latest" \
--labels="environment=production,commit=${{ github.sha }},branch=${{ github.ref_name }}"
# Ensure 100% traffic goes to the new revision
echo "Ensuring traffic is routed to the new revision..."
gcloud run services update-traffic ${{ env.SERVICE_NAME }} \
--to-latest \
--project=${{ env.PROJECT_ID }} \
--region=${{ env.REGION }} \
--platform=managed
echo "✅ Traffic routed to latest revision"
- name: Get Service URL
id: service-url
run: |
SERVICE_URL=$(gcloud run services describe ${{ env.SERVICE_NAME }} \
--project=${{ env.PROJECT_ID }} \
--region=${{ env.REGION }} \
--format='value(status.url)')
echo "Service deployed at: ${SERVICE_URL}"
echo "service_url=${SERVICE_URL}" >> $GITHUB_OUTPUT
# Create deployment summary
echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
echo "- **Service**: ${{ env.SERVICE_NAME }}" >> $GITHUB_STEP_SUMMARY
echo "- **Environment**: production" >> $GITHUB_STEP_SUMMARY
echo "- **URL**: ${SERVICE_URL}" >> $GITHUB_STEP_SUMMARY
echo "- **Image**: ${{ env.IMAGE_TAG }}" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
- name: Smoke Test
run: |
echo "Running smoke test..."
SERVICE_URL="${{ steps.service-url.outputs.service_url }}"
# Wait for service to be ready
sleep 10
# Check health endpoint
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" ${SERVICE_URL}/health)
if [ $HTTP_CODE -eq 200 ]; then
echo "✅ Health check passed"
else
echo "❌ Health check failed with HTTP ${HTTP_CODE}"
exit 1
fi
- name: Notify Deployment
if: always()
uses: actions/github-script@v7
with:
script: |
const status = '${{ job.status }}' === 'success' ? '✅' : '❌';
const serviceUrl = '${{ steps.service-url.outputs.service_url }}';
const comment = `## ${status} Backend Deployment
**Environment**: production
**Service URL**: ${serviceUrl}
**Commit**: ${{ github.sha }}
**Status**: ${{ job.status }}
`;
console.log('Deployment completed with status:', '${{ job.status }}');