Skip to content

Commit dfffec3

Browse files
authored
Add option to use uv (#427)
* Add option to use uv * Add uv to test script and ci
1 parent 6b94d99 commit dfffec3

12 files changed

+492
-63
lines changed

.github/workflows/testing.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -238,38 +238,38 @@ jobs:
238238
- name: ruff
239239
working-directory: ${{ env.WORKING_DIR }}
240240
run: ruff check .
241-
setuptools-test:
241+
uv-linting:
242242
strategy:
243243
fail-fast: false
244244
matrix:
245245
project_type: ["application", "lib"]
246-
os: [ubuntu-latest, macos-latest]
247-
runs-on: ${{ matrix.os }}
246+
runs-on: ubuntu-latest
248247
steps:
249248
- uses: actions/checkout@v4
250249
- name: Install Rust
251250
run: |
252251
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
253252
- name: Cache Rust dependencies
254253
uses: Swatinem/[email protected]
254+
- name: Install uv
255+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
255256
- name: Set up Python
256257
uses: actions/setup-python@v5
257258
with:
258-
python-version: "3.11"
259+
python-version: "${{ env.MIN_PYTHON_VERSION }}"
259260
- name: Build package
260261
run: cargo build --release
261262
- name: Run creation
262263
run: |
263-
./scripts/ci_run.sh ${{ matrix.project_type }} 3
264+
./scripts/ci_run.sh ${{ matrix.project_type }} 4
264265
- name: Install Dependencies
265266
working-directory: ${{ env.WORKING_DIR }}
266267
run: |
267-
python -m pip install -U pip
268-
pipx install pre-commit
269-
python -m pip install -r requirements-dev.txt
270-
- name: Pre-commit install
268+
uv lock
269+
uv sync --locked
270+
- name: MyPy
271271
working-directory: ${{ env.WORKING_DIR }}
272-
run: pre-commit install
273-
- name: Test with pytest
272+
run: uv run mypy .
273+
- name: ruff
274274
working-directory: ${{ env.WORKING_DIR }}
275-
run: pytest
275+
run: uv run ruff check .

scripts/ci_run.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ project_manager="1"
1717

1818
# Check for user provided project manager input
1919
if [ $# -gt 1 ]; then
20-
if [ $2 -lt 1 ] || [ $2 -gt 3 ]; then
20+
if [ $2 -lt 1 ] || [ $2 -gt 4 ]; then
2121
echo "Invalid project_manager value"
2222
exit 1
2323
else

src/github_actions.rs

Lines changed: 239 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,84 @@ jobs:
135135
)
136136
}
137137

138+
fn create_uv_ci_testing_linux_only_file(
139+
source_dir: &str,
140+
min_python_version: &str,
141+
github_action_python_test_versions: &[String],
142+
) -> String {
143+
let python_versions = build_actions_python_test_versions(github_action_python_test_versions);
144+
145+
format!(
146+
r#"name: Testing
147+
148+
on:
149+
push:
150+
branches:
151+
- main
152+
pull_request:
153+
env:
154+
UV_CACHE_DIR: /tmp/.uv-cache
155+
jobs:
156+
linting:
157+
runs-on: ubuntu-latest
158+
steps:
159+
- uses: actions/checkout@v4
160+
- name: Install uv
161+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
162+
- name: Set up Python
163+
uses: actions/setup-python@v5
164+
with:
165+
python-version: "{min_python_version}"
166+
- name: Restore uv cache
167+
uses: actions/cache@v4
168+
with:
169+
path: ${{ env.UV_CACHE_DIR }}
170+
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
171+
restore-keys: |
172+
uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
173+
uv-${{ runner.os }}
174+
- name: Install Dependencies
175+
run: uv sync --locked
176+
- name: Ruff format check
177+
run: uv run ruff format {source_dir} tests --check
178+
- name: Lint with ruff
179+
run: uv run ruff check .
180+
- name: mypy check
181+
run: uv run mypy .
182+
- name: Minimize uv cache
183+
run: uv cache prune --ci
184+
testing:
185+
strategy:
186+
fail-fast: false
187+
matrix:
188+
python-version: [{python_versions}]
189+
runs-on: ubuntu-latest
190+
steps:
191+
- uses: actions/checkout@v4
192+
- name: Install uv
193+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
194+
- name: Set up Python ${{{{ matrix.python-version }}}}
195+
uses: actions/setup-python@v5
196+
with:
197+
python-version: ${{{{ matrix.python-version }}}}
198+
- name: Restore uv cache
199+
uses: actions/cache@v4
200+
with:
201+
path: ${{ env.UV_CACHE_DIR }}
202+
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
203+
restore-keys: |
204+
uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
205+
uv-${{ runner.os }}
206+
- name: Install Dependencies
207+
run: uv sync --locked
208+
- name: Test with pytest
209+
run: uv run pytest
210+
- name: Minimize uv cache
211+
run: uv cache prune --ci
212+
"#
213+
)
214+
}
215+
138216
fn create_ci_testing_linux_only_file_pyo3(
139217
source_dir: &str,
140218
min_python_version: &str,
@@ -247,6 +325,11 @@ pub fn save_ci_testing_linux_only_file(project_info: &ProjectInfo) -> Result<()>
247325
&project_info.min_python_version,
248326
&project_info.github_actions_python_test_versions,
249327
),
328+
ProjectManager::Uv => create_uv_ci_testing_linux_only_file(
329+
&project_info.source_dir,
330+
&project_info.min_python_version,
331+
&project_info.github_actions_python_test_versions,
332+
),
250333
};
251334

