From 503fbbf63f2126e5776fe1edba8de104310ece8e Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sat, 11 Oct 2025 08:37:49 -0600 Subject: [PATCH 1/8] ci: implement prebuilt deploy with GitHub-linked deployments and hidden prod URL --- .github/workflows/ci-deploy.yml | 62 ++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index ad55c14..02df6d2 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -2,9 +2,9 @@ name: CI + Deploy (prebuilt) on: push: - branches: [ '**' ] + branches: [ '**' ] # prod only for main; others -> preview pull_request: - branches: [ main ] + branches: [ main ] # PRs into main get preview link permissions: contents: read @@ -23,25 +23,25 @@ jobs: # Checkout repo - uses: actions/checkout@v4 - # Setup Node + cache + # Node + npm cache - uses: actions/setup-node@v4 with: node-version: 18 cache: 'npm' - # Install dependencies (CI preferred) + # Install deps - name: Install run: npm ci || npm install - # Lint if exists + # Lint if script exists - name: Lint run: npm run -s | grep -qE '(^| )lint( |:)' && npm run lint || echo "No lint script" - # Unit tests if exist + # Unit tests if script exists - name: Unit tests run: npm run -s | grep -qE '(^| )test( |:)' && npm test --ci --passWithNoTests=false || echo "No test script" - # E2E tests if exist + # E2E if script exists - name: E2E tests (optional) run: npm run -s | grep -qE '(^| )e2e( |:)' && npm run e2e || echo "No e2e script" @@ -49,7 +49,7 @@ jobs: - name: App build run: npm run build - # Short summary for PR checks + # Short build note - name: Build summary run: echo "Build & tests passed ✅" >> "$GITHUB_STEP_SUMMARY" @@ -58,20 +58,20 @@ jobs: if: ${{ success() }} runs-on: ubuntu-latest steps: - # Checkout again for deploy context + # Fresh checkout for deploy context - uses: actions/checkout@v4 - # Setup Node for Vercel CLI + # Node for Vercel CLI - uses: actions/setup-node@v4 with: node-version: 18 cache: 'npm' - # Install Vercel CLI + # Vercel CLI - name: Install Vercel CLI run: npm i -g vercel@latest - # Decide environment target + # Decide env: preview for PR/branches, production for main - name: Decide target id: tgt run: | @@ -83,7 +83,7 @@ jobs: echo "target=preview" >> $GITHUB_OUTPUT fi - # Pull Vercel config + envs + # Pull project settings + envs - name: Pull Vercel project settings run: | vercel pull --yes \ @@ -91,14 +91,14 @@ jobs: --token "${{ env.VERCEL_TOKEN }}" \ --scope "${{ env.VERCEL_ORG }}" - # Prebuild locally + # Build to .vercel/output (prebuilt) - name: Vercel prebuild run: | vercel build \ --token "${{ env.VERCEL_TOKEN }}" \ --scope "${{ env.VERCEL_ORG }}" - # Deploy prebuilt output (skip build on Vercel) + # Deploy prebuilt (no build on Vercel) - name: Deploy (prebuilt) id: deploy env: @@ -113,14 +113,18 @@ jobs: echo "url=$URL" >> "$GITHUB_OUTPUT" echo "Deployed: $URL" - # Show summary in job checks + # Summary: hide prod URL, show preview URL - name: Summary run: | echo "### Deployment" >> "$GITHUB_STEP_SUMMARY" echo "- Target: **${{ steps.tgt.outputs.target }}**" >> "$GITHUB_STEP_SUMMARY" - echo "- URL: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY" + if [ "${{ steps.tgt.outputs.target }}" = "production" ]; then + echo "- URL: (hidden for production)" >> "$GITHUB_STEP_SUMMARY" + else + echo "- URL: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY" + fi - # Comment preview link for PR reviewers + # PR comment with preview link - name: Post Preview URL to PR if: ${{ github.event_name == 'pull_request' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 @@ -132,13 +136,16 @@ jobs: body: `✅ Preview ready: ${{ steps.deploy.outputs.url }}` }) - # Link deployment to merge commit (appears in PR "merged commit ..." line) - - name: Link deployment to merge commit + # GitHub Deployment card on commit: + # main → production (no URL); others → preview with URL + - name: Link deployment to commit if: ${{ github.event_name == 'push' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 with: script: | - const envName = '${{ github.ref_name }}'; + const isProd = (context.ref === 'refs/heads/main'); + const envName = isProd ? 'production' : context.ref.replace('refs/heads/', ''); + const { data: dep } = await github.rest.repos.createDeployment({ ...context.repo, ref: context.sha, @@ -146,10 +153,15 @@ jobs: auto_merge: false, required_contexts: [] }); - await github.rest.repos.createDeploymentStatus({ + + const status = { ...context.repo, deployment_id: dep.id, state: 'success', - environment: envName, - environment_url: '${{ steps.deploy.outputs.url }}' - }); \ No newline at end of file + environment: envName + }; + if (!isProd) { + status.environment_url = '${{ steps.deploy.outputs.url }}'; + } + + await github.rest.repos.createDeploymentStatus(status); \ No newline at end of file From 0d8a867a7b3cb85a8347fdf4e4dce55edac457df Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sat, 11 Oct 2025 08:53:06 -0600 Subject: [PATCH 2/8] =?UTF-8?q?ci:=20simplify=20and=20document=20prebuilt?= =?UTF-8?q?=20GitHub=E2=86=92Vercel=20pipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-deploy.yml | 106 ++++++++++++++------------------ 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index 02df6d2..0746397 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -1,10 +1,12 @@ +Here’s your optimized YAML with short English comments only — just describing each step, no explanations or extra notes: + name: CI + Deploy (prebuilt) on: push: - branches: [ '**' ] # prod only for main; others -> preview + branches: ['**'] # prod only for main; others -> preview pull_request: - branches: [ main ] # PRs into main get preview link + branches: [ main ] # PRs into main get preview link permissions: contents: read @@ -20,101 +22,88 @@ jobs: build_and_test: runs-on: ubuntu-latest steps: - # Checkout repo + # Checkout repository - uses: actions/checkout@v4 - # Node + npm cache + # Setup Node.js and npm cache - uses: actions/setup-node@v4 with: node-version: 18 - cache: 'npm' + cache: npm - # Install deps - - name: Install + # Install dependencies + - name: Install dependencies run: npm ci || npm install - # Lint if script exists - - name: Lint + # Run lint + - name: Run lint (if exists) run: npm run -s | grep -qE '(^| )lint( |:)' && npm run lint || echo "No lint script" - # Unit tests if script exists - - name: Unit tests + # Run unit tests + - name: Run unit tests (if exists) run: npm run -s | grep -qE '(^| )test( |:)' && npm test --ci --passWithNoTests=false || echo "No test script" - # E2E if script exists - - name: E2E tests (optional) + # Run e2e tests + - name: Run e2e tests (if exists) run: npm run -s | grep -qE '(^| )e2e( |:)' && npm run e2e || echo "No e2e script" - # Project build - - name: App build + # Build project + - name: Build project run: npm run build - # Short build note + # Add build summary - name: Build summary - run: echo "Build & tests passed ✅" >> "$GITHUB_STEP_SUMMARY" + run: echo "✅ Build & tests passed" >> "$GITHUB_STEP_SUMMARY" deploy: needs: build_and_test - if: ${{ success() }} runs-on: ubuntu-latest + if: ${{ success() }} steps: - # Fresh checkout for deploy context + # Checkout repository - uses: actions/checkout@v4 - # Node for Vercel CLI + # Setup Node.js - uses: actions/setup-node@v4 with: node-version: 18 - cache: 'npm' + cache: npm - # Vercel CLI + # Install Vercel CLI - name: Install Vercel CLI run: npm i -g vercel@latest - # Decide env: preview for PR/branches, production for main - - name: Decide target + # Decide deploy target + - name: Decide deploy target id: tgt run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "target=preview" >> $GITHUB_OUTPUT - elif [ "${{ github.ref_name }}" = "main" ]; then + if [ "${{ github.ref_name }}" = "main" ]; then echo "target=production" >> $GITHUB_OUTPUT else echo "target=preview" >> $GITHUB_OUTPUT fi - # Pull project settings + envs + # Pull project settings - name: Pull Vercel project settings - run: | - vercel pull --yes \ - --environment "${{ steps.tgt.outputs.target }}" \ - --token "${{ env.VERCEL_TOKEN }}" \ - --scope "${{ env.VERCEL_ORG }}" + run: vercel pull --yes --environment "${{ steps.tgt.outputs.target }}" \ + --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}" - # Build to .vercel/output (prebuilt) - - name: Vercel prebuild - run: | - vercel build \ - --token "${{ env.VERCEL_TOKEN }}" \ - --scope "${{ env.VERCEL_ORG }}" + # Build project output + - name: Build prebuilt output + run: vercel build --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}" - # Deploy prebuilt (no build on Vercel) - - name: Deploy (prebuilt) + # Deploy prebuilt output + - name: Deploy prebuilt id: deploy - env: - VC_TOKEN: ${{ env.VERCEL_TOKEN }} - VC_TEAM: ${{ env.VERCEL_ORG }} - TARGET: ${{ steps.tgt.outputs.target }} run: | - set -e - ARGS=(deploy --yes --token "$VC_TOKEN" --scope "$VC_TEAM" --prebuilt) - [ "$TARGET" = "production" ] && ARGS+=(--prod) || true - URL="$(vercel "${ARGS[@]}")" + ARGS=(deploy --yes --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}" --prebuilt) + [ "${{ steps.tgt.outputs.target }}" = "production" ] && ARGS+=(--prod) + URL=$(vercel "${ARGS[@]}") echo "url=$URL" >> "$GITHUB_OUTPUT" - echo "Deployed: $URL" + echo "✅ Deployed: $URL" - # Summary: hide prod URL, show preview URL - - name: Summary + # Add deployment summary + - name: Deployment summary run: | echo "### Deployment" >> "$GITHUB_STEP_SUMMARY" echo "- Target: **${{ steps.tgt.outputs.target }}**" >> "$GITHUB_STEP_SUMMARY" @@ -124,8 +113,8 @@ jobs: echo "- URL: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY" fi - # PR comment with preview link - - name: Post Preview URL to PR + # Post preview comment + - name: Comment preview on PR if: ${{ github.event_name == 'pull_request' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 with: @@ -136,9 +125,8 @@ jobs: body: `✅ Preview ready: ${{ steps.deploy.outputs.url }}` }) - # GitHub Deployment card on commit: - # main → production (no URL); others → preview with URL - - name: Link deployment to commit + # Create GitHub deployment card + - name: Create GitHub Deployment if: ${{ github.event_name == 'push' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 with: @@ -160,8 +148,6 @@ jobs: state: 'success', environment: envName }; - if (!isProd) { - status.environment_url = '${{ steps.deploy.outputs.url }}'; - } + if (!isProd) status.environment_url = '${{ steps.deploy.outputs.url }}'; await github.rest.repos.createDeploymentStatus(status); \ No newline at end of file From 6c2aa94e22351364acda9dba7aa8d15a91e6ae61 Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sat, 11 Oct 2025 09:14:00 -0600 Subject: [PATCH 3/8] feat(ci): add merge conflict detection and PR warning --- .github/workflows/ci-deploy.yml | 115 ++++++++++++++++---------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index 0746397..1551f8d 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -1,12 +1,10 @@ -Here’s your optimized YAML with short English comments only — just describing each step, no explanations or extra notes: - name: CI + Deploy (prebuilt) on: push: - branches: ['**'] # prod only for main; others -> preview + branches: [ '**' ] # prod only for main; others -> preview pull_request: - branches: [ main ] # PRs into main get preview link + branches: [ main ] # PRs into main get preview link permissions: contents: read @@ -22,88 +20,95 @@ jobs: build_and_test: runs-on: ubuntu-latest steps: - # Checkout repository - uses: actions/checkout@v4 - - # Setup Node.js and npm cache - uses: actions/setup-node@v4 with: node-version: 18 - cache: npm - - # Install dependencies - - name: Install dependencies + cache: 'npm' + - name: Install run: npm ci || npm install - - # Run lint - - name: Run lint (if exists) + - name: Lint run: npm run -s | grep -qE '(^| )lint( |:)' && npm run lint || echo "No lint script" - - # Run unit tests - - name: Run unit tests (if exists) + - name: Unit tests run: npm run -s | grep -qE '(^| )test( |:)' && npm test --ci --passWithNoTests=false || echo "No test script" - - # Run e2e tests - - name: Run e2e tests (if exists) + - name: E2E tests (optional) run: npm run -s | grep -qE '(^| )e2e( |:)' && npm run e2e || echo "No e2e script" - - # Build project - - name: Build project + - name: App build run: npm run build - - # Add build summary - name: Build summary - run: echo "✅ Build & tests passed" >> "$GITHUB_STEP_SUMMARY" + run: echo "Build & tests passed ✅" >> "$GITHUB_STEP_SUMMARY" deploy: needs: build_and_test - runs-on: ubuntu-latest if: ${{ success() }} + runs-on: ubuntu-latest steps: - # Checkout repository - - uses: actions/checkout@v4 + # PR conflict notice (comment) + - name: Warn if conflicts detected + if: ${{ github.event_name == 'pull_request' && github.event.pull_request.mergeable == false }} + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + ...context.repo, + issue_number: context.payload.pull_request.number, + body: "⚠️ **Merge conflict detected!**\nPlease resolve conflicts before merging." + }) - # Setup Node.js + # PR conflict → fail checks (stops deploy) + - name: Fail if conflicts detected + if: ${{ github.event_name == 'pull_request' && github.event.pull_request.mergeable == false }} + run: | + echo "::error title=Merge conflict detected::Please resolve conflicts before merging." + exit 1 + + - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 18 - cache: npm - - # Install Vercel CLI + cache: 'npm' - name: Install Vercel CLI run: npm i -g vercel@latest - # Decide deploy target - - name: Decide deploy target + - name: Decide target id: tgt run: | - if [ "${{ github.ref_name }}" = "main" ]; then + if [ "${{ github.event_name }}" = "pull_request" ]; then + echo "target=preview" >> $GITHUB_OUTPUT + elif [ "${{ github.ref_name }}" = "main" ]; then echo "target=production" >> $GITHUB_OUTPUT else echo "target=preview" >> $GITHUB_OUTPUT fi - # Pull project settings - name: Pull Vercel project settings - run: vercel pull --yes --environment "${{ steps.tgt.outputs.target }}" \ - --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}" + run: | + vercel pull --yes \ + --environment "${{ steps.tgt.outputs.target }}" \ + --token "${{ env.VERCEL_TOKEN }}" \ + --scope "${{ env.VERCEL_ORG }}" - # Build project output - - name: Build prebuilt output - run: vercel build --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}" + - name: Vercel prebuild + run: | + vercel build \ + --token "${{ env.VERCEL_TOKEN }}" \ + --scope "${{ env.VERCEL_ORG }}" - # Deploy prebuilt output - - name: Deploy prebuilt + - name: Deploy (prebuilt) id: deploy + env: + VC_TOKEN: ${{ env.VERCEL_TOKEN }} + VC_TEAM: ${{ env.VERCEL_ORG }} + TARGET: ${{ steps.tgt.outputs.target }} run: | - ARGS=(deploy --yes --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}" --prebuilt) - [ "${{ steps.tgt.outputs.target }}" = "production" ] && ARGS+=(--prod) - URL=$(vercel "${ARGS[@]}") + set -e + ARGS=(deploy --yes --token "$VC_TOKEN" --scope "$VC_TEAM" --prebuilt) + [ "$TARGET" = "production" ] && ARGS+=(--prod) || true + URL="$(vercel "${ARGS[@]}")" echo "url=$URL" >> "$GITHUB_OUTPUT" - echo "✅ Deployed: $URL" + echo "Deployed: $URL" - # Add deployment summary - - name: Deployment summary + - name: Summary run: | echo "### Deployment" >> "$GITHUB_STEP_SUMMARY" echo "- Target: **${{ steps.tgt.outputs.target }}**" >> "$GITHUB_STEP_SUMMARY" @@ -111,10 +116,8 @@ jobs: echo "- URL: (hidden for production)" >> "$GITHUB_STEP_SUMMARY" else echo "- URL: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY" - fi - # Post preview comment - - name: Comment preview on PR + - name: Post Preview URL to PR if: ${{ github.event_name == 'pull_request' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 with: @@ -125,15 +128,13 @@ jobs: body: `✅ Preview ready: ${{ steps.deploy.outputs.url }}` }) - # Create GitHub deployment card - - name: Create GitHub Deployment + - name: Link deployment to commit if: ${{ github.event_name == 'push' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 with: script: | const isProd = (context.ref === 'refs/heads/main'); const envName = isProd ? 'production' : context.ref.replace('refs/heads/', ''); - const { data: dep } = await github.rest.repos.createDeployment({ ...context.repo, ref: context.sha, @@ -141,13 +142,11 @@ jobs: auto_merge: false, required_contexts: [] }); - const status = { ...context.repo, deployment_id: dep.id, state: 'success', environment: envName }; - if (!isProd) status.environment_url = '${{ steps.deploy.outputs.url }}'; await github.rest.repos.createDeploymentStatus(status); \ No newline at end of file From 0fba4fb2158d12b9f154babbc8461bf8ee0fe552 Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sat, 11 Oct 2025 09:19:34 -0600 Subject: [PATCH 4/8] =?UTF-8?q?ci:=20simplify=20GitHub=E2=86=92Vercel=20pi?= =?UTF-8?q?peline=20to=20match=20Rez=E2=80=99s=20deployment=20flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-deploy.yml | 139 +++++++++++--------------------- 1 file changed, 49 insertions(+), 90 deletions(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index 1551f8d..b7cf5a3 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -2,151 +2,110 @@ name: CI + Deploy (prebuilt) on: push: - branches: [ '**' ] # prod only for main; others -> preview + branches: [ '**' ] pull_request: - branches: [ main ] # PRs into main get preview link + branches: [ main ] permissions: contents: read - issues: write - pull-requests: write deployments: write + pull-requests: write env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} VERCEL_ORG: ${{ secrets.VERCEL_ORG_ID }} jobs: - build_and_test: + build_and_deploy: runs-on: ubuntu-latest steps: + # Checkout repo - uses: actions/checkout@v4 + + # Setup Node.js + cache - uses: actions/setup-node@v4 with: node-version: 18 cache: 'npm' - - name: Install - run: npm ci || npm install - - name: Lint - run: npm run -s | grep -qE '(^| )lint( |:)' && npm run lint || echo "No lint script" - - name: Unit tests - run: npm run -s | grep -qE '(^| )test( |:)' && npm test --ci --passWithNoTests=false || echo "No test script" - - name: E2E tests (optional) - run: npm run -s | grep -qE '(^| )e2e( |:)' && npm run e2e || echo "No e2e script" - - name: App build - run: npm run build - - name: Build summary - run: echo "Build & tests passed ✅" >> "$GITHUB_STEP_SUMMARY" - deploy: - needs: build_and_test - if: ${{ success() }} - runs-on: ubuntu-latest - steps: - # PR conflict notice (comment) - - name: Warn if conflicts detected - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.mergeable == false }} - uses: actions/github-script@v7 - with: - script: | - await github.rest.issues.createComment({ - ...context.repo, - issue_number: context.payload.pull_request.number, - body: "⚠️ **Merge conflict detected!**\nPlease resolve conflicts before merging." - }) + # Install dependencies + - name: Install dependencies + run: npm ci || npm install - # PR conflict → fail checks (stops deploy) - - name: Fail if conflicts detected - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.mergeable == false }} - run: | - echo "::error title=Merge conflict detected::Please resolve conflicts before merging." - exit 1 + # Build project + - name: Build app + run: npm run build - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 18 - cache: 'npm' - - name: Install Vercel CLI + # Install Vercel CLI + - name: Setup Vercel CLI run: npm i -g vercel@latest - - name: Decide target - id: tgt + # Define target (preview or production) + - name: Define target + id: target run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "target=preview" >> $GITHUB_OUTPUT - elif [ "${{ github.ref_name }}" = "main" ]; then - echo "target=production" >> $GITHUB_OUTPUT + if [ "${{ github.ref_name }}" = "main" ]; then + echo "env=production" >> $GITHUB_OUTPUT else - echo "target=preview" >> $GITHUB_OUTPUT + echo "env=preview" >> $GITHUB_OUTPUT fi - - name: Pull Vercel project settings + # Pull project config and environment vars + - name: Pull Vercel settings run: | vercel pull --yes \ - --environment "${{ steps.tgt.outputs.target }}" \ - --token "${{ env.VERCEL_TOKEN }}" \ - --scope "${{ env.VERCEL_ORG }}" + --environment="${{ steps.target.outputs.env }}" \ + --token="${{ env.VERCEL_TOKEN }}" \ + --scope="${{ env.VERCEL_ORG }}" - - name: Vercel prebuild + # Prebuild app (creates .vercel/output) + - name: Prebuild Vercel output run: | vercel build \ - --token "${{ env.VERCEL_TOKEN }}" \ - --scope "${{ env.VERCEL_ORG }}" + --token="${{ env.VERCEL_TOKEN }}" \ + --scope="${{ env.VERCEL_ORG }}" - - name: Deploy (prebuilt) + # Deploy prebuilt build to Vercel + - name: Deploy prebuilt build id: deploy - env: - VC_TOKEN: ${{ env.VERCEL_TOKEN }} - VC_TEAM: ${{ env.VERCEL_ORG }} - TARGET: ${{ steps.tgt.outputs.target }} run: | set -e - ARGS=(deploy --yes --token "$VC_TOKEN" --scope "$VC_TEAM" --prebuilt) - [ "$TARGET" = "production" ] && ARGS+=(--prod) || true - URL="$(vercel "${ARGS[@]}")" - echo "url=$URL" >> "$GITHUB_OUTPUT" - echo "Deployed: $URL" - - - name: Summary - run: | - echo "### Deployment" >> "$GITHUB_STEP_SUMMARY" - echo "- Target: **${{ steps.tgt.outputs.target }}**" >> "$GITHUB_STEP_SUMMARY" - if [ "${{ steps.tgt.outputs.target }}" = "production" ]; then - echo "- URL: (hidden for production)" >> "$GITHUB_STEP_SUMMARY" + if [ "${{ steps.target.outputs.env }}" = "production" ]; then + URL=$(vercel deploy --prebuilt --prod --yes --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}") else - echo "- URL: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY" + URL=$(vercel deploy --prebuilt --yes --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}") + fi + echo "url=$URL" >> "$GITHUB_OUTPUT" + echo "✅ Deployed to $URL" - - name: Post Preview URL to PR - if: ${{ github.event_name == 'pull_request' && steps.deploy.outputs.url != '' }} + # Comment on PRs (preview link only) + - name: Comment Preview URL on PR + if: ${{ github.event_name == 'pull_request' }} uses: actions/github-script@v7 with: script: | await github.rest.issues.createComment({ ...context.repo, issue_number: context.payload.pull_request.number, - body: `✅ Preview ready: ${{ steps.deploy.outputs.url }}` + body: `✅ **Preview ready:** ${{ steps.deploy.outputs.url }}` }) - - name: Link deployment to commit - if: ${{ github.event_name == 'push' && steps.deploy.outputs.url != '' }} + # Create GitHub Deployment card for main branch + - name: Create Deployment Card + if: ${{ github.ref_name == 'main' }} uses: actions/github-script@v7 with: script: | - const isProd = (context.ref === 'refs/heads/main'); - const envName = isProd ? 'production' : context.ref.replace('refs/heads/', ''); const { data: dep } = await github.rest.repos.createDeployment({ ...context.repo, ref: context.sha, - environment: envName, + environment: 'production', auto_merge: false, required_contexts: [] }); - const status = { + await github.rest.repos.createDeploymentStatus({ ...context.repo, deployment_id: dep.id, state: 'success', - environment: envName - }; - if (!isProd) status.environment_url = '${{ steps.deploy.outputs.url }}'; - await github.rest.repos.createDeploymentStatus(status); \ No newline at end of file + environment: 'production' + }); \ No newline at end of file From 0268eeef01e3458752e683a8c58dccdbb6a5d277 Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sun, 12 Oct 2025 11:28:36 -0600 Subject: [PATCH 5/8] ci: add vercel deployment diagnostics for access and API check --- .github/workflows/ci-deploy.yml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index b7cf5a3..6fb89aa 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -10,6 +10,7 @@ permissions: contents: read deployments: write pull-requests: write + issues: write env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} @@ -68,19 +69,22 @@ jobs: # Deploy prebuilt build to Vercel - name: Deploy prebuilt build id: deploy + env: + VC_TOKEN: ${{ env.VERCEL_TOKEN }} + VC_TEAM: ${{ env.VERCEL_ORG }} + ENV: ${{ steps.target.outputs.env }} run: | set -e - if [ "${{ steps.target.outputs.env }}" = "production" ]; then - URL=$(vercel deploy --prebuilt --prod --yes --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}") - else - URL=$(vercel deploy --prebuilt --yes --token "${{ env.VERCEL_TOKEN }}" --scope "${{ env.VERCEL_ORG }}") - fi + ARGS=(deploy --prebuilt --yes --token "$VC_TOKEN" --scope "$VC_TEAM") + [ "$ENV" = "production" ] && ARGS+=(--prod) || true + OUT="$(vercel "${ARGS[@]}")" + # take only public *.vercel.app URL (avoid private Inspect link) + URL="$(printf "%s\n" "$OUT" | grep -Eo 'https?://[a-zA-Z0-9.-]+\.vercel\.app' | tail -1 || true)" echo "url=$URL" >> "$GITHUB_OUTPUT" - echo "✅ Deployed to $URL" + echo "✅ Deployed to: ${URL:-(no public URL)}" - # Comment on PRs (preview link only) - name: Comment Preview URL on PR - if: ${{ github.event_name == 'pull_request' }} + if: ${{ github.event_name == 'pull_request' && steps.deploy.outputs.url != '' }} uses: actions/github-script@v7 with: script: | @@ -90,8 +94,7 @@ jobs: body: `✅ **Preview ready:** ${{ steps.deploy.outputs.url }}` }) - # Create GitHub Deployment card for main branch - - name: Create Deployment Card + - name: Create Deployment Card (main only) if: ${{ github.ref_name == 'main' }} uses: actions/github-script@v7 with: @@ -108,4 +111,5 @@ jobs: deployment_id: dep.id, state: 'success', environment: 'production' + // no environment_url on purpose (per Rez's requirement) }); \ No newline at end of file From 24893dd19d91cde43f43263121f3296067dc55fd Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sun, 12 Oct 2025 14:42:35 -0600 Subject: [PATCH 6/8] ci: add vercel deployment diagnostics for access and API check --- .github/workflows/ci-deploy.yml | 52 ++++++++++++--------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index 6fb89aa..a6f4ab6 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -2,15 +2,14 @@ name: CI + Deploy (prebuilt) on: push: - branches: [ '**' ] + branches: ['**'] pull_request: - branches: [ main ] + branches: [main] permissions: contents: read - deployments: write - pull-requests: write issues: write + deployments: write env: VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} @@ -20,65 +19,51 @@ jobs: build_and_deploy: runs-on: ubuntu-latest steps: - # Checkout repo + # Checkout - uses: actions/checkout@v4 - # Setup Node.js + cache + # Node + npm cache - uses: actions/setup-node@v4 with: node-version: 18 - cache: 'npm' + cache: npm - # Install dependencies + # Install deps - name: Install dependencies run: npm ci || npm install - # Build project - - name: Build app - run: npm run build - - # Install Vercel CLI + # Vercel CLI - name: Setup Vercel CLI run: npm i -g vercel@latest - # Define target (preview or production) - - name: Define target - id: target - run: | - if [ "${{ github.ref_name }}" = "main" ]; then - echo "env=production" >> $GITHUB_OUTPUT - else - echo "env=preview" >> $GITHUB_OUTPUT - fi - - # Pull project config and environment vars + # Pull project config + envs - name: Pull Vercel settings run: | vercel pull --yes \ - --environment="${{ steps.target.outputs.env }}" \ + --environment="$([ '${{ github.ref_name }}' = 'main' ] && echo production || echo preview)" \ --token="${{ env.VERCEL_TOKEN }}" \ --scope="${{ env.VERCEL_ORG }}" - # Prebuild app (creates .vercel/output) - - name: Prebuild Vercel output + # Prebuild (.vercel/output) + - name: Vercel build (prebuilt) run: | vercel build \ --token="${{ env.VERCEL_TOKEN }}" \ --scope="${{ env.VERCEL_ORG }}" - # Deploy prebuilt build to Vercel + # Deploy prebuilt - name: Deploy prebuilt build id: deploy env: VC_TOKEN: ${{ env.VERCEL_TOKEN }} VC_TEAM: ${{ env.VERCEL_ORG }} - ENV: ${{ steps.target.outputs.env }} run: | set -e - ARGS=(deploy --prebuilt --yes --token "$VC_TOKEN" --scope "$VC_TEAM") - [ "$ENV" = "production" ] && ARGS+=(--prod) || true - OUT="$(vercel "${ARGS[@]}")" - # take only public *.vercel.app URL (avoid private Inspect link) + if [ "${{ github.ref_name }}" = "main" ]; then + OUT="$(vercel deploy --prebuilt --prod --yes --token "$VC_TOKEN" --scope "$VC_TEAM")" + else + OUT="$(vercel deploy --prebuilt --yes --token "$VC_TOKEN" --scope "$VC_TEAM")" + fi URL="$(printf "%s\n" "$OUT" | grep -Eo 'https?://[a-zA-Z0-9.-]+\.vercel\.app' | tail -1 || true)" echo "url=$URL" >> "$GITHUB_OUTPUT" echo "✅ Deployed to: ${URL:-(no public URL)}" @@ -111,5 +96,4 @@ jobs: deployment_id: dep.id, state: 'success', environment: 'production' - // no environment_url on purpose (per Rez's requirement) }); \ No newline at end of file From b07304e2d4d0a3811470bc7207567ad2900d4fdb Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sun, 12 Oct 2025 14:53:41 -0600 Subject: [PATCH 7/8] ci: add vercel deployment diagnostics for access and API check --- .github/workflows/ci-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index a6f4ab6..fb9cafc 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -96,4 +96,4 @@ jobs: deployment_id: dep.id, state: 'success', environment: 'production' - }); \ No newline at end of file + }); From c10a91df0fd9f1106886915ba9d30338595ae41e Mon Sep 17 00:00:00 2001 From: Yevhen <38507392+JenyaL@users.noreply.github.com> Date: Sun, 12 Oct 2025 14:55:14 -0600 Subject: [PATCH 8/8] ci: add vercel deployment diagnostics for access and API check --- .github/workflows/ci-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml index fb9cafc..a6f4ab6 100644 --- a/.github/workflows/ci-deploy.yml +++ b/.github/workflows/ci-deploy.yml @@ -96,4 +96,4 @@ jobs: deployment_id: dep.id, state: 'success', environment: 'production' - }); + }); \ No newline at end of file