Skip to content

feat(app): vault front door, PRF browser gate, honest backup copy, passkey names #75

feat(app): vault front door, PRF browser gate, honest backup copy, passkey names

feat(app): vault front door, PRF browser gate, honest backup copy, passkey names #75

Workflow file for this run

name: Deploy Vault SPA
on:
push:
branches:
- main
paths:
- "app/**"
- ".github/workflows/deploy-app.yml"
pull_request:
paths:
- "app/**"
- ".github/workflows/deploy-app.yml"
# One in-flight deploy per ref. New pushes cancel queued runs so we never
# leak a stale build over a newer commit.
concurrency:
group: deploy-app-${{ github.ref }}
cancel-in-progress: true
jobs:
build-and-deploy:
name: Build & Deploy
runs-on: ubuntu-latest
permissions:
contents: read
deployments: write
pull-requests: write
defaults:
run:
working-directory: app
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 20
cache: npm
cache-dependency-path: app/package-lock.json
- name: Install dependencies
run: npm ci
- name: Typecheck + unit tests
run: |
npx tsc -b --noEmit
npx vitest run
- name: Build
env:
# Production main → real prod relay. Anything else (PR previews,
# branch builds) → staging relay. Keep this in sync with the
# CORS_ORIGINS env var on each Railway service.
VITE_SERVER_URL: ${{ github.ref == 'refs/heads/main' && 'https://api.totalreclaw.xyz' || 'https://api-staging.totalreclaw.xyz' }}
run: npm run build
- name: Publish to Cloudflare Pages
id: deploy
uses: cloudflare/wrangler-action@v4
env:
# wrangler-action did not always propagate the `apiToken` /
# `accountId` inputs into wrangler's process env (observed on v3),
# so set them explicitly here (where wrangler actually reads them)
# as a belt-and-suspenders guard across action versions.
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
workingDirectory: app
# PR previews land on <hash>.totalreclaw-app.pages.dev, main lands
# on the production alias (custom domain once attached). Slashes
# in branch names break the CF Pages branch alias, so replace.
command: pages deploy dist --project-name=totalreclaw-app --branch=${{ github.head_ref && format('pr-{0}', github.event.pull_request.number) || github.ref_name }}
- name: Comment preview URL on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v8
with:
script: |
const url = `${{ steps.deploy.outputs.deployment-url }}`;
if (!url) return;
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const marker = "<!-- vault-spa-preview -->";
const body = `${marker}\n🔗 **Vault SPA preview**: ${url}\n\nBacked by staging relay (\`api-staging.totalreclaw.xyz\`).`;
const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number });
const existing = comments.find(c => c.body && c.body.includes(marker));
if (existing) {
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
} else {
await github.rest.issues.createComment({ owner, repo, issue_number, body });
}
# Fire qa-autopilot on the internal repo against this preview URL. The
# phrase + reporting stay private over there. Skipped if the dispatch
# PAT isn't configured yet (gate-by-secret-presence in the next step).
- name: Check internal-dispatch PAT
id: dispatch_gate
if: github.event_name == 'pull_request' && steps.deploy.outputs.deployment-url != ''
env:
PAT: ${{ secrets.INTERNAL_DISPATCH_PAT }}
run: |
if [ -n "$PAT" ]; then
echo "ready=true" >> "$GITHUB_OUTPUT"
else
echo "ready=false" >> "$GITHUB_OUTPUT"
echo "::notice::INTERNAL_DISPATCH_PAT not set — skipping QA autopilot dispatch"
fi
- name: Trigger QA autopilot on totalreclaw-internal
if: steps.dispatch_gate.outputs.ready == 'true'
env:
GH_TOKEN: ${{ secrets.INTERNAL_DISPATCH_PAT }}
PREVIEW_URL: ${{ steps.deploy.outputs.deployment-url }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
gh workflow run qa-autopilot.yml \
--repo graphprotocol/totalreclaw-internal \
--ref main \
--field target_url="$PREVIEW_URL" \
--field pr_number="$PR_NUMBER"