Releasing RAMPART¶
This section is for maintainers only. If you don't know who the maintainers are but you need to reach them, please file an issue or (if it needs to remain private) contact the email address listed in pyproject.toml.
Follow the instructions in the order provided.
Note: Releases are immutable, please follow these steps carefully!
1. Release Readiness¶
Before starting the release process, verify the codebase is in a healthy state.
- Check for pending changes. Ask other RAMPART maintainers whether they have any in-flight changes that should land before the release.
- Verify CI pipelines. Confirm that all unit tests, lint, type checks, and coverage gates are green on
main. If anything is failing, fix it before proceeding. - Verify the PyRIT pin. RAMPART pins PyRIT to a specific version in
pyproject.toml. Confirm the pinned version is the one you intend to ship against — see PyRIT Dependency.
2. Decide the Next Version¶
RAMPART follows Semantic Versioning (MAJOR.MINOR.PATCH):
| Component | Increment when |
|---|---|
| MAJOR | Breaking changes to the public API |
| MINOR | New features, new attack/probe types, backward-compatible additions |
| PATCH | Bug fixes, documentation corrections, dependency updates |
Pre-1.0 stability
While RAMPART is below 1.0, minor version bumps may include breaking changes. The API is stabilizing but not yet frozen. The first stable release will be 1.0.0.
3. Remove Deprecated Functionality¶
If you are incrementing the minor version, search the codebase for the new minor version (no leading v) to find occurrences where functionality was deprecated and announced for removal in this version. Typically, functionality is deprecated and stays for two minor versions before being removed.
If you find functionality to remove, merge the removal PR to main before proceeding.
4. Update the Version¶
pyproject.toml¶
Set the version in pyproject.toml to the version established in step 2.
Update README File¶
The README file is published to PyPI and also needs to be updated so the links work properly. Note: There may not be any links to update, but it is good practice to check in case our README changes.
Replace all “main” links like “doc/index.md” with “raw” links that have the correct version number, i.e., “https://raw.githubusercontent.com/microsoft/RAMPART/releases/vx.y.z/docs/index.md”.
For images, update using the “raw” link, e.g., “https://raw.githubusercontent.com/microsoft/RAMPART/releases/vx.y.z/docs/images/RAMPART.png”.
For directories, update using the “tree” link, e.g., “https://github.com/microsoft/RAMPART/tree/releases/vx.y.z/docs/usage"
This is required for the release branch because PyPI does not pick up other files besides the README, which results in local links breaking.
5. Publish the Release Branch to GitHub¶
Commit your changes to a release branch and push the tag:
git checkout -b releases/vx.y.z
git commit -am "release vx.y.z"
git push origin releases/vx.y.z
git tag -a vx.y.z -m "vx.y.z release"
git push --tags
6. Build the Package¶
Install build if it is not already available, then build the wheel and sdist:
You should see output similar to:
7. Test the Built Package¶
This step ensures the new package works out of the box.
Create a clean environment and install the built wheel:
Verify the install:
Confirm the version matches the release and the package is installed under the environment's site-packages. Then run the following smoke checks outside the repository root so you don't accidentally test the editable source instead of the installed wheel:
-
Public API imports. Confirm the top-level symbols resolve without error:
-
Pytest plugin registration. RAMPART ships a pytest plugin via the
pytest11entry point. Confirm pytest discovers it: -
End-to-end smoke test. Run
tests/integration/test_smoke.pyagainst the installed wheel. It exercises an evaluator and a probe throughMockAdapterand requires no external services:
If you need to make changes to fix issues found during testing, cherry-pick from main after the fix lands:
git checkout main && git pull
git log main # find the commit hash to cherry-pick
git checkout releases/vx.y.z
git cherry-pick <commit-hash>
git push origin releases/vx.y.z
git tag -a vx.y.z -m "vx.y.z release" --force
git push --tags --force
Rebuild the package after any cherry-pick and re-test.
8. Publish to PyPI¶
Create a PyPI account if you don't have one and ask another maintainer to add you to the rampart project. Before publishing, have an API token scoped to the project ready (create one in your PyPI project settings).
If successful, the URL https://pypi.org/project/rampart/x.y.z/ will return the new release.
9. Update main¶
After the release is on PyPI, open a PR to main containing only:
- In line with PyPA versioning guidance, bump the version in
pyproject.tomlto the next development version (e.g.,x.y.(z+1).dev0orx.(y+1).0.dev0, depending on the next planned release). - Replace any references to the previous release version in the codebase with the new released version (without
.dev0) where applicable (e.g., installation docs that pin to the latest tag).
Open this PR from a branch separate from your releases/vx.y.z branch.
10. Create the GitHub Release¶
Go to the releases page, select Draft a new release, and choose the tag you pushed in step 5. Click Generate release notes to pre-populate the description.
Structure the description as:
- What's changed — a curated short list of user-facing changes (new features, bug fixes, breaking changes).
- Full list of changes — the auto-generated full changelog.
Maintenance changes, CI updates, and documentation fixes generally belong only in the full list. Verify the New contributors section is accurate. Mark the release as Latest and publish.
Appendix¶
PyRIT Dependency¶
RAMPART pins PyRIT to a specific version in pyproject.toml:
When updating the PyRIT dependency, use the helper script:
Re-run the full test suite after bumping — PyRIT changes are a common source of regressions.
Patch Releases (Cherry-Pick Process)¶
A patch release (e.g., 0.2.0 → 0.2.1) ships a targeted fix — typically a security patch or a critical bug fix — without including other in-flight changes from main.
When to use a patch release¶
- A security vulnerability fix needs to be shipped urgently.
- A critical bug was found in the latest release that blocks users.
- The fix is already merged to
main, butmaincontains other changes that aren't ready for release.
Abbreviated steps¶
-
Create a release branch from the previous tag, not from
main: -
Cherry-pick the fix from
main:Resolve any conflicts manually. Patch-sized fixes typically apply cleanly.
-
Bump the version in
pyproject.tomlto the new patch version. Also update any version-pinned links inREADME.md. -
Push and tag:
-
Follow the regular release process from step 6 onward: build, test, publish to PyPI, update
main, and create the GitHub release. Patch release notes should clearly state the reason for the patch (e.g., "Security fix for…" or "Critical bug fix for…").
Key differences from a regular release¶
| Aspect | Regular release | Patch release |
|---|---|---|
| Branch base | main |
Previous release tag |
| Changes included | Everything on main |
Only cherry-picked fix(es) |
| Deprecated code removal | Yes (if minor bump) | No |
| Release notes | Full changelog with curated summary | Short, focused on the reason for the patch |