Skip to content
Merged
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
28 changes: 25 additions & 3 deletions .github/workflows/demo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions: {}
environment: demo
outputs:
url: ${{ steps.version.outputs.url }}
id: ${{ steps.version.outputs.id }}
Expand Down Expand Up @@ -214,7 +215,8 @@ jobs:
mkdir -p placeholder/site
printf '<!doctype html><meta charset="utf-8"><title>Stackyard demo</title><p>The demo is being prepared.</p>\n' > placeholder/site/index.html
printf '/ /index.html 200\n' > placeholder/site/_redirects
cp upload/wrangler.jsonc placeholder/
# Without the routes, so a placeholder never takes the demo address.
node -e 'const c = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); delete c.routes; require("fs").writeFileSync(process.argv[2], JSON.stringify(c, null, 2));' upload/wrangler.jsonc placeholder/wrangler.jsonc

- name: Create the Worker
if: steps.creds.outputs.set == 'true' && steps.worker.outputs.exists == 'false'
Expand Down Expand Up @@ -303,11 +305,31 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions: {}
environment: demo
steps:
- name: Deploy the version
- name: Checkout the Wrangler config
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
path: repo
sparse-checkout: scripts/demo/wrangler.jsonc
sparse-checkout-cone-mode: false

- name: Prepare the config
run: |
set -euo pipefail
mkdir -p promote/site
cp repo/scripts/demo/wrangler.jsonc promote/
rm -rf repo

# Version uploads leave routes alone; triggers deploy applies the demo address.
- name: Deploy the version and its address
uses: cloudflare/wrangler-action@953926a2e2182532811c01a25e53647d93bf07c0 # v4.1.3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
wranglerVersion: ${{ env.WRANGLER_VERSION }}
command: versions deploy ${{ needs.upload.outputs.id }}@100 --name stackyard-demo --yes --message "Stackyard ${{ inputs.version }}"
workingDirectory: promote
command: |
versions deploy ${{ needs.upload.outputs.id }}@100 --yes --message "Stackyard ${{ inputs.version }}"
triggers deploy
1 change: 1 addition & 0 deletions scripts/demo/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"compatibility_date": "2026-10-01",
"workers_dev": true,
"preview_urls": true,
"routes": [{ "pattern": "demo.sandobserver.com", "custom_domain": true }],
"assets": {
"directory": "./site",
"html_handling": "none",
Expand Down
33 changes: 33 additions & 0 deletions test/repo/demo-workflow.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { test } = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const yaml = require('js-yaml');

const root = path.join(__dirname, '..', '..');
const wf = yaml.load(fs.readFileSync(path.join(root, '.github', 'workflows', 'demo.yml'), 'utf8'));
const config = JSON.parse(fs.readFileSync(path.join(root, 'scripts', 'demo', 'wrangler.jsonc'), 'utf8'));
const usesSecret = job => JSON.stringify(job).includes('secrets.CLOUDFLARE');

test('only the demo environment hands out the Cloudflare token', () => {
for (const [name, job] of Object.entries(wf.jobs)) {
if (usesSecret(job))
assert.equal(job.environment, 'demo', `${name} reads a Cloudflare secret outside the environment`);
}
assert.ok(!usesSecret(wf.jobs.build), 'the build job runs dev dependencies');
assert.ok(!usesSecret(wf.jobs.verify), 'the verify job runs dev dependencies');
});

test('the demo address is in the config and applied when a version goes live', () => {
assert.deepEqual(config.routes, [{ pattern: 'demo.sandobserver.com', custom_domain: true }]);
const deploy = wf.jobs.promote.steps.find(s => String(s.with?.command || '').includes('versions deploy'));
assert.ok(deploy, 'the promote job no longer deploys a version');
assert.match(deploy.with.command, /^\s*triggers deploy\s*$/m, 'a version upload alone leaves the address unset');
});

test('the first-run placeholder never takes the demo address', () => {
const prep = wf.jobs.upload.steps.find(s => s.name === 'Prepare the placeholder');
assert.ok(prep, 'the placeholder step is gone');
assert.match(prep.run, /delete c\.routes/);
assert.doesNotMatch(prep.run, /cp upload\/wrangler\.jsonc placeholder/);
});
Loading