Skip to content

Commit 90d8503

Browse files
dceoyclaude
andcommitted
Update Python package workflows to improve uv.lock handling
- Set up uv using astral-sh/setup-uv action when uv.lock is present - Detect lock files early in workflow execution - Add uv-version parameter for controlling uv version - Clarify parameter descriptions for uv.lock compatibility - Use EXECUTOR environment variable for command execution abstraction 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent d67f63b commit 90d8503

4 files changed

Lines changed: 159 additions & 51 deletions

File tree

.github/workflows/python-package-format-and-pr.yml

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ on:
1111
python-version:
1212
required: false
1313
type: string
14-
description: Python version to use
14+
description: Python version to use (not applicable if uv.lock is present)
1515
default: 3.x
16+
uv-version:
17+
required: false
18+
type: string
19+
description: Version of uv to use (applicable only if uv.lock is present)
20+
default: latest
1621
use-black:
1722
required: false
1823
type: boolean
@@ -31,7 +36,7 @@ on:
3136
requirements-txt:
3237
required: false
3338
type: string
34-
description: Path to the requirements.txt file
39+
description: Path to the requirements.txt file (not applicable if uv.lock is present)
3540
default: null
3641
runs-on:
3742
required: false
@@ -55,28 +60,46 @@ jobs:
5560
steps:
5661
- name: Checkout repository
5762
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
63+
- name: Detect uv.lock or poetry.lock
64+
id: detect-lock-file
65+
run: |
66+
if [[ -f uv.lock ]]; then
67+
echo "lock_file=uv.lock" >> "${GITHUB_OUTPUT}"
68+
elif [[ -f poetry.lock ]]; then
69+
echo "lock_file=poetry.lock" >> "${GITHUB_OUTPUT}"
70+
else
71+
echo "lock_file=" >> "${GITHUB_OUTPUT}"
72+
fi
73+
- name: Set up uv
74+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
75+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
76+
with:
77+
version: latest
78+
- name: Install packages using uv
79+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
80+
run: |
81+
uv sync --dev
82+
uv add --dev \
83+
${{ inputs.use-black && 'black' || 'ruff' }} \
84+
${{ inputs.use-isort && 'isort' || '' }}
85+
echo "EXECUTOR=uv run --directory ${PWD}" | tee -a "${GITHUB_ENV}"
5886
- name: Set up Python
87+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
5988
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
6089
with:
6190
python-version: ${{ inputs.python-version }}
6291
- name: Install packages
92+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
6393
env:
64-
POETRY_HOME: /opt/poetry
94+
LOCK_FILE: ${{ steps.detect-lock-file.outputs.lock_file }}
6595
REQUIREMENTS_TXT_PATH: ${{ inputs.requirements-txt }}
6696
working-directory: ${{ inputs.package-path }}
6797
run: |
6898
pip install -U --no-cache-dir pip
6999
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
70100
pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
71101
fi
72-
if [[ -f uv.lock ]]; then
73-
pip install --no-cache-dir uv
74-
uv sync --dev
75-
uv add --dev \
76-
${{ inputs.use-black && 'black' || 'ruff' }} \
77-
${{ inputs.use-isort && 'isort' || '' }}
78-
echo "EXECUTOR=uv run --directory ${PWD}" | tee -a "${GITHUB_ENV}"
79-
elif [[ -f poetry.lock ]]; then
102+
if [[ "${LOCK_FILE}" == "poetry.lock" ]]; then
80103
pip install --no-cache-dir poetry
81104
poetry lock --no-interaction
82105
poetry add --group=dev --no-interaction \