252335
save_file_with_content(&file_path, &content)?;
@@ -473,6 +556,90 @@ jobs:
473556
)
474557
}
475558

559+
fn create_uv_ci_testing_multi_os_file(
560+
source_dir: &str,
561+
min_python_version: &str,
562+
github_action_python_test_versions: &[String],
563+
) -> String {
564+
let python_versions = build_actions_python_test_versions(github_action_python_test_versions);
565+
566+
format!(
567+
r#"name: Testing
568+
569+
on:
570+
push:
571+
branches:
572+
- main
573+
pull_request:
574+
env:
575+
UV_CACHE_DIR: /tmp/.uv-cache
576+
jobs:
577+
linting:
578+
runs-on: ubuntu-latest
579+
steps:
580+
- uses: actions/checkout@v4
581+
- name: Install uv
582+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
583+
- name: Set up Python
584+
uses: actions/setup-python@v5
585+
with:
586+
python-version: "{min_python_version}"
587+
- name: Restore uv cache
588+
uses: actions/cache@v4
589+
with:
590+
path: ${{ env.UV_CACHE_DIR }}
591+
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
592+
restore-keys: |
593+
uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
594+
uv-${{ runner.os }}
595+
- name: Install Dependencies
596+
run: uv sync --locked
597+
- name: Ruff format check
598+
run: uv run ruff format {source_dir} tests --check
599+
- name: Lint with ruff
600+
run: uv run ruff check .
601+
- name: mypy check
602+
run: uv run mypy .
603+
- name: Minimize uv cache
604+
run: uv cache prune --ci
605+
testing:
606+
strategy:
607+
fail-fast: false
608+
matrix:
609+
python-version: [{python_versions}]
610+
os: [ubuntu-latest, windows-latest, macos-latest]
611+
runs-on: ${{{{ matrix.os }}}}
612+
steps:
613+
- uses: actions/checkout@v4
614+
- name: Set up uv ubuntu/mac
615+
if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' }}
616+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
617+
- name: Set up uv windows
618+
if: ${{ matrix.os == 'windows-latest' }}
619+
run: irm https://astral.sh/uv/install.ps1 | iex
620+
shell: powershell
621+
- name: Set up Python ${{{{ matrix.python-version }}}}
622+
uses: actions/setup-python@v5
623+
with:
624+
python-version: ${{{{ matrix.python-version }}}}
625+
- name: Restore uv cache
626+
uses: actions/cache@v4
627+
with:
628+
path: ${{ env.UV_CACHE_DIR }}
629+
key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
630+
restore-keys: |
631+
uv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
632+
uv-${{ runner.os }}
633+
- name: Install Dependencies
634+
run: uv sync --locked
635+
- name: Test with pytest
636+
run: uv run pytest
637+
- name: Minimize uv cache
638+
run: uv cache prune --ci
639+
"#
640+
)
641+
}
642+
476643
pub fn save_ci_testing_multi_os_file(project_info: &ProjectInfo) -> Result<()> {
477644
let file_path = project_info
478645
.base_dir()
@@ -493,6 +660,11 @@ pub fn save_ci_testing_multi_os_file(project_info: &ProjectInfo) -> Result<()> {
493660
&project_info.min_python_version,
494661
&project_info.github_actions_python_test_versions,
495662
),
663+
ProjectManager::Uv => create_uv_ci_testing_multi_os_file(
664+
&project_info.source_dir,
665+
&project_info.min_python_version,
666+
&project_info.github_actions_python_test_versions,
667+
),
496668
};
497669

