Skip to content
Open
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
40 changes: 39 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,41 @@ jobs:
- name: Run website script tests
run: node website/test_toEmbedUrl.mjs

# ── Website end-to-end + accessibility (Playwright + axe) ─────────────────
website-e2e:
name: Website (Playwright + axe)
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1

- name: Set up Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"
cache: npm
cache-dependency-path: website/package-lock.json

- name: Install dependencies
working-directory: website
run: npm ci

- name: Install Playwright's Chromium
working-directory: website
run: npx playwright install --with-deps chromium

- name: Run rendering, navigation, editor-removal, XSS, and accessibility tests
working-directory: website
run: npx playwright test

- name: Upload Playwright report on failure
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: website-playwright-report
path: website/playwright-report/
retention-days: 7

# ── Enforce branch flow: main may only receive PRs from dev ───────────────
# No-op on dev PRs (step skipped -> job succeeds). To allow hotfixes straight
# to main, widen the condition below to also accept a 'hotfix/*' head branch.
Expand All @@ -734,7 +769,7 @@ jobs:
name: CI Summary
runs-on: ubuntu-latest
needs:
[lint, rule-validation, secret-scan, sast-bandit, sast-semgrep, sca-pip-audit, sbom, container-scan, backend-tests, frontend, website, enforce-source-branch]
[lint, rule-validation, secret-scan, sast-bandit, sast-semgrep, sca-pip-audit, sbom, container-scan, backend-tests, frontend, website, website-e2e, enforce-source-branch]
if: always()
steps:
- name: Build summary
Expand All @@ -750,6 +785,7 @@ jobs:
BACKEND_TESTS: ${{ needs.backend-tests.result }}
FRONTEND: ${{ needs.frontend.result }}
WEBSITE: ${{ needs.website.result }}
WEBSITE_E2E: ${{ needs.website-e2e.result }}
ENFORCE_SOURCE: ${{ needs.enforce-source-branch.result }}
run: |
python3 - <<'PYEOF'
Expand All @@ -767,6 +803,7 @@ jobs:
("Backend Tests (pytest + coverage)", os.environ["BACKEND_TESTS"]),
("Frontend (lint + build)", os.environ["FRONTEND"]),
("Website (script tests)", os.environ["WEBSITE"]),
("Website (Playwright + axe)", os.environ["WEBSITE_E2E"]),
("Enforce dev to main source", os.environ["ENFORCE_SOURCE"]),
]

Expand Down Expand Up @@ -819,5 +856,6 @@ jobs:
needs.backend-tests.result != 'success' ||
needs.frontend.result != 'success' ||
needs.website.result != 'success' ||
needs.website-e2e.result != 'success' ||
needs.enforce-source-branch.result != 'success'
run: exit 1
4 changes: 4 additions & 0 deletions website/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
.vercel
node_modules
test-results
playwright-report
.last-run.json
25 changes: 22 additions & 3 deletions website/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Vercel picks up `vercel.json` automatically. Every push to `main` triggers a red

## Adding Content

All content lives in `website/content.js`. Edit it directly on a branch and open a PR to `dev`. Alternatively, use the built-in editor at the Blog Editor section (requires a GitHub personal access token with `repo` scope).
All content lives in `website/content.js`. Edit it directly on a branch and open a PR to `dev`. The built-in editor at the Blog Editor section can build and format the entry for you, but it no longer publishes for you directly — it does not ask for or use a GitHub token. Use "Export Entry" to get the formatted snippet, paste it into the right array in `website/content.js`, and open the PR yourself (see #297 — a page that can request a `repo`-scoped credential in the browser is a real risk on its own).

### Blog post

Expand All @@ -47,7 +47,7 @@ All content lives in `website/content.js`. Edit it directly on a branch and open
**Images in blog posts:**
- Cover image: commit to `website/assets/blog/` and set `image: "assets/blog/filename.jpg"`
- Inline images: use standard Markdown `![alt](assets/blog/filename.jpg)` inside the `content` field
- Max file size for GitHub API upload via the editor: **700 KB**. Larger files must be committed manually.
- The editor no longer uploads images for you — commit the file to `website/assets/blog/` yourself as part of your PR.

**Video embeds:**
- Paste a YouTube watch URL (`https://www.youtube.com/watch?v=...`) or Vimeo URL (`https://vimeo.com/...`) into the `video` field
Expand Down Expand Up @@ -121,7 +121,7 @@ Paste the output as the `rules` array in `content.js`.

| Section | Editor support |
|---|---|
| Blog posts | Yes — Blog Post type (image upload, video embed, Markdown content) |
| Blog posts | Yes — Blog Post type (image preview, video embed, Markdown content) |
| Events | Yes — Community Event type |
| Contributors | Yes — New Contributor type |
| Releases | Yes — Release type |
Expand All @@ -145,4 +145,23 @@ python3 -m http.server 8080

---

## Testing

`node test_toEmbedUrl.mjs` runs the fast, pure-function tests (no browser needed).

Rendering, navigation, the removed GitHub-token flow, an XSS regression corpus, and
accessibility (axe + keyboard) are covered by Playwright:

```bash
cd website
npm install
npx playwright install --with-deps chromium # first run only
npm run test:e2e
```

The suite serves the site itself on `127.0.0.1:4173` (see `playwright.config.js`) —
no separate server needs to be running first.

---

Core philosophy: keep it technical, keep it open.
Loading
Loading