.github/workflows/python-package-lint-and-scan.yml

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ on:
1111
python-version:
1212
required: false
1313
type: string
14-
description: Python version to use
14+
description: Python version to use (not applicable if uv.lock is present)
1515
default: 3.x
16+
uv-version:
17+
required: false
18+
type: string
19+
description: Version of uv to use (applicable only if uv.lock is present)
20+
default: latest
1621
use-pyright:
1722
required: false
1823
type: boolean
@@ -46,7 +51,7 @@ on:
4651
requirements-txt:
4752
required: false
4853
type: string
49-
description: Path to the requirements.txt file
54+
description: Path to the requirements.txt file (not applicable if uv.lock is present)
5055
default: null
5156
runs-on:
5257
required: false
@@ -63,13 +68,47 @@ jobs:
6368
steps:
6469
- name: Checkout repository
6570
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
71+
- name: Detect uv.lock or poetry.lock
72+
id: detect-lock-file
73+
run: |
74+
if [[ -f uv.lock ]]; then
75+
echo "lock_file=uv.lock" >> "${GITHUB_OUTPUT}"
76+
elif [[ -f poetry.lock ]]; then
77+
echo "lock_file=poetry.lock" >> "${GITHUB_OUTPUT}"
78+
else
79+
echo "lock_file=" >> "${GITHUB_OUTPUT}"
80+
fi
81+
- name: Set up uv
82+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
83+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
84+
with:
85+
version: latest
86+
- name: Install packages using uv
87+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
88+
working-directory: ${{ inputs.package-path }}
89+
run: |
90+
uv sync --dev
91+
uv add --dev \
92+
${{ inputs.use-flake8 && 'flake8' || '' }} \
93+
${{ inputs.use-bandit && 'bandit' || '' }} \
94+
${{ inputs.use-mypy && 'mypy' || '' }} \
95+
${{ inputs.use-pyright && 'pyright' || '' }} \
96+
ruff
97+
for p in $(echo "${{ inputs.additional-python-packages }}" | tr ' ' '\n'); do
98+
if [[ -n "${p}" ]]; then
99+
uv add --dev "${p}"
100+
fi
101+
done
102+
echo "EXECUTOR=uv run --directory ${PWD}" | tee -a "${GITHUB_ENV}"
66103
- name: Set up Python
104+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
67105
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
68106
with:
69107
python-version: ${{ inputs.python-version }}
70108
- name: Install packages
109+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
71110
env:
72-
POETRY_HOME: /opt/poetry
111+
LOCK_FILE: ${{ steps.detect-lock-file.outputs.lock_file }}
73112
ADDITIONAL_PYTHON_PACKAGES: ${{ inputs.additional-python-packages }}
74113
REQUIREMENTS_TXT_PATH: ${{ inputs.requirements-txt }}
75114
working-directory: ${{ inputs.package-path }}
@@ -78,22 +117,7 @@ jobs:
78117
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
79118
pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
80119
fi
81-
if [[ -f uv.lock ]]; then
82-
pip install --no-cache-dir uv
83-
uv sync --dev
84-
uv add --dev \
85-
${{ inputs.use-flake8 && 'flake8' || '' }} \
86-
${{ inputs.use-bandit && 'bandit' || '' }} \
87-
${{ inputs.use-mypy && 'mypy' || '' }} \
88-
${{ inputs.use-pyright && 'pyright' || '' }} \
89-
ruff
90-
for p in $(echo "${ADDITIONAL_PYTHON_PACKAGES}" | tr ' ' '\n'); do
91-
if [[ -n "${p}" ]]; then
92-
uv add --dev "${p}"
93-
fi
94-
done
95-
echo "EXECUTOR=uv run --directory ${PWD}" | tee -a "${GITHUB_ENV}"
96-
elif [[ -f poetry.lock ]]; then
120+
if [[ "${LOCK_FILE}" == "poetry.lock" ]]; then
97121
pip install --no-cache-dir poetry
98122
poetry lock --no-interaction
99123
poetry add --group=dev --no-interaction \

.github/workflows/python-package-release-on-pypi-and-github.yml

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,17 @@ on:
2121
python-version:
2222
required: false
2323
type: string
24-
description: Python version to use
24+
description: Python version to use (not applicable if uv.lock is present)
2525
default: 3.x
26+
uv-version:
27+
required: false
28+
type: string
29+
description: Version of uv to use (applicable only if uv.lock is present)
30+
default: latest
2631
requirements-txt:
2732
required: false
2833
type: string
29-
description: Path to the requirements.txt file
34+
description: Path to the requirements.txt file (not applicable if uv.lock is present)
3035
default: null
3136
artifact-retention-days:
3237
required: false
@@ -63,14 +68,30 @@ jobs:
6368
steps:
6469
- name: Checkout repository
6570
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
71+
- name: Detect uv.lock or poetry.lock
72+
id: detect-lock-file
73+
run: |
74+
if [[ -f uv.lock ]]; then
75+
echo "lock_file=uv.lock" >> "${GITHUB_OUTPUT}"
76+
elif [[ -f poetry.lock ]]; then
77+
echo "lock_file=poetry.lock" >> "${GITHUB_OUTPUT}"
78+
else
79+
echo "lock_file=" >> "${GITHUB_OUTPUT}"
80+
fi
81+
- name: Set up uv
82+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
83+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
84+
with:
85+
version: latest
6686
- name: Set up Python
87+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
6788
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
6889
with:
6990
python-version: ${{ inputs.python-version }}
7091
- name: Read the project name
7192
id: read-project-name
7293
working-directory: ${{ inputs.package-path }}
73-
shell: python3 {0}
94+
shell: ${{ steps.detect-lock-file.outputs.lock_file == 'uv.lock' && 'uv ' || '' }} python {0}
7495
run: |
7596
import os
7697
import tomllib
@@ -87,22 +108,24 @@ jobs:
87108
print(f"project_name={name}", file=f)
88109
- name: Build a binary wheel and a source tarball
89110
env:
111+
LOCK_FILE: ${{ steps.detect-lock-file.outputs.lock_file }}
90112
REQUIREMENTS_TXT_PATH: ${{ inputs.requirements-txt }}
91113
working-directory: ${{ inputs.package-path }}
92114
run: |
93-
pip install -U --no-cache-dir pip
94-
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
95-
pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
96-
fi
97-
if [[ -f uv.lock ]]; then
98-
pip install --no-cache-dir uv
115+
if [[ "${LOCK_FILE}" == "uv.lock" ]]; then
99116
uv build
100-
elif [[ -f poetry.lock ]]; then
101-
pip install --no-cache-dir poetry
102-
poetry build --format=wheel --no-interaction
103117
else
104-
pip install --no-cache-dir build
105-
python -m build
118+
pip install -U --no-cache-dir pip
119+
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
120+
pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
121+
fi
122+
if [[ "${LOCK_FILE}" == "poetry.lock" ]]; then
123+
pip install --no-cache-dir poetry
124+
poetry build --format=wheel --no-interaction
125+
else
126+
pip install --no-cache-dir build
127+
python -m build
128+
fi
106129
fi
107130
mv dist /tmp/${{ steps.read-project-name.outputs.project_name }}_dist
108131
- name: Store the distribution packages

