mirror of
https://github.com/astral-sh/setup-uv.git
synced 2025-12-15 11:07:14 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38f3f10444 | ||
|
|
8bdd012be5 | ||
|
|
5f42d5af6c | ||
|
|
26ddfef6e1 | ||
|
|
ee4fa33003 | ||
|
|
420915557e | ||
|
|
9839fa9fb5 | ||
|
|
196fe5f098 | ||
|
|
49d8a3d9a8 | ||
|
|
d8db0a86d3 | ||
|
|
ed171c292b | ||
|
|
691a091485 | ||
|
|
9b71657bb2 |
10
.github/workflows/test-cache-windows.yml
vendored
10
.github/workflows/test-cache-windows.yml
vendored
@@ -11,10 +11,7 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-setup-cache:
|
test-setup-cache:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: windows-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [windows-latest]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup with cache
|
- name: Setup with cache
|
||||||
@@ -25,10 +22,7 @@ jobs:
|
|||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__\fixtures\uv-project
|
working-directory: __tests__\fixtures\uv-project
|
||||||
test-restore-cache:
|
test-restore-cache:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: windows-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [windows-latest]
|
|
||||||
needs: test-setup-cache
|
needs: test-setup-cache
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|||||||
59
.github/workflows/test-cache.yml
vendored
59
.github/workflows/test-cache.yml
vendored
@@ -11,24 +11,18 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-setup-cache:
|
test-setup-cache:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-latest, macos-14]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup with cache
|
- name: Setup with cache
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache
|
||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__/fixtures/uv-project
|
working-directory: __tests__/fixtures/uv-project
|
||||||
test-restore-cache:
|
test-restore-cache:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, macos-latest, macos-14]
|
|
||||||
needs: test-setup-cache
|
needs: test-setup-cache
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -37,7 +31,7 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache
|
||||||
- name: Cache was hit
|
- name: Cache was hit
|
||||||
run: |
|
run: |
|
||||||
if [ "$CACHE_HIT" != "true" ]; then
|
if [ "$CACHE_HIT" != "true" ]; then
|
||||||
@@ -59,7 +53,7 @@ jobs:
|
|||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
__tests__/fixtures/uv-project/uv.lock
|
__tests__/fixtures/uv-project/uv.lock
|
||||||
**/pyproject.toml
|
**/pyproject.toml
|
||||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob
|
||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__/fixtures/uv-project
|
working-directory: __tests__/fixtures/uv-project
|
||||||
test-restore-cache-dependency-glob:
|
test-restore-cache-dependency-glob:
|
||||||
@@ -79,7 +73,8 @@ jobs:
|
|||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
__tests__/fixtures/uv-project/uv.lock
|
__tests__/fixtures/uv-project/uv.lock
|
||||||
**/pyproject.toml
|
**/pyproject.toml
|
||||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob
|
||||||
|
ignore-nothing-to-cache: true
|
||||||
- name: Cache was not hit
|
- name: Cache was not hit
|
||||||
run: |
|
run: |
|
||||||
if [ "$CACHE_HIT" == "true" ]; then
|
if [ "$CACHE_HIT" == "true" ]; then
|
||||||
@@ -96,7 +91,7 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local
|
||||||
cache-local-path: /tmp/uv-cache
|
cache-local-path: /tmp/uv-cache
|
||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__/fixtures/uv-project
|
working-directory: __tests__/fixtures/uv-project
|
||||||
@@ -110,7 +105,7 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local
|
||||||
cache-local-path: /tmp/uv-cache
|
cache-local-path: /tmp/uv-cache
|
||||||
- name: Cache was hit
|
- name: Cache was hit
|
||||||
run: |
|
run: |
|
||||||
@@ -122,38 +117,38 @@ jobs:
|
|||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__/fixtures/uv-project
|
working-directory: __tests__/fixtures/uv-project
|
||||||
|
|
||||||
prepare-tilde-expansion-tests:
|
test-tilde-expansion-cache-local-path:
|
||||||
runs-on: selfhosted-ubuntu-arm64
|
runs-on: selfhosted-ubuntu-arm64
|
||||||
steps:
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Create cache directory
|
||||||
|
run: mkdir -p ~/uv-cache
|
||||||
|
shell: bash
|
||||||
|
- name: Setup with cache
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
cache-local-path: ~/uv-cache/cache-local-path
|
||||||
|
- run: uv sync
|
||||||
|
working-directory: __tests__/fixtures/uv-project
|
||||||
|
|
||||||
|
test-tilde-expansion-cache-dependency-glob:
|
||||||
|
runs-on: selfhosted-ubuntu-arm64
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
- name: Create cache directory
|
- name: Create cache directory
|
||||||
run: mkdir -p ~/uv-cache
|
run: mkdir -p ~/uv-cache
|
||||||
shell: bash
|
shell: bash
|
||||||
- name: Create cache dependency glob file
|
- name: Create cache dependency glob file
|
||||||
run: touch ~/uv-cache.glob
|
run: touch ~/uv-cache.glob
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
test-tilde-expansion-cache-local-path:
|
|
||||||
needs: prepare-tilde-expansion-tests
|
|
||||||
runs-on: selfhosted-ubuntu-arm64
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup with cache
|
|
||||||
uses: ./
|
|
||||||
with:
|
|
||||||
enable-cache: true
|
|
||||||
cache-local-path: ~/uv-cache/cache-local-path
|
|
||||||
|
|
||||||
test-tilde-expansion-cache-dependency-glob:
|
|
||||||
needs: prepare-tilde-expansion-tests
|
|
||||||
runs-on: selfhosted-ubuntu-arm64
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup with cache
|
- name: Setup with cache
|
||||||
uses: ./
|
uses: ./
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-local-path: ~/uv-cache/cache-dependency-glob
|
cache-local-path: ~/uv-cache/cache-dependency-glob
|
||||||
cache-dependency-glob: "~/uv-cache.glob"
|
cache-dependency-glob: "~/uv-cache.glob"
|
||||||
|
- run: uv sync
|
||||||
|
working-directory: __tests__/fixtures/uv-project
|
||||||
|
|
||||||
cleanup-tilde-expansion-tests:
|
cleanup-tilde-expansion-tests:
|
||||||
needs:
|
needs:
|
||||||
|
|||||||
43
.github/workflows/test.yml
vendored
43
.github/workflows/test.yml
vendored
@@ -28,19 +28,18 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, macos-14, selfhosted-ubuntu-arm64]
|
os: [ubuntu-latest, macos-latest, macos-14]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install default version
|
- name: Install latest version
|
||||||
uses: ./
|
uses: ./
|
||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__/fixtures/uv-project
|
working-directory: __tests__/fixtures/uv-project
|
||||||
test-specific-version:
|
test-specific-version:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, macos-14, selfhosted-ubuntu-arm64]
|
uv-version: ["0.3.0", "0.3.2", "0.3", "0.3.x", ">=0.3.0"]
|
||||||
uv-version: ["latest", "0.3.0", "0.3.2", "0.3", "0.3.x", ">=0.3.0"]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install version ${{ matrix.uv-version }}
|
- name: Install version ${{ matrix.uv-version }}
|
||||||
@@ -50,10 +49,7 @@ jobs:
|
|||||||
- run: uv sync
|
- run: uv sync
|
||||||
working-directory: __tests__/fixtures/uv-project
|
working-directory: __tests__/fixtures/uv-project
|
||||||
test-semver-range:
|
test-semver-range:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ubuntu-latest, selfhosted-ubuntu-arm64]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Install version 0.3
|
- name: Install version 0.3
|
||||||
@@ -72,15 +68,15 @@ jobs:
|
|||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, selfhosted-ubuntu-arm64]
|
os: [ubuntu-latest, macos-latest]
|
||||||
checksum:
|
checksum:
|
||||||
["4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd"]
|
["4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd"]
|
||||||
exclude:
|
exclude:
|
||||||
- os: selfhosted-ubuntu-arm64
|
- os: macos-latest
|
||||||
checksum: "4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd"
|
checksum: "4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd"
|
||||||
include:
|
include:
|
||||||
- os: selfhosted-ubuntu-arm64
|
- os: macos-latest
|
||||||
checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
|
checksum: "a70cbfbf3bb5c08b2f84963b4f12c94e08fbb2468ba418a3bfe1066fbe9e7218"
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Checksum matches expected
|
- name: Checksum matches expected
|
||||||
@@ -115,7 +111,6 @@ jobs:
|
|||||||
macos-latest,
|
macos-latest,
|
||||||
macos-14,
|
macos-14,
|
||||||
windows-latest,
|
windows-latest,
|
||||||
selfhosted-ubuntu-arm64,
|
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -123,7 +118,6 @@ jobs:
|
|||||||
uses: ./
|
uses: ./
|
||||||
- run: uv tool install ruff
|
- run: uv tool install ruff
|
||||||
- run: ruff --version
|
- run: ruff --version
|
||||||
|
|
||||||
test-tilde-expansion-tool-dirs:
|
test-tilde-expansion-tool-dirs:
|
||||||
runs-on: selfhosted-ubuntu-arm64
|
runs-on: selfhosted-ubuntu-arm64
|
||||||
steps:
|
steps:
|
||||||
@@ -143,4 +137,21 @@ jobs:
|
|||||||
echo "UV_TOOL_DIR does not contain /home/ubuntu/tool-dir: $UV_TOOL_DIR"
|
echo "UV_TOOL_DIR does not contain /home/ubuntu/tool-dir: $UV_TOOL_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
test-python-version:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.12", "3.13t"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install latest version
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Verify UV_PYTHON is set to correct version
|
||||||
|
run: |
|
||||||
|
if [ "$UV_PYTHON" != "${{ matrix.python-version }}" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
- run: uv sync
|
||||||
|
working-directory: __tests__/fixtures/uv-project
|
||||||
|
|||||||
110
README.md
110
README.md
@@ -14,10 +14,13 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs
|
|||||||
- [Install the latest version (default)](#install-the-latest-version-default)
|
- [Install the latest version (default)](#install-the-latest-version-default)
|
||||||
- [Install a specific version](#install-a-specific-version)
|
- [Install a specific version](#install-a-specific-version)
|
||||||
- [Install a version by supplying a semver range](#install-a-version-by-supplying-a-semver-range)
|
- [Install a version by supplying a semver range](#install-a-version-by-supplying-a-semver-range)
|
||||||
|
- [Python version](#python-version)
|
||||||
- [Validate checksum](#validate-checksum)
|
- [Validate checksum](#validate-checksum)
|
||||||
- [Enable Caching](#enable-caching)
|
- [Enable Caching](#enable-caching)
|
||||||
- [Cache dependency glob](#cache-dependency-glob)
|
- [Cache dependency glob](#cache-dependency-glob)
|
||||||
- [Local cache path](#local-cache-path)
|
- [Local cache path](#local-cache-path)
|
||||||
|
- [Disable cache pruning](#disable-cache-pruning)
|
||||||
|
- [Ignore nothing to cache](#ignore-nothing-to-cache)
|
||||||
- [GitHub authentication token](#github-authentication-token)
|
- [GitHub authentication token](#github-authentication-token)
|
||||||
- [UV_TOOL_DIR](#uv_tool_dir)
|
- [UV_TOOL_DIR](#uv_tool_dir)
|
||||||
- [UV_TOOL_BIN_DIR](#uv_tool_bin_dir)
|
- [UV_TOOL_BIN_DIR](#uv_tool_bin_dir)
|
||||||
@@ -31,7 +34,7 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install the latest version of uv
|
- name: Install the latest version of uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
version: "latest"
|
version: "latest"
|
||||||
```
|
```
|
||||||
@@ -39,49 +42,75 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs
|
|||||||
For an example workflow, see
|
For an example workflow, see
|
||||||
[here](https://github.com/charliermarsh/autobot/blob/e42c66659bf97b90ca9ff305a19cc99952d0d43f/.github/workflows/ci.yaml).
|
[here](https://github.com/charliermarsh/autobot/blob/e42c66659bf97b90ca9ff305a19cc99952d0d43f/.github/workflows/ci.yaml).
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
>
|
|
||||||
> Using `latest` requires that uv download the executable on every run, which incurs a cost
|
|
||||||
> (especially on self-hosted runners). As a best practice, consider pinning the version to a
|
|
||||||
> specific release.
|
|
||||||
|
|
||||||
### Install a specific version
|
### Install a specific version
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install a specific version of uv
|
- name: Install a specific version of uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
version: "0.4.4"
|
version: "0.4.4"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Install a version by supplying a semver range
|
### Install a version by supplying a semver range
|
||||||
|
|
||||||
You can also specify a [semver range](https://github.com/npm/node-semver?tab=readme-ov-file#ranges)
|
You can specify a [semver range](https://github.com/npm/node-semver?tab=readme-ov-file#ranges)
|
||||||
to install the latest version that satisfies the range.
|
to install the latest version that satisfies the range.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install a semver range of uv
|
- name: Install a semver range of uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
version: ">=0.4.0"
|
version: ">=0.4.0"
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Pinning a minor version of uv
|
- name: Pinning a minor version of uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
version: "0.4.x"
|
version: "0.4.x"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Python version
|
||||||
|
|
||||||
|
You can use the input `python-version` to set the environment variable `UV_PYTHON` for the rest
|
||||||
|
of your workflow.
|
||||||
|
This will override any python version specifications in `pyproject.toml` and `.python-version`
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Install the latest version of uv and set the python version to 3.12
|
||||||
|
uses: astral-sh/setup-uv@v4
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can combine this with a matrix to test multiple python versions:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ["3.9", "3.10", "3.11", "3.12"]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install the latest version of uv and set the python version
|
||||||
|
uses: astral-sh/setup-uv@v4
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
- name: Test with python ${{ matrix.python-version }}
|
||||||
|
run: uv run --frozen pytest
|
||||||
|
```
|
||||||
|
|
||||||
### Validate checksum
|
### Validate checksum
|
||||||
|
|
||||||
You can also specify a checksum to validate the downloaded file. Checksums up to the default version
|
You can specify a checksum to validate the downloaded executable. Checksums up to the default version
|
||||||
are automatically verified by this action. The sha256 hashes can be found on the
|
are automatically verified by this action. The sha256 hashes can be found on the
|
||||||
[releases page](https://github.com/astral-sh/uv/releases) of the uv repo.
|
[releases page](https://github.com/astral-sh/uv/releases) of the uv repo.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install a specific version and validate the checksum
|
- name: Install a specific version and validate the checksum
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
version: "0.3.1"
|
version: "0.3.1"
|
||||||
checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
|
checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
|
||||||
@@ -89,8 +118,8 @@ are automatically verified by this action. The sha256 hashes can be found on the
|
|||||||
|
|
||||||
### Enable caching
|
### Enable caching
|
||||||
|
|
||||||
If you enable caching, the [uv cache](https://docs.astral.sh/uv/concepts/cache/) will be cached to
|
If you enable caching, the [uv cache](https://docs.astral.sh/uv/concepts/cache/) will be uploaded to
|
||||||
the GitHub Actions Cache. This can speed up runs that reuse the cache by several minutes.
|
the GitHub Actions cache. This can speed up runs that reuse the cache by several minutes.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
>
|
>
|
||||||
@@ -102,7 +131,7 @@ You can optionally define a custom cache key suffix.
|
|||||||
```yaml
|
```yaml
|
||||||
- name: Enable caching and define a custom cache key suffix
|
- name: Enable caching and define a custom cache key suffix
|
||||||
id: setup-uv
|
id: setup-uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-suffix: "optional-suffix"
|
cache-suffix: "optional-suffix"
|
||||||
@@ -119,9 +148,9 @@ use it in subsequent steps. For example, to use the cache in the above case:
|
|||||||
|
|
||||||
#### Cache dependency glob
|
#### Cache dependency glob
|
||||||
|
|
||||||
If you want to control when the cache is invalidated, specify a glob pattern with the
|
If you want to control when the GitHub Actions cache is invalidated, specify a glob pattern with the
|
||||||
`cache-dependency-glob` input. The cache will be invalidated if any file matching the glob pattern
|
`cache-dependency-glob` input. The GitHub Actions cache will be invalidated if any file matching the glob pattern
|
||||||
changes. If you use relative paths, the glob matches files relative to the repository root.
|
changes. If you use relative paths, they are relative to the repository root.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
>
|
>
|
||||||
@@ -129,7 +158,7 @@ changes. If you use relative paths, the glob matches files relative to the repos
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Define a cache dependency glob
|
- name: Define a cache dependency glob
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-dependency-glob: "**/requirements*.txt"
|
cache-dependency-glob: "**/requirements*.txt"
|
||||||
@@ -137,7 +166,7 @@ changes. If you use relative paths, the glob matches files relative to the repos
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Define a list of cache dependency globs
|
- name: Define a list of cache dependency globs
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-dependency-glob: |
|
cache-dependency-glob: |
|
||||||
@@ -147,7 +176,7 @@ changes. If you use relative paths, the glob matches files relative to the repos
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Define an absolute cache dependency glob
|
- name: Define an absolute cache dependency glob
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-dependency-glob: "/tmp/my-folder/requirements*.txt"
|
cache-dependency-glob: "/tmp/my-folder/requirements*.txt"
|
||||||
@@ -155,7 +184,7 @@ changes. If you use relative paths, the glob matches files relative to the repos
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Never invalidate the cache
|
- name: Never invalidate the cache
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
cache-dependency-glob: ""
|
cache-dependency-glob: ""
|
||||||
@@ -170,7 +199,7 @@ It defaults to `setup-uv-cache` in the `TMP` dir, `D:\a\_temp\uv-tool-dir` on Wi
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Define a custom uv cache path
|
- name: Define a custom uv cache path
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
cache-local-path: "/path/to/cache"
|
cache-local-path: "/path/to/cache"
|
||||||
```
|
```
|
||||||
@@ -181,20 +210,33 @@ By default, the uv cache is pruned after every run, removing pre-built wheels, b
|
|||||||
wheels that were built from source. On GitHub-hosted runners, it's typically faster to omit those
|
wheels that were built from source. On GitHub-hosted runners, it's typically faster to omit those
|
||||||
pre-built wheels from the cache (and instead re-download them from the registry on each run).
|
pre-built wheels from the cache (and instead re-download them from the registry on each run).
|
||||||
However, on self-hosted or local runners, preserving the cache may be more efficient. See
|
However, on self-hosted or local runners, preserving the cache may be more efficient. See
|
||||||
the[documentation](https://docs.astral.sh/uv/concepts/cache/#caching-in-continuous-integration) for
|
the [documentation](https://docs.astral.sh/uv/concepts/cache/#caching-in-continuous-integration) for
|
||||||
more.
|
more information.
|
||||||
|
|
||||||
If you want to persist the entire cache across runs, disable cache pruning with the `prune-cache`
|
If you want to persist the entire cache across runs, disable cache pruning with the `prune-cache`
|
||||||
input.
|
input.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Don't prune the cache before saving it
|
- name: Don't prune the cache before saving it
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
prune-cache: false
|
prune-cache: false
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Ignore nothing to cache
|
||||||
|
|
||||||
|
By default, the action will fail if caching is enabled but there is nothing to upload (the uv cache directory does not exist).
|
||||||
|
If you want to ignore this, set the `ignore-nothing-to-cache` input to `true`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Ignore nothing to cache
|
||||||
|
uses: astral-sh/setup-uv@v4
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
ignore-nothing-to-cache: true
|
||||||
|
```
|
||||||
|
|
||||||
### GitHub authentication token
|
### GitHub authentication token
|
||||||
|
|
||||||
This action uses the GitHub API to fetch the uv release artifacts. To avoid hitting the GitHub API
|
This action uses the GitHub API to fetch the uv release artifacts. To avoid hitting the GitHub API
|
||||||
@@ -207,7 +249,7 @@ are not sufficient, you can provide a custom GitHub token with the necessary per
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install the latest version of uv with a custom GitHub token
|
- name: Install the latest version of uv with a custom GitHub token
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
|
github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
|
||||||
```
|
```
|
||||||
@@ -225,7 +267,7 @@ input:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install the latest version of uv with a custom tool dir
|
- name: Install the latest version of uv with a custom tool dir
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
tool-dir: "/path/to/tool/dir"
|
tool-dir: "/path/to/tool/dir"
|
||||||
```
|
```
|
||||||
@@ -244,7 +286,7 @@ If you want to change this behaviour (especially on self-hosted runners) you can
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install the latest version of uv with a custom tool bin dir
|
- name: Install the latest version of uv with a custom tool bin dir
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
tool-bin-dir: "/path/to/tool-bin/dir"
|
tool-bin-dir: "/path/to/tool-bin/dir"
|
||||||
```
|
```
|
||||||
@@ -260,7 +302,7 @@ This action supports expanding the `~` character to the user's home directory fo
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Expand the tilde character
|
- name: Expand the tilde character
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
cache-local-path: "~/path/to/cache"
|
cache-local-path: "~/path/to/cache"
|
||||||
tool-dir: "~/path/to/tool/dir"
|
tool-dir: "~/path/to/tool/dir"
|
||||||
@@ -292,7 +334,7 @@ For example:
|
|||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@main
|
uses: actions/checkout@main
|
||||||
- name: Install the latest version of uv
|
- name: Install the latest version of uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
- name: Test
|
- name: Test
|
||||||
@@ -304,7 +346,7 @@ To install a specific version of Python, use
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Install the latest version of uv
|
- name: Install the latest version of uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
with:
|
with:
|
||||||
enable-cache: true
|
enable-cache: true
|
||||||
- name: Install Python 3.12
|
- name: Install Python 3.12
|
||||||
@@ -323,7 +365,7 @@ output:
|
|||||||
uses: actions/checkout@main
|
uses: actions/checkout@main
|
||||||
- name: Install the default version of uv
|
- name: Install the default version of uv
|
||||||
id: setup-uv
|
id: setup-uv
|
||||||
uses: astral-sh/setup-uv@v3
|
uses: astral-sh/setup-uv@v4
|
||||||
- name: Print the installed version
|
- name: Print the installed version
|
||||||
run: echo "Installed uv version is ${{ steps.setup-uv.outputs.uv-version }}"
|
run: echo "Installed uv version is ${{ steps.setup-uv.outputs.uv-version }}"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ inputs:
|
|||||||
version:
|
version:
|
||||||
description: "The version of uv to install"
|
description: "The version of uv to install"
|
||||||
default: "latest"
|
default: "latest"
|
||||||
|
python-version:
|
||||||
|
description: "The version of Python to set UV_PYTHON to"
|
||||||
|
required: false
|
||||||
checksum:
|
checksum:
|
||||||
description: "The checksum of the uv version to install"
|
description: "The checksum of the uv version to install"
|
||||||
required: false
|
required: false
|
||||||
@@ -31,7 +34,10 @@ inputs:
|
|||||||
default: ""
|
default: ""
|
||||||
prune-cache:
|
prune-cache:
|
||||||
description: "Prune cache before saving."
|
description: "Prune cache before saving."
|
||||||
default: true
|
default: "true"
|
||||||
|
ignore-nothing-to-cache:
|
||||||
|
description: "Ignore when nothing is found to cache."
|
||||||
|
default: "false"
|
||||||
tool-dir:
|
tool-dir:
|
||||||
description: "Custom path to set UV_TOOL_DIR to."
|
description: "Custom path to set UV_TOOL_DIR to."
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
33
dist/save-cache/index.js
generated
vendored
33
dist/save-cache/index.js
generated
vendored
@@ -82336,7 +82336,7 @@ function computeKeys(version) {
|
|||||||
core.info(`Searching files using cache dependency glob: ${inputs_1.cacheDependencyGlob.split("\n").join(",")}`);
|
core.info(`Searching files using cache dependency glob: ${inputs_1.cacheDependencyGlob.split("\n").join(",")}`);
|
||||||
cacheDependencyPathHash += yield (0, hash_files_1.hashFiles)(inputs_1.cacheDependencyGlob, true);
|
cacheDependencyPathHash += yield (0, hash_files_1.hashFiles)(inputs_1.cacheDependencyGlob, true);
|
||||||
if (cacheDependencyPathHash === "-") {
|
if (cacheDependencyPathHash === "-") {
|
||||||
throw new Error(`No file in ${process.cwd()} matched to [${inputs_1.cacheDependencyGlob.split("\n").join(",")}], make sure you have checked out the target repository`);
|
throw new Error(`No file matched to [${inputs_1.cacheDependencyGlob.split("\n").join(",")}], make sure you have checked out the target repository`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -82510,6 +82510,7 @@ exports.run = run;
|
|||||||
const cache = __importStar(__nccwpck_require__(5116));
|
const cache = __importStar(__nccwpck_require__(5116));
|
||||||
const core = __importStar(__nccwpck_require__(7484));
|
const core = __importStar(__nccwpck_require__(7484));
|
||||||
const exec = __importStar(__nccwpck_require__(5236));
|
const exec = __importStar(__nccwpck_require__(5236));
|
||||||
|
const fs = __importStar(__nccwpck_require__(3024));
|
||||||
const restore_cache_1 = __nccwpck_require__(5391);
|
const restore_cache_1 = __nccwpck_require__(5391);
|
||||||
const inputs_1 = __nccwpck_require__(9612);
|
const inputs_1 = __nccwpck_require__(9612);
|
||||||
function run() {
|
function run() {
|
||||||
@@ -82517,13 +82518,18 @@ function run() {
|
|||||||
try {
|
try {
|
||||||
if (inputs_1.enableCache) {
|
if (inputs_1.enableCache) {
|
||||||
yield saveCache();
|
yield saveCache();
|
||||||
|
// node will stay alive if any promises are not resolved,
|
||||||
|
// which is a possibility if HTTP requests are dangling
|
||||||
|
// due to retries or timeouts. We know that if we got here
|
||||||
|
// that all promises that we care about have successfully
|
||||||
|
// resolved, so simply exit with success.
|
||||||
|
process.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
const err = error;
|
const err = error;
|
||||||
core.setFailed(err.message);
|
core.setFailed(err.message);
|
||||||
}
|
}
|
||||||
process.exit(0);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function saveCache() {
|
function saveCache() {
|
||||||
@@ -82542,8 +82548,23 @@ function saveCache() {
|
|||||||
yield pruneCache();
|
yield pruneCache();
|
||||||
}
|
}
|
||||||
core.info(`Saving cache path: ${inputs_1.cacheLocalPath}`);
|
core.info(`Saving cache path: ${inputs_1.cacheLocalPath}`);
|
||||||
yield cache.saveCache([inputs_1.cacheLocalPath], cacheKey);
|
if (!fs.existsSync(inputs_1.cacheLocalPath) && !inputs_1.ignoreNothingToCache) {
|
||||||
core.info(`cache saved with the key: ${cacheKey}`);
|
throw new Error(`Cache path ${inputs_1.cacheLocalPath} does not exist on disk. This likely indicates that there are no dependencies to cache. Consider disabling the cache input if it is not needed.`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
yield cache.saveCache([inputs_1.cacheLocalPath], cacheKey);
|
||||||
|
core.info(`cache saved with the key: ${cacheKey}`);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (e instanceof Error &&
|
||||||
|
e.message ===
|
||||||
|
"Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.") {
|
||||||
|
core.info("No cacheable paths were found. Ignoring because ignore-nothing-to-save is enabled.");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function pruneCache() {
|
function pruneCache() {
|
||||||
@@ -82593,16 +82614,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
exports.githubToken = exports.toolDir = exports.toolBinDir = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.version = void 0;
|
exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.pythonVersion = exports.version = void 0;
|
||||||
const core = __importStar(__nccwpck_require__(7484));
|
const core = __importStar(__nccwpck_require__(7484));
|
||||||
const node_path_1 = __importDefault(__nccwpck_require__(6760));
|
const node_path_1 = __importDefault(__nccwpck_require__(6760));
|
||||||
exports.version = core.getInput("version");
|
exports.version = core.getInput("version");
|
||||||
|
exports.pythonVersion = core.getInput("python-version");
|
||||||
exports.checkSum = core.getInput("checksum");
|
exports.checkSum = core.getInput("checksum");
|
||||||
exports.enableCache = core.getInput("enable-cache") === "true";
|
exports.enableCache = core.getInput("enable-cache") === "true";
|
||||||
exports.cacheSuffix = core.getInput("cache-suffix") || "";
|
exports.cacheSuffix = core.getInput("cache-suffix") || "";
|
||||||
exports.cacheLocalPath = getCacheLocalPath();
|
exports.cacheLocalPath = getCacheLocalPath();
|
||||||
exports.cacheDependencyGlob = core.getInput("cache-dependency-glob");
|
exports.cacheDependencyGlob = core.getInput("cache-dependency-glob");
|
||||||
exports.pruneCache = core.getInput("prune-cache") === "true";
|
exports.pruneCache = core.getInput("prune-cache") === "true";
|
||||||
|
exports.ignoreNothingToCache = core.getInput("ignore-nothing-to-cache") === "true";
|
||||||
exports.toolBinDir = getToolBinDir();
|
exports.toolBinDir = getToolBinDir();
|
||||||
exports.toolDir = getToolDir();
|
exports.toolDir = getToolDir();
|
||||||
exports.githubToken = core.getInput("github-token");
|
exports.githubToken = core.getInput("github-token");
|
||||||
|
|||||||
314
dist/setup/index.js
generated
vendored
314
dist/setup/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
2141
dist/update-known-checksums/index.js
generated
vendored
2141
dist/update-known-checksums/index.js
generated
vendored
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
|||||||
"package": "ncc build -o dist/setup src/setup-uv.ts && ncc build -o dist/save-cache src/save-cache.ts && ncc build -o dist/update-known-checksums src/update-known-checksums.ts",
|
"package": "ncc build -o dist/setup src/setup-uv.ts && ncc build -o dist/save-cache src/save-cache.ts && ncc build -o dist/update-known-checksums src/update-known-checksums.ts",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
"act": "act pull_request -W .github/workflows/test.yml --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(gh auth token)\"",
|
"act": "act pull_request -W .github/workflows/test.yml --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(gh auth token)\"",
|
||||||
"update-known-checksums": "node dist/update-known-checksums/index.js src/download/checksum/known-checksums.ts \"$(gh auth token)\"",
|
"update-known-checksums": "RUNNER_TEMP=known_checksums node dist/update-known-checksums/index.js src/download/checksum/known-checksums.ts \"$(gh auth token)\"",
|
||||||
"all": "npm run build && npm run format && npm run lint && npm run package && npm test"
|
"all": "npm run build && npm run format && npm run lint && npm run package && npm test"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
2
src/cache/restore-cache.ts
vendored
2
src/cache/restore-cache.ts
vendored
@@ -42,7 +42,7 @@ async function computeKeys(version: string): Promise<string> {
|
|||||||
cacheDependencyPathHash += await hashFiles(cacheDependencyGlob, true);
|
cacheDependencyPathHash += await hashFiles(cacheDependencyGlob, true);
|
||||||
if (cacheDependencyPathHash === "-") {
|
if (cacheDependencyPathHash === "-") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`No file in ${process.cwd()} matched to [${cacheDependencyGlob.split("\n").join(",")}], make sure you have checked out the target repository`,
|
`No file matched to [${cacheDependencyGlob.split("\n").join(",")}], make sure you have checked out the target repository`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
|||||||
import { promises as fs } from "node:fs";
|
import { promises as fs } from "node:fs";
|
||||||
import * as tc from "@actions/tool-cache";
|
import * as tc from "@actions/tool-cache";
|
||||||
|
import { KNOWN_CHECKSUMS } from "./known-checksums";
|
||||||
export async function updateChecksums(
|
export async function updateChecksums(
|
||||||
filePath: string,
|
filePath: string,
|
||||||
downloadUrls: string[],
|
downloadUrls: string[],
|
||||||
@@ -7,31 +8,50 @@ export async function updateChecksums(
|
|||||||
await fs.rm(filePath);
|
await fs.rm(filePath);
|
||||||
await fs.appendFile(
|
await fs.appendFile(
|
||||||
filePath,
|
filePath,
|
||||||
"// AUTOGENERATED_DO_NOT_EDIT\nexport const KNOWN_CHECKSUMS: {[key: string]: string} = {\n",
|
"// AUTOGENERATED_DO_NOT_EDIT\nexport const KNOWN_CHECKSUMS: { [key: string]: string } = {\n",
|
||||||
);
|
);
|
||||||
let firstLine = true;
|
let firstLine = true;
|
||||||
for (const downloadUrl of downloadUrls) {
|
for (const downloadUrl of downloadUrls) {
|
||||||
const content = await downloadAssetContent(downloadUrl);
|
|
||||||
const checksum = content.split(" ")[0].trim();
|
|
||||||
const key = getKey(downloadUrl);
|
const key = getKey(downloadUrl);
|
||||||
|
if (key === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const checksum = await getOrDownloadChecksum(key, downloadUrl);
|
||||||
if (!firstLine) {
|
if (!firstLine) {
|
||||||
await fs.appendFile(filePath, ",\n");
|
await fs.appendFile(filePath, ",\n");
|
||||||
}
|
}
|
||||||
await fs.appendFile(filePath, ` '${key}':\n '${checksum}'`);
|
await fs.appendFile(filePath, ` "${key}":\n "${checksum}"`);
|
||||||
firstLine = false;
|
firstLine = false;
|
||||||
}
|
}
|
||||||
await fs.appendFile(filePath, "}\n");
|
await fs.appendFile(filePath, ",\n};\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getKey(downloadUrl: string): string {
|
function getKey(downloadUrl: string): string | undefined {
|
||||||
// https://github.com/astral-sh/uv/releases/download/0.3.2/uv-aarch64-apple-darwin.tar.gz.sha256
|
// https://github.com/astral-sh/uv/releases/download/0.3.2/uv-aarch64-apple-darwin.tar.gz.sha256
|
||||||
const parts = downloadUrl.split("/");
|
const parts = downloadUrl.split("/");
|
||||||
const fileName = parts[parts.length - 1];
|
const fileName = parts[parts.length - 1];
|
||||||
|
if (fileName.startsWith("source")) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
const name = fileName.split(".")[0].split("uv-")[1];
|
const name = fileName.split(".")[0].split("uv-")[1];
|
||||||
const version = parts[parts.length - 2];
|
const version = parts[parts.length - 2];
|
||||||
return `${name}-${version}`;
|
return `${name}-${version}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getOrDownloadChecksum(
|
||||||
|
key: string,
|
||||||
|
downloadUrl: string,
|
||||||
|
): Promise<string> {
|
||||||
|
let checksum = "";
|
||||||
|
if (key in KNOWN_CHECKSUMS) {
|
||||||
|
checksum = KNOWN_CHECKSUMS[key];
|
||||||
|
} else {
|
||||||
|
const content = await downloadAssetContent(downloadUrl);
|
||||||
|
checksum = content.split(" ")[0].trim();
|
||||||
|
}
|
||||||
|
return checksum;
|
||||||
|
}
|
||||||
|
|
||||||
async function downloadAssetContent(downloadUrl: string): Promise<string> {
|
async function downloadAssetContent(downloadUrl: string): Promise<string> {
|
||||||
const downloadPath = await tc.downloadTool(downloadUrl);
|
const downloadPath = await tc.downloadTool(downloadUrl);
|
||||||
const content = await fs.readFile(downloadPath, "utf8");
|
const content = await fs.readFile(downloadPath, "utf8");
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
import * as core from "@actions/core";
|
|
||||||
import * as tc from "@actions/tool-cache";
|
|
||||||
import * as exec from "@actions/exec";
|
|
||||||
import * as path from "node:path";
|
|
||||||
import { promises as fs } from "node:fs";
|
|
||||||
import type { Architecture, Platform } from "../utils/platforms";
|
|
||||||
import { validateChecksum } from "./checksum/checksum";
|
|
||||||
import { OWNER, REPO, TOOL_CACHE_NAME } from "../utils/constants";
|
|
||||||
|
|
||||||
export async function downloadLatest(
|
|
||||||
platform: Platform,
|
|
||||||
arch: Architecture,
|
|
||||||
checkSum: string | undefined,
|
|
||||||
githubToken: string | undefined,
|
|
||||||
): Promise<{ cachedToolDir: string; version: string }> {
|
|
||||||
const artifact = `uv-${arch}-${platform}`;
|
|
||||||
let extension = ".tar.gz";
|
|
||||||
if (platform === "pc-windows-msvc") {
|
|
||||||
extension = ".zip";
|
|
||||||
}
|
|
||||||
const downloadUrl = `https://github.com/${OWNER}/${REPO}/releases/latest/download/${artifact}${extension}`;
|
|
||||||
core.info(`Downloading uv from "${downloadUrl}" ...`);
|
|
||||||
|
|
||||||
const downloadPath = await tc.downloadTool(
|
|
||||||
downloadUrl,
|
|
||||||
undefined,
|
|
||||||
githubToken,
|
|
||||||
);
|
|
||||||
let uvExecutablePath: string;
|
|
||||||
let uvDir: string;
|
|
||||||
if (platform === "pc-windows-msvc") {
|
|
||||||
const fullPathWithExtension = `${downloadPath}${extension}`;
|
|
||||||
await fs.copyFile(downloadPath, fullPathWithExtension);
|
|
||||||
uvDir = await tc.extractZip(fullPathWithExtension);
|
|
||||||
// On windows extracting the zip does not create an intermediate directory
|
|
||||||
uvExecutablePath = path.join(uvDir, "uv.exe");
|
|
||||||
} else {
|
|
||||||
const extractedDir = await tc.extractTar(downloadPath);
|
|
||||||
uvDir = path.join(extractedDir, artifact);
|
|
||||||
uvExecutablePath = path.join(uvDir, "uv");
|
|
||||||
}
|
|
||||||
const version = await getVersion(uvExecutablePath);
|
|
||||||
await validateChecksum(checkSum, downloadPath, arch, platform, version);
|
|
||||||
const cachedToolDir = await tc.cacheDir(
|
|
||||||
uvDir,
|
|
||||||
TOOL_CACHE_NAME,
|
|
||||||
version,
|
|
||||||
arch,
|
|
||||||
);
|
|
||||||
|
|
||||||
return { cachedToolDir, version };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getVersion(uvExecutablePath: string): Promise<string> {
|
|
||||||
// Parse the output of `uv --version` to get the version
|
|
||||||
// The output looks like
|
|
||||||
// uv 0.3.1 (be17d132a 2024-08-21)
|
|
||||||
|
|
||||||
const options: exec.ExecOptions = {
|
|
||||||
silent: !core.isDebug(),
|
|
||||||
};
|
|
||||||
const execArgs = ["--version"];
|
|
||||||
|
|
||||||
let output = "";
|
|
||||||
options.listeners = {
|
|
||||||
stdout: (data: Buffer) => {
|
|
||||||
output += data.toString();
|
|
||||||
},
|
|
||||||
};
|
|
||||||
await exec.exec(uvExecutablePath, execArgs, options);
|
|
||||||
const parts = output.split(" ");
|
|
||||||
return parts[1].trim();
|
|
||||||
}
|
|
||||||
@@ -70,10 +70,14 @@ export async function downloadVersion(
|
|||||||
return { version: resolvedVersion, cachedToolDir };
|
return { version: resolvedVersion, cachedToolDir };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function resolveVersion(
|
export async function resolveVersion(
|
||||||
version: string,
|
versionInput: string,
|
||||||
githubToken: string,
|
githubToken: string,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
const version =
|
||||||
|
versionInput === "latest"
|
||||||
|
? await getLatestVersion(githubToken)
|
||||||
|
: versionInput;
|
||||||
if (tc.isExplicitVersion(version)) {
|
if (tc.isExplicitVersion(version)) {
|
||||||
core.debug(`Version ${version} is an explicit version.`);
|
core.debug(`Version ${version} is an explicit version.`);
|
||||||
return version;
|
return version;
|
||||||
@@ -95,3 +99,17 @@ async function getAvailableVersions(githubToken: string): Promise<string[]> {
|
|||||||
});
|
});
|
||||||
return response.map((release) => release.tag_name);
|
return response.map((release) => release.tag_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getLatestVersion(githubToken: string) {
|
||||||
|
const octokit = github.getOctokit(githubToken);
|
||||||
|
|
||||||
|
const { data: latestRelease } = await octokit.rest.repos.getLatestRelease({
|
||||||
|
owner: OWNER,
|
||||||
|
repo: REPO,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!latestRelease) {
|
||||||
|
throw new Error("Could not determine latest release.");
|
||||||
|
}
|
||||||
|
return latestRelease.tag_name;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import * as cache from "@actions/cache";
|
import * as cache from "@actions/cache";
|
||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as exec from "@actions/exec";
|
import * as exec from "@actions/exec";
|
||||||
|
import * as fs from "node:fs";
|
||||||
import {
|
import {
|
||||||
STATE_CACHE_MATCHED_KEY,
|
STATE_CACHE_MATCHED_KEY,
|
||||||
STATE_CACHE_KEY,
|
STATE_CACHE_KEY,
|
||||||
@@ -8,6 +9,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
cacheLocalPath,
|
cacheLocalPath,
|
||||||
enableCache,
|
enableCache,
|
||||||
|
ignoreNothingToCache,
|
||||||
pruneCache as shouldPruneCache,
|
pruneCache as shouldPruneCache,
|
||||||
} from "./utils/inputs";
|
} from "./utils/inputs";
|
||||||
|
|
||||||
@@ -15,12 +17,17 @@ export async function run(): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
if (enableCache) {
|
if (enableCache) {
|
||||||
await saveCache();
|
await saveCache();
|
||||||
|
// node will stay alive if any promises are not resolved,
|
||||||
|
// which is a possibility if HTTP requests are dangling
|
||||||
|
// due to retries or timeouts. We know that if we got here
|
||||||
|
// that all promises that we care about have successfully
|
||||||
|
// resolved, so simply exit with success.
|
||||||
|
process.exit(0);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const err = error as Error;
|
const err = error as Error;
|
||||||
core.setFailed(err.message);
|
core.setFailed(err.message);
|
||||||
}
|
}
|
||||||
process.exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveCache(): Promise<void> {
|
async function saveCache(): Promise<void> {
|
||||||
@@ -41,9 +48,27 @@ async function saveCache(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
core.info(`Saving cache path: ${cacheLocalPath}`);
|
core.info(`Saving cache path: ${cacheLocalPath}`);
|
||||||
await cache.saveCache([cacheLocalPath], cacheKey);
|
if (!fs.existsSync(cacheLocalPath) && !ignoreNothingToCache) {
|
||||||
|
throw new Error(
|
||||||
core.info(`cache saved with the key: ${cacheKey}`);
|
`Cache path ${cacheLocalPath} does not exist on disk. This likely indicates that there are no dependencies to cache. Consider disabling the cache input if it is not needed.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await cache.saveCache([cacheLocalPath], cacheKey);
|
||||||
|
core.info(`cache saved with the key: ${cacheKey}`);
|
||||||
|
} catch (e) {
|
||||||
|
if (
|
||||||
|
e instanceof Error &&
|
||||||
|
e.message ===
|
||||||
|
"Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved."
|
||||||
|
) {
|
||||||
|
core.info(
|
||||||
|
"No cacheable paths were found. Ignoring because ignore-nothing-to-save is enabled.",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pruneCache(): Promise<void> {
|
async function pruneCache(): Promise<void> {
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import * as path from "node:path";
|
|||||||
import {
|
import {
|
||||||
downloadVersion,
|
downloadVersion,
|
||||||
tryGetFromToolCache,
|
tryGetFromToolCache,
|
||||||
|
resolveVersion,
|
||||||
} from "./download/download-version";
|
} from "./download/download-version";
|
||||||
import { restoreCache } from "./cache/restore-cache";
|
import { restoreCache } from "./cache/restore-cache";
|
||||||
|
|
||||||
import { downloadLatest } from "./download/download-latest";
|
|
||||||
import {
|
import {
|
||||||
type Architecture,
|
type Architecture,
|
||||||
getArch,
|
getArch,
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
checkSum,
|
checkSum,
|
||||||
enableCache,
|
enableCache,
|
||||||
githubToken,
|
githubToken,
|
||||||
|
pythonVersion,
|
||||||
toolBinDir,
|
toolBinDir,
|
||||||
toolDir,
|
toolDir,
|
||||||
version,
|
version,
|
||||||
@@ -45,12 +46,13 @@ async function run(): Promise<void> {
|
|||||||
addUvToPath(setupResult.uvDir);
|
addUvToPath(setupResult.uvDir);
|
||||||
addToolBinToPath();
|
addToolBinToPath();
|
||||||
setToolDir();
|
setToolDir();
|
||||||
core.setOutput("uv-version", setupResult.version);
|
setupPython();
|
||||||
core.info(`Successfully installed uv version ${setupResult.version}`);
|
|
||||||
|
|
||||||
addMatchers();
|
addMatchers();
|
||||||
setCacheDir(cacheLocalPath);
|
setCacheDir(cacheLocalPath);
|
||||||
|
|
||||||
|
core.setOutput("uv-version", setupResult.version);
|
||||||
|
core.info(`Successfully installed uv version ${setupResult.version}`);
|
||||||
|
|
||||||
if (enableCache) {
|
if (enableCache) {
|
||||||
await restoreCache(setupResult.version);
|
await restoreCache(setupResult.version);
|
||||||
}
|
}
|
||||||
@@ -67,38 +69,28 @@ async function setupUv(
|
|||||||
checkSum: string | undefined,
|
checkSum: string | undefined,
|
||||||
githubToken: string,
|
githubToken: string,
|
||||||
): Promise<{ uvDir: string; version: string }> {
|
): Promise<{ uvDir: string; version: string }> {
|
||||||
let installedPath: string | undefined;
|
const resolvedVersion = await resolveVersion(versionInput, githubToken);
|
||||||
let cachedToolDir: string;
|
const toolCacheResult = tryGetFromToolCache(arch, resolvedVersion);
|
||||||
let version: string;
|
if (toolCacheResult.installedPath) {
|
||||||
if (versionInput === "latest") {
|
core.info(`Found uv in tool-cache for ${toolCacheResult.version}`);
|
||||||
const latestResult = await downloadLatest(
|
return {
|
||||||
platform,
|
uvDir: toolCacheResult.installedPath,
|
||||||
arch,
|
version: toolCacheResult.version,
|
||||||
checkSum,
|
};
|
||||||
githubToken,
|
|
||||||
);
|
|
||||||
version = latestResult.version;
|
|
||||||
cachedToolDir = latestResult.cachedToolDir;
|
|
||||||
} else {
|
|
||||||
const toolCacheResult = tryGetFromToolCache(arch, versionInput);
|
|
||||||
version = toolCacheResult.version;
|
|
||||||
installedPath = toolCacheResult.installedPath;
|
|
||||||
if (installedPath) {
|
|
||||||
core.info(`Found uv in tool-cache for ${versionInput}`);
|
|
||||||
return { uvDir: installedPath, version };
|
|
||||||
}
|
|
||||||
const versionResult = await downloadVersion(
|
|
||||||
platform,
|
|
||||||
arch,
|
|
||||||
versionInput,
|
|
||||||
checkSum,
|
|
||||||
githubToken,
|
|
||||||
);
|
|
||||||
cachedToolDir = versionResult.cachedToolDir;
|
|
||||||
version = versionResult.version;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { uvDir: cachedToolDir, version };
|
const downloadVersionResult = await downloadVersion(
|
||||||
|
platform,
|
||||||
|
arch,
|
||||||
|
resolvedVersion,
|
||||||
|
checkSum,
|
||||||
|
githubToken,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
uvDir: downloadVersionResult.cachedToolDir,
|
||||||
|
version: downloadVersionResult.version,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addUvToPath(cachedPath: string): void {
|
function addUvToPath(cachedPath: string): void {
|
||||||
@@ -133,6 +125,13 @@ function setToolDir(): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupPython(): void {
|
||||||
|
if (pythonVersion !== "") {
|
||||||
|
core.exportVariable("UV_PYTHON", pythonVersion);
|
||||||
|
core.info(`Set UV_PYTHON to ${pythonVersion}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setCacheDir(cacheLocalPath: string): void {
|
function setCacheDir(cacheLocalPath: string): void {
|
||||||
core.exportVariable("UV_CACHE_DIR", cacheLocalPath);
|
core.exportVariable("UV_CACHE_DIR", cacheLocalPath);
|
||||||
core.info(`Set UV_CACHE_DIR to ${cacheLocalPath}`);
|
core.info(`Set UV_CACHE_DIR to ${cacheLocalPath}`);
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ import * as core from "@actions/core";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|
||||||
export const version = core.getInput("version");
|
export const version = core.getInput("version");
|
||||||
|
export const pythonVersion = core.getInput("python-version");
|
||||||
export const checkSum = core.getInput("checksum");
|
export const checkSum = core.getInput("checksum");
|
||||||
export const enableCache = core.getInput("enable-cache") === "true";
|
export const enableCache = core.getInput("enable-cache") === "true";
|
||||||
export const cacheSuffix = core.getInput("cache-suffix") || "";
|
export const cacheSuffix = core.getInput("cache-suffix") || "";
|
||||||
export const cacheLocalPath = getCacheLocalPath();
|
export const cacheLocalPath = getCacheLocalPath();
|
||||||
export const cacheDependencyGlob = core.getInput("cache-dependency-glob");
|
export const cacheDependencyGlob = core.getInput("cache-dependency-glob");
|
||||||
export const pruneCache = core.getInput("prune-cache") === "true";
|
export const pruneCache = core.getInput("prune-cache") === "true";
|
||||||
|
export const ignoreNothingToCache =
|
||||||
|
core.getInput("ignore-nothing-to-cache") === "true";
|
||||||
export const toolBinDir = getToolBinDir();
|
export const toolBinDir = getToolBinDir();
|
||||||
export const toolDir = getToolDir();
|
export const toolDir = getToolDir();
|
||||||
export const githubToken = core.getInput("github-token");
|
export const githubToken = core.getInput("github-token");
|
||||||
|
|||||||
Reference in New Issue
Block a user