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
35 changes: 29 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,16 @@ jobs:
demo:
# Records the demo against this commit and uploads it to the public demos
# bucket (stacks/github.ts): PRs get a demo comment linking it and the
# preview, and main's is the one in the README.
needs: deploy
# preview, and main's is the one in the README. It deploys its own stages,
# so it runs alongside test and deploy rather than after them.
needs: check
# tcut's browser pane records through WebKit, which macOS has built in.
runs-on: macos-latest
timeout-minutes: 30
permissions:
contents: read
issues: write
pull-requests: write
outputs:
url: ${{ steps.upload.outputs.url }}
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Expand Down Expand Up @@ -135,18 +136,40 @@ jobs:
- name: Record demo
run: pnpm demo
- name: Upload demo
id: upload
run: |
prefix=${{ github.event_name == 'pull_request' && format('pr-{0}/{1}', github.event.number, github.event.pull_request.head.sha) || 'main' }}
bun packages/demos/upload.ts "$prefix"
echo "DEMO_URL=$DEMO_BASE_URL/$prefix" >> "$GITHUB_ENV"
echo "url=$DEMO_BASE_URL/$prefix" >> "$GITHUB_OUTPUT"
env:
DEMO_BUCKET: ${{ vars.DEMO_BUCKET }}
DEMO_BASE_URL: ${{ vars.DEMO_BASE_URL }}

demo-comment:
# Links the demo and the preview, so it waits for both.
if: github.event_name == 'pull_request'
needs: [deploy, demo]
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- uses: oven-sh/setup-bun@v2
with:
bun-version: 1.4.2
- run: pnpm install --frozen-lockfile
- name: Comment the demo on the PR
if: github.event_name == 'pull_request'
run: bun packages/demos/comment.ts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PULL_REQUEST: ${{ github.event.number }}
DEMO_URL: ${{ needs.demo.outputs.url }}
APP_URL: ${{ needs.deploy.outputs.url }}
DEMO_SHA: ${{ github.event.pull_request.head.sha }}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ alchemy.run.ts stack: `@cafe/backend` Worker + Foldkit Website (VITE
stacks/
github.ts stack: CI infra: Cloudflare credentials as Actions secrets, public R2 bucket for demos
.github/workflows/
ci.yml check → live tests → deploy → demo, one stage per PR
ci.yml check → live tests → deploy, demo in parallel, one stage per PR
cleanup.yml destroys a PR's stages when it closes
packages/
api/ @cafe/api: HTTP API + RPC schemas, safe to import from the browser
Expand Down Expand Up @@ -95,7 +95,7 @@ The e2e tests need Playwright's Chromium: `pnpm --filter @cafe/frontend exec pla
1. **check**: typecheck, lint, frontend unit tests.
2. **test**: backend API tests and Playwright e2e tests against real Cloudflare, in stage `test-pr-<number>` (each suite destroys what it deployed).
3. **deploy**: `alchemy deploy` to stage `pr-<number>` (or `prod` on `main`), with a PR comment linking the preview.
4. **demo**: records the demo (macOS, tcut) and uploads it to the demos bucket: `pr-<number>/<sha>/` goes into the PR's demo comment, `main/` is the README demo. PR demos expire after 30 days.
4. **demo**: records the demo (macOS, tcut) in its own stages, alongside test and deploy, and uploads it to the demos bucket: `pr-<number>/<sha>/` goes into the PR's demo comment (**demo-comment**, once the preview is deployed too), `main/` is the README demo. PR demos expire after 30 days.
5. **cleanup** (`cleanup.yml`): when a PR closes, waits for the PR's CI runs to finish, then `alchemy destroy`s its `pr-<number>` and demo stages. It is a separate workflow so no CI run can cancel it.

CI authenticates with the `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` repository secrets. `stacks/github.ts` writes them from the profile it is deployed with, which must use a Cloudflare API token (requires admin on the repository):
Expand Down
Loading