|
1 | | -name: Build, push and deploy CheatCode AI |
| 1 | +name: Build and Deploy to Cloud Run |
2 | 2 |
|
3 | 3 | on: |
4 | 4 | push: |
5 | 5 | branches: |
6 | | - - main |
7 | | - - PRODUCTION |
| 6 | + - master |
| 7 | + paths: |
| 8 | + - 'backend/**' |
| 9 | + - '.github/workflows/docker-build.yml' |
8 | 10 | workflow_dispatch: |
9 | 11 |
|
10 | | -permissions: |
11 | | - contents: read |
12 | | - packages: write |
| 12 | +env: |
| 13 | + PROJECT_ID: cheatcode-prod |
| 14 | + REGION: asia-south1 |
| 15 | + REGISTRY: asia-south1-docker.pkg.dev |
| 16 | + REPOSITORY: cheatcode |
13 | 17 |
|
14 | 18 | jobs: |
15 | | - build-and-push: |
| 19 | + build-and-deploy: |
16 | 20 | runs-on: ubuntu-latest |
| 21 | + permissions: |
| 22 | + contents: read |
| 23 | + id-token: write |
| 24 | + |
17 | 25 | steps: |
18 | 26 | - uses: actions/checkout@v4 |
19 | 27 |
|
20 | | - - name: Get tag name |
21 | | - shell: bash |
22 | | - run: | |
23 | | - if [[ "${GITHUB_REF#refs/heads/}" == "main" ]]; then |
24 | | - echo "branch=latest" >> $GITHUB_OUTPUT |
25 | | - echo "environment=staging" >> $GITHUB_OUTPUT |
26 | | - elif [[ "${GITHUB_REF#refs/heads/}" == "PRODUCTION" ]]; then |
27 | | - echo "branch=prod" >> $GITHUB_OUTPUT |
28 | | - echo "environment=prod" >> $GITHUB_OUTPUT |
29 | | - else |
30 | | - echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT |
31 | | - echo "environment=staging" >> $GITHUB_OUTPUT |
32 | | - fi |
33 | | - id: get_tag_name |
| 28 | + - name: authenticate to google cloud |
| 29 | + uses: google-github-actions/auth@v2 |
| 30 | + with: |
| 31 | + credentials_json: ${{ secrets.GCP_SA_KEY }} |
34 | 32 |
|
35 | | - - name: Set up Docker Buildx |
36 | | - uses: docker/setup-buildx-action@v3 |
| 33 | + - name: set up cloud sdk |
| 34 | + uses: google-github-actions/setup-gcloud@v2 |
37 | 35 |
|
38 | | - - name: Log in to GitHub Container Registry |
39 | | - uses: docker/login-action@v3 |
40 | | - with: |
41 | | - registry: ghcr.io |
42 | | - username: ${{ github.actor }} |
43 | | - password: ${{ secrets.GITHUB_TOKEN }} |
| 36 | + - name: configure docker for artifact registry |
| 37 | + run: gcloud auth configure-docker ${{ env.REGISTRY }} --quiet |
| 38 | + |
| 39 | + - name: set up docker buildx |
| 40 | + uses: docker/setup-buildx-action@v3 |
44 | 41 |
|
45 | | - - name: Build and push Backend image |
| 42 | + - name: build and push api image |
46 | 43 | uses: docker/build-push-action@v5 |
47 | 44 | with: |
48 | 45 | context: ./backend |
49 | 46 | file: ./backend/Dockerfile |
50 | 47 | push: true |
51 | 48 | platforms: linux/amd64 |
52 | | - tags: ghcr.io/${{ github.repository }}/backend:${{ steps.get_tag_name.outputs.branch }} |
| 49 | + tags: ${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/api:latest |
53 | 50 | cache-from: type=gha |
54 | 51 | cache-to: type=gha,mode=max |
55 | 52 |
|
56 | | - - name: Build and push Frontend image |
| 53 | + - name: build and push worker image |
57 | 54 | uses: docker/build-push-action@v5 |
58 | 55 | with: |
59 | | - context: ./frontend |
60 | | - file: ./frontend/Dockerfile |
| 56 | + context: ./backend |
| 57 | + file: ./backend/Dockerfile.worker |
61 | 58 | push: true |
62 | 59 | platforms: linux/amd64 |
63 | | - tags: ghcr.io/${{ github.repository }}/frontend:${{ steps.get_tag_name.outputs.branch }} |
| 60 | + tags: ${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/worker:latest |
64 | 61 | cache-from: type=gha |
65 | 62 | cache-to: type=gha,mode=max |
66 | 63 |
|
67 | | - - name: Deploy to staging |
68 | | - if: steps.get_tag_name.outputs.environment == 'staging' |
69 | | - uses: appleboy/ssh-action@v1 |
70 | | - with: |
71 | | - host: ${{ secrets.STAGING_HOST }} |
72 | | - username: ${{ secrets.STAGING_USERNAME }} |
73 | | - key: ${{ secrets.STAGING_KEY }} |
74 | | - script: | |
75 | | - cd /home/cheatcode/deployment-cheatcode |
76 | | - git pull |
77 | | - docker compose build |
78 | | - docker compose up -d |
| 64 | + - name: deploy api to cloud run |
| 65 | + run: | |
| 66 | + gcloud run deploy cheatcode-api \ |
| 67 | + --project=${{ env.PROJECT_ID }} \ |
| 68 | + --region=${{ env.REGION }} \ |
| 69 | + --image=${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/api:latest \ |
| 70 | + --platform=managed \ |
| 71 | + --allow-unauthenticated \ |
| 72 | + --cpu=1 \ |
| 73 | + --memory=2Gi \ |
| 74 | + --timeout=3500 \ |
| 75 | + --min-instances=0 \ |
| 76 | + --max-instances=5 \ |
| 77 | + --cpu-throttling \ |
| 78 | + --vpc-connector=cheatcode-connector \ |
| 79 | + --vpc-egress=private-ranges-only \ |
| 80 | + --service-account=cheatcode-api@${{ env.PROJECT_ID }}.iam.gserviceaccount.com \ |
| 81 | + --set-secrets="REDIS_URL=REDIS_URL:latest,ANTHROPIC_API_KEY=ANTHROPIC_API_KEY:latest,OPENAI_API_KEY=OPENAI_API_KEY:latest,OPENROUTER_API_KEY=OPENROUTER_API_KEY:latest,SUPABASE_URL=SUPABASE_URL:latest,SUPABASE_ANON_KEY=SUPABASE_ANON_KEY:latest,SUPABASE_SERVICE_ROLE_KEY=SUPABASE_SERVICE_ROLE_KEY:latest,CLERK_SECRET_KEY=CLERK_SECRET_KEY:latest,CLERK_DOMAIN=CLERK_DOMAIN:latest,POLAR_ACCESS_TOKEN=POLAR_ACCESS_TOKEN:latest,POLAR_ORGANIZATION_ID=POLAR_ORGANIZATION_ID:latest,POLAR_PRODUCT_ID_PRO=POLAR_PRODUCT_ID_PRO:latest,POLAR_PRODUCT_ID_PREMIUM=POLAR_PRODUCT_ID_PREMIUM:latest,POLAR_PRODUCT_ID_BYOK=POLAR_PRODUCT_ID_BYOK:latest,DAYTONA_API_KEY=DAYTONA_API_KEY:latest,DAYTONA_SERVER_URL=DAYTONA_SERVER_URL:latest,TAVILY_API_KEY=TAVILY_API_KEY:latest,FIRECRAWL_API_KEY=FIRECRAWL_API_KEY:latest,LANGFUSE_PUBLIC_KEY=LANGFUSE_PUBLIC_KEY:latest,LANGFUSE_SECRET_KEY=LANGFUSE_SECRET_KEY:latest,MCP_CREDENTIAL_ENCRYPTION_KEY=MCP_CREDENTIAL_ENCRYPTION_KEY:latest,COMPOSIO_API_KEY=COMPOSIO_API_KEY:latest,FREESTYLE_API_KEY=FREESTYLE_API_KEY:latest,GOOGLE_API_KEY=GOOGLE_API_KEY:latest,MORPH_API_KEY=MORPH_API_KEY:latest" \ |
| 82 | + --set-env-vars="ENV_MODE=production,LOG_LEVEL=INFO,LANGFUSE_HOST=https://us.cloud.langfuse.com,MODEL_TO_USE=openrouter/anthropic/claude-sonnet-4,FIRECRAWL_URL=https://api.firecrawl.dev,DAYTONA_TARGET=us" |
79 | 83 |
|
80 | | - - name: Deploy to prod |
81 | | - if: steps.get_tag_name.outputs.environment == 'prod' |
82 | | - uses: appleboy/ssh-action@v1 |
83 | | - with: |
84 | | - host: ${{ secrets.PROD_HOST }} |
85 | | - username: ${{ secrets.PROD_USERNAME }} |
86 | | - key: ${{ secrets.PROD_KEY }} |
87 | | - script: | |
88 | | - cd /mnt/gluster-shared/data/infra/cheatcode-ai |
89 | | - set -a; source .env; set +a |
90 | | - docker stack deploy -c docker-compose.yml cheatcode-ai |
| 84 | + - name: deploy worker to cloud run |
| 85 | + run: | |
| 86 | + gcloud run deploy cheatcode-worker \ |
| 87 | + --project=${{ env.PROJECT_ID }} \ |
| 88 | + --region=${{ env.REGION }} \ |
| 89 | + --image=${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/${{ env.REPOSITORY }}/worker:latest \ |
| 90 | + --platform=managed \ |
| 91 | + --no-allow-unauthenticated \ |
| 92 | + --cpu=1 \ |
| 93 | + --memory=2Gi \ |
| 94 | + --timeout=3500 \ |
| 95 | + --min-instances=1 \ |
| 96 | + --max-instances=3 \ |
| 97 | + --no-cpu-throttling \ |
| 98 | + --vpc-connector=cheatcode-connector \ |
| 99 | + --vpc-egress=private-ranges-only \ |
| 100 | + --service-account=cheatcode-api@${{ env.PROJECT_ID }}.iam.gserviceaccount.com \ |
| 101 | + --set-secrets="REDIS_URL=REDIS_URL:latest,ANTHROPIC_API_KEY=ANTHROPIC_API_KEY:latest,OPENAI_API_KEY=OPENAI_API_KEY:latest,OPENROUTER_API_KEY=OPENROUTER_API_KEY:latest,SUPABASE_URL=SUPABASE_URL:latest,SUPABASE_ANON_KEY=SUPABASE_ANON_KEY:latest,SUPABASE_SERVICE_ROLE_KEY=SUPABASE_SERVICE_ROLE_KEY:latest,CLERK_SECRET_KEY=CLERK_SECRET_KEY:latest,CLERK_DOMAIN=CLERK_DOMAIN:latest,POLAR_ACCESS_TOKEN=POLAR_ACCESS_TOKEN:latest,POLAR_ORGANIZATION_ID=POLAR_ORGANIZATION_ID:latest,POLAR_PRODUCT_ID_PRO=POLAR_PRODUCT_ID_PRO:latest,POLAR_PRODUCT_ID_PREMIUM=POLAR_PRODUCT_ID_PREMIUM:latest,POLAR_PRODUCT_ID_BYOK=POLAR_PRODUCT_ID_BYOK:latest,DAYTONA_API_KEY=DAYTONA_API_KEY:latest,DAYTONA_SERVER_URL=DAYTONA_SERVER_URL:latest,TAVILY_API_KEY=TAVILY_API_KEY:latest,FIRECRAWL_API_KEY=FIRECRAWL_API_KEY:latest,LANGFUSE_PUBLIC_KEY=LANGFUSE_PUBLIC_KEY:latest,LANGFUSE_SECRET_KEY=LANGFUSE_SECRET_KEY:latest,MCP_CREDENTIAL_ENCRYPTION_KEY=MCP_CREDENTIAL_ENCRYPTION_KEY:latest,COMPOSIO_API_KEY=COMPOSIO_API_KEY:latest,FREESTYLE_API_KEY=FREESTYLE_API_KEY:latest,GOOGLE_API_KEY=GOOGLE_API_KEY:latest,MORPH_API_KEY=MORPH_API_KEY:latest" \ |
| 102 | + --set-env-vars="ENV_MODE=production,LOG_LEVEL=INFO,LANGFUSE_HOST=https://us.cloud.langfuse.com,MODEL_TO_USE=openrouter/anthropic/claude-sonnet-4,FIRECRAWL_URL=https://api.firecrawl.dev,DAYTONA_TARGET=us" |
0 commit comments