From a94a4674ff43a621434afef1bd77134ed37061f5 Mon Sep 17 00:00:00 2001 From: Zach Giordano Date: Tue, 2 Jun 2026 14:52:13 -0400 Subject: [PATCH 1/2] Add workflows for publishing to PyPI --- .github/workflows/publish.yml | 51 +++++++++ .github/workflows/stable-release.yml | 22 ++++ .github/workflows/version-bump-on-release.yml | 104 ++++++++++++++++++ Makefile | 38 +++++++ pyproject.toml | 4 +- uv.lock | 6 +- 6 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/stable-release.yml create mode 100644 .github/workflows/version-bump-on-release.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..55ca91d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,51 @@ +name: Publish + +permissions: + contents: read + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Tag to publish (e.g. v0.2.0)' + required: true + type: string + +jobs: + pre-publish-checks: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.12"] + steps: + - name: Checkout actions + uses: actions/checkout@v6 + with: + ref: ${{ inputs.tag || github.ref }} + - name: Init environment + uses: ./.github/actions/init-environment + - name: Run checks + run: make check + + publish-pypi: + needs: pre-publish-checks + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' || github.event.release.prerelease == false + strategy: + fail-fast: false + matrix: + python-version: ["3.12"] + steps: + - name: Checkout actions + uses: actions/checkout@v6 + with: + ref: ${{ inputs.tag || github.ref }} + - name: Init environment + uses: ./.github/actions/init-environment + - name: uv Build + run: uv build + - name: uv Publish + run: uv publish --token ${{ secrets.PYPI_TOKEN }} diff --git a/.github/workflows/stable-release.yml b/.github/workflows/stable-release.yml new file mode 100644 index 0000000..7533f1b --- /dev/null +++ b/.github/workflows/stable-release.yml @@ -0,0 +1,22 @@ +name: Create Stable Release + +on: + push: + tags: + - v* + +permissions: + contents: write + +jobs: + release: + name: Release pushed tag + runs-on: ubuntu-22.04 + steps: + - name: Create release + uses: softprops/action-gh-release@v3 + with: + token: ${{ secrets.RELEASE_PAT }} + generate_release_notes: true + make_latest: true + prerelease: false diff --git a/.github/workflows/version-bump-on-release.yml b/.github/workflows/version-bump-on-release.yml new file mode 100644 index 0000000..50d5db6 --- /dev/null +++ b/.github/workflows/version-bump-on-release.yml @@ -0,0 +1,104 @@ +name: Version Bump on Release Branch + +on: + push: + branches: + - release/** + +jobs: + cherry-pick-version-bump: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout main branch + uses: actions/checkout@v6 + with: + ref: main + fetch-depth: 0 + token: ${{ secrets.RELEASE_PAT }} + + - name: Configure git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Fetch release branch + run: git fetch origin ${{ github.ref }} + + - name: Find version bump commit + id: find-commit + run: | + # Find commits on the release branch that are not on main and modify pyproject.toml + COMMIT_SHA=$(git log origin/${{ github.ref_name }} ^origin/main --format="%H" --grep="version\|bump" -i -- pyproject.toml | head -1) + + # If no commit found with grep, try to find any commit that modified pyproject.toml not on main + if [ -z "$COMMIT_SHA" ]; then + COMMIT_SHA=$(git log origin/${{ github.ref_name }} ^origin/main --format="%H" -- pyproject.toml | head -1) + fi + + if [ -z "$COMMIT_SHA" ]; then + echo "No version bump commit found on release branch that isn't already on main" + echo "found=false" >> $GITHUB_OUTPUT + else + echo "Version bump commit found: $COMMIT_SHA" + # Get commit message for logging + COMMIT_MSG=$(git log -1 --format="%s" $COMMIT_SHA) + echo "Commit message: $COMMIT_MSG" + echo "sha=$COMMIT_SHA" >> $GITHUB_OUTPUT + echo "message=$COMMIT_MSG" >> $GITHUB_OUTPUT + echo "found=true" >> $GITHUB_OUTPUT + fi + + - name: Create cherry-pick branch + if: steps.find-commit.outputs.found == 'true' + id: create-branch + run: | + BRANCH_NAME="version-bump-from-${{ github.ref_name }}" + git checkout -b $BRANCH_NAME + echo "branch=$BRANCH_NAME" >> $GITHUB_OUTPUT + + - name: Cherry-pick version bump commit + if: steps.find-commit.outputs.found == 'true' + run: | + git cherry-pick ${{ steps.find-commit.outputs.sha }} || { + # If cherry-pick fails due to conflicts, try to resolve + if git diff --name-only --diff-filter=U | grep -q "pyproject.toml"; then + # Accept the incoming version change + git checkout --theirs pyproject.toml + git add pyproject.toml + git cherry-pick --continue + else + echo "Cherry-pick failed with non-version conflicts" + exit 1 + fi + } + + - name: Push cherry-pick branch + if: steps.find-commit.outputs.found == 'true' + run: | + git push origin ${{ steps.create-branch.outputs.branch }} --force + + - name: Check if PR already exists + if: steps.find-commit.outputs.found == 'true' + id: check-pr + run: | + PR_EXISTS=$(gh pr list --base main --head ${{ steps.create-branch.outputs.branch }} --json number --jq length) + echo "exists=$PR_EXISTS" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_PAT }} + + - name: Create pull request into main + if: steps.find-commit.outputs.found == 'true' && steps.check-pr.outputs.exists == '0' + run: | + gh pr create \ + --base main \ + --head ${{ steps.create-branch.outputs.branch }} \ + --title "${{ steps.find-commit.outputs.message }}" \ + --body "This PR cherry-picks the version bump commit from \`${{ github.ref_name }}\`. + + Cherry-picked commit: ${{ steps.find-commit.outputs.sha }}" + env: + GITHUB_TOKEN: ${{ secrets.RELEASE_PAT }} diff --git a/Makefile b/Makefile index 85ce977..895bb63 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,41 @@ +.PHONY: version/get +version/get: ## Get version. + @uv version | awk '{print $$2}' + +.PHONY: version/set +version/set: ## Set version. + @uv version $(v) + @make version/commit + +.PHONY: version/patch +version/patch: ## Bump patch version. + @uv version --bump patch + @make version/commit + +.PHONY: version/minor +version/minor: ## Bump minor version. + @uv version --bump minor + @make version/commit + +.PHONY: version/major +version/major: ## Bump major version. + @uv version --bump major + @make version/commit + +.PHONY: version/commit +version/commit: ## Commit version. + @uv lock + @git add pyproject.toml uv.lock + @git commit -m "chore: bump v$$(make version/get)" + +.PHONY: version/publish +version/publish: ## Create and push git tags. + @git fetch --tags --force + @git tag v$$(make version/get) + @git tag stable -f + @git push -f --tags + @git push origin HEAD:refs/heads/release/v$$(make version/get | awk -F. '{print $$1 "." $$2}') + .PHONY: install install: ## Install all dependencies. @make install/all diff --git a/pyproject.toml b/pyproject.toml index 3e231e7..ef76314 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "griptape_cloud_client" -version = "0.1.0" +version = "0.2.0" description = "Python client for Griptape Cloud API" readme = "README.md" requires-python = ">=3.12.0, <3.13" @@ -73,4 +73,4 @@ reportIncompatibleMethodOverride = false [build-system] requires = ["hatchling"] -build-backend = "hatchling.build" \ No newline at end of file +build-backend = "hatchling.build" diff --git a/uv.lock b/uv.lock index f405d04..81b0721 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,6 @@ version = 1 -revision = 2 -requires-python = ">=3.12.0, <3.13" +revision = 3 +requires-python = "==3.12.*" [[package]] name = "annotated-types" @@ -66,7 +66,7 @@ wheels = [ [[package]] name = "griptape-cloud-client" -version = "0.1.0" +version = "0.2.0" source = { editable = "." } dependencies = [ { name = "attrs" }, From 462ca2589e9f98e3e4f4061e619e2412d73b07fa Mon Sep 17 00:00:00 2001 From: Zach Giordano Date: Tue, 2 Jun 2026 14:57:32 -0400 Subject: [PATCH 2/2] Switch build backends --- pyproject.toml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ef76314..172ce8f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -72,5 +72,13 @@ pythonVersion = "3.12" reportIncompatibleMethodOverride = false [build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" +requires = ["uv_build>=0.7.2,<0.12"] +build-backend = "uv_build" + +[tool.uv.build-backend] +module-name = "griptape_cloud_client" +module-root = "" +# `generated/` is a scratch directory used by scripts/gen_sdk.py; its contents are +# moved into the package proper, so it must not be packaged. +source-exclude = ["griptape_cloud_client/generated"] +wheel-exclude = ["generated"]