Thank you for your interest in contributing to QualOps! This document provides guidelines and instructions for contributing.
# Clone the repository
git clone https://github.com/eggai-tech/qualops.git
cd qualops
# Install dependencies
npm install
# Run tests
npm test
# Run linting
npm run lint
# Build
npm run buildUse descriptive branch names:
feat/- New featuresfix/- Bug fixesdocs/- Documentation changesrefactor/- Code refactoringchore/- Maintenance tasks
Follow Conventional Commits:
feat: add new review pass for security checks
fix: handle empty file arrays in pipeline
docs: update README with new configuration options
chore: update dependencies
Every PR must update CHANGELOG.md under the [Unreleased] section (unless it's a documentation-only or CI change).
Add your changes under the appropriate subsection:
## [Unreleased]
### Added
- New feature description
### Changed
- Change description
### Fixed
- Bug fix description
### Removed
- Removed feature descriptionPRs that only touch docs/, .github/, examples/, or root config files are auto-skipped by CI — no label needed.
- Create a feature branch from
main - Make your changes
- Update
CHANGELOG.mdunder[Unreleased] - Ensure all tests pass:
npm test - Ensure linting passes:
npm run lint - Create a Pull Request to
main - Wait for CI to pass and request review
- All CI checks must pass
- At least one approval required
- Changelog must be updated (or
skip-changeloglabel applied)
QualOps ships on two tiers:
@beta— pre-release track for internal users. Consumed asuses: eggai-tech/qualops@betaornpm install @eggai/qualops@beta.@stable— production track for external clients. Consumed asuses: eggai-tech/qualops@stableor the defaultnpm install @eggai/qualops.
beta and stable are movable lightweight git tags. They are moved automatically by CI on every release or promotion. Never move them by hand. If you find them out of sync, see docs/tdr/0001-release-process.md.
- Make sure
[Unreleased]inCHANGELOG.mdreflects all the changes you intend to ship. - Go to Actions → Create Release PR → Run workflow.
- Enter a pre-release version, e.g.
0.3.0-beta.1. - Review the PR the workflow opens. It bumps
package.jsononly —[Unreleased]is intentionally left untouched on beta releases. - Merge the PR. CI will:
- Tag the commit
v0.3.0-beta.1(immutable). - Publish
@eggai/qualops@0.3.0-beta.1to npm with thebetadist-tag (latestis not touched). - Create a GitHub Release marked as pre-release.
- Force-move the
betagit tag to the release commit.
- Tag the commit
Soak the beta for at least 5–7 days by running it against internal workloads. When you're confident:
- Go to Actions → Promote to Stable → Run workflow.
- Fill in:
beta_version: the beta you want to promote (e.g.,0.3.0-beta.1).stable_version: the clean version (e.g.,0.3.0).reason: short justification — gets surfaced in the PR and the audit log.
- The workflow:
- Verifies the beta exists on npm with the
betadist-tag. - Branches off the exact commit that
v$BETA_VERSIONtags. - Bumps
package.jsonto$STABLE_VERSIONand moves[Unreleased]entries into[$STABLE_VERSION]. - Opens a release PR labelled
promotion.
- Verifies the beta exists on npm with the
- Review the PR. Check the diff against
main— if other PRs have landed since the beta, decide whether those changes need additional soaking before promotion. - Merge the PR. CI will:
- Tag
v0.3.0. - Publish
@eggai/qualops@0.3.0to npm with the defaultlatestdist-tag. - Create a GitHub Release.
- Force-move the
stablegit tag and mark the release as--latest.
- Tag
For an urgent fix to the current stable without going through beta:
git checkout -b hotfix/0.3.1 stable(branch directly off thestabletag).- Apply the fix and update
CHANGELOG.mdunder[Unreleased]. - Run Create Release PR with
0.3.1. Merge. - CI publishes
@eggai/qualops@0.3.1tolatestand force-movesstableto the new commit. - Open a separate PR to merge the fix forward into
main.
We follow Semantic Versioning:
- MAJOR (
1.0.0): Breaking changes. - MINOR (
0.3.0): New features, backward compatible. - PATCH (
0.3.1): Bug fixes, backward compatible.
Pre-release suffix: -beta.N (e.g., 0.3.0-beta.1, 0.3.0-beta.2). The -rc.N and -alpha.N suffixes are also accepted by the workflow and follow the same dist-tag handling as -beta.
stableandbetagit tags point at unexpected commits. Do not move them manually. Open an issue — the recovery path is to run aPromote to Stable(orCreate Release PRfor beta) for the version you want them to point at; CI will overwrite the tag.- A release workflow fails partway. Check the auto-generated failure issue — it lists which stage failed. If
publish-npmsucceeded but a later stage failed, re-running the workflow is safe (later stages are idempotent). Ifpublish-npmitself failed, check npm for partial state before retrying. Create Release PRleft arelease/v*branch behind after a failure. Delete it manually withgit push origin --delete release/vX.Y.Zand re-run.
The full design rationale lives in docs/tdr/0001-release-process.md.
- TypeScript with strict mode
- ESLint + Prettier for formatting
- Run
npm run lint:fixbefore committing
# Run all tests
npm test
# Run specific test file
npx jest path/to/test.spec.ts
# Run tests in watch mode
npx jest --watch
# Run with coverage
npx jest --coverageOpen an issue or reach out to the maintainers.