From ab352f87bbf75381a21cc773bbc3d67c2377eb07 Mon Sep 17 00:00:00 2001 From: duyet <5009534+duyet@users.noreply.github.com> Date: Sat, 3 Oct 2026 06:28:46 +0700 Subject: [PATCH] feat(ci): publish Python SDK to PyPI via trusted publishing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add .github/workflows/publish-python-sdk.yml mirroring publish-sdk.yml for the Python package: path-filtered push to main (pyproject.toml and agentstate sources) plus workflow_dispatch with a dry_run input, skips publish when the version is already on PyPI, and publishes via PyPI trusted publishing (OIDC, id-token: write) — no API tokens needed. Closes #374 Co-Authored-By: Duyet Le Co-Authored-By: duyetbot Co-Authored-By: Claude Code --- .github/workflows/publish-python-sdk.yml | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 .github/workflows/publish-python-sdk.yml diff --git a/.github/workflows/publish-python-sdk.yml b/.github/workflows/publish-python-sdk.yml new file mode 100644 index 00000000..e2fa40dc --- /dev/null +++ b/.github/workflows/publish-python-sdk.yml @@ -0,0 +1,70 @@ +name: Publish Python SDK + +on: + push: + branches: [main] + paths: + - "packages/python-sdk/pyproject.toml" + - "packages/python-sdk/agentstate/**" + workflow_dispatch: + inputs: + dry_run: + description: "Dry run (skip actual publish)" + required: false + default: "false" + +permissions: + contents: read + id-token: write + +jobs: + publish: + name: Build & Publish + runs-on: ubuntu-latest + defaults: + run: + working-directory: packages/python-sdk + + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-python@v7 + with: + python-version: "3.14" + + - name: Install test dependencies + run: python -m pip install -e ".[dev]" + + - name: Unit tests + run: python -m pytest -q + + - name: Install build tooling + run: python -m pip install build + + - name: Build distributions + run: python -m build + + - name: Check if version already published + id: check-version + run: | + PKG_NAME=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['name'])") + PKG_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])") + echo "pkg_name=${PKG_NAME}" >> "$GITHUB_OUTPUT" + echo "pkg_version=${PKG_VERSION}" >> "$GITHUB_OUTPUT" + if curl -sf "https://pypi.org/pypi/${PKG_NAME}/${PKG_VERSION}/json" > /dev/null; then + echo "already_published=true" >> "$GITHUB_OUTPUT" + echo "::notice::${PKG_NAME}==${PKG_VERSION} already on PyPI — skipping publish" + else + echo "already_published=false" >> "$GITHUB_OUTPUT" + echo "Publishing ${PKG_NAME}==${PKG_VERSION}" + fi + + - name: Publish (dry run) + if: steps.check-version.outputs.already_published == 'false' && github.event.inputs.dry_run == 'true' + run: echo "::notice::Dry run — skipping publish of ${{ steps.check-version.outputs.pkg_name }}==${{ steps.check-version.outputs.pkg_version }}" + + - name: Publish + if: steps.check-version.outputs.already_published == 'false' && github.event.inputs.dry_run != 'true' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-to-upload: packages/python-sdk/dist/*