diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml index ca2fd29..2456286 100644 --- a/.github/workflows/release-please.yaml +++ b/.github/workflows/release-please.yaml @@ -5,7 +5,6 @@ on: branches: - main - develop - - chore/update-docs-and-release-process workflow_dispatch: permissions: @@ -22,15 +21,35 @@ jobs: needs: test-suite if: needs.test-suite.outputs.tests_passed == 'true' outputs: - releases_created: ${{ steps.release.outputs.releases_created }} - paths_released: ${{ steps.release.outputs.paths_released }} + releases_created: ${{ steps.release-develop.outputs.releases_created || steps.release-main.outputs.releases_created }} + paths_released: ${{ steps.release-develop.outputs.paths_released || steps.release-main.outputs.paths_released }} steps: + - uses: actions/checkout@v4 + + # Create temporary prerelease config for develop branch + - name: Create prerelease config for develop + if: github.ref == 'refs/heads/develop' + run: | + cat .release-please-config.json | jq '. + {"prerelease": true, "prerelease-type": "alpha"}' > .release-please-config-develop.json + + # Release-please for develop branch (creates alpha prereleases) - uses: googleapis/release-please-action@v4 - id: release + if: github.ref == 'refs/heads/develop' + id: release-develop + with: + config-file: .release-please-config-develop.json + manifest-file: .release-please-manifest.json + target-branch: develop + token: ${{ secrets.GITHUB_TOKEN }} + + # Release-please for main branch (creates stable releases) + - uses: googleapis/release-please-action@v4 + if: github.ref == 'refs/heads/main' + id: release-main with: config-file: .release-please-config.json manifest-file: .release-please-manifest.json - target-branch: develop # FIXME: Change to 'main' after initial setup + target-branch: main token: ${{ secrets.GITHUB_TOKEN }} # Trigger appropriate publish workflows based on release type @@ -45,9 +64,6 @@ jobs: steps: - uses: actions/checkout@v4 - - - - name: Install uv uses: astral-sh/setup-uv@v6 with: @@ -99,7 +115,7 @@ jobs: echo "Version $PROJECT_VERSION (clean: $CLEAN_VERSION) is <= 0.3.2, skipping TestPyPI publish" fi - # For develop branch: trigger TestPyPI build (both alpha and stable releases go to TestPyPI from develop) + # For develop branch: trigger TestPyPI build (alpha prereleases go to TestPyPI from develop) # Publish with "trusted publisher" mechanism: # https://docs.pypi.org/trusted-publishers/ @@ -107,14 +123,14 @@ jobs: # Requires GHA token permission (above in YAML) and PyPI management: # https://test.pypi.org/manage/project/otdf-python/settings/publishing/ - name: Publish package distributions to TestPyPI - if: (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/chore/update-docs-and-release-process') && steps.check_version.outputs.should_publish == 'true' + if: github.ref == 'refs/heads/develop' && steps.check_version.outputs.should_publish == 'true' uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ verbose: true packages-dir: dist/ - # For main branch: trigger PyPI build (both alpha and stable releases go to PyPI from main) + # For main branch: trigger PyPI build (stable releases go to PyPI from main) # Publish with "trusted publisher" mechanism: # https://docs.pypi.org/trusted-publishers/ # diff --git a/.release-please-config.json b/.release-please-config.json index 120e71b..6609e7a 100644 --- a/.release-please-config.json +++ b/.release-please-config.json @@ -1,8 +1,6 @@ { "release-type": "python", "include-v-in-tag": true, - "prerelease-type": "alpha", - "prerelease": true, "bootstrap-sha": "5ed358b3e2e0fd12dc336133f701b4ba5d8a298c", "packages": { ".": { @@ -19,7 +17,7 @@ { "path": "otdf-python-proto/pyproject.toml", "type": "toml", - "jsonpath": "$.project[?(@.name=='otdf-python-proto')].version" + "jsonpath": "$.project.version" }, { "path": "otdf-python-proto/uv.lock", diff --git a/.release-please-manifest.json b/.release-please-manifest.json index beea3f7..8d7a673 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.3.1" + ".": "0.3.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index e5edfc2..825c32f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,29 +1 @@ # Changelog - -## [0.3.1](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-v0.3.0...otdf-python-v0.3.1) (2025-09-05) - - -### Bug Fixes - -* address pre-commit (lint) issues ([f61b020](https://github.com/b-long/opentdf-python-sdk/commit/f61b02033f4a132ee1e552be61917d18d5a0bf4c)) -* omit README from Github releases ([cca9e3e](https://github.com/b-long/opentdf-python-sdk/commit/cca9e3efb9ead3693d401261e3e74debd985653e)) -* use correct 'extra-files' for uv.lock ([0e09171](https://github.com/b-long/opentdf-python-sdk/commit/0e091714cad2a5f462bf0a5444e92d8e71639626)) - - -### Miscellaneous Chores - -* release 0.3.1 ([c1395b1](https://github.com/b-long/opentdf-python-sdk/commit/c1395b1ff6bf02ffb24f20e7d45ca0869ae033f5)) - -## [0.3.0](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-v0.3.0...otdf-python-v0.3.0) (2025-09-05) - - -### Bug Fixes - -* fix publishing ([de00583](https://github.com/b-long/opentdf-python-sdk/commit/de005832c2a961f732f564b6a0380b6007a59b6b)) -* fix publishing ([dbc9f80](https://github.com/b-long/opentdf-python-sdk/commit/dbc9f8002d04ae08dc0403dea61507bd2eb19cd2)) - - -### Miscellaneous Chores - -* release 0.3.0a10 ([3bb4283](https://github.com/b-long/opentdf-python-sdk/commit/3bb42837fa9547273023859db48c4e4f69325273)) -* release 0.3.0a11 ([ce8a520](https://github.com/b-long/opentdf-python-sdk/commit/ce8a52064969aa5e27876c4454d2e32b42a36f5b)) diff --git a/docs/RELEASES.md b/docs/RELEASES.md index 828f270..aabc18c 100644 --- a/docs/RELEASES.md +++ b/docs/RELEASES.md @@ -1,259 +1,132 @@ -# Release Process for Maintainers +# Release Process for OpenTDF Python SDK -This document provides comprehensive guidance for maintainers on the OpenTDF Python SDK release process, including both automated releases and feature branch testing. +This document describes the automated release process for the OpenTDF Python SDK using Release Please and GitHub Actions. -## Legacy Version +## Overview -**NOTE:** For the legacy (`gopy`-based) version of this project, please refer to the [LEGACY_VERSION.md](./LEGACY_VERSION.md) file. +The OpenTDF Python SDK uses a **dual-branch release strategy** with automated publishing: -## Release Overview +- **`develop` branch**: Creates alpha prereleases (e.g., `v1.0.0-alpha.1`) → Published to TestPyPI +- **`main` branch**: Creates stable releases (e.g., `v1.0.0`) → Published to PyPI -The OpenTDF Python SDK uses **Release Please** for automated version management and publishing. The system supports: +This ensures that alpha and stable releases have distinct version numbers and publishing destinations, preventing conflicts between development and production releases. -- **Alpha releases** (e.g., `0.3.0a9`): Automated publishing to both test.pypi.org and pypi.org -- **Stable releases** (e.g., `0.3.0`): Automated publishing to pypi.org only -- **Feature branch testing**: Manual alpha releases from development branches +## Branch Strategy -## Current Version Status +### Develop Branch (Alpha Releases) +- **Purpose**: Development and testing +- **Release Type**: Alpha prereleases (`v1.0.0-alpha.1`, `v1.0.0-alpha.2`, etc.) +- **GitHub Status**: Marked as "pre-release" +- **Publishing Target**: TestPyPI (test.pypi.org) +- **Trigger**: Push to `develop` branch with conventional commits -```bash -# Check current version -uv version --short - -# Preview next alpha version -uv version --bump alpha --dry-run +### Main Branch (Stable Releases) +- **Purpose**: Production releases +- **Release Type**: Stable releases (`v1.0.0`, `v1.0.1`, etc.) +- **GitHub Status**: Marked as stable release +- **Publishing Target**: PyPI (pypi.org) +- **Trigger**: Push to `main` branch with conventional commits -# Preview next stable version -uv version --bump minor --dry-run # or patch/major -``` - -## Automated Release Process (Main Branch) +## Automated Release Process ### Prerequisites ✅ **All tests must pass** before any release: -- Unit tests: `uv run pytest tests/` -- Integration tests: `uv run pytest tests/ -m integration` -- Linting: `uv run ruff check` and `uv run ruff format` -- Platform integration tests (via GitHub Actions) +- Unit tests via GitHub Actions test suite +- Integration tests +- Code quality checks (linting, formatting) -### Standard Release Flow +### For Alpha Releases (Develop Branch) -1. **Commit with Conventional Commit Messages** to `main` branch: +1. **Commit with Conventional Commit Messages** to `develop` branch: ```bash + git checkout develop git commit -m "feat: add new encryption algorithm support" git commit -m "fix: resolve TDF decryption issue with large files" - git commit -m "docs: update SDK configuration examples" - ``` - -2. **Push to Main**: - ```bash - git push origin main + git push origin develop ``` -3. **Automated Process**: - - Release Please creates a PR with version bump and changelog +2. **Automated Process**: + - Release Please creates a PR with alpha version bump and changelog - Once PR is merged, GitHub Actions automatically: - - Runs full test suite (unit, integration, platform tests) - - Builds wheels for multiple platforms (macOS, Linux x86_64, Linux ARM) - - Publishes to PyPI (alpha versions go to both test.pypi.org and pypi.org) - - Creates GitHub release with artifacts - -### Release Type Determination - -The system automatically determines release type based on version format: - -- **Alpha**: `X.Y.ZaN` (e.g., `0.3.0a9`) → Published to test.pypi.org + pypi.org -- **Stable**: `X.Y.Z` (e.g., `0.3.0`) → Published to pypi.org only - -## Manual Release Management - -### Bootstrap Release Please (First Time Setup) - -If this is the first time setting up Release Please: - -```bash -# Bootstrap Release Please for the repository -npx release-please bootstrap \ - --repo-url=b-long/opentdf-python-sdk \ - --release-type=python - -# This creates the initial configuration files and release PR -``` - -### Preview Release Changes + - Runs full test suite + - Builds the package + - Creates GitHub release marked as "pre-release" + - Publishes to TestPyPI (if version > 0.3.2) -```bash -# See what Release Please would create (after bootstrap) -npx release-please release-pr \ - --repo-url=b-long/opentdf-python-sdk \ - --config-file=.release-please-config.json \ - --manifest-file=.release-please-manifest.json -``` - -### Manual Release Creation - -```bash -# Manually trigger GitHub release (if needed) -npx release-please github-release \ - --repo-url=b-long/opentdf-python-sdk \ - --config-file=.release-please-config.json \ - --manifest-file=.release-please-manifest.json -``` - -### Workflow Dispatch - -You can manually trigger releases via GitHub Actions: -- Go to Actions → "Release Please" → "Run workflow" -- Or Actions → "PyPIBuild" → "Run workflow" - -## Feature Branch Alpha Releases (For Testing) +### For Stable Releases (Main Branch) -### When to Use Feature Branch Releases - -Use this approach when you need to test changes before merging to main: -- Testing breaking changes with external users -- Validating integration with downstream systems -- Providing preview releases for feedback - -### Process for Feature Branch Releases - -1. **Create Feature Branch**: +1. **Merge from develop** (or commit directly): ```bash - git checkout -b feature/new-encryption-method - # Make your changes - git commit -m "feat: implement new encryption method" - ``` - -2. **Manually Bump Version** (create unique alpha version): - ```bash - # Option A: Use uv to bump version in pyproject.toml - uv version --bump alpha - - # Option B: Edit pyproject.toml directly to create unique alpha - # If current is 0.3.0a9, you might use 0.3.0a9.dev1 or 0.3.1a1 - ``` - -3. **Update Version Files**: - ```bash - # Update any version references in extra files - # (Release Please normally handles this) - sed -i 's/0.3.0a9/0.3.0a9.dev1/g' src/otdf_python/cli.py - ``` - -4. **Commit Version Changes**: - ```bash - git add . - git commit -m "chore: bump version for feature testing to 0.3.0a9.dev1" + git checkout main + git merge develop + # OR make direct commits with conventional commit messages + git commit -m "feat: stable feature ready for production" + git push origin main ``` -5. **Push Feature Branch**: - ```bash - git push origin feature/new-encryption-method - ``` +2. **Automated Process**: + - Release Please creates a PR with stable version bump and changelog + - Once PR is merged, GitHub Actions automatically: + - Runs full test suite + - Builds the package + - Creates GitHub release marked as stable + - Publishes to PyPI -6. **Manual Build and Publish**: +## Version Numbering - **Option A: GitHub Actions (Recommended)** - - Push to a temporary branch that matches main branch patterns - - Or trigger workflow dispatch with your branch +### Alpha Versions (from develop) +- Format: `vX.Y.Z-alpha.N` (e.g., `v1.0.0-alpha.1`, `v1.0.0-alpha.2`) +- Automatically incremented by Release Please +- Marked as pre-release on GitHub +- Published to TestPyPI - **Option B: Local Build** (for internal testing): - ```bash - # Build wheel locally - uv build +### Stable Versions (from main) +- Format: `vX.Y.Z` (e.g., `v1.0.0`, `v1.0.1`) +- Follow semantic versioning +- Marked as stable release on GitHub +- Published to PyPI - # Install for testing - pip install dist/otdf_python-0.3.0a9.dev1-*.whl +## Manual Release Triggers - # Or upload to test.pypi.org manually - uv publish --repository testpypi dist/* - ``` +You can manually trigger releases via GitHub Actions: +- Go to **Actions** → **"Release Please"** → **"Run workflow"** +- Select the appropriate branch (`develop` for alpha, `main` for stable) -### Feature Branch Naming Convention +## Conventional Commit Messages -For feature branches that need releases, use clear naming: -- `feature/new-encryption-method` -- `experimental/performance-improvements` -- `preview/api-v2` +Release Please determines version bumps based on commit message types: -### Cleanup After Feature Branch Testing +- `feat:` → Minor version bump (new features) +- `fix:` → Patch version bump (bug fixes) +- `BREAKING CHANGE:` → Major version bump (breaking changes) +- `docs:`, `chore:`, `style:` → No version bump +Examples: ```bash -# After merging feature to main, clean up -git branch -d feature/new-encryption-method -git push origin --delete feature/new-encryption-method - -# The main branch release will supersede the feature branch alpha +git commit -m "feat: add support for new TDF format" # Minor bump +git commit -m "fix: resolve memory leak in encryption" # Patch bump +git commit -m "feat!: redesign SDK API (BREAKING CHANGE)" # Major bump ``` -## Version Numbering Strategy - -### Alpha Versions -- **Sequential alphas**: `0.3.0a1`, `0.3.0a2`, `0.3.0a3`... -- **Feature branch alphas**: `0.3.0a9.dev1`, `0.3.1a1.dev1` -- **Experimental**: `0.4.0a1.experimental` - -### Stable Versions -- **Patch releases**: `0.3.0` → `0.3.1` (bug fixes) -- **Minor releases**: `0.3.0` → `0.4.0` (new features) -- **Major releases**: `0.3.0` → `1.0.0` (breaking changes) - -## Testing Release Candidates +## Testing Process -### Before Publishing +### Testing Alpha Releases ```bash -# Run full test suite -uv run pytest tests/ -v +# Install from TestPyPI +pip install --index-url https://test.pypi.org/simple/ otdf-python==1.0.0a1 -# Run integration tests -uv run pytest tests/ -m integration -v - -# Check code quality -uv run ruff check -uv run ruff format --check - -# Type checking (if configured) -uvx ty check src/ +# Test functionality +python -c "import otdf_python; print('Alpha version works!')" ``` -### After Publishing +### Testing Stable Releases ```bash -# Test installation from PyPI -pip install otdf-python==0.3.0a9 +# Install from PyPI +pip install otdf-python==1.0.0 -# Test basic functionality -python -c "import otdf_python; print('Import successful')" - -# Run smoke tests -uv run pytest tests/test_sdk.py::test_basic_functionality -``` - -## Troubleshooting Releases - -### Failed Test Suite -```bash -# Check what failed -uv run pytest tests/ -v --tb=short - -# Fix issues and re-run -uv run pytest tests/ -v -``` - -### Failed Build -- Check GitHub Actions logs -- Verify all platforms build successfully -- Ensure version format is correct - -### Failed PyPI Upload -- Verify PyPI trusted publisher setup -- Check for version conflicts -- Ensure all required metadata is present - -### Version Conflicts -```bash -# If version already exists on PyPI -uv version --bump patch # increment to next available version +# Test functionality +python -c "import otdf_python; print('Stable version works!')" ``` ## Multi-Package Releases @@ -262,72 +135,45 @@ This repository manages two packages: - `otdf-python` (main SDK) - `otdf-python-proto` (protobuf submodule) -Both packages should maintain version sync. Release Please handles this automatically for main branch releases. +Release Please automatically updates version references in both packages using the `extra-files` configuration. -## Security Considerations +## Troubleshooting -- Never commit API keys or credentials -- Trusted publishing prevents credential management -- All releases require passing security tests -- Alpha releases are publicly available on PyPI +### No Release Created +- Verify commits use conventional commit format +- Check that tests pass in GitHub Actions +- Ensure commits were pushed to the correct branch -## Rollback Procedures +### Failed Publishing +- Check GitHub Actions logs for detailed error messages +- Verify PyPI trusted publisher configuration +- Ensure version doesn't already exist on the target repository -### Yanking a Bad Release -```bash -# Yank from PyPI (makes it unavailable for new installs) -uv publish --yank "0.3.0a9" --reason "Critical security issue" +### Version Conflicts +- Alpha and stable releases use different version formats, preventing conflicts +- If conflicts occur, check the Release Please manifest and config files -# Create hotfix release -git checkout main -# Make fixes -git commit -m "fix: critical security issue" -# Follow normal release process -``` +## Emergency Procedures -### Emergency Hotfix +### Hotfix for Stable Release ```bash -# Create hotfix branch from last good release -git checkout v0.3.0 -git checkout -b hotfix/security-fix - -# Make minimal fix -git commit -m "fix: security vulnerability" - -# Merge back to main and release +# Create hotfix directly on main git checkout main -git merge hotfix/security-fix -# Follow normal release process +git commit -m "fix: critical security vulnerability" +git push origin main +# Release Please will create a patch release ``` -## Release Checklist for Maintainers - -### Pre-Release -- [ ] All tests passing locally -- [ ] Integration tests passing -- [ ] Documentation updated -- [ ] CHANGELOG reviewed -- [ ] Version bump appropriate -- [ ] No security issues - -### During Release -- [ ] GitHub Actions tests pass -- [ ] Build artifacts created successfully -- [ ] PyPI upload successful -- [ ] GitHub release created +## Configuration Files -### Post-Release -- [ ] Test installation from PyPI -- [ ] Verify SDK functionality -- [ ] Update any dependent projects -- [ ] Communicate release to users -- [ ] Monitor for issues +- `.release-please-config.json`: Main configuration +- `.release-please-manifest.json`: Version tracking +- `.github/workflows/release-please.yaml`: GitHub Actions workflow -## Support and Escalation +## Support For release issues: -1. Check GitHub Actions logs -2. Review PyPI trusted publisher setup -3. Verify release-please configuration +1. Check GitHub Actions logs in the "Release Please" workflow +2. Review the Release Please documentation +3. Create a GitHub issue with workflow logs 4. Contact repository maintainers -5. Create GitHub issue for persistent problems diff --git a/otdf-python-proto/CHANGELOG.md b/otdf-python-proto/CHANGELOG.md deleted file mode 100644 index 7cccc92..0000000 --- a/otdf-python-proto/CHANGELOG.md +++ /dev/null @@ -1,16 +0,0 @@ -# Changelog - -## [0.3.1](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-proto-v0.3.0...otdf-python-proto-v0.3.1) (2025-09-05) - - -### Miscellaneous Chores - -* release 0.3.1 ([c1395b1](https://github.com/b-long/opentdf-python-sdk/commit/c1395b1ff6bf02ffb24f20e7d45ca0869ae033f5)) - -## [0.3.0](https://github.com/b-long/opentdf-python-sdk/compare/otdf-python-proto-v0.3.0...otdf-python-proto-v0.3.0) (2025-09-05) - - -### Miscellaneous Chores - -* release 0.3.0a10 ([3bb4283](https://github.com/b-long/opentdf-python-sdk/commit/3bb42837fa9547273023859db48c4e4f69325273)) -* release 0.3.0a11 ([ce8a520](https://github.com/b-long/opentdf-python-sdk/commit/ce8a52064969aa5e27876c4454d2e32b42a36f5b)) diff --git a/otdf-python-proto/pyproject.toml b/otdf-python-proto/pyproject.toml index f120b6e..a89de6a 100644 --- a/otdf-python-proto/pyproject.toml +++ b/otdf-python-proto/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "otdf-python-proto" -version = "0.3.1" +version = "0.3.0" description = "Generated protobuf files for OpenTDF Python SDK" readme = "README.md" authors = [ diff --git a/otdf-python-proto/src/otdf_python_proto/__init__.py b/otdf-python-proto/src/otdf_python_proto/__init__.py index 3bfcae0..123e171 100644 --- a/otdf-python-proto/src/otdf_python_proto/__init__.py +++ b/otdf-python-proto/src/otdf_python_proto/__init__.py @@ -5,7 +5,7 @@ and other OpenTDF services. """ -__version__ = "0.3.1" +__version__ = "0.3.0" # Import submodules to make them available from . import authorization diff --git a/otdf-python-proto/uv.lock b/otdf-python-proto/uv.lock index 179ca3b..d410e13 100644 --- a/otdf-python-proto/uv.lock +++ b/otdf-python-proto/uv.lock @@ -481,7 +481,7 @@ wheels = [ [[package]] name = "otdf-python-proto" -version = "0.3.1" +version = "0.3.0" source = { editable = "." } dependencies = [ { name = "connect-python", extra = ["compiler"] }, diff --git a/pyproject.toml b/pyproject.toml index d1e5eb4..311b1b0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "otdf-python" -version = "0.3.1" +version = "0.3.0" description = "Unofficial OpenTDF SDK for Python" readme = "README.md" authors = [ diff --git a/src/otdf_python/cli.py b/src/otdf_python/cli.py index 83873e6..5ef1c93 100644 --- a/src/otdf_python/cli.py +++ b/src/otdf_python/cli.py @@ -22,7 +22,7 @@ from otdf_python.tdf import TDFReaderConfig # Version - get from project metadata -__version__ = "0.3.1" +__version__ = "0.3.0" # Set up logging diff --git a/uv.lock b/uv.lock index a2c1930..c164b51 100644 --- a/uv.lock +++ b/uv.lock @@ -686,7 +686,7 @@ wheels = [ [[package]] name = "otdf-python" -version = "0.3.1" +version = "0.3.0" source = { editable = "." } dependencies = [ { name = "connect-python", extra = ["compiler"] },