diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1cc9e56..569d871 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -5,6 +5,11 @@ on: branches: - main pull_request: + types: + - opened + - synchronize + - reopened + - closed jobs: deploy: @@ -12,6 +17,8 @@ jobs: permissions: contents: read deployments: write + issues: write + pull-requests: write steps: - uses: actions/checkout@v4 @@ -25,35 +32,148 @@ jobs: - name: Install dependencies run: npm ci - - name: Build + - name: Build Next.js run: npm run build env: NODE_ENV: production - - name: Deploy to Cloudflare (Preview for PR / Production for main) - uses: cloudflare/wrangler-action@v3 - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - command: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - # Deploy to preview with unique name based on PR number - opennextjs-cloudflare build - wrangler deploy --env preview --name sparkmemos-pr-${{ github.event.pull_request.number }} - else - # Deploy to production - opennextjs-cloudflare deploy - fi + - name: Build OpenNext + run: npx opennextjs-cloudflare build + + - name: Install Wrangler + run: npm install -g wrangler + + # Deploy to main domain (main branch only) + - name: Deploy to Cloudflare (Main) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: wrangler deploy + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + + # Deploy to preview environment (PR only) + - name: Deploy to Cloudflare (Preview) + if: github.event_name == 'pull_request' + run: | + wrangler deploy --env pr-${{ github.event.pull_request.number }} --legacy-env + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + + # Get actual domain from Cloudflare API + - name: Get deployment URL + if: github.event_name == 'pull_request' + id: get-url + run: | + PR_NUM=${{ github.event.pull_request.number }} + ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + WORKER_NAME="sparkmemos" + + SUBDOMAIN_RESPONSE=$(curl -s -X GET \ + "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/subdomain" \ + -H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \ + -H "Content-Type: application/json") + + ACCOUNT_SUBDOMAIN=$(echo $SUBDOMAIN_RESPONSE | jq -r '.result.subdomain // empty') + + if [ -z "$ACCOUNT_SUBDOMAIN" ]; then + ACCOUNT_SUBDOMAIN=$ACCOUNT_ID + fi + + PREVIEW_URL="https://${WORKER_NAME}-pr-${PR_NUM}.${ACCOUNT_SUBDOMAIN}.workers.dev" + + echo "Preview URL: $PREVIEW_URL" + echo "preview_url=${PREVIEW_URL}" >> $GITHUB_OUTPUT + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + # Comment preview link on PR - name: Deploy status comment if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | - const previewUrl = `https://sparkmemos-pr-${{ github.event.pull_request.number }}.workers.dev`; + const previewUrl = process.env.PREVIEW_URL; + const prNumber = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + + const { data: comments } = await github.rest.issues.listComments({ + owner, + repo, + issue_number: prNumber + }); + + const existingComment = comments.find(comment => + comment.body.includes('๐Ÿš€ Preview deployed:') + ); + + const commentBody = `๐Ÿš€ Preview deployed: ${previewUrl}`; + + if (existingComment) { + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existingComment.id, + body: commentBody + }); + } else { + await github.rest.issues.createComment({ + owner, + repo, + issue_number: prNumber, + body: commentBody + }); + } + env: + PREVIEW_URL: ${{ steps.get-url.outputs.preview_url }} + + cleanup: + runs-on: ubuntu-latest + permissions: + contents: read + deployments: write + issues: write + pull-requests: write + + if: github.event_name == 'pull_request' && github.event.action == 'closed' + + steps: + - name: Install Wrangler + run: npm install -g wrangler + + - name: Cleanup preview environment + run: | + PR_NUM=${{ github.event.pull_request.number }} + ACCOUNT_ID=${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + WORKER_NAME="sparkmemos" + + echo "Cleaning up preview environment for PR #${PR_NUM}" + + RESPONSE=$(curl -s -X DELETE \ + "https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/workers/scripts/${WORKER_NAME}/environments/pr-${PR_NUM}" \ + -H "Authorization: Bearer ${{ secrets.CLOUDFLARE_API_TOKEN }}" \ + -H "Content-Type: application/json") + + echo "API Cleanup response: $RESPONSE" + + echo "Cleanup completed for PR #${PR_NUM}" + env: + CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} + CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + + - name: Add cleanup comment + uses: actions/github-script@v7 + with: + script: | + const prNumber = context.payload.pull_request.number; + const owner = context.repo.owner; + const repo = context.repo.repo; + await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.payload.pull_request.number, - body: `๐Ÿš€ Preview deployed: ${previewUrl}` + owner, + repo, + issue_number: prNumber, + body: `๐Ÿงน Preview environment cleaned up (PR #${prNumber} closed/merged)` }); diff --git a/README.md b/README.md index c403366..a0e7cb8 100644 --- a/README.md +++ b/README.md @@ -34,3 +34,4 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +# Test