Skip to content
Open
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
18 changes: 18 additions & 0 deletions agent_sdks/python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ directory:
uv run pyink .
```

## Releasing the SDK

To release a new version of the SDK, follow these steps:

1. Update the version in `src/a2ui/version.py`.
2. Run the release script from the `agent_sdks/python` directory:

```bash
./release.sh
```

The script will build the package, upload it to the Artifact Registry, and trigger the release pipeline.

## Tracking the release

1. Check the release status through Sponge: go/spng2?q=PROJECT%3Aa2ui%2Fpypi
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to add this internal link to the OSS project? @jacobsimionato @gspencergoog

2. You will see logs for the jobs involved in your release. A successful release is confirmed when the final job, named "publisher", completes successfully.

## Disclaimer

Important: The sample code provided is for demonstration purposes and
Expand Down
64 changes: 64 additions & 0 deletions agent_sdks/python/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
Comment on lines +6 to +11
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The project, repository, and GCS bucket names are hardcoded to production values. To make the script more flexible and testable (e.g., for dry runs or staging releases), consider allowing these to be overridden via environment variables with the current values as defaults.

Suggested change
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
PACKAGE_NAME="${PACKAGE_NAME:-a2ui-agent-sdk}"
REPOSITORY="${REPOSITORY:-a2ui--pypi}"
PROJECT="${PROJECT:-oss-exit-gate-prod}"
LOCATION="${LOCATION:-us}"
REPOSITORY_URL="${REPOSITORY_URL:-https://us-python.pkg.dev/${PROJECT}/${REPOSITORY}}"
GCS_URI="${GCS_URI:-gs://oss-exit-gate-prod-projects-bucket/a2ui/pypi/manifests}"

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Comment on lines +14 to +15
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using uv tool install modifies the user's global tool environment every time the script runs. For a release script, it is generally better to use uvx (or uv tool run) to execute these tools in a transient, isolated environment. This avoids polluting the user's global state and ensures the script is more self-contained.


set -e # Exit on error
#set -x # Echo commands

PACKAGE_NAME="a2ui-agent-sdk"
REPOSITORY="a2ui--pypi"
PROJECT="oss-exit-gate-prod"
LOCATION="us"
REPOSITORY_URL="https://us-python.pkg.dev/${PROJECT}/${REPOSITORY}"
GCS_URI="gs://oss-exit-gate-prod-projects-bucket/a2ui/pypi/manifests"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Importing the package to extract the version number can be fragile if the environment is not fully set up or if the package has side effects on import. Since the version is defined in a simple Python file, consider parsing it directly to avoid unnecessary execution.

Suggested change
GCS_URI="gs://oss-exit-gate-prod-projects-bucket/a2ui/pypi/manifests"
version=$(sed -n 's/__version__ = "\(.*\)"/\1/p' src/a2ui/version.py)


echo "--- Installing helper packages ---"
uv tool install twine --with keyrings.google-artifactregistry-auth --with keyring
uv tool install keyring --with keyrings.google-artifactregistry-auth
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The command gcloud auth application-default login is interactive and will cause the script to hang or fail in non-interactive environments like CI/CD pipelines. It is better to exit with an error message instructing the user to authenticate if credentials are missing.

Suggested change
uv tool install keyring --with keyrings.google-artifactregistry-auth
echo "Error: Application Default Credentials not found. Please run 'gcloud auth application-default login'." >&2
exit 1


echo "--- Building the package ---"
rm -rf dist
uv build

echo "--- Uploading the package ---"
twine --version
twine check dist/*

version=$(uv run python -c "import a2ui; print(a2ui.__version__)")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

It is recommended to use the --non-interactive flag with twine upload to ensure the script fails immediately if authentication is not correctly configured, rather than waiting for user input.

Suggested change
version=$(uv run python -c "import a2ui; print(a2ui.__version__)")
twine upload --non-interactive --repository-url $REPOSITORY_URL dist/*


# Authenticate with Google Cloud
if ! gcloud auth application-default print-access-token --quiet > /dev/null; then
gcloud auth application-default login
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The manifest.json file is created in the local directory but never removed. Consider adding a cleanup step to ensure temporary files are deleted after the script finishes.

Suggested change
gcloud auth application-default login
echo '{ "publish_all": true }' > manifest.json
trap 'rm -f manifest.json' EXIT

fi

# Check if the version already exists in the staging repository
if gcloud artifacts versions describe "$version" --package=$PACKAGE_NAME --repository=$REPOSITORY --location=$LOCATION --project=$PROJECT > /dev/null 2>&1; then
echo "Version $version already exists in Artifact Registry. Skip the release."
echo "Hint: If you intended to release a new version, please update 'src/a2ui/version.py'."
exit 0
fi

twine upload --repository-url $REPOSITORY_URL dist/*
echo "Version $version uploaded to Artifact Registry."

echo "--- Creating manifest.json ---"
echo '{ "publish_all": true }' > manifest.json

echo "--- Uploading manifest to GCS to trigger OSS Exit Gate ---"
MANIFEST_NAME="manifest-${version}-$(date +%Y%m%d%H%M%S).json"
gcloud storage cp manifest.json "${GCS_URI}/${MANIFEST_NAME}"

echo "Manifest ${MANIFEST_NAME} uploaded."
echo "--- Build script finished ---"
Loading