diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9b47e8..ffc478b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,11 +5,19 @@ on: branches: [main] pull_request: branches: [main] + workflow_dispatch: + inputs: + target: + type: choice + description: Deploy target + options: [preview, production] + default: preview jobs: ci: name: Lint, Typecheck, Test & Build runs-on: ubuntu-latest + if: github.event_name != 'workflow_dispatch' steps: - name: Checkout @@ -49,11 +57,46 @@ jobs: DIRECT_URL: ${{ secrets.DIRECT_URL }} SESSION_SECRET: ${{ secrets.SESSION_SECRET }} + changes: + name: Detect deploy-relevant changes + runs-on: ubuntu-latest + needs: ci + if: github.event_name != 'workflow_dispatch' + outputs: + code: ${{ steps.filter.outputs.code }} + steps: + - uses: actions/checkout@v5 + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + code: + - 'app/**' + - 'components/**' + - 'lib/**' + - 'actions/**' + - 'stores/**' + - 'prisma/**' + - 'public/**' + - 'package.json' + - 'package-lock.json' + - 'next.config.ts' + - 'tsconfig.json' + - 'vercel.json' + - 'proxy.ts' + - 'middleware.ts' + - '.github/workflows/**' + deploy-preview: name: Deploy Preview (PR) runs-on: ubuntu-latest - needs: ci - if: github.event_name == 'pull_request' + needs: [ci, changes] + if: | + github.event_name == 'pull_request' && ( + (needs.changes.outputs.code == 'true' + && !contains(github.event.pull_request.labels.*.name, 'skip-deploy')) + || contains(github.event.pull_request.labels.*.name, 'force-deploy') + ) steps: - name: Checkout @@ -80,8 +123,11 @@ jobs: deploy-production: name: Deploy Production (main) runs-on: ubuntu-latest - needs: ci - if: github.ref == 'refs/heads/main' && github.event_name == 'push' + needs: [ci, changes] + if: | + github.ref == 'refs/heads/main' + && github.event_name == 'push' + && needs.changes.outputs.code == 'true' steps: - name: Checkout @@ -110,3 +156,42 @@ jobs: env: VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + + deploy-manual: + name: Deploy Manual (workflow_dispatch) + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: '24' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install Vercel CLI + run: npm install -g vercel@latest + + - name: Run database migrations (production only) + if: inputs.target == 'production' + run: npx prisma migrate deploy + env: + DATABASE_URL: ${{ secrets.DATABASE_URL }} + DIRECT_URL: ${{ secrets.DIRECT_URL }} + + - name: Deploy + run: | + if [ "${{ inputs.target }}" = "production" ]; then + vercel deploy --prod --token=${{ secrets.VERCEL_TOKEN }} + else + vercel deploy --token=${{ secrets.VERCEL_TOKEN }} + fi + env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}