This document describes how to manage versioning for the Microsoft Agent 365 Python SDK, whether you're creating development builds or official releases.
Observability is retired. Only the eight active workspace distributions may be released. Follow the migration and package-owner checklist for PyPI archival and external/old-branch publishing controls.
Never upload a reusable dist/* directory or an old artifact drop. Each build
below creates a fresh SDK_DIST_DIR and verifies the exact wheel set, version,
metadata dependencies, and absence of retired code. Set the version and build
backend path before invoking a build:
export PYTHONPATH="$PWD/versioning/helper"
export AGENT365_PYTHON_SDK_PACKAGE_VERSION="$(cd versioning && python -m setuptools_git_versioning)"For PowerShell:
$env:PYTHONPATH = Join-Path (Get-Location) "versioning/helper"
Push-Location versioning
$env:AGENT365_PYTHON_SDK_PACKAGE_VERSION = python -m setuptools_git_versioning
Pop-Location
$output = Join-Path ([System.IO.Path]::GetTempPath()) ("agent365-wheels-" + [guid]::NewGuid())
uv build --all-packages --wheel --out-dir $output
uv run --frozen --no-sync python scripts/verify_release_artifacts.py $output --version $env:AGENT365_PYTHON_SDK_PACKAGE_VERSIONThe repository follows a specific branch strategy for releases:
mainbranch: Active development, always contains dev versions (e.g.,0.1.0dev5)release/*branches: Official releases, where tags are created and packages are published- Feature branches: Development work, merges into
main
Important: Official releases and package publishing only happen on release/* branches, never on main.
This repository uses setuptools-git-versioning to automatically calculate version numbers based on Git history. The version is determined by:
- The base version in
versioning/TARGET-VERSION - The number of commits since that file was last modified
- Whether the current commit has a Git tag
- The branch where the commit exists (release branches vs. main/feature branches)
All versions follow PEP 440 format:
- Development versions:
0.1.0dev5(base version + dev + commit count) - Release versions:
0.1.0(exact version from Git tag)
Where versions are generated:
mainand feature branches → Development versions withdevsuffixrelease/*branches with Git tags → Official release versions withoutdevsuffix
Development builds are created automatically for any commit that doesn't have a release tag. These builds include a dev suffix to clearly indicate they are not official releases.
A development version is generated in these scenarios:
-
After making commits to the repository
- Each commit increments the dev counter
- Example:
0.1.0dev1,0.1.0dev2,0.1.0dev3, etc.
-
When working on feature branches
- All commits get dev versions based on commit count
-
In CI/CD pipelines
- Pull requests and branch pushes automatically get dev versions
-
Check your current version:
.\replace-version.ps1Or on Linux/Mac:
cd versioning python -m setuptools_git_versioning -
Build packages with the dev version:
SDK_DIST_DIR="$(mktemp -d)" uv build --all-packages --wheel --out-dir "$SDK_DIST_DIR" uv run --frozen --no-sync python scripts/verify_release_artifacts.py "$SDK_DIST_DIR" --version "$AGENT365_PYTHON_SDK_PACKAGE_VERSION"
-
Example output:
Package version: 0.1.0dev7 Building: microsoft-agents-a365-runtime-0.1.0dev7-py3-none-any.whl
The CI pipeline automatically:
- Checks out the full Git history (
fetch-depth: 0) - Runs
setuptools-git-versioningin theversioning/directory - Sets the
AGENT365_PYTHON_SDK_PACKAGE_VERSIONenvironment variable - Builds all packages with that version
No manual intervention needed!
Official releases are created by tagging specific commits on release/* branches. Once tagged, that commit produces an exact version number without the dev suffix.
Important: Official builds and publishing to package repositories should only happen from
release/*branches, not frommain.
Before creating an official release, ensure:
- All intended changes are merged to
main - All tests pass in CI on
main - Documentation is updated
- Changelog is updated (if applicable)
- You have write permissions to create release branches and tags
Official releases must be done from a release/* branch:
-
Checkout and update
main:git checkout main git pull origin main
-
Create a release branch:
# For version 0.2.0 git checkout -b release/0.2.0 -
Update
versioning/TARGET-VERSION:# For version 0.2.0 echo "0.2.0." > versioning/TARGET-VERSION
-
Commit the version file change:
git add versioning/TARGET-VERSION git commit -m "Bump version to 0.2.0" -
Push the release branch:
git push origin release/0.2.0
-
Wait for CI to pass on the release branch
Note: After this commit, new commits will produce versions like
0.2.0dev0,0.2.0dev1, etc.
-
Ensure you're on the release branch:
git checkout release/0.2.0 git pull origin release/0.2.0
-
Create an annotated Git tag on the release branch:
# For version 0.2.0 git tag -a v0.2.0 -m "Release version 0.2.0"
Tag naming convention:
v{MAJOR}.{MINOR}.{PATCH}- Use semantic versioning
- Always prefix with
v - Examples:
v0.1.0,v1.0.0,v1.2.3 - Must be created on a
release/*branch
-
Push the tag to the remote repository:
git push origin v0.2.0
Important: The workflow has branch-push triggers, not a tag-push trigger. SDK-changing pushes to
release/*may publish development versions without a tag. Tags control version calculation; pushing a tag alone does not start this workflow. Coordinate the tagged build/publication through the approved release pipeline rather than relying on a tag to gate publishing.
-
Check out the tagged commit:
git checkout v0.2.0
-
Verify the version:
.\replace-version.ps1Expected output:
0.2.0(nodevsuffix) -
Build packages:
SDK_DIST_DIR="$(mktemp -d)" uv build --all-packages --wheel --out-dir "$SDK_DIST_DIR" uv run --frozen --no-sync python scripts/verify_release_artifacts.py "$SDK_DIST_DIR" --version "$AGENT365_PYTHON_SDK_PACKAGE_VERSION"
Expected output:
Package version: 0.2.0 Building: microsoft-agents-a365-runtime-0.2.0-py3-none-any.whl
The checked-in workflow verifies and uploads only the fresh wheel directory on
SDK-changing release/* branch pushes, using one downstream job after both
Python 3.11 and 3.12 jobs succeed. It downloads the verified Python 3.11 artifact
and re-verifies its wheels immediately before uploading. Before
publishing, owners must set the repository variable
AGENT365_PACKAGE_REPOSITORY_URL to the approved package-upload endpoint and
configure the AZURE_DEVOPS_TOKEN secret for that feed. The workflow passes the
URL directly to Twine; it does not require a .pypirc or default to public PyPI.
A missing URL fails explicitly before any upload. Downstream promotion to PyPI
must be audited separately. Tags alone do not trigger publication.
For manual releases, first install the locked tools with
uv sync --locked --all-extras --dev, then set TWINE_REPOSITORY_URL to that same
approved endpoint and supply the appropriate TWINE_USERNAME and
TWINE_PASSWORD credentials.
# Only for an explicitly approved manual release, after a fresh build:
: "${TWINE_REPOSITORY_URL:?Set the approved package-upload endpoint}" &&
uv run --frozen --no-sync python scripts/verify_release_artifacts.py "$SDK_DIST_DIR" --version "$AGENT365_PYTHON_SDK_PACKAGE_VERSION" &&
uv run --frozen --no-sync twine upload --non-interactive --repository-url "$TWINE_REPOSITORY_URL" "$SDK_DIST_DIR"/*.whlAfter a successful release, you may want to merge the release branch back to main:
git checkout main
git merge release/0.2.0
git push origin mainYou want to release version 0.1.1 after 0.1.0:
- Create release branch:
git checkout -b release/0.1.1 - Update
versioning/TARGET-VERSIONto0.1.1. - Commit and push:
git push origin release/0.1.1 - Create and push tag:
git tag -a v0.1.1 -m "Release 0.1.1 - Bug fixes" - Push tag:
git push origin v0.1.1
You want to release version 0.2.0 after 0.1.5:
- Create release branch:
git checkout -b release/0.2.0 - Update
versioning/TARGET-VERSIONto0.2.0. - Commit and push:
git push origin release/0.2.0 - Create and push tag:
git tag -a v0.2.0 -m "Release 0.2.0 - New features" - Push tag:
git push origin v0.2.0
You want to release version 1.0.0:
- Create release branch:
git checkout -b release/1.0.0 - Update
versioning/TARGET-VERSIONto1.0.0. - Commit and push:
git push origin release/1.0.0 - Create and push tag:
git tag -a v1.0.0 -m "Release 1.0.0 - First stable release" - Push tag:
git push origin v1.0.0
After releasing 0.2.0 on release/0.2.0 branch, you want to continue development on main for 0.3.0:
- Checkout main:
git checkout main - Update
versioning/TARGET-VERSIONto0.3.0. - Commit and push to main
- Next commit automatically becomes
0.3.0dev0 - Subsequent commits increment:
0.3.0dev1,0.3.0dev2, etc.
You need to create a hotfix 0.2.1 after 0.2.0 has been released:
- Checkout the release branch:
git checkout release/0.2.0 - Create a new branch for the hotfix:
git checkout -b release/0.2.1 - Apply your fixes and commit them
- Update
versioning/TARGET-VERSIONto0.2.1. - Commit and push:
git push origin release/0.2.1 - Create and push tag:
git tag -a v0.2.1 -m "Release 0.2.1 - Hotfix" - Push tag:
git push origin v0.2.1 - Merge back to main:
git checkout main && git merge release/0.2.1
Cause: The AGENT365_PYTHON_SDK_PACKAGE_VERSION environment variable is not set.
Solution:
# Set the environment variable before building
cd versioning
export AGENT365_PYTHON_SDK_PACKAGE_VERSION=$(python -m setuptools_git_versioning)
cd ..
SDK_DIST_DIR="$(mktemp -d)"
uv build --all-packages --wheel --out-dir "$SDK_DIST_DIR"
uv run --frozen --no-sync python scripts/verify_release_artifacts.py "$SDK_DIST_DIR" --version "$AGENT365_PYTHON_SDK_PACKAGE_VERSION"Cause: Git history might be incomplete (shallow clone).
Solution:
# Fetch full Git history
git fetch --unshallowCause: The TARGET-VERSION file wasn't actually committed or modified.
Solution:
- Verify the file change is committed:
git log versioning/TARGET-VERSION - Ensure
count_commits_from_version_file = trueinversioning/pyproject.toml
Cause: You're not on the tagged commit, or the tag wasn't created properly.
Solution:
# Check you're on the tagged commit
git describe --tags --exact-match
# If not, checkout the tag
git checkout v0.2.0
# Verify tag exists
git tag -l "v0.2.0"- Create release branches: Always use
release/*branches for official releases - Always use annotated tags:
git tag -a v1.0.0 -m "Message" - Follow semantic versioning (MAJOR.MINOR.PATCH)
- Update
TARGET-VERSIONbefore tagging for new releases - Test builds locally before pushing tags
- Document releases in changelog/release notes
- Merge release branches back to
mainafter successful releases
- Tag
mainbranch for releases: Official releases must be onrelease/*branches - Use lightweight tags:
git tag v1.0.0(missing-a) - Manually edit version numbers in code
- Delete and recreate tags (causes confusion)
- Skip version numbers (e.g., jump from 0.1.0 to 0.3.0)
- Forget to push tags:
git push --tags - Create releases directly on
mainbranch
| Action | Command |
|---|---|
| Check current version | .\replace-version.ps1 or cd versioning && python -m setuptools_git_versioning |
| Create release branch | git checkout -b release/0.2.0 |
| Update base version | Edit versioning/TARGET-VERSION |
| Create release tag | git tag -a v0.2.0 -m "Release 0.2.0" |
| Push tag | git push origin v0.2.0 |
| Push release branch | git push origin release/0.2.0 |
| List all tags | git tag -l |
| List release branches | git branch -r | grep release/ |
| Delete local tag | git tag -d v0.2.0 |
| Delete remote tag | git push origin :refs/tags/v0.2.0 |
| Build and verify packages | Follow the fresh-directory build procedure |
| View tag details | git show v0.2.0 |
| Merge release to main | git checkout main && git merge release/0.2.0 |
- PEP 440 - Version Identification
- Semantic Versioning 2.0.0
- setuptools-git-versioning Documentation
- Git Tagging Documentation
If you encounter issues with versioning:
- Check this document's Troubleshooting section
- Verify your Git setup with
git logandgit describe - Check CI logs for version calculation errors
- Open an issue with version output and Git status