Skip to content
HELiX

Build Pipeline

apps/docs/src/content/docs/architecture/build-pipeline Click to copy
Copied! apps/docs/src/content/docs/architecture/build-pipeline

The HELIX build pipeline uses Turborepo for local development and CI/CD, ensuring fast, reproducible builds.

Use pnpm run scripts (defined in the root package.json) rather than invoking turbo directly:

Terminal window
# Start all dev servers
pnpm run dev
# Start only docs
pnpm run dev:docs
# Build everything
pnpm run build
# Build only the component library
pnpm run build:library
# Build only docs
pnpm run build:docs
# Type-check all packages
pnpm run type-check

Turborepo automatically resolves build order from dependsOn relationships in turbo.json:

  1. packages/hx-tokens — design token source compiled to CSS custom properties
  2. packages/hx-library — Lit 3.x components built with Vite; CEM (Custom Elements Manifest) generated inline by the build script
  3. packages/hx-react — React wrappers auto-generated from CEM via scripts/generate-react-wrappers.ts
  4. apps/storybook, apps/docs, apps/admin — consume the built packages

The packages/drupal-starter helixui.libraries.yml is generated on-demand by pnpm run generate:drupal-libraries; it is not part of the automatic build order.

Turborepo caches build outputs by default:

  • Local cache: .turbo/ directory (gitignored)
  • Remote cache: not configured; CI uses pnpm dependency cache + Turbo local cache only
  • Cache keys: Hashed from source files, config, and environment variables

Cached outputs per task (from turbo.json):

TaskCached Outputs
builddist/**, build/**, .astro/**, .next/**, custom-elements.json, aaa-verdicts.json, figma-inventory.json
cemcustom-elements.json
generatepackages/hx-react/src/components/**
generate:drupal-librariespackages/drupal-starter/helixui.libraries.yml
test.cache/test-results.json

The CI/CD pipeline (.github/workflows/ci.yml) runs on PRs to dev, staging, and main, and on pushes to those branches. Audit batch branches and non-source PRs skip most jobs via the detect-changes filter.

JobPurposeBlocks merge?
secret-scanDetect leaked credentials (gitleaks)Yes
lintESLint 9 flat configYes
formatPrettier format checkYes
type-checkTypeScript strict — zero errorsYes
buildVite library build + CEM + publish dry-runYes
auditpnpm security auditInformational (network failures + retired audit endpoint don’t fail quality-gates)
testVitest browser mode, path-filtered to changed componentsSkippable (no source changes)
vrtPlaywright visual regression (Chromium only)Skippable
changesetRequires .changeset/*.md for source changesSkippable via skip-changeset label / audit branches / non-source PRs
bundle-sizeEnforces per-component size budgetsSkippable
a11y-auditaxe-core AA regression guard against static Storybook buildYes
storybook-testsStorybook 10 interaction testsYes
quality-gatesAggregate required status check for branch protection

The canonical accessibility cert posture is WCAG 2.2 AAA on the P0 surface, asserted by pnpm aaa:audit and gated locally by preflight (check-aaa-verdicts.mjs). The CI a11y-audit is an additional AA regression sweep, not the cert authority.

Branch protection points to a single quality-gates job rather than individual jobs. This means adding or renaming CI jobs never requires a GitHub admin to update branch protection rules.

The test job uses git diff to identify which component source files changed, then runs Vitest only for those components — typically just the changed components’ test files rather than the full suite (3,200+ tests).

Terminal window
# Equivalent local command
pnpm run test:smart

Before every push, run the full preflight check to catch CI failures locally:

Terminal window
pnpm run preflight

preflight runs 11 gates in order (per scripts/preflight.sh): lint → format:check → type-check → build → smart tests → CEM regen drift → changeset check → full test matrix (conditional) → Docker CI parity (conditional) → AAA verdicts (refuses regression to Partial/Fail) → docs version drift (refuses stale @helixui/* pins).