Skip to content

fix(scratchnode): keep live composer placeholder consistent on mobile #148

fix(scratchnode): keep live composer placeholder consistent on mobile

fix(scratchnode): keep live composer placeholder consistent on mobile #148

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