Merge branch 'feat/cloudflare-hosting' #194
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 (Cloudflare) | |
| # Both public sites are static assets served by a Worker with NO script, in the | |
| # Cloudflare account that also holds the archlang.uk zone. `main` is absent from | |
| # each wrangler.jsonc on purpose: with no code to invoke, every request is a | |
| # static-asset request — free, unmetered, and exempt from the Workers free-plan | |
| # request cap. | |
| # | |
| # We deploy from CI rather than from Cloudflare's Git integration because the | |
| # build is a monorepo build: `npm run docs:build` / `npm run playground:build` | |
| # build the CORE first and then the site (docs-site/sync-docs.mjs hard-exits if | |
| # dist/ is missing), and because the smoke check below belongs welded to the | |
| # deploy that produced it. | |
| # | |
| # Two repository secrets are required: | |
| # CLOUDFLARE_API_TOKEN — Workers Scripts:Edit + Workers Routes:Edit on the | |
| # account, DNS:Edit + Zone:Read on the archlang.uk zone. | |
| # Create at https://dash.cloudflare.com/profile/api-tokens | |
| # CLOUDFLARE_ACCOUNT_ID — the account the Workers live in (not a secret value, | |
| # kept as one so the workflow reads the same way). | |
| # Then push to main (or run this workflow manually) to deploy. | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: cloudflare-deploy-${{ github.ref }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| deploy: | |
| name: Deploy ${{ matrix.name }} | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: docs | |
| dir: docs-site | |
| build: docs:build | |
| url: https://archlang.uk | |
| - name: playground | |
| dir: playground | |
| build: playground:build | |
| url: https://playground.archlang.uk | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| steps: | |
| - name: Check Cloudflare credentials are set | |
| run: | | |
| if [ -z "$CLOUDFLARE_API_TOKEN" ] || [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then | |
| echo "::error::CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID are not set. Add them in Settings → Secrets and variables → Actions, then re-run this workflow." | |
| exit 1 | |
| fi | |
| # fetch-depth: 0 is load-bearing, not caution: docs-site/.vitepress/config.ts | |
| # sets `lastUpdated: true`, which reads each page's git commit time at BUILD | |
| # time. A depth-1 clone has no history, so every "Last updated" stamp would | |
| # silently collapse to the deploy commit. | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - name: Install dependencies | |
| run: npm ci | |
| # Builds the core, then the site. Run from the repo ROOT — both scripts are | |
| # `npm run build && npm -w <workspace> run build`. | |
| - name: Build | |
| run: npm run ${{ matrix.build }} | |
| - name: Install Wrangler | |
| # pinned for reproducibility in a token-bearing job; bump deliberately | |
| run: npm i -g wrangler@4.108.0 | |
| # Uploads the asset directory named by ${{ matrix.dir }}/wrangler.jsonc and | |
| # attaches/keeps its custom domain. Idempotent: an unchanged asset set | |
| # uploads nothing. | |
| - name: Deploy to Cloudflare | |
| working-directory: ${{ matrix.dir }} | |
| run: wrangler deploy | |
| - name: Smoke check (machine routes + assets; retries ~30s for propagation) | |
| # A 200 on `/` proved almost nothing — the site's real contract is the machine | |
| # routes (/llms-full.txt, the raw /<page>.md copies, the schemas, the GBNF grammar, | |
| # the example SVGs) and, on the playground, the hashed JS bundle the shell loads. | |
| # scripts/smoke.mjs checks those; it is zero-dep Node and derives the docs route | |
| # list from docs-site/sync-docs.mjs, so a new page is covered automatically. | |
| run: node scripts/smoke.mjs --site ${{ matrix.name }} --base ${{ matrix.url }} |