Skip to content

Commit 53a611a

Browse files
authored
chore: Check whether version in PR is already released (#12)
We have a recurring issue that you often forget to bump the package version number in a PR, and then when you merge it to `master`, the package publication fails because the version you're trying to publish already exists. This adds a check to CI which detects these issues early and fails the CI, so you can't merge those PRs without bumping the package version number. Same as apify/apify-sdk-python#127.
1 parent b6c751d commit 53a611a

File tree

6 files changed

+63
-14
lines changed

6 files changed

+63
-14
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Check package version availability
2+
3+
on:
4+
workflow_call:
5+
6+
jobs:
7+
check_version_availability:
8+
name: Check version availability
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- name: Checkout repository
13+
uses: actions/checkout@v4
14+
15+
- name: Set up Python
16+
uses: actions/setup-python@v4
17+
with:
18+
python-version: "3.8"
19+
20+
- name: Install dependencies
21+
run: make install-dev
22+
23+
- name: Check version availability
24+
run: make check-version-availability

.github/workflows/run_checks.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ on:
44
pull_request:
55

66
jobs:
7+
check_version_availability:
8+
name: Check version availability
9+
uses: ./.github/workflows/check_version_availability.yaml
10+
711
lint_and_type_checks:
812
name: Run lint and type checks
913
uses: ./.github/workflows/lint_and_type_checks.yaml

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: clean install-dev build publish twine-check lint unit-tests type-check check-code format check-changelog-entry
1+
.PHONY: clean install-dev build publish twine-check lint unit-tests type-check check-code format check-version-availability check-changelog-entry
22

33
clean:
44
rm -rf build dist .mypy_cache .pytest_cache src/*.egg-info __pycache__
@@ -32,5 +32,8 @@ format:
3232
python3 -m isort src tests
3333
python3 -m autopep8 --in-place --recursive src tests
3434

35+
check-version-availability:
36+
python3 scripts/check_version_availability.py
37+
3538
check-changelog-entry:
3639
python3 scripts/check_version_in_changelog.py
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python3
2+
from utils import get_current_package_version, get_published_package_versions
3+
4+
# Checks whether the current package version number was not already used in a published release.
5+
if __name__ == '__main__':
6+
current_version = get_current_package_version()
7+
8+
# Load the version numbers of the currently published versions from PyPI
9+
published_versions = get_published_package_versions()
10+
11+
# We don't want to try to publish a version with the same version number as an already released stable version
12+
if current_version in published_versions:
13+
raise RuntimeError(f'The current version {current_version} was already released!')

scripts/update_version_for_prerelease.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
#!/usr/bin/env python3
22

3-
import json
43
import re
54
import sys
6-
import urllib.request
75

8-
from utils import PACKAGE_NAME, get_current_package_version, set_current_package_version
6+
from utils import get_current_package_version, get_published_package_versions, set_current_package_version
97

108
# Checks whether the current package version number was not already used in a published release,
119
# and if not, modifies the package version number in pyproject.toml
@@ -32,16 +30,7 @@
3230
raise RuntimeError(f'The current version {current_version} does not match the proper semver format for stable releases (X.Y.Z)')
3331

3432
# Load the version numbers of the currently published versions from PyPI
35-
# If the URL returns 404, it means the package has no releases yet (which is okay in our case)
36-
package_info_url = f'https://pypi.org/pypi/{PACKAGE_NAME}/json'
37-
try:
38-
conn = urllib.request.urlopen(package_info_url)
39-
package_data = json.load(urllib.request.urlopen(package_info_url))
40-
published_versions = list(package_data['releases'].keys())
41-
except urllib.error.HTTPError as e:
42-
if e.code != 404:
43-
raise e
44-
published_versions = []
33+
published_versions = get_published_package_versions()
4534

4635
# We don't want to publish a prerelease version with the same version number as an already released stable version
4736
if current_version in published_versions:

scripts/utils.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import json
12
import pathlib
3+
import urllib.request
24

35
PACKAGE_NAME = 'apify_shared'
46
REPO_ROOT = pathlib.Path(__file__).parent.resolve() / '..'
@@ -36,3 +38,17 @@ def set_current_package_version(version: str) -> None:
3638
pyproject_toml_file.seek(0)
3739
pyproject_toml_file.write(''.join(updated_pyproject_toml_file_lines))
3840
pyproject_toml_file.truncate()
41+
42+
43+
# Load the version numbers of the currently published versions from PyPI
44+
def get_published_package_versions() -> list:
45+
package_info_url = f'https://pypi.org/pypi/{PACKAGE_NAME}/json'
46+
try:
47+
package_data = json.load(urllib.request.urlopen(package_info_url))
48+
published_versions = list(package_data['releases'].keys())
49+
# If the URL returns 404, it means the package has no releases yet (which is okay in our case)
50+
except urllib.error.HTTPError as e:
51+
if e.code != 404:
52+
raise e
53+
published_versions = []
54+
return published_versions

0 commit comments

Comments
 (0)