python-discovery 1.6.3__tar.gz → 1.6.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.github/dependabot.yaml +4 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.github/workflows/check.yaml +32 -2
- python_discovery-1.6.4/.github/workflows/prepare-release.yaml +156 -0
- python_discovery-1.6.4/.github/workflows/release.yaml +105 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/PKG-INFO +1 -1
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/changelog.rst +28 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/how-to/standalone-usage.rst +4 -4
- {python_discovery-1.6.3 → python_discovery-1.6.4}/pyproject.toml +0 -1
- python_discovery-1.6.4/tasks/release.py +82 -0
- python_discovery-1.6.3/.github/workflows/prepare-release.yaml +0 -92
- python_discovery-1.6.3/.github/workflows/release.yaml +0 -49
- python_discovery-1.6.3/docs/changelog/147.bugfix.rst +0 -2
- python_discovery-1.6.3/docs/changelog/148.bugfix.rst +0 -2
- python_discovery-1.6.3/tasks/release.py +0 -173
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.github/FUNDING.yaml +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.github/SECURITY.md +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.github/release.yaml +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.gitignore +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.pre-commit-config.yaml +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.readthedocs.yaml +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/.readthedocs.yml +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/CODE_OF_CONDUCT.md +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/LICENSE +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/README.md +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/_static/custom.css +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/_static/logo.svg +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/changelog/template.jinja2 +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/conf.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/explanation.rst +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/index.rst +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/reference/api.rst +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/reference/environment-variables.rst +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/docs/tutorial/getting-started.rst +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/__init__.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_cache.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_cached_py_info.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_compat.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_discovery.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_py_info.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_py_info_collect.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_py_spec.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_specifier.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_windows/__init__.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_windows/_pep514.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/_windows/_propose.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/src/python_discovery/py.typed +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tasks/old_target_check.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tasks/old_target_check.sh +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/conftest.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/py_info/test_py_info.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/py_info/test_py_info_exe_based_of.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_cache.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_cache_recovery.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_cached_py_info.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_discovery.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_discovery_extra.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_iter_interpreters.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_py_info_collect.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_py_info_extra.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_py_spec.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_py_spec_extra.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_query_timeout.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/test_specifier.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/windows/conftest.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/windows/test_windows.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/windows/test_windows_pep514.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tests/windows/winreg_mock_values.py +0 -0
- {python_discovery-1.6.3 → python_discovery-1.6.4}/tox.toml +0 -0
|
@@ -5,6 +5,7 @@ on:
|
|
|
5
5
|
branches: ["main"]
|
|
6
6
|
tags-ignore: ["**"]
|
|
7
7
|
pull_request:
|
|
8
|
+
types: [opened, synchronize, reopened, labeled, unlabeled]
|
|
8
9
|
schedule:
|
|
9
10
|
- cron: "0 8 * * *"
|
|
10
11
|
concurrency:
|
|
@@ -37,7 +38,7 @@ jobs:
|
|
|
37
38
|
fetch-depth: 0
|
|
38
39
|
persist-credentials: false
|
|
39
40
|
- name: Install the latest version of uv
|
|
40
|
-
uses: astral-sh/setup-uv@
|
|
41
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
41
42
|
with:
|
|
42
43
|
python-version: "3.15"
|
|
43
44
|
enable-cache: false
|
|
@@ -63,7 +64,7 @@ jobs:
|
|
|
63
64
|
fetch-depth: 0
|
|
64
65
|
persist-credentials: false
|
|
65
66
|
- name: Install the latest version of uv
|
|
66
|
-
uses: astral-sh/setup-uv@
|
|
67
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
67
68
|
with:
|
|
68
69
|
python-version: "3.15"
|
|
69
70
|
enable-cache: false
|
|
@@ -80,3 +81,32 @@ jobs:
|
|
|
80
81
|
run: tasks/old_target_check.sh 3.5 rejected
|
|
81
82
|
- name: Reject Python 2.7
|
|
82
83
|
run: tasks/old_target_check.sh 2.7 rejected
|
|
84
|
+
changelog:
|
|
85
|
+
if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'skip news')
|
|
86
|
+
runs-on: ubuntu-24.04
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
89
|
+
with:
|
|
90
|
+
fetch-depth: 0
|
|
91
|
+
persist-credentials: false
|
|
92
|
+
- uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
93
|
+
with:
|
|
94
|
+
python-version: "3.15"
|
|
95
|
+
enable-cache: false
|
|
96
|
+
- run: uvx towncrier check --compare-with "origin/${GITHUB_BASE_REF}"
|
|
97
|
+
gate:
|
|
98
|
+
name: Required checks pass
|
|
99
|
+
if: always()
|
|
100
|
+
needs: [test, old-target, changelog]
|
|
101
|
+
runs-on: ubuntu-24.04
|
|
102
|
+
steps:
|
|
103
|
+
- env:
|
|
104
|
+
NEEDS_JSON: ${{ toJSON(needs) }}
|
|
105
|
+
run: |
|
|
106
|
+
jq -e '
|
|
107
|
+
all(
|
|
108
|
+
to_entries[];
|
|
109
|
+
.value.result == "success" or
|
|
110
|
+
(.key == "changelog" and .value.result == "skipped")
|
|
111
|
+
)
|
|
112
|
+
' <<< "$NEEDS_JSON"
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
name: Prepare Release
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
inputs:
|
|
5
|
+
bump:
|
|
6
|
+
description: "Version bump type"
|
|
7
|
+
required: true
|
|
8
|
+
type: choice
|
|
9
|
+
options:
|
|
10
|
+
- auto
|
|
11
|
+
- major
|
|
12
|
+
- minor
|
|
13
|
+
- patch
|
|
14
|
+
default: auto
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
env:
|
|
18
|
+
FORCE_COLOR: 1
|
|
19
|
+
jobs:
|
|
20
|
+
assemble:
|
|
21
|
+
if: github.ref == 'refs/heads/main'
|
|
22
|
+
runs-on: ubuntu-24.04
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
outputs:
|
|
26
|
+
version: ${{ steps.version.outputs.version }}
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
29
|
+
with:
|
|
30
|
+
fetch-depth: 0 # The next version comes from the tags.
|
|
31
|
+
persist-credentials: false
|
|
32
|
+
- name: Install uv
|
|
33
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
34
|
+
with:
|
|
35
|
+
python-version: "3.15"
|
|
36
|
+
enable-cache: false
|
|
37
|
+
- name: Require a news fragment
|
|
38
|
+
run: |
|
|
39
|
+
if ! compgen -G 'docs/changelog/*.*.rst' > /dev/null; then
|
|
40
|
+
echo '::error::add a docs/changelog/*.rst fragment before preparing a release'
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
- name: Set up remote tracking
|
|
44
|
+
run: |
|
|
45
|
+
git remote -v
|
|
46
|
+
git fetch origin
|
|
47
|
+
git branch -a
|
|
48
|
+
- name: Calculate next version
|
|
49
|
+
id: version
|
|
50
|
+
env:
|
|
51
|
+
BUMP: ${{ inputs.bump }}
|
|
52
|
+
run: |
|
|
53
|
+
current=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
|
|
54
|
+
echo "Current version: $current"
|
|
55
|
+
|
|
56
|
+
IFS='.' read -r major minor patch <<< "$current"
|
|
57
|
+
|
|
58
|
+
bump_type="$BUMP"
|
|
59
|
+
if [ "$bump_type" = "auto" ]; then
|
|
60
|
+
feature_count=$(find docs/changelog -name "*.feature.rst" 2>/dev/null | wc -l)
|
|
61
|
+
breaking_count=$(find docs/changelog -name "*.breaking.rst" 2>/dev/null | wc -l)
|
|
62
|
+
if [ "$breaking_count" -gt 0 ]; then
|
|
63
|
+
bump_type="major"
|
|
64
|
+
echo "Auto-detected: major bump (found $breaking_count breaking changelog(s))"
|
|
65
|
+
elif [ "$feature_count" -gt 0 ]; then
|
|
66
|
+
bump_type="minor"
|
|
67
|
+
echo "Auto-detected: minor bump (found $feature_count feature changelog(s))"
|
|
68
|
+
else
|
|
69
|
+
bump_type="patch"
|
|
70
|
+
echo "Auto-detected: patch bump (no feature changelogs)"
|
|
71
|
+
fi
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
case "$bump_type" in
|
|
75
|
+
major)
|
|
76
|
+
next="$((major + 1)).0.0"
|
|
77
|
+
;;
|
|
78
|
+
minor)
|
|
79
|
+
next="$major.$((minor + 1)).0"
|
|
80
|
+
;;
|
|
81
|
+
patch)
|
|
82
|
+
next="$major.$minor.$((patch + 1))"
|
|
83
|
+
;;
|
|
84
|
+
esac
|
|
85
|
+
|
|
86
|
+
echo "Next version: $next"
|
|
87
|
+
echo "version=$next" >> "$GITHUB_OUTPUT"
|
|
88
|
+
- name: Build release patch
|
|
89
|
+
env:
|
|
90
|
+
VERSION: ${{ steps.version.outputs.version }}
|
|
91
|
+
run: |
|
|
92
|
+
set -euo pipefail
|
|
93
|
+
uvx towncrier build --yes --version "$VERSION"
|
|
94
|
+
uvx --with pre-commit-uv pre-commit run --files docs/changelog.rst ||
|
|
95
|
+
uvx --with pre-commit-uv pre-commit run --files docs/changelog.rst
|
|
96
|
+
git diff HEAD --binary > "$RUNNER_TEMP/release.patch"
|
|
97
|
+
test -s "$RUNNER_TEMP/release.patch"
|
|
98
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
99
|
+
with:
|
|
100
|
+
name: release-patch
|
|
101
|
+
path: ${{ runner.temp }}/release.patch
|
|
102
|
+
if-no-files-found: error
|
|
103
|
+
push:
|
|
104
|
+
needs: assemble
|
|
105
|
+
runs-on: ubuntu-24.04
|
|
106
|
+
environment: release-auth
|
|
107
|
+
permissions:
|
|
108
|
+
contents: read
|
|
109
|
+
steps:
|
|
110
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
111
|
+
with:
|
|
112
|
+
fetch-depth: 0
|
|
113
|
+
persist-credentials: false
|
|
114
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
115
|
+
with:
|
|
116
|
+
name: release-patch
|
|
117
|
+
path: ${{ runner.temp }}/release-patch
|
|
118
|
+
- name: Validate release patch
|
|
119
|
+
env:
|
|
120
|
+
VERSION: ${{ needs.assemble.outputs.version }}
|
|
121
|
+
run: |
|
|
122
|
+
set -euo pipefail
|
|
123
|
+
git fetch origin main
|
|
124
|
+
git reset --hard origin/main
|
|
125
|
+
git apply --check "$RUNNER_TEMP/release-patch/release.patch"
|
|
126
|
+
git apply --index "$RUNNER_TEMP/release-patch/release.patch"
|
|
127
|
+
while IFS= read -r path; do
|
|
128
|
+
case "$path" in
|
|
129
|
+
docs/changelog.rst|docs/changelog/*.rst) ;;
|
|
130
|
+
*) echo "::error::unexpected release path: $path"; exit 1 ;;
|
|
131
|
+
esac
|
|
132
|
+
done < <(git diff --cached --name-only)
|
|
133
|
+
grep -qE "^ v${VERSION//./\\.} \(" docs/changelog.rst
|
|
134
|
+
git diff --cached --check
|
|
135
|
+
- id: token
|
|
136
|
+
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
|
|
137
|
+
with:
|
|
138
|
+
client-id: ${{ vars.RELEASE_APP_CLIENT_ID }}
|
|
139
|
+
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
|
|
140
|
+
owner: ${{ github.repository_owner }}
|
|
141
|
+
repositories: ${{ github.event.repository.name }}
|
|
142
|
+
permission-contents: write
|
|
143
|
+
- name: Commit and tag the release
|
|
144
|
+
env:
|
|
145
|
+
VERSION: ${{ needs.assemble.outputs.version }}
|
|
146
|
+
GH_TOKEN: ${{ steps.token.outputs.token }}
|
|
147
|
+
APP_SLUG: ${{ steps.token.outputs.app-slug }}
|
|
148
|
+
run: |
|
|
149
|
+
set -euo pipefail
|
|
150
|
+
app_user_id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)
|
|
151
|
+
git config user.name "${APP_SLUG}[bot]"
|
|
152
|
+
git config user.email "${app_user_id}+${APP_SLUG}[bot]@users.noreply.github.com"
|
|
153
|
+
git commit -m "release $VERSION"
|
|
154
|
+
git tag -a "$VERSION" -m "release $VERSION"
|
|
155
|
+
gh auth setup-git --hostname github.com --force
|
|
156
|
+
git push --atomic origin HEAD:main "refs/tags/$VERSION"
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags: ["*"]
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
env:
|
|
8
|
+
dists-artifact-name: python-package-distributions
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-26.04
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
14
|
+
with:
|
|
15
|
+
fetch-depth: 0
|
|
16
|
+
persist-credentials: false
|
|
17
|
+
- name: Require a changelog section for the tag
|
|
18
|
+
env:
|
|
19
|
+
TAG: ${{ github.ref_name }}
|
|
20
|
+
run: |
|
|
21
|
+
if [[ ! "$TAG" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
22
|
+
echo "::error::unexpected release tag $TAG"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
if ! grep -qE "^ v${TAG//./\\.} \\(" docs/changelog.rst; then
|
|
26
|
+
echo "::error::docs/changelog.rst has no section for $TAG"
|
|
27
|
+
exit 1
|
|
28
|
+
fi
|
|
29
|
+
- name: Install the latest version of uv
|
|
30
|
+
uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
|
|
31
|
+
with:
|
|
32
|
+
python-version: "3.15"
|
|
33
|
+
enable-cache: false
|
|
34
|
+
cache-dependency-glob: "pyproject.toml"
|
|
35
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
36
|
+
- name: Build package
|
|
37
|
+
run: uv build --python 3.15 --python-preference only-managed --sdist --wheel . --out-dir dist
|
|
38
|
+
- name: Store the distribution packages
|
|
39
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
40
|
+
with:
|
|
41
|
+
name: ${{ env.dists-artifact-name }}
|
|
42
|
+
path: dist/*
|
|
43
|
+
release:
|
|
44
|
+
needs:
|
|
45
|
+
- build
|
|
46
|
+
runs-on: ubuntu-26.04
|
|
47
|
+
environment:
|
|
48
|
+
name: release
|
|
49
|
+
url: https://pypi.org/project/python-discovery/${{ github.ref_name }}
|
|
50
|
+
permissions:
|
|
51
|
+
id-token: write
|
|
52
|
+
steps:
|
|
53
|
+
- name: Download all the dists
|
|
54
|
+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
55
|
+
with:
|
|
56
|
+
name: ${{ env.dists-artifact-name }}
|
|
57
|
+
path: dist/
|
|
58
|
+
- name: Publish to PyPI
|
|
59
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
60
|
+
with:
|
|
61
|
+
attestations: true
|
|
62
|
+
github-release:
|
|
63
|
+
needs: release
|
|
64
|
+
runs-on: ubuntu-26.04
|
|
65
|
+
permissions:
|
|
66
|
+
contents: write
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
69
|
+
with:
|
|
70
|
+
fetch-depth: 0
|
|
71
|
+
persist-credentials: false
|
|
72
|
+
- name: Publish GitHub Release
|
|
73
|
+
env:
|
|
74
|
+
GH_TOKEN: ${{ github.token }}
|
|
75
|
+
TAG: ${{ github.ref_name }}
|
|
76
|
+
run: |
|
|
77
|
+
set -euo pipefail
|
|
78
|
+
awk -v tag="$TAG" '
|
|
79
|
+
index($0, " v" tag " (") == 1 { found = 1; next }
|
|
80
|
+
found && /^ v[0-9]+\.[0-9]+\.[0-9]+ \(/ { exit }
|
|
81
|
+
found && $0 !~ /^\*+$/ { print }
|
|
82
|
+
' docs/changelog.rst > "$RUNNER_TEMP/release-notes.md"
|
|
83
|
+
python3 - "$RUNNER_TEMP/release-notes.md" <<'PY'
|
|
84
|
+
import re
|
|
85
|
+
import sys
|
|
86
|
+
from pathlib import Path
|
|
87
|
+
|
|
88
|
+
path = Path(sys.argv[1])
|
|
89
|
+
body = path.read_text().strip()
|
|
90
|
+
if not body:
|
|
91
|
+
raise SystemExit("release notes are empty")
|
|
92
|
+
body = re.sub(r":user:`([^`]+)`", r"\1", body)
|
|
93
|
+
body = re.sub(r":(?:issue|pull):`(\d+)`", r"#\1", body)
|
|
94
|
+
body = re.sub(r":[a-z]+:`~?([^`]+)`", lambda match: f"`{match.group(1).split('.')[-1]}`", body)
|
|
95
|
+
path.write_text(body.replace("``", "`") + "\n")
|
|
96
|
+
PY
|
|
97
|
+
test -s "$RUNNER_TEMP/release-notes.md"
|
|
98
|
+
printf '\n[PyPI release](https://pypi.org/project/python-discovery/%s/)\n' "$TAG" >> "$RUNNER_TEMP/release-notes.md"
|
|
99
|
+
previous=$(git tag --list '[0-9]*' | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | sort -V | awk -v tag="$TAG" '$0 == tag { print previous; exit } { previous = $0 }')
|
|
100
|
+
if [[ -n "$previous" ]]; then
|
|
101
|
+
printf '\n**Full Changelog**: https://github.com/%s/compare/%s...%s\n' "$GITHUB_REPOSITORY" "$previous" "$TAG" >> "$RUNNER_TEMP/release-notes.md"
|
|
102
|
+
else
|
|
103
|
+
printf '\n**Full Changelog**: https://github.com/%s/commits/%s\n' "$GITHUB_REPOSITORY" "$TAG" >> "$RUNNER_TEMP/release-notes.md"
|
|
104
|
+
fi
|
|
105
|
+
gh release create "$TAG" --verify-tag --title "v$TAG" --notes-file "$RUNNER_TEMP/release-notes.md"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: python-discovery
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.4
|
|
4
4
|
Summary: Python interpreter discovery
|
|
5
5
|
Project-URL: Changelog, https://github.com/tox-dev/python-discovery/releases
|
|
6
6
|
Project-URL: Documentation, https://python-discovery.readthedocs.io
|
|
@@ -6,6 +6,26 @@
|
|
|
6
6
|
|
|
7
7
|
.. towncrier release notes start
|
|
8
8
|
|
|
9
|
+
********************
|
|
10
|
+
v1.6.4 (2026-10-19)
|
|
11
|
+
********************
|
|
12
|
+
|
|
13
|
+
Improved documentation - 1.6.4
|
|
14
|
+
==============================
|
|
15
|
+
- Clarify the executable paths accepted by ``try_first_with`` in the standalone usage example. (:issue:`150`)
|
|
16
|
+
|
|
17
|
+
********************
|
|
18
|
+
v1.6.3 (2026-10-16)
|
|
19
|
+
********************
|
|
20
|
+
|
|
21
|
+
Bug fixes - 1.6.3
|
|
22
|
+
=================
|
|
23
|
+
- Treat specs with dot-only version components, such as ``python.``, as literal executable paths instead of raising
|
|
24
|
+
``IndexError`` - by :user:`harbinresearcher`. (:issue:`147`)
|
|
25
|
+
- Pass PEP 514 ``ExecutableArguments`` to registered Windows interpreters when querying them, so a registration that
|
|
26
|
+
points at a launcher such as ``py.exe -3.11`` reports the interpreter it selects - by :user:`blouirts123`.
|
|
27
|
+
(:issue:`148`)
|
|
28
|
+
|
|
9
29
|
********************
|
|
10
30
|
v1.6.2 (2026-10-10)
|
|
11
31
|
********************
|
|
@@ -61,6 +81,14 @@ Improved documentation - 1.5.3
|
|
|
61
81
|
==============================
|
|
62
82
|
- Document the version floors: runs on Python 3.8+, discovers interpreters down to 3.6 - by :user:`gaborbernat`. (:issue:`116`)
|
|
63
83
|
|
|
84
|
+
********************
|
|
85
|
+
v1.5.2 (2026-08-12)
|
|
86
|
+
********************
|
|
87
|
+
|
|
88
|
+
Bug fixes - 1.5.2
|
|
89
|
+
=================
|
|
90
|
+
- Move interpreter interrogation into a Python 3.6-compatible collector. (:issue:`117`)
|
|
91
|
+
|
|
64
92
|
********************
|
|
65
93
|
v1.5.1 (2026-07-31)
|
|
66
94
|
********************
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
How-to guides
|
|
2
2
|
=============
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
Try specific executables first
|
|
5
|
+
------------------------------
|
|
6
6
|
|
|
7
|
-
If you know
|
|
7
|
+
If you know the path to an interpreter executable, pass it via ``try_first_with`` to check it
|
|
8
8
|
before the normal search. This is useful when you have a custom Python install outside the
|
|
9
9
|
standard locations.
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ standard locations.
|
|
|
12
12
|
|
|
13
13
|
from python_discovery import get_interpreter
|
|
14
14
|
|
|
15
|
-
info = get_interpreter("python3.12", try_first_with=["/opt/python/bin"])
|
|
15
|
+
info = get_interpreter("python3.12", try_first_with=["/opt/python/bin/python3.12"])
|
|
16
16
|
if info is not None:
|
|
17
17
|
print(info.executable)
|
|
18
18
|
|
|
@@ -228,5 +228,4 @@ type = [
|
|
|
228
228
|
{ directory = "doc", name = "Improved documentation", showcontent = true },
|
|
229
229
|
{ directory = "packaging", name = "Packaging updates and notes for downstreams", showcontent = true },
|
|
230
230
|
{ directory = "contrib", name = "Contributor-facing changes", showcontent = true },
|
|
231
|
-
{ directory = "misc", name = "Miscellaneous internal changes", showcontent = true },
|
|
232
231
|
]
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from subprocess import CalledProcessError, check_call, run
|
|
5
|
+
from typing import Final
|
|
6
|
+
|
|
7
|
+
from git import Commit, Remote, Repo
|
|
8
|
+
from packaging.version import Version
|
|
9
|
+
|
|
10
|
+
_ROOT_SRC_DIR: Final[Path] = Path(__file__).parents[1]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main(version_str: str) -> None:
|
|
14
|
+
version = Version(version_str)
|
|
15
|
+
repo = Repo(str(_ROOT_SRC_DIR))
|
|
16
|
+
|
|
17
|
+
if repo.is_dirty():
|
|
18
|
+
msg = "Current repository is dirty. Please commit any changes and try again."
|
|
19
|
+
raise RuntimeError(msg)
|
|
20
|
+
upstream = get_upstream(repo)
|
|
21
|
+
upstream.fetch()
|
|
22
|
+
if str(version) in {tag.name for tag in repo.tags}:
|
|
23
|
+
msg = f"release tag {version} already exists"
|
|
24
|
+
raise RuntimeError(msg)
|
|
25
|
+
repo.git.checkout("-B", f"release-{version}", upstream.refs.main)
|
|
26
|
+
release_commit = release_changelog(repo, version)
|
|
27
|
+
repo.create_tag(str(version), ref=release_commit.hexsha, message=f"release {version}")
|
|
28
|
+
repo.git.push(upstream.name, "HEAD:main")
|
|
29
|
+
repo.git.push(upstream.name, f"refs/tags/{version}")
|
|
30
|
+
create_github_release(version)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_upstream(repo: Repo) -> Remote:
|
|
34
|
+
for remote in repo.remotes:
|
|
35
|
+
if any("tox-dev/python-discovery" in url for url in remote.urls):
|
|
36
|
+
return remote
|
|
37
|
+
msg = "could not find tox-dev/python-discovery remote"
|
|
38
|
+
raise RuntimeError(msg)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def release_changelog(repo: Repo, version: Version) -> Commit:
|
|
42
|
+
print("generate release commit") # ruff:ignore[print]
|
|
43
|
+
check_call(["towncrier", "build", "--yes", "--version", version.public], cwd=str(_ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
44
|
+
print("format changelog with pre-commit") # ruff:ignore[print]
|
|
45
|
+
changelog_path = _ROOT_SRC_DIR / "docs" / "changelog.rst"
|
|
46
|
+
try:
|
|
47
|
+
check_call(["pre-commit", "run", "--files", str(changelog_path)], cwd=str(_ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
48
|
+
except CalledProcessError:
|
|
49
|
+
check_call(["pre-commit", "run", "--files", str(changelog_path)], cwd=str(_ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
50
|
+
repo.git.add("-A", "--", "docs/changelog.rst", "docs/changelog")
|
|
51
|
+
return repo.index.commit(f"release {version}")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def create_github_release(version: Version) -> None:
|
|
55
|
+
print("create github release") # ruff:ignore[print]
|
|
56
|
+
version_str = str(version)
|
|
57
|
+
try:
|
|
58
|
+
result = run(
|
|
59
|
+
["gh", "release", "create", version_str, "--title", f"v{version_str}", "--generate-notes"], # ruff:ignore[start-process-with-partial-path]
|
|
60
|
+
cwd=str(_ROOT_SRC_DIR),
|
|
61
|
+
capture_output=True,
|
|
62
|
+
text=True,
|
|
63
|
+
check=True,
|
|
64
|
+
)
|
|
65
|
+
if result.stdout:
|
|
66
|
+
print(result.stdout) # ruff:ignore[print]
|
|
67
|
+
except CalledProcessError as e:
|
|
68
|
+
print(f"gh release create failed with exit code {e.returncode}") # ruff:ignore[print]
|
|
69
|
+
if e.stdout:
|
|
70
|
+
print(f"stdout: {e.stdout}") # ruff:ignore[print]
|
|
71
|
+
if e.stderr:
|
|
72
|
+
print(f"stderr: {e.stderr}") # ruff:ignore[print]
|
|
73
|
+
raise
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
if __name__ == "__main__":
|
|
77
|
+
import argparse
|
|
78
|
+
|
|
79
|
+
parser = argparse.ArgumentParser(prog="release")
|
|
80
|
+
parser.add_argument("--version", required=True)
|
|
81
|
+
options = parser.parse_args()
|
|
82
|
+
main(options.version)
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
name: Prepare Release
|
|
2
|
-
on:
|
|
3
|
-
workflow_dispatch:
|
|
4
|
-
inputs:
|
|
5
|
-
bump:
|
|
6
|
-
description: "Version bump type"
|
|
7
|
-
required: true
|
|
8
|
-
type: choice
|
|
9
|
-
options:
|
|
10
|
-
- auto
|
|
11
|
-
- major
|
|
12
|
-
- minor
|
|
13
|
-
- patch
|
|
14
|
-
default: auto
|
|
15
|
-
permissions:
|
|
16
|
-
contents: read
|
|
17
|
-
env:
|
|
18
|
-
FORCE_COLOR: 1
|
|
19
|
-
jobs:
|
|
20
|
-
prepare-release:
|
|
21
|
-
runs-on: ubuntu-24.04
|
|
22
|
-
environment: release-auth
|
|
23
|
-
permissions:
|
|
24
|
-
contents: write
|
|
25
|
-
steps:
|
|
26
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
27
|
-
with:
|
|
28
|
-
fetch-depth: 0
|
|
29
|
-
token: ${{ secrets.RELEASE_PAT }}
|
|
30
|
-
persist-credentials: true
|
|
31
|
-
- name: Install the latest version of uv
|
|
32
|
-
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
33
|
-
with:
|
|
34
|
-
python-version: "3.15"
|
|
35
|
-
enable-cache: true
|
|
36
|
-
cache-dependency-glob: "pyproject.toml"
|
|
37
|
-
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
38
|
-
- name: Configure git
|
|
39
|
-
run: |
|
|
40
|
-
git config user.name "${GITHUB_ACTOR}"
|
|
41
|
-
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
|
|
42
|
-
- name: Calculate next version
|
|
43
|
-
id: version
|
|
44
|
-
env:
|
|
45
|
-
BUMP: ${{ inputs.bump }}
|
|
46
|
-
run: |
|
|
47
|
-
current=$(git describe --tags --abbrev=0 2>/dev/null || echo "0.0.0")
|
|
48
|
-
echo "Current version: $current"
|
|
49
|
-
|
|
50
|
-
IFS='.' read -r major minor patch <<< "$current"
|
|
51
|
-
|
|
52
|
-
bump_type="$BUMP"
|
|
53
|
-
if [ "$bump_type" = "auto" ]; then
|
|
54
|
-
feature_count=$(find docs/changelog -name "*.feature.rst" 2>/dev/null | wc -l)
|
|
55
|
-
breaking_count=$(find docs/changelog -name "*.breaking.rst" 2>/dev/null | wc -l)
|
|
56
|
-
if [ "$breaking_count" -gt 0 ]; then
|
|
57
|
-
bump_type="major"
|
|
58
|
-
echo "Auto-detected: major bump (found $breaking_count breaking changelog(s))"
|
|
59
|
-
elif [ "$feature_count" -gt 0 ]; then
|
|
60
|
-
bump_type="minor"
|
|
61
|
-
echo "Auto-detected: minor bump (found $feature_count feature changelog(s))"
|
|
62
|
-
else
|
|
63
|
-
bump_type="patch"
|
|
64
|
-
echo "Auto-detected: patch bump (no feature changelogs)"
|
|
65
|
-
fi
|
|
66
|
-
fi
|
|
67
|
-
|
|
68
|
-
case "$bump_type" in
|
|
69
|
-
major)
|
|
70
|
-
next="$((major + 1)).0.0"
|
|
71
|
-
;;
|
|
72
|
-
minor)
|
|
73
|
-
next="$major.$((minor + 1)).0"
|
|
74
|
-
;;
|
|
75
|
-
patch)
|
|
76
|
-
next="$major.$minor.$((patch + 1))"
|
|
77
|
-
;;
|
|
78
|
-
esac
|
|
79
|
-
|
|
80
|
-
echo "Next version: $next"
|
|
81
|
-
echo "version=$next" >> $GITHUB_OUTPUT
|
|
82
|
-
- name: Install tox
|
|
83
|
-
run: uv tool install --python-preference only-managed --python 3.15 tox@latest --with tox-uv
|
|
84
|
-
- name: Run release process
|
|
85
|
-
run: tox run -e release -- ${STEPS_VERSION_OUTPUTS_VERSION}
|
|
86
|
-
env:
|
|
87
|
-
GH_TOKEN: ${{ secrets.RELEASE_PAT }}
|
|
88
|
-
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
|
|
89
|
-
- name: Display completion message
|
|
90
|
-
run: echo "Release ${STEPS_VERSION_OUTPUTS_VERSION} prepared and pushed successfully!"
|
|
91
|
-
env:
|
|
92
|
-
STEPS_VERSION_OUTPUTS_VERSION: ${{ steps.version.outputs.version }}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
name: Release to PyPI
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
tags: ["*"]
|
|
5
|
-
permissions:
|
|
6
|
-
contents: read
|
|
7
|
-
env:
|
|
8
|
-
dists-artifact-name: python-package-distributions
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
runs-on: ubuntu-26.04
|
|
12
|
-
steps:
|
|
13
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
14
|
-
with:
|
|
15
|
-
fetch-depth: 0
|
|
16
|
-
persist-credentials: false
|
|
17
|
-
- name: Install the latest version of uv
|
|
18
|
-
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
|
|
19
|
-
with:
|
|
20
|
-
python-version: "3.15"
|
|
21
|
-
enable-cache: false
|
|
22
|
-
cache-dependency-glob: "pyproject.toml"
|
|
23
|
-
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
24
|
-
- name: Build package
|
|
25
|
-
run: uv build --python 3.15 --python-preference only-managed --sdist --wheel . --out-dir dist
|
|
26
|
-
- name: Store the distribution packages
|
|
27
|
-
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
28
|
-
with:
|
|
29
|
-
name: ${{ env.dists-artifact-name }}
|
|
30
|
-
path: dist/*
|
|
31
|
-
release:
|
|
32
|
-
needs:
|
|
33
|
-
- build
|
|
34
|
-
runs-on: ubuntu-26.04
|
|
35
|
-
environment:
|
|
36
|
-
name: release
|
|
37
|
-
url: https://pypi.org/project/python-discovery/${{ github.ref_name }}
|
|
38
|
-
permissions:
|
|
39
|
-
id-token: write
|
|
40
|
-
steps:
|
|
41
|
-
- name: Download all the dists
|
|
42
|
-
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
43
|
-
with:
|
|
44
|
-
name: ${{ env.dists-artifact-name }}
|
|
45
|
-
path: dist/
|
|
46
|
-
- name: Publish to PyPI
|
|
47
|
-
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
|
48
|
-
with:
|
|
49
|
-
attestations: true
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
"""Handles creating a release commit and tag, then publishes the GitHub release."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from subprocess import CalledProcessError, check_call, run
|
|
7
|
-
|
|
8
|
-
from git import Commit, Head, Remote, Repo, TagReference
|
|
9
|
-
from packaging.version import Version
|
|
10
|
-
|
|
11
|
-
ROOT_SRC_DIR = Path(__file__).parents[1]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def main(version_str: str) -> None:
|
|
15
|
-
version = Version(version_str)
|
|
16
|
-
repo = Repo(str(ROOT_SRC_DIR))
|
|
17
|
-
|
|
18
|
-
if repo.is_dirty():
|
|
19
|
-
msg = "Current repository is dirty. Please commit any changes and try again."
|
|
20
|
-
raise RuntimeError(msg)
|
|
21
|
-
upstream, release_branch = create_release_branch(repo, version)
|
|
22
|
-
original_main_sha = upstream.refs.main.commit.hexsha
|
|
23
|
-
main_pushed = False
|
|
24
|
-
tag_pushed = False
|
|
25
|
-
release_created = False
|
|
26
|
-
try:
|
|
27
|
-
main_pushed, tag_pushed, release_created = push_release(repo, upstream, release_branch, version)
|
|
28
|
-
finalize_release(repo, upstream, release_branch)
|
|
29
|
-
except Exception:
|
|
30
|
-
cleanup_failed_release(
|
|
31
|
-
repo,
|
|
32
|
-
upstream,
|
|
33
|
-
version,
|
|
34
|
-
release_branch,
|
|
35
|
-
original_main_sha,
|
|
36
|
-
release_created=release_created,
|
|
37
|
-
tag_pushed=tag_pushed,
|
|
38
|
-
main_pushed=main_pushed,
|
|
39
|
-
)
|
|
40
|
-
raise
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def create_release_branch(repo: Repo, version: Version) -> tuple[Remote, Head]:
|
|
44
|
-
print("create release branch from upstream main") # ruff:ignore[print]
|
|
45
|
-
upstream = get_upstream(repo)
|
|
46
|
-
upstream.fetch()
|
|
47
|
-
branch_name = f"release-{version}"
|
|
48
|
-
release_branch = repo.create_head(branch_name, upstream.refs.main, force=True)
|
|
49
|
-
upstream.push(refspec=f"{branch_name}:{branch_name}", force=True)
|
|
50
|
-
release_branch.set_tracking_branch(upstream.refs[branch_name])
|
|
51
|
-
release_branch.checkout()
|
|
52
|
-
return upstream, release_branch
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def get_upstream(repo: Repo) -> Remote:
|
|
56
|
-
for remote in repo.remotes:
|
|
57
|
-
if any("tox-dev/python-discovery" in url for url in remote.urls):
|
|
58
|
-
return remote
|
|
59
|
-
msg = "could not find tox-dev/python-discovery remote"
|
|
60
|
-
raise RuntimeError(msg)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def push_release(repo: Repo, upstream: Remote, release_branch: Head, version: Version) -> tuple[bool, bool, bool]:
|
|
64
|
-
release_commit = release_changelog(repo, version)
|
|
65
|
-
tag = tag_release_commit(release_commit, repo, version)
|
|
66
|
-
print("push release commit") # ruff:ignore[print]
|
|
67
|
-
repo.git.push(upstream.name, f"{release_branch}:main", "-f")
|
|
68
|
-
print("push release tag") # ruff:ignore[print]
|
|
69
|
-
repo.git.push(upstream.name, tag, "-f")
|
|
70
|
-
create_github_release(version)
|
|
71
|
-
return True, True, True
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def release_changelog(repo: Repo, version: Version) -> Commit:
|
|
75
|
-
print("generate release commit") # ruff:ignore[print]
|
|
76
|
-
check_call(["towncrier", "build", "--yes", "--version", version.public], cwd=str(ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
77
|
-
print("format changelog with pre-commit") # ruff:ignore[print]
|
|
78
|
-
changelog_path = ROOT_SRC_DIR / "docs" / "changelog.rst"
|
|
79
|
-
try:
|
|
80
|
-
check_call(["pre-commit", "run", "--files", str(changelog_path)], cwd=str(ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
81
|
-
except CalledProcessError:
|
|
82
|
-
print("pre-commit made formatting changes, staging them") # ruff:ignore[print]
|
|
83
|
-
repo.index.add([str(changelog_path)])
|
|
84
|
-
return repo.index.commit(f"release {version}")
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def tag_release_commit(release_commit: Commit, repo: Repo, version: Version) -> TagReference:
|
|
88
|
-
print("tag release commit") # ruff:ignore[print]
|
|
89
|
-
version_str = str(version)
|
|
90
|
-
if version_str in {tag.name for tag in repo.tags}:
|
|
91
|
-
print(f"delete existing tag {version_str}") # ruff:ignore[print]
|
|
92
|
-
repo.delete_tag(repo.tags[version_str])
|
|
93
|
-
print(f"create tag {version_str}") # ruff:ignore[print]
|
|
94
|
-
return repo.create_tag(version_str, ref=release_commit.hexsha, force=True)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def create_github_release(version: Version) -> None:
|
|
98
|
-
print("create github release") # ruff:ignore[print]
|
|
99
|
-
version_str = str(version)
|
|
100
|
-
try:
|
|
101
|
-
result = run(
|
|
102
|
-
["gh", "release", "create", version_str, "--title", f"v{version_str}", "--generate-notes"], # ruff:ignore[start-process-with-partial-path]
|
|
103
|
-
cwd=str(ROOT_SRC_DIR),
|
|
104
|
-
capture_output=True,
|
|
105
|
-
text=True,
|
|
106
|
-
check=True,
|
|
107
|
-
)
|
|
108
|
-
if result.stdout:
|
|
109
|
-
print(result.stdout) # ruff:ignore[print]
|
|
110
|
-
except CalledProcessError as e:
|
|
111
|
-
print(f"gh release create failed with exit code {e.returncode}") # ruff:ignore[print]
|
|
112
|
-
if e.stdout:
|
|
113
|
-
print(f"stdout: {e.stdout}") # ruff:ignore[print]
|
|
114
|
-
if e.stderr:
|
|
115
|
-
print(f"stderr: {e.stderr}") # ruff:ignore[print]
|
|
116
|
-
raise
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def finalize_release(repo: Repo, upstream: Remote, release_branch: Head) -> None:
|
|
120
|
-
print("checkout main to new release and delete release branch") # ruff:ignore[print]
|
|
121
|
-
repo.heads.main.checkout()
|
|
122
|
-
repo.delete_head(release_branch, force=True)
|
|
123
|
-
print("delete remote release branch") # ruff:ignore[print]
|
|
124
|
-
repo.git.push(upstream.name, f":{release_branch}", "--no-verify")
|
|
125
|
-
upstream.fetch()
|
|
126
|
-
repo.git.reset("--hard", f"{upstream.name}/main")
|
|
127
|
-
print("All done!") # ruff:ignore[print]
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def cleanup_failed_release( # ruff:ignore[too-many-arguments]
|
|
131
|
-
repo: Repo,
|
|
132
|
-
upstream: Remote,
|
|
133
|
-
version: Version,
|
|
134
|
-
release_branch: Head,
|
|
135
|
-
original_main_sha: str,
|
|
136
|
-
*,
|
|
137
|
-
release_created: bool,
|
|
138
|
-
tag_pushed: bool,
|
|
139
|
-
main_pushed: bool,
|
|
140
|
-
) -> None:
|
|
141
|
-
print("Release failed! Cleaning up...") # ruff:ignore[print]
|
|
142
|
-
if release_created:
|
|
143
|
-
print(f"Deleting GitHub release {version}") # ruff:ignore[print]
|
|
144
|
-
try:
|
|
145
|
-
check_call(["gh", "release", "delete", str(version), "--yes"], cwd=str(ROOT_SRC_DIR)) # ruff:ignore[start-process-with-partial-path]
|
|
146
|
-
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
147
|
-
print(f"Warning: Failed to delete GitHub release: {cleanup_error}") # ruff:ignore[print]
|
|
148
|
-
if tag_pushed:
|
|
149
|
-
print(f"Deleting remote tag {version}") # ruff:ignore[print]
|
|
150
|
-
try:
|
|
151
|
-
repo.git.push(upstream.name, f":refs/tags/{version}", "--no-verify")
|
|
152
|
-
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
153
|
-
print(f"Warning: Failed to delete remote tag: {cleanup_error}") # ruff:ignore[print]
|
|
154
|
-
if main_pushed:
|
|
155
|
-
print(f"Reverting main to {original_main_sha[:8]}") # ruff:ignore[print]
|
|
156
|
-
try:
|
|
157
|
-
repo.git.push(upstream.name, f"{original_main_sha}:main", "-f", "--no-verify")
|
|
158
|
-
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
159
|
-
print(f"Warning: Failed to revert main: {cleanup_error}") # ruff:ignore[print]
|
|
160
|
-
print("Deleting remote release branch") # ruff:ignore[print]
|
|
161
|
-
try:
|
|
162
|
-
repo.git.push(upstream.name, f":{release_branch}", "--no-verify")
|
|
163
|
-
except Exception as cleanup_error: # ruff:ignore[blind-except]
|
|
164
|
-
print(f"Warning: Failed to delete remote branch: {cleanup_error}") # ruff:ignore[print]
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
if __name__ == "__main__":
|
|
168
|
-
import argparse
|
|
169
|
-
|
|
170
|
-
parser = argparse.ArgumentParser(prog="release")
|
|
171
|
-
parser.add_argument("--version", required=True)
|
|
172
|
-
options = parser.parse_args()
|
|
173
|
-
main(options.version)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_discovery-1.6.3 → python_discovery-1.6.4}/tests/py_info/test_py_info_exe_based_of.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|