diff --git a/.github/workflows/_test_release.yml b/.github/workflows/_test_release.yml index d2ea9087..d983e2bc 100644 --- a/.github/workflows/_test_release.yml +++ b/.github/workflows/_test_release.yml @@ -83,5 +83,4 @@ jobs: repository-url: https://test.pypi.org/legacy/ # This setting ONLY IN CI AND ON TEST PYPI! See https://github.com/pypa/gh-action-pypi-publish#tolerating-release-package-file-duplicates skip-existing: true - # TODO determine whether to enable attestations later on, and how - attestations: false + attestations: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ebe5db0..dce39218 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,6 +23,7 @@ jobs: outputs: pkg-name: ${{ steps.check-version.outputs.pkg-name }} version: ${{ steps.check-version.outputs.version }} + version-exists: ${{ steps.check-pypi.outputs.version-exists }} steps: - uses: actions/checkout@v4 @@ -61,9 +62,42 @@ jobs: f.write(f"pkg-name={pkg_name}\n") f.write(f"version={version}\n") + - name: Check if version exists on PyPI + id: check-pypi + shell: python + env: + PKG_NAME: ${{ steps.check-version.outputs.pkg-name }} + VERSION: ${{ steps.check-version.outputs.version }} + run: | + import os + import urllib.request + import urllib.error + + pkg_name = os.environ["PKG_NAME"] + version = os.environ["VERSION"] + + try: + url = f"https://pypi.org/pypi/{pkg_name}/{version}/json" + with urllib.request.urlopen(url, timeout=30) as response: + # If we get here, the version exists on PyPI + print(f"Version {version} already exists on PyPI") + version_exists = "true" + except urllib.error.HTTPError as e: + if e.code == 404: + # Version doesn't exist, we can proceed + print(f"Version {version} does not exist on PyPI, proceeding with release") + version_exists = "false" + else: + # Other HTTP error, fail the workflow + raise + + with open(os.environ["GITHUB_OUTPUT"], "a") as f: + f.write(f"version-exists={version_exists}\n") + test-pypi-publish: needs: - build + if: success() && needs.build.outputs.version-exists == 'false' uses: ./.github/workflows/_test_release.yml permissions: write-all @@ -75,6 +109,7 @@ jobs: needs: - build - test-pypi-publish + if: success() && needs.build.outputs.version-exists == 'false' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -132,6 +167,7 @@ jobs: needs: - build - test-pypi-publish + if: success() && needs.build.outputs.version-exists == 'false' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -169,8 +205,11 @@ jobs: - test-pypi-publish - pre-release-checks - pre-release-unit-lowest-python + if: success() && needs.build.outputs.version-exists == 'false' runs-on: ubuntu-latest # This requires an 'environment' with this name on the github repo (and is best practice to restrict permissions) + # NOTE: Once this trusted publishing workflow is fully verified with actual releases, + # revoke any legacy PyPI API tokens/keys for astrapy for enhanced security. environment: pypi permissions: # Needed by trusted publish: https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/ @@ -196,8 +235,7 @@ jobs: packages-dir: dist/ verbose: true print-hash: true - # TODO determine whether to enable attestations later on, and how - attestations: false + attestations: true mark-release: needs: @@ -206,6 +244,7 @@ jobs: - pre-release-checks - pre-release-unit-lowest-python - publish + if: success() && needs.build.outputs.version-exists == 'false' runs-on: ubuntu-latest permissions: # Needed by `ncipollo/release-action` for creating the release