Skip to content

Add script to release the SDK along the OpenAPI spec #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
May 6, 2025
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
133 changes: 133 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: Release LocalStack Python Client

on:
repository_dispatch:
types: [release-sdk]
workflow_dispatch:
inputs:
version:
description: The version of the OpenAPI spec to release the client for
required: true

env:
git_user_name: localstack[bot]
git_user_email: localstack-bot@users.noreply.github.com

jobs:

test_python:
runs-on: ubuntu-latest
env:
release: ${{ github.event_name == 'workflow_dispatch' && inputs.version || github.event.client_payload.version}}

steps:
- name: "Pull image"
run: |
docker pull localstack/localstack-pro:${{ env.release }}

- name: "Checkout"
uses: actions/checkout@v4
with:
# setuptools_scm requires git history to determine the version
fetch-depth: 0

- name: "Set up Python 3.11"
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: "Install uv"
uses: astral-sh/setup-uv@v3

- name: "Generate code from spec"
run: |
make clean-generated
./bin/generate.sh ${{ env.release }}

- name: "Prepare git config"
run: |
git config user.name ${{ env.git_user_name }}
git config user.email ${{ env.git_user_email }}

- name: "Commit changed code"
run: |
# Code automatically generated goes into the packages directory.
# As we generate code for the version to be released, we commit those changes.
if git status --porcelain packages/ | grep -q '^'; then
Copy link
Member

Choose a reason for hiding this comment

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

nitpick (non-blocking): ‏That's an interesting condition, could you maybe add a comment here to explain what's going on in this line?

git add packages/
git commit -m "Generate code for ${{ env.release }}"

echo "Changes committed successfully"
else
echo "No changes detected after generating the code"
fi

- name: "Install project"
run: |
make install-dev

- name: "Install LocalStack"
run: |
pip install localstack==${{ env.release }}
Comment on lines +69 to +71
Copy link
Member

Choose a reason for hiding this comment

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

nitpick (non-blocking): The installation of the right version of localstack is just defined here in the pipeline. But it seems there is also a requirements-spec.txt (which defines localstack as a dependency, but might not be used at all anymore?). I think it would be nice to:

  • Clean up / remove the requirements file
  • Either extend the readme explaining that one needs to start the right version of LocalStack manually, or integrate an automatic startup of the right version of LocalStack into the pytest conftest / setup.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. The requirement file is just a leftover from previous iterations.


- name: "Start Localstack"
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
run: |
source .venv/bin/activate
DEBUG=1 DISABLE_EVENTS="1" IMAGE_NAME="localstack/localstack-pro:${{ env.release }}" localstack start -d
localstack wait -t 120 || (python -m localstack.cli.main logs && false)

- name: "Run Python Tests"
env:
LOCALSTACK_AUTH_TOKEN: ${{ secrets.LOCALSTACK_AUTH_TOKEN }}
run: |
make test

- name: "Stop Localstack"
if: success() || failure()
run: |
source .venv/bin/activate
localstack logs
localstack stop

- name: "Install release helper"
run: |
curl -o bin/release-helper.sh -L https://api.github.com/repos/localstack/localstack/contents/bin/release-helper.sh -H 'Accept: application/vnd.github.v3.raw'
chmod +x bin/release-helper.sh

- name: "Create the release commit and tag"
run: |
bin/release-helper.sh git-commit-release ${{ env.release }}

- name: "Publish release to pypi"
run: |
make install publish
with:
UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }}

- name: "Push the release commit and tag"
run: |
git push --follow-tags

- name: "Create GitHub release"
env:
GITHUB_TOKEN: ${{ secrets.LOCALSTACK_GITHUB_TOKEN }}
run: gh release create "${{ env.release }}" --generate-notes --draft

- name: "Commit and push next development version"
run: |
bin/release-helper.sh git-commit-increment
git push

- name: "Publish development version to pypi"
run: |
make install publish
with:
UV_PUBLISH_TOKEN: ${{ secrets.UV_PUBLISH_TOKEN }}

- name: "Show git modifications"
run: |
git log --oneline -n 4
git show HEAD~1
git show HEAD
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,6 @@ localstack-sdk-python-2/.openapi-generator/

# setuptools_scm version.py
**/version.py

# release helper
bin/release-helper.sh
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,21 @@ clean: ## Clean up the virtual environment
rm -rf $(VENV_DIR)
rm -rf dist/

clean-dist:
rm -rf dist/

clean-generated: ## Cleanup generated code
rm -rf packages/localstack-sdk-generated/localstack/

generate: ## Generate the code from the OpenAPI specs
./bin/generate.sh

build:
uv build

publish: clean-dist build
uv publish

format:
($(VENV_RUN); python -m ruff format --exclude packages .; python -m ruff check --output-format=full --exclude packages --fix .)

Expand All @@ -32,4 +41,4 @@ lint:
test: ## Run automated tests
($(VENV_RUN); $(TEST_EXEC) pytest --durations=10 --log-cli-level=$(PYTEST_LOGLEVEL) $(PYTEST_ARGS) $(TEST_PATH))

.PHONY: clean install install-dev
.PHONY: clean install install-dev clean clean-dist clean-generated generate build publish format lint test
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ To run the integration test suite:
make test
```

Note that LocalStack (pro) should be running in the background to execute the test.
Note that LocalStack Pro (with the same version as the SDK) should be running in the background to execute the test.

### Quickstart

Expand Down
15 changes: 14 additions & 1 deletion bin/generate.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
#!/bin/bash

# Use the latest spec by default
SPEC_URL="https://raw.githubusercontent.com/localstack/openapi/refs/heads/main/openapi/emulators/localstack-spec-latest.yml"

if [ -n "$1" ]; then
SPEC_URL="https://github.com/localstack/openapi/releases/download/v$1/localstack-spec.yml"
fi

# Check if the URL is valid
if ! wget --spider -q "$SPEC_URL"; then
echo "Spec URL seems not accessible: $SPEC_URL"
exit 1
fi

docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli:v7.10.0 generate \
-i https://raw.githubusercontent.com/localstack/openapi/refs/heads/main/openapi/emulators/localstack-spec-latest.yml \
-i "$SPEC_URL" \
--skip-validate-spec \
-g python \
-o /local//packages/localstack-sdk-generated \
Expand Down
2 changes: 0 additions & 2 deletions requirements-spec.txt

This file was deleted.