Development and Release Process

Control Tower uses main as the active integration branch. It is where reviewed development work lands, but it is not the stable release channel.

For the most up-to-date released package, install Control Tower from PyPI:

pip install control-tower

Use a checkout of main when you are contributing to the project or need unreleased changes. APIs, commands, and workflows on main may change before the next release.

Development Flow

  1. Create a feature branch from the latest main.
  2. Make the change and update docs when behavior, commands, or workflows change.
  3. Run make check before opening or merging a PR.
  4. Open a PR back into main and follow the PR conventions.
  5. Merge into main after review and passing checks.

Do not use main as a promise of release stability. If you need a version intended for general use, use the latest PyPI release or a GitHub release tag.

Release Flow

Releases are cut from a clean, up-to-date main after tests and checks pass. The release script enforces that the repository is on main, has no uncommitted changes, and matches origin/main before it creates a release branch.

For a Control Tower release:

./scripts/release.sh <major|minor|patch>

For an environment release:

./scripts/release.sh <major|minor|patch> --env <env_name>

The release script:

  1. Creates a release/vX.Y.Z branch from main.
  2. Bumps the version in pyproject.toml.
  3. Updates uv.lock when present.
  4. Prepends a generated entry to CHANGELOG.md.
  5. Commits the release changes, pushes the release branch, and opens a PR into main.

After the release PR is reviewed and merged, GitHub Actions creates the vX.Y.Z tag and GitHub release, publishes the control-tower distribution to PyPI, and builds the versioned internet-simulator image. Release PRs should not be used for unrelated changes.

Pre-Release Checklist

Before cutting a release:

  • Confirm all intended development PRs have merged into main.
  • Pull the latest main and confirm it is clean.
  • Run make check.
  • Use a major bump for breaking changes, a minor bump for backwards-compatible features, and a patch bump for backwards-compatible fixes.
  • Run the release script and review the generated changelog entry before merging the release PR.