diff --git a/.github/workflows/check_version_availability.yaml b/.github/workflows/check_version_availability.yaml new file mode 100644 index 00000000..a2c31358 --- /dev/null +++ b/.github/workflows/check_version_availability.yaml @@ -0,0 +1,25 @@ +name: Check package version availability + +on: + workflow_call: + +jobs: + check_version_availability: + name: Check version availability + runs-on: ubuntu-latest + if: (!startsWith(github.event.pull_request.title, 'docs:')) + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.8" + + - name: Install dependencies + run: make install-dev + + - name: Check version availability + run: make check-version-availability diff --git a/.github/workflows/run_checks.yaml b/.github/workflows/run_checks.yaml index 7843f648..517d7a37 100644 --- a/.github/workflows/run_checks.yaml +++ b/.github/workflows/run_checks.yaml @@ -4,6 +4,10 @@ on: pull_request: jobs: + check_version_availability: + name: Check version availability + uses: ./.github/workflows/check_version_availability.yaml + lint_and_type_checks: name: Run lint and type checks uses: ./.github/workflows/lint_and_type_checks.yaml diff --git a/Makefile b/Makefile index 42551615..31d6dab8 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: clean install-dev build publish twine-check lint unit-tests integration-tests type-check check-code format check-changelog-entry build-api-reference +.PHONY: clean install-dev build publish twine-check lint unit-tests integration-tests type-check check-code format check-version-availability check-changelog-entry build-api-reference # This is default for local testing, but GitHub workflows override it to a higher value in CI INTEGRATION_TESTS_CONCURRENCY = 1 @@ -38,6 +38,9 @@ format: python3 -m isort src tests python3 -m autopep8 --in-place --recursive src tests +check-version-availability: + python3 scripts/check_version_availability.py + check-changelog-entry: python3 scripts/check_version_in_changelog.py diff --git a/scripts/check_version_availability.py b/scripts/check_version_availability.py new file mode 100644 index 00000000..b133a9ae --- /dev/null +++ b/scripts/check_version_availability.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +from utils import get_current_package_version, get_published_package_versions + +# Checks whether the current package version number was not already used in a published release. +if __name__ == '__main__': + current_version = get_current_package_version() + + # Load the version numbers of the currently published versions from PyPI + published_versions = get_published_package_versions() + + # We don't want to try to publish a version with the same version number as an already released stable version + if current_version in published_versions: + raise RuntimeError(f'The current version {current_version} was already released!') diff --git a/scripts/update_version_for_prerelease.py b/scripts/update_version_for_prerelease.py index d29fc313..51ddf655 100644 --- a/scripts/update_version_for_prerelease.py +++ b/scripts/update_version_for_prerelease.py @@ -1,11 +1,9 @@ #!/usr/bin/env python3 -import json import re import sys -import urllib.request -from utils import PACKAGE_NAME, get_current_package_version, set_current_package_version +from utils import get_current_package_version, get_published_package_versions, set_current_package_version # Checks whether the current package version number was not already used in a published release, # and if not, modifies the package version number in pyproject.toml @@ -32,16 +30,7 @@ raise RuntimeError(f'The current version {current_version} does not match the proper semver format for stable releases (X.Y.Z)') # Load the version numbers of the currently published versions from PyPI - # If the URL returns 404, it means the package has no releases yet (which is okay in our case) - package_info_url = f'https://pypi.org/pypi/{PACKAGE_NAME}/json' - try: - conn = urllib.request.urlopen(package_info_url) - package_data = json.load(urllib.request.urlopen(package_info_url)) - published_versions = list(package_data['releases'].keys()) - except urllib.error.HTTPError as e: - if e.code != 404: - raise e - published_versions = [] + published_versions = get_published_package_versions() # We don't want to publish a prerelease version with the same version number as an already released stable version if current_version in published_versions: diff --git a/scripts/utils.py b/scripts/utils.py index ad4e5339..06a3ace7 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -1,4 +1,6 @@ +import json import pathlib +import urllib.request PACKAGE_NAME = 'apify' REPO_ROOT = pathlib.Path(__file__).parent.resolve() / '..' @@ -36,3 +38,17 @@ def set_current_package_version(version: str) -> None: pyproject_toml_file.seek(0) pyproject_toml_file.write(''.join(updated_pyproject_toml_file_lines)) pyproject_toml_file.truncate() + + +# Load the version numbers of the currently published versions from PyPI +def get_published_package_versions() -> list: + package_info_url = f'https://pypi.org/pypi/{PACKAGE_NAME}/json' + try: + package_data = json.load(urllib.request.urlopen(package_info_url)) + published_versions = list(package_data['releases'].keys()) + # If the URL returns 404, it means the package has no releases yet (which is okay in our case) + except urllib.error.HTTPError as e: + if e.code != 404: + raise e + published_versions = [] + return published_versions