diff --git a/.bcr/metadata.template.json b/.bcr/metadata.template.json new file mode 100644 index 00000000..07a182a5 --- /dev/null +++ b/.bcr/metadata.template.json @@ -0,0 +1,19 @@ +{ + "homepage": "https://github.com/cncf/xds", + "maintainers": [ + { + "name": "Adi Peleg", + "github_user_id": 4787431, + "github": "adisuissa" + }, + { + "github_user_id": 454682, + "github": "phlax" + } + ], + "repository": [ + "github:cncf/xds" + ], + "versions": [], + "yanked_versions": {} +} diff --git a/.bcr/presubmit.yml b/.bcr/presubmit.yml new file mode 100644 index 00000000..1c9da899 --- /dev/null +++ b/.bcr/presubmit.yml @@ -0,0 +1,17 @@ +matrix: + platform: + - macos + - ubuntu2204 + bazel: + - 7.x + - 8.x + - 9.x +tasks: + verify_targets: + name: "Verify build targets" + platform: ${{ platform }} + bazel: ${{ bazel }} + build_targets: + - "@xds//..." + test_targets: + - "@xds//..." diff --git a/.bcr/source.template.json b/.bcr/source.template.json new file mode 100644 index 00000000..ac0722c1 --- /dev/null +++ b/.bcr/source.template.json @@ -0,0 +1,5 @@ +{ + "integrity": "", + "strip_prefix": "xds-{VERSION}", + "url": "https://github.com/{OWNER}/{REPO}/archive/refs/tags/{TAG}.tar.gz" +} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..58865cf2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: "weekly" diff --git a/.github/workflows/go-release.yml b/.github/workflows/go-release.yml new file mode 100644 index 00000000..b96e122c --- /dev/null +++ b/.github/workflows/go-release.yml @@ -0,0 +1,34 @@ +name: Go Module Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + name: Verify and Test Go Module + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Set up Go + uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 + with: + go-version: '1.24' + + - name: Verify Go module + working-directory: go + run: | + go mod verify + go mod tidy + go build ./... + + - name: Run Go tests + working-directory: go + run: go test ./... -v + diff --git a/.github/workflows/publish-to-bcr.yml b/.github/workflows/publish-to-bcr.yml new file mode 100644 index 00000000..94d50be7 --- /dev/null +++ b/.github/workflows/publish-to-bcr.yml @@ -0,0 +1,21 @@ +name: Publish to BCR + +on: + push: + tags: + - 'v*' + +jobs: + publish: + name: Publish to Bazel Central Registry + permissions: + contents: write + id-token: write + attestations: write + uses: bazel-contrib/publish-to-bcr/.github/workflows/publish.yaml@0bd40ad4f872b4d216d3f01bc0844ade304e2b5a # v1.1.0 + with: + tag_name: ${{ github.ref_name }} + draft: false + secrets: + publish_token: ${{ secrets.BCR_PUBLISH_TOKEN }} + diff --git a/.github/workflows/python-release.yml b/.github/workflows/python-release.yml new file mode 100644 index 00000000..09ca0222 --- /dev/null +++ b/.github/workflows/python-release.yml @@ -0,0 +1,47 @@ +name: Python Package Release + +on: + push: + tags: + - 'v*' + +jobs: + release: + name: Build and Publish Python Package + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/cncf-xds + permissions: + contents: write + id-token: write + + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install build dependencies + run: | + python -m pip install --upgrade pip + pip install build + + - name: Build package + working-directory: python + run: python -m build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 + with: + packages-dir: python/dist/ + + - name: Upload Python artifacts to release + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release upload "${{ github.ref_name }}" python/dist/* + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..6e22587d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Create Release + +on: + push: + tags: + - 'v*' + +jobs: + create-release: + name: Create GitHub Release + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Extract version from tag + id: version + run: | + VERSION=${GITHUB_REF#refs/tags/v} + echo "number=$VERSION" >> $GITHUB_OUTPUT + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ github.token }} + run: | + cat > "$RUNNER_TEMP/release-notes.md" << 'EOF' + # xDS Release ${{ github.ref_name }} + + This release includes updates for all language bindings: + + ## Python (PyPI) + ```bash + pip install cncf-xds==${{ steps.version.outputs.number }} + ``` + + ## Go Module + ```bash + go get github.com/cncf/xds/go@${{ github.ref_name }} + ``` + + ## Bazel (BCR) + ```starlark + bazel_dep(name = "xds", version = "${{ steps.version.outputs.number }}") + ``` + EOF + + gh release create "${{ github.ref_name }}" \ + --title "Release ${{ github.ref_name }}" \ + --notes-file "$RUNNER_TEMP/release-notes.md" \ + --generate-notes + + diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml new file mode 100644 index 00000000..a0708aeb --- /dev/null +++ b/.github/workflows/version-bump.yml @@ -0,0 +1,64 @@ +name: Version Bump + +on: + workflow_dispatch: + inputs: + version: + description: 'New version (e.g., 1.2.3)' + required: true + type: string + create_tag: + description: 'Create and push tag' + required: true + type: boolean + default: false + +jobs: + bump-version: + name: Bump Version + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Update Python version + working-directory: python + run: | + sed -i "s/version = \".*\"/version = \"${{ inputs.version }}\"/" pyproject.toml + cat pyproject.toml + + - name: Update Go version (create VERSION file) + working-directory: go + run: | + echo "${{ inputs.version }}" > VERSION + cat VERSION + + - name: Update Bazel version + run: | + sed -i "s/version = \".*\"/version = \"${{ inputs.version }}\"/" MODULE.bazel + cat MODULE.bazel + + - name: Commit version changes + run: | + git add . + git commit -m "chore: bump version to ${{ inputs.version }}" + git push + + - name: Create and push tag + if: inputs.create_tag + run: | + TAG_NAME="v${{ inputs.version }}" + git tag -a "$TAG_NAME" -m "Release version ${{ inputs.version }}" + git push origin "$TAG_NAME" + echo "Created and pushed tag: $TAG_NAME" + diff --git a/.gitignore b/.gitignore index 0d9fbad4..9ad5727e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ bazel-* MODULE.bazel.lock -__pycache__/ \ No newline at end of file +__pycache__/ + +# Python build artifacts +python/dist/ +python/build/ +python/*.egg-info/ +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ \ No newline at end of file diff --git a/DEVELOPER.md b/DEVELOPER.md index 46a10f53..3ed5ef43 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -8,3 +8,17 @@ Run the following command to update the generated files and commit them with you bazel build //... tools/generate_go_protobuf.py ``` + +## Versioning and Releases + +For information about versioning and the release process, see [VERSIONING.md](VERSIONING.md). + +### Quick Release Guide + +To create a new release: + +1. Use the GitHub Actions **Version Bump** workflow to update the version +2. Or manually create a tag: `git tag python/v1.2.3` or `git tag go/v1.2.3` +3. Push the tag: `git push origin ` +4. The release workflow will automatically build and publish the package + diff --git a/README.md b/README.md index 06f66a59..32b8e4d0 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,21 @@ https://github.com/envoyproxy/envoy/tree/main/api. Our long-term goal is to move the entire API to this repository, this will be done opportunistically over time as we generalize parts of the API to be less client-specific. +## Language Bindings + +This repository provides xDS protocol buffer bindings for multiple languages with unified versioning: + +- **Python**: Available on [PyPI](https://pypi.org/project/cncf-xds/) - `pip install cncf-xds` +- **Go**: Available as a Go module - `go get github.com/cncf/xds/go` +- **Bazel**: Available on [Bazel Central Registry](https://registry.bazel.build/) - Add to `MODULE.bazel`: + ```starlark + bazel_dep(name = "xds", version = "X.Y.Z") + ``` + +All language bindings share the same version number and are released together. + +For versioning and release information, see [VERSIONING.md](VERSIONING.md). + # Mailing list and meetings We have an open mailing list [xds-wg@lists.cncf.io](https://lists.cncf.io/g/xds-wg/) for communication and announcements. We also meet diff --git a/VERSIONING.md b/VERSIONING.md new file mode 100644 index 00000000..ec639ac8 --- /dev/null +++ b/VERSIONING.md @@ -0,0 +1,145 @@ +# Versioning Guide + +This document describes the versioning and release process for the xDS project. + +## Overview + +The xDS project uses a unified version across all language ecosystems: + +- **Python**: Published to PyPI as the `xds` package +- **Go**: Published as Go modules at `github.com/cncf/xds/go` +- **Bazel**: Published to Bazel Central Registry (BCR) as `xds` module + +All ecosystems share the same version number and are released together. + +## Version Format + +All versions follow [Semantic Versioning 2.0.0](https://semver.org/): + +- **MAJOR** version for incompatible API changes +- **MINOR** version for backwards-compatible functionality additions +- **PATCH** version for backwards-compatible bug fixes + +## Tag Format + +A single tag format is used for all ecosystems: + +- Releases: `v1.2.3` + +Pushing a `v*` tag triggers releases for Python (PyPI), Go (GitHub release), and Bazel (BCR) simultaneously. + +## Release Process + +### Manual Version Bump + +Use the Version Bump workflow to update version numbers across all ecosystems: + +1. Go to **Actions** → **Version Bump** +2. Click **Run workflow** +3. Enter the new version (e.g., `1.2.3`) +4. Choose whether to create a tag immediately +5. Click **Run workflow** + +This will: +- Update the version in Python's `pyproject.toml` +- Update the version in Go's `VERSION` file +- Update the version in Bazel's `MODULE.bazel` +- Commit the changes +- Optionally create and push a version tag + +### Automated Release + +When a `v*` tag is pushed, all release workflows are triggered simultaneously: + +#### Release Creation +1. A unified GitHub release is created with release notes +2. Release includes installation instructions for all ecosystems + +#### Python +1. Builds the Python package +2. Publishes to PyPI +3. Uploads Python distribution artifacts to the release + +#### Go +1. Verifies the Go module +2. Runs tests + +#### Bazel +1. Automatically publishes to Bazel Central Registry using the `publish-to-bcr` reusable workflow +2. Generates BCR entry files (MODULE.bazel, source.json, presubmit.yml, metadata.json) +3. Creates attestations for security verification +4. Opens a pull request to bazelbuild/bazel-central-registry + + +### Creating a Release Manually + +To create a unified release for all ecosystems: + +```bash +# Update version in all ecosystem files +cd python +sed -i 's/version = ".*"/version = "X.Y.Z"/' pyproject.toml +cd ../go +echo "X.Y.Z" > VERSION +cd .. +sed -i 's/version = ".*"/version = "X.Y.Z"/' MODULE.bazel + +# Commit changes +git add python/pyproject.toml go/VERSION MODULE.bazel +git commit -m "chore: bump version to X.Y.Z" +git push + +# Create and push tag (this will trigger all release workflows) +git tag vX.Y.Z +git push origin vX.Y.Z + +# The following happens automatically: +# - Python package is built and published to PyPI +# - Go module release is created on GitHub +# - publish-to-bcr workflow generates BCR entry and opens PR to bazel-central-registry +``` + +## Publishing Credentials + +### Python (PyPI) + +The Python release workflow uses OIDC trusted publishing. To configure: + +1. Go to PyPI → Account Settings → Publishing +2. Add a new publisher: + - PyPI Project Name: `xds` + - Owner: `cncf` + - Repository: `xds` + - Workflow: `python-release.yml` + - Environment: (leave empty) + +No API tokens are needed with OIDC. + +### Go Modules + +Go modules are automatically published when tags are pushed. No additional setup required. + +### Bazel (BCR) + +Bazel modules are automatically published to the Bazel Central Registry using the `publish-to-bcr` reusable workflow: + +#### Setup (One-time) + +1. **Fork the BCR**: Fork [bazel-central-registry](https://github.com/bazelbuild/bazel-central-registry) to the CNCF organization or appropriate account +2. **Create a Personal Access Token (PAT)**: + - Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic) + - Create a new token with `repo` and `workflow` scopes + - Save it as a repository secret named `BCR_PUBLISH_TOKEN` +3. **Update the workflow**: Set `registry_fork` in `.github/workflows/publish-to-bcr.yml` to the CNCF fork (currently set to `cncf/bazel-central-registry`) + +#### How It Works + +When you push a `v*` tag: +1. The workflow automatically generates BCR entry files from `.bcr` templates +2. Creates security attestations +3. Opens a pull request to the BCR repository +4. BCR maintainers review and merge the PR + +No manual file copying or PR creation needed! + +See [publish-to-bcr documentation](https://github.com/bazel-contrib/publish-to-bcr) for more details. diff --git a/python/dist/xds-0.1.0-py3-none-any.whl b/python/dist/xds-0.1.0-py3-none-any.whl deleted file mode 100644 index 604b11bb..00000000 Binary files a/python/dist/xds-0.1.0-py3-none-any.whl and /dev/null differ diff --git a/python/dist/xds-0.1.0.tar.gz b/python/dist/xds-0.1.0.tar.gz deleted file mode 100644 index 608d815a..00000000 Binary files a/python/dist/xds-0.1.0.tar.gz and /dev/null differ diff --git a/python/pyproject.toml b/python/pyproject.toml index 3b03df67..da007930 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -6,9 +6,9 @@ requires = [ build-backend = "setuptools.build_meta" [project] -name = "xds" +name = "cncf-xds" version = "0.1.0" -description = "xds Protocol Buffer Messages" +description = "CNCF xDS API Protocol Buffer Messages" requires-python = ">=3.7" # Or the appropriate minimum Python version dependencies = [ "protobuf==5.29.1"