CI/CD
This page documents the continuous integration and deployment workflows for the ms package. The project uses GitHub Actions to automate testing, quality checks, and publishing to npm. All workflows are triggered on pushes to the main branch, with some also running on pull requests.
Workflow Overview
The repository defines three GitHub Actions workflows, each responsible for a distinct phase of the CI/CD pipeline:
| Workflow File | Name | Trigger | Purpose |
|---|---|---|---|
.github/workflows/quality.yml | Quality | Push to main, PR to main | Static analysis and code quality checks |
.github/workflows/test.yml | Test | Push to main, PR to main | Unit and runtime tests across Node.js versions |
.github/workflows/release.yml | Publish | Push to main | Build and publish nightly canary releases to npm |
All workflows run on ubuntu-latest runners and use pnpm as the package manager, with caching enabled via actions/setup-node .github/workflows/quality.yml:17-19 .github/workflows/test.yml:17-19 .github/workflows/release.yml:17-19.
Quality Workflow
The Quality workflow ensures codebase health by running four independent tasks in parallel: format, lint, typecheck, and attw .github/workflows/quality.yml:10-12. Each task runs on Node.js 24. The fail-fast: false strategy ensures that all tasks complete even if one fails, providing a full picture of any issues .github/workflows/quality.yml:13-13.
The tasks correspond to the following pnpm scripts defined in package.json:
- format: Checks code formatting (likely via Prettier, configured in
lint-staged.config.ts). - lint: Runs the linter (ESLint) to enforce code style and catch errors.
- typecheck: Executes TypeScript type checking to verify type safety.
- attw: Runs
@arethetypeswrong/clito detect issues with TypeScript type declarations in the package.
This workflow is triggered on every push to main and on every pull request targeting main .github/workflows/quality.yml:3-6.
Test Workflow
The Test workflow runs the project's test suites across multiple Node.js versions to ensure compatibility. It uses a matrix strategy with two dimensions: Node.js version (20, 22, 24) and test task (test:nodejs, test:edge) .github/workflows/test.yml:10-14.
| Task | Purpose |
|---|---|
test:nodejs | Runs unit tests in a standard Node.js environment |
test:edge | Runs tests in an edge-runtime environment (e.g., Cloudflare Workers, Vercel Edge Functions) |
The fail-fast: false strategy is used here as well, so all six combinations (3 Node versions × 2 test tasks) execute independently .github/workflows/test.yml:15-15. This workflow triggers on the same events as the Quality workflow: push to main and pull requests to main .github/workflows/test.yml:3-6.
Publish Workflow
The Publish workflow handles deployment of the package to npm. It is triggered only on pushes to main (not on pull requests) .github/workflows/release.yml:3-5.
Permissions and Authentication
The workflow requires id-token: write permission to support npm provenance .github/workflows/release.yml:7-7. Authentication is configured using an npm auth token stored as a repository secret:
- name: Set NPM Auth Token
run: |
npm config set loglevel verbose
npm config set //registry.npmjs.org/:_authToken=${{ secrets.NPM_TOKEN_ELEVATED }}.github/workflows/release.yml:22-25
The token is also passed as the NPM_TOKEN environment variable during the publish step .github/workflows/release.yml:31-31.
Build Step
Before publishing, the package is built using pnpm build .github/workflows/release.yml:28-28. This compiles the TypeScript source into the distribution format(s) configured in tsdown.config.ts.
Canary (Nightly) Release Process
The Publish workflow creates a nightly canary release rather than publishing the version from package.json directly. The process works as follows:
- Extract base version: The workflow reads the current version from
package.jsonand strips any pre-release suffix by splitting on-and taking the first part.github/workflows/release.yml:33-33. - Generate nightly version: A timestamp is created in
YYYYMMDDHHMMformat. The nightly version string is constructed as{base}-nightly.{timestamp}.github/workflows/release.yml:34-34. - Update version: The package version is updated in-memory (without creating a git tag) using
pnpm version --no-git-tag-version "$NIGHTLY".github/workflows/release.yml:36-36. - Publish to npm: The package is published under the
nightlydist-tag with public access and without git checks.github/workflows/release.yml:37-37.
- name: Publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }}
NPM_CONFIG_PROVENANCE: 'true'
run: |
BASE=$(node -p "require('./package.json').version.split('-')[0]")
DATE=$(date +'%Y%m%d%H%M')
NIGHTLY="${BASE}-nightly.${DATE}"
pnpm version --no-git-tag-version "$NIGHTLY"
pnpm publish --tag nightly --access public --no-git-checks.github/workflows/release.yml:30-37
This approach means that every push to main produces a new nightly release on npm under the nightly tag, allowing consumers to install the latest development version with npm install ms@nightly. The --no-git-checks flag bypasses git-related validation since the version change is not committed. Provenance is enabled via NPM_CONFIG_PROVENANCE: 'true', which attaches a signed attestation to the published package.
Summary of CI/CD Pipeline
The overall pipeline for a push to main proceeds as follows:
- Quality checks run in parallel (format, lint, typecheck, attw) on Node.js 24.
- Tests run across Node.js 20, 22, and 24 for both Node.js and edge environments.
- If all checks pass, the Publish workflow builds the package and publishes a nightly canary release to npm.
Pull requests trigger only the Quality and Test workflows, ensuring that proposed changes meet quality standards and pass tests before merging.
Related Pages
- CI/CD (this page)
- Architecture