fix(scratchnode): keep live composer placeholder consistent on mobile #148
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: Vercel Deploy Hook Backup | |
| # Belt-and-suspenders for the GitHub→Vercel push integration. The native | |
| # webhook silently dropped events for 3+ consecutive merges to main earlier | |
| # this session (the project's `link.sourceless` flag had been set to true, | |
| # which suppressed deploys). We re-wired the integration via | |
| # `vercel git disconnect && vercel git connect`, but webhook integrations | |
| # can drift again — silently. This workflow guarantees that every push to | |
| # main triggers a Vercel Production deploy by `curl`-ing the project's | |
| # Deploy Hook URL directly. If the native webhook works, Vercel | |
| # deduplicates by commit SHA. If it doesn't, this picks up the slack. | |
| # | |
| # Required repo secret: VERCEL_DEPLOY_HOOK_URL | |
| # - Created via Vercel project settings -> Git -> Deploy Hooks | |
| # - Or via API: POST /v1/projects/{id}/deploy-hooks { name, ref: "main" } | |
| # | |
| # See .claude/rules/live_dom_verification.md for the underlying invariant | |
| # this workflow enforces ("don't claim 'live' without a deploy actually | |
| # happening"). | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: "Override ref (default: main)" | |
| required: false | |
| default: "main" | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: vercel-deploy-hook-backup-${{ github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| ping-vercel-deploy-hook: | |
| name: Ping Vercel Deploy Hook | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Sanity-check secret presence | |
| run: | | |
| if [ -z "${{ secrets.VERCEL_DEPLOY_HOOK_URL }}" ]; then | |
| echo "::error::VERCEL_DEPLOY_HOOK_URL secret is missing. Create one in Vercel Project Settings -> Git -> Deploy Hooks (ref: main) and add as a repo secret." | |
| exit 1 | |
| fi | |
| echo "secret-present=true" | |
| # Why this wait: GitHub's main branch HEAD takes a few seconds to | |
| # propagate to Vercel's git-mirror. If we fire the deploy hook | |
| # immediately after a merge, Vercel can clone an OLDER commit and | |
| # ship a build that doesn't contain the just-merged code — exactly | |
| # what bit us on commit 5a4d690 (PR #204): a deploy completed at | |
| # 08:13:43 but built without the merged source, causing 15 minutes | |
| # of stale serving until a manual re-trigger. Native GitHub→Vercel | |
| # webhook integration usually handles this race because it passes | |
| # the commit SHA explicitly; deploy hook URLs do not, so we wait. | |
| - name: Wait for git mirror propagation (race fix) | |
| if: github.event_name == 'push' | |
| run: | | |
| echo "Waiting 60s before firing deploy hook so Vercel's git mirror catches up to GitHub HEAD..." | |
| sleep 60 | |
| echo "Done waiting." | |
| - name: Trigger Vercel deploy hook | |
| env: | |
| DEPLOY_HOOK_URL: ${{ secrets.VERCEL_DEPLOY_HOOK_URL }} | |
| run: | | |
| # Vercel's deploy hook accepts an optional `ref` query param when | |
| # triggered from a non-target branch. We always use main here since | |
| # this workflow is gated on push to main / manual dispatch. | |
| response=$(curl -sS -w "\n%{http_code}" -X POST "$DEPLOY_HOOK_URL") | |
| body=$(echo "$response" | sed '$d') | |
| code=$(echo "$response" | tail -n1) | |
| echo "HTTP $code" | |
| echo "$body" | |
| if [ "$code" != "200" ] && [ "$code" != "201" ]; then | |
| echo "::error::Deploy hook returned non-2xx: $code" | |
| exit 1 | |
| fi | |
| # Tier-A live verification per .claude/rules/live_dom_verification.md: | |
| # poll the production URL until the entry-bundle hash changes from | |
| # whatever was previously served. Times out at ~7 minutes | |
| # (35 polls × 12s). Non-blocking — if Vercel takes longer, we still | |
| # fail loudly so engineers know to check. | |
| - name: Verify new bundle is live (Tier A) | |
| if: github.event_name == 'push' | |
| env: | |
| PROD_URL: https://www.nodebenchai.com | |
| run: | | |
| echo "Capturing baseline bundle hash before deploy completes..." | |
| baseline=$(curl -fsS "$PROD_URL/?nc=$RANDOM-$(date +%s)" 2>/dev/null | grep -oE 'assets/index-[A-Za-z0-9_-]+\.js' | head -1 || echo "none") | |
| echo "Baseline: $baseline" | |
| for i in $(seq 1 35); do | |
| sleep 12 | |
| current=$(curl -fsS "$PROD_URL/?nc=$RANDOM-$(date +%s)" 2>/dev/null | grep -oE 'assets/index-[A-Za-z0-9_-]+\.js' | head -1 || echo "none") | |
| if [ "$current" != "$baseline" ] && [ "$current" != "none" ]; then | |
| echo "::notice::Live bundle rotated to $current after ~$((i*12))s" | |
| echo "live-verified=true" >> "$GITHUB_OUTPUT" 2>/dev/null || true | |
| exit 0 | |
| fi | |
| echo "Poll $i/35: still $current" | |
| done | |
| echo "::warning::Live bundle did not rotate within 7 minutes. Vercel deploy may still be in progress, or edge cache is stuck. Check https://vercel.com/hshum2018-gmailcoms-projects/nodebench-ai" | |
| - name: Summary | |
| if: success() | |
| run: | | |
| echo "## Vercel deploy hook fired" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Triggered for commit \`${{ github.sha }}\` on \`main\` after 60s mirror-propagation wait." >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Vercel deduplicates by commit SHA, so this is a no-op if the native push integration also fired. If the native integration is broken, this is the only thing that ships your code." >> $GITHUB_STEP_SUMMARY |