Deploy web #1
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: Deploy web | |
| on: | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| deploy: | |
| name: Deploy web to Vercel | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| cache-dependency-path: web/package-lock.json | |
| - name: Deploy web to Vercel | |
| working-directory: web | |
| env: | |
| VERCEL_AUTH_JSON: ${{ secrets.VERCEL_AUTH_JSON }} | |
| VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} | |
| VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} | |
| VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} | |
| run: | | |
| test -n "$VERCEL_ORG_ID" || { echo "VERCEL_ORG_ID secret is required for web deploy"; exit 1; } | |
| test -n "$VERCEL_PROJECT_ID" || { echo "VERCEL_PROJECT_ID secret is required for web deploy"; exit 1; } | |
| if [ -n "$VERCEL_AUTH_JSON" ]; then | |
| VERCEL_CONFIG_DIR="$RUNNER_TEMP/vercel" | |
| mkdir -p "$VERCEL_CONFIG_DIR" | |
| printf '%s' "$VERCEL_AUTH_JSON" > "$VERCEL_CONFIG_DIR/auth.json" | |
| env -u VERCEL_TOKEN npx --yes vercel@latest deploy --prod --yes --global-config "$VERCEL_CONFIG_DIR" | |
| else | |
| test -n "$VERCEL_TOKEN" || { echo "VERCEL_AUTH_JSON or VERCEL_TOKEN secret is required for web deploy"; exit 1; } | |
| npx --yes vercel@latest deploy --prod --yes --token="$VERCEL_TOKEN" | |
| fi | |
| - name: Verify live simulation freshness | |
| run: | | |
| node --input-type=module <<'NODE' | |
| import { readFileSync } from "node:fs"; | |
| const expected = JSON.parse(readFileSync("web/public/sim/vault_sim.json", "utf8")); | |
| const expectedReportAsOf = expected.reportAsOf; | |
| const expectedFillRows = expected.source?.fillRows; | |
| if (!expectedReportAsOf || !expectedFillRows) { | |
| throw new Error("committed simulation JSON is missing reportAsOf/source.fillRows"); | |
| } | |
| let last = {}; | |
| for (let attempt = 1; attempt <= 20; attempt += 1) { | |
| const response = await fetch("https://capletfi.vercel.app/sim/vault_sim.json", { | |
| headers: { "cache-control": "no-cache" }, | |
| }); | |
| if (response.ok) { | |
| const live = await response.json(); | |
| last = { | |
| reportAsOf: live.reportAsOf, | |
| fillRows: live.source?.fillRows, | |
| }; | |
| if (last.reportAsOf === expectedReportAsOf && last.fillRows === expectedFillRows) { | |
| console.log("CAPLETFI_SIM_DEPLOY_FRESH"); | |
| console.log(JSON.stringify({ ...last, attempt }, null, 2)); | |
| process.exit(0); | |
| } | |
| } | |
| await new Promise((resolve) => setTimeout(resolve, 15_000)); | |
| } | |
| throw new Error( | |
| `live sim ${JSON.stringify(last)} did not match committed ${JSON.stringify({ | |
| reportAsOf: expectedReportAsOf, | |
| fillRows: expectedFillRows, | |
| })}`, | |
| ); | |
| NODE |