Build, Infrastructure, and CI/CD
July 28, 2026 ยท View on GitHub
This is an outline of the tooling that runs the Elements monorepo. This tooling powers a fully automated continuous deployment of many npm packages as well as documentation. This configuration enables:
- Building 30+ libraries, packages and starter projects
- 3500+ unit tests, visual regressions tests and performance lighthouse tests
- Fully automated deployment, versioning and publishing of packages and documentation
The CI pipeline takes an average of ~10 minutes from the moment a PR merges to deploying and becoming available to end users. The average clone, install, and build of the CI pipeline locally takes about ~1-2 min on a MacBook M series.
The local CI job is the same CI job run in GitHub Actions, this ensures that if it passes locally, there is a high probability it passes in CI without issue.
GitHub Features and Integrations
The Elements repo uses standard GitHub tooling to run its CI/CD pipeline.
The .github/workflows/ci.yml contains the configuration for the entire pipeline.
-
Deploy static site hosting with GitHub Actions workflows.
-
Automated workflows for building, testing, and deploying on every push and pull request.
-
The pipeline leverages GitHub Actions cache to cache pnpm installations between jobs, which drastically improves CI speed.
-
Issues templates provide an easy way for users to file bugs or feature requests. This helps ensure the teams get the information they need to have a productive discussion with users.
-
Code Scanning / Security Audits
Security audits such as runtime, dependency, and secret detection scanning.
-
Standardized way to source control large files without bloating git history. Useful for visual regression baseline images.
-
GitHub-hosted runners for executing CI/CD workflows.
-
Ability to upload job build artifacts and outputs that other jobs or CI jobs can reference.
-
Tag artifacts with specific Git tags for standardized release artifact history and tracking.
-
Standardized way to store API keys/secrets.
-
Automated dependency updates and security vulnerability alerts.
-
Publishing with existing Git Tags with Semantic Release
Configure Semantic Release to recognize pre-existing version tags so releases continue from the correct version after migration.
-
Commit Signatures and Verification
Cryptographically sign commits to verify author identity and ensure code integrity across the supply chain.
-
Prevent anyone from modifying or deleting published releases, so downstream consumers always install the exact artifacts reviewers approved and tested.
-
Enforce automated code quality gates on pull requests to catch issues before they merge to main.
-
Define custom secret scanning patterns to detect internal tokens, API keys, or proprietary identifiers that GitHub's built-in patterns may not cover.
-
Enforce the Developer Certificate of Origin on all pull requests, requiring contributors to sign off on their commits to certify they have the right to submit the code.
-
Establish community standards and expectations for contributor behavior in an open source project.
-
Secret Scanning and Push Protection
Block pushes that contain detected secrets before they reach the remote, preventing accidental credential leaks in the repository history.
-
Dependency Monitoring and Alerts
Receive alerts when dependencies have known security vulnerabilities so maintainers can patch or upgrade them promptly.
-
Keep GitHub Actions workflow dependencies up to date automatically, reducing exposure to vulnerabilities in third-party actions.
-
Disable the public issue tracker when project maintainers route bug reports and feature requests through a different channel.
-
Allow external security researchers to report vulnerabilities privately, giving maintainers time to patch before public disclosure.
-
Store sensitive values like API keys and tokens securely, accessible only to GitHub Actions workflows at runtime.
-
Link the GitHub repository directly to npm so GitHub Actions can publish packages through OIDC tokens without storing long-lived npm credentials.
Build
The following are the repo wide tools that apply to all source code and projects.
-
mise installs and activates the repository toolchain from
mise.toml, including Node.js, pnpm, Vale, Go, Git LFS, and Hugo. CI uses the same manifest through the shared setup action. -
pnpm is a NodeJS package manager that enables highly cacheable and fast installs of Node packages.
-
Wireit provides a way to unify node based build tooling across the repo, enabling build caching and dependency based build systems like Bazel.
-
An open source tool for managing automatic publishing and deployment of libraries and packages following semver. Executes a release in the CI environment after every successful build. No human is directly involved in the release process and the tool guarantees releases remain unromantic and unsentimental.
-
A open source tool for compiling and building web applications. Built on Rollup and ESBuild to provide a large plugin ecosystem and fast builds.
Linting/Formatting
-
Husky provides Git hooks to run pre code check ins such as linting and commit formatting. This reduces the turnaround time catching errors before they land in a CI job.
-
Provides a way to lint and format source code only within Git staging.
-
Ensures consistent code formatting for the entire repo.
-
Prose linter for documentation and JSDoc comments. Enforces consistent technical writing using the Google developer documentation style guide and write-good rules. Configuration is in
.vale.iniwith custom vocabulary and rules inconfig/vale/styles/. Vale runs against*.mdand*.tsfiles inprojects/source directories. mise installs the Vale binary for local development and CI.
Testing
-
Used for real browser unit testing and visual regression testing.
-
Built on Vite, Vitest provides testing tools and runners to execute automated tests. These tests can be unit tests, e2e tests or visual snapshots.
-
An open source project providing a suite of e2e tests for performance, accessibility, and general best practices for web development.
Repo Configuration
The following GitHub settings optimize code quality and stability within the repo.
-
Ensure Git tags cannot be overridden or accidentally deleted. This is important for stability and Semantic Release based releases.
-
Protects the
mainbranch and requires going through the PR Review/CI Pipeline process. -
Branch Protection: Require Linear History
Enforce that PRs must be rebased before merging. This ensures a clean Git history with no merge commits. This also ensures there is a 1:1 match of a commit and its release.
-
Branch Protection: Require Status Checks
Ensure the PR passes the CI pipeline which includes automated unit, integration, and performance tests.
-
Provides an easy to deploy static host for documentation and UI applications.
-
Scheduled workflows run nightly builds of the documentation as well as full runs of Lighthouse CI against each of the 50+ components in the Elements library.
The Pages deployment workflow notifies IndexNow after it publishes documentation updates. Before merging changes that enable this workflow, add an INDEXNOW_KEY repository Actions secret containing 8 to 128 letters, numbers, or dashes. The workflow publishes the verification file under the Pages project path, submits only changed sitemap URLs, and retains each notification payload for 30 days so maintainers can rerun a failed notification job.
Release
Semantic Release is an open source tool for managing automatic publishing and deployment of libraries and packages following SEMVER. This enables a fix or feature to be available within minutes of it merging and passing the CI automated tests. To integrate into GitHub, complete the following:
- Generate a
GITHUB_TOKEN(automatically available in GitHub Actions) - Generate an
NPM_TOKENvia npm trusted publishers or access token - Add
NPM_TOKENto the repository secrets - Follow standard Semantic Release tooling/configuration. To see an example of this look at the Elements release.config.cjs file.
Git LFS
To add large static assets such as images and video use Git LFS.
- Add the asset paths to the
.gitattributesfile. Be sure to commit the update to.gitattributesfirst.
# example path
projects/site/assets/**/*.webm filter=lfs diff=lfs merge=lfs -text
projects/site/assets/**/*.webp filter=lfs diff=lfs merge=lfs -text
- Once you commit
.gitattributes, add the assets as a followup commit to ensure Git LFS stores them.