Skip to content

Release Process

This document describes how JARVIS RD Assistant versions are tagged, how the CHANGELOG is generated, and how Docker images are versioned and published.

How We Tag

Releases follow Semantic Versioning: vMAJOR.MINOR.PATCH.

  • MAJOR — breaking API or schema changes that require manual operator steps.
  • MINOR — new features; existing deployments can upgrade with ./update.sh.
  • PATCH — backwards-compatible fixes, security patches, release metadata updates, and maintainer-approved documentation or UX corrections that do not require API, schema, or operator migration changes.

To cut a release:

# 1. Ensure all planned changes have merged and tests pass.
uv run pytest -x
npm --prefix frontend run test -- --run
uv run ruff check services/ libs/ scripts/

# 2. Generate CHANGELOG from conventional commits (see cliff.toml).
git cliff --tag vX.Y.Z -o CHANGELOG.md

# 3. Commit the CHANGELOG.
git add CHANGELOG.md
git commit -m "chore(release): generate CHANGELOG for vX.Y.Z"

# 4. Tag (annotated, not signed — operator choice).
git tag -a vX.Y.Z -m "Release vX.Y.Z — <one-line summary>"

# 5. Push tag and commits.
git push origin HEAD vX.Y.Z

Pre-release Tags

For alpha/beta releases, use semantic versioning with pre-release suffix:

git cliff --tag v0.1.0-alpha --pre-release -o CHANGELOG.md
git tag -a v0.1.0-alpha -m "Release v0.1.0-alpha"

How CHANGELOG Is Generated

CHANGELOG.md is generated by git-cliff, configured in cliff.toml at the repo root. The tool reads conventional-commit messages and groups them into sections.

Commit-to-Section Mapping

The cliff.toml configuration maps conventional-commit prefixes to CHANGELOG sections:

Commit prefix CHANGELOG section
feat Features
fix Bug Fixes
perf Performance
refactor Refactoring
security Security
docs Documentation
test Testing
chore Miscellaneous Tasks

Breaking changes (commits with BREAKING: in body) are highlighted in the output. Merge commits and reverts are automatically filtered out.

Re-generating the Changelog

To regenerate or update CHANGELOG.md after a release, run:

git cliff -o CHANGELOG.md --tag vX.Y.Z

The --tag flag is optional; if omitted, the tool generates entries for all commits since the last Git tag.

Docker Image Versioning

The four main services (paper_ingestion, learning_engine, telegram_bot, dashboard) are tagged using the JARVIS_VERSION environment variable. The compose fallback tracks the current release; set it explicitly in .env or versions.env before building a different version:

JARVIS_VERSION=1.0.4
docker compose build
docker compose up -d

The image: tag in docker-compose.yml is applied to the built result so that docker compose pull works after images have been pushed to a registry.

Release Checklist

Before tagging a release:

  • [ ] All planned changes for the milestone have merged to main.
  • [ ] Version bumped in lockstep: pyproject.toml, frontend/package.json (and package-lock.json, via npm version), the docker-compose.yml JARVIS_VERSION fallback, and the CHANGELOG.md heading + date.
  • [ ] uv run pytest -x passes.
  • [ ] npm --prefix frontend run test -- --run passes.
  • [ ] uv run ruff check services/ libs/ scripts/ is clean.
  • [ ] CHANGELOG.md generated and reviewed.
  • [ ] docs/known-residual-risks.md updated with any newly accepted risks.
  • [ ] Docker images built and smoke-tested against a fresh stack.
  • [ ] All external service keys verified (LiteLLM, Langfuse, SMTP, Telegram).
  • [ ] Tag annotated and pushed.

Rollback Procedures

Code Rollback

Database warning: A git reset --hard without a matching database rollback will leave the schema ahead of the code. Always coordinate a code rollback with a database restore from backup (see below), or use a forward-only "reverse migration" instead.

To revert to a previous release after confirming the DB state is compatible:

# Redeploy the target version
docker compose down
docker compose pull  # if images exist in registry
# Or build locally against the tag's source
docker compose up -d

Database Rollback

Important: Database migrations are intentionally forward-only. There is no automated rollback mechanism. To revert a schema change:

  1. Restore from backup — take a snapshot before upgrading; see scripts/backup.sh for the backup procedure. The backup is AES-256 encrypted when ENC_KEYFILE is set.
  2. Manually craft a "reverse" migration — if a change must be undone in-place, add a new migration that restores the old schema state (e.g., re-add a dropped column with default value).

Always review migration diffs before upgrading. Test migrations on a copy of production data before applying to the live database.