Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 39 additions & 29 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,59 +317,69 @@ async def test_get_user_returns_user_when_found():

## Releasing a New Version

The release workflow (`.github/workflows/release.yml`) builds, tests, and publishes the package. The version is defined in `pyproject.toml`.
The official release flow is the Azure DevOps `eng/ci/library-release.yml`
pipeline. It creates a `release/{version}` branch, updates
`src/azure/connectors/__init__.py`, builds the wheel and source distribution,
creates a GitHub draft release with the artifacts, uploads partner drops, and
then requires a manual partner-release/PyPI step. The package version is loaded
from `azure.connectors.__version__` via `src/pyproject.toml`.

### Standard Release (tag push)
### Standard Release (ADO pipeline)

Creates a GitHub Release with auto-generated notes and publishes to PyPI:
Run the ADO release pipeline with the intended version. The pipeline creates a
bare numeric Git tag such as `1.2.3` or `1.2.3b1`; Python release tags are not
`v`-prefixed.

```shell
git checkout main
git pull origin main
# Update version in pyproject.toml first
git tag v1.2.3
git push origin v1.2.3
# Example versions accepted by the release pipeline:
1.2.3
1.2.3a1
1.2.3b1
1.2.3rc1
```

### Pre-release

Use SemVer pre-release suffixes:
Use Python/PEP 440 pre-release suffixes:

```shell
git tag v1.2.3a1 # Alpha
git tag v1.2.3b1 # Beta
git tag v1.2.3rc1 # Release candidate
git push origin v1.2.3a1
1.2.3a1 # Alpha
1.2.3b1 # Beta
1.2.3rc1 # Release candidate
```

### Manual Dispatch (packages only, no GitHub Release)
### Manual PyPI Publication

Use when you need to publish without creating a tag or GitHub Release:

1. Go to Actions → Release → Run workflow
2. Enter the version (e.g., `1.2.3`)
After artifacts are uploaded to the Azure SDK partner drops location, manually
trigger the partner-release pipeline using the BlobPath printed by the official
pipeline. Return to the original run and approve the final manual gate once the
partner-release pipeline has started.

### Re-releasing a Version

If a release fails midway:
Do not delete or recreate a published release tag as a normal retry path. Release
tags are part of the supply-chain integrity boundary and are protected by tag
rulesets. If a release fails after a tag was pushed, use a new version. For a
retry of the same base package, use a PEP 440 post-release such as
`1.2.3.post1`.

```shell
gh release delete v1.2.3 --yes # delete the failed GitHub Release (if one was created)
git push origin --delete v1.2.3 # delete remote tag
git tag -d v1.2.3 # delete local tag
git tag v1.2.3 # re-tag on current HEAD
git push origin v1.2.3 # push to trigger release
# Run the official release pipeline again with a new version:
1.2.3.post1
```

**Note:** PyPI does not allow re-uploading the same version. If the package was pushed successfully but the release failed, use a new version number (e.g., `1.2.3.post1`).
**Note:** PyPI does not allow re-uploading the same version. If the package was
pushed successfully but the release failed, always use a new version number.
Deleting or retagging an existing remote tag should be treated as break-glass
admin work, not the standard process.

### What the Release Workflow Does

1. Builds and tests with pytest
1. Creates and validates a `release/{version}` branch
2. Builds wheel and sdist with `python -m build`
3. Uploads distribution files as build artifacts
4. Publishes to PyPI (requires `PYPI_API_TOKEN` secret)
5. Creates a GitHub Release with the distribution files attached (tag push only)
3. Creates a GitHub draft release with the distribution files attached
4. Uploads distribution files to Azure SDK partner drops
5. Guides the maintainer through the manual partner-release/PyPI publication

## Adding a New Connector

Expand Down
21 changes: 15 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,21 @@ open _build/html/index.html

## Release Process

Releases are automated via GitHub Actions (`.github/workflows/release.yml`). Only maintainers can create releases.

1. Update version in `src/pyproject.toml`
2. Update `CHANGELOG.md` with release notes
3. Create and push a tag: `git tag v0.1.0 && git push origin v0.1.0`
4. GitHub Actions will build, test, and publish to PyPI
Releases use the Azure DevOps `eng/ci/library-release.yml` pipeline. Only
maintainers can start the release.

1. Update `CHANGELOG.md` with release notes.
2. Run the official release pipeline with the intended version (for example
`1.2.3`, `1.2.3b1`, or `1.2.3.post1`).
3. The pipeline creates `release/{version}`, updates
`src/azure/connectors/__init__.py`, builds the artifacts, creates a GitHub
draft release, and uploads artifacts to Azure SDK partner drops.
4. Trigger the partner-release pipeline for PyPI using the BlobPath printed by
the official release pipeline, then approve the final confirmation gate.

Do not delete or recreate published release tags as a normal retry path. If a
release fails after the tag is pushed, use a new version such as
`1.2.3.post1`; retagging is break-glass admin work only.

See [ROADMAP.md](ROADMAP.md) for release planning.

Expand Down
2 changes: 1 addition & 1 deletion eng/ci/library-release.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
- name: libraryVersion
type: string
displayName: 'Library version to release (e.g., 0.1.0)'
displayName: 'Library version to release (e.g., 0.1.0, 0.1.0b1, 0.1.0.post1)'
- name: blobPath
type: string
default: 'azure-connectors/python/connector-sdk'
Expand Down
6 changes: 3 additions & 3 deletions eng/templates/official/jobs/bump-version.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
parameters:
- name: libraryVersion
type: string
displayName: 'Library version to release (e.g., 0.2.0)'
displayName: 'Library version to release (e.g., 0.2.0, 0.2.0.dev1, 0.2.0b1, 0.2.0.post1)'
- name: githubOrg
type: string
default: 'Azure'
Expand All @@ -24,7 +24,7 @@ jobs:
$githubToken = "$(GithubPat)"
$newLibraryVersion = "${{ parameters.libraryVersion }}"

if($newLibraryVersion -match '^\d+\.\d+\.\d+(dev|a|b|rc)?\d*$') {
if($newLibraryVersion -match '^\d+\.\d+\.\d+((a|b|rc)\d+|\.dev\d+|\.post\d+|-[0-9A-Za-z]+(\.[0-9A-Za-z]+)*)?$') {
# Create GitHub credential
git config --global user.name "AzureConnectors"
git config --global user.email "azurelogicapps@microsoft.com"
Expand All @@ -46,7 +46,7 @@ jobs:
git push origin "release/$newLibraryVersion"

} else {
Write-Host "NewLibraryVersion $newLibraryVersion is malformed (example: 1.5.0)"
Write-Host "NewLibraryVersion $newLibraryVersion is malformed (examples: 1.5.0, 1.5.0.dev1, 1.5.0b1, 1.5.0.post1)"
exit -1
}
displayName: 'Push release/x.y.z'
Expand Down