Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion .github/workflows/vercel-web-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,37 @@ jobs:
run: npx vercel@latest build --prod --token=$VERCEL_TOKEN

- name: Deploy web to Vercel production
id: deploy
working-directory: web
run: npx vercel@latest deploy --prebuilt --prod --token=$VERCEL_TOKEN
run: |
deployment_url="$(npx vercel@latest deploy --prebuilt --prod --token=$VERCEL_TOKEN)"
echo "deployment_url=${deployment_url}" >> "$GITHUB_OUTPUT"

- name: Smoke-check production deployment
env:
DEPLOYMENT_URL: ${{ steps.deploy.outputs.deployment_url }}
PRODUCTION_URL: https://blockdata.run
run: |
node --input-type=module - <<'EOF'
const targets = [
['deployment', process.env.DEPLOYMENT_URL?.trim()],
['production', process.env.PRODUCTION_URL?.trim()],
];

for (const [label, url] of targets) {
if (!url) {
throw new Error(`Missing ${label} url for smoke verification`);
}

const response = await fetch(url, { redirect: 'follow' });
const html = await response.text();

if (!response.ok) {
throw new Error(`${label} smoke check failed with ${response.status} for ${url}`);
}

if (!html.includes('<title>BlockData</title>')) {
throw new Error(`${label} smoke check did not find the BlockData HTML title for ${url}`);
}
}
EOF
13 changes: 13 additions & 0 deletions scripts/tests/vercel-web-deploy-workflow.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,17 @@ test('vercel web deploy workflow is repo-owned and production-scoped', () => {
assert.match(workflow, /vercel@latest pull --yes --environment=production/, 'workflow must pull production config');
assert.match(workflow, /vercel@latest build --prod/, 'workflow must build through Vercel CLI');
assert.match(workflow, /vercel@latest deploy --prebuilt --prod/, 'workflow must deploy the prebuilt output');
assert.match(workflow, /id:\s*deploy/, 'workflow must capture the production deploy step output');
assert.match(workflow, /PRODUCTION_URL:\s*https:\/\/blockdata\.run/, 'workflow must smoke-check the official production domain');
assert.match(workflow, /BlockData/, 'workflow smoke verification must assert the production shell marker');
});

test('web vercel config disables direct master git deployments', () => {
const config = JSON.parse(read('web/vercel.json'));

assert.equal(
config.git?.deploymentEnabled?.master,
false,
'web/vercel.json must disable direct Vercel Git deployments for master so production flows through the repo-owned workflow',
);
});
6 changes: 6 additions & 0 deletions web/vercel.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"git": {
"deploymentEnabled": {
"master": false
}
},
"outputDirectory": "dist",
"rewrites": [
{ "source": "/docs/:path*", "destination": "https://blockdata-ct.vercel.app/docs/:path*" }
Expand Down
Loading