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
19 changes: 10 additions & 9 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# Dependencies update themselves. Each week Dependabot opens one grouped pull
# request per ecosystem, against master, with releases at least 14 days old;
# dependabot-merge.yml merges it and deploys once CI, Lighthouse included,
# has passed. A pull request that fails CI stays open, and nothing ships.
# Dependencies update themselves. Each week Dependabot opens, against master
# and with releases at least 14 days old, one grouped pull request for the
# minor and patch updates of each ecosystem, and one per major update, so a
# major that breaks the build never holds back the others. dependabot-merge.yml
# merges each one and deploys once CI has passed; one that fails stays open,
# and Dependabot rebases it until a later release makes it pass.
#
# Node itself is not covered by Dependabot: node-lts.yml moves .nvmrc.
version: 2
updates:
- package-ecosystem: npm
Expand All @@ -13,11 +17,7 @@ updates:
groups:
npm:
patterns: ['*']
ignore:
# @astrojs/check supports TypeScript ^5 || ^6. Lift this once it
# supports 7, or the build fails.
- dependency-name: typescript
update-types: ['version-update:semver-major']
update-types: [minor, patch]

- package-ecosystem: github-actions
directory: /
Expand All @@ -28,3 +28,4 @@ updates:
groups:
actions:
patterns: ['*']
update-types: [minor, patch]
25 changes: 15 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
# Checks a pull request before it is merged: formatting, types, a full build,
# browser tests, and Lighthouse against the budgets in lighthouserc.json. It
# deploys nothing.
# then the browser tests and the Lighthouse budgets (tests/). It deploys
# nothing.

name: CI

on:
pull_request:
branches: [develop, master]
# node-lts.yml runs the same checks on a newer Node before switching to it.
workflow_call:
inputs:
node-version:
description: Overrides .nvmrc.
type: string
required: false

concurrency:
group: ci-${{ github.event.pull_request.number }}
group: ci-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

permissions:
Expand All @@ -24,6 +31,7 @@ jobs:

- uses: actions/setup-node@v7.1.0
with:
node-version: ${{ inputs.node-version }}
node-version-file: .nvmrc
cache: npm

Expand All @@ -36,13 +44,10 @@ jobs:
run: npm run build

# What a visitor sees: every section, image and link, the layout from a
# 320px phone up, the four themes, and the page without JavaScript.
- name: Browser tests
# 320px phone up, the four themes, and the page without JavaScript. Then,
# alone, Lighthouse: performance at least 95, accessibility, best
# practices and SEO at 100, no layout shift, a page under 250 KB.
- name: Browser tests and Lighthouse
run: |
npx playwright install --with-deps chromium
npm test

# Fails if performance, accessibility, best practices or SEO drop below
# their budgets, or if the page grows past 250 KB.
- name: Lighthouse
run: npm run lighthouse
28 changes: 26 additions & 2 deletions .github/workflows/dependabot-merge.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Merges Dependabot's pull requests once CI has passed on them, deploys, and
# brings develop up to date. CI (format, types, build, Lighthouse budgets) is
# the gate: a pull request that fails it is left open for a person.
# brings develop up to date. CI (format, types, build, browser tests,
# Lighthouse budgets) is the gate: a pull request that fails it is left open,
# with a comment that notifies the owner.
#
# It runs on workflow_run, after CI, and never checks out the pull request's
# code: it only merges the exact commit CI tested.
Expand Down Expand Up @@ -64,3 +65,26 @@ jobs:
git fetch origin master
git merge --no-edit origin/master
git push origin develop

