Add Spotlight (#107) #901
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Build & Deploy | |
on: | |
push: | |
branches: | |
- main | |
workflow_dispatch: | |
inputs: | |
force: | |
description: "Force deploy to all services" | |
default: true | |
type: boolean | |
nocache: | |
description: "Do not rely on existing layer cache" | |
default: false | |
type: boolean | |
env: | |
REGION: us-central1 | |
PROJECT_ID: cask-382601 | |
GOOGLE_CLIENT_ID: "721909483682-uk3befic1j1krv3drig2puu30v1i4v48.apps.googleusercontent.com" | |
SENTRY_DSN: "https://[email protected]/4505138086019073" | |
SENTRY_ORG: "peated" | |
SENTRY_PROJECT: "peated" | |
API_SERVER: https://api.peated.com | |
URL_PREFIX: https://peated.com | |
FATHOM_SITE_ID: "OGNPFEUC" | |
jobs: | |
build: | |
name: 🚀 Build | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
runs-on: ubuntu-latest | |
permissions: | |
contents: "read" | |
id-token: "write" | |
steps: | |
- name: ⬇️ Checkout repo | |
uses: actions/checkout@v3 | |
- name: "Google auth" | |
id: "auth" | |
uses: "google-github-actions/auth@v1" | |
with: | |
token_format: access_token | |
workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER_RESOURCE_NAME }} | |
service_account: ${{ secrets.SERVICE_ACCOUNT }}@${{ env.PROJECT_ID }}.iam.gserviceaccount.com | |
access_token_lifetime: 300s | |
# - name: Login to Artifact Registry | |
# uses: docker/login-action@v1 | |
# with: | |
# registry: us-central-docker.pkg.dev | |
# username: oauth2accesstoken | |
# password: ${{ steps.auth.outputs.access_token }} | |
- name: "Set up Cloud SDK" | |
uses: "google-github-actions/setup-gcloud@v1" | |
with: | |
project_id: "${{ env.PROJECT_ID }}" | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: "Docker auth" | |
run: |- | |
gcloud auth configure-docker ${{ env.REGION }}-docker.pkg.dev | |
- name: Record Version | |
id: vars | |
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT | |
- name: Verify Web | |
id: verify_web | |
run: | | |
if gcloud artifacts docker images describe "${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/web:${{ github.sha }}"; then | |
echo "image_exists=true" >> "$GITHUB_OUTPUT" | |
else | |
echo "image_exists=false" >> "$GITHUB_OUTPUT" | |
fi | |
- name: Verify API | |
id: verify_api | |
run: | | |
if gcloud artifacts docker images describe "${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/api:${{ github.sha }}"; then | |
echo "image_exists=true" >> "$GITHUB_OUTPUT" | |
else | |
echo "image_exists=false" >> "$GITHUB_OUTPUT" | |
fi | |
- name: Verify Worker | |
id: verify_worker | |
run: | | |
if gcloud artifacts docker images describe "${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/worker:${{ github.sha }}"; then | |
echo "image_exists=true" >> "$GITHUB_OUTPUT" | |
else | |
echo "image_exists=false" >> "$GITHUB_OUTPUT" | |
fi | |
# optimize cache by building all stages | |
- name: Build All Stages | |
uses: docker/build-push-action@v5 | |
if: steps.verify_web.outputs.image_exists == 'false' || steps.verify_api.outputs.image_exists == 'false' || steps.verify_worker.outputs.image_exists == 'false' | |
with: | |
context: . | |
cache-from: type=gha,scope=prod | |
cache-to: type=gha,mode=max,scope=prod | |
no-cache: ${{ inputs.nocache == 'true' }} | |
build-args: | | |
VERSION=${{ github.sha }} | |
API_SERVER=${{ env.API_SERVER }} | |
URL_PREFIX=${{ env.URL_PREFIX }} | |
GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID }} | |
SENTRY_DSN=${{ env.SENTRY_DSN }} | |
SENTRY_ORG=${{ env.SENTRY_ORG }} | |
SENTRY_PROJECT=${{ env.SENTRY_PROJECT }} | |
FATHOM_SITE_ID=${{ env.FATHOM_SITE_ID }} | |
secrets: | | |
"SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" | |
- name: Build Web | |
uses: docker/build-push-action@v5 | |
if: steps.verify_web.outputs.image_exists == 'false' | |
with: | |
context: . | |
cache-from: type=gha,scope=prod | |
no-cache: ${{ inputs.nocache == 'true' }} | |
push: true | |
target: web | |
build-args: | | |
VERSION=${{ github.sha }} | |
API_SERVER=${{ env.API_SERVER }} | |
URL_PREFIX=${{ env.URL_PREFIX }} | |
GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID }} | |
SENTRY_DSN=${{ env.SENTRY_DSN }} | |
SENTRY_ORG=${{ env.SENTRY_ORG }} | |
SENTRY_PROJECT=${{ env.SENTRY_PROJECT }} | |
FATHOM_SITE_ID=${{ env.FATHOM_SITE_ID }} | |
secrets: | | |
"SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" | |
tags: | | |
${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/web:${{ github.sha }} | |
- name: Build API | |
uses: docker/build-push-action@v5 | |
if: steps.verify_api.outputs.image_exists == 'false' | |
with: | |
context: . | |
cache-from: type=gha,scope=prod | |
no-cache: ${{ inputs.nocache == 'true' }} | |
push: true | |
target: api | |
build-args: | | |
VERSION=${{ github.sha }} | |
API_SERVER=${{ env.API_SERVER }} | |
URL_PREFIX=${{ env.URL_PREFIX }} | |
GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID }} | |
SENTRY_DSN=${{ env.SENTRY_DSN }} | |
SENTRY_ORG=${{ env.SENTRY_ORG }} | |
SENTRY_PROJECT=${{ env.SENTRY_PROJECT }} | |
FATHOM_SITE_ID=${{ env.FATHOM_SITE_ID }} | |
secrets: | | |
"SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" | |
tags: | | |
${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/api:${{ github.sha }} | |
- name: Build Worker | |
uses: docker/build-push-action@v5 | |
if: steps.verify_worker.outputs.image_exists == 'false' | |
with: | |
context: . | |
cache-from: type=gha,scope=prod | |
no-cache: ${{ inputs.nocache == 'true' }} | |
push: true | |
target: worker | |
build-args: | | |
VERSION=${{ github.sha }} | |
API_SERVER={{ env.API_SERVER }} | |
URL_PREFIX=${{ env.URL_PREFIX }} | |
GOOGLE_CLIENT_ID=${{ env.GOOGLE_CLIENT_ID }} | |
SENTRY_DSN=${{ env.SENTRY_DSN }} | |
SENTRY_ORG=${{ env.SENTRY_ORG }} | |
SENTRY_PROJECT=${{ env.SENTRY_PROJECT }} | |
FATHOM_SITE_ID=${{ env.FATHOM_SITE_ID }} | |
secrets: | | |
"SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" | |
tags: | | |
${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/worker:${{ github.sha }} | |
deploy: | |
name: 🚀 Deploy | |
concurrency: | |
group: ${{ github.workflow }} | |
runs-on: ubuntu-latest | |
needs: [build] | |
permissions: | |
contents: "read" | |
id-token: "write" | |
steps: | |
- name: ⬇️ Checkout repo | |
uses: actions/checkout@v3 | |
- name: "Google auth" | |
id: "auth" | |
uses: "google-github-actions/auth@v1" | |
with: | |
token_format: access_token | |
workload_identity_provider: ${{ secrets.WORKLOAD_IDENTITY_PROVIDER_RESOURCE_NAME }} | |
service_account: ${{ secrets.SERVICE_ACCOUNT }}@${{ env.PROJECT_ID }}.iam.gserviceaccount.com | |
access_token_lifetime: 300s | |
- name: "Set up Cloud SDK" | |
uses: "google-github-actions/setup-gcloud@v1" | |
with: | |
project_id: "${{ env.PROJECT_ID }}" | |
- name: Get GKE credentials | |
uses: google-github-actions/get-gke-credentials@v1 | |
with: | |
cluster_name: default | |
location: ${{ env.REGION }} | |
- name: Record Version | |
id: vars | |
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT | |
- name: Get changed files | |
id: changed-files-yaml | |
uses: tj-actions/changed-files@v39 | |
with: | |
files_yaml: | | |
api: | |
- apps/server/** | |
web: | |
- apps/web/** | |
worker: | |
- apps/worker/** | |
common: | |
- packages/** | |
- apps/server** | |
- Dockerfile | |
- package.json | |
migrations: | |
- apps/**/migrations/*.sql | |
- packages/**/migrations/*.sql | |
- name: Run Migrations | |
if: ${{ inputs.force || steps.changed-files-yaml.outputs.migrations_any_changed == 'true' }} | |
run: |- | |
gcloud run jobs update migrate-database \ | |
--region ${{ env.REGION }} \ | |
--image "${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/api:${{ github.sha }}" | |
gcloud run jobs execute migrate-database \ | |
--region ${{ env.REGION }} \ | |
--wait | |
- name: "Deploy API" | |
if: ${{ inputs.force || steps.changed-files-yaml.outputs.api_any_changed == 'true' || steps.changed-files-yaml.outputs.common_any_changed == 'true' }} | |
run: |- | |
kubectl set image deployment.v1.apps/peated-api peated-api="${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/api:${{ github.sha }}" | |
kubectl rollout status deployment/peated-api --timeout=5m | |
- name: "Deploy Web" | |
if: ${{ inputs.force || steps.changed-files-yaml.outputs.web_any_changed == 'true' || steps.changed-files-yaml.outputs.common_any_changed == 'true' }} | |
run: |- | |
kubectl set image deployment.v1.apps/peated-web peated-web="${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/web:${{ github.sha }}" | |
kubectl rollout status deployment/peated-web --timeout=5m | |
- name: "Deploy Worker" | |
if: ${{ inputs.force || steps.changed-files-yaml.outputs.worker_any_changed == 'true' || steps.changed-files-yaml.outputs.common_any_changed == 'true' }} | |
run: |- | |
kubectl set image deployment.v1.apps/peated-worker peated-worker="${{ env.REGION }}-docker.pkg.dev/${{ env.PROJECT_ID }}/peated/worker:${{ github.sha }}" | |
kubectl rollout status deployment/peated-worker --timeout=5m | |
- name: Discord notification (success) | |
if: success() | |
env: | |
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} | |
uses: Ilshidur/[email protected] | |
with: | |
args: | | |
"${{ github.actor }} deployed version [${{ steps.vars.outputs.sha_short }}](https://github.com/{{ EVENT_PAYLOAD.repository.full_name }}/commit/${{ github.sha }})." | |
- name: Discord notification (failure) | |
if: failure() | |
env: | |
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} | |
uses: Ilshidur/[email protected] | |
with: | |
args: | | |
"ERROR: Failed to deploy version [${{ steps.vars.outputs.sha_short }}](https://github.com/{{ EVENT_PAYLOAD.repository.full_name }}/commit/${{ github.sha }})." |