From 3b7e2afdbfbcbb970e78305e117f93eb90b3fa7c Mon Sep 17 00:00:00 2001 From: James Kebinger Date: Thu, 20 Nov 2025 09:57:28 -0600 Subject: [PATCH] Add PyPI publish workflow with duplicate version check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backports the publish workflow from ReforgeHQ/sdk-python and adapts it for prefab-cloud-python. Key features: - Triggers on push to main or manual workflow dispatch - Checks PyPI before publishing to prevent duplicate releases - Uses trusted publishing (OIDC) for secure authentication - Runs tests before publishing - Only publishes if version doesn't already exist on PyPI Changes from sdk-python workflow: - Uses pyproject.toml for version (instead of VERSION file) - Uses prefab-cloud-python as PyPI package name - Uses PREFAB_INTEGRATION_TEST_API_KEY secret - Runs pytest with '-k not integration' filter (matches CI) PyPI coordinates: https://pypi.org/project/prefab-cloud-python 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .github/workflows/publish.yml | 71 +++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..aca31d1 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,71 @@ +name: "Publish to PyPI" + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + publish: + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + environment: release + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + contents: read + + steps: + - name: Checkout repo + submodules + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Check if version already published + id: version-check + run: | + VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/') + echo "Current version: $VERSION" + + # Check if this version exists on PyPI + HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pypi.org/pypi/prefab-cloud-python/$VERSION/json") + + if [ "$HTTP_STATUS" = "200" ]; then + echo "Version $VERSION already exists on PyPI" + echo "skip=true" >> $GITHUB_OUTPUT + else + echo "Version $VERSION not found on PyPI, proceeding with publish" + echo "skip=false" >> $GITHUB_OUTPUT + fi + + - name: Install Poetry + if: steps.version-check.outputs.skip == 'false' + uses: snok/install-poetry@v1 + with: + virtualenvs-create: true + + - name: Install dependencies + if: steps.version-check.outputs.skip == 'false' + run: | + poetry install --no-interaction + + - name: Run tests + if: steps.version-check.outputs.skip == 'false' + run: poetry run pytest -k 'not integration' + env: + PREFAB_INTEGRATION_TEST_API_KEY: ${{ secrets.PREFAB_INTEGRATION_TEST_API_KEY }} + + - name: Build package + if: steps.version-check.outputs.skip == 'false' + run: poetry build + + - name: Publish to PyPI + if: steps.version-check.outputs.skip == 'false' + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/