498670
save_file_with_content(&file_path, &content)?;
@@ -791,7 +963,7 @@ jobs:
791963
python -m pip install -U pip
792964
python -m pip -r requirements-dev.txt
793965
python -m pip install build setuptools wheel twine
794-
- name: Publish package
966+
- name: Build and publish package
795967
env:
796968
TWINE_USERNAME: __token__
797969
TWINE_PASSWORD: ${{{{ secrets.PYPI_API_KEY }}}}
@@ -802,6 +974,37 @@ jobs:
802974
)
803975
}
804976

977+
fn create_uv_pypi_publish_file(python_version: &str) -> String {
978+
format!(
979+
r#"name: PyPi Publish
980+
on:
981+
release:
982+
types:
983+
- published
984+
jobs:
985+
deploy:
986+
runs-on: ubuntu-latest
987+
steps:
988+
- uses: actions/checkout@v4
989+
- name: Install uv
990+
run: curl -LsSf https://astral.sh/uv/install.sh | sh
991+
- name: Set up Python
992+
uses: actions/setup-python@v5
993+
with:
994+
python-version: "{python_version}"
995+
- name: Install Dependencies
996+
run: uv sync --frozen
997+
- name: Build and publish package
998+
env:
999+
TWINE_USERNAME: __token__
1000+
TWINE_PASSWORD: ${{{{ secrets.PYPI_API_KEY }}}}
1001+
run: |
1002+
uvx --from build pyproject-build --installer uv
1003+
uvx twine upload dist/*
1004+
"#
1005+
)
1006+
}
1007+
8051008
pub fn save_pypi_publish_file(project_info: &ProjectInfo) -> Result<()> {
8061009
let file_path = project_info
8071010
.base_dir()
@@ -812,6 +1015,7 @@ pub fn save_pypi_publish_file(project_info: &ProjectInfo) -> Result<()> {
8121015
ProjectManager::Setuptools => {
8131016
create_setuptools_pypi_publish_file(&project_info.python_version)
8141017
}
1018+
ProjectManager::Uv => create_uv_pypi_publish_file(&project_info.python_version),
8151019
};
8161020

8171021
save_file_with_content(&file_path, &content)?;
@@ -989,6 +1193,23 @@ mod tests {
9891193
assert_yaml_snapshot!(content);
9901194
}
9911195

1196+
#[test]
1197+
fn test_save_uv_ci_testing_linux_only_file() {
1198+
let mut project_info = project_info_dummy();
1199+
project_info.project_manager = ProjectManager::Uv;
1200+
project_info.use_multi_os_ci = false;
1201+
let base = project_info.base_dir();
1202+
create_dir_all(base.join(".github/workflows")).unwrap();
1203+
let expected_file = base.join(".github/workflows/testing.yml");
1204+
save_ci_testing_linux_only_file(&project_info).unwrap();
1205+
1206+
assert!(expected_file.is_file());
1207+
1208+
let content = std::fs::read_to_string(expected_file).unwrap();
1209+
1210+
assert_yaml_snapshot!(content);
1211+
}
1212+
9921213
#[test]
9931214
fn test_save_poetry_ci_testing_multi_os_file() {
9941215
let mut project_info = project_info_dummy();
@@ -1040,6 +1261,23 @@ mod tests {
10401261
assert_yaml_snapshot!(content);
10411262
}
10421263

1264+
#[test]
1265+
fn test_save_uv_ci_testing_multi_os_file() {
1266+
let mut project_info = project_info_dummy();
1267+
project_info.project_manager = ProjectManager::Uv;
1268+
project_info.use_multi_os_ci = true;
1269+
let base = project_info.base_dir();
1270+
create_dir_all(base.join(".github/workflows")).unwrap();
1271+
let expected_file = base.join(".github/workflows/testing.yml");
1272+
save_ci_testing_multi_os_file(&project_info).unwrap();
1273+
1274+
assert!(expected_file.is_file());
1275+
1276+
let content = std::fs::read_to_string(expected_file).unwrap();
1277+
1278+
assert_yaml_snapshot!(content);
1279+
}
1280+
10431281
#[test]
10441282
fn test_save_dependabot_file() {
10451283
let mut project_info = project_info_dummy();

0 commit comments

Comments
 (0)