Deploy #52
This file contains hidden or 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: Deploy | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: [completed] | |
| workflow_dispatch: | |
| concurrency: | |
| group: deploy-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: read-all | |
| env: | |
| REGISTRY: ghcr.io | |
| BACKEND_IMAGE: ghcr.io/${{ github.repository }}-backend | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Detect which parts of the repo changed | |
| # --------------------------------------------------------------------------- | |
| changes: | |
| name: Detect Changes | |
| runs-on: ubuntu-latest | |
| if: | | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'workflow_run' && | |
| github.event.workflow_run.conclusion == 'success' && | |
| github.event.workflow_run.head_branch == 'main') | |
| outputs: | |
| frontend: ${{ steps.detect.outputs.frontend }} | |
| backend: ${{ steps.detect.outputs.backend }} | |
| manual: ${{ github.event_name == 'workflow_dispatch' }} | |
| steps: | |
| - name: Checkout (manual dispatch) | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| fetch-depth: 2 | |
| - name: Checkout tested commit (CI workflow_run) | |
| if: github.event_name == 'workflow_run' && github.event.workflow_run.head_branch == 'main' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| ref: main | |
| fetch-depth: 2 | |
| - name: Detect changed paths | |
| id: detect | |
| shell: bash | |
| env: | |
| EVENT_NAME: ${{ github.event_name }} | |
| run: | | |
| if [ "$EVENT_NAME" = "workflow_dispatch" ]; then | |
| echo "frontend=true" >> "$GITHUB_OUTPUT" | |
| echo "backend=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # Diff against the previous commit on main. | |
| changed_files="$(git diff --name-only HEAD^ HEAD || true)" | |
| if [ -z "$changed_files" ]; then | |
| changed_files="$(git show --pretty='' --name-only HEAD || true)" | |
| fi | |
| frontend=false | |
| backend=false | |
| while IFS= read -r file; do | |
| case "$file" in | |
| app/*|components/*|lib/*|public/*|package.json|bun.lockb|next.config.mjs|tailwind.config.js|tsconfig.json) | |
| frontend=true | |
| ;; | |
| backend/*) | |
| backend=true | |
| ;; | |
| esac | |
| done <<< "$changed_files" | |
| echo "frontend=$frontend" >> "$GITHUB_OUTPUT" | |
| echo "backend=$backend" >> "$GITHUB_OUTPUT" | |
| # --------------------------------------------------------------------------- | |
| # Frontend -> Vercel | |
| # --------------------------------------------------------------------------- | |
| deploy-frontend: | |
| name: Deploy Frontend (Vercel) | |
| runs-on: ubuntu-latest | |
| needs: changes | |
| if: needs.changes.outputs.frontend == 'true' || needs.changes.outputs.manual == 'true' | |
| environment: | |
| name: production | |
| url: ${{ steps.vercel.outputs.preview-url }} | |
| steps: | |
| - name: Checkout (manual dispatch) | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| - name: Checkout tested commit (CI workflow_run) | |
| if: github.event_name == 'workflow_run' && github.event.workflow_run.head_branch == 'main' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| ref: main | |
| - name: Validate Vercel credentials | |
| id: vercel-preflight | |
| shell: bash | |
| env: | |
| VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} | |
| VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} | |
| VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} | |
| run: | | |
| missing=0 | |
| for key in VERCEL_TOKEN VERCEL_ORG_ID VERCEL_PROJECT_ID; do | |
| if [ -z "${!key}" ]; then | |
| echo "::warning::Skipping frontend deploy: missing ${key}." | |
| missing=1 | |
| fi | |
| done | |
| if [ "$missing" -eq 0 ]; then | |
| echo "can_deploy=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "can_deploy=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Deploy to Vercel | |
| if: steps.vercel-preflight.outputs.can_deploy == 'true' | |
| id: vercel | |
| uses: amondnet/vercel-action@16e87c0a08142b0d0d33b76aeaf20823c381b9b9 | |
| with: | |
| vercel-token: ${{ secrets.VERCEL_TOKEN }} | |
| vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} | |
| vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} | |
| vercel-args: --prod | |
| working-directory: ./ | |
| # --------------------------------------------------------------------------- | |
| # Backend -> GHCR Docker image | |
| # --------------------------------------------------------------------------- | |
| deploy-backend: | |
| name: Deploy Backend (Docker) | |
| runs-on: ubuntu-latest | |
| needs: changes | |
| if: needs.changes.outputs.backend == 'true' || needs.changes.outputs.manual == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| environment: | |
| name: production | |
| steps: | |
| - name: Checkout (manual dispatch) | |
| if: github.event_name == 'workflow_dispatch' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| - name: Checkout tested commit (CI workflow_run) | |
| if: github.event_name == 'workflow_run' && github.event.workflow_run.head_branch == 'main' | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 | |
| with: | |
| ref: main | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 | |
| with: | |
| images: ${{ env.BACKEND_IMAGE }} | |
| tags: | | |
| type=sha,prefix= | |
| type=raw,value=latest | |
| - name: Build and push backend image | |
| uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 | |
| env: | |
| BUILD_DATE_VALUE: ${{ github.event.repository.updated_at }} | |
| GIT_SHA_VALUE: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }} | |
| with: | |
| context: . | |
| file: Dockerfile.backend | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| build-args: | | |
| BUILD_DATE=${{ env.BUILD_DATE_VALUE }} | |
| GIT_SHA=${{ env.GIT_SHA_VALUE }} |