.github/workflows/python-pyinstaller.yml

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,17 @@ on:
1010
python-version:
1111
required: false
1212
type: string
13-
description: Python version to use
13+
description: Python version to use (not applicable if uv.lock is present)
1414
default: 3.x
15+
uv-version:
16+
required: false
17+
type: string
18+
description: Version of uv to use (applicable only if uv.lock is present)
19+
default: latest
1520
requirements-txt:
1621
required: false
1722
type: string
18-
description: Path to the requirements.txt file
23+
description: Path to the requirements.txt file (not applicable if uv.lock is present)
1924
default: null
2025
artifact-name:
2126
required: false
@@ -52,24 +57,57 @@ jobs:
5257
steps:
5358
- name: Checkout repository
5459
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
60+
- name: Detect uv.lock or poetry.lock
61+
id: detect-lock-file
62+
run: |
63+
if [[ -f uv.lock ]]; then
64+
echo "lock_file=uv.lock" >> "${GITHUB_OUTPUT}"
65+
elif [[ -f poetry.lock ]]; then
66+
echo "lock_file=poetry.lock" >> "${GITHUB_OUTPUT}"
67+
else
68+
echo "lock_file=" >> "${GITHUB_OUTPUT}"
69+
fi
70+
- name: Set up uv
71+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
72+
uses: astral-sh/setup-uv@e92bafb6253dcd438e0484186d7669ea7a8ca1cc # v6.4.3
73+
with:
74+
version: latest
75+
- name: Install packages using uv
76+
if: steps.detect-lock-file.outputs.lock_file == 'uv.lock'
77+
run: |
78+
uv sync --dev
79+
uv add --dev PyInstaller
80+
echo "EXECUTOR=uv run" | tee -a "${GITHUB_ENV}"
5581
- name: Set up Python
82+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
5683
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
5784
with:
5885
python-version: ${{ inputs.python-version }}
5986
- name: Install packages
87+
if: steps.detect-lock-file.outputs.lock_file != 'uv.lock'
6088
env:
89+
LOCK_FILE: ${{ steps.detect-lock-file.outputs.lock_file }}
6190
REQUIREMENTS_TXT_PATH: ${{ inputs.requirements-txt }}
6291
run: |
63-
python -m pip install -U --no-cache-dir pip
64-
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
65-
python -m pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
92+
if [[ "${LOCK_FILE}" == "poetry.lock" ]]; then
93+
python -m pip install --no-cache-dir poetry
94+
poetry lock --no-interaction
95+
poetry add --group=dev --no-interaction PyInstaller
96+
poetry install --no-interaction
97+
echo "EXECUTOR=poetry run" | tee -a "${GITHUB_ENV}"
98+
else
99+
python -m pip install -U --no-cache-dir pip
100+
if [[ -n "${REQUIREMENTS_TXT_PATH}" ]]; then
101+
python -m pip install -U --no-cache-dir -r "${REQUIREMENTS_TXT_PATH}"
102+
fi
103+
python -m pip install --no-cache-dir PyInstaller
104+
echo "EXECUTOR=python -m" | tee -a "${GITHUB_ENV}"
66105
fi
67-
python -m pip install --no-cache-dir PyInstaller
68106
- name: Build an executable file
69107
env:
70108
APP_SCRIPT_PATH: ${{ inputs.app-script-path }}
71109
run: >
72-
python -m PyInstaller --clean --noconsole --onefile "${APP_SCRIPT_PATH}"
110+
${{ env.EXECUTOR }} PyInstaller --clean --noconsole --onefile "${APP_SCRIPT_PATH}"
73111
- name: Upload the artifact
74112
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
75113
with:

0 commit comments

Comments
 (0)