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
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "monthly"
groups:
all-npm:
patterns:
- "*"
open-pull-requests-limit: 1
labels:
- "dependencies"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
groups:
all-actions:
patterns:
- "*"
open-pull-requests-limit: 1
labels:
- "dependencies"
86 changes: 86 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Builds every pull request and every push to main, and deploys main.
#
# The build job's name is the required check in the branch ruleset, so renaming
# it silently drops the gate.
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

concurrency:
# A pull request's run is superseded by its next push; a run on main is never
# cancelled, so a deploy is never cut off halfway.
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

jobs:
build:
name: Build and check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version-file: .node-version
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm run check
- run: pnpm run build
env:
PUBLIC_POSTHOG_KEY: ${{ vars.POSTHOG_PROJECT_KEY_SITES }}
- uses: actions/upload-artifact@v7
with:
name: dist
path: dist/
include-hidden-files: true
retention-days: 7

deploy:
name: Deploy to withmarfa.com
needs: build
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 10
# One deploy at a time, in order, across runs.
concurrency:
group: deploy-withmarfa-com
cancel-in-progress: false
steps:
- uses: actions/checkout@v7
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version-file: .node-version
cache: pnpm
- run: pnpm install --frozen-lockfile
# Deploys exactly what the build job checked.
- uses: actions/download-artifact@v8
with:
name: dist
path: dist/
- run: pnpm exec wrangler deploy
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ vars.CLOUDFLARE_ACCOUNT_ID }}
# A green run means the site serves this build, not only that the upload
# succeeded: the page must carry this build's script.
- name: Check the live site
run: |
script="$(grep -o '/_astro/[^"]*\.js' dist/index.html | head -1)"
for attempt in 1 2 3 4 5 6; do
if curl -fsS https://withmarfa.com/ | grep -qF "Introducing Marfa" \
&& { [ -z "$script" ] || curl -fsS https://withmarfa.com/ | grep -qF "$script"; }; then
echo "withmarfa.com serves this build"; exit 0
fi
sleep 10
done
echo "::error::withmarfa.com does not serve this build"; exit 1
10 changes: 6 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# WithMarfa website

The source of the public site at `withmarfa.com`: Astro, built to static files and served as a Cloudflare Worker with static assets only. Cloudflare Workers Builds builds every branch and deploys `main`.
The source of the public site at `withmarfa.com`: Astro, built to static files and served as a Cloudflare Worker with static assets only. GitHub Actions builds every pull request and deploys `main`.

## Conventions

Expand Down Expand Up @@ -33,10 +33,11 @@ pnpm preview # build, then serve dist/ with Wrangler as Cloudflare will

## Deploying

- **Merging to `main` deploys.** Workers Builds runs `pnpm run check && pnpm run build`, then `npx wrangler deploy`. A pull request gets a preview URL and a check on GitHub, and the check is required.
- The Worker is `withmarfa-website`; its name in `wrangler.jsonc` must match the one Workers Builds is connected to.
- **Merging to `main` deploys.** The `CI` workflow's `Build and check` job runs `pnpm run check` and `pnpm run build` on every pull request and push; it is the required check. On `main`, the `Deploy to withmarfa.com` job deploys exactly the files that job built with `wrangler deploy`, then fails unless withmarfa.com serves them.
- The workflow uses the `CLOUDFLARE_API_TOKEN` secret, a token that can only deploy Workers in the WithMarfa account and manage Worker routes on withmarfa.com, and the `CLOUDFLARE_ACCOUNT_ID` and `POSTHOG_PROJECT_KEY_SITES` variables. Never commit any of them.
- `withmarfa.com` is the Worker's custom domain (`wrangler.jsonc`). Redirects from `www.withmarfa.com`, `marfa.so` and `www.marfa.so` are zone redirect rules in Cloudflare, not in this repository, because `_redirects` cannot change the host.
- `PUBLIC_POSTHOG_KEY` is a build variable in Workers Builds. A build without it sends nothing, which is what a fork or a local build gets.
- A build without `PUBLIC_POSTHOG_KEY` sends nothing, which is what a fork or a local build gets.
- The fallback when the workflow cannot deploy is `pnpm run build && pnpm exec wrangler deploy` from a shell authenticated to the WithMarfa account.

## Analytics

Expand All @@ -49,6 +50,7 @@ pnpm preview # build, then serve dist/ with Wrangler as Cloudflare will
Report only a problem you can show: name the page, input or step, and what goes wrong.

- **Untrue about Marfa.** Flag a claim about what Marfa does, where it runs or what it costs that withmarfa/marfa or docs.marfa.so contradicts. Never say Marfa Cloud is free.
- **Deploy weakened.** Flag a `paths` filter on `ci.yml`, a renamed `Build and check` job, or a deploy that no longer checks the live site.
- **Analytics grown.** Flag an option in `src/lib/analytics.ts` that turns on autocapture, replay, surveys, flags, cookies or storage, or a static import of `posthog-js`.
- **Policy broken.** Flag an inline script or style, or a new third-party origin, that `public/_headers` does not allow.
- **Private detail committed.** Flag a token, key, account ID, internal hostname or personal path in a tracked file.
Expand Down
Loading