fix: neutral state for dashboard kpis #69
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: CI and Deploy | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| rebuild_migrate: | |
| description: Rebuild and publish the migrate image before deploy | |
| required: false | |
| default: false | |
| type: boolean | |
| env: | |
| REGISTRY: ghcr.io | |
| APP_IMAGE_NAME: ${{ github.repository }} | |
| MIGRATE_IMAGE_NAME: ${{ github.repository }}-migrate | |
| jobs: | |
| verify: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Set up Bun | |
| uses: oven-sh/setup-bun@v2 | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Typecheck | |
| run: bun typecheck | |
| - name: Test | |
| run: bun test | |
| - name: Build app bundle | |
| run: bun run build | |
| publish-and-deploy: | |
| if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' | |
| needs: verify | |
| runs-on: ubuntu-24.04-arm | |
| environment: production | |
| concurrency: | |
| group: production-deploy | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v5 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Resolve migrate image | |
| id: migrate-image | |
| env: | |
| FORCE_REBUILD_MIGRATE: ${{ github.event_name == 'workflow_dispatch' && inputs.rebuild_migrate || 'false' }} | |
| MIGRATE_IMAGE_TAG: inputs-${{ hashFiles('Dockerfile', 'package.json', 'bun.lock', 'drizzle.config.ts', 'drizzle/**', 'src/db/**') }} | |
| run: | | |
| set -euo pipefail | |
| cache_image="$REGISTRY/$MIGRATE_IMAGE_NAME:$MIGRATE_IMAGE_TAG" | |
| build_migrate=false | |
| if [ "$FORCE_REBUILD_MIGRATE" = "true" ]; then | |
| build_migrate=true | |
| elif ! docker buildx imagetools inspect "$cache_image" >/dev/null 2>&1; then | |
| build_migrate=true | |
| fi | |
| echo "build=$build_migrate" >> "$GITHUB_OUTPUT" | |
| echo "cache_image=$cache_image" >> "$GITHUB_OUTPUT" | |
| - name: Build and push app image | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| pull: true | |
| platforms: linux/arm64 | |
| push: true | |
| target: release | |
| tags: | | |
| ${{ env.REGISTRY }}/${{ env.APP_IMAGE_NAME }}:latest | |
| ${{ env.REGISTRY }}/${{ env.APP_IMAGE_NAME }}:sha-${{ github.sha }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Build and push migrate image | |
| if: steps.migrate-image.outputs.build == 'true' | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| pull: true | |
| platforms: linux/arm64 | |
| push: true | |
| target: migrate | |
| tags: | | |
| ${{ steps.migrate-image.outputs.cache_image }} | |
| ${{ env.REGISTRY }}/${{ env.MIGRATE_IMAGE_NAME }}:latest | |
| ${{ env.REGISTRY }}/${{ env.MIGRATE_IMAGE_NAME }}:sha-${{ github.sha }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| - name: Configure SSH | |
| env: | |
| DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} | |
| DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} | |
| run: | | |
| install -m 700 -d ~/.ssh | |
| printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519 | |
| chmod 600 ~/.ssh/id_ed25519 | |
| ssh-keyscan -H "$DEPLOY_HOST" > ~/.ssh/known_hosts | |
| - name: Deploy release | |
| env: | |
| DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} | |
| DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }} | |
| DEPLOY_USER: ${{ secrets.DEPLOY_USER }} | |
| APP_IMAGE: ${{ env.REGISTRY }}/${{ env.APP_IMAGE_NAME }}:sha-${{ github.sha }} | |
| GHCR_USERNAME: ${{ github.actor }} | |
| GHCR_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| MIGRATE_IMAGE: ${{ steps.migrate-image.outputs.cache_image }} | |
| run: | | |
| printf '%s\n' "$GHCR_TOKEN" | ssh "$DEPLOY_USER@$DEPLOY_HOST" "docker login ghcr.io -u '$GHCR_USERNAME' --password-stdin" | |
| ssh "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p '$DEPLOY_PATH'" | |
| cat docker-compose.deploy.yml | ssh "$DEPLOY_USER@$DEPLOY_HOST" "cat > '$DEPLOY_PATH/docker-compose.deploy.yml'" | |
| ssh "$DEPLOY_USER@$DEPLOY_HOST" <<EOF | |
| set -e | |
| cd "$DEPLOY_PATH" | |
| export KLEIS_APP_IMAGE="$APP_IMAGE" | |
| export KLEIS_MIGRATE_IMAGE="$MIGRATE_IMAGE" | |
| docker compose -f docker-compose.deploy.yml pull | |
| docker compose -f docker-compose.deploy.yml run --rm --interactive=false migrate | |
| docker compose -f docker-compose.deploy.yml up -d app | |
| docker image prune -af | |
| EOF |