notify:
if: >-
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.event == 'pull_request' &&
github.event.workflow_run.actor.login == 'dependabot[bot]'
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
RUN_URL: ${{ github.event.workflow_run.html_url }}
OWNER: ${{ github.repository_owner }}
steps:
- name: Say why the update was not merged
run: |
pr=$(gh pr list -R "$REPO" --head "$HEAD_BRANCH" --state open \
--json number,headRefOid --jq ".[] | select(.headRefOid == \"$HEAD_SHA\") | .number")
if [ -z "$pr" ]; then
exit 0
fi
gh pr comment "$pr" -R "$REPO" --body "@$OWNER CI failed on this update, so it was not merged and nothing was deployed. The site stays on the previous versions. Details: $RUN_URL"
82 changes: 82 additions & 0 deletions .github/workflows/node-lts.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Moves the site to the newest Node LTS, which Dependabot does not do: once a
# month, if an LTS line newer than .nvmrc has been LTS for at least 14 days,
# runs CI on it, and only if CI passes, commits the new .nvmrc to master,
# deploys, and brings develop up to date.

name: Node LTS

on:
schedule:
- cron: '0 6 1 * *'
workflow_dispatch:

permissions:
contents: read

jobs:
detect:
runs-on: ubuntu-latest
outputs:
major: ${{ steps.lts.outputs.major }}
steps:
- uses: actions/checkout@v7.0.1
with:
ref: master

