Skip to content

fix: add Authorization header to CORS configuration (#71) #81

fix: add Authorization header to CORS configuration (#71)

fix: add Authorization header to CORS configuration (#71) #81

Workflow file for this run

# CI — runs on every PR and push to the default branch.
#
# Fully hermetic: the build + E2E suites use the vendored docs-example fixture
# (tests/fixtures/docs-example.dist.tar.gz) via apps.json `prebuilt` entries, so
# no GITHUB_TOKEN, network, or sibling repo is required.
#
# Jobs:
# typecheck — astro check (TypeScript / Astro type errors)
# build — headless build from the vendored fixture; uploads dist/
# e2e — Playwright: embedded web-fragment harness + standalone layer
# image — docker build + container integration tests against real nginx + Trivy scan
# audit — npm dependency vulnerability gate
name: CI
on:
push:
branches: [master, main]
pull_request:
branches: [master, main]
# Least privilege: jobs only read the repo. Override per-job if more is needed.
permissions:
contents: read
jobs:
# ── 1. TypeScript / Astro type-check ───────────────────────────────────────
# Non-blocking: `astro check` is memory-hungry and can OOM on standard runners
# (tracked separately). The `build` job below is the hard compile gate — a real
# type/template error fails `astro build`. This job surfaces strict diagnostics
# without wedging CI on an OOM.
typecheck:
name: Type-check (non-blocking)
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- run: npm ci
- name: Astro type-check
run: npx astro check
env:
NODE_OPTIONS: --max-old-space-size=6144
# ── 2. Build (headless, hermetic) ──────────────────────────────────────────
build:
name: Build (headless)
runs-on: ubuntu-latest
needs: typecheck
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- run: npm ci
# Builds from the committed apps.json (vendored fixture) — no token/network.
- name: Build (headless)
run: npm run build:headless
- name: Upload dist artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dist
path: dist/
retention-days: 7
# ── 3. Playwright E2E ──────────────────────────────────────────────────────
#
# Two layers, both hermetic (each webServer rebuilds from the fixture):
# • embedded (playwright.config.js) — full web-fragment harness: host
# gateway proxies/embeds the fragment, shadow-DOM isolation, SPA routing,
# cross-app nav, asset 404s, history limitation.
# • standalone (playwright.config.ci.js) — fragment server only: HTTP header
# safety, headless contract, CSS-link stability (#297), asset routing.
e2e:
name: E2E (Playwright)
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- run: npm ci
- name: Install Playwright browser
run: npx playwright install --with-deps chromium
- name: Embedded web-fragment tests
run: npm test
- name: Standalone fragment tests
run: npx playwright test --config=playwright.config.ci.js
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report
path: playwright-report/
retention-days: 7
# ── 4. publish-single-page-docs action self-test ───────────────────────────
#
# actions/publish-single-page-docs/ ships its own pinned dependency tree, so it is not
# covered by the root `npm ci` or by the Playwright suites (which stay hermetic
# and must not depend on the action's node_modules). This job renders a sample
# markdown file through the real pipeline and pins the validation messages —
# they are the action's user interface for onboarding repos.
publish-single-page-docs:
name: publish-single-page-docs action self-test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
# Matches the node-version the composite action pins in action.yml.
node-version: '20'
cache: npm
cache-dependency-path: actions/publish-single-page-docs/package-lock.json
- run: npm ci
working-directory: actions/publish-single-page-docs
# Action manifests are only parsed by *consuming* repositories' runners, so
# a syntax error here ships green and breaks every downstream workflow at
# "Set up job" (#39). Parse them with the same pinned `yaml` package the
# action already depends on, so this needs no extra tooling.
- name: Validate action manifests
working-directory: actions/publish-single-page-docs
run: |
node -e '
const fs = require("node:fs");
const path = require("node:path");
const YAML = require("yaml");
const root = path.resolve("../..");
const files = [];
(function walk(dir) {
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
if (entry.name === "node_modules") continue;
const full = path.join(dir, entry.name);
if (entry.isDirectory()) walk(full);
else if (/\.ya?ml$/.test(entry.name)) files.push(full);
}
})(path.join(root, "actions"));
if (files.length === 0) {
console.error("no action manifests found under actions/ — check this glob");
process.exit(1);
}
let failed = 0;
for (const file of files) {
const name = path.relative(root, file);
try {
YAML.parse(fs.readFileSync(file, "utf8"));
console.log("ok " + name);
} catch (error) {
failed += 1;
console.error("FAILED " + name + ": " + error.message);
}
}
process.exit(failed === 0 ? 0 : 1);
'
- run: npm run selftest
working-directory: actions/publish-single-page-docs
# ── 5. Container image ─────────────────────────────────────────────────────
#
# Builds the runtime image from the dist/ the build job produced, then scans
# it. `npm audit` below covers JS dependencies only — nothing else in CI looks
# at the nginx base image, which is what the digest pin in the Dockerfile
# exists to control. CRITICAL-only so a routine base-image CVE does not block
# unrelated PRs; the fix is to bump the pinned digest.
image:
name: Image build + integration + scan
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- run: npm ci
- name: Download dist artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: dist
path: dist
# Also proves the Dockerfile's dist/ sanity checks pass on a real build.
- name: Build image
run: docker build -t knowledge-base:ci .
# The CSP checks in the container suite need a real browser: a policy that
# blocks something the page needs fails silently, and only a browser
# reports the violation.
- name: Install Playwright browser
run: npx playwright install --with-deps chromium
# The only place nginx.conf itself is executed. The other suites run
# against tests/fragment-server.mjs, an Express mirror of the rewrites —
# see playwright.config.docker.js for why that is not sufficient.
# KB_SKIP_BUILD reuses the image built above instead of building twice.
- name: Container integration tests
run: npm run test:container
env:
KB_IMAGE: knowledge-base:ci
KB_SKIP_BUILD: 'true'
- name: Scan image
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: knowledge-base:ci
format: table
exit-code: '1'
ignore-unfixed: true
severity: CRITICAL
- name: Upload Playwright report
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-report-container
path: playwright-report/
retention-days: 7
# ── 6. Dependency audit ────────────────────────────────────────────────────
audit:
name: npm audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '24'
cache: npm
- run: npm ci
# Fail only on production-dependency vulnerabilities (high or above).
- name: Audit production dependencies
run: npm audit --omit=dev --audit-level=high