- name: Find a newer LTS line, at least 14 days old
id: lts
run: |
current=$(cat .nvmrc)
cutoff=$(date -d '14 days ago' +%s)
# For each LTS line, the date of its first LTS release.
major=$(curl -fsSL https://nodejs.org/dist/index.json | jq --argjson cutoff "$cutoff" '
[.[] | select(.lts != false)
| {major: (.version | ltrimstr("v") | split(".")[0] | tonumber), date}]
| group_by(.major) | map(min_by(.date))
| map(select((.date + "T00:00:00Z" | fromdateiso8601) <= $cutoff) | .major)
| max')
echo "Current $current, newest LTS old enough: $major"
if [ "$major" -gt "$current" ]; then
echo "major=$major" >> "$GITHUB_OUTPUT"
fi

check:
needs: detect
if: needs.detect.outputs.major
uses: ./.github/workflows/ci.yml
with:
node-version: ${{ needs.detect.outputs.major }}

switch:
needs: [detect, check]
runs-on: ubuntu-latest
permissions:
contents: write
actions: write
env:
GH_TOKEN: ${{ github.token }}
MAJOR: ${{ needs.detect.outputs.major }}
steps:
- uses: actions/checkout@v7.0.1
with:
ref: master
fetch-depth: 0

- name: Commit the new .nvmrc to master
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
echo "$MAJOR" > .nvmrc
git commit -am "build(node): move to Node $MAJOR, the active LTS"
git push origin master

# A push made with the workflow token does not trigger other workflows,
# so the deployment is started explicitly.
- name: Deploy
run: gh workflow run deploy.yml --ref master

- name: Bring develop up to date
run: |
git checkout develop
git merge --no-edit master
git push origin develop
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@ node_modules/
*.log
.DS_Store
.tern-port
.lighthouseci/
test-results/
playwright-report/
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,5 @@ dist
.astro
node_modules
package-lock.json
.lighthouseci
test-results
playwright-report
41 changes: 23 additions & 18 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ and hold no text of their own, except section headings.
2. Run `npm run dev` and check the page in a light and a dark theme: the
theme follows the clock, so change the hour, or set `data-season` and
`data-time` on `<html>` in the browser's inspector.
3. Before pushing: `npm run format`, then `npm run build && npm test && npm run lighthouse`.
3. Before pushing: `npm run format`, then `npm run build && npm test`.
The first time, `npx playwright install chromium` downloads the test browser.
4. Open a pull request into `develop`. CI runs the same checks; it must pass.
5. To publish, merge `develop` into `master`. `deploy.yml` builds and deploys.

## Standards the checks hold

| Check | Budget | Where |
| ---------------------------------- | ------------------------------- | ------------------- |
| Formatting | Prettier, no diff | `npm run format` |
| Types | `astro check`, strict, 0 errors | `npm run build` |
| Browser tests | All pass | `tests/` |
| Lighthouse performance | ≥ 95 | `lighthouserc.json` |
| Accessibility, best practices, SEO | 100 | `lighthouserc.json` |
| Layout shift (CLS) | ≤ 0.01 | `lighthouserc.json` |
| Page weight | ≤ 250 KB | `lighthouserc.json` |
| Check | Budget | Where |
| ---------------------------------- | ------------------------------- | -------------------------- |
| Formatting | Prettier, no diff | `npm run format` |
| Types | `astro check`, strict, 0 errors | `npm run build` |
| Browser tests | All pass | `tests/` |
| Lighthouse performance | ≥ 95 | `tests/lighthouse.spec.ts` |
| Accessibility, best practices, SEO | 100 | `tests/lighthouse.spec.ts` |
| Layout shift (CLS) | ≤ 0.01 | `tests/lighthouse.spec.ts` |
| Page weight | ≤ 250 KB | `tests/lighthouse.spec.ts` |

Text colours must meet WCAG AA (4.5:1) in all four themes: a new colour is
checked against every background it sits on.
Expand All @@ -54,17 +54,22 @@ checked against every background it sits on.

Dependencies update themselves; nobody has to accept a pull request.

- Every Monday, Dependabot opens one grouped pull request for npm and one for
GitHub Actions, against `master`, with releases at least 14 days old
(`cooldown` in `.github/dependabot.yml`).
- CI runs on it: format, types, build, browser tests, Lighthouse budgets.
- Every Monday, Dependabot opens, against `master` and with releases at least
14 days old (`cooldown` in `.github/dependabot.yml`), one grouped pull
request for the minor and patch updates of npm and one of GitHub Actions,
and one pull request per major update. Security fixes come as soon as they
are published.
- CI runs on each: format, types, build, browser tests, Lighthouse budgets.
- If CI passes, `dependabot-merge.yml` merges it, deploys, and merges `master`
back into `develop`.
- If CI fails, the pull request stays open and nothing ships. That is the one
case that needs a person: usually a major version that needs a code change.
- If CI fails, the pull request stays open, nothing ships, and a comment
notifies the owner. A major that is not supported yet by another package
usually passes on its own later: Dependabot rebases it as the rest updates.
- Node is not covered by Dependabot. On the 1st of each month, `node-lts.yml`
moves `.nvmrc` to the newest Node LTS that has been LTS for 14 days, if CI
passes on it, then deploys.
- Every version is exact (`.npmrc` sets `save-exact`), in `package.json` and in
workflows (`actions/checkout@v7.0.1`, not `@v7`). Node follows the active LTS
(`.nvmrc`).
workflows (`actions/checkout@v7.0.1`, not `@v7`).

## Commits

Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ runs in the browser: the only JavaScript picks the theme and fades sections in.

## Working on it

Node 24 (see `.nvmrc`).
Node, the active LTS (see `.nvmrc`; it updates itself).

```bash
npm ci
npm run dev # http://localhost:4321, reloads on save
npm run build # type-checks, then builds into dist/
npm run preview # serves dist/ as it will be deployed
npm run format # Prettier, Astro files included
npm run lighthouse # Lighthouse against the budgets, on the last build
npm test # browser tests, then Lighthouse budgets, on the last build
```

## Where things are
Expand Down Expand Up @@ -54,6 +54,7 @@ served from this site.

A push to `master` builds the site and publishes it with GitHub Actions
(`deploy.yml`). Work happens on `develop`; pull requests are checked by `ci.yml`.
Dependencies update and deploy themselves once CI passes (`dependabot-merge.yml`).
Dependencies, and Node, update and deploy themselves once CI passes
(`dependabot-merge.yml`, `node-lts.yml`).

How to change the site, and the standards CI holds it to: [CONTRIBUTING.md](CONTRIBUTING.md).
20 changes: 0 additions & 20 deletions lighthouserc.json

This file was deleted.

Loading
Loading