Compare commits

..

1 Commits

Author SHA1 Message Date
Kevin Stillhammer
01149c4575 Speed up version client by partial response reads 2026-03-14 18:00:39 +01:00
56 changed files with 10995 additions and 13435 deletions

View File

@@ -26,7 +26,6 @@ Use this skill when the user wants to:
- Inspect `package.json` before editing. - Inspect `package.json` before editing.
- Run `npm ci --ignore-scripts` before applying updates. - Run `npm ci --ignore-scripts` before applying updates.
- Use `npm install ... --ignore-scripts` for direct dependency changes so `package-lock.json` stays in sync. - Use `npm install ... --ignore-scripts` for direct dependency changes so `package-lock.json` stays in sync.
- When updating `@biomejs/biome`, also update the Biome schema URL version in `biome.json` to match the installed Biome version.
7. Run `npm run all`. 7. Run `npm run all`.
8. If requested, commit the changed source, lockfile, and generated artifacts, then push and open a PR. 8. If requested, commit the changed source, lockfile, and generated artifacts, then push and open a PR.

View File

@@ -1,9 +0,0 @@
{
"compilerOptions": {
"module": "nodenext",
"moduleResolution": "nodenext",
"target": "es2022",
"types": ["node"]
},
"include": ["check-all-tests-passed-needs.ts"]
}

View File

@@ -47,7 +47,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 uses: github/codeql-action/init@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
source-root: src source-root: src
@@ -59,7 +59,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 uses: github/codeql-action/autobuild@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -73,4 +73,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 uses: github/codeql-action/analyze@45cbd0c69e560cd9e7cd7f8c32362050c9b7ded2 # v4.32.2

View File

@@ -19,8 +19,6 @@ jobs:
pull-requests: read pull-requests: read
steps: steps:
- name: 🚀 Run Release Drafter - name: 🚀 Run Release Drafter
uses: release-drafter/release-drafter@693d20e7c1ce1a81d3a41962f85914253b518449 # v7.3.1 uses: release-drafter/release-drafter@6db134d15f3909ccc9eefd369f02bd1e9cffdf97 # v6.2.0
with:
commitish: ${{ github.sha }}
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,113 +0,0 @@
name: Release
on:
workflow_dispatch:
inputs:
version:
description: "Release version (e.g., 8.1.0)"
required: true
type: string
permissions: {}
jobs:
validate-release:
name: Validate release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Validate version and draft release
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
TAG: v${{ inputs.version }}
run: |
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
echo "::error::Version must match MAJOR.MINOR.PATCH (e.g., 8.1.0)"
exit 1
fi
RELEASE_JSON=$(gh release view "$TAG" --json isDraft,targetCommitish 2>&1) || {
echo "::error::No release found for $TAG"
exit 1
}
IS_DRAFT=$(echo "$RELEASE_JSON" | jq -r '.isDraft')
TARGET=$(echo "$RELEASE_JSON" | jq -r '.targetCommitish')
if [[ "$IS_DRAFT" != "true" ]]; then
echo "::error::Release $TAG already exists and is not a draft"
exit 1
fi
if [[ "$TARGET" != "$GITHUB_SHA" ]]; then
echo "::error::Draft release target ($TARGET) does not match current commit ($GITHUB_SHA)"
exit 1
fi
release-gate:
# N.B. This name should not change, it is used for downstream checks.
name: release-gate
needs:
- validate-release
runs-on: ubuntu-latest
environment:
name: release-gate
steps:
- run: echo "Release approved"
create-deployment:
name: create-deployment
needs:
- validate-release
- release-gate
runs-on: ubuntu-latest
environment:
name: release
steps:
- run: echo "Release deployment created"
release:
name: Release
needs:
- validate-release
- release-gate
- create-deployment
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Publish release
env:
GH_REPO: ${{ github.repository }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ inputs.version }}
TAG: v${{ inputs.version }}
run: |
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
echo "::error::Version must match MAJOR.MINOR.PATCH (e.g., 8.1.0)"
exit 1
fi
RELEASE_JSON=$(gh release view "$TAG" --json isDraft,targetCommitish 2>&1) || {
echo "::error::No release found for $TAG"
exit 1
}
IS_DRAFT=$(echo "$RELEASE_JSON" | jq -r '.isDraft')
TARGET=$(echo "$RELEASE_JSON" | jq -r '.targetCommitish')
if [[ "$IS_DRAFT" != "true" ]]; then
echo "::error::Release $TAG already exists and is not a draft"
exit 1
fi
if [[ "$TARGET" != "$GITHUB_SHA" ]]; then
echo "::error::Draft release target ($TARGET) does not match current commit ($GITHUB_SHA)"
exit 1
fi
echo "Publishing draft release $TAG"
gh release edit "$TAG" --draft=false

View File

@@ -25,10 +25,10 @@ jobs:
with: with:
persist-credentials: false persist-credentials: false
- name: Actionlint - name: Actionlint
uses: eifinger/actionlint-action@1fc89649be682d16ec5cf65ea16e269eb88d3982 # v1.10.2 uses: eifinger/actionlint-action@7802e0cc3ab3f81cbffb36fb0bf1a3621d994b89 # v1.10.1
- name: Run zizmor - name: Run zizmor
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: npm cache: npm
@@ -38,7 +38,7 @@ jobs:
npm run all npm run all
- name: Check all jobs are in all-tests-passed.needs - name: Check all jobs are in all-tests-passed.needs
run: | run: |
tsc -p tsconfig.json tsc --module nodenext --moduleResolution nodenext --target es2022 check-all-tests-passed-needs.ts
node check-all-tests-passed-needs.js node check-all-tests-passed-needs.js
working-directory: .github/scripts working-directory: .github/scripts
- name: Make sure no changes from linters are detected - name: Make sure no changes from linters are detected
@@ -164,22 +164,10 @@ jobs:
- name: Latest version gets installed - name: Latest version gets installed
run: | run: |
LATEST_VERSION=$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/astral-sh/uv/releases/latest | jq -r '.tag_name') LATEST_VERSION=$(gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/astral-sh/uv/releases/latest | jq -r '.tag_name')
UV_VERSION_OUTPUT=$(uv --version)
if [[ ! "$UV_VERSION_OUTPUT" =~ ^uv[[:space:]]+([^[:space:]]+) ]]; then
echo "Could not parse uv version from: $UV_VERSION_OUTPUT"
exit 1
fi
UV_VERSION="${BASH_REMATCH[1]}"
echo "Latest version is $LATEST_VERSION" echo "Latest version is $LATEST_VERSION"
echo "uv --version output is $UV_VERSION_OUTPUT" if [ "$(uv --version)" != "uv $LATEST_VERSION" ]; then
echo "Parsed uv version is $UV_VERSION" echo "Wrong uv version: $(uv --version)"
exit 1
if [ "$UV_VERSION" != "$LATEST_VERSION" ]; then
echo "Wrong uv version: $UV_VERSION_OUTPUT"
exit 1
fi fi
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
@@ -430,49 +418,6 @@ jobs:
PY PY
shell: bash shell: bash
test-activate-environment-no-project:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Create incompatible pyproject.toml
run: |
cat > pyproject.toml <<'EOF'
[project]
name = "test-no-project"
version = "0.1.0"
[dependency-groups]
dev = [
"-e file:///${PROJECT_ROOT}/projects/pkg",
]
EOF
shell: bash
- name: Install latest version with no-project
id: setup-uv
uses: ./
with:
python-version: 3.13.1t
activate-environment: true
no-project: true
- name: Verify packages can be installed
run: uv pip install pip
shell: bash
- name: Verify output venv is set
run: |
if [ -z "$UV_VENV" ]; then
echo "output venv is not set"
exit 1
fi
if [ ! -d "$UV_VENV" ]; then
echo "output venv not point to a directory: $UV_VENV"
exit 1
fi
shell: bash
env:
UV_VENV: ${{ steps.setup-uv.outputs.venv }}
test-debian-unstable: test-debian-unstable:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: debian:unstable container: debian:unstable
@@ -851,30 +796,16 @@ jobs:
- name: Install from custom manifest file - name: Install from custom manifest file
uses: ./ uses: ./
with: with:
manifest-file: "https://raw.githubusercontent.com/astral-sh/setup-uv/${{ github.ref }}/__tests__/download/custom-manifest.ndjson" manifest-file: "https://raw.githubusercontent.com/astral-sh/setup-uv/${{ github.ref }}/__tests__/download/custom-manifest.json"
- run: uv sync - run: uv sync
working-directory: __tests__/fixtures/uv-project working-directory: __tests__/fixtures/uv-project
- name: Correct version gets installed - name: Correct version gets installed
run: | run: |
if [ "$(uv --version)" != "uv 0.9.26" ]; then if [ "$(uv --version)" != "uv 0.7.12-alpha.1" ]; then
echo "Wrong uv version: $(uv --version)" echo "Wrong uv version: $(uv --version)"
exit 1 exit 1
fi fi
test-download-from-astral-mirror-false:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install with download-from-astral-mirror disabled
id: setup-uv
uses: ./
with:
download-from-astral-mirror: false
- name: Verify uv is installed
run: uv --version
test-absolute-path: test-absolute-path:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@@ -1114,7 +1045,6 @@ jobs:
- test-python-version - test-python-version
- test-activate-environment - test-activate-environment
- test-activate-environment-custom-path - test-activate-environment-custom-path
- test-activate-environment-no-project
- test-debian-unstable - test-debian-unstable
- test-musl - test-musl
- test-cache-key-os-version - test-cache-key-os-version
@@ -1133,7 +1063,6 @@ jobs:
- test-restore-cache-restore-cache-false - test-restore-cache-restore-cache-false
- test-no-python-version - test-no-python-version
- test-custom-manifest-file - test-custom-manifest-file
- test-download-from-astral-mirror-false
- test-absolute-path - test-absolute-path
- test-relative-path - test-relative-path
- test-cache-prune-force - test-cache-prune-force

View File

@@ -1,69 +0,0 @@
name: "Update docs"
on:
push:
tags:
- "v*.*.*"
permissions: {}
jobs:
update-docs:
runs-on: ubuntu-24.04-arm
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: true
- name: Get tag info
id: tag-info
run: |
TAG_NAME="${GITHUB_REF#refs/tags/}"
COMMIT_SHA=$(git rev-list -n 1 "$TAG_NAME")
echo "tag=$TAG_NAME" >> "$GITHUB_OUTPUT"
echo "sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT"
- name: Update references in docs
run: |
OLD_REF=$(grep -oh 'astral-sh/setup-uv@[a-f0-9]\{40\} # v[0-9][^ ]*' README.md docs/*.md | head -1)
OLD_SHA=$(echo "$OLD_REF" | sed 's/astral-sh\/setup-uv@\([a-f0-9]*\) # .*/\1/')
OLD_VERSION=$(echo "$OLD_REF" | sed 's/astral-sh\/setup-uv@[a-f0-9]* # \(v[^ ]*\)/\1/')
echo "Replacing $OLD_SHA # $OLD_VERSION with $NEW_SHA # $NEW_VERSION"
find README.md docs/ -type f \( -name "*.md" \) -exec \
sed -i "s|$OLD_SHA # $OLD_VERSION|$NEW_SHA # $NEW_VERSION|g" {} +
env:
NEW_SHA: ${{ steps.tag-info.outputs.sha }}
NEW_VERSION: ${{ steps.tag-info.outputs.tag }}
- name: Check for changes
id: changes-exist
run: |
if [ -n "$(git status --porcelain)" ]; then
echo "changes-exist=true" >> "$GITHUB_OUTPUT"
else
echo "changes-exist=false" >> "$GITHUB_OUTPUT"
fi
- name: Commit and push changes
if: ${{ steps.changes-exist.outputs.changes-exist == 'true' }}
id: commit-and-push
continue-on-error: true
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
git add .
git commit -m "docs: update version references to $NEW_VERSION"
git push origin HEAD:refs/heads/main
env:
NEW_VERSION: ${{ steps.tag-info.outputs.tag }}
- name: Create Pull Request
if: ${{ steps.changes-exist.outputs.changes-exist == 'true' && steps.commit-and-push.outcome != 'success' }}
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
commit-message: "docs: update version references to ${{ steps.tag-info.outputs.tag }}"
title: "docs: update version references to ${{ steps.tag-info.outputs.tag }}"
body: |
Update `uses: astral-sh/setup-uv@...` references in documentation to
`${{ steps.tag-info.outputs.sha }} # ${{ steps.tag-info.outputs.tag }}`.
base: main
labels: "automated-pr,update-docs"
branch: update-docs-${{ steps.tag-info.outputs.tag }}
delete-branch: true

View File

@@ -18,7 +18,7 @@ jobs:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: true persist-credentials: true
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with: with:
node-version-file: .nvmrc node-version-file: .nvmrc
cache: npm cache: npm
@@ -54,7 +54,7 @@ jobs:
- name: Create Pull Request - name: Create Pull Request
if: ${{ steps.changes-exist.outputs.changes-exist == 'true' && steps.commit-and-push.outcome != 'success' }} if: ${{ steps.changes-exist.outputs.changes-exist == 'true' && steps.commit-and-push.outcome != 'success' }}
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with: with:
commit-message: "chore: update known checksums" commit-message: "chore: update known checksums"
title: title:

View File

@@ -0,0 +1,51 @@
---
name: Update Major Minor Tags
on:
push:
branches-ignore:
- "**"
tags:
- "v*.*.*"
permissions: {}
jobs:
update_major_minor_tags:
name: Make sure major and minor tags are up to date on a patch release
runs-on: ubuntu-24.04-arm
permissions:
contents: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: true # needed for git push below
- name: Update Major Minor Tags
run: |
set -x
cd "${GITHUB_WORKSPACE}" || exit
# Set up variables.
TAG="${GITHUB_REF#refs/tags/}" # v1.2.3
MINOR="${TAG%.*}" # v1.2
MAJOR="${MINOR%.*}" # v1
if [ "${GITHUB_REF}" = "${TAG}" ]; then
echo "This workflow is not triggered by tag push: GITHUB_REF=${GITHUB_REF}"
exit 1
fi
MESSAGE="Release ${TAG}"
# Set up Git.
git config user.name "${GITHUB_ACTOR}"
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
# Update MAJOR/MINOR tag
git tag -fa "${MAJOR}" -m "${MESSAGE}"
git tag -fa "${MINOR}" -m "${MESSAGE}"
# Push
git push --force origin "${MINOR}"
git push --force origin "${MAJOR}"

View File

@@ -7,7 +7,7 @@ This repository is a TypeScript-based GitHub Action for installing `uv` in GitHu
1. `npm ci --ignore-scripts` 1. `npm ci --ignore-scripts`
2. `npm run all` 2. `npm run all`
- `npm run check` uses Biome (not ESLint/Prettier) and rewrites files in place. - `npm run check` uses Biome (not ESLint/Prettier) and rewrites files in place.
- User-facing changes are usually multi-file changes. If you add or change inputs, outputs, or behavior, update `action.yml`, `action-types.yml`, the implementation in `src/`, tests in `__tests__/`, relevant docs/README, and then re-package. - User-facing changes are usually multi-file changes. If you add or change inputs, outputs, or behavior, update `action.yml`, the implementation in `src/`, tests in `__tests__/`, relevant docs/README, and then re-package.
- The easiest areas to regress are version resolution and caching. When touching them, add or update tests for precedence, cache invalidation, and cross-platform path behavior. - The easiest areas to regress are version resolution and caching. When touching them, add or update tests for precedence, cache invalidation, and cross-platform path behavior.
- Workflow edits have extra CI-only checks (`actionlint` and `zizmor`); `npm run all` does not cover them. - Workflow edits have extra CI-only checks (`actionlint` and `zizmor`); `npm run all` does not cover them.
- Source is authored with bundler-friendly TypeScript, but published action artifacts in `dist/` are bundled as CommonJS for maximum GitHub Actions runtime compatibility with `@actions/*` dependencies. - Source is authored with bundler-friendly TypeScript, but published action artifacts in `dist/` are bundled as CommonJS for maximum GitHub Actions runtime compatibility with `@actions/*` dependencies.

View File

@@ -26,7 +26,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
``` ```
If you do not specify a version, this action will look for a [required-version](https://docs.astral.sh/uv/reference/settings/#required-version) If you do not specify a version, this action will look for a [required-version](https://docs.astral.sh/uv/reference/settings/#required-version)
@@ -42,7 +42,7 @@ Have a look under [Advanced Configuration](#advanced-configuration) for detailed
```yaml ```yaml
- name: Install uv with all available options - name: Install uv with all available options
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
# The version of uv to install (default: searches for version in config files, then latest) # The version of uv to install (default: searches for version in config files, then latest)
version: "" version: ""
@@ -62,9 +62,6 @@ Have a look under [Advanced Configuration](#advanced-configuration) for detailed
# Custom path for the virtual environment when using activate-environment (default: .venv in the working directory) # Custom path for the virtual environment when using activate-environment (default: .venv in the working directory)
venv-path: "" venv-path: ""
# Pass --no-project when creating the venv with activate-environment.
no-project: "false"
# The directory to execute all commands in and look for files such as pyproject.toml # The directory to execute all commands in and look for files such as pyproject.toml
working-directory: "" working-directory: ""
@@ -117,17 +114,11 @@ Have a look under [Advanced Configuration](#advanced-configuration) for detailed
# Custom path to set UV_TOOL_BIN_DIR to # Custom path to set UV_TOOL_BIN_DIR to
tool-bin-dir: "" tool-bin-dir: ""
# URL to a custom manifest file in the astral-sh/versions format # URL to a custom manifest file (NDJSON preferred, legacy JSON array is deprecated)
manifest-file: "" manifest-file: ""
# Download uv from the Astral mirror instead of directly from GitHub Releases
download-from-astral-mirror: "true"
# Add problem matchers # Add problem matchers
add-problem-matchers: "true" add-problem-matchers: "true"
# Suppress info-level log output. Only warnings and errors are shown
quiet: "false"
``` ```
### Outputs ### Outputs
@@ -148,7 +139,7 @@ This will override any python version specifications in `pyproject.toml` and `.p
```yaml ```yaml
- name: Install the latest version of uv and set the python version to 3.13t - name: Install the latest version of uv and set the python version to 3.13t
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
python-version: 3.13t python-version: 3.13t
- run: uv pip install --python=3.13t pip - run: uv pip install --python=3.13t pip
@@ -166,7 +157,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v5
- name: Install the latest version of uv and set the python version - name: Install the latest version of uv and set the python version
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Test with python ${{ matrix.python-version }} - name: Test with python ${{ matrix.python-version }}
@@ -183,7 +174,7 @@ It also controls where [the venv gets created](#activate-environment), unless `v
```yaml ```yaml
- name: Install uv based on the config files in the working-directory - name: Install uv based on the config files in the working-directory
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
working-directory: my/subproject/dir working-directory: my/subproject/dir
``` ```
@@ -199,8 +190,8 @@ For more advanced configuration options, see our detailed documentation:
## How it works ## How it works
By default, this action resolves uv versions from the By default, this action resolves uv versions from
[`astral-sh/versions`](https://github.com/astral-sh/versions) manifest and downloads uv from the [`astral-sh/versions`](https://github.com/astral-sh/versions) (NDJSON) and downloads uv from the
official [GitHub Releases](https://github.com/astral-sh/uv). official [GitHub Releases](https://github.com/astral-sh/uv).
It then uses the [GitHub Actions Toolkit](https://github.com/actions/toolkit) to cache uv as a It then uses the [GitHub Actions Toolkit](https://github.com/actions/toolkit) to cache uv as a
@@ -225,7 +216,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
- name: Test - name: Test
@@ -237,7 +228,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
- name: Install Python 3.12 - name: Install Python 3.12
@@ -256,7 +247,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
- 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 }}"
``` ```

View File

@@ -0,0 +1,9 @@
[
{
"arch": "x86_64",
"artifactName": "uv-x86_64-unknown-linux-gnu.tar.gz",
"downloadUrl": "https://release.pyx.dev/0.7.12-alpha.1/uv-x86_64-unknown-linux-gnu.tar.gz",
"platform": "unknown-linux-gnu",
"version": "0.7.12-alpha.1"
}
]

View File

@@ -1 +0,0 @@
{"version":"0.9.26","artifacts":[{"platform":"x86_64-unknown-linux-gnu","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz","archive_format":"tar.gz","sha256":"30ccbf0a66dc8727a02b0e245c583ee970bdafecf3a443c1686e1b30ec4939e8"}]}

View File

@@ -32,16 +32,32 @@ jest.unstable_mockModule("@actions/tool-cache", () => ({
})); }));
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests. // biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetLatestVersion = jest.fn<any>(); const mockGetLatestVersionFromNdjson = jest.fn<any>();
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests. // biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetAllVersions = jest.fn<any>(); const mockGetAllVersionsFromNdjson = jest.fn<any>();
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests. // biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetArtifact = jest.fn<any>(); const mockGetArtifactFromNdjson = jest.fn<any>();
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetHighestSatisfyingVersionFromNdjson = jest.fn<any>();
jest.unstable_mockModule("../../src/download/manifest", () => ({ jest.unstable_mockModule("../../src/download/versions-client", () => ({
getAllVersions: mockGetAllVersions, getAllVersions: mockGetAllVersionsFromNdjson,
getArtifact: mockGetArtifact, getArtifact: mockGetArtifactFromNdjson,
getLatestVersion: mockGetLatestVersion, getHighestSatisfyingVersion: mockGetHighestSatisfyingVersionFromNdjson,
getLatestVersion: mockGetLatestVersionFromNdjson,
}));
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetAllManifestVersions = jest.fn<any>();
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetLatestVersionInManifest = jest.fn<any>();
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockGetManifestArtifact = jest.fn<any>();
jest.unstable_mockModule("../../src/download/version-manifest", () => ({
getAllVersions: mockGetAllManifestVersions,
getLatestKnownVersion: mockGetLatestVersionInManifest,
getManifestArtifact: mockGetManifestArtifact,
})); }));
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests. // biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
@@ -51,9 +67,11 @@ jest.unstable_mockModule("../../src/download/checksum/checksum", () => ({
validateChecksum: mockValidateChecksum, validateChecksum: mockValidateChecksum,
})); }));
const { downloadVersion, resolveVersion, rewriteToMirror } = await import( const {
"../../src/download/download-version" downloadVersionFromManifest,
); downloadVersionFromNdjson,
resolveVersion,
} = await import("../../src/download/download-version");
describe("download-version", () => { describe("download-version", () => {
beforeEach(() => { beforeEach(() => {
@@ -63,9 +81,13 @@ describe("download-version", () => {
mockExtractTar.mockReset(); mockExtractTar.mockReset();
mockExtractZip.mockReset(); mockExtractZip.mockReset();
mockCacheDir.mockReset(); mockCacheDir.mockReset();
mockGetLatestVersion.mockReset(); mockGetLatestVersionFromNdjson.mockReset();
mockGetAllVersions.mockReset(); mockGetAllVersionsFromNdjson.mockReset();
mockGetArtifact.mockReset(); mockGetArtifactFromNdjson.mockReset();
mockGetHighestSatisfyingVersionFromNdjson.mockReset();
mockGetAllManifestVersions.mockReset();
mockGetLatestVersionInManifest.mockReset();
mockGetManifestArtifact.mockReset();
mockValidateChecksum.mockReset(); mockValidateChecksum.mockReset();
mockDownloadTool.mockResolvedValue("/tmp/downloaded"); mockDownloadTool.mockResolvedValue("/tmp/downloaded");
@@ -75,57 +97,49 @@ describe("download-version", () => {
}); });
describe("resolveVersion", () => { describe("resolveVersion", () => {
it("uses the default manifest to resolve latest", async () => { it("uses astral-sh/versions to resolve latest", async () => {
mockGetLatestVersion.mockResolvedValue("0.9.26"); mockGetLatestVersionFromNdjson.mockResolvedValue("0.9.26");
const version = await resolveVersion("latest", undefined); const version = await resolveVersion("latest", undefined);
expect(version).toBe("0.9.26"); expect(version).toBe("0.9.26");
expect(mockGetLatestVersion).toHaveBeenCalledTimes(1); expect(mockGetLatestVersionFromNdjson).toHaveBeenCalledTimes(1);
expect(mockGetLatestVersion).toHaveBeenCalledWith(undefined);
}); });
it("uses the default manifest to resolve available versions", async () => { it("streams astral-sh/versions to resolve the highest matching version", async () => {
mockGetAllVersions.mockResolvedValue(["0.9.26", "0.9.25"]); mockGetHighestSatisfyingVersionFromNdjson.mockResolvedValue("0.9.26");
const version = await resolveVersion("^0.9.0", undefined); const version = await resolveVersion("^0.9.0", undefined);
expect(version).toBe("0.9.26"); expect(version).toBe("0.9.26");
expect(mockGetAllVersions).toHaveBeenCalledTimes(1); expect(mockGetHighestSatisfyingVersionFromNdjson).toHaveBeenCalledWith(
expect(mockGetAllVersions).toHaveBeenCalledWith(undefined); "^0.9.0",
);
expect(mockGetAllVersionsFromNdjson).not.toHaveBeenCalled();
}); });
it("treats == exact pins as explicit versions", async () => { it("still loads all versions when resolving the lowest matching version", async () => {
const version = await resolveVersion("==0.9.26", undefined); mockGetAllVersionsFromNdjson.mockResolvedValue(["0.9.26", "0.9.25"]);
expect(version).toBe("0.9.26");
expect(mockGetAllVersions).not.toHaveBeenCalled();
expect(mockGetLatestVersion).not.toHaveBeenCalled();
});
it("uses latest for minimum-only ranges when using the highest strategy", async () => {
mockGetLatestVersion.mockResolvedValue("0.9.26");
const version = await resolveVersion(">=0.9.0", undefined, "highest");
expect(version).toBe("0.9.26");
expect(mockGetLatestVersion).toHaveBeenCalledTimes(1);
expect(mockGetLatestVersion).toHaveBeenCalledWith(undefined);
expect(mockGetAllVersions).not.toHaveBeenCalled();
});
it("uses the lowest compatible version when requested", async () => {
mockGetAllVersions.mockResolvedValue(["0.9.26", "0.9.25"]);
const version = await resolveVersion("^0.9.0", undefined, "lowest"); const version = await resolveVersion("^0.9.0", undefined, "lowest");
expect(version).toBe("0.9.25"); expect(version).toBe("0.9.25");
expect(mockGetAllVersions).toHaveBeenCalledTimes(1); expect(mockGetAllVersionsFromNdjson).toHaveBeenCalledTimes(1);
expect(mockGetAllVersions).toHaveBeenCalledWith(undefined); expect(mockGetHighestSatisfyingVersionFromNdjson).not.toHaveBeenCalled();
});
it("does not fall back when astral-sh/versions fails", async () => {
mockGetLatestVersionFromNdjson.mockRejectedValue(
new Error("NDJSON unavailable"),
);
await expect(resolveVersion("latest", undefined)).rejects.toThrow(
"NDJSON unavailable",
);
}); });
it("uses manifest-file when provided", async () => { it("uses manifest-file when provided", async () => {
mockGetAllVersions.mockResolvedValue(["0.9.26", "0.9.25"]); mockGetAllManifestVersions.mockResolvedValue(["0.9.26", "0.9.25"]);
const version = await resolveVersion( const version = await resolveVersion(
"^0.9.0", "^0.9.0",
@@ -133,35 +147,37 @@ describe("download-version", () => {
); );
expect(version).toBe("0.9.26"); expect(version).toBe("0.9.26");
expect(mockGetAllVersions).toHaveBeenCalledWith( expect(mockGetAllManifestVersions).toHaveBeenCalledWith(
"https://example.com/custom.ndjson", "https://example.com/custom.ndjson",
); );
}); });
}); });
describe("downloadVersion", () => { describe("downloadVersionFromNdjson", () => {
it("fails when manifest lookup fails", async () => { it("fails when NDJSON metadata lookup fails", async () => {
mockGetArtifact.mockRejectedValue(new Error("manifest unavailable")); mockGetArtifactFromNdjson.mockRejectedValue(
new Error("NDJSON unavailable"),
);
await expect( await expect(
downloadVersion( downloadVersionFromNdjson(
"unknown-linux-gnu", "unknown-linux-gnu",
"x86_64", "x86_64",
"0.9.26", "0.9.26",
undefined, undefined,
"token", "token",
), ),
).rejects.toThrow("manifest unavailable"); ).rejects.toThrow("NDJSON unavailable");
expect(mockDownloadTool).not.toHaveBeenCalled(); expect(mockDownloadTool).not.toHaveBeenCalled();
expect(mockValidateChecksum).not.toHaveBeenCalled(); expect(mockValidateChecksum).not.toHaveBeenCalled();
}); });
it("fails when no matching artifact exists in the default manifest", async () => { it("fails when no matching artifact exists in NDJSON metadata", async () => {
mockGetArtifact.mockResolvedValue(undefined); mockGetArtifactFromNdjson.mockResolvedValue(undefined);
await expect( await expect(
downloadVersion( downloadVersionFromNdjson(
"unknown-linux-gnu", "unknown-linux-gnu",
"x86_64", "x86_64",
"0.9.26", "0.9.26",
@@ -176,14 +192,14 @@ describe("download-version", () => {
expect(mockValidateChecksum).not.toHaveBeenCalled(); expect(mockValidateChecksum).not.toHaveBeenCalled();
}); });
it("uses built-in checksums for default manifest downloads", async () => { it("uses built-in checksums for default NDJSON downloads", async () => {
mockGetArtifact.mockResolvedValue({ mockGetArtifactFromNdjson.mockResolvedValue({
archiveFormat: "tar.gz", archiveFormat: "tar.gz",
checksum: "manifest-checksum-that-should-be-ignored", sha256: "ndjson-checksum-that-should-be-ignored",
downloadUrl: "https://example.com/uv.tar.gz", url: "https://example.com/uv.tar.gz",
}); });
await downloadVersion( await downloadVersionFromNdjson(
"unknown-linux-gnu", "unknown-linux-gnu",
"x86_64", "x86_64",
"0.9.26", "0.9.26",
@@ -199,148 +215,23 @@ describe("download-version", () => {
"0.9.26", "0.9.26",
); );
}); });
});
it("rewrites GitHub Releases URLs to the Astral mirror", async () => { describe("downloadVersionFromManifest", () => {
mockGetArtifact.mockResolvedValue({
archiveFormat: "tar.gz",
checksum: "abc123",
downloadUrl:
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
});
await downloadVersion(
"unknown-linux-gnu",
"x86_64",
"0.9.26",
undefined,
"token",
);
expect(mockDownloadTool).toHaveBeenCalledWith(
"https://releases.astral.sh/github/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
undefined,
undefined,
);
});
it("does not send the token to non-GitHub URLs from the default manifest", async () => {
mockGetArtifact.mockResolvedValue({
archiveFormat: "tar.gz",
checksum: "abc123",
downloadUrl: "https://example.com/uv.tar.gz",
});
await downloadVersion(
"unknown-linux-gnu",
"x86_64",
"0.9.26",
undefined,
"token",
);
expect(mockDownloadTool).toHaveBeenCalledWith(
"https://example.com/uv.tar.gz",
undefined,
undefined,
);
});
it("does not send the token to GitHub lookalike hosts", async () => {
mockGetArtifact.mockResolvedValue({
archiveFormat: "tar.gz",
checksum: "abc123",
downloadUrl: "https://github.com.evil.test/uv.tar.gz",
});
await downloadVersion(
"unknown-linux-gnu",
"x86_64",
"0.9.26",
undefined,
"token",
);
expect(mockDownloadTool).toHaveBeenCalledWith(
"https://github.com.evil.test/uv.tar.gz",
undefined,
undefined,
);
});
it("falls back to GitHub Releases when the mirror fails", async () => {
mockGetArtifact.mockResolvedValue({
archiveFormat: "tar.gz",
checksum: "abc123",
downloadUrl:
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
});
mockDownloadTool
.mockRejectedValueOnce(new Error("mirror unavailable"))
.mockResolvedValueOnce("/tmp/downloaded");
await downloadVersion(
"unknown-linux-gnu",
"x86_64",
"0.9.26",
undefined,
"token",
);
expect(mockDownloadTool).toHaveBeenCalledTimes(2);
expect(mockDownloadTool).toHaveBeenNthCalledWith(
1,
"https://releases.astral.sh/github/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
undefined,
undefined,
);
expect(mockDownloadTool).toHaveBeenNthCalledWith(
2,
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
undefined,
"token",
);
expect(mockWarning).toHaveBeenCalledWith(
"Failed to download from mirror, falling back to GitHub Releases: mirror unavailable",
);
});
it("does not fall back for non-GitHub URLs", async () => {
mockGetArtifact.mockResolvedValue({
archiveFormat: "tar.gz",
checksum: "abc123",
downloadUrl: "https://example.com/uv.tar.gz",
});
mockDownloadTool.mockRejectedValue(new Error("download failed"));
await expect(
downloadVersion(
"unknown-linux-gnu",
"x86_64",
"0.9.26",
undefined,
"token",
),
).rejects.toThrow("download failed");
expect(mockDownloadTool).toHaveBeenCalledTimes(1);
});
it("uses manifest-file checksum metadata when checksum input is unset", async () => { it("uses manifest-file checksum metadata when checksum input is unset", async () => {
mockGetArtifact.mockResolvedValue({ mockGetManifestArtifact.mockResolvedValue({
archiveFormat: "tar.gz", archiveFormat: "tar.gz",
checksum: "manifest-checksum", checksum: "manifest-checksum",
downloadUrl: "https://example.com/custom-uv.tar.gz", downloadUrl: "https://example.com/custom-uv.tar.gz",
}); });
await downloadVersion( await downloadVersionFromManifest(
"https://example.com/custom.ndjson",
"unknown-linux-gnu", "unknown-linux-gnu",
"x86_64", "x86_64",
"0.9.26", "0.9.26",
"", "",
"token", "token",
"https://example.com/custom.ndjson",
); );
expect(mockValidateChecksum).toHaveBeenCalledWith( expect(mockValidateChecksum).toHaveBeenCalledWith(
@@ -353,19 +244,19 @@ describe("download-version", () => {
}); });
it("prefers checksum input over manifest-file checksum metadata", async () => { it("prefers checksum input over manifest-file checksum metadata", async () => {
mockGetArtifact.mockResolvedValue({ mockGetManifestArtifact.mockResolvedValue({
archiveFormat: "tar.gz", archiveFormat: "tar.gz",
checksum: "manifest-checksum", checksum: "manifest-checksum",
downloadUrl: "https://example.com/custom-uv.tar.gz", downloadUrl: "https://example.com/custom-uv.tar.gz",
}); });
await downloadVersion( await downloadVersionFromManifest(
"https://example.com/custom.ndjson",
"unknown-linux-gnu", "unknown-linux-gnu",
"x86_64", "x86_64",
"0.9.26", "0.9.26",
"user-checksum", "user-checksum",
"token", "token",
"https://example.com/custom.ndjson",
); );
expect(mockValidateChecksum).toHaveBeenCalledWith( expect(mockValidateChecksum).toHaveBeenCalledWith(
@@ -376,55 +267,5 @@ describe("download-version", () => {
"0.9.26", "0.9.26",
); );
}); });
it("skips the Astral mirror when downloadFromAstralMirror is false", async () => {
mockGetArtifact.mockResolvedValue({
archiveFormat: "tar.gz",
checksum: "abc123",
downloadUrl:
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
});
await downloadVersion(
"unknown-linux-gnu",
"x86_64",
"0.9.26",
undefined,
"token",
undefined,
false,
);
expect(mockDownloadTool).toHaveBeenCalledWith(
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
undefined,
"token",
);
expect(mockDownloadTool).toHaveBeenCalledTimes(1);
});
});
describe("rewriteToMirror", () => {
it("rewrites a GitHub Releases URL to the Astral mirror", () => {
expect(
rewriteToMirror(
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
),
).toBe(
"https://releases.astral.sh/github/uv/releases/download/0.9.26/uv-x86_64-unknown-linux-gnu.tar.gz",
);
});
it("returns undefined for non-GitHub URLs", () => {
expect(rewriteToMirror("https://example.com/uv.tar.gz")).toBeUndefined();
});
it("returns undefined for a different GitHub repo", () => {
expect(
rewriteToMirror(
"https://github.com/other/repo/releases/download/v1.0/file.tar.gz",
),
).toBeUndefined();
});
}); });
}); });

View File

@@ -1,180 +0,0 @@
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockFetch = jest.fn<any>();
jest.unstable_mockModule("@actions/core", () => ({
debug: jest.fn(),
info: jest.fn(),
}));
jest.unstable_mockModule("../../src/utils/fetch", () => ({
fetch: mockFetch,
}));
const {
clearManifestCache,
fetchManifest,
getAllVersions,
getArtifact,
getLatestVersion,
parseManifest,
} = await import("../../src/download/manifest");
const sampleManifestResponse = `{"version":"0.9.26","artifacts":[{"platform":"aarch64-apple-darwin","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.tar.gz","archive_format":"tar.gz","sha256":"fcf0a9ea6599c6ae28a4c854ac6da76f2c889354d7c36ce136ef071f7ab9721f"},{"platform":"x86_64-pc-windows-msvc","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-pc-windows-msvc.zip","archive_format":"zip","sha256":"eb02fd95d8e0eed462b4a67ecdd320d865b38c560bffcda9a0b87ec944bdf036"}]}
{"version":"0.9.25","artifacts":[{"platform":"aarch64-apple-darwin","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.25/uv-aarch64-apple-darwin.tar.gz","archive_format":"tar.gz","sha256":"606b3c6949d971709f2526fa0d9f0fd23ccf60e09f117999b406b424af18a6a6"}]}`;
const multiVariantManifestResponse = `{"version":"0.9.26","artifacts":[{"platform":"aarch64-apple-darwin","variant":"python-managed","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin-managed.tar.gz","archive_format":"tar.gz","sha256":"managed-checksum"},{"platform":"aarch64-apple-darwin","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.zip","archive_format":"zip","sha256":"default-checksum"}]}`;
function createMockResponse(
ok: boolean,
status: number,
statusText: string,
data: string,
) {
return {
ok,
status,
statusText,
text: async () => data,
};
}
describe("manifest", () => {
beforeEach(() => {
clearManifestCache();
mockFetch.mockReset();
});
describe("fetchManifest", () => {
it("fetches and parses manifest data", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleManifestResponse),
);
const versions = await fetchManifest();
expect(versions).toHaveLength(2);
expect(versions[0]?.version).toBe("0.9.26");
expect(versions[1]?.version).toBe("0.9.25");
});
it("throws on a failed fetch", async () => {
mockFetch.mockResolvedValue(
createMockResponse(false, 500, "Internal Server Error", ""),
);
await expect(fetchManifest()).rejects.toThrow(
"Failed to fetch manifest data: 500 Internal Server Error",
);
});
it("caches results per URL", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleManifestResponse),
);
await fetchManifest("https://example.com/custom.ndjson");
await fetchManifest("https://example.com/custom.ndjson");
expect(mockFetch).toHaveBeenCalledTimes(1);
});
});
describe("getAllVersions", () => {
it("returns all version strings", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleManifestResponse),
);
const versions = await getAllVersions(
"https://example.com/custom.ndjson",
);
expect(versions).toEqual(["0.9.26", "0.9.25"]);
});
});
describe("getLatestVersion", () => {
it("returns the first version string", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleManifestResponse),
);
await expect(
getLatestVersion("https://example.com/custom.ndjson"),
).resolves.toBe("0.9.26");
});
});
describe("getArtifact", () => {
beforeEach(() => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleManifestResponse),
);
});
it("finds an artifact by version and platform", async () => {
const artifact = await getArtifact("0.9.26", "aarch64", "apple-darwin");
expect(artifact).toEqual({
archiveFormat: "tar.gz",
checksum:
"fcf0a9ea6599c6ae28a4c854ac6da76f2c889354d7c36ce136ef071f7ab9721f",
downloadUrl:
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.tar.gz",
});
});
it("finds a windows artifact", async () => {
const artifact = await getArtifact("0.9.26", "x86_64", "pc-windows-msvc");
expect(artifact).toEqual({
archiveFormat: "zip",
checksum:
"eb02fd95d8e0eed462b4a67ecdd320d865b38c560bffcda9a0b87ec944bdf036",
downloadUrl:
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-pc-windows-msvc.zip",
});
});
it("prefers the default variant when multiple artifacts share a platform", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", multiVariantManifestResponse),
);
const artifact = await getArtifact("0.9.26", "aarch64", "apple-darwin");
expect(artifact).toEqual({
archiveFormat: "zip",
checksum: "default-checksum",
downloadUrl:
"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.zip",
});
});
it("returns undefined for an unknown version", async () => {
const artifact = await getArtifact("0.0.1", "aarch64", "apple-darwin");
expect(artifact).toBeUndefined();
});
it("returns undefined for an unknown platform", async () => {
const artifact = await getArtifact(
"0.9.26",
"aarch64",
"unknown-linux-musl",
);
expect(artifact).toBeUndefined();
});
});
describe("parseManifest", () => {
it("throws for malformed manifest data", () => {
expect(() => parseManifest('{"version":"0.1.0"', "test-source")).toThrow(
"Failed to parse manifest data from test-source",
);
});
});
});

View File

@@ -0,0 +1,136 @@
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
const mockWarning = jest.fn();
jest.unstable_mockModule("@actions/core", () => ({
debug: jest.fn(),
info: jest.fn(),
warning: mockWarning,
}));
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockFetch = jest.fn<any>();
jest.unstable_mockModule("../../src/utils/fetch", () => ({
fetch: mockFetch,
}));
const {
clearManifestCache,
getAllVersions,
getLatestKnownVersion,
getManifestArtifact,
} = await import("../../src/download/version-manifest");
const legacyManifestResponse = JSON.stringify([
{
arch: "x86_64",
artifactName: "uv-x86_64-unknown-linux-gnu.tar.gz",
downloadUrl:
"https://example.com/releases/download/0.7.12-alpha.1/uv-x86_64-unknown-linux-gnu.tar.gz",
platform: "unknown-linux-gnu",
version: "0.7.12-alpha.1",
},
{
arch: "x86_64",
artifactName: "uv-x86_64-unknown-linux-gnu.tar.gz",
downloadUrl:
"https://example.com/releases/download/0.7.13/uv-x86_64-unknown-linux-gnu.tar.gz",
platform: "unknown-linux-gnu",
version: "0.7.13",
},
]);
const ndjsonManifestResponse = `{"version":"0.10.0","artifacts":[{"platform":"x86_64-unknown-linux-gnu","variant":"default","url":"https://example.com/releases/download/0.10.0/uv-x86_64-unknown-linux-gnu.tar.gz","archive_format":"tar.gz","sha256":"checksum-100"}]}
{"version":"0.9.30","artifacts":[{"platform":"x86_64-unknown-linux-gnu","variant":"default","url":"https://example.com/releases/download/0.9.30/uv-x86_64-unknown-linux-gnu.tar.gz","archive_format":"tar.gz","sha256":"checksum-0930"}]}`;
const multiVariantManifestResponse = `{"version":"0.10.0","artifacts":[{"platform":"x86_64-unknown-linux-gnu","variant":"managed-python","url":"https://example.com/releases/download/0.10.0/uv-x86_64-unknown-linux-gnu-managed-python.tar.gz","archive_format":"tar.gz","sha256":"checksum-managed"},{"platform":"x86_64-unknown-linux-gnu","variant":"default","url":"https://example.com/releases/download/0.10.0/uv-x86_64-unknown-linux-gnu-default.zip","archive_format":"zip","sha256":"checksum-default"}]}`;
function createMockResponse(
ok: boolean,
status: number,
statusText: string,
data: string,
) {
return {
ok,
status,
statusText,
text: async () => data,
};
}
describe("version-manifest", () => {
beforeEach(() => {
clearManifestCache();
mockFetch.mockReset();
mockWarning.mockReset();
});
it("supports the legacy JSON manifest format", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", legacyManifestResponse),
);
const latest = await getLatestKnownVersion(
"https://example.com/legacy.json",
);
const artifact = await getManifestArtifact(
"https://example.com/legacy.json",
"0.7.13",
"x86_64",
"unknown-linux-gnu",
);
expect(latest).toBe("0.7.13");
expect(artifact).toEqual({
archiveFormat: undefined,
checksum: undefined,
downloadUrl:
"https://example.com/releases/download/0.7.13/uv-x86_64-unknown-linux-gnu.tar.gz",
});
expect(mockWarning).toHaveBeenCalledTimes(1);
});
it("supports NDJSON manifests", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", ndjsonManifestResponse),
);
const versions = await getAllVersions("https://example.com/custom.ndjson");
const artifact = await getManifestArtifact(
"https://example.com/custom.ndjson",
"0.10.0",
"x86_64",
"unknown-linux-gnu",
);
expect(versions).toEqual(["0.10.0", "0.9.30"]);
expect(artifact).toEqual({
archiveFormat: "tar.gz",
checksum: "checksum-100",
downloadUrl:
"https://example.com/releases/download/0.10.0/uv-x86_64-unknown-linux-gnu.tar.gz",
});
expect(mockWarning).not.toHaveBeenCalled();
});
it("prefers the default variant when a manifest contains multiple variants", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", multiVariantManifestResponse),
);
const artifact = await getManifestArtifact(
"https://example.com/multi-variant.ndjson",
"0.10.0",
"x86_64",
"unknown-linux-gnu",
);
expect(artifact).toEqual({
archiveFormat: "zip",
checksum: "checksum-default",
downloadUrl:
"https://example.com/releases/download/0.10.0/uv-x86_64-unknown-linux-gnu-default.zip",
});
});
});

View File

@@ -0,0 +1,241 @@
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
// biome-ignore lint/suspicious/noExplicitAny: Mock requires flexible typing in tests.
const mockFetch = jest.fn<any>();
jest.unstable_mockModule("../../src/utils/fetch", () => ({
fetch: mockFetch,
}));
const {
clearCache,
fetchVersionData,
getAllVersions,
getArtifact,
getHighestSatisfyingVersion,
getLatestVersion,
parseVersionData,
} = await import("../../src/download/versions-client");
const sampleNdjsonResponse = `{"version":"0.9.26","artifacts":[{"platform":"aarch64-apple-darwin","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.tar.gz","archive_format":"tar.gz","sha256":"fcf0a9ea6599c6ae28a4c854ac6da76f2c889354d7c36ce136ef071f7ab9721f"},{"platform":"x86_64-pc-windows-msvc","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-pc-windows-msvc.zip","archive_format":"zip","sha256":"eb02fd95d8e0eed462b4a67ecdd320d865b38c560bffcda9a0b87ec944bdf036"}]}
{"version":"0.9.25","artifacts":[{"platform":"aarch64-apple-darwin","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.25/uv-aarch64-apple-darwin.tar.gz","archive_format":"tar.gz","sha256":"606b3c6949d971709f2526fa0d9f0fd23ccf60e09f117999b406b424af18a6a6"}]}`;
const multiVariantNdjsonResponse = `{"version":"0.9.26","artifacts":[{"platform":"aarch64-apple-darwin","variant":"python-managed","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin-managed.tar.gz","archive_format":"tar.gz","sha256":"managed-checksum"},{"platform":"aarch64-apple-darwin","variant":"default","url":"https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.zip","archive_format":"zip","sha256":"default-checksum"}]}`;
function createMockStream(chunks: string[]): ReadableStream<Uint8Array> {
const encoder = new TextEncoder();
return new ReadableStream<Uint8Array>({
start(controller) {
for (const chunk of chunks) {
controller.enqueue(encoder.encode(chunk));
}
controller.close();
},
});
}
function createMockResponse(
ok: boolean,
status: number,
statusText: string,
data: string,
chunks: string[] = [data],
) {
return {
body: createMockStream(chunks),
ok,
status,
statusText,
text: async () => data,
};
}
describe("versions-client", () => {
beforeEach(() => {
clearCache();
mockFetch.mockReset();
});
describe("fetchVersionData", () => {
it("should fetch and parse NDJSON data", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleNdjsonResponse),
);
const versions = await fetchVersionData();
expect(versions).toHaveLength(2);
expect(versions[0].version).toBe("0.9.26");
expect(versions[1].version).toBe("0.9.25");
});
it("should throw error on failed fetch", async () => {
mockFetch.mockResolvedValue(
createMockResponse(false, 500, "Internal Server Error", ""),
);
await expect(fetchVersionData()).rejects.toThrow(
"Failed to fetch version data: 500 Internal Server Error",
);
});
it("should cache results", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleNdjsonResponse),
);
await fetchVersionData();
await fetchVersionData();
expect(mockFetch).toHaveBeenCalledTimes(1);
});
});
describe("getLatestVersion", () => {
it("should return the first version (newest)", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleNdjsonResponse),
);
const latest = await getLatestVersion();
expect(latest).toBe("0.9.26");
});
it("should stop after the first record when resolving latest", async () => {
mockFetch.mockResolvedValue(
createMockResponse(
true,
200,
"OK",
`${sampleNdjsonResponse}\n{"version":`,
[`${sampleNdjsonResponse.split("\n")[0]}\n`, '{"version":'],
),
);
const latest = await getLatestVersion();
expect(latest).toBe("0.9.26");
});
});
describe("getAllVersions", () => {
it("should return all version strings", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleNdjsonResponse),
);
const versions = await getAllVersions();
expect(versions).toEqual(["0.9.26", "0.9.25"]);
});
});
describe("getHighestSatisfyingVersion", () => {
it("should return the first matching version from the stream", async () => {
mockFetch.mockResolvedValue(
createMockResponse(
true,
200,
"OK",
`${sampleNdjsonResponse}\n{"version":`,
[`${sampleNdjsonResponse.split("\n")[0]}\n`, '{"version":'],
),
);
const version = await getHighestSatisfyingVersion("^0.9.0");
expect(version).toBe("0.9.26");
});
});
describe("getArtifact", () => {
beforeEach(() => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", sampleNdjsonResponse),
);
});
it("should find artifact by version and platform", async () => {
const artifact = await getArtifact("0.9.26", "aarch64", "apple-darwin");
expect(artifact).toEqual({
archiveFormat: "tar.gz",
sha256:
"fcf0a9ea6599c6ae28a4c854ac6da76f2c889354d7c36ce136ef071f7ab9721f",
url: "https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.tar.gz",
});
});
it("should stop once the requested version is found", async () => {
mockFetch.mockResolvedValue(
createMockResponse(
true,
200,
"OK",
`${sampleNdjsonResponse}\n{"version":`,
[`${sampleNdjsonResponse.split("\n")[0]}\n`, '{"version":'],
),
);
const artifact = await getArtifact("0.9.26", "aarch64", "apple-darwin");
expect(artifact).toEqual({
archiveFormat: "tar.gz",
sha256:
"fcf0a9ea6599c6ae28a4c854ac6da76f2c889354d7c36ce136ef071f7ab9721f",
url: "https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.tar.gz",
});
});
it("should find windows artifact", async () => {
const artifact = await getArtifact("0.9.26", "x86_64", "pc-windows-msvc");
expect(artifact).toEqual({
archiveFormat: "zip",
sha256:
"eb02fd95d8e0eed462b4a67ecdd320d865b38c560bffcda9a0b87ec944bdf036",
url: "https://github.com/astral-sh/uv/releases/download/0.9.26/uv-x86_64-pc-windows-msvc.zip",
});
});
it("should prefer the default variant when multiple artifacts share a platform", async () => {
mockFetch.mockResolvedValue(
createMockResponse(true, 200, "OK", multiVariantNdjsonResponse),
);
const artifact = await getArtifact("0.9.26", "aarch64", "apple-darwin");
expect(artifact).toEqual({
archiveFormat: "zip",
sha256: "default-checksum",
url: "https://github.com/astral-sh/uv/releases/download/0.9.26/uv-aarch64-apple-darwin.zip",
});
});
it("should return undefined for unknown version", async () => {
const artifact = await getArtifact("0.0.1", "aarch64", "apple-darwin");
expect(artifact).toBeUndefined();
});
it("should return undefined for unknown platform", async () => {
const artifact = await getArtifact(
"0.9.26",
"aarch64",
"unknown-linux-musl",
);
expect(artifact).toBeUndefined();
});
});
describe("parseVersionData", () => {
it("should throw for malformed NDJSON", () => {
expect(() =>
parseVersionData('{"version":"0.1.0"', "test-source"),
).toThrow("Failed to parse version data from test-source");
});
});
});

View File

@@ -1,6 +1,3 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { import {
afterEach, afterEach,
beforeEach, beforeEach,
@@ -10,13 +7,9 @@ import {
jest, jest,
} from "@jest/globals"; } from "@jest/globals";
// Will be mutated per test before (re-)importing the module under test
let mockInputs: Record<string, string> = {}; let mockInputs: Record<string, string> = {};
const tempDirs: string[] = [];
const ORIGINAL_HOME = process.env.HOME; const ORIGINAL_HOME = process.env.HOME;
const ORIGINAL_RUNNER_ENVIRONMENT = process.env.RUNNER_ENVIRONMENT;
const ORIGINAL_RUNNER_TEMP = process.env.RUNNER_TEMP;
const ORIGINAL_UV_CACHE_DIR = process.env.UV_CACHE_DIR;
const ORIGINAL_UV_PYTHON_INSTALL_DIR = process.env.UV_PYTHON_INSTALL_DIR;
const mockDebug = jest.fn(); const mockDebug = jest.fn();
const mockGetBooleanInput = jest.fn( const mockGetBooleanInput = jest.fn(
@@ -34,220 +27,118 @@ jest.unstable_mockModule("@actions/core", () => ({
warning: mockWarning, warning: mockWarning,
})); }));
const { CacheLocalSource, loadInputs } = await import("../../src/utils/inputs"); async function importInputsModule() {
return await import("../../src/utils/inputs");
function createTempProject(files: Record<string, string> = {}): string {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "setup-uv-inputs-test-"));
tempDirs.push(dir);
for (const [relativePath, content] of Object.entries(files)) {
const filePath = path.join(dir, relativePath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, content);
}
return dir;
} }
function resetEnvironment(): void {
jest.clearAllMocks();
mockInputs = {};
process.env.HOME = "/home/testuser";
delete process.env.RUNNER_ENVIRONMENT;
delete process.env.RUNNER_TEMP;
delete process.env.UV_CACHE_DIR;
delete process.env.UV_PYTHON_INSTALL_DIR;
}
function restoreEnvironment(): void {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { force: true, recursive: true });
}
process.env.HOME = ORIGINAL_HOME;
process.env.RUNNER_ENVIRONMENT = ORIGINAL_RUNNER_ENVIRONMENT;
process.env.RUNNER_TEMP = ORIGINAL_RUNNER_TEMP;
process.env.UV_CACHE_DIR = ORIGINAL_UV_CACHE_DIR;
process.env.UV_PYTHON_INSTALL_DIR = ORIGINAL_UV_PYTHON_INSTALL_DIR;
}
beforeEach(resetEnvironment);
afterEach(restoreEnvironment);
describe("loadInputs", () => {
it("loads defaults for a github-hosted runner", () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["enable-cache"] = "auto";
process.env.RUNNER_ENVIRONMENT = "github-hosted";
process.env.RUNNER_TEMP = "/runner-temp";
const inputs = loadInputs();
expect(inputs.enableCache).toBe(true);
expect(inputs.cacheLocalPath).toEqual({
path: "/runner-temp/setup-uv-cache",
source: CacheLocalSource.Default,
});
expect(inputs.pythonDir).toBe("/runner-temp/uv-python-dir");
expect(inputs.venvPath).toBe("/workspace/.venv");
expect(inputs.manifestFile).toBeUndefined();
expect(inputs.resolutionStrategy).toBe("highest");
});
it("uses cache-dir from pyproject.toml when present", () => {
mockInputs["working-directory"] = createTempProject({
"pyproject.toml": `[project]
name = "uv-project"
version = "0.1.0"
[tool.uv]
cache-dir = "/tmp/pyproject-toml-defined-cache-path"
`,
});
const inputs = loadInputs();
expect(inputs.cacheLocalPath).toEqual({
path: "/tmp/pyproject-toml-defined-cache-path",
source: CacheLocalSource.Config,
});
expect(mockInfo).toHaveBeenCalledWith(
expect.stringContaining("Found cache-dir in"),
);
});
it("uses UV_CACHE_DIR from the environment", () => {
mockInputs["working-directory"] = createTempProject();
process.env.UV_CACHE_DIR = "/env/cache-dir";
const inputs = loadInputs();
expect(inputs.cacheLocalPath).toEqual({
path: "/env/cache-dir",
source: CacheLocalSource.Env,
});
expect(mockInfo).toHaveBeenCalledWith(
"UV_CACHE_DIR is already set to /env/cache-dir",
);
});
it("uses UV_PYTHON_INSTALL_DIR from the environment", () => {
mockInputs["working-directory"] = "/workspace";
process.env.UV_PYTHON_INSTALL_DIR = "/env/python-dir";
const inputs = loadInputs();
expect(inputs.pythonDir).toBe("/env/python-dir");
expect(mockInfo).toHaveBeenCalledWith(
"UV_PYTHON_INSTALL_DIR is already set to /env/python-dir",
);
});
it("warns when parsing a malformed pyproject.toml for cache-dir", () => {
mockInputs["working-directory"] = createTempProject({
"pyproject.toml": `[project]
name = "malformed-pyproject-toml-project"
version = "0.1.0"
[malformed-toml
`,
});
const inputs = loadInputs();
expect(inputs.cacheLocalPath).toBeUndefined();
expect(mockWarning).toHaveBeenCalledWith(
expect.stringContaining("Error while parsing pyproject.toml:"),
);
});
it("throws for an invalid resolution strategy", () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["resolution-strategy"] = "middle";
expect(() => loadInputs()).toThrow(
"Invalid resolution-strategy: middle. Must be 'highest' or 'lowest'.",
);
});
});
describe("cacheDependencyGlob", () => { describe("cacheDependencyGlob", () => {
it("returns empty string when input not provided", () => { beforeEach(() => {
mockInputs["working-directory"] = "/workspace"; jest.resetModules();
jest.clearAllMocks();
const inputs = loadInputs(); mockInputs = {};
process.env.HOME = "/home/testuser";
expect(inputs.cacheDependencyGlob).toBe("");
}); });
it.each([ afterEach(() => {
["requirements.txt", "/workspace/requirements.txt"], process.env.HOME = ORIGINAL_HOME;
["./uv.lock", "/workspace/uv.lock"],
])("resolves %s to %s", (globInput, expected) => {
mockInputs["working-directory"] = "/workspace";
mockInputs["cache-dependency-glob"] = globInput;
const inputs = loadInputs();
expect(inputs.cacheDependencyGlob).toBe(expected);
}); });
it("handles multiple lines, trimming whitespace, tilde expansion and absolute paths", () => { it("returns empty string when input not provided", async () => {
mockInputs["working-directory"] = "/workspace";
const { cacheDependencyGlob } = await importInputsModule();
expect(cacheDependencyGlob).toBe("");
});
it("resolves a single relative path", async () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["cache-dependency-glob"] = "requirements.txt";
const { cacheDependencyGlob } = await importInputsModule();
expect(cacheDependencyGlob).toBe("/workspace/requirements.txt");
});
it("strips leading ./ from relative path", async () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["cache-dependency-glob"] = "./uv.lock";
const { cacheDependencyGlob } = await importInputsModule();
expect(cacheDependencyGlob).toBe("/workspace/uv.lock");
});
it("handles multiple lines, trimming whitespace, tilde expansion and absolute paths", async () => {
mockInputs["working-directory"] = "/workspace"; mockInputs["working-directory"] = "/workspace";
mockInputs["cache-dependency-glob"] = mockInputs["cache-dependency-glob"] =
" ~/.cache/file1\n ./rel/file2 \nfile3.txt"; " ~/.cache/file1\n ./rel/file2 \nfile3.txt";
const { cacheDependencyGlob } = await importInputsModule();
const inputs = loadInputs(); expect(cacheDependencyGlob).toBe(
expect(inputs.cacheDependencyGlob).toBe(
[ [
"/home/testuser/.cache/file1", "/home/testuser/.cache/file1", // expanded tilde, absolute path unchanged
"/workspace/rel/file2", "/workspace/rel/file2", // ./ stripped and resolved
"/workspace/file3.txt", "/workspace/file3.txt", // relative path resolved
].join("\n"), ].join("\n"),
); );
}); });
it.each([ it("keeps absolute path unchanged in multiline input", async () => {
[
"/abs/path.lock\nrelative.lock",
["/abs/path.lock", "/workspace/relative.lock"].join("\n"),
],
[
"!/abs/path.lock\n!relative.lock",
["!/abs/path.lock", "!/workspace/relative.lock"].join("\n"),
],
])("normalizes multiline glob %s", (globInput, expected) => {
mockInputs["working-directory"] = "/workspace"; mockInputs["working-directory"] = "/workspace";
mockInputs["cache-dependency-glob"] = globInput; mockInputs["cache-dependency-glob"] = "/abs/path.lock\nrelative.lock";
const { cacheDependencyGlob } = await importInputsModule();
expect(cacheDependencyGlob).toBe(
["/abs/path.lock", "/workspace/relative.lock"].join("\n"),
);
});
const inputs = loadInputs(); it("handles exclusions in relative paths correct", async () => {
mockInputs["working-directory"] = "/workspace";
expect(inputs.cacheDependencyGlob).toBe(expected); mockInputs["cache-dependency-glob"] = "!/abs/path.lock\n!relative.lock";
const { cacheDependencyGlob } = await importInputsModule();
expect(cacheDependencyGlob).toBe(
["!/abs/path.lock", "!/workspace/relative.lock"].join("\n"),
);
}); });
}); });
describe("tool directories", () => { describe("tool directories", () => {
it("expands tilde for tool-bin-dir and tool-dir", () => { beforeEach(() => {
jest.resetModules();
jest.clearAllMocks();
mockInputs = {};
process.env.HOME = "/home/testuser";
});
afterEach(() => {
process.env.HOME = ORIGINAL_HOME;
});
it("expands tilde for tool-bin-dir and tool-dir", async () => {
mockInputs["working-directory"] = "/workspace"; mockInputs["working-directory"] = "/workspace";
mockInputs["tool-bin-dir"] = "~/tool-bin-dir"; mockInputs["tool-bin-dir"] = "~/tool-bin-dir";
mockInputs["tool-dir"] = "~/tool-dir"; mockInputs["tool-dir"] = "~/tool-dir";
const inputs = loadInputs(); const { toolBinDir, toolDir } = await importInputsModule();
expect(inputs.toolBinDir).toBe("/home/testuser/tool-bin-dir"); expect(toolBinDir).toBe("/home/testuser/tool-bin-dir");
expect(inputs.toolDir).toBe("/home/testuser/tool-dir"); expect(toolDir).toBe("/home/testuser/tool-dir");
}); });
}); });
describe("cacheLocalPath", () => { describe("cacheLocalPath", () => {
it("expands tilde in cache-local-path", () => { beforeEach(() => {
jest.resetModules();
jest.clearAllMocks();
mockInputs = {};
process.env.HOME = "/home/testuser";
});
afterEach(() => {
process.env.HOME = ORIGINAL_HOME;
});
it("expands tilde in cache-local-path", async () => {
mockInputs["working-directory"] = "/workspace"; mockInputs["working-directory"] = "/workspace";
mockInputs["cache-local-path"] = "~/uv-cache/cache-local-path"; mockInputs["cache-local-path"] = "~/uv-cache/cache-local-path";
const inputs = loadInputs(); const { CacheLocalSource, cacheLocalPath } = await importInputsModule();
expect(inputs.cacheLocalPath).toEqual({ expect(cacheLocalPath).toEqual({
path: "/home/testuser/uv-cache/cache-local-path", path: "/home/testuser/uv-cache/cache-local-path",
source: CacheLocalSource.Input, source: CacheLocalSource.Input,
}); });
@@ -255,37 +146,63 @@ describe("cacheLocalPath", () => {
}); });
describe("venvPath", () => { describe("venvPath", () => {
it("defaults to .venv in the working directory", () => { beforeEach(() => {
mockInputs["working-directory"] = "/workspace"; jest.resetModules();
jest.clearAllMocks();
const inputs = loadInputs(); mockInputs = {};
process.env.HOME = "/home/testuser";
expect(inputs.venvPath).toBe("/workspace/.venv");
}); });
it.each([ afterEach(() => {
["custom-venv", "/workspace/custom-venv"], process.env.HOME = ORIGINAL_HOME;
["custom-venv/", "/workspace/custom-venv"], });
["/tmp/custom-venv", "/tmp/custom-venv"],
["~/.venv", "/home/testuser/.venv"], it("defaults to .venv in the working directory", async () => {
])("resolves venv-path %s to %s", (venvPathInput, expected) => { mockInputs["working-directory"] = "/workspace";
const { venvPath } = await importInputsModule();
expect(venvPath).toBe("/workspace/.venv");
});
it("resolves a relative venv-path", async () => {
mockInputs["working-directory"] = "/workspace"; mockInputs["working-directory"] = "/workspace";
mockInputs["activate-environment"] = "true"; mockInputs["activate-environment"] = "true";
mockInputs["venv-path"] = venvPathInput; mockInputs["venv-path"] = "custom-venv";
const { venvPath } = await importInputsModule();
const inputs = loadInputs(); expect(venvPath).toBe("/workspace/custom-venv");
expect(inputs.venvPath).toBe(expected);
}); });
it("warns when venv-path is set but activate-environment is false", () => { it("normalizes venv-path with trailing slash", async () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["activate-environment"] = "true";
mockInputs["venv-path"] = "custom-venv/";
const { venvPath } = await importInputsModule();
expect(venvPath).toBe("/workspace/custom-venv");
});
it("keeps an absolute venv-path unchanged", async () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["activate-environment"] = "true";
mockInputs["venv-path"] = "/tmp/custom-venv";
const { venvPath } = await importInputsModule();
expect(venvPath).toBe("/tmp/custom-venv");
});
it("expands tilde in venv-path", async () => {
mockInputs["working-directory"] = "/workspace";
mockInputs["activate-environment"] = "true";
mockInputs["venv-path"] = "~/.venv";
const { venvPath } = await importInputsModule();
expect(venvPath).toBe("/home/testuser/.venv");
});
it("warns when venv-path is set but activate-environment is false", async () => {
mockInputs["working-directory"] = "/workspace"; mockInputs["working-directory"] = "/workspace";
mockInputs["venv-path"] = "custom-venv"; mockInputs["venv-path"] = "custom-venv";
const inputs = loadInputs(); const { activateEnvironment, venvPath } = await importInputsModule();
expect(inputs.activateEnvironment).toBe(false); expect(activateEnvironment).toBe(false);
expect(inputs.venvPath).toBe("/workspace/custom-venv"); expect(venvPath).toBe("/workspace/custom-venv");
expect(mockWarning).toHaveBeenCalledWith( expect(mockWarning).toHaveBeenCalledWith(
"venv-path is only used when activate-environment is true", "venv-path is only used when activate-environment is true",
); );

View File

@@ -1,5 +1,5 @@
import { expect, test } from "@jest/globals"; import { expect, test } from "@jest/globals";
import { getUvVersionFromFile } from "../../src/version/file-parser"; import { getUvVersionFromFile } from "../../src/version/resolve";
test("ignores dependencies starting with uv", async () => { test("ignores dependencies starting with uv", async () => {
const parsedVersion = getUvVersionFromFile( const parsedVersion = getUvVersionFromFile(

View File

@@ -1,5 +1,5 @@
import { expect, test } from "@jest/globals"; import { expect, test } from "@jest/globals";
import { getUvVersionFromFile } from "../../src/version/file-parser"; import { getUvVersionFromFile } from "../../src/version/resolve";
test("ignores dependencies starting with uv", async () => { test("ignores dependencies starting with uv", async () => {
const parsedVersion = getUvVersionFromFile( const parsedVersion = getUvVersionFromFile(

View File

@@ -1,125 +0,0 @@
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, expect, it } from "@jest/globals";
import { resolveVersionRequest } from "../../src/version/version-request-resolver";
const tempDirs: string[] = [];
function createTempProject(files: Record<string, string> = {}): string {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "setup-uv-version-test-"));
tempDirs.push(dir);
for (const [relativePath, content] of Object.entries(files)) {
const filePath = path.join(dir, relativePath);
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, content);
}
return dir;
}
afterEach(() => {
for (const dir of tempDirs.splice(0)) {
fs.rmSync(dir, { force: true, recursive: true });
}
});
describe("resolveVersionRequest", () => {
it("prefers explicit input over version-file and workspace config", () => {
const workingDirectory = createTempProject({
".tool-versions": "uv 0.4.0\n",
"pyproject.toml": `[tool.uv]\nrequired-version = "==0.5.14"\n`,
"uv.toml": `required-version = "==0.5.15"\n`,
});
const request = resolveVersionRequest({
version: "==0.6.0",
versionFile: path.join(workingDirectory, ".tool-versions"),
workingDirectory,
});
expect(request).toEqual({
source: "input",
specifier: "0.6.0",
});
});
it("uses .tool-versions when it is passed via version-file", () => {
const workingDirectory = createTempProject({
".tool-versions": "uv 0.5.15\n",
});
const request = resolveVersionRequest({
versionFile: path.join(workingDirectory, ".tool-versions"),
workingDirectory,
});
expect(request).toEqual({
format: ".tool-versions",
source: "version-file",
sourcePath: path.join(workingDirectory, ".tool-versions"),
specifier: "0.5.15",
});
});
it("uses requirements.txt when it is passed via version-file", () => {
const workingDirectory = createTempProject({
"requirements.txt": "uv==0.6.17\nuvicorn==0.35.0\n",
});
const request = resolveVersionRequest({
versionFile: path.join(workingDirectory, "requirements.txt"),
workingDirectory,
});
expect(request).toEqual({
format: "requirements",
source: "version-file",
sourcePath: path.join(workingDirectory, "requirements.txt"),
specifier: "0.6.17",
});
});
it("prefers uv.toml over pyproject.toml during workspace discovery", () => {
const workingDirectory = createTempProject({
"pyproject.toml": `[tool.uv]\nrequired-version = "==0.5.14"\n`,
"uv.toml": `required-version = "==0.5.15"\n`,
});
const request = resolveVersionRequest({ workingDirectory });
expect(request).toEqual({
format: "uv.toml",
source: "uv.toml",
sourcePath: path.join(workingDirectory, "uv.toml"),
specifier: "0.5.15",
});
});
it("falls back to latest when no version source is found", () => {
const workingDirectory = createTempProject({});
const request = resolveVersionRequest({ workingDirectory });
expect(request).toEqual({
source: "default",
specifier: "latest",
});
});
it("throws when version-file does not resolve a version", () => {
const workingDirectory = createTempProject({
"requirements.txt": "uvicorn==0.35.0\n",
});
expect(() =>
resolveVersionRequest({
versionFile: path.join(workingDirectory, "requirements.txt"),
workingDirectory,
}),
).toThrow(
`Could not determine uv version from file: ${path.join(workingDirectory, "requirements.txt")}`,
);
});
});

View File

@@ -11,8 +11,6 @@ inputs:
type: boolean type: boolean
venv-path: venv-path:
type: string type: string
no-project:
type: boolean
working-directory: working-directory:
type: string type: string
checksum: checksum:
@@ -52,12 +50,8 @@ inputs:
type: string type: string
manifest-file: manifest-file:
type: string type: string
download-from-astral-mirror:
type: boolean
add-problem-matchers: add-problem-matchers:
type: boolean type: boolean
quiet:
type: boolean
resolution-strategy: resolution-strategy:
type: enum type: enum
allowed-values: allowed-values:

View File

@@ -18,9 +18,6 @@ inputs:
venv-path: venv-path:
description: "Custom path for the virtual environment when using activate-environment. Defaults to '.venv' in the working directory." description: "Custom path for the virtual environment when using activate-environment. Defaults to '.venv' in the working directory."
default: "" default: ""
no-project:
description: "Pass --no-project when creating the venv with activate-environment."
default: "false"
working-directory: working-directory:
description: "The directory to execute all commands in and look for files such as pyproject.toml" description: "The directory to execute all commands in and look for files such as pyproject.toml"
default: ${{ github.workspace }} default: ${{ github.workspace }}
@@ -78,17 +75,11 @@ inputs:
description: "Custom path to set UV_TOOL_BIN_DIR to." description: "Custom path to set UV_TOOL_BIN_DIR to."
required: false required: false
manifest-file: manifest-file:
description: "URL to a custom manifest file in the astral-sh/versions format." description: "URL to a custom manifest file. Supports the astral-sh/versions NDJSON format and the legacy JSON array format (deprecated)."
required: false required: false
download-from-astral-mirror:
description: "Download uv from the Astral mirror instead of directly from GitHub Releases."
default: "true"
add-problem-matchers: add-problem-matchers:
description: "Add problem matchers." description: "Add problem matchers."
default: "true" default: "true"
quiet:
description: "Suppress info-level log output. Only warnings and errors are shown."
default: "false"
resolution-strategy: resolution-strategy:
description: "Resolution strategy to use when resolving version ranges. 'highest' uses the latest compatible version, 'lowest' uses the oldest compatible version." description: "Resolution strategy to use when resolving version ranges. 'highest' uses the latest compatible version, 'lowest' uses the oldest compatible version."
default: "highest" default: "highest"

View File

@@ -1,5 +1,5 @@
{ {
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json", "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json",
"assist": { "assist": {
"actions": { "actions": {
"source": { "source": {

969
dist/save-cache/index.cjs generated vendored
View File

@@ -133,7 +133,7 @@ var require_tunnel = __commonJS({
connectOptions.headers = connectOptions.headers || {}; connectOptions.headers = connectOptions.headers || {};
connectOptions.headers["Proxy-Authorization"] = "Basic " + new Buffer(connectOptions.proxyAuth).toString("base64"); connectOptions.headers["Proxy-Authorization"] = "Basic " + new Buffer(connectOptions.proxyAuth).toString("base64");
} }
debug3("making CONNECT request"); debug2("making CONNECT request");
var connectReq = self2.request(connectOptions); var connectReq = self2.request(connectOptions);
connectReq.useChunkedEncodingByDefault = false; connectReq.useChunkedEncodingByDefault = false;
connectReq.once("response", onResponse); connectReq.once("response", onResponse);
@@ -153,7 +153,7 @@ var require_tunnel = __commonJS({
connectReq.removeAllListeners(); connectReq.removeAllListeners();
socket.removeAllListeners(); socket.removeAllListeners();
if (res.statusCode !== 200) { if (res.statusCode !== 200) {
debug3( debug2(
"tunneling socket could not be established, statusCode=%d", "tunneling socket could not be established, statusCode=%d",
res.statusCode res.statusCode
); );
@@ -165,7 +165,7 @@ var require_tunnel = __commonJS({
return; return;
} }
if (head.length > 0) { if (head.length > 0) {
debug3("got illegal response body from proxy"); debug2("got illegal response body from proxy");
socket.destroy(); socket.destroy();
var error2 = new Error("got illegal response body from proxy"); var error2 = new Error("got illegal response body from proxy");
error2.code = "ECONNRESET"; error2.code = "ECONNRESET";
@@ -173,13 +173,13 @@ var require_tunnel = __commonJS({
self2.removeSocket(placeholder); self2.removeSocket(placeholder);
return; return;
} }
debug3("tunneling connection has established"); debug2("tunneling connection has established");
self2.sockets[self2.sockets.indexOf(placeholder)] = socket; self2.sockets[self2.sockets.indexOf(placeholder)] = socket;
return cb(socket); return cb(socket);
} }
function onError(cause) { function onError(cause) {
connectReq.removeAllListeners(); connectReq.removeAllListeners();
debug3( debug2(
"tunneling socket could not be established, cause=%s\n", "tunneling socket could not be established, cause=%s\n",
cause.message, cause.message,
cause.stack cause.stack
@@ -241,9 +241,9 @@ var require_tunnel = __commonJS({
} }
return target; return target;
} }
var debug3; var debug2;
if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
debug3 = function() { debug2 = function() {
var args = Array.prototype.slice.call(arguments); var args = Array.prototype.slice.call(arguments);
if (typeof args[0] === "string") { if (typeof args[0] === "string") {
args[0] = "TUNNEL: " + args[0]; args[0] = "TUNNEL: " + args[0];
@@ -253,10 +253,10 @@ var require_tunnel = __commonJS({
console.error.apply(console, args); console.error.apply(console, args);
}; };
} else { } else {
debug3 = function() { debug2 = function() {
}; };
} }
exports2.debug = debug3; exports2.debug = debug2;
} }
}); });
@@ -1492,36 +1492,36 @@ var require_diagnostics = __commonJS({
const debuglog = fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog; const debuglog = fetchDebuglog.enabled ? fetchDebuglog : undiciDebugLog;
diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => {
const { const {
connectParams: { version: version3, protocol, port, host } connectParams: { version: version4, protocol, port, host }
} = evt; } = evt;
debuglog( debuglog(
"connecting to %s using %s%s", "connecting to %s using %s%s",
`${host}${port ? `:${port}` : ""}`, `${host}${port ? `:${port}` : ""}`,
protocol, protocol,
version3 version4
); );
}); });
diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => {
const { const {
connectParams: { version: version3, protocol, port, host } connectParams: { version: version4, protocol, port, host }
} = evt; } = evt;
debuglog( debuglog(
"connected to %s using %s%s", "connected to %s using %s%s",
`${host}${port ? `:${port}` : ""}`, `${host}${port ? `:${port}` : ""}`,
protocol, protocol,
version3 version4
); );
}); });
diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => {
const { const {
connectParams: { version: version3, protocol, port, host }, connectParams: { version: version4, protocol, port, host },
error: error2 error: error2
} = evt; } = evt;
debuglog( debuglog(
"connection to %s using %s%s errored - %s", "connection to %s using %s%s errored - %s",
`${host}${port ? `:${port}` : ""}`, `${host}${port ? `:${port}` : ""}`,
protocol, protocol,
version3, version4,
error2.message error2.message
); );
}); });
@@ -1570,31 +1570,31 @@ var require_diagnostics = __commonJS({
const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog; const debuglog = undiciDebugLog.enabled ? undiciDebugLog : websocketDebuglog;
diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => { diagnosticsChannel.channel("undici:client:beforeConnect").subscribe((evt) => {
const { const {
connectParams: { version: version3, protocol, port, host } connectParams: { version: version4, protocol, port, host }
} = evt; } = evt;
debuglog( debuglog(
"connecting to %s%s using %s%s", "connecting to %s%s using %s%s",
host, host,
port ? `:${port}` : "", port ? `:${port}` : "",
protocol, protocol,
version3 version4
); );
}); });
diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => { diagnosticsChannel.channel("undici:client:connected").subscribe((evt) => {
const { const {
connectParams: { version: version3, protocol, port, host } connectParams: { version: version4, protocol, port, host }
} = evt; } = evt;
debuglog( debuglog(
"connected to %s%s using %s%s", "connected to %s%s using %s%s",
host, host,
port ? `:${port}` : "", port ? `:${port}` : "",
protocol, protocol,
version3 version4
); );
}); });
diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => { diagnosticsChannel.channel("undici:client:connectError").subscribe((evt) => {
const { const {
connectParams: { version: version3, protocol, port, host }, connectParams: { version: version4, protocol, port, host },
error: error2 error: error2
} = evt; } = evt;
debuglog( debuglog(
@@ -1602,7 +1602,7 @@ var require_diagnostics = __commonJS({
host, host,
port ? `:${port}` : "", port ? `:${port}` : "",
protocol, protocol,
version3, version4,
error2.message error2.message
); );
}); });
@@ -18936,7 +18936,7 @@ var require_minimatch = __commonJS({
} }
this.parseNegate(); this.parseNegate();
var set = this.globSet = this.braceExpand(); var set = this.globSet = this.braceExpand();
if (options.debug) this.debug = function debug3() { if (options.debug) this.debug = function debug2() {
console.error.apply(console, arguments); console.error.apply(console, arguments);
}; };
this.debug(this.pattern, set); this.debug(this.pattern, set);
@@ -19414,9 +19414,9 @@ var require_constants6 = __commonJS({
var require_debug = __commonJS({ var require_debug = __commonJS({
"node_modules/@actions/cache/node_modules/semver/internal/debug.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/internal/debug.js"(exports2, module2) {
"use strict"; "use strict";
var debug3 = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => { var debug2 = typeof process === "object" && process.env && process.env.NODE_DEBUG && /\bsemver\b/i.test(process.env.NODE_DEBUG) ? (...args) => console.error("SEMVER", ...args) : () => {
}; };
module2.exports = debug3; module2.exports = debug2;
} }
}); });
@@ -19429,7 +19429,7 @@ var require_re = __commonJS({
MAX_SAFE_BUILD_LENGTH, MAX_SAFE_BUILD_LENGTH,
MAX_LENGTH MAX_LENGTH
} = require_constants6(); } = require_constants6();
var debug3 = require_debug(); var debug2 = require_debug();
exports2 = module2.exports = {}; exports2 = module2.exports = {};
var re = exports2.re = []; var re = exports2.re = [];
var safeRe = exports2.safeRe = []; var safeRe = exports2.safeRe = [];
@@ -19452,7 +19452,7 @@ var require_re = __commonJS({
var createToken = (name, value, isGlobal) => { var createToken = (name, value, isGlobal) => {
const safe = makeSafeRegex(value); const safe = makeSafeRegex(value);
const index = R++; const index = R++;
debug3(name, index, value); debug2(name, index, value);
t[name] = index; t[name] = index;
src[index] = value; src[index] = value;
safeSrc[index] = safe; safeSrc[index] = safe;
@@ -19556,37 +19556,37 @@ var require_identifiers = __commonJS({
var require_semver = __commonJS({ var require_semver = __commonJS({
"node_modules/@actions/cache/node_modules/semver/classes/semver.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/classes/semver.js"(exports2, module2) {
"use strict"; "use strict";
var debug3 = require_debug(); var debug2 = require_debug();
var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants6(); var { MAX_LENGTH, MAX_SAFE_INTEGER } = require_constants6();
var { safeRe: re, t } = require_re(); var { safeRe: re, t } = require_re();
var parseOptions = require_parse_options(); var parseOptions = require_parse_options();
var { compareIdentifiers } = require_identifiers(); var { compareIdentifiers } = require_identifiers();
var SemVer = class _SemVer { var SemVer = class _SemVer {
constructor(version3, options) { constructor(version4, options) {
options = parseOptions(options); options = parseOptions(options);
if (version3 instanceof _SemVer) { if (version4 instanceof _SemVer) {
if (version3.loose === !!options.loose && version3.includePrerelease === !!options.includePrerelease) { if (version4.loose === !!options.loose && version4.includePrerelease === !!options.includePrerelease) {
return version3; return version4;
} else { } else {
version3 = version3.version; version4 = version4.version;
} }
} else if (typeof version3 !== "string") { } else if (typeof version4 !== "string") {
throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version3}".`); throw new TypeError(`Invalid version. Must be a string. Got type "${typeof version4}".`);
} }
if (version3.length > MAX_LENGTH) { if (version4.length > MAX_LENGTH) {
throw new TypeError( throw new TypeError(
`version is longer than ${MAX_LENGTH} characters` `version is longer than ${MAX_LENGTH} characters`
); );
} }
debug3("SemVer", version3, options); debug2("SemVer", version4, options);
this.options = options; this.options = options;
this.loose = !!options.loose; this.loose = !!options.loose;
this.includePrerelease = !!options.includePrerelease; this.includePrerelease = !!options.includePrerelease;
const m = version3.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]); const m = version4.trim().match(options.loose ? re[t.LOOSE] : re[t.FULL]);
if (!m) { if (!m) {
throw new TypeError(`Invalid Version: ${version3}`); throw new TypeError(`Invalid Version: ${version4}`);
} }
this.raw = version3; this.raw = version4;
this.major = +m[1]; this.major = +m[1];
this.minor = +m[2]; this.minor = +m[2];
this.patch = +m[3]; this.patch = +m[3];
@@ -19626,7 +19626,7 @@ var require_semver = __commonJS({
return this.version; return this.version;
} }
compare(other) { compare(other) {
debug3("SemVer.compare", this.version, this.options, other); debug2("SemVer.compare", this.version, this.options, other);
if (!(other instanceof _SemVer)) { if (!(other instanceof _SemVer)) {
if (typeof other === "string" && other === this.version) { if (typeof other === "string" && other === this.version) {
return 0; return 0;
@@ -19677,7 +19677,7 @@ var require_semver = __commonJS({
do { do {
const a = this.prerelease[i]; const a = this.prerelease[i];
const b = other.prerelease[i]; const b = other.prerelease[i];
debug3("prerelease compare", i, a, b); debug2("prerelease compare", i, a, b);
if (a === void 0 && b === void 0) { if (a === void 0 && b === void 0) {
return 0; return 0;
} else if (b === void 0) { } else if (b === void 0) {
@@ -19699,7 +19699,7 @@ var require_semver = __commonJS({
do { do {
const a = this.build[i]; const a = this.build[i];
const b = other.build[i]; const b = other.build[i];
debug3("build compare", i, a, b); debug2("build compare", i, a, b);
if (a === void 0 && b === void 0) { if (a === void 0 && b === void 0) {
return 0; return 0;
} else if (b === void 0) { } else if (b === void 0) {
@@ -19836,12 +19836,12 @@ var require_parse2 = __commonJS({
"node_modules/@actions/cache/node_modules/semver/functions/parse.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/functions/parse.js"(exports2, module2) {
"use strict"; "use strict";
var SemVer = require_semver(); var SemVer = require_semver();
var parse3 = (version3, options, throwErrors = false) => { var parse3 = (version4, options, throwErrors = false) => {
if (version3 instanceof SemVer) { if (version4 instanceof SemVer) {
return version3; return version4;
} }
try { try {
return new SemVer(version3, options); return new SemVer(version4, options);
} catch (er) { } catch (er) {
if (!throwErrors) { if (!throwErrors) {
return null; return null;
@@ -19858,8 +19858,8 @@ var require_valid = __commonJS({
"node_modules/@actions/cache/node_modules/semver/functions/valid.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/functions/valid.js"(exports2, module2) {
"use strict"; "use strict";
var parse3 = require_parse2(); var parse3 = require_parse2();
var valid = (version3, options) => { var valid = (version4, options) => {
const v = parse3(version3, options); const v = parse3(version4, options);
return v ? v.version : null; return v ? v.version : null;
}; };
module2.exports = valid; module2.exports = valid;
@@ -19871,8 +19871,8 @@ var require_clean = __commonJS({
"node_modules/@actions/cache/node_modules/semver/functions/clean.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/functions/clean.js"(exports2, module2) {
"use strict"; "use strict";
var parse3 = require_parse2(); var parse3 = require_parse2();
var clean2 = (version3, options) => { var clean2 = (version4, options) => {
const s = parse3(version3.trim().replace(/^[=v]+/, ""), options); const s = parse3(version4.trim().replace(/^[=v]+/, ""), options);
return s ? s.version : null; return s ? s.version : null;
}; };
module2.exports = clean2; module2.exports = clean2;
@@ -19884,7 +19884,7 @@ var require_inc = __commonJS({
"node_modules/@actions/cache/node_modules/semver/functions/inc.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/functions/inc.js"(exports2, module2) {
"use strict"; "use strict";
var SemVer = require_semver(); var SemVer = require_semver();
var inc = (version3, release, options, identifier, identifierBase) => { var inc = (version4, release, options, identifier, identifierBase) => {
if (typeof options === "string") { if (typeof options === "string") {
identifierBase = identifier; identifierBase = identifier;
identifier = options; identifier = options;
@@ -19892,7 +19892,7 @@ var require_inc = __commonJS({
} }
try { try {
return new SemVer( return new SemVer(
version3 instanceof SemVer ? version3.version : version3, version4 instanceof SemVer ? version4.version : version4,
options options
).inc(release, identifier, identifierBase).version; ).inc(release, identifier, identifierBase).version;
} catch (er) { } catch (er) {
@@ -19982,8 +19982,8 @@ var require_prerelease = __commonJS({
"node_modules/@actions/cache/node_modules/semver/functions/prerelease.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/functions/prerelease.js"(exports2, module2) {
"use strict"; "use strict";
var parse3 = require_parse2(); var parse3 = require_parse2();
var prerelease = (version3, options) => { var prerelease = (version4, options) => {
const parsed = parse3(version3, options); const parsed = parse3(version4, options);
return parsed && parsed.prerelease.length ? parsed.prerelease : null; return parsed && parsed.prerelease.length ? parsed.prerelease : null;
}; };
module2.exports = prerelease; module2.exports = prerelease;
@@ -20171,24 +20171,24 @@ var require_coerce = __commonJS({
var SemVer = require_semver(); var SemVer = require_semver();
var parse3 = require_parse2(); var parse3 = require_parse2();
var { safeRe: re, t } = require_re(); var { safeRe: re, t } = require_re();
var coerce = (version3, options) => { var coerce = (version4, options) => {
if (version3 instanceof SemVer) { if (version4 instanceof SemVer) {
return version3; return version4;
} }
if (typeof version3 === "number") { if (typeof version4 === "number") {
version3 = String(version3); version4 = String(version4);
} }
if (typeof version3 !== "string") { if (typeof version4 !== "string") {
return null; return null;
} }
options = options || {}; options = options || {};
let match2 = null; let match2 = null;
if (!options.rtl) { if (!options.rtl) {
match2 = version3.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]); match2 = version4.match(options.includePrerelease ? re[t.COERCEFULL] : re[t.COERCE]);
} else { } else {
const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL]; const coerceRtlRegex = options.includePrerelease ? re[t.COERCERTLFULL] : re[t.COERCERTL];
let next; let next;
while ((next = coerceRtlRegex.exec(version3)) && (!match2 || match2.index + match2[0].length !== version3.length)) { while ((next = coerceRtlRegex.exec(version4)) && (!match2 || match2.index + match2[0].length !== version4.length)) {
if (!match2 || next.index + next[0].length !== match2.index + match2[0].length) { if (!match2 || next.index + next[0].length !== match2.index + match2[0].length) {
match2 = next; match2 = next;
} }
@@ -20327,21 +20327,21 @@ var require_range = __commonJS({
const loose = this.options.loose; const loose = this.options.loose;
const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE]; const hr = loose ? re[t.HYPHENRANGELOOSE] : re[t.HYPHENRANGE];
range2 = range2.replace(hr, hyphenReplace(this.options.includePrerelease)); range2 = range2.replace(hr, hyphenReplace(this.options.includePrerelease));
debug3("hyphen replace", range2); debug2("hyphen replace", range2);
range2 = range2.replace(re[t.COMPARATORTRIM], comparatorTrimReplace); range2 = range2.replace(re[t.COMPARATORTRIM], comparatorTrimReplace);
debug3("comparator trim", range2); debug2("comparator trim", range2);
range2 = range2.replace(re[t.TILDETRIM], tildeTrimReplace); range2 = range2.replace(re[t.TILDETRIM], tildeTrimReplace);
debug3("tilde trim", range2); debug2("tilde trim", range2);
range2 = range2.replace(re[t.CARETTRIM], caretTrimReplace); range2 = range2.replace(re[t.CARETTRIM], caretTrimReplace);
debug3("caret trim", range2); debug2("caret trim", range2);
let rangeList = range2.split(" ").map((comp26) => parseComparator(comp26, this.options)).join(" ").split(/\s+/).map((comp26) => replaceGTE0(comp26, this.options)); let rangeList = range2.split(" ").map((comp26) => parseComparator(comp26, this.options)).join(" ").split(/\s+/).map((comp26) => replaceGTE0(comp26, this.options));
if (loose) { if (loose) {
rangeList = rangeList.filter((comp26) => { rangeList = rangeList.filter((comp26) => {
debug3("loose invalid filter", comp26, this.options); debug2("loose invalid filter", comp26, this.options);
return !!comp26.match(re[t.COMPARATORLOOSE]); return !!comp26.match(re[t.COMPARATORLOOSE]);
}); });
} }
debug3("range list", rangeList); debug2("range list", rangeList);
const rangeMap = /* @__PURE__ */ new Map(); const rangeMap = /* @__PURE__ */ new Map();
const comparators = rangeList.map((comp26) => new Comparator(comp26, this.options)); const comparators = rangeList.map((comp26) => new Comparator(comp26, this.options));
for (const comp26 of comparators) { for (const comp26 of comparators) {
@@ -20372,19 +20372,19 @@ var require_range = __commonJS({
}); });
} }
// if ANY of the sets match ALL of its comparators, then pass // if ANY of the sets match ALL of its comparators, then pass
test(version3) { test(version4) {
if (!version3) { if (!version4) {
return false; return false;
} }
if (typeof version3 === "string") { if (typeof version4 === "string") {
try { try {
version3 = new SemVer(version3, this.options); version4 = new SemVer(version4, this.options);
} catch (er) { } catch (er) {
return false; return false;
} }
} }
for (let i = 0; i < this.set.length; i++) { for (let i = 0; i < this.set.length; i++) {
if (testSet(this.set[i], version3, this.options)) { if (testSet(this.set[i], version4, this.options)) {
return true; return true;
} }
} }
@@ -20396,7 +20396,7 @@ var require_range = __commonJS({
var cache = new LRU(); var cache = new LRU();
var parseOptions = require_parse_options(); var parseOptions = require_parse_options();
var Comparator = require_comparator(); var Comparator = require_comparator();
var debug3 = require_debug(); var debug2 = require_debug();
var SemVer = require_semver(); var SemVer = require_semver();
var { var {
safeRe: re, safeRe: re,
@@ -20422,15 +20422,15 @@ var require_range = __commonJS({
}; };
var parseComparator = (comp26, options) => { var parseComparator = (comp26, options) => {
comp26 = comp26.replace(re[t.BUILD], ""); comp26 = comp26.replace(re[t.BUILD], "");
debug3("comp", comp26, options); debug2("comp", comp26, options);
comp26 = replaceCarets(comp26, options); comp26 = replaceCarets(comp26, options);
debug3("caret", comp26); debug2("caret", comp26);
comp26 = replaceTildes(comp26, options); comp26 = replaceTildes(comp26, options);
debug3("tildes", comp26); debug2("tildes", comp26);
comp26 = replaceXRanges(comp26, options); comp26 = replaceXRanges(comp26, options);
debug3("xrange", comp26); debug2("xrange", comp26);
comp26 = replaceStars(comp26, options); comp26 = replaceStars(comp26, options);
debug3("stars", comp26); debug2("stars", comp26);
return comp26; return comp26;
}; };
var isX = (id) => !id || id.toLowerCase() === "x" || id === "*"; var isX = (id) => !id || id.toLowerCase() === "x" || id === "*";
@@ -20440,7 +20440,7 @@ var require_range = __commonJS({
var replaceTilde = (comp26, options) => { var replaceTilde = (comp26, options) => {
const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE]; const r = options.loose ? re[t.TILDELOOSE] : re[t.TILDE];
return comp26.replace(r, (_, M, m, p, pr) => { return comp26.replace(r, (_, M, m, p, pr) => {
debug3("tilde", comp26, _, M, m, p, pr); debug2("tilde", comp26, _, M, m, p, pr);
let ret; let ret;
if (isX(M)) { if (isX(M)) {
ret = ""; ret = "";
@@ -20449,12 +20449,12 @@ var require_range = __commonJS({
} else if (isX(p)) { } else if (isX(p)) {
ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`; ret = `>=${M}.${m}.0 <${M}.${+m + 1}.0-0`;
} else if (pr) { } else if (pr) {
debug3("replaceTilde pr", pr); debug2("replaceTilde pr", pr);
ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`; ret = `>=${M}.${m}.${p}-${pr} <${M}.${+m + 1}.0-0`;
} else { } else {
ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`; ret = `>=${M}.${m}.${p} <${M}.${+m + 1}.0-0`;
} }
debug3("tilde return", ret); debug2("tilde return", ret);
return ret; return ret;
}); });
}; };
@@ -20462,11 +20462,11 @@ var require_range = __commonJS({
return comp26.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" "); return comp26.trim().split(/\s+/).map((c) => replaceCaret(c, options)).join(" ");
}; };
var replaceCaret = (comp26, options) => { var replaceCaret = (comp26, options) => {
debug3("caret", comp26, options); debug2("caret", comp26, options);
const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET]; const r = options.loose ? re[t.CARETLOOSE] : re[t.CARET];
const z = options.includePrerelease ? "-0" : ""; const z = options.includePrerelease ? "-0" : "";
return comp26.replace(r, (_, M, m, p, pr) => { return comp26.replace(r, (_, M, m, p, pr) => {
debug3("caret", comp26, _, M, m, p, pr); debug2("caret", comp26, _, M, m, p, pr);
let ret; let ret;
if (isX(M)) { if (isX(M)) {
ret = ""; ret = "";
@@ -20479,7 +20479,7 @@ var require_range = __commonJS({
ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`; ret = `>=${M}.${m}.0${z} <${+M + 1}.0.0-0`;
} }
} else if (pr) { } else if (pr) {
debug3("replaceCaret pr", pr); debug2("replaceCaret pr", pr);
if (M === "0") { if (M === "0") {
if (m === "0") { if (m === "0") {
ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`; ret = `>=${M}.${m}.${p}-${pr} <${M}.${m}.${+p + 1}-0`;
@@ -20490,7 +20490,7 @@ var require_range = __commonJS({
ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`; ret = `>=${M}.${m}.${p}-${pr} <${+M + 1}.0.0-0`;
} }
} else { } else {
debug3("no pr"); debug2("no pr");
if (M === "0") { if (M === "0") {
if (m === "0") { if (m === "0") {
ret = `>=${M}.${m}.${p}${z} <${M}.${m}.${+p + 1}-0`; ret = `>=${M}.${m}.${p}${z} <${M}.${m}.${+p + 1}-0`;
@@ -20501,19 +20501,19 @@ var require_range = __commonJS({
ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`; ret = `>=${M}.${m}.${p} <${+M + 1}.0.0-0`;
} }
} }
debug3("caret return", ret); debug2("caret return", ret);
return ret; return ret;
}); });
}; };
var replaceXRanges = (comp26, options) => { var replaceXRanges = (comp26, options) => {
debug3("replaceXRanges", comp26, options); debug2("replaceXRanges", comp26, options);
return comp26.split(/\s+/).map((c) => replaceXRange(c, options)).join(" "); return comp26.split(/\s+/).map((c) => replaceXRange(c, options)).join(" ");
}; };
var replaceXRange = (comp26, options) => { var replaceXRange = (comp26, options) => {
comp26 = comp26.trim(); comp26 = comp26.trim();
const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE]; const r = options.loose ? re[t.XRANGELOOSE] : re[t.XRANGE];
return comp26.replace(r, (ret, gtlt, M, m, p, pr) => { return comp26.replace(r, (ret, gtlt, M, m, p, pr) => {
debug3("xRange", comp26, ret, gtlt, M, m, p, pr); debug2("xRange", comp26, ret, gtlt, M, m, p, pr);
const xM = isX(M); const xM = isX(M);
const xm = xM || isX(m); const xm = xM || isX(m);
const xp = xm || isX(p); const xp = xm || isX(p);
@@ -20560,16 +20560,16 @@ var require_range = __commonJS({
} else if (xp) { } else if (xp) {
ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`; ret = `>=${M}.${m}.0${pr} <${M}.${+m + 1}.0-0`;
} }
debug3("xRange return", ret); debug2("xRange return", ret);
return ret; return ret;
}); });
}; };
var replaceStars = (comp26, options) => { var replaceStars = (comp26, options) => {
debug3("replaceStars", comp26, options); debug2("replaceStars", comp26, options);
return comp26.trim().replace(re[t.STAR], ""); return comp26.trim().replace(re[t.STAR], "");
}; };
var replaceGTE0 = (comp26, options) => { var replaceGTE0 = (comp26, options) => {
debug3("replaceGTE0", comp26, options); debug2("replaceGTE0", comp26, options);
return comp26.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], ""); return comp26.trim().replace(re[options.includePrerelease ? t.GTE0PRE : t.GTE0], "");
}; };
var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => { var hyphenReplace = (incPr) => ($0, from, fM, fm, fp, fpr, fb, to, tM, tm, tp, tpr) => {
@@ -20599,21 +20599,21 @@ var require_range = __commonJS({
} }
return `${from} ${to}`.trim(); return `${from} ${to}`.trim();
}; };
var testSet = (set, version3, options) => { var testSet = (set, version4, options) => {
for (let i = 0; i < set.length; i++) { for (let i = 0; i < set.length; i++) {
if (!set[i].test(version3)) { if (!set[i].test(version4)) {
return false; return false;
} }
} }
if (version3.prerelease.length && !options.includePrerelease) { if (version4.prerelease.length && !options.includePrerelease) {
for (let i = 0; i < set.length; i++) { for (let i = 0; i < set.length; i++) {
debug3(set[i].semver); debug2(set[i].semver);
if (set[i].semver === Comparator.ANY) { if (set[i].semver === Comparator.ANY) {
continue; continue;
} }
if (set[i].semver.prerelease.length > 0) { if (set[i].semver.prerelease.length > 0) {
const allowed = set[i].semver; const allowed = set[i].semver;
if (allowed.major === version3.major && allowed.minor === version3.minor && allowed.patch === version3.patch) { if (allowed.major === version4.major && allowed.minor === version4.minor && allowed.patch === version4.patch) {
return true; return true;
} }
} }
@@ -20644,7 +20644,7 @@ var require_comparator = __commonJS({
} }
} }
comp26 = comp26.trim().split(/\s+/).join(" "); comp26 = comp26.trim().split(/\s+/).join(" ");
debug3("comparator", comp26, options); debug2("comparator", comp26, options);
this.options = options; this.options = options;
this.loose = !!options.loose; this.loose = !!options.loose;
this.parse(comp26); this.parse(comp26);
@@ -20653,7 +20653,7 @@ var require_comparator = __commonJS({
} else { } else {
this.value = this.operator + this.semver.version; this.value = this.operator + this.semver.version;
} }
debug3("comp", this); debug2("comp", this);
} }
parse(comp26) { parse(comp26) {
const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR]; const r = this.options.loose ? re[t.COMPARATORLOOSE] : re[t.COMPARATOR];
@@ -20674,19 +20674,19 @@ var require_comparator = __commonJS({
toString() { toString() {
return this.value; return this.value;
} }
test(version3) { test(version4) {
debug3("Comparator.test", version3, this.options.loose); debug2("Comparator.test", version4, this.options.loose);
if (this.semver === ANY || version3 === ANY) { if (this.semver === ANY || version4 === ANY) {
return true; return true;
} }
if (typeof version3 === "string") { if (typeof version4 === "string") {
try { try {
version3 = new SemVer(version3, this.options); version4 = new SemVer(version4, this.options);
} catch (er) { } catch (er) {
return false; return false;
} }
} }
return cmp(version3, this.operator, this.semver, this.options); return cmp(version4, this.operator, this.semver, this.options);
} }
intersects(comp26, options) { intersects(comp26, options) {
if (!(comp26 instanceof _Comparator)) { if (!(comp26 instanceof _Comparator)) {
@@ -20732,7 +20732,7 @@ var require_comparator = __commonJS({
var parseOptions = require_parse_options(); var parseOptions = require_parse_options();
var { safeRe: re, t } = require_re(); var { safeRe: re, t } = require_re();
var cmp = require_cmp(); var cmp = require_cmp();
var debug3 = require_debug(); var debug2 = require_debug();
var SemVer = require_semver(); var SemVer = require_semver();
var Range = require_range(); var Range = require_range();
} }
@@ -20743,13 +20743,13 @@ var require_satisfies = __commonJS({
"node_modules/@actions/cache/node_modules/semver/functions/satisfies.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/functions/satisfies.js"(exports2, module2) {
"use strict"; "use strict";
var Range = require_range(); var Range = require_range();
var satisfies = (version3, range2, options) => { var satisfies = (version4, range2, options) => {
try { try {
range2 = new Range(range2, options); range2 = new Range(range2, options);
} catch (er) { } catch (er) {
return false; return false;
} }
return range2.test(version3); return range2.test(version4);
}; };
module2.exports = satisfies; module2.exports = satisfies;
} }
@@ -20911,8 +20911,8 @@ var require_outside = __commonJS({
var lt = require_lt(); var lt = require_lt();
var lte = require_lte(); var lte = require_lte();
var gte2 = require_gte(); var gte2 = require_gte();
var outside = (version3, range2, hilo, options) => { var outside = (version4, range2, hilo, options) => {
version3 = new SemVer(version3, options); version4 = new SemVer(version4, options);
range2 = new Range(range2, options); range2 = new Range(range2, options);
let gtfn, ltefn, ltfn, comp26, ecomp; let gtfn, ltefn, ltfn, comp26, ecomp;
switch (hilo) { switch (hilo) {
@@ -20933,7 +20933,7 @@ var require_outside = __commonJS({
default: default:
throw new TypeError('Must provide a hilo val of "<" or ">"'); throw new TypeError('Must provide a hilo val of "<" or ">"');
} }
if (satisfies(version3, range2, options)) { if (satisfies(version4, range2, options)) {
return false; return false;
} }
for (let i = 0; i < range2.set.length; ++i) { for (let i = 0; i < range2.set.length; ++i) {
@@ -20955,9 +20955,9 @@ var require_outside = __commonJS({
if (high.operator === comp26 || high.operator === ecomp) { if (high.operator === comp26 || high.operator === ecomp) {
return false; return false;
} }
if ((!low.operator || low.operator === comp26) && ltefn(version3, low.semver)) { if ((!low.operator || low.operator === comp26) && ltefn(version4, low.semver)) {
return false; return false;
} else if (low.operator === ecomp && ltfn(version3, low.semver)) { } else if (low.operator === ecomp && ltfn(version4, low.semver)) {
return false; return false;
} }
} }
@@ -20972,7 +20972,7 @@ var require_gtr = __commonJS({
"node_modules/@actions/cache/node_modules/semver/ranges/gtr.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/ranges/gtr.js"(exports2, module2) {
"use strict"; "use strict";
var outside = require_outside(); var outside = require_outside();
var gtr = (version3, range2, options) => outside(version3, range2, ">", options); var gtr = (version4, range2, options) => outside(version4, range2, ">", options);
module2.exports = gtr; module2.exports = gtr;
} }
}); });
@@ -20982,7 +20982,7 @@ var require_ltr = __commonJS({
"node_modules/@actions/cache/node_modules/semver/ranges/ltr.js"(exports2, module2) { "node_modules/@actions/cache/node_modules/semver/ranges/ltr.js"(exports2, module2) {
"use strict"; "use strict";
var outside = require_outside(); var outside = require_outside();
var ltr = (version3, range2, options) => outside(version3, range2, "<", options); var ltr = (version4, range2, options) => outside(version4, range2, "<", options);
module2.exports = ltr; module2.exports = ltr;
} }
}); });
@@ -21012,12 +21012,12 @@ var require_simplify = __commonJS({
let first = null; let first = null;
let prev = null; let prev = null;
const v = versions.sort((a, b) => compare(a, b, options)); const v = versions.sort((a, b) => compare(a, b, options));
for (const version3 of v) { for (const version4 of v) {
const included = satisfies(version3, range2, options); const included = satisfies(version4, range2, options);
if (included) { if (included) {
prev = version3; prev = version4;
if (!first) { if (!first) {
first = version3; first = version4;
} }
} else { } else {
if (prev) { if (prev) {
@@ -21456,11 +21456,11 @@ var require_common = __commonJS({
let enableOverride = null; let enableOverride = null;
let namespacesCache; let namespacesCache;
let enabledCache; let enabledCache;
function debug3(...args) { function debug2(...args) {
if (!debug3.enabled) { if (!debug2.enabled) {
return; return;
} }
const self2 = debug3; const self2 = debug2;
const curr = Number(/* @__PURE__ */ new Date()); const curr = Number(/* @__PURE__ */ new Date());
const ms = curr - (prevTime || curr); const ms = curr - (prevTime || curr);
self2.diff = ms; self2.diff = ms;
@@ -21490,12 +21490,12 @@ var require_common = __commonJS({
const logFn = self2.log || createDebug.log; const logFn = self2.log || createDebug.log;
logFn.apply(self2, args); logFn.apply(self2, args);
} }
debug3.namespace = namespace; debug2.namespace = namespace;
debug3.useColors = createDebug.useColors(); debug2.useColors = createDebug.useColors();
debug3.color = createDebug.selectColor(namespace); debug2.color = createDebug.selectColor(namespace);
debug3.extend = extend2; debug2.extend = extend2;
debug3.destroy = createDebug.destroy; debug2.destroy = createDebug.destroy;
Object.defineProperty(debug3, "enabled", { Object.defineProperty(debug2, "enabled", {
enumerable: true, enumerable: true,
configurable: false, configurable: false,
get: () => { get: () => {
@@ -21513,9 +21513,9 @@ var require_common = __commonJS({
} }
}); });
if (typeof createDebug.init === "function") { if (typeof createDebug.init === "function") {
createDebug.init(debug3); createDebug.init(debug2);
} }
return debug3; return debug2;
} }
function extend2(namespace, delimiter3) { function extend2(namespace, delimiter3) {
const newDebug = createDebug(this.namespace + (typeof delimiter3 === "undefined" ? ":" : delimiter3) + namespace); const newDebug = createDebug(this.namespace + (typeof delimiter3 === "undefined" ? ":" : delimiter3) + namespace);
@@ -21840,10 +21840,10 @@ var require_supports_color = __commonJS({
return 3; return 3;
} }
if ("TERM_PROGRAM" in env) { if ("TERM_PROGRAM" in env) {
const version3 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10); const version4 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
switch (env.TERM_PROGRAM) { switch (env.TERM_PROGRAM) {
case "iTerm.app": case "iTerm.app":
return version3 >= 3 ? 3 : 2; return version4 >= 3 ? 3 : 2;
case "Apple_Terminal": case "Apple_Terminal":
return 2; return 2;
} }
@@ -22025,11 +22025,11 @@ var require_node = __commonJS({
function load() { function load() {
return process.env.DEBUG; return process.env.DEBUG;
} }
function init(debug3) { function init(debug2) {
debug3.inspectOpts = {}; debug2.inspectOpts = {};
const keys = Object.keys(exports2.inspectOpts); const keys = Object.keys(exports2.inspectOpts);
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
debug3.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]]; debug2.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]];
} }
} }
module2.exports = require_common()(exports2); module2.exports = require_common()(exports2);
@@ -22292,7 +22292,7 @@ var require_parse_proxy_response = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true }); Object.defineProperty(exports2, "__esModule", { value: true });
exports2.parseProxyResponse = void 0; exports2.parseProxyResponse = void 0;
var debug_1 = __importDefault(require_src()); var debug_1 = __importDefault(require_src());
var debug3 = (0, debug_1.default)("https-proxy-agent:parse-proxy-response"); var debug2 = (0, debug_1.default)("https-proxy-agent:parse-proxy-response");
function parseProxyResponse(socket) { function parseProxyResponse(socket) {
return new Promise((resolve2, reject) => { return new Promise((resolve2, reject) => {
let buffersLength = 0; let buffersLength = 0;
@@ -22311,12 +22311,12 @@ var require_parse_proxy_response = __commonJS({
} }
function onend() { function onend() {
cleanup(); cleanup();
debug3("onend"); debug2("onend");
reject(new Error("Proxy connection ended before receiving CONNECT response")); reject(new Error("Proxy connection ended before receiving CONNECT response"));
} }
function onerror(err) { function onerror(err) {
cleanup(); cleanup();
debug3("onerror %o", err); debug2("onerror %o", err);
reject(err); reject(err);
} }
function ondata(b) { function ondata(b) {
@@ -22325,7 +22325,7 @@ var require_parse_proxy_response = __commonJS({
const buffered = Buffer.concat(buffers, buffersLength); const buffered = Buffer.concat(buffers, buffersLength);
const endOfHeaders = buffered.indexOf("\r\n\r\n"); const endOfHeaders = buffered.indexOf("\r\n\r\n");
if (endOfHeaders === -1) { if (endOfHeaders === -1) {
debug3("have not received end of HTTP headers yet..."); debug2("have not received end of HTTP headers yet...");
read(); read();
return; return;
} }
@@ -22358,7 +22358,7 @@ var require_parse_proxy_response = __commonJS({
headers[key] = value; headers[key] = value;
} }
} }
debug3("got proxy server response: %o %o", firstLine, headers); debug2("got proxy server response: %o %o", firstLine, headers);
cleanup(); cleanup();
resolve2({ resolve2({
connect: { connect: {
@@ -22421,7 +22421,7 @@ var require_dist2 = __commonJS({
var agent_base_1 = require_dist(); var agent_base_1 = require_dist();
var url_1 = require("url"); var url_1 = require("url");
var parse_proxy_response_1 = require_parse_proxy_response(); var parse_proxy_response_1 = require_parse_proxy_response();
var debug3 = (0, debug_1.default)("https-proxy-agent"); var debug2 = (0, debug_1.default)("https-proxy-agent");
var setServernameFromNonIpHost = (options) => { var setServernameFromNonIpHost = (options) => {
if (options.servername === void 0 && options.host && !net.isIP(options.host)) { if (options.servername === void 0 && options.host && !net.isIP(options.host)) {
return { return {
@@ -22437,7 +22437,7 @@ var require_dist2 = __commonJS({
this.options = { path: void 0 }; this.options = { path: void 0 };
this.proxy = typeof proxy === "string" ? new url_1.URL(proxy) : proxy; this.proxy = typeof proxy === "string" ? new url_1.URL(proxy) : proxy;
this.proxyHeaders = opts?.headers ?? {}; this.proxyHeaders = opts?.headers ?? {};
debug3("Creating new HttpsProxyAgent instance: %o", this.proxy.href); debug2("Creating new HttpsProxyAgent instance: %o", this.proxy.href);
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ""); const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, "");
const port = this.proxy.port ? parseInt(this.proxy.port, 10) : this.proxy.protocol === "https:" ? 443 : 80; const port = this.proxy.port ? parseInt(this.proxy.port, 10) : this.proxy.protocol === "https:" ? 443 : 80;
this.connectOpts = { this.connectOpts = {
@@ -22459,10 +22459,10 @@ var require_dist2 = __commonJS({
} }
let socket; let socket;
if (proxy.protocol === "https:") { if (proxy.protocol === "https:") {
debug3("Creating `tls.Socket`: %o", this.connectOpts); debug2("Creating `tls.Socket`: %o", this.connectOpts);
socket = tls.connect(setServernameFromNonIpHost(this.connectOpts)); socket = tls.connect(setServernameFromNonIpHost(this.connectOpts));
} else { } else {
debug3("Creating `net.Socket`: %o", this.connectOpts); debug2("Creating `net.Socket`: %o", this.connectOpts);
socket = net.connect(this.connectOpts); socket = net.connect(this.connectOpts);
} }
const headers = typeof this.proxyHeaders === "function" ? this.proxyHeaders() : { ...this.proxyHeaders }; const headers = typeof this.proxyHeaders === "function" ? this.proxyHeaders() : { ...this.proxyHeaders };
@@ -22490,7 +22490,7 @@ var require_dist2 = __commonJS({
if (connect.statusCode === 200) { if (connect.statusCode === 200) {
req.once("socket", resume); req.once("socket", resume);
if (opts.secureEndpoint) { if (opts.secureEndpoint) {
debug3("Upgrading socket connection to TLS"); debug2("Upgrading socket connection to TLS");
return tls.connect({ return tls.connect({
...omit(setServernameFromNonIpHost(opts), "host", "path", "port"), ...omit(setServernameFromNonIpHost(opts), "host", "path", "port"),
socket socket
@@ -22502,7 +22502,7 @@ var require_dist2 = __commonJS({
const fakeSocket = new net.Socket({ writable: false }); const fakeSocket = new net.Socket({ writable: false });
fakeSocket.readable = true; fakeSocket.readable = true;
req.once("socket", (s) => { req.once("socket", (s) => {
debug3("Replaying proxy buffer for failed request"); debug2("Replaying proxy buffer for failed request");
(0, assert_1.default)(s.listenerCount("data") > 0); (0, assert_1.default)(s.listenerCount("data") > 0);
s.push(buffered); s.push(buffered);
s.push(null); s.push(null);
@@ -22570,13 +22570,13 @@ var require_dist3 = __commonJS({
var events_1 = require("events"); var events_1 = require("events");
var agent_base_1 = require_dist(); var agent_base_1 = require_dist();
var url_1 = require("url"); var url_1 = require("url");
var debug3 = (0, debug_1.default)("http-proxy-agent"); var debug2 = (0, debug_1.default)("http-proxy-agent");
var HttpProxyAgent2 = class extends agent_base_1.Agent { var HttpProxyAgent2 = class extends agent_base_1.Agent {
constructor(proxy, opts) { constructor(proxy, opts) {
super(opts); super(opts);
this.proxy = typeof proxy === "string" ? new url_1.URL(proxy) : proxy; this.proxy = typeof proxy === "string" ? new url_1.URL(proxy) : proxy;
this.proxyHeaders = opts?.headers ?? {}; this.proxyHeaders = opts?.headers ?? {};
debug3("Creating new HttpProxyAgent instance: %o", this.proxy.href); debug2("Creating new HttpProxyAgent instance: %o", this.proxy.href);
const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, ""); const host = (this.proxy.hostname || this.proxy.host).replace(/^\[|\]$/g, "");
const port = this.proxy.port ? parseInt(this.proxy.port, 10) : this.proxy.protocol === "https:" ? 443 : 80; const port = this.proxy.port ? parseInt(this.proxy.port, 10) : this.proxy.protocol === "https:" ? 443 : 80;
this.connectOpts = { this.connectOpts = {
@@ -22622,21 +22622,21 @@ var require_dist3 = __commonJS({
} }
let first; let first;
let endOfHeaders; let endOfHeaders;
debug3("Regenerating stored HTTP header string for request"); debug2("Regenerating stored HTTP header string for request");
req._implicitHeader(); req._implicitHeader();
if (req.outputData && req.outputData.length > 0) { if (req.outputData && req.outputData.length > 0) {
debug3("Patching connection write() output buffer with updated header"); debug2("Patching connection write() output buffer with updated header");
first = req.outputData[0].data; first = req.outputData[0].data;
endOfHeaders = first.indexOf("\r\n\r\n") + 4; endOfHeaders = first.indexOf("\r\n\r\n") + 4;
req.outputData[0].data = req._header + first.substring(endOfHeaders); req.outputData[0].data = req._header + first.substring(endOfHeaders);
debug3("Output buffer: %o", req.outputData[0].data); debug2("Output buffer: %o", req.outputData[0].data);
} }
let socket; let socket;
if (this.proxy.protocol === "https:") { if (this.proxy.protocol === "https:") {
debug3("Creating `tls.Socket`: %o", this.connectOpts); debug2("Creating `tls.Socket`: %o", this.connectOpts);
socket = tls.connect(this.connectOpts); socket = tls.connect(this.connectOpts);
} else { } else {
debug3("Creating `net.Socket`: %o", this.connectOpts); debug2("Creating `net.Socket`: %o", this.connectOpts);
socket = net.connect(this.connectOpts); socket = net.connect(this.connectOpts);
} }
await (0, events_1.once)(socket, "connect"); await (0, events_1.once)(socket, "connect");
@@ -24039,9 +24039,9 @@ var require_reflection_type_check = __commonJS({
var reflection_info_1 = require_reflection_info(); var reflection_info_1 = require_reflection_info();
var oneof_1 = require_oneof(); var oneof_1 = require_oneof();
var ReflectionTypeCheck = class { var ReflectionTypeCheck = class {
constructor(info3) { constructor(info2) {
var _a; var _a;
this.fields = (_a = info3.fields) !== null && _a !== void 0 ? _a : []; this.fields = (_a = info2.fields) !== null && _a !== void 0 ? _a : [];
} }
prepare() { prepare() {
if (this.data) if (this.data)
@@ -24287,8 +24287,8 @@ var require_reflection_json_reader = __commonJS({
var assert_1 = require_assert(); var assert_1 = require_assert();
var reflection_long_convert_1 = require_reflection_long_convert(); var reflection_long_convert_1 = require_reflection_long_convert();
var ReflectionJsonReader = class { var ReflectionJsonReader = class {
constructor(info3) { constructor(info2) {
this.info = info3; this.info = info2;
} }
prepare() { prepare() {
var _a; var _a;
@@ -24584,9 +24584,9 @@ var require_reflection_json_writer = __commonJS({
var reflection_info_1 = require_reflection_info(); var reflection_info_1 = require_reflection_info();
var assert_1 = require_assert(); var assert_1 = require_assert();
var ReflectionJsonWriter = class { var ReflectionJsonWriter = class {
constructor(info3) { constructor(info2) {
var _a; var _a;
this.fields = (_a = info3.fields) !== null && _a !== void 0 ? _a : []; this.fields = (_a = info2.fields) !== null && _a !== void 0 ? _a : [];
} }
/** /**
* Converts the message to a JSON object, based on the field descriptors. * Converts the message to a JSON object, based on the field descriptors.
@@ -24839,8 +24839,8 @@ var require_reflection_binary_reader = __commonJS({
var reflection_long_convert_1 = require_reflection_long_convert(); var reflection_long_convert_1 = require_reflection_long_convert();
var reflection_scalar_default_1 = require_reflection_scalar_default(); var reflection_scalar_default_1 = require_reflection_scalar_default();
var ReflectionBinaryReader = class { var ReflectionBinaryReader = class {
constructor(info3) { constructor(info2) {
this.info = info3; this.info = info2;
} }
prepare() { prepare() {
var _a; var _a;
@@ -25013,8 +25013,8 @@ var require_reflection_binary_writer = __commonJS({
var assert_1 = require_assert(); var assert_1 = require_assert();
var pb_long_1 = require_pb_long(); var pb_long_1 = require_pb_long();
var ReflectionBinaryWriter = class { var ReflectionBinaryWriter = class {
constructor(info3) { constructor(info2) {
this.info = info3; this.info = info2;
} }
prepare() { prepare() {
if (!this.fields) { if (!this.fields) {
@@ -25264,9 +25264,9 @@ var require_reflection_merge_partial = __commonJS({
"use strict"; "use strict";
Object.defineProperty(exports2, "__esModule", { value: true }); Object.defineProperty(exports2, "__esModule", { value: true });
exports2.reflectionMergePartial = void 0; exports2.reflectionMergePartial = void 0;
function reflectionMergePartial4(info3, target, source) { function reflectionMergePartial4(info2, target, source) {
let fieldValue, input = source, output; let fieldValue, input = source, output;
for (let field of info3.fields) { for (let field of info2.fields) {
let name = field.localName; let name = field.localName;
if (field.oneof) { if (field.oneof) {
const group = input[field.oneof]; const group = input[field.oneof];
@@ -25335,12 +25335,12 @@ var require_reflection_equals = __commonJS({
Object.defineProperty(exports2, "__esModule", { value: true }); Object.defineProperty(exports2, "__esModule", { value: true });
exports2.reflectionEquals = void 0; exports2.reflectionEquals = void 0;
var reflection_info_1 = require_reflection_info(); var reflection_info_1 = require_reflection_info();
function reflectionEquals(info3, a, b) { function reflectionEquals(info2, a, b) {
if (a === b) if (a === b)
return true; return true;
if (!a || !b) if (!a || !b)
return false; return false;
for (let field of info3.fields) { for (let field of info2.fields) {
let localName = field.localName; let localName = field.localName;
let val_a = field.oneof ? a[field.oneof][localName] : a[localName]; let val_a = field.oneof ? a[field.oneof][localName] : a[localName];
let val_b = field.oneof ? b[field.oneof][localName] : b[localName]; let val_b = field.oneof ? b[field.oneof][localName] : b[localName];
@@ -27060,15 +27060,15 @@ var require_version = __commonJS({
stringify: stringify2 stringify: stringify2
}; };
var validRegex = new RegExp("^" + VERSION_PATTERN + "$", "i"); var validRegex = new RegExp("^" + VERSION_PATTERN + "$", "i");
function valid(version3) { function valid(version4) {
return validRegex.test(version3) ? version3 : null; return validRegex.test(version4) ? version4 : null;
} }
var cleanRegex = new RegExp("^\\s*" + VERSION_PATTERN + "\\s*$", "i"); var cleanRegex = new RegExp("^\\s*" + VERSION_PATTERN + "\\s*$", "i");
function clean2(version3) { function clean2(version4) {
return stringify2(parse3(version3, cleanRegex)); return stringify2(parse3(version4, cleanRegex));
} }
function parse3(version3, regex) { function parse3(version4, regex) {
const { groups } = (regex || validRegex).exec(version3) || {}; const { groups } = (regex || validRegex).exec(version4) || {};
if (!groups) { if (!groups) {
return null; return null;
} }
@@ -27142,8 +27142,8 @@ var require_version = __commonJS({
} }
return null; return null;
} }
function explain(version3) { function explain(version4) {
const parsed = parse3(version3); const parsed = parse3(version4);
if (!parsed) { if (!parsed) {
return parsed; return parsed;
} }
@@ -27194,36 +27194,36 @@ var require_operator = __commonJS({
">": gt, ">": gt,
"===": arbitrary "===": arbitrary
}; };
function lt(version3, other) { function lt(version4, other) {
return compare(version3, other) < 0; return compare(version4, other) < 0;
} }
function le(version3, other) { function le(version4, other) {
return compare(version3, other) <= 0; return compare(version4, other) <= 0;
} }
function eq(version3, other) { function eq(version4, other) {
return compare(version3, other) === 0; return compare(version4, other) === 0;
} }
function ne(version3, other) { function ne(version4, other) {
return compare(version3, other) !== 0; return compare(version4, other) !== 0;
} }
function ge(version3, other) { function ge(version4, other) {
return compare(version3, other) >= 0; return compare(version4, other) >= 0;
} }
function gt(version3, other) { function gt(version4, other) {
return compare(version3, other) > 0; return compare(version4, other) > 0;
} }
function arbitrary(version3, other) { function arbitrary(version4, other) {
return version3.toLowerCase() === other.toLowerCase(); return version4.toLowerCase() === other.toLowerCase();
} }
function compare(version3, other) { function compare(version4, other) {
const parsedVersion = parse3(version3); const parsedVersion = parse3(version4);
const parsedOther = parse3(other); const parsedOther = parse3(other);
const keyVersion = calculateKey(parsedVersion); const keyVersion = calculateKey(parsedVersion);
const keyOther = calculateKey(parsedOther); const keyOther = calculateKey(parsedOther);
return pyCompare(keyVersion, keyOther); return pyCompare(keyVersion, keyOther);
} }
function rcompare(version3, other) { function rcompare(version4, other) {
return -compare(version3, other); return -compare(version4, other);
} }
function pyCompare(elemIn, otherIn) { function pyCompare(elemIn, otherIn) {
let elem = elemIn; let elem = elemIn;
@@ -27317,9 +27317,9 @@ var require_specifier = __commonJS({
return null; return null;
} }
let { ...spec } = groups; let { ...spec } = groups;
const { operator, version: version3, prefix: prefix2, legacy } = groups; const { operator, version: version4, prefix: prefix2, legacy } = groups;
if (version3) { if (version4) {
spec = { ...spec, ...explainVersion(version3) }; spec = { ...spec, ...explainVersion(version4) };
if (operator === "~=") { if (operator === "~=") {
if (spec.release.length < 2) { if (spec.release.length < 2) {
return null; return null;
@@ -27364,8 +27364,8 @@ var require_specifier = __commonJS({
if (!parsed) { if (!parsed) {
return []; return [];
} }
return versions.filter((version3) => { return versions.filter((version4) => {
const explained = explainVersion(version3); const explained = explainVersion(version4);
if (!parsed.length) { if (!parsed.length) {
return explained && !(explained.is_prerelease && !options.prereleases); return explained && !(explained.is_prerelease && !options.prereleases);
} }
@@ -27373,12 +27373,12 @@ var require_specifier = __commonJS({
if (!pass) { if (!pass) {
return false; return false;
} }
return contains({ ...spec, ...options }, { version: version3, explained }); return contains({ ...spec, ...options }, { version: version4, explained });
}, true); }, true);
}); });
} }
function satisfies(version3, specifier, options = {}) { function satisfies(version4, specifier, options = {}) {
const filtered = pick([version3], specifier, options); const filtered = pick([version4], specifier, options);
return filtered.length === 1; return filtered.length === 1;
} }
function arrayStartsWith(array, prefix2) { function arrayStartsWith(array, prefix2) {
@@ -27394,7 +27394,7 @@ var require_specifier = __commonJS({
} }
function contains(specifier, input) { function contains(specifier, input) {
const { explained } = input; const { explained } = input;
let { version: version3 } = input; let { version: version4 } = input;
const { ...spec } = specifier; const { ...spec } = specifier;
if (spec.prereleases === void 0) { if (spec.prereleases === void 0) {
spec.prereleases = spec.is_prerelease; spec.prereleases = spec.is_prerelease;
@@ -27407,7 +27407,7 @@ var require_specifier = __commonJS({
if (spec.epoch) { if (spec.epoch) {
compatiblePrefix = spec.epoch + "!" + compatiblePrefix; compatiblePrefix = spec.epoch + "!" + compatiblePrefix;
} }
return satisfies(version3, `>=${spec.version}, ==${compatiblePrefix}`, { return satisfies(version4, `>=${spec.version}, ==${compatiblePrefix}`, {
prereleases: spec.prereleases prereleases: spec.prereleases
}); });
} }
@@ -27418,7 +27418,7 @@ var require_specifier = __commonJS({
} }
if (explained) { if (explained) {
if (explained.local && spec.version) { if (explained.local && spec.version) {
version3 = explained.public; version4 = explained.public;
spec.version = explainVersion(spec.version).public; spec.version = explainVersion(spec.version).public;
} }
} }
@@ -27428,7 +27428,7 @@ var require_specifier = __commonJS({
} }
} }
const op = Operator[spec.operator]; const op = Operator[spec.operator];
return op(version3, spec.version || spec.legacy); return op(version4, spec.version || spec.legacy);
} }
function validRange(specifier) { function validRange(specifier) {
return Boolean(parse3(specifier)); return Boolean(parse3(specifier));
@@ -27447,36 +27447,36 @@ var require_semantic = __commonJS({
inc inc
}; };
function major(input) { function major(input) {
const version3 = explain(input); const version4 = explain(input);
if (!version3) { if (!version4) {
throw new TypeError("Invalid Version: " + input); throw new TypeError("Invalid Version: " + input);
} }
return version3.release[0]; return version4.release[0];
} }
function minor(input) { function minor(input) {
const version3 = explain(input); const version4 = explain(input);
if (!version3) { if (!version4) {
throw new TypeError("Invalid Version: " + input); throw new TypeError("Invalid Version: " + input);
} }
if (version3.release.length < 2) { if (version4.release.length < 2) {
return 0; return 0;
} }
return version3.release[1]; return version4.release[1];
} }
function patch(input) { function patch(input) {
const version3 = explain(input); const version4 = explain(input);
if (!version3) { if (!version4) {
throw new TypeError("Invalid Version: " + input); throw new TypeError("Invalid Version: " + input);
} }
if (version3.release.length < 3) { if (version4.release.length < 3) {
return 0; return 0;
} }
return version3.release[2]; return version4.release[2];
} }
function inc(input, release, preReleaseIdentifier) { function inc(input, release, preReleaseIdentifier) {
let identifier = preReleaseIdentifier || `a`; let identifier = preReleaseIdentifier || `a`;
const version3 = parse3(input); const version4 = parse3(input);
if (!version3) { if (!version4) {
return null; return null;
} }
if (!["a", "b", "c", "rc", "alpha", "beta", "pre", "preview"].includes( if (!["a", "b", "c", "rc", "alpha", "beta", "pre", "preview"].includes(
@@ -27487,103 +27487,103 @@ var require_semantic = __commonJS({
switch (release) { switch (release) {
case "premajor": case "premajor":
{ {
const [majorVersion] = version3.release; const [majorVersion] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion + 1; version4.release[0] = majorVersion + 1;
} }
version3.pre = [identifier, 0]; version4.pre = [identifier, 0];
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
case "preminor": case "preminor":
{ {
const [majorVersion, minorVersion = 0] = version3.release; const [majorVersion, minorVersion = 0] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion; version4.release[0] = majorVersion;
version3.release[1] = minorVersion + 1; version4.release[1] = minorVersion + 1;
} }
version3.pre = [identifier, 0]; version4.pre = [identifier, 0];
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
case "prepatch": case "prepatch":
{ {
const [majorVersion, minorVersion = 0, patchVersion = 0] = version3.release; const [majorVersion, minorVersion = 0, patchVersion = 0] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion; version4.release[0] = majorVersion;
version3.release[1] = minorVersion; version4.release[1] = minorVersion;
version3.release[2] = patchVersion + 1; version4.release[2] = patchVersion + 1;
} }
version3.pre = [identifier, 0]; version4.pre = [identifier, 0];
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
case "prerelease": case "prerelease":
if (version3.pre === null) { if (version4.pre === null) {
const [majorVersion, minorVersion = 0, patchVersion = 0] = version3.release; const [majorVersion, minorVersion = 0, patchVersion = 0] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion; version4.release[0] = majorVersion;
version3.release[1] = minorVersion; version4.release[1] = minorVersion;
version3.release[2] = patchVersion + 1; version4.release[2] = patchVersion + 1;
version3.pre = [identifier, 0]; version4.pre = [identifier, 0];
} else { } else {
if (preReleaseIdentifier === void 0 && version3.pre !== null) { if (preReleaseIdentifier === void 0 && version4.pre !== null) {
[identifier] = version3.pre; [identifier] = version4.pre;
} }
const [letter, number] = version3.pre; const [letter, number] = version4.pre;
if (letter === identifier) { if (letter === identifier) {
version3.pre = [letter, number + 1]; version4.pre = [letter, number + 1];
} else { } else {
version3.pre = [identifier, 0]; version4.pre = [identifier, 0];
} }
} }
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
case "major": case "major":
if (version3.release.slice(1).some((value) => value !== 0) || version3.pre === null) { if (version4.release.slice(1).some((value) => value !== 0) || version4.pre === null) {
const [majorVersion] = version3.release; const [majorVersion] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion + 1; version4.release[0] = majorVersion + 1;
} }
delete version3.pre; delete version4.pre;
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
case "minor": case "minor":
if (version3.release.slice(2).some((value) => value !== 0) || version3.pre === null) { if (version4.release.slice(2).some((value) => value !== 0) || version4.pre === null) {
const [majorVersion, minorVersion = 0] = version3.release; const [majorVersion, minorVersion = 0] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion; version4.release[0] = majorVersion;
version3.release[1] = minorVersion + 1; version4.release[1] = minorVersion + 1;
} }
delete version3.pre; delete version4.pre;
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
case "patch": case "patch":
if (version3.release.slice(3).some((value) => value !== 0) || version3.pre === null) { if (version4.release.slice(3).some((value) => value !== 0) || version4.pre === null) {
const [majorVersion, minorVersion = 0, patchVersion = 0] = version3.release; const [majorVersion, minorVersion = 0, patchVersion = 0] = version4.release;
version3.release.fill(0); version4.release.fill(0);
version3.release[0] = majorVersion; version4.release[0] = majorVersion;
version3.release[1] = minorVersion; version4.release[1] = minorVersion;
version3.release[2] = patchVersion + 1; version4.release[2] = patchVersion + 1;
} }
delete version3.pre; delete version4.pre;
delete version3.post; delete version4.post;
delete version3.dev; delete version4.dev;
delete version3.local; delete version4.local;
break; break;
default: default:
return null; return null;
} }
return stringify2(version3); return stringify2(version4);
} }
} }
}); });
@@ -28045,12 +28045,12 @@ var HttpClient = class {
throw new Error("Client has already been disposed."); throw new Error("Client has already been disposed.");
} }
const parsedUrl = new URL(requestUrl); const parsedUrl = new URL(requestUrl);
let info3 = this._prepareRequest(verb, parsedUrl, headers); let info2 = this._prepareRequest(verb, parsedUrl, headers);
const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
let numTries = 0; let numTries = 0;
let response; let response;
do { do {
response = yield this.requestRaw(info3, data); response = yield this.requestRaw(info2, data);
if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
let authenticationHandler; let authenticationHandler;
for (const handler of this.handlers) { for (const handler of this.handlers) {
@@ -28060,7 +28060,7 @@ var HttpClient = class {
} }
} }
if (authenticationHandler) { if (authenticationHandler) {
return authenticationHandler.handleAuthentication(this, info3, data); return authenticationHandler.handleAuthentication(this, info2, data);
} else { } else {
return response; return response;
} }
@@ -28083,8 +28083,8 @@ var HttpClient = class {
} }
} }
} }
info3 = this._prepareRequest(verb, parsedRedirectUrl, headers); info2 = this._prepareRequest(verb, parsedRedirectUrl, headers);
response = yield this.requestRaw(info3, data); response = yield this.requestRaw(info2, data);
redirectsRemaining--; redirectsRemaining--;
} }
if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) { if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -28113,7 +28113,7 @@ var HttpClient = class {
* @param info * @param info
* @param data * @param data
*/ */
requestRaw(info3, data) { requestRaw(info2, data) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve2, reject) => { return new Promise((resolve2, reject) => {
function callbackForResult(err, res) { function callbackForResult(err, res) {
@@ -28125,7 +28125,7 @@ var HttpClient = class {
resolve2(res); resolve2(res);
} }
} }
this.requestRawWithCallback(info3, data, callbackForResult); this.requestRawWithCallback(info2, data, callbackForResult);
}); });
}); });
} }
@@ -28135,12 +28135,12 @@ var HttpClient = class {
* @param data * @param data
* @param onResult * @param onResult
*/ */
requestRawWithCallback(info3, data, onResult) { requestRawWithCallback(info2, data, onResult) {
if (typeof data === "string") { if (typeof data === "string") {
if (!info3.options.headers) { if (!info2.options.headers) {
info3.options.headers = {}; info2.options.headers = {};
} }
info3.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8"); info2.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
} }
let callbackCalled = false; let callbackCalled = false;
function handleResult(err, res) { function handleResult(err, res) {
@@ -28149,7 +28149,7 @@ var HttpClient = class {
onResult(err, res); onResult(err, res);
} }
} }
const req = info3.httpModule.request(info3.options, (msg) => { const req = info2.httpModule.request(info2.options, (msg) => {
const res = new HttpClientResponse(msg); const res = new HttpClientResponse(msg);
handleResult(void 0, res); handleResult(void 0, res);
}); });
@@ -28161,7 +28161,7 @@ var HttpClient = class {
if (socket) { if (socket) {
socket.end(); socket.end();
} }
handleResult(new Error(`Request timeout: ${info3.options.path}`)); handleResult(new Error(`Request timeout: ${info2.options.path}`));
}); });
req.on("error", function(err) { req.on("error", function(err) {
handleResult(err); handleResult(err);
@@ -28197,27 +28197,27 @@ var HttpClient = class {
return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
} }
_prepareRequest(method, requestUrl, headers) { _prepareRequest(method, requestUrl, headers) {
const info3 = {}; const info2 = {};
info3.parsedUrl = requestUrl; info2.parsedUrl = requestUrl;
const usingSsl = info3.parsedUrl.protocol === "https:"; const usingSsl = info2.parsedUrl.protocol === "https:";
info3.httpModule = usingSsl ? https : http; info2.httpModule = usingSsl ? https : http;
const defaultPort = usingSsl ? 443 : 80; const defaultPort = usingSsl ? 443 : 80;
info3.options = {}; info2.options = {};
info3.options.host = info3.parsedUrl.hostname; info2.options.host = info2.parsedUrl.hostname;
info3.options.port = info3.parsedUrl.port ? parseInt(info3.parsedUrl.port) : defaultPort; info2.options.port = info2.parsedUrl.port ? parseInt(info2.parsedUrl.port) : defaultPort;
info3.options.path = (info3.parsedUrl.pathname || "") + (info3.parsedUrl.search || ""); info2.options.path = (info2.parsedUrl.pathname || "") + (info2.parsedUrl.search || "");
info3.options.method = method; info2.options.method = method;
info3.options.headers = this._mergeHeaders(headers); info2.options.headers = this._mergeHeaders(headers);
if (this.userAgent != null) { if (this.userAgent != null) {
info3.options.headers["user-agent"] = this.userAgent; info2.options.headers["user-agent"] = this.userAgent;
} }
info3.options.agent = this._getAgent(info3.parsedUrl); info2.options.agent = this._getAgent(info2.parsedUrl);
if (this.handlers) { if (this.handlers) {
for (const handler of this.handlers) { for (const handler of this.handlers) {
handler.prepareRequest(info3.options); handler.prepareRequest(info2.options);
} }
} }
return info3; return info2;
} }
_mergeHeaders(headers) { _mergeHeaders(headers) {
if (this.requestOptions && this.requestOptions.headers) { if (this.requestOptions && this.requestOptions.headers) {
@@ -30412,8 +30412,8 @@ function getVersion(app_1) {
function getCompressionMethod() { function getCompressionMethod() {
return __awaiter10(this, void 0, void 0, function* () { return __awaiter10(this, void 0, void 0, function* () {
const versionOutput = yield getVersion("zstd", ["--quiet"]); const versionOutput = yield getVersion("zstd", ["--quiet"]);
const version3 = semver.clean(versionOutput); const version4 = semver.clean(versionOutput);
debug(`zstd version: ${version3}`); debug(`zstd version: ${version4}`);
if (versionOutput === "") { if (versionOutput === "") {
return CompressionMethod.Gzip; return CompressionMethod.Gzip;
} else { } else {
@@ -30601,14 +30601,14 @@ function disable() {
return result; return result;
} }
function createDebugger(namespace) { function createDebugger(namespace) {
const newDebugger = Object.assign(debug3, { const newDebugger = Object.assign(debug2, {
enabled: enabled(namespace), enabled: enabled(namespace),
destroy, destroy,
log: debugObj.log, log: debugObj.log,
namespace, namespace,
extend extend
}); });
function debug3(...args) { function debug2(...args) {
if (!newDebugger.enabled) { if (!newDebugger.enabled) {
return; return;
} }
@@ -34098,12 +34098,12 @@ function getOperationRequestInfo(request) {
if (hasOriginalRequest(request)) { if (hasOriginalRequest(request)) {
return getOperationRequestInfo(request[originalRequestSymbol]); return getOperationRequestInfo(request[originalRequestSymbol]);
} }
let info3 = state2.operationRequestMap.get(request); let info2 = state2.operationRequestMap.get(request);
if (!info3) { if (!info2) {
info3 = {}; info2 = {};
state2.operationRequestMap.set(request, info3); state2.operationRequestMap.set(request, info2);
} }
return info3; return info2;
} }
// node_modules/@azure/core-client/dist/esm/deserializationPolicy.js // node_modules/@azure/core-client/dist/esm/deserializationPolicy.js
@@ -54754,8 +54754,8 @@ var SASQueryParameters = class {
} }
return void 0; return void 0;
} }
constructor(version3, signature, permissionsOrOptions, services, resourceTypes, protocol, startsOn, expiresOn2, ipRange, identifier, resource, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType2, userDelegationKey, preauthorizedAgentObjectId, correlationId, encryptionScope2, delegatedUserObjectId) { constructor(version4, signature, permissionsOrOptions, services, resourceTypes, protocol, startsOn, expiresOn2, ipRange, identifier, resource, cacheControl, contentDisposition, contentEncoding, contentLanguage, contentType2, userDelegationKey, preauthorizedAgentObjectId, correlationId, encryptionScope2, delegatedUserObjectId) {
this.version = version3; this.version = version4;
this.signature = signature; this.signature = signature;
if (permissionsOrOptions !== void 0 && typeof permissionsOrOptions !== "string") { if (permissionsOrOptions !== void 0 && typeof permissionsOrOptions !== "string") {
this.permissions = permissionsOrOptions.permissions; this.permissions = permissionsOrOptions.permissions;
@@ -54962,7 +54962,7 @@ function generateBlobSASQueryParameters(blobSASSignatureValues, sharedKeyCredent
return generateBlobSASQueryParametersInternal(blobSASSignatureValues, sharedKeyCredentialOrUserDelegationKey, accountName).sasQueryParameters; return generateBlobSASQueryParametersInternal(blobSASSignatureValues, sharedKeyCredentialOrUserDelegationKey, accountName).sasQueryParameters;
} }
function generateBlobSASQueryParametersInternal(blobSASSignatureValues, sharedKeyCredentialOrUserDelegationKey, accountName) { function generateBlobSASQueryParametersInternal(blobSASSignatureValues, sharedKeyCredentialOrUserDelegationKey, accountName) {
const version3 = blobSASSignatureValues.version ? blobSASSignatureValues.version : SERVICE_VERSION; const version4 = blobSASSignatureValues.version ? blobSASSignatureValues.version : SERVICE_VERSION;
const sharedKeyCredential = sharedKeyCredentialOrUserDelegationKey instanceof StorageSharedKeyCredential ? sharedKeyCredentialOrUserDelegationKey : void 0; const sharedKeyCredential = sharedKeyCredentialOrUserDelegationKey instanceof StorageSharedKeyCredential ? sharedKeyCredentialOrUserDelegationKey : void 0;
let userDelegationKeyCredential; let userDelegationKeyCredential;
if (sharedKeyCredential === void 0 && accountName !== void 0) { if (sharedKeyCredential === void 0 && accountName !== void 0) {
@@ -54971,29 +54971,29 @@ function generateBlobSASQueryParametersInternal(blobSASSignatureValues, sharedKe
if (sharedKeyCredential === void 0 && userDelegationKeyCredential === void 0) { if (sharedKeyCredential === void 0 && userDelegationKeyCredential === void 0) {
throw TypeError("Invalid sharedKeyCredential, userDelegationKey or accountName."); throw TypeError("Invalid sharedKeyCredential, userDelegationKey or accountName.");
} }
if (version3 >= "2020-12-06") { if (version4 >= "2020-12-06") {
if (sharedKeyCredential !== void 0) { if (sharedKeyCredential !== void 0) {
return generateBlobSASQueryParameters20201206(blobSASSignatureValues, sharedKeyCredential); return generateBlobSASQueryParameters20201206(blobSASSignatureValues, sharedKeyCredential);
} else { } else {
if (version3 >= "2025-07-05") { if (version4 >= "2025-07-05") {
return generateBlobSASQueryParametersUDK20250705(blobSASSignatureValues, userDelegationKeyCredential); return generateBlobSASQueryParametersUDK20250705(blobSASSignatureValues, userDelegationKeyCredential);
} else { } else {
return generateBlobSASQueryParametersUDK20201206(blobSASSignatureValues, userDelegationKeyCredential); return generateBlobSASQueryParametersUDK20201206(blobSASSignatureValues, userDelegationKeyCredential);
} }
} }
} }
if (version3 >= "2018-11-09") { if (version4 >= "2018-11-09") {
if (sharedKeyCredential !== void 0) { if (sharedKeyCredential !== void 0) {
return generateBlobSASQueryParameters20181109(blobSASSignatureValues, sharedKeyCredential); return generateBlobSASQueryParameters20181109(blobSASSignatureValues, sharedKeyCredential);
} else { } else {
if (version3 >= "2020-02-10") { if (version4 >= "2020-02-10") {
return generateBlobSASQueryParametersUDK20200210(blobSASSignatureValues, userDelegationKeyCredential); return generateBlobSASQueryParametersUDK20200210(blobSASSignatureValues, userDelegationKeyCredential);
} else { } else {
return generateBlobSASQueryParametersUDK20181109(blobSASSignatureValues, userDelegationKeyCredential); return generateBlobSASQueryParametersUDK20181109(blobSASSignatureValues, userDelegationKeyCredential);
} }
} }
} }
if (version3 >= "2015-04-05") { if (version4 >= "2015-04-05") {
if (sharedKeyCredential !== void 0) { if (sharedKeyCredential !== void 0) {
return generateBlobSASQueryParameters20150405(blobSASSignatureValues, sharedKeyCredential); return generateBlobSASQueryParameters20150405(blobSASSignatureValues, sharedKeyCredential);
} else { } else {
@@ -55368,44 +55368,44 @@ function getCanonicalName(accountName, containerName, blobName) {
return elements.join(""); return elements.join("");
} }
function SASSignatureValuesSanityCheckAndAutofill(blobSASSignatureValues) { function SASSignatureValuesSanityCheckAndAutofill(blobSASSignatureValues) {
const version3 = blobSASSignatureValues.version ? blobSASSignatureValues.version : SERVICE_VERSION; const version4 = blobSASSignatureValues.version ? blobSASSignatureValues.version : SERVICE_VERSION;
if (blobSASSignatureValues.snapshotTime && version3 < "2018-11-09") { if (blobSASSignatureValues.snapshotTime && version4 < "2018-11-09") {
throw RangeError("'version' must be >= '2018-11-09' when providing 'snapshotTime'."); throw RangeError("'version' must be >= '2018-11-09' when providing 'snapshotTime'.");
} }
if (blobSASSignatureValues.blobName === void 0 && blobSASSignatureValues.snapshotTime) { if (blobSASSignatureValues.blobName === void 0 && blobSASSignatureValues.snapshotTime) {
throw RangeError("Must provide 'blobName' when providing 'snapshotTime'."); throw RangeError("Must provide 'blobName' when providing 'snapshotTime'.");
} }
if (blobSASSignatureValues.versionId && version3 < "2019-10-10") { if (blobSASSignatureValues.versionId && version4 < "2019-10-10") {
throw RangeError("'version' must be >= '2019-10-10' when providing 'versionId'."); throw RangeError("'version' must be >= '2019-10-10' when providing 'versionId'.");
} }
if (blobSASSignatureValues.blobName === void 0 && blobSASSignatureValues.versionId) { if (blobSASSignatureValues.blobName === void 0 && blobSASSignatureValues.versionId) {
throw RangeError("Must provide 'blobName' when providing 'versionId'."); throw RangeError("Must provide 'blobName' when providing 'versionId'.");
} }
if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.setImmutabilityPolicy && version3 < "2020-08-04") { if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.setImmutabilityPolicy && version4 < "2020-08-04") {
throw RangeError("'version' must be >= '2020-08-04' when provided 'i' permission."); throw RangeError("'version' must be >= '2020-08-04' when provided 'i' permission.");
} }
if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.deleteVersion && version3 < "2019-10-10") { if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.deleteVersion && version4 < "2019-10-10") {
throw RangeError("'version' must be >= '2019-10-10' when providing 'x' permission."); throw RangeError("'version' must be >= '2019-10-10' when providing 'x' permission.");
} }
if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.permanentDelete && version3 < "2019-10-10") { if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.permanentDelete && version4 < "2019-10-10") {
throw RangeError("'version' must be >= '2019-10-10' when providing 'y' permission."); throw RangeError("'version' must be >= '2019-10-10' when providing 'y' permission.");
} }
if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.tag && version3 < "2019-12-12") { if (blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.tag && version4 < "2019-12-12") {
throw RangeError("'version' must be >= '2019-12-12' when providing 't' permission."); throw RangeError("'version' must be >= '2019-12-12' when providing 't' permission.");
} }
if (version3 < "2020-02-10" && blobSASSignatureValues.permissions && (blobSASSignatureValues.permissions.move || blobSASSignatureValues.permissions.execute)) { if (version4 < "2020-02-10" && blobSASSignatureValues.permissions && (blobSASSignatureValues.permissions.move || blobSASSignatureValues.permissions.execute)) {
throw RangeError("'version' must be >= '2020-02-10' when providing the 'm' or 'e' permission."); throw RangeError("'version' must be >= '2020-02-10' when providing the 'm' or 'e' permission.");
} }
if (version3 < "2021-04-10" && blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.filterByTags) { if (version4 < "2021-04-10" && blobSASSignatureValues.permissions && blobSASSignatureValues.permissions.filterByTags) {
throw RangeError("'version' must be >= '2021-04-10' when providing the 'f' permission."); throw RangeError("'version' must be >= '2021-04-10' when providing the 'f' permission.");
} }
if (version3 < "2020-02-10" && (blobSASSignatureValues.preauthorizedAgentObjectId || blobSASSignatureValues.correlationId)) { if (version4 < "2020-02-10" && (blobSASSignatureValues.preauthorizedAgentObjectId || blobSASSignatureValues.correlationId)) {
throw RangeError("'version' must be >= '2020-02-10' when providing 'preauthorizedAgentObjectId' or 'correlationId'."); throw RangeError("'version' must be >= '2020-02-10' when providing 'preauthorizedAgentObjectId' or 'correlationId'.");
} }
if (blobSASSignatureValues.encryptionScope && version3 < "2020-12-06") { if (blobSASSignatureValues.encryptionScope && version4 < "2020-12-06") {
throw RangeError("'version' must be >= '2020-12-06' when provided 'encryptionScope' in SAS."); throw RangeError("'version' must be >= '2020-12-06' when provided 'encryptionScope' in SAS.");
} }
blobSASSignatureValues.version = version3; blobSASSignatureValues.version = version4;
return blobSASSignatureValues; return blobSASSignatureValues;
} }
@@ -60801,14 +60801,14 @@ function getCacheServiceVersion() {
return process.env["ACTIONS_CACHE_SERVICE_V2"] ? "v2" : "v1"; return process.env["ACTIONS_CACHE_SERVICE_V2"] ? "v2" : "v1";
} }
function getCacheServiceURL() { function getCacheServiceURL() {
const version3 = getCacheServiceVersion(); const version4 = getCacheServiceVersion();
switch (version3) { switch (version4) {
case "v1": case "v1":
return process.env["ACTIONS_CACHE_URL"] || process.env["ACTIONS_RESULTS_URL"] || ""; return process.env["ACTIONS_CACHE_URL"] || process.env["ACTIONS_RESULTS_URL"] || "";
case "v2": case "v2":
return process.env["ACTIONS_RESULTS_URL"] || ""; return process.env["ACTIONS_RESULTS_URL"] || "";
default: default:
throw new Error(`Unsupported cache service version: ${version3}`); throw new Error(`Unsupported cache service version: ${version4}`);
} }
} }
@@ -60874,10 +60874,10 @@ function createHttpClient() {
function reserveCache(key, paths, options) { function reserveCache(key, paths, options) {
return __awaiter13(this, void 0, void 0, function* () { return __awaiter13(this, void 0, void 0, function* () {
const httpClient = createHttpClient(); const httpClient = createHttpClient();
const version3 = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive); const version4 = getCacheVersion(paths, options === null || options === void 0 ? void 0 : options.compressionMethod, options === null || options === void 0 ? void 0 : options.enableCrossOsArchive);
const reserveCacheRequest = { const reserveCacheRequest = {
key, key,
version: version3, version: version4,
cacheSize: options === null || options === void 0 ? void 0 : options.cacheSize cacheSize: options === null || options === void 0 ? void 0 : options.cacheSize
}; };
const response = yield retryTypedResponse("reserveCache", () => __awaiter13(this, void 0, void 0, function* () { const response = yield retryTypedResponse("reserveCache", () => __awaiter13(this, void 0, void 0, function* () {
@@ -61887,14 +61887,14 @@ function getTarArgs(tarPath_1, compressionMethod_1, type_1) {
const args = [`"${tarPath.path}"`]; const args = [`"${tarPath.path}"`];
const cacheFileName = getCacheFileName(compressionMethod); const cacheFileName = getCacheFileName(compressionMethod);
const tarFile = "cache.tar"; const tarFile = "cache.tar";
const workingDirectory = getWorkingDirectory(); const workingDirectory2 = getWorkingDirectory();
const BSD_TAR_ZSTD = tarPath.type === ArchiveToolType.BSD && compressionMethod !== CompressionMethod.Gzip && IS_WINDOWS8; const BSD_TAR_ZSTD = tarPath.type === ArchiveToolType.BSD && compressionMethod !== CompressionMethod.Gzip && IS_WINDOWS8;
switch (type) { switch (type) {
case "create": case "create":
args.push("--posix", "-cf", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "--exclude", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "-P", "-C", workingDirectory.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "--files-from", ManifestFilename); args.push("--posix", "-cf", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "--exclude", BSD_TAR_ZSTD ? tarFile : cacheFileName.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "-P", "-C", workingDirectory2.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "--files-from", ManifestFilename);
break; break;
case "extract": case "extract":
args.push("-xf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "-P", "-C", workingDirectory.replace(new RegExp(`\\${path9.sep}`, "g"), "/")); args.push("-xf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "-P", "-C", workingDirectory2.replace(new RegExp(`\\${path9.sep}`, "g"), "/"));
break; break;
case "list": case "list":
args.push("-tf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "-P"); args.push("-tf", BSD_TAR_ZSTD ? tarFile : archivePath.replace(new RegExp(`\\${path9.sep}`, "g"), "/"), "-P");
@@ -62177,10 +62177,10 @@ function saveCacheV2(paths_1, key_1, options_1) {
debug(`File Size: ${archiveFileSize}`); debug(`File Size: ${archiveFileSize}`);
options.archiveSizeBytes = archiveFileSize; options.archiveSizeBytes = archiveFileSize;
debug("Reserving Cache"); debug("Reserving Cache");
const version3 = getCacheVersion(paths, compressionMethod, enableCrossOsArchive); const version4 = getCacheVersion(paths, compressionMethod, enableCrossOsArchive);
const request = { const request = {
key, key,
version: version3 version: version4
}; };
let signedUploadUrl; let signedUploadUrl;
try { try {
@@ -62200,7 +62200,7 @@ function saveCacheV2(paths_1, key_1, options_1) {
yield saveCache(cacheId, archivePath, signedUploadUrl, options); yield saveCache(cacheId, archivePath, signedUploadUrl, options);
const finalizeRequest = { const finalizeRequest = {
key, key,
version: version3, version: version4,
sizeBytes: `${archiveFileSize}` sizeBytes: `${archiveFileSize}`
}; };
const finalizeResponse = yield twirpClient.FinalizeCacheEntryUpload(finalizeRequest); const finalizeResponse = yield twirpClient.FinalizeCacheEntryUpload(finalizeRequest);
@@ -62241,30 +62241,6 @@ function saveCacheV2(paths_1, key_1, options_1) {
// src/save-cache.ts // src/save-cache.ts
var pep440 = __toESM(require_pep440(), 1); var pep440 = __toESM(require_pep440(), 1);
// src/utils/logging.ts
var quiet;
function isQuiet() {
if (quiet === void 0) {
quiet = typeof getInput === "function" && getInput("quiet") === "true";
}
return quiet;
}
function info2(msg) {
if (!isQuiet()) {
info(msg);
}
}
var warning2 = warning;
// src/cache/restore-cache.ts
var STATE_CACHE_KEY = "cache-key";
var STATE_CACHE_MATCHED_KEY = "cache-matched-key";
var STATE_PYTHON_CACHE_MATCHED_KEY = "python-cache-matched-key";
// src/utils/constants.ts
var STATE_UV_PATH = "uv-path";
var STATE_UV_VERSION = "uv-version";
// src/utils/inputs.ts // src/utils/inputs.ts
var import_node_path = __toESM(require("node:path"), 1); var import_node_path = __toESM(require("node:path"), 1);
@@ -62342,14 +62318,9 @@ function skipComment(str, ptr) {
} }
function skipVoid(str, ptr, banNewLines, banComments) { function skipVoid(str, ptr, banNewLines, banComments) {
let c; let c;
while (1) { while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n"))
while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n")) ptr++;
ptr++; return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines);
if (banComments || c !== "#")
break;
ptr = skipComment(str, ptr);
}
return ptr;
} }
function skipUntil(str, ptr, sep7, end, banNewLines = false) { function skipUntil(str, ptr, sep7, end, banNewLines = false) {
if (!end) { if (!end) {
@@ -62967,12 +62938,6 @@ function getConfigValueFromTomlFile(filePath, key) {
return void 0; return void 0;
} }
const fileContent = import_node_fs2.default.readFileSync(filePath, "utf-8"); const fileContent = import_node_fs2.default.readFileSync(filePath, "utf-8");
return getConfigValueFromTomlContent(filePath, fileContent, key);
}
function getConfigValueFromTomlContent(filePath, fileContent, key) {
if (!filePath.endsWith(".toml")) {
return void 0;
}
if (filePath.endsWith("pyproject.toml")) { if (filePath.endsWith("pyproject.toml")) {
const tomlContent2 = parse2(fileContent); const tomlContent2 = parse2(fileContent);
return tomlContent2?.tool?.uv?.[key]; return tomlContent2?.tool?.uv?.[key];
@@ -62982,86 +62947,48 @@ function getConfigValueFromTomlContent(filePath, fileContent, key) {
} }
// src/utils/inputs.ts // src/utils/inputs.ts
function loadInputs() { var workingDirectory = getInput("working-directory");
const workingDirectory = getInput("working-directory"); var version3 = getInput("version");
const version3 = getInput("version"); var versionFile = getVersionFile();
const versionFile = getVersionFile(workingDirectory); var pythonVersion = getInput("python-version");
const pythonVersion = getInput("python-version"); var activateEnvironment = getBooleanInput("activate-environment");
const activateEnvironment = getBooleanInput("activate-environment"); var venvPath = getVenvPath();
const noProject = getBooleanInput("no-project"); var checkSum = getInput("checksum");
const venvPath = getVenvPath(workingDirectory, activateEnvironment); var enableCache = getEnableCache();
const checksum = getInput("checksum"); var restoreCache = getInput("restore-cache") === "true";
const enableCache = getEnableCache(); var saveCache3 = getInput("save-cache") === "true";
const restoreCache2 = getInput("restore-cache") === "true"; var cacheSuffix = getInput("cache-suffix") || "";
const saveCache4 = getInput("save-cache") === "true"; var cacheLocalPath = getCacheLocalPath();
const cacheSuffix = getInput("cache-suffix") || ""; var cacheDependencyGlob = getCacheDependencyGlob();
const cacheLocalPath = getCacheLocalPath( var pruneCache = getInput("prune-cache") === "true";
workingDirectory, var cachePython = getInput("cache-python") === "true";
versionFile, var ignoreNothingToCache = getInput("ignore-nothing-to-cache") === "true";
enableCache var ignoreEmptyWorkdir = getInput("ignore-empty-workdir") === "true";
); var toolBinDir = getToolBinDir();
const cacheDependencyGlob = getCacheDependencyGlob(workingDirectory); var toolDir = getToolDir();
const pruneCache2 = getInput("prune-cache") === "true"; var pythonDir = getUvPythonDir();
const cachePython = getInput("cache-python") === "true"; var githubToken = getInput("github-token");
const ignoreNothingToCache = getInput("ignore-nothing-to-cache") === "true"; var manifestFile = getManifestFile();
const ignoreEmptyWorkdir = getInput("ignore-empty-workdir") === "true"; var addProblemMatchers = getInput("add-problem-matchers") === "true";
const toolBinDir = getToolBinDir(workingDirectory); var resolutionStrategy = getResolutionStrategy();
const toolDir = getToolDir(workingDirectory); function getVersionFile() {
const pythonDir = getUvPythonDir();
const githubToken = getInput("github-token");
const manifestFile = getManifestFile();
const downloadFromAstralMirror = getInput("download-from-astral-mirror") === "true";
const addProblemMatchers = getInput("add-problem-matchers") === "true";
const quiet2 = getInput("quiet") === "true";
const resolutionStrategy = getResolutionStrategy();
return {
activateEnvironment,
addProblemMatchers,
cacheDependencyGlob,
cacheLocalPath,
cachePython,
cacheSuffix,
checksum,
downloadFromAstralMirror,
enableCache,
githubToken,
ignoreEmptyWorkdir,
ignoreNothingToCache,
manifestFile,
noProject,
pruneCache: pruneCache2,
pythonDir,
pythonVersion,
quiet: quiet2,
resolutionStrategy,
restoreCache: restoreCache2,
saveCache: saveCache4,
toolBinDir,
toolDir,
venvPath,
version: version3,
versionFile,
workingDirectory
};
}
function getVersionFile(workingDirectory) {
const versionFileInput = getInput("version-file"); const versionFileInput = getInput("version-file");
if (versionFileInput !== "") { if (versionFileInput !== "") {
const tildeExpanded = expandTilde(versionFileInput); const tildeExpanded = expandTilde(versionFileInput);
return resolveRelativePath(workingDirectory, tildeExpanded); return resolveRelativePath(tildeExpanded);
} }
return versionFileInput; return versionFileInput;
} }
function getVenvPath(workingDirectory, activateEnvironment) { function getVenvPath() {
const venvPathInput = getInput("venv-path"); const venvPathInput = getInput("venv-path");
if (venvPathInput !== "") { if (venvPathInput !== "") {
if (!activateEnvironment) { if (!activateEnvironment) {
warning2("venv-path is only used when activate-environment is true"); warning("venv-path is only used when activate-environment is true");
} }
const tildeExpanded = expandTilde(venvPathInput); const tildeExpanded = expandTilde(venvPathInput);
return normalizePath(resolveRelativePath(workingDirectory, tildeExpanded)); return normalizePath(resolveRelativePath(tildeExpanded));
} }
return normalizePath(resolveRelativePath(workingDirectory, ".venv")); return normalizePath(resolveRelativePath(".venv"));
} }
function getEnableCache() { function getEnableCache() {
const enableCacheInput = getInput("enable-cache"); const enableCacheInput = getInput("enable-cache");
@@ -63070,11 +62997,11 @@ function getEnableCache() {
} }
return enableCacheInput === "true"; return enableCacheInput === "true";
} }
function getToolBinDir(workingDirectory) { function getToolBinDir() {
const toolBinDirInput = getInput("tool-bin-dir"); const toolBinDirInput = getInput("tool-bin-dir");
if (toolBinDirInput !== "") { if (toolBinDirInput !== "") {
const tildeExpanded = expandTilde(toolBinDirInput); const tildeExpanded = expandTilde(toolBinDirInput);
return resolveRelativePath(workingDirectory, tildeExpanded); return resolveRelativePath(tildeExpanded);
} }
if (process.platform === "win32") { if (process.platform === "win32") {
if (process.env.RUNNER_TEMP !== void 0) { if (process.env.RUNNER_TEMP !== void 0) {
@@ -63086,11 +63013,11 @@ function getToolBinDir(workingDirectory) {
} }
return void 0; return void 0;
} }
function getToolDir(workingDirectory) { function getToolDir() {
const toolDirInput = getInput("tool-dir"); const toolDirInput = getInput("tool-dir");
if (toolDirInput !== "") { if (toolDirInput !== "") {
const tildeExpanded = expandTilde(toolDirInput); const tildeExpanded = expandTilde(toolDirInput);
return resolveRelativePath(workingDirectory, tildeExpanded); return resolveRelativePath(tildeExpanded);
} }
if (process.platform === "win32") { if (process.platform === "win32") {
if (process.env.RUNNER_TEMP !== void 0) { if (process.env.RUNNER_TEMP !== void 0) {
@@ -63102,27 +63029,24 @@ function getToolDir(workingDirectory) {
} }
return void 0; return void 0;
} }
function getCacheLocalPath(workingDirectory, versionFile, enableCache) { function getCacheLocalPath() {
const cacheLocalPathInput = getInput("cache-local-path"); const cacheLocalPathInput = getInput("cache-local-path");
if (cacheLocalPathInput !== "") { if (cacheLocalPathInput !== "") {
const tildeExpanded = expandTilde(cacheLocalPathInput); const tildeExpanded = expandTilde(cacheLocalPathInput);
return { return {
path: resolveRelativePath(workingDirectory, tildeExpanded), path: resolveRelativePath(tildeExpanded),
source: 0 /* Input */ source: 0 /* Input */
}; };
} }
const cacheDirFromConfig = getCacheDirFromConfig( const cacheDirFromConfig = getCacheDirFromConfig();
workingDirectory,
versionFile
);
if (cacheDirFromConfig !== void 0) { if (cacheDirFromConfig !== void 0) {
return { path: cacheDirFromConfig, source: 1 /* Config */ }; return { path: cacheDirFromConfig, source: 1 /* Config */ };
} }
if (process.env.UV_CACHE_DIR !== void 0) { if (process.env.UV_CACHE_DIR !== void 0) {
info2(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`); info(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`);
return { path: process.env.UV_CACHE_DIR, source: 2 /* Env */ }; return { path: process.env.UV_CACHE_DIR, source: 2 /* Env */ };
} }
if (enableCache) { if (getEnableCache()) {
if (process.env.RUNNER_ENVIRONMENT === "github-hosted") { if (process.env.RUNNER_ENVIRONMENT === "github-hosted") {
if (process.env.RUNNER_TEMP !== void 0) { if (process.env.RUNNER_TEMP !== void 0) {
return { return {
@@ -63146,18 +63070,18 @@ function getCacheLocalPath(workingDirectory, versionFile, enableCache) {
}; };
} }
} }
function getCacheDirFromConfig(workingDirectory, versionFile) { function getCacheDirFromConfig() {
for (const filePath of [versionFile, "uv.toml", "pyproject.toml"]) { for (const filePath of [versionFile, "uv.toml", "pyproject.toml"]) {
const resolvedPath = resolveRelativePath(workingDirectory, filePath); const resolvedPath = resolveRelativePath(filePath);
try { try {
const cacheDir = getConfigValueFromTomlFile(resolvedPath, "cache-dir"); const cacheDir = getConfigValueFromTomlFile(resolvedPath, "cache-dir");
if (cacheDir !== void 0) { if (cacheDir !== void 0) {
info2(`Found cache-dir in ${resolvedPath}: ${cacheDir}`); info(`Found cache-dir in ${resolvedPath}: ${cacheDir}`);
return cacheDir; return cacheDir;
} }
} catch (err) { } catch (err) {
const message = err.message; const message = err.message;
warning2(`Error while parsing ${filePath}: ${message}`); warning(`Error while parsing ${filePath}: ${message}`);
return void 0; return void 0;
} }
} }
@@ -63165,7 +63089,7 @@ function getCacheDirFromConfig(workingDirectory, versionFile) {
} }
function getUvPythonDir() { function getUvPythonDir() {
if (process.env.UV_PYTHON_INSTALL_DIR !== void 0) { if (process.env.UV_PYTHON_INSTALL_DIR !== void 0) {
info2( info(
`UV_PYTHON_INSTALL_DIR is already set to ${process.env.UV_PYTHON_INSTALL_DIR}` `UV_PYTHON_INSTALL_DIR is already set to ${process.env.UV_PYTHON_INSTALL_DIR}`
); );
return process.env.UV_PYTHON_INSTALL_DIR; return process.env.UV_PYTHON_INSTALL_DIR;
@@ -63173,8 +63097,9 @@ function getUvPythonDir() {
if (process.env.RUNNER_ENVIRONMENT !== "github-hosted") { if (process.env.RUNNER_ENVIRONMENT !== "github-hosted") {
if (process.platform === "win32") { if (process.platform === "win32") {
return `${process.env.APPDATA}${import_node_path.default.sep}uv${import_node_path.default.sep}python`; return `${process.env.APPDATA}${import_node_path.default.sep}uv${import_node_path.default.sep}python`;
} else {
return `${process.env.HOME}${import_node_path.default.sep}.local${import_node_path.default.sep}share${import_node_path.default.sep}uv${import_node_path.default.sep}python`;
} }
return `${process.env.HOME}${import_node_path.default.sep}.local${import_node_path.default.sep}share${import_node_path.default.sep}uv${import_node_path.default.sep}python`;
} }
if (process.env.RUNNER_TEMP !== void 0) { if (process.env.RUNNER_TEMP !== void 0) {
return `${process.env.RUNNER_TEMP}${import_node_path.default.sep}uv-python-dir`; return `${process.env.RUNNER_TEMP}${import_node_path.default.sep}uv-python-dir`;
@@ -63183,10 +63108,10 @@ function getUvPythonDir() {
"Could not determine UV_PYTHON_INSTALL_DIR. Please make sure RUNNER_TEMP is set or provide the UV_PYTHON_INSTALL_DIR environment variable" "Could not determine UV_PYTHON_INSTALL_DIR. Please make sure RUNNER_TEMP is set or provide the UV_PYTHON_INSTALL_DIR environment variable"
); );
} }
function getCacheDependencyGlob(workingDirectory) { function getCacheDependencyGlob() {
const cacheDependencyGlobInput = getInput("cache-dependency-glob"); const cacheDependencyGlobInput = getInput("cache-dependency-glob");
if (cacheDependencyGlobInput !== "") { if (cacheDependencyGlobInput !== "") {
return cacheDependencyGlobInput.split("\n").map((part) => part.trim()).map((part) => expandTilde(part)).map((part) => resolveRelativePath(workingDirectory, part)).join("\n"); return cacheDependencyGlobInput.split("\n").map((part) => part.trim()).map((part) => expandTilde(part)).map((part) => resolveRelativePath(part)).join("\n");
} }
return cacheDependencyGlobInput; return cacheDependencyGlobInput;
} }
@@ -63205,7 +63130,7 @@ function normalizePath(inputPath) {
} }
return trimmed; return trimmed;
} }
function resolveRelativePath(workingDirectory, inputPath) { function resolveRelativePath(inputPath) {
const hasNegation = inputPath.startsWith("!"); const hasNegation = inputPath.startsWith("!");
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath; const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
const resolvedPath = import_node_path.default.resolve(workingDirectory, pathWithoutNegation); const resolvedPath = import_node_path.default.resolve(workingDirectory, pathWithoutNegation);
@@ -63234,33 +63159,25 @@ function getResolutionStrategy() {
); );
} }
// src/cache/restore-cache.ts
var STATE_CACHE_KEY = "cache-key";
var STATE_CACHE_MATCHED_KEY = "cache-matched-key";
var STATE_PYTHON_CACHE_MATCHED_KEY = "python-cache-matched-key";
// src/utils/constants.ts
var STATE_UV_PATH = "uv-path";
var STATE_UV_VERSION = "uv-version";
// src/save-cache.ts // src/save-cache.ts
function formatUnexpectedFailure(error2) {
if (error2 instanceof Error) {
return error2.stack ?? error2.message;
}
return String(error2);
}
function failUnexpectedly(event, error2) {
setFailed(`${event}: ${formatUnexpectedFailure(error2)}`);
process.exit(1);
}
process.on("uncaughtException", (error2) => {
failUnexpectedly("Uncaught exception", error2);
});
process.on("unhandledRejection", (reason) => {
failUnexpectedly("Unhandled promise rejection", reason);
});
async function run() { async function run() {
try { try {
const inputs = loadInputs(); if (enableCache) {
if (inputs.enableCache) { if (saveCache3) {
if (inputs.saveCache) { await saveCache4();
await saveCache3(inputs);
} else { } else {
info2("save-cache is false. Skipping save cache step."); info("save-cache is false. Skipping save cache step.");
} }
await new Promise((resolve2) => setTimeout(resolve2, 100)); await new Promise((resolve2) => setTimeout(resolve2, 50));
process.exit(0); process.exit(0);
} }
} catch (error2) { } catch (error2) {
@@ -63268,23 +63185,23 @@ async function run() {
setFailed(err.message); setFailed(err.message);
} }
} }
async function saveCache3(inputs) { async function saveCache4() {
const cacheKey = getState(STATE_CACHE_KEY); const cacheKey = getState(STATE_CACHE_KEY);
const matchedKey = getState(STATE_CACHE_MATCHED_KEY); const matchedKey = getState(STATE_CACHE_MATCHED_KEY);
if (!cacheKey) { if (!cacheKey) {
warning2("Error retrieving cache key from state."); warning("Error retrieving cache key from state.");
return; return;
} }
if (matchedKey === cacheKey) { if (matchedKey === cacheKey) {
info2(`Cache hit occurred on key ${cacheKey}, not saving cache.`); info(`Cache hit occurred on key ${cacheKey}, not saving cache.`);
} else { } else {
if (inputs.pruneCache) { if (pruneCache) {
await pruneCache(); await pruneCache2();
} }
const actualCachePath = getUvCachePath(inputs); const actualCachePath = getUvCachePath();
if (!fs7.existsSync(actualCachePath)) { if (!fs7.existsSync(actualCachePath)) {
if (inputs.ignoreNothingToCache) { if (ignoreNothingToCache) {
info2( info(
"No cacheable uv cache paths were found. Ignoring because ignore-nothing-to-cache is enabled." "No cacheable uv cache paths were found. Ignoring because ignore-nothing-to-cache is enabled."
); );
} else { } else {
@@ -63301,23 +63218,23 @@ async function saveCache3(inputs) {
); );
} }
} }
if (inputs.cachePython) { if (cachePython) {
if (!fs7.existsSync(inputs.pythonDir)) { if (!fs7.existsSync(pythonDir)) {
warning2( warning(
`Python cache path ${inputs.pythonDir} does not exist on disk. Skipping Python cache save because no managed Python installation was found. If you want uv to install managed Python instead of using a system interpreter, set UV_PYTHON_PREFERENCE=only-managed.` `Python cache path ${pythonDir} does not exist on disk. Skipping Python cache save because no managed Python installation was found. If you want uv to install managed Python instead of using a system interpreter, set UV_PYTHON_PREFERENCE=only-managed.`
); );
return; return;
} }
const pythonCacheKey = `${cacheKey}-python`; const pythonCacheKey = `${cacheKey}-python`;
await saveCacheToKey( await saveCacheToKey(
pythonCacheKey, pythonCacheKey,
inputs.pythonDir, pythonDir,
STATE_PYTHON_CACHE_MATCHED_KEY, STATE_PYTHON_CACHE_MATCHED_KEY,
"Python cache" "Python cache"
); );
} }
} }
async function pruneCache() { async function pruneCache2() {
const forceSupported = pep440.gte(getState(STATE_UV_VERSION), "0.8.24"); const forceSupported = pep440.gte(getState(STATE_UV_VERSION), "0.8.24");
const options = { const options = {
silent: false silent: false
@@ -63326,33 +63243,35 @@ async function pruneCache() {
if (forceSupported) { if (forceSupported) {
execArgs.push("--force"); execArgs.push("--force");
} }
info2("Pruning cache..."); info("Pruning cache...");
const uvPath = getState(STATE_UV_PATH); const uvPath = getState(STATE_UV_PATH);
await exec(uvPath, execArgs, options); await exec(uvPath, execArgs, options);
} }
function getUvCachePath(inputs) { function getUvCachePath() {
if (inputs.cacheLocalPath === void 0) { if (cacheLocalPath === void 0) {
throw new Error( throw new Error(
"cache-local-path is not set. Cannot save cache without a valid cache path." "cache-local-path is not set. Cannot save cache without a valid cache path."
); );
} }
if (process.env.UV_CACHE_DIR && process.env.UV_CACHE_DIR !== inputs.cacheLocalPath.path) { if (process.env.UV_CACHE_DIR && process.env.UV_CACHE_DIR !== cacheLocalPath.path) {
warning2( warning(
`The environment variable UV_CACHE_DIR has been changed to "${process.env.UV_CACHE_DIR}", by an action or step running after astral-sh/setup-uv. This can lead to unexpected behavior. If you expected this to happen set the cache-local-path input to "${process.env.UV_CACHE_DIR}" instead of "${inputs.cacheLocalPath.path}".` `The environment variable UV_CACHE_DIR has been changed to "${process.env.UV_CACHE_DIR}", by an action or step running after astral-sh/setup-uv. This can lead to unexpected behavior. If you expected this to happen set the cache-local-path input to "${process.env.UV_CACHE_DIR}" instead of "${cacheLocalPath.path}".`
); );
return process.env.UV_CACHE_DIR; return process.env.UV_CACHE_DIR;
} }
return inputs.cacheLocalPath.path; return cacheLocalPath.path;
} }
async function saveCacheToKey(cacheKey, cachePath, stateKey, cacheName) { async function saveCacheToKey(cacheKey, cachePath, stateKey, cacheName) {
const matchedKey = getState(stateKey); const matchedKey = getState(stateKey);
if (matchedKey === cacheKey) { if (matchedKey === cacheKey) {
info2(`${cacheName} hit occurred on key ${cacheKey}, not saving cache.`); info(
`${cacheName} hit occurred on key ${cacheKey}, not saving cache.`
);
return; return;
} }
info2(`Including ${cacheName} path: ${cachePath}`); info(`Including ${cacheName} path: ${cachePath}`);
await saveCache2([cachePath], cacheKey); await saveCache2([cachePath], cacheKey);
info2(`${cacheName} saved with key: ${cacheKey}`); info(`${cacheName} saved with key: ${cacheKey}`);
} }
run(); run();
// Annotate the CommonJS export names for ESM import in node: // Annotate the CommonJS export names for ESM import in node:

12094
dist/setup/index.cjs generated vendored

File diff suppressed because one or more lines are too long

5162
dist/update-known-checksums/index.cjs generated vendored

File diff suppressed because one or more lines are too long

View File

@@ -6,7 +6,7 @@ This document covers advanced options for configuring which version of uv to ins
```yaml ```yaml
- name: Install the latest version of uv - name: Install the latest version of uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version: "latest" version: "latest"
``` ```
@@ -15,7 +15,7 @@ This document covers advanced options for configuring which version of uv to ins
```yaml ```yaml
- name: Install a specific version of uv - name: Install a specific version of uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version: "0.4.4" version: "0.4.4"
``` ```
@@ -28,21 +28,21 @@ 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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version: "0.4.x" version: "0.4.x"
``` ```
```yaml ```yaml
- name: Install a pep440-specifier-satisfying version of uv - name: Install a pep440-specifier-satisfying version of uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version: ">=0.4.25,<0.5" version: ">=0.4.25,<0.5"
``` ```
@@ -54,7 +54,7 @@ You can change this behavior using the `resolution-strategy` input:
```yaml ```yaml
- name: Install the lowest compatible version of uv - name: Install the lowest compatible version of uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version: ">=0.4.0" version: ">=0.4.0"
resolution-strategy: "lowest" resolution-strategy: "lowest"
@@ -76,7 +76,7 @@ uv defined as a dependency in `pyproject.toml` or `requirements.txt`.
```yaml ```yaml
- name: Install uv based on the version defined in pyproject.toml - name: Install uv based on the version defined in pyproject.toml
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version-file: "pyproject.toml" version-file: "pyproject.toml"
``` ```

View File

@@ -23,7 +23,7 @@ The computed cache key is available as the `cache-key` output:
```yaml ```yaml
- name: Setup uv - name: Setup uv
id: setup-uv id: setup-uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
- name: Print cache key - name: Print cache key
@@ -50,7 +50,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
cache-suffix: "optional-suffix" cache-suffix: "optional-suffix"
@@ -89,7 +89,7 @@ changes. If you use relative paths, they are relative to the working directory.
```yaml ```yaml
- name: Define a cache dependency glob - name: Define a cache dependency glob
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
cache-dependency-glob: "**/pyproject.toml" cache-dependency-glob: "**/pyproject.toml"
@@ -97,7 +97,7 @@ changes. If you use relative paths, they are relative to the working directory.
```yaml ```yaml
- name: Define a list of cache dependency globs - name: Define a list of cache dependency globs
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
cache-dependency-glob: | cache-dependency-glob: |
@@ -107,7 +107,7 @@ changes. If you use relative paths, they are relative to the working directory.
```yaml ```yaml
- name: Define an absolute cache dependency glob - name: Define an absolute cache dependency glob
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
cache-dependency-glob: "/tmp/my-folder/requirements*.txt" cache-dependency-glob: "/tmp/my-folder/requirements*.txt"
@@ -115,7 +115,7 @@ changes. If you use relative paths, they are relative to the working directory.
```yaml ```yaml
- name: Never invalidate the cache - name: Never invalidate the cache
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
cache-dependency-glob: "" cache-dependency-glob: ""
@@ -128,7 +128,7 @@ By default, the cache will be restored.
```yaml ```yaml
- name: Don't restore an existing cache - name: Don't restore an existing cache
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
restore-cache: false restore-cache: false
@@ -142,7 +142,7 @@ By default, the cache will be saved.
```yaml ```yaml
- name: Don't save the cache after the run - name: Don't save the cache after the run
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
save-cache: false save-cache: false
@@ -168,7 +168,7 @@ It defaults to `setup-uv-cache` in the `TMP` dir, `D:\a\_temp\setup-uv-cache` on
```yaml ```yaml
- name: Define a custom uv cache path - name: Define a custom uv cache path
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
cache-local-path: "/path/to/cache" cache-local-path: "/path/to/cache"
``` ```
@@ -187,7 +187,7 @@ 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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
prune-cache: false prune-cache: false
@@ -205,7 +205,7 @@ To force managed Python installs, set `UV_PYTHON_PREFERENCE=only-managed`.
```yaml ```yaml
- name: Cache Python installs - name: Cache Python installs
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
cache-python: true cache-python: true
@@ -213,17 +213,12 @@ To force managed Python installs, set `UV_PYTHON_PREFERENCE=only-managed`.
## Ignore nothing to cache ## 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) with an error like By default, the action will fail if caching is enabled but there is nothing to upload (the uv cache directory does not exist).
```console
Error: Cache path /home/runner/.cache/uv 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.
```
If you want to ignore this, set the `ignore-nothing-to-cache` input to `true`. If you want to ignore this, set the `ignore-nothing-to-cache` input to `true`.
```yaml ```yaml
- name: Ignore nothing to cache - name: Ignore nothing to cache
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
enable-cache: true enable-cache: true
ignore-nothing-to-cache: true ignore-nothing-to-cache: true

View File

@@ -10,7 +10,7 @@ are automatically verified by this action. The sha256 hashes can be found on the
```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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
version: "0.3.1" version: "0.3.1"
checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8" checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
@@ -19,14 +19,14 @@ are automatically verified by this action. The sha256 hashes can be found on the
## Manifest file ## Manifest file
By default, setup-uv reads version metadata from By default, setup-uv reads version metadata from
[`astral-sh/versions`](https://github.com/astral-sh/versions). [`astral-sh/versions`](https://github.com/astral-sh/versions) (NDJSON format).
The `manifest-file` input lets you override that source with your own URL, for example to test The `manifest-file` input lets you override that source with your own URL, for example to test
custom uv builds or alternate download locations. custom uv builds or alternate download locations.
### Format ### Format
The manifest file must use the same format as `astral-sh/versions`: one JSON object per line, where each object represents a version and its artifacts. The versions must be sorted in descending order. For example: The manifest file must be in NDJSON format, where each line is a JSON object representing a version and its artifacts. For example:
```json ```json
{"version":"0.10.7","artifacts":[{"platform":"x86_64-unknown-linux-gnu","variant":"default","url":"https://example.com/uv-x86_64-unknown-linux-gnu.tar.gz","archive_format":"tar.gz","sha256":"..."}]} {"version":"0.10.7","artifacts":[{"platform":"x86_64-unknown-linux-gnu","variant":"default","url":"https://example.com/uv-x86_64-unknown-linux-gnu.tar.gz","archive_format":"tar.gz","sha256":"..."}]}
@@ -37,9 +37,26 @@ setup-uv currently only supports `default` as the `variant`.
The `archive_format` field is currently ignored. The `archive_format` field is currently ignored.
### Legacy format: JSON array (deprecated)
The previous JSON array format is still supported for compatibility, but deprecated and will be
removed in a future major release.
```json
[
{
"version": "0.7.13",
"artifactName": "uv-aarch64-apple-darwin.tar.gz",
"arch": "aarch64",
"platform": "apple-darwin",
"downloadUrl": "https://github.com/astral-sh/uv/releases/download/0.7.13/uv-aarch64-apple-darwin.tar.gz"
}
]
```
```yaml ```yaml
- name: Use a custom manifest file - name: Use a custom manifest file
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
manifest-file: "https://example.com/my-custom-manifest.ndjson" manifest-file: "https://example.com/my-custom-manifest.ndjson"
``` ```
@@ -58,7 +75,7 @@ You can disable this by setting the `add-problem-matchers` input to `false`.
```yaml ```yaml
- name: Install the latest version of uv without problem matchers - name: Install the latest version of uv without problem matchers
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
add-problem-matchers: false add-problem-matchers: false
``` ```

View File

@@ -9,7 +9,7 @@ This allows directly using it in later steps:
```yaml ```yaml
- name: Install the latest version of uv and activate the environment - name: Install the latest version of uv and activate the environment
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
activate-environment: true activate-environment: true
- run: uv pip install pip - run: uv pip install pip
@@ -20,7 +20,7 @@ By default, the venv is created at `.venv` inside the `working-directory`.
You can customize the venv location with `venv-path`, for example to place it in the runner temp directory: You can customize the venv location with `venv-path`, for example to place it in the runner temp directory:
```yaml ```yaml
- uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 - uses: astral-sh/setup-uv@v7
with: with:
activate-environment: true activate-environment: true
venv-path: ${{ runner.temp }}/custom-venv venv-path: ${{ runner.temp }}/custom-venv
@@ -51,7 +51,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }} github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
``` ```
@@ -69,7 +69,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
tool-dir: "/path/to/tool/dir" tool-dir: "/path/to/tool/dir"
``` ```
@@ -88,7 +88,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
tool-bin-dir: "/path/to/tool-bin/dir" tool-bin-dir: "/path/to/tool-bin/dir"
``` ```
@@ -105,7 +105,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@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
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"
@@ -122,7 +122,7 @@ If you want to ignore this, set the `ignore-empty-workdir` input to `true`.
```yaml ```yaml
- name: Ignore empty workdir - name: Ignore empty workdir
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
ignore-empty-workdir: true ignore-empty-workdir: true
``` ```
@@ -145,7 +145,7 @@ This action sets several environment variables that influence uv's behavior and
```yaml ```yaml
- name: Example using environment variables - name: Example using environment variables
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 uses: astral-sh/setup-uv@v7
with: with:
python-version: "3.12" python-version: "3.12"
tool-dir: "/custom/tool/dir" tool-dir: "/custom/tool/dir"

659
package-lock.json generated
View File

@@ -16,19 +16,19 @@
"@actions/io": "^3.0.2", "@actions/io": "^3.0.2",
"@actions/tool-cache": "^4.0.0", "@actions/tool-cache": "^4.0.0",
"@renovatebot/pep440": "^4.2.2", "@renovatebot/pep440": "^4.2.2",
"smol-toml": "^1.6.1", "smol-toml": "^1.6.0",
"undici": "^8.3.0" "undici": "^7.24.2"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^2.4.16", "@biomejs/biome": "^2.4.7",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^25.5.0", "@types/node": "^25.5.0",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"@vercel/ncc": "^0.38.4", "@vercel/ncc": "^0.38.4",
"esbuild": "^0.28.0", "esbuild": "^0.27.4",
"jest": "^30.3.0", "jest": "^30.3.0",
"js-yaml": "^4.1.1", "js-yaml": "^4.1.1",
"ts-jest": "^29.4.11", "ts-jest": "^29.4.6",
"typescript": "^5.9.3" "typescript": "^5.9.3"
} }
}, },
@@ -863,10 +863,11 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@biomejs/biome": { "node_modules/@biomejs/biome": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.7.tgz",
"integrity": "sha512-x9ajFh1zChVybCiM3TN6OD4phAqLgtPZjFrZF+aTMYCPjwBO+k529TX7PPsAqtGNLeV4UgzwQnowEgS7bGmzcA==", "integrity": "sha512-vXrgcmNGZ4lpdwZSpMf1hWw1aWS6B+SyeSYKTLrNsiUsAdSRN0J4d/7mF3ogJFbIwFFSOL3wT92Zzxia/d5/ng==",
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"bin": { "bin": {
"biome": "bin/biome" "biome": "bin/biome"
}, },
@@ -878,24 +879,25 @@
"url": "https://opencollective.com/biome" "url": "https://opencollective.com/biome"
}, },
"optionalDependencies": { "optionalDependencies": {
"@biomejs/cli-darwin-arm64": "2.4.16", "@biomejs/cli-darwin-arm64": "2.4.7",
"@biomejs/cli-darwin-x64": "2.4.16", "@biomejs/cli-darwin-x64": "2.4.7",
"@biomejs/cli-linux-arm64": "2.4.16", "@biomejs/cli-linux-arm64": "2.4.7",
"@biomejs/cli-linux-arm64-musl": "2.4.16", "@biomejs/cli-linux-arm64-musl": "2.4.7",
"@biomejs/cli-linux-x64": "2.4.16", "@biomejs/cli-linux-x64": "2.4.7",
"@biomejs/cli-linux-x64-musl": "2.4.16", "@biomejs/cli-linux-x64-musl": "2.4.7",
"@biomejs/cli-win32-arm64": "2.4.16", "@biomejs/cli-win32-arm64": "2.4.7",
"@biomejs/cli-win32-x64": "2.4.16" "@biomejs/cli-win32-x64": "2.4.7"
} }
}, },
"node_modules/@biomejs/cli-darwin-arm64": { "node_modules/@biomejs/cli-darwin-arm64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.7.tgz",
"integrity": "sha512-wxPvu4XOA85YJk9ixSWUmq/QBHbid85BISbOAqqBM/5xQpPk9ayjk5375tOlSC0BeCwNSbPFafQBm+vBumXq0A==", "integrity": "sha512-Oo0cF5mHzmvDmTXw8XSjhCia8K6YrZnk7aCS54+/HxyMdZMruMO3nfpDsrlar/EQWe41r1qrwKiCa2QDYHDzWA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -905,13 +907,14 @@
} }
}, },
"node_modules/@biomejs/cli-darwin-x64": { "node_modules/@biomejs/cli-darwin-x64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.7.tgz",
"integrity": "sha512-xFCqGPwYusQJp4N4NJLi1XJiZqjwFdjhT+KqtNy+Ug3qgfczqnTa6MSDvxJF6TkuDLoYJItMapz6tAf7kCekFw==", "integrity": "sha512-I+cOG3sd/7HdFtvDSnF9QQPrWguUH7zrkIMMykM3PtfWU9soTcS2yRb9Myq6MHmzbeCT08D1UmY+BaiMl5CcoQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"darwin" "darwin"
@@ -921,13 +924,14 @@
} }
}, },
"node_modules/@biomejs/cli-linux-arm64": { "node_modules/@biomejs/cli-linux-arm64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.7.tgz",
"integrity": "sha512-2kFb4//jxfZaP6D+Rj5VkHkxgyD9EoRAVBEQb8PKRv+s4NO2zYNJKXFaJmK1CmhufJOWEfpHKaRbOja7qjmdhQ==", "integrity": "sha512-om6FugwmibzfP/6ALj5WRDVSND4H2G9X0nkI1HZpp2ySf9lW2j0X68oQSaHEnls6666oy4KDsc5RFjT4m0kV0w==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -937,13 +941,14 @@
} }
}, },
"node_modules/@biomejs/cli-linux-arm64-musl": { "node_modules/@biomejs/cli-linux-arm64-musl": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.7.tgz",
"integrity": "sha512-oYxnW0ARfJkr72ezzF2OR8N/rtkgLUQeYtF8cFhVswbknHxtTcmzSsanVJP8yQKnGpGpc2ck6c5zLvHahL6Cbg==", "integrity": "sha512-I2NvM9KPb09jWml93O2/5WMfNR7Lee5Latag1JThDRMURVhPX74p9UDnyTw3Ae6cE1DgXfw7sqQgX7rkvpc0vw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -953,13 +958,14 @@
} }
}, },
"node_modules/@biomejs/cli-linux-x64": { "node_modules/@biomejs/cli-linux-x64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.7.tgz",
"integrity": "sha512-NbcBbi/nJqn5baae6wqRXdS7Gadf2uRpehSh6vMSYpG8OhkXl/Xg8aorWrJ+9VWqAT5ml90alLvorkpMW0nBwQ==", "integrity": "sha512-bV8/uo2Tj+gumnk4sUdkerWyCPRabaZdv88IpbmDWARQQoA/Q0YaqPz1a+LSEDIL7OfrnPi9Hq1Llz4ZIGyIQQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -969,13 +975,14 @@
} }
}, },
"node_modules/@biomejs/cli-linux-x64-musl": { "node_modules/@biomejs/cli-linux-x64-musl": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.7.tgz",
"integrity": "sha512-iHDS+MCM65DPqWGu+ECC3uoALyj2H7F4nVUPxIPjz/PIl94EUu+EDfGZDzFP+NY1EOPVt9NQvwFqq7HdMmowdg==", "integrity": "sha512-00kx4YrBMU8374zd2wHuRV5wseh0rom5HqRND+vDldJPrWwQw+mzd/d8byI9hPx926CG+vWzq6AeiT7Yi5y59g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"linux" "linux"
@@ -985,13 +992,14 @@
} }
}, },
"node_modules/@biomejs/cli-win32-arm64": { "node_modules/@biomejs/cli-win32-arm64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.7.tgz",
"integrity": "sha512-0rgImMsNb5v/chhkIFe3wu7PEFClS6RBAYUijGL9UsYN3PanSaoK24HSSuSJb1pYbYYVjzAyZTl3gtjJ84BM8A==", "integrity": "sha512-hOUHBMlFCvDhu3WCq6vaBoG0dp0LkWxSEnEEsxxXvOa9TfT6ZBnbh72A/xBM7CBYB7WgwqboetzFEVDnMxelyw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -1001,13 +1009,14 @@
} }
}, },
"node_modules/@biomejs/cli-win32-x64": { "node_modules/@biomejs/cli-win32-x64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.7.tgz",
"integrity": "sha512-Kp85jgoBHa05gix6UIRjfCDiUV3w/8VIdZ247VyyO2gEjaw12WEVhdIjlxp/AMzXxqxQwbxNTDVZ3Mwd2RG5rw==", "integrity": "sha512-qEpGjSkPC3qX4ycbMUthXvi9CkRq7kZpkqMY1OyhmYlYLnANnooDQ7hDerM8+0NJ+DZKVnsIc07h30XOpt7LtQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
"dev": true, "dev": true,
"license": "MIT OR Apache-2.0",
"optional": true, "optional": true,
"os": [ "os": [
"win32" "win32"
@@ -1051,9 +1060,9 @@
} }
}, },
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
"integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -1068,9 +1077,9 @@
} }
}, },
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
"integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -1085,9 +1094,9 @@
} }
}, },
"node_modules/@esbuild/android-arm64": { "node_modules/@esbuild/android-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
"integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1102,9 +1111,9 @@
} }
}, },
"node_modules/@esbuild/android-x64": { "node_modules/@esbuild/android-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
"integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1119,9 +1128,9 @@
} }
}, },
"node_modules/@esbuild/darwin-arm64": { "node_modules/@esbuild/darwin-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
"integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1136,9 +1145,9 @@
} }
}, },
"node_modules/@esbuild/darwin-x64": { "node_modules/@esbuild/darwin-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
"integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1153,9 +1162,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-arm64": { "node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
"integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1170,9 +1179,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-x64": { "node_modules/@esbuild/freebsd-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
"integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1187,9 +1196,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm": { "node_modules/@esbuild/linux-arm": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
"integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -1204,9 +1213,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm64": { "node_modules/@esbuild/linux-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
"integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1221,9 +1230,9 @@
} }
}, },
"node_modules/@esbuild/linux-ia32": { "node_modules/@esbuild/linux-ia32": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
"integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -1238,9 +1247,9 @@
} }
}, },
"node_modules/@esbuild/linux-loong64": { "node_modules/@esbuild/linux-loong64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
"integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@@ -1255,9 +1264,9 @@
} }
}, },
"node_modules/@esbuild/linux-mips64el": { "node_modules/@esbuild/linux-mips64el": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
"integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
@@ -1272,9 +1281,9 @@
} }
}, },
"node_modules/@esbuild/linux-ppc64": { "node_modules/@esbuild/linux-ppc64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
"integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -1289,9 +1298,9 @@
} }
}, },
"node_modules/@esbuild/linux-riscv64": { "node_modules/@esbuild/linux-riscv64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
"integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -1306,9 +1315,9 @@
} }
}, },
"node_modules/@esbuild/linux-s390x": { "node_modules/@esbuild/linux-s390x": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
"integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -1323,9 +1332,9 @@
} }
}, },
"node_modules/@esbuild/linux-x64": { "node_modules/@esbuild/linux-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
"integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1340,9 +1349,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-arm64": { "node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
"integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1357,9 +1366,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-x64": { "node_modules/@esbuild/netbsd-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
"integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1374,9 +1383,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-arm64": { "node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
"integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1391,9 +1400,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-x64": { "node_modules/@esbuild/openbsd-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
"integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1408,9 +1417,9 @@
} }
}, },
"node_modules/@esbuild/openharmony-arm64": { "node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
"integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1425,9 +1434,9 @@
} }
}, },
"node_modules/@esbuild/sunos-x64": { "node_modules/@esbuild/sunos-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
"integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -1442,9 +1451,9 @@
} }
}, },
"node_modules/@esbuild/win32-arm64": { "node_modules/@esbuild/win32-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
"integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -1459,9 +1468,9 @@
} }
}, },
"node_modules/@esbuild/win32-ia32": { "node_modules/@esbuild/win32-ia32": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
"integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -1476,9 +1485,9 @@
} }
}, },
"node_modules/@esbuild/win32-x64": { "node_modules/@esbuild/win32-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
"integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3055,9 +3064,9 @@
} }
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
@@ -3068,32 +3077,32 @@
"node": ">=18" "node": ">=18"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.0", "@esbuild/aix-ppc64": "0.27.4",
"@esbuild/android-arm": "0.28.0", "@esbuild/android-arm": "0.27.4",
"@esbuild/android-arm64": "0.28.0", "@esbuild/android-arm64": "0.27.4",
"@esbuild/android-x64": "0.28.0", "@esbuild/android-x64": "0.27.4",
"@esbuild/darwin-arm64": "0.28.0", "@esbuild/darwin-arm64": "0.27.4",
"@esbuild/darwin-x64": "0.28.0", "@esbuild/darwin-x64": "0.27.4",
"@esbuild/freebsd-arm64": "0.28.0", "@esbuild/freebsd-arm64": "0.27.4",
"@esbuild/freebsd-x64": "0.28.0", "@esbuild/freebsd-x64": "0.27.4",
"@esbuild/linux-arm": "0.28.0", "@esbuild/linux-arm": "0.27.4",
"@esbuild/linux-arm64": "0.28.0", "@esbuild/linux-arm64": "0.27.4",
"@esbuild/linux-ia32": "0.28.0", "@esbuild/linux-ia32": "0.27.4",
"@esbuild/linux-loong64": "0.28.0", "@esbuild/linux-loong64": "0.27.4",
"@esbuild/linux-mips64el": "0.28.0", "@esbuild/linux-mips64el": "0.27.4",
"@esbuild/linux-ppc64": "0.28.0", "@esbuild/linux-ppc64": "0.27.4",
"@esbuild/linux-riscv64": "0.28.0", "@esbuild/linux-riscv64": "0.27.4",
"@esbuild/linux-s390x": "0.28.0", "@esbuild/linux-s390x": "0.27.4",
"@esbuild/linux-x64": "0.28.0", "@esbuild/linux-x64": "0.27.4",
"@esbuild/netbsd-arm64": "0.28.0", "@esbuild/netbsd-arm64": "0.27.4",
"@esbuild/netbsd-x64": "0.28.0", "@esbuild/netbsd-x64": "0.27.4",
"@esbuild/openbsd-arm64": "0.28.0", "@esbuild/openbsd-arm64": "0.27.4",
"@esbuild/openbsd-x64": "0.28.0", "@esbuild/openbsd-x64": "0.27.4",
"@esbuild/openharmony-arm64": "0.28.0", "@esbuild/openharmony-arm64": "0.27.4",
"@esbuild/sunos-x64": "0.28.0", "@esbuild/sunos-x64": "0.27.4",
"@esbuild/win32-arm64": "0.28.0", "@esbuild/win32-arm64": "0.27.4",
"@esbuild/win32-ia32": "0.28.0", "@esbuild/win32-ia32": "0.27.4",
"@esbuild/win32-x64": "0.28.0" "@esbuild/win32-x64": "0.27.4"
} }
}, },
"node_modules/escalade": { "node_modules/escalade": {
@@ -3397,9 +3406,9 @@
"dev": true "dev": true
}, },
"node_modules/handlebars": { "node_modules/handlebars": {
"version": "4.7.9", "version": "4.7.8",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
"integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4913,9 +4922,9 @@
} }
}, },
"node_modules/smol-toml": { "node_modules/smol-toml": {
"version": "1.6.1", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz",
"integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">= 18" "node": ">= 18"
@@ -5223,19 +5232,19 @@
"dev": true "dev": true
}, },
"node_modules/ts-jest": { "node_modules/ts-jest": {
"version": "29.4.11", "version": "29.4.6",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz",
"integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bs-logger": "^0.2.6", "bs-logger": "^0.2.6",
"fast-json-stable-stringify": "^2.1.0", "fast-json-stable-stringify": "^2.1.0",
"handlebars": "^4.7.9", "handlebars": "^4.7.8",
"json5": "^2.2.3", "json5": "^2.2.3",
"lodash.memoize": "^4.1.2", "lodash.memoize": "^4.1.2",
"make-error": "^1.3.6", "make-error": "^1.3.6",
"semver": "^7.8.0", "semver": "^7.7.3",
"type-fest": "^4.41.0", "type-fest": "^4.41.0",
"yargs-parser": "^21.1.1" "yargs-parser": "^21.1.1"
}, },
@@ -5252,7 +5261,7 @@
"babel-jest": "^29.0.0 || ^30.0.0", "babel-jest": "^29.0.0 || ^30.0.0",
"jest": "^29.0.0 || ^30.0.0", "jest": "^29.0.0 || ^30.0.0",
"jest-util": "^29.0.0 || ^30.0.0", "jest-util": "^29.0.0 || ^30.0.0",
"typescript": ">=4.3 <7" "typescript": ">=4.3 <6"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"@babel/core": { "@babel/core": {
@@ -5276,9 +5285,9 @@
} }
}, },
"node_modules/ts-jest/node_modules/semver": { "node_modules/ts-jest/node_modules/semver": {
"version": "7.8.1", "version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
@@ -5355,12 +5364,12 @@
} }
}, },
"node_modules/undici": { "node_modules/undici": {
"version": "8.3.0", "version": "7.24.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-8.3.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.2.tgz",
"integrity": "sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==", "integrity": "sha512-P9J1HWYV/ajFr8uCqk5QixwiRKmB1wOamgS0e+o2Z4A44Ej2+thFVRLG/eA7qprx88XXhnV5Bl8LHXTURpzB3Q==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=22.19.0" "node": ">=20.18.1"
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
@@ -6293,74 +6302,74 @@
"dev": true "dev": true
}, },
"@biomejs/biome": { "@biomejs/biome": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.4.7.tgz",
"integrity": "sha512-x9ajFh1zChVybCiM3TN6OD4phAqLgtPZjFrZF+aTMYCPjwBO+k529TX7PPsAqtGNLeV4UgzwQnowEgS7bGmzcA==", "integrity": "sha512-vXrgcmNGZ4lpdwZSpMf1hWw1aWS6B+SyeSYKTLrNsiUsAdSRN0J4d/7mF3ogJFbIwFFSOL3wT92Zzxia/d5/ng==",
"dev": true, "dev": true,
"requires": { "requires": {
"@biomejs/cli-darwin-arm64": "2.4.16", "@biomejs/cli-darwin-arm64": "2.4.7",
"@biomejs/cli-darwin-x64": "2.4.16", "@biomejs/cli-darwin-x64": "2.4.7",
"@biomejs/cli-linux-arm64": "2.4.16", "@biomejs/cli-linux-arm64": "2.4.7",
"@biomejs/cli-linux-arm64-musl": "2.4.16", "@biomejs/cli-linux-arm64-musl": "2.4.7",
"@biomejs/cli-linux-x64": "2.4.16", "@biomejs/cli-linux-x64": "2.4.7",
"@biomejs/cli-linux-x64-musl": "2.4.16", "@biomejs/cli-linux-x64-musl": "2.4.7",
"@biomejs/cli-win32-arm64": "2.4.16", "@biomejs/cli-win32-arm64": "2.4.7",
"@biomejs/cli-win32-x64": "2.4.16" "@biomejs/cli-win32-x64": "2.4.7"
} }
}, },
"@biomejs/cli-darwin-arm64": { "@biomejs/cli-darwin-arm64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.4.7.tgz",
"integrity": "sha512-wxPvu4XOA85YJk9ixSWUmq/QBHbid85BISbOAqqBM/5xQpPk9ayjk5375tOlSC0BeCwNSbPFafQBm+vBumXq0A==", "integrity": "sha512-Oo0cF5mHzmvDmTXw8XSjhCia8K6YrZnk7aCS54+/HxyMdZMruMO3nfpDsrlar/EQWe41r1qrwKiCa2QDYHDzWA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-darwin-x64": { "@biomejs/cli-darwin-x64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.4.7.tgz",
"integrity": "sha512-xFCqGPwYusQJp4N4NJLi1XJiZqjwFdjhT+KqtNy+Ug3qgfczqnTa6MSDvxJF6TkuDLoYJItMapz6tAf7kCekFw==", "integrity": "sha512-I+cOG3sd/7HdFtvDSnF9QQPrWguUH7zrkIMMykM3PtfWU9soTcS2yRb9Myq6MHmzbeCT08D1UmY+BaiMl5CcoQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-linux-arm64": { "@biomejs/cli-linux-arm64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.4.7.tgz",
"integrity": "sha512-2kFb4//jxfZaP6D+Rj5VkHkxgyD9EoRAVBEQb8PKRv+s4NO2zYNJKXFaJmK1CmhufJOWEfpHKaRbOja7qjmdhQ==", "integrity": "sha512-om6FugwmibzfP/6ALj5WRDVSND4H2G9X0nkI1HZpp2ySf9lW2j0X68oQSaHEnls6666oy4KDsc5RFjT4m0kV0w==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-linux-arm64-musl": { "@biomejs/cli-linux-arm64-musl": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.4.7.tgz",
"integrity": "sha512-oYxnW0ARfJkr72ezzF2OR8N/rtkgLUQeYtF8cFhVswbknHxtTcmzSsanVJP8yQKnGpGpc2ck6c5zLvHahL6Cbg==", "integrity": "sha512-I2NvM9KPb09jWml93O2/5WMfNR7Lee5Latag1JThDRMURVhPX74p9UDnyTw3Ae6cE1DgXfw7sqQgX7rkvpc0vw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-linux-x64": { "@biomejs/cli-linux-x64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.4.7.tgz",
"integrity": "sha512-NbcBbi/nJqn5baae6wqRXdS7Gadf2uRpehSh6vMSYpG8OhkXl/Xg8aorWrJ+9VWqAT5ml90alLvorkpMW0nBwQ==", "integrity": "sha512-bV8/uo2Tj+gumnk4sUdkerWyCPRabaZdv88IpbmDWARQQoA/Q0YaqPz1a+LSEDIL7OfrnPi9Hq1Llz4ZIGyIQQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-linux-x64-musl": { "@biomejs/cli-linux-x64-musl": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.4.7.tgz",
"integrity": "sha512-iHDS+MCM65DPqWGu+ECC3uoALyj2H7F4nVUPxIPjz/PIl94EUu+EDfGZDzFP+NY1EOPVt9NQvwFqq7HdMmowdg==", "integrity": "sha512-00kx4YrBMU8374zd2wHuRV5wseh0rom5HqRND+vDldJPrWwQw+mzd/d8byI9hPx926CG+vWzq6AeiT7Yi5y59g==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-win32-arm64": { "@biomejs/cli-win32-arm64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.4.7.tgz",
"integrity": "sha512-0rgImMsNb5v/chhkIFe3wu7PEFClS6RBAYUijGL9UsYN3PanSaoK24HSSuSJb1pYbYYVjzAyZTl3gtjJ84BM8A==", "integrity": "sha512-hOUHBMlFCvDhu3WCq6vaBoG0dp0LkWxSEnEEsxxXvOa9TfT6ZBnbh72A/xBM7CBYB7WgwqboetzFEVDnMxelyw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@biomejs/cli-win32-x64": { "@biomejs/cli-win32-x64": {
"version": "2.4.16", "version": "2.4.7",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.16.tgz", "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.4.7.tgz",
"integrity": "sha512-Kp85jgoBHa05gix6UIRjfCDiUV3w/8VIdZ247VyyO2gEjaw12WEVhdIjlxp/AMzXxqxQwbxNTDVZ3Mwd2RG5rw==", "integrity": "sha512-qEpGjSkPC3qX4ycbMUthXvi9CkRq7kZpkqMY1OyhmYlYLnANnooDQ7hDerM8+0NJ+DZKVnsIc07h30XOpt7LtQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
@@ -6396,184 +6405,184 @@
} }
}, },
"@esbuild/aix-ppc64": { "@esbuild/aix-ppc64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.4.tgz",
"integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", "integrity": "sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/android-arm": { "@esbuild/android-arm": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.4.tgz",
"integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", "integrity": "sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/android-arm64": { "@esbuild/android-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.4.tgz",
"integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", "integrity": "sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/android-x64": { "@esbuild/android-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.4.tgz",
"integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", "integrity": "sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/darwin-arm64": { "@esbuild/darwin-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.4.tgz",
"integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", "integrity": "sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/darwin-x64": { "@esbuild/darwin-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.4.tgz",
"integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", "integrity": "sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/freebsd-arm64": { "@esbuild/freebsd-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.4.tgz",
"integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", "integrity": "sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/freebsd-x64": { "@esbuild/freebsd-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.4.tgz",
"integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", "integrity": "sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-arm": { "@esbuild/linux-arm": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.4.tgz",
"integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", "integrity": "sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-arm64": { "@esbuild/linux-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.4.tgz",
"integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", "integrity": "sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-ia32": { "@esbuild/linux-ia32": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.4.tgz",
"integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", "integrity": "sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-loong64": { "@esbuild/linux-loong64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.4.tgz",
"integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", "integrity": "sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-mips64el": { "@esbuild/linux-mips64el": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.4.tgz",
"integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", "integrity": "sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-ppc64": { "@esbuild/linux-ppc64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.4.tgz",
"integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", "integrity": "sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-riscv64": { "@esbuild/linux-riscv64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.4.tgz",
"integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", "integrity": "sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-s390x": { "@esbuild/linux-s390x": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.4.tgz",
"integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", "integrity": "sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/linux-x64": { "@esbuild/linux-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.4.tgz",
"integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", "integrity": "sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/netbsd-arm64": { "@esbuild/netbsd-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.4.tgz",
"integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", "integrity": "sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/netbsd-x64": { "@esbuild/netbsd-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.4.tgz",
"integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", "integrity": "sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/openbsd-arm64": { "@esbuild/openbsd-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.4.tgz",
"integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", "integrity": "sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/openbsd-x64": { "@esbuild/openbsd-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.4.tgz",
"integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", "integrity": "sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/openharmony-arm64": { "@esbuild/openharmony-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.4.tgz",
"integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", "integrity": "sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/sunos-x64": { "@esbuild/sunos-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.4.tgz",
"integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", "integrity": "sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/win32-arm64": { "@esbuild/win32-arm64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.4.tgz",
"integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", "integrity": "sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/win32-ia32": { "@esbuild/win32-ia32": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.4.tgz",
"integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", "integrity": "sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"@esbuild/win32-x64": { "@esbuild/win32-x64": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.4.tgz",
"integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", "integrity": "sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==",
"dev": true, "dev": true,
"optional": true "optional": true
}, },
@@ -7648,37 +7657,37 @@
} }
}, },
"esbuild": { "esbuild": {
"version": "0.28.0", "version": "0.27.4",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.4.tgz",
"integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", "integrity": "sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@esbuild/aix-ppc64": "0.28.0", "@esbuild/aix-ppc64": "0.27.4",
"@esbuild/android-arm": "0.28.0", "@esbuild/android-arm": "0.27.4",
"@esbuild/android-arm64": "0.28.0", "@esbuild/android-arm64": "0.27.4",
"@esbuild/android-x64": "0.28.0", "@esbuild/android-x64": "0.27.4",
"@esbuild/darwin-arm64": "0.28.0", "@esbuild/darwin-arm64": "0.27.4",
"@esbuild/darwin-x64": "0.28.0", "@esbuild/darwin-x64": "0.27.4",
"@esbuild/freebsd-arm64": "0.28.0", "@esbuild/freebsd-arm64": "0.27.4",
"@esbuild/freebsd-x64": "0.28.0", "@esbuild/freebsd-x64": "0.27.4",
"@esbuild/linux-arm": "0.28.0", "@esbuild/linux-arm": "0.27.4",
"@esbuild/linux-arm64": "0.28.0", "@esbuild/linux-arm64": "0.27.4",
"@esbuild/linux-ia32": "0.28.0", "@esbuild/linux-ia32": "0.27.4",
"@esbuild/linux-loong64": "0.28.0", "@esbuild/linux-loong64": "0.27.4",
"@esbuild/linux-mips64el": "0.28.0", "@esbuild/linux-mips64el": "0.27.4",
"@esbuild/linux-ppc64": "0.28.0", "@esbuild/linux-ppc64": "0.27.4",
"@esbuild/linux-riscv64": "0.28.0", "@esbuild/linux-riscv64": "0.27.4",
"@esbuild/linux-s390x": "0.28.0", "@esbuild/linux-s390x": "0.27.4",
"@esbuild/linux-x64": "0.28.0", "@esbuild/linux-x64": "0.27.4",
"@esbuild/netbsd-arm64": "0.28.0", "@esbuild/netbsd-arm64": "0.27.4",
"@esbuild/netbsd-x64": "0.28.0", "@esbuild/netbsd-x64": "0.27.4",
"@esbuild/openbsd-arm64": "0.28.0", "@esbuild/openbsd-arm64": "0.27.4",
"@esbuild/openbsd-x64": "0.28.0", "@esbuild/openbsd-x64": "0.27.4",
"@esbuild/openharmony-arm64": "0.28.0", "@esbuild/openharmony-arm64": "0.27.4",
"@esbuild/sunos-x64": "0.28.0", "@esbuild/sunos-x64": "0.27.4",
"@esbuild/win32-arm64": "0.28.0", "@esbuild/win32-arm64": "0.27.4",
"@esbuild/win32-ia32": "0.28.0", "@esbuild/win32-ia32": "0.27.4",
"@esbuild/win32-x64": "0.28.0" "@esbuild/win32-x64": "0.27.4"
} }
}, },
"escalade": { "escalade": {
@@ -7880,9 +7889,9 @@
"dev": true "dev": true
}, },
"handlebars": { "handlebars": {
"version": "4.7.9", "version": "4.7.8",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
"integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"minimist": "^1.2.5", "minimist": "^1.2.5",
@@ -8921,9 +8930,9 @@
"dev": true "dev": true
}, },
"smol-toml": { "smol-toml": {
"version": "1.6.1", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz",
"integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==" "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw=="
}, },
"source-map": { "source-map": {
"version": "0.6.1", "version": "0.6.1",
@@ -9129,26 +9138,26 @@
"dev": true "dev": true
}, },
"ts-jest": { "ts-jest": {
"version": "29.4.11", "version": "29.4.6",
"resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.6.tgz",
"integrity": "sha512-IrFl7l9AuB/qrNw5quqvAv/hmKMb8dhWOH4jQOGo0Oq8tCeo1O86/iTFG1FaRimgUkF13l4PcepO8ATFT6Ns4g==", "integrity": "sha512-fSpWtOO/1AjSNQguk43hb/JCo16oJDnMJf3CdEGNkqsEX3t0KX96xvyX1D7PfLCpVoKu4MfVrqUkFyblYoY4lA==",
"dev": true, "dev": true,
"requires": { "requires": {
"bs-logger": "^0.2.6", "bs-logger": "^0.2.6",
"fast-json-stable-stringify": "^2.1.0", "fast-json-stable-stringify": "^2.1.0",
"handlebars": "^4.7.9", "handlebars": "^4.7.8",
"json5": "^2.2.3", "json5": "^2.2.3",
"lodash.memoize": "^4.1.2", "lodash.memoize": "^4.1.2",
"make-error": "^1.3.6", "make-error": "^1.3.6",
"semver": "^7.8.0", "semver": "^7.7.3",
"type-fest": "^4.41.0", "type-fest": "^4.41.0",
"yargs-parser": "^21.1.1" "yargs-parser": "^21.1.1"
}, },
"dependencies": { "dependencies": {
"semver": { "semver": {
"version": "7.8.1", "version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg==", "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true "dev": true
} }
} }
@@ -9189,9 +9198,9 @@
"optional": true "optional": true
}, },
"undici": { "undici": {
"version": "8.3.0", "version": "7.24.2",
"resolved": "https://registry.npmjs.org/undici/-/undici-8.3.0.tgz", "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.2.tgz",
"integrity": "sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q==" "integrity": "sha512-P9J1HWYV/ajFr8uCqk5QixwiRKmB1wOamgS0e+o2Z4A44Ej2+thFVRLG/eA7qprx88XXhnV5Bl8LHXTURpzB3Q=="
}, },
"undici-types": { "undici-types": {
"version": "7.18.2", "version": "7.18.2",

View File

@@ -9,6 +9,7 @@
"build": "tsc --noEmit", "build": "tsc --noEmit",
"check": "biome check --write", "check": "biome check --write",
"package": "node scripts/build-dist.mjs", "package": "node scripts/build-dist.mjs",
"bench:versions": "node scripts/bench-versions-client.mjs",
"test:unit": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", "test:unit": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js",
"test": "npm run build && npm run test:unit", "test": "npm run build && npm run test:unit",
"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)\"",
@@ -35,19 +36,19 @@
"@actions/io": "^3.0.2", "@actions/io": "^3.0.2",
"@actions/tool-cache": "^4.0.0", "@actions/tool-cache": "^4.0.0",
"@renovatebot/pep440": "^4.2.2", "@renovatebot/pep440": "^4.2.2",
"smol-toml": "^1.6.1", "smol-toml": "^1.6.0",
"undici": "^8.3.0" "undici": "^7.24.2"
}, },
"devDependencies": { "devDependencies": {
"@biomejs/biome": "^2.4.16", "@biomejs/biome": "^2.4.7",
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",
"@types/node": "^25.5.0", "@types/node": "^25.5.0",
"@types/semver": "^7.7.1", "@types/semver": "^7.7.1",
"@vercel/ncc": "^0.38.4", "@vercel/ncc": "^0.38.4",
"esbuild": "^0.28.0", "esbuild": "^0.27.4",
"jest": "^30.3.0", "jest": "^30.3.0",
"js-yaml": "^4.1.1", "js-yaml": "^4.1.1",
"ts-jest": "^29.4.11", "ts-jest": "^29.4.6",
"typescript": "^5.9.3" "typescript": "^5.9.3"
} }
} }

View File

@@ -0,0 +1,483 @@
import { performance } from "node:perf_hooks";
import * as pep440 from "@renovatebot/pep440";
import * as semver from "semver";
import { ProxyAgent, fetch as undiciFetch } from "undici";
const DEFAULT_URL =
"https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
const DEFAULT_ITERATIONS = 100;
const DEFAULT_ARCH = "aarch64";
const DEFAULT_PLATFORM = "apple-darwin";
function getProxyAgent() {
const httpProxy = process.env.HTTP_PROXY || process.env.http_proxy;
if (httpProxy) {
return new ProxyAgent(httpProxy);
}
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
if (httpsProxy) {
return new ProxyAgent(httpsProxy);
}
return undefined;
}
async function fetch(url) {
return await undiciFetch(url, {
dispatcher: getProxyAgent(),
});
}
function parseArgs(argv) {
const options = {
arch: DEFAULT_ARCH,
iterations: DEFAULT_ITERATIONS,
platform: DEFAULT_PLATFORM,
url: DEFAULT_URL,
};
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
const next = argv[index + 1];
if (arg === "--iterations" && next !== undefined) {
options.iterations = Number.parseInt(next, 10);
index += 1;
continue;
}
if (arg === "--url" && next !== undefined) {
options.url = next;
index += 1;
continue;
}
if (arg === "--arch" && next !== undefined) {
options.arch = next;
index += 1;
continue;
}
if (arg === "--platform" && next !== undefined) {
options.platform = next;
index += 1;
}
}
if (!Number.isInteger(options.iterations) || options.iterations <= 0) {
throw new Error("--iterations must be a positive integer");
}
return options;
}
function parseVersionLine(line, sourceDescription, lineNumber) {
let parsed;
try {
parsed = JSON.parse(line);
} catch (error) {
throw new Error(
`Failed to parse version data from ${sourceDescription} at line ${lineNumber}: ${error.message}`,
);
}
if (
typeof parsed !== "object" ||
parsed === null ||
typeof parsed.version !== "string" ||
!Array.isArray(parsed.artifacts)
) {
throw new Error(
`Invalid NDJSON record in ${sourceDescription} at line ${lineNumber}.`,
);
}
return parsed;
}
function parseVersionData(data, sourceDescription) {
const versions = [];
for (const [index, line] of data.split("\n").entries()) {
const trimmed = line.trim();
if (trimmed === "") {
continue;
}
versions.push(parseVersionLine(trimmed, sourceDescription, index + 1));
}
if (versions.length === 0) {
throw new Error(`No version data found in ${sourceDescription}.`);
}
return versions;
}
async function readEntireResponse(response) {
if (response.body === null) {
const text = await response.text();
return {
bytesRead: Buffer.byteLength(text, "utf8"),
text,
};
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
const chunks = [];
let bytesRead = 0;
while (true) {
const { done, value } = await reader.read();
if (done) {
chunks.push(decoder.decode());
break;
}
bytesRead += value.byteLength;
chunks.push(decoder.decode(value, { stream: true }));
}
return {
bytesRead,
text: chunks.join(""),
};
}
async function fetchAllVersions(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Failed to fetch version data: ${response.status} ${response.statusText}`,
);
}
const { bytesRead, text } = await readEntireResponse(response);
return {
bytesRead,
versions: parseVersionData(text, url),
};
}
async function streamUntil(url, predicate) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(
`Failed to fetch version data: ${response.status} ${response.statusText}`,
);
}
if (response.body === null) {
const { bytesRead, versions } = await fetchAllVersions(url);
return {
bytesRead,
matchedVersion: versions.find(predicate),
};
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let bytesRead = 0;
let buffer = "";
let lineNumber = 0;
while (true) {
const { done, value } = await reader.read();
if (done) {
buffer += decoder.decode();
break;
}
bytesRead += value.byteLength;
buffer += decoder.decode(value, { stream: true });
let newlineIndex = buffer.indexOf("\n");
while (newlineIndex !== -1) {
const line = buffer.slice(0, newlineIndex);
buffer = buffer.slice(newlineIndex + 1);
const trimmed = line.trim();
if (trimmed !== "") {
lineNumber += 1;
const versionData = parseVersionLine(trimmed, url, lineNumber);
if (predicate(versionData)) {
await reader.cancel();
return { bytesRead, matchedVersion: versionData };
}
}
newlineIndex = buffer.indexOf("\n");
}
}
if (buffer.trim() !== "") {
lineNumber += 1;
const versionData = parseVersionLine(buffer.trim(), url, lineNumber);
if (predicate(versionData)) {
return { bytesRead, matchedVersion: versionData };
}
}
return { bytesRead, matchedVersion: undefined };
}
function versionSatisfies(version, versionSpecifier) {
return (
semver.satisfies(version, versionSpecifier) ||
pep440.satisfies(version, versionSpecifier)
);
}
function maxSatisfying(versions, versionSpecifier) {
const semverMatch = semver.maxSatisfying(versions, versionSpecifier);
if (semverMatch !== null) {
return semverMatch;
}
return pep440.maxSatisfying(versions, versionSpecifier) ?? undefined;
}
function selectArtifact(artifacts) {
if (artifacts.length === 1) {
return artifacts[0];
}
const defaultVariant = artifacts.find(
(candidate) => candidate.variant === "default",
);
if (defaultVariant !== undefined) {
return defaultVariant;
}
return artifacts[0];
}
async function benchmarkCase(name, expected, implementations, iterations) {
const results = {
name,
new: [],
old: [],
};
for (let iteration = 0; iteration < iterations; iteration += 1) {
const order = iteration % 2 === 0 ? ["old", "new"] : ["new", "old"];
for (const label of order) {
const implementation = implementations[label];
const startedAt = performance.now();
const outcome = await implementation.run();
const durationMs = performance.now() - startedAt;
if (outcome.value !== expected) {
throw new Error(
`${name} ${label} produced ${JSON.stringify(outcome.value)}; expected ${JSON.stringify(expected)}`,
);
}
results[label].push({
bytesRead: outcome.bytesRead,
durationMs,
});
}
}
return results;
}
function summarize(samples) {
const durations = samples
.map((sample) => sample.durationMs)
.sort((left, right) => left - right);
const bytes = samples
.map((sample) => sample.bytesRead)
.sort((left, right) => left - right);
const sum = (values) => values.reduce((total, value) => total + value, 0);
const percentile = (values, ratio) => {
const index = Math.min(
values.length - 1,
Math.max(0, Math.ceil(values.length * ratio) - 1),
);
return values[index];
};
return {
avgBytes: sum(bytes) / bytes.length,
avgMs: sum(durations) / durations.length,
maxMs: durations[durations.length - 1],
medianMs: percentile(durations, 0.5),
minMs: durations[0],
p95Ms: percentile(durations, 0.95),
};
}
function formatNumber(value, digits = 2) {
return value.toFixed(digits);
}
function formatSummary(name, oldSummary, newSummary) {
const speedup = oldSummary.avgMs / newSummary.avgMs;
const timeReduction =
((oldSummary.avgMs - newSummary.avgMs) / oldSummary.avgMs) * 100;
const byteReduction =
((oldSummary.avgBytes - newSummary.avgBytes) / oldSummary.avgBytes) * 100;
return [
`Scenario: ${name}`,
` old avg: ${formatNumber(oldSummary.avgMs)} ms | median: ${formatNumber(oldSummary.medianMs)} ms | p95: ${formatNumber(oldSummary.p95Ms)} ms | avg bytes: ${Math.round(oldSummary.avgBytes)}`,
` new avg: ${formatNumber(newSummary.avgMs)} ms | median: ${formatNumber(newSummary.medianMs)} ms | p95: ${formatNumber(newSummary.p95Ms)} ms | avg bytes: ${Math.round(newSummary.avgBytes)}`,
` delta: ${formatNumber(timeReduction)}% faster | ${formatNumber(speedup)}x speedup | ${formatNumber(byteReduction)}% fewer bytes read`,
].join("\n");
}
async function main() {
const options = parseArgs(process.argv.slice(2));
console.log(`Preparing benchmark data from ${options.url}`);
const baseline = await fetchAllVersions(options.url);
const latestVersion = baseline.versions[0]?.version;
if (!latestVersion) {
throw new Error("No versions found in NDJSON data");
}
const latestArtifact = selectArtifact(
baseline.versions[0].artifacts.filter(
(candidate) =>
candidate.platform === `${options.arch}-${options.platform}`,
),
);
if (!latestArtifact) {
throw new Error(
`No artifact found for ${options.arch}-${options.platform} in ${latestVersion}`,
);
}
const rangeSpecifier = `^${latestVersion.split(".")[0]}.${latestVersion.split(".")[1]}.0`;
console.log(
`Running ${options.iterations} iterations per scenario against ${options.url}`,
);
console.log(`Latest version: ${latestVersion}`);
console.log(`Range benchmark: ${rangeSpecifier}`);
console.log(`Artifact benchmark: ${options.arch}-${options.platform}`);
console.log("");
const scenarios = [
await benchmarkCase(
"latest version",
latestVersion,
{
new: {
run: async () => {
const { bytesRead, matchedVersion } = await streamUntil(
options.url,
() => true,
);
return {
bytesRead,
value: matchedVersion?.version,
};
},
},
old: {
run: async () => {
const { bytesRead, versions } = await fetchAllVersions(options.url);
return {
bytesRead,
value: versions[0]?.version,
};
},
},
},
options.iterations,
),
await benchmarkCase(
"highest satisfying range",
latestVersion,
{
new: {
run: async () => {
const { bytesRead, matchedVersion } = await streamUntil(
options.url,
(candidate) =>
versionSatisfies(candidate.version, rangeSpecifier),
);
return {
bytesRead,
value: matchedVersion?.version,
};
},
},
old: {
run: async () => {
const { bytesRead, versions } = await fetchAllVersions(options.url);
return {
bytesRead,
value: maxSatisfying(
versions.map((versionData) => versionData.version),
rangeSpecifier,
),
};
},
},
},
options.iterations,
),
await benchmarkCase(
"exact version artifact",
latestArtifact.url,
{
new: {
run: async () => {
const { bytesRead, matchedVersion } = await streamUntil(
options.url,
(candidate) => candidate.version === latestVersion,
);
const artifact = matchedVersion
? selectArtifact(
matchedVersion.artifacts.filter(
(candidate) =>
candidate.platform ===
`${options.arch}-${options.platform}`,
),
)
: undefined;
return {
bytesRead,
value: artifact?.url,
};
},
},
old: {
run: async () => {
const { bytesRead, versions } = await fetchAllVersions(options.url);
const versionData = versions.find(
(candidate) => candidate.version === latestVersion,
);
const artifact = selectArtifact(
versionData.artifacts.filter(
(candidate) =>
candidate.platform === `${options.arch}-${options.platform}`,
),
);
return {
bytesRead,
value: artifact?.url,
};
},
},
},
options.iterations,
),
];
for (const scenario of scenarios) {
const oldSummary = summarize(scenario.old);
const newSummary = summarize(scenario.new);
console.log(formatSummary(scenario.name, oldSummary, newSummary));
console.log("");
}
}
await main();

View File

@@ -1,8 +1,15 @@
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 { hashFiles } from "../hash/hash-files"; import { hashFiles } from "../hash/hash-files";
import type { SetupInputs } from "../utils/inputs"; import {
import * as log from "../utils/logging"; cacheDependencyGlob,
cacheLocalPath,
cachePython,
cacheSuffix,
pruneCache,
pythonDir,
restoreCache as shouldRestoreCache,
} from "../utils/inputs";
import { getArch, getOSNameVersion, getPlatform } from "../utils/platforms"; import { getArch, getOSNameVersion, getPlatform } from "../utils/platforms";
export const STATE_CACHE_KEY = "cache-key"; export const STATE_CACHE_KEY = "cache-key";
@@ -11,21 +18,18 @@ export const STATE_PYTHON_CACHE_MATCHED_KEY = "python-cache-matched-key";
const CACHE_VERSION = "2"; const CACHE_VERSION = "2";
export async function restoreCache( export async function restoreCache(pythonVersion?: string): Promise<void> {
inputs: SetupInputs, const cacheKey = await computeKeys(pythonVersion);
pythonVersion?: string,
): Promise<void> {
const cacheKey = await computeKeys(inputs, pythonVersion);
core.saveState(STATE_CACHE_KEY, cacheKey); core.saveState(STATE_CACHE_KEY, cacheKey);
core.setOutput("cache-key", cacheKey); core.setOutput("cache-key", cacheKey);
if (!inputs.restoreCache) { if (!shouldRestoreCache) {
log.info("restore-cache is false. Skipping restore cache step."); core.info("restore-cache is false. Skipping restore cache step.");
core.setOutput("python-cache-hit", false); core.setOutput("python-cache-hit", false);
return; return;
} }
if (inputs.cacheLocalPath === undefined) { if (cacheLocalPath === undefined) {
throw new Error( throw new Error(
"cache-local-path is not set. Cannot restore cache without a valid cache path.", "cache-local-path is not set. Cannot restore cache without a valid cache path.",
); );
@@ -33,15 +37,15 @@ export async function restoreCache(
await restoreCacheFromKey( await restoreCacheFromKey(
cacheKey, cacheKey,
inputs.cacheLocalPath.path, cacheLocalPath.path,
STATE_CACHE_MATCHED_KEY, STATE_CACHE_MATCHED_KEY,
"cache-hit", "cache-hit",
); );
if (inputs.cachePython) { if (cachePython) {
await restoreCacheFromKey( await restoreCacheFromKey(
`${cacheKey}-python`, `${cacheKey}-python`,
inputs.pythonDir, pythonDir,
STATE_PYTHON_CACHE_MATCHED_KEY, STATE_PYTHON_CACHE_MATCHED_KEY,
"python-cache-hit", "python-cache-hit",
); );
@@ -56,7 +60,7 @@ async function restoreCacheFromKey(
stateKey: string, stateKey: string,
outputKey: string, outputKey: string,
): Promise<void> { ): Promise<void> {
log.info( core.info(
`Trying to restore cache from GitHub Actions cache with key: ${cacheKey}`, `Trying to restore cache from GitHub Actions cache with key: ${cacheKey}`,
); );
let matchedKey: string | undefined; let matchedKey: string | undefined;
@@ -64,7 +68,7 @@ async function restoreCacheFromKey(
matchedKey = await cache.restoreCache([cachePath], cacheKey); matchedKey = await cache.restoreCache([cachePath], cacheKey);
} catch (err) { } catch (err) {
const message = (err as Error).message; const message = (err as Error).message;
log.warning(message); core.warning(message);
core.setOutput(outputKey, false); core.setOutput(outputKey, false);
return; return;
} }
@@ -72,34 +76,28 @@ async function restoreCacheFromKey(
handleMatchResult(matchedKey, cacheKey, stateKey, outputKey); handleMatchResult(matchedKey, cacheKey, stateKey, outputKey);
} }
async function computeKeys( async function computeKeys(pythonVersion?: string): Promise<string> {
inputs: SetupInputs,
pythonVersion?: string,
): Promise<string> {
let cacheDependencyPathHash = "-"; let cacheDependencyPathHash = "-";
if (inputs.cacheDependencyGlob !== "") { if (cacheDependencyGlob !== "") {
log.info( core.info(
`Searching files using cache dependency glob: ${inputs.cacheDependencyGlob.split("\n").join(",")}`, `Searching files using cache dependency glob: ${cacheDependencyGlob.split("\n").join(",")}`,
);
cacheDependencyPathHash += await hashFiles(
inputs.cacheDependencyGlob,
true,
); );
cacheDependencyPathHash += await hashFiles(cacheDependencyGlob, true);
if (cacheDependencyPathHash === "-") { if (cacheDependencyPathHash === "-") {
log.warning( core.warning(
`No file matched to [${inputs.cacheDependencyGlob.split("\n").join(",")}]. The cache will never get invalidated. Make sure you have checked out the target repository and configured the cache-dependency-glob input correctly.`, `No file matched to [${cacheDependencyGlob.split("\n").join(",")}]. The cache will never get invalidated. Make sure you have checked out the target repository and configured the cache-dependency-glob input correctly.`,
); );
} }
} }
if (cacheDependencyPathHash === "-") { if (cacheDependencyPathHash === "-") {
cacheDependencyPathHash = "-no-dependency-glob"; cacheDependencyPathHash = "-no-dependency-glob";
} }
const suffix = inputs.cacheSuffix ? `-${inputs.cacheSuffix}` : ""; const suffix = cacheSuffix ? `-${cacheSuffix}` : "";
const version = pythonVersion ?? "unknown"; const version = pythonVersion ?? "unknown";
const platform = await getPlatform(); const platform = await getPlatform();
const osNameVersion = getOSNameVersion(); const osNameVersion = getOSNameVersion();
const pruned = inputs.pruneCache ? "-pruned" : ""; const pruned = pruneCache ? "-pruned" : "";
const python = inputs.cachePython ? "-py" : ""; const python = cachePython ? "-py" : "";
return `setup-uv-${CACHE_VERSION}-${getArch()}-${platform}-${osNameVersion}-${version}${pruned}${python}${cacheDependencyPathHash}${suffix}`; return `setup-uv-${CACHE_VERSION}-${getArch()}-${platform}-${osNameVersion}-${version}${pruned}${python}${cacheDependencyPathHash}${suffix}`;
} }
@@ -110,12 +108,12 @@ function handleMatchResult(
outputKey: string, outputKey: string,
): void { ): void {
if (!matchedKey) { if (!matchedKey) {
log.info(`No GitHub Actions cache found for key: ${primaryKey}`); core.info(`No GitHub Actions cache found for key: ${primaryKey}`);
core.setOutput(outputKey, false); core.setOutput(outputKey, false);
return; return;
} }
core.saveState(stateKey, matchedKey); core.saveState(stateKey, matchedKey);
log.info(`cache restored from GitHub Actions cache with key: ${matchedKey}`); core.info(`cache restored from GitHub Actions cache with key: ${matchedKey}`);
core.setOutput(outputKey, true); core.setOutput(outputKey, true);
} }

View File

@@ -1,755 +1,5 @@
// AUTOGENERATED_DO_NOT_EDIT // AUTOGENERATED_DO_NOT_EDIT
export const KNOWN_CHECKSUMS: { [key: string]: string } = { export const KNOWN_CHECKSUMS: { [key: string]: string } = {
"aarch64-apple-darwin-0.11.18":
"1a7adf8dadae3b55853115d13a8bf564d219597ad13824b93b213706933863e5",
"aarch64-pc-windows-msvc-0.11.18":
"0689e1a40d36b387522d2b1b865cd98a15ddd4a7507e256ad93be6f6a335fec1",
"aarch64-unknown-linux-gnu-0.11.18":
"0f03c6648df1c159557f4222c0f37250f84733fb88d6fc3c16770e17c177a8c9",
"aarch64-unknown-linux-musl-0.11.18":
"6d895725333680bf7633ad635baff8e49dc45d3b52e00b2b3adf6ced41f2ebe2",
"arm-unknown-linux-musleabihf-0.11.18":
"c4fe354b28c489fa6649531808076c43eb3a34122df49b0a3005bb75dbf101c3",
"armv7-unknown-linux-gnueabihf-0.11.18":
"a70a8b1124dc1fabcce9f2bbe6591c72a05d49df74125d1c327b5745f2becbb6",
"armv7-unknown-linux-musleabihf-0.11.18":
"f8b6f4df3ff9d142a25892be575ade438672a8353ad71997f7db88e9b9a1062d",
"i686-pc-windows-msvc-0.11.18":
"7505112a7bf72f50391c50f2aa07950b95b3c43c7d9fd4da5626876407d15dda",
"i686-unknown-linux-gnu-0.11.18":
"5f3df0d62af1d174a06b82a6faf1a5e9a1f729b87d11c7d9cd87d4241e04f23d",
"i686-unknown-linux-musl-0.11.18":
"4237cfcd03fb8767a7ec713ab3db14381d83bbd0bf5ccc88cd6f28ac8c2c616f",
"powerpc64le-unknown-linux-gnu-0.11.18":
"fc8f46a198e540ca2d89fd9480da0648d673ff3e25b4048c82ca5c292a478052",
"riscv64gc-unknown-linux-gnu-0.11.18":
"cdb0555db7828bbd1dc24e55171b8ac3dbbc24fe17b6a7387783cd4d543a1538",
"riscv64gc-unknown-linux-musl-0.11.18":
"3d5b533080bb593c82b281b8d289e29d51b97c0994655099845752e948181fe2",
"s390x-unknown-linux-gnu-0.11.18":
"7a91aa963680f2fe14ebf89291cf8eafcff634eccdeb6d301e0252b282171818",
"x86_64-apple-darwin-0.11.18":
"00a61e3db99b53c927a7e6c4ccdccb898aa3253d07928822211e9dc570a25661",
"x86_64-pc-windows-msvc-0.11.18":
"bf8e0021336b7c77bd80a078b612125f385b08f541437edaea8c8ca9e574db0d",
"x86_64-unknown-linux-gnu-0.11.18":
"588f3e360f69ce02b6982aa99f2240e803933a6b7e176ac01617830adf955add",
"x86_64-unknown-linux-musl-0.11.18":
"a095a969fc8357f42e35652e0554525a47a29010ddb814bd82650c2ffa7d6d62",
"aarch64-apple-darwin-0.11.17":
"2a162f6b90ff3691a2f9cae1622e066a3ce592e110f66670cdcc841324b28226",
"aarch64-pc-windows-msvc-0.11.17":
"f4463aa9671c6d153d32f2a9b272389675a711a9bca806c4ab4a3c7559b045c2",
"aarch64-unknown-linux-gnu-0.11.17":
"de008880a903ac2c5654647dc19a75c0d6652313c977a2bc5ce05e1e3a93429e",
"aarch64-unknown-linux-musl-0.11.17":
"9e5eaf16ffad968fc689f18c2733ace914ed417d4e5572e92d807fd51a90228c",
"arm-unknown-linux-musleabihf-0.11.17":
"201c7d727423095aa4ba39cc79b16cac2465720d4348270a3977824009526179",
"armv7-unknown-linux-gnueabihf-0.11.17":
"c941377b20fdd4b101376a9c8ce37c209d36655697815a32658a7cbcb3212409",
"armv7-unknown-linux-musleabihf-0.11.17":
"12606cc40d15c5ab5fd06e434c8ee1b0ef7e3ca3cd4d5b2b135a16dd1a45fed2",
"i686-pc-windows-msvc-0.11.17":
"be48cd9aa35c8615eff3dba6a24e214edf00885150eacde032a258399131c59d",
"i686-unknown-linux-gnu-0.11.17":
"89f859f3bfaf3a74733aef671e6a4ade36173623d4539d3559e11caa2c722718",
"i686-unknown-linux-musl-0.11.17":
"8d2ecb44951b80861570f4a7f732c9f16f3b342450eeb0bd2eef876b10395400",
"powerpc64le-unknown-linux-gnu-0.11.17":
"714c7b292c805231edbfc77ca14b29e6e469342236ef1cfb58fe7d6f8fed48a4",
"riscv64gc-unknown-linux-gnu-0.11.17":
"f8bece740520b35f69c82653da77912b38a29a5634a6e0ce7d83122a485c6a6f",
"riscv64gc-unknown-linux-musl-0.11.17":
"ae07b4e9c2bea3dcba2e3267e9e4229e45de63c15e74eee7fac7ccf9df6e04cd",
"s390x-unknown-linux-gnu-0.11.17":
"10ec2070644dda19ab9c8dcc3d6f3bbf4b09ad6665b8a8be067d7fdb5a58b56c",
"x86_64-apple-darwin-0.11.17":
"6c66e41eaf4d15abeda58d3f268161b6e3f742d98390341b174a7cfc1b48841d",
"x86_64-pc-windows-msvc-0.11.17":
"35fc29e03e62f3cda769bc12773f3cb70ce305d0d36c0d8bd0c117dd0b3fcd14",
"x86_64-unknown-linux-gnu-0.11.17":
"0017ccecaeb4d431d7f93b583ebff0c5c38e00eb734fcf13d05f72ca419125fe",
"x86_64-unknown-linux-musl-0.11.17":
"4231a429d4e0f7c1937d8916658c08a7706cd7872afebeb87203a18c2e0dc28e",
"aarch64-apple-darwin-0.11.16":
"2b25be1af546be330b340b0a76b99f989daa6d92678fdffb87438e661e9d88fb",
"aarch64-pc-windows-msvc-0.11.16":
"e4f8e70eb21f0f4efd2eeb159ab289f9a16057d59881a4475758be4ce39bc8c5",
"aarch64-unknown-linux-gnu-0.11.16":
"8c9d0f0ee98166ae6ab198747519ba6f25db29d185bd2ae5960ecebc91a5c22a",
"aarch64-unknown-linux-musl-0.11.16":
"ac022d96411143b9a2dd75ea711fa8dd4cd14538bf248f2e5df3c10a80f7f6a4",
"arm-unknown-linux-musleabihf-0.11.16":
"cdd60c84597690139e3696461d1278bf4dcd598cd44e3896a98aa75aa59965bf",
"armv7-unknown-linux-gnueabihf-0.11.16":
"71cf33cb511c9fe28ae261c0b4789e1fd9bb84d1bc68828db647b77305a15185",
"armv7-unknown-linux-musleabihf-0.11.16":
"f24fca34326c5b8f7ddc0001a40e5454bc8091ca67f9ce931ffdaef4ea4815e8",
"i686-pc-windows-msvc-0.11.16":
"7417090298bf202395b9b3d6eefb9230332d8d6c94a5616e531148a0b041c8e2",
"i686-unknown-linux-gnu-0.11.16":
"0d1e427cd3fcc042e85dfc75f6d95e076dff9b930241686969d6706afda21375",
"i686-unknown-linux-musl-0.11.16":
"d5e611deffd3f5fd637b2dc89dbe252342ce4a38c8970e63add8029afe2b5629",
"powerpc64le-unknown-linux-gnu-0.11.16":
"8a3b09ce14d14a75dbbf051cdb78a314fb579e78fb3a02e1ee833c4cb5f6e81e",
"riscv64gc-unknown-linux-gnu-0.11.16":
"0314895f159ce97bcedac00a4b97fa7e53c16fee911a6a2d9f0b69ee6461b7d5",
"riscv64gc-unknown-linux-musl-0.11.16":
"8a1aef4261011143f56c964eeaed5e06fa0cb95ff3005386381c610c91784feb",
"s390x-unknown-linux-gnu-0.11.16":
"d161e914ad552aed83478fe9766061844297dadfa77a43e56285a147bde0021e",
"x86_64-apple-darwin-0.11.16":
"6b91ae3de155f51bd1f5b74814821c79f016a176561f252cd9ddfb976939af2e",
"x86_64-pc-windows-msvc-0.11.16":
"dd9d6d6554bfab265bfa98aa8e8a406c5c3a7b97582f93de1f4d48d9154a0395",
"x86_64-unknown-linux-gnu-0.11.16":
"74947fe2c03315cf07e82ab3acc703eddef01aba4d5232a98e4c6825ec116131",
"x86_64-unknown-linux-musl-0.11.16":
"1bc4be1be0a000f893b0d1db97906cf392b63fa22fda9a0ecf33d0d4bbb4bc9a",
"aarch64-apple-darwin-0.11.15":
"7e5b336108f8576eda1939920ca0a805b4a9a3c3d3eb2f6140e38b7092fbe4f3",
"aarch64-pc-windows-msvc-0.11.15":
"9eac2d68f3a66326c3e1fc97ef28bd54f1d13136ec092c2f0a8173ae12aaaf1e",
"aarch64-unknown-linux-gnu-0.11.15":
"21a7dd1a03ea17ac0366887455dab15d215b31dba0870dcd65d3714e22f46c81",
"aarch64-unknown-linux-musl-0.11.15":
"6505075cec3f551fad4fe9026922967ff9c895c9f513c97682b24e7a1c9becd3",
"arm-unknown-linux-musleabihf-0.11.15":
"f9206848d617b7beec37c346624ad961d8d4110606990653ebbfc4c62b1f1741",
"armv7-unknown-linux-gnueabihf-0.11.15":
"eb6a12e3e80e1474c1018edc9541bbe71cdf2248fa17b583dcbcc7bb391ad0c0",
"armv7-unknown-linux-musleabihf-0.11.15":
"a40ee3c41443341846137afc5c7f29be766a9a677bd70c7ff91cbb4273e5383c",
"i686-pc-windows-msvc-0.11.15":
"6a9431f0044a1ff59fd6920f6f982b691acf336b6e26ac8cd40a02b5ab839cd1",
"i686-unknown-linux-gnu-0.11.15":
"557e329e76072b513e47bcd8b50ca4bad07ec87cb325cbfc05e6069847af06c4",
"i686-unknown-linux-musl-0.11.15":
"69490ca5580958cdee3353b54357925913ec0540dc8e09819294b9e5b6d48556",
"powerpc64le-unknown-linux-gnu-0.11.15":
"6be3637ef86cdee3f5fcfbc66681ecbf6d57c6a123398a1bdd09786d65a06016",
"riscv64gc-unknown-linux-gnu-0.11.15":
"a43e22243e3f3b1fb136a0998b730367fe2589ea98ce6cd4f0d7d20b9f77fb5b",
"riscv64gc-unknown-linux-musl-0.11.15":
"2256c9b625d67a55986adda62b09782b5547e28a79fba472e7e93ac3ec0af258",
"s390x-unknown-linux-gnu-0.11.15":
"df2b69ed893ce00e242d8cfe5b9fdc7b7a42d578df487d09aa624563a9801578",
"x86_64-apple-darwin-0.11.15":
"42bca7cc879d117ed7139a0e26de8cab0b6f033ad439a32144f324d1f8580d8c",
"x86_64-pc-windows-msvc-0.11.15":
"04b98d414a9000e25e5e0e7c9f53749e66b790cdaffc582829e6f58c544ee11c",
"x86_64-unknown-linux-gnu-0.11.15":
"b03e572f010bea94a4a52d42671ba72981e12894f71576181a1d26ff68546da7",
"x86_64-unknown-linux-musl-0.11.15":
"200ccf2f351849c5d6698714e7e7eb9ead1e8c097dbdbb43730e1a4e059ceb87",
"aarch64-apple-darwin-0.11.14":
"4333af5c0730d94323a7819bbdf87ce92dd07fc857d67fff0059e0fca31b5c02",
"aarch64-pc-windows-msvc-0.11.14":
"d66c76ba912ba66fed011e0189dfbc4527dd9e620a2b5d5d5ecd2ad8936601b8",
"aarch64-unknown-linux-gnu-0.11.14":
"c4958f729e216f1610632574ed927b8cf0af1bd02cb88cb30d948571727aee43",
"aarch64-unknown-linux-musl-0.11.14":
"d7d3966e46915c5f6932692aaf152a2473eecb1d2517ca4f8e88a07484b380b6",
"arm-unknown-linux-musleabihf-0.11.14":
"31b07fa8bc5bbc8f22064fc1d4238b53c663bdb4812cbfead0b43719571aec03",
"armv7-unknown-linux-gnueabihf-0.11.14":
"2aca3925d7ad91d2e02a0f9cf75974ebd077ec5cb939a5eb66aba096d5666819",
"armv7-unknown-linux-musleabihf-0.11.14":
"988d79544bbf55ebeaf6521d3cbf46957bcfbab998d22092ea860580639e2f30",
"i686-pc-windows-msvc-0.11.14":
"579408a1134ec3c45dd7b94187978b98b15df4e0c49ebf05c52565e3858d9f2a",
"i686-unknown-linux-gnu-0.11.14":
"8c93880c54dc7a632f602b7627d4338d80011ecf32e340fd2f67129df5325dc7",
"i686-unknown-linux-musl-0.11.14":
"c84acf1036767797a7be97a3315122b9565a78bf90b5733741b1abeefa58387f",
"powerpc64le-unknown-linux-gnu-0.11.14":
"d2da5ba5911b86dfec96f0737b7d1053ed78c0c65e51585db03fb4969b2a3825",
"riscv64gc-unknown-linux-gnu-0.11.14":
"55731359293842826cd82d5fbd826a6bce542c3fec458214604e308b352560ed",
"riscv64gc-unknown-linux-musl-0.11.14":
"86b053903d29a2d04441e4cbd05a8f690b8ec56f8959d27f15df13efffb5879b",
"s390x-unknown-linux-gnu-0.11.14":
"cc7b233541a76dd484516a39c06d9d14100d1048708483e6f49ee20b6cc5761b",
"x86_64-apple-darwin-0.11.14":
"9836c1440b0bd6aa5f81793648a339bd01d593b7b8f575de3b855dae4ab64654",
"x86_64-pc-windows-msvc-0.11.14":
"52ba5d19409aaa688a8a1a6ec8dfb6a4817230d20186e75f4006105c3e39a846",
"x86_64-unknown-linux-gnu-0.11.14":
"f3b623eb0e6141a7053d571d59a0bdc341e0f238ea8f5f0b4815ddbec9a2a296",
"x86_64-unknown-linux-musl-0.11.14":
"077d36f45a0cc6d440b653b2d5c53e7731121e99e54b0221267eec5d1cae76ce",
"aarch64-apple-darwin-0.11.13":
"196a58aa24da89144187670df7c407358028984537fbc2f8f2d8f7a2604980df",
"aarch64-pc-windows-msvc-0.11.13":
"07c3c997020430a9f287fc05ff4c63fd5744eec49df5392a34731ed1a0971f2e",
"aarch64-unknown-linux-gnu-0.11.13":
"12366407dc1fdba5179b10bd69c11ebfc2eff25791366089c0b2f5701056efc5",
"aarch64-unknown-linux-musl-0.11.13":
"bea8a97b1b3ed41491e075c1f474e7f0249582aa3f62849c4e874b5f34ddc95e",
"arm-unknown-linux-musleabihf-0.11.13":
"ee282adf170eb845821309ca6038fdd87a93dd25326f96efe6ea58a1b66a9064",
"armv7-unknown-linux-gnueabihf-0.11.13":
"4761e38e3d5ca62e87ef13bc35ba169e6ebd126472482095405367b31be88945",
"armv7-unknown-linux-musleabihf-0.11.13":
"d54342a96dda65339b4f7b9e6bb7a27b81aeeffca14e5dfa7911d00fe4a3ead9",
"i686-pc-windows-msvc-0.11.13":
"a9b2d96a118a401c7dc5b717752a074b6324ddc9b36dcb2b60466a4e2912a3ba",
"i686-unknown-linux-gnu-0.11.13":
"630774d3fd255a219a6eef58f004201737c60f4b282777fb99e599cd90567fe4",
"i686-unknown-linux-musl-0.11.13":
"52cb28c81ca43ea5184f944c31555981cb29c03c2497fa848541af5ee4d8448f",
"powerpc64le-unknown-linux-gnu-0.11.13":
"7f302104ea18a01381fe58434b593f887c4f10bc523ad50781de408fbec54354",
"riscv64gc-unknown-linux-gnu-0.11.13":
"3264ce97b34d5c8d37c1e67821a74960ca89237e001253309a3cda25fb416040",
"riscv64gc-unknown-linux-musl-0.11.13":
"44f23b8e59fd8628fb68383e4cbdf78c3cff02ed86d3dcea5605ebd7757ca363",
"s390x-unknown-linux-gnu-0.11.13":
"e0e5e0a652650900d97f6a660bae526601033d9d071ca5dd9ca735442161ebed",
"x86_64-apple-darwin-0.11.13":
"99aad3f4956f5b92efd83eca6d87bf03e10688899487ad541f904c9c25c61dc1",
"x86_64-pc-windows-msvc-0.11.13":
"0953ac2ef4fbe47ad469bfa80b658a577a02c4d73a2fb9c4c7c70dda432efded",
"x86_64-unknown-linux-gnu-0.11.13":
"f830ea3d38ae1492acf53cb7f2cd0f81d6ae22b42d2d7310a6c7d42c451e1a43",
"x86_64-unknown-linux-musl-0.11.13":
"5635afc285df86ce6f05f3f22335f9548b0026e58531904482c9670a1c1c65d9",
"aarch64-apple-darwin-0.11.12":
"bb7c6ef869ec00cd1452f4884acf23d00b153c356ba9197ae99a1bc1ceadb7f3",
"aarch64-pc-windows-msvc-0.11.12":
"393de1abc2f663cb9dd24405c7a7b31119e2a734609a233d9b89415821f39bf9",
"aarch64-unknown-linux-gnu-0.11.12":
"d6e3e5183e71bbd40400da3d2913743cefb98835d8312a5e7908c33865597515",
"aarch64-unknown-linux-musl-0.11.12":
"b70e87f15f12d750d218042c4ed36e41de0757eab249d332ee2e242e4174b5d5",
"arm-unknown-linux-musleabihf-0.11.12":
"c1991e652c345395eff3e43aaa0f2ce5d7f0c7ed0dd5a72dcb0a3c109289ac11",
"armv7-unknown-linux-gnueabihf-0.11.12":
"432e6a96ecc976861dc884d96ac3aa3cc305abc3bb49d3204544477d4a290c64",
"armv7-unknown-linux-musleabihf-0.11.12":
"a8855302bad162af78c8fa53f402128a3496b7806dc7201252e7f123eefed8b9",
"i686-pc-windows-msvc-0.11.12":
"98efe2a4cb9529724639aac488c43b28753e738b0f4c679d3e2dea150e5a9b20",
"i686-unknown-linux-gnu-0.11.12":
"22dbbbcd9088ad3ddefce9be142ce2b127b3950718222413e3890f7fbf4a567d",
"i686-unknown-linux-musl-0.11.12":
"fc5ff3fef5facf01a664f0942f372988804bda1bb8c7f9e9642d9d29398cf129",
"powerpc64le-unknown-linux-gnu-0.11.12":
"36619f91357b240648caed6557fe893922c7986319c070f4feb225e8f3180b49",
"riscv64gc-unknown-linux-gnu-0.11.12":
"9bdcac006731a2094ad002d93c4fe84a259484e4d35566e29fcb76962961cef9",
"riscv64gc-unknown-linux-musl-0.11.12":
"80012ba0aa3b21561c96edda003add87d9111daf3425e5cc3243957ca76ba396",
"s390x-unknown-linux-gnu-0.11.12":
"c9ae09f73066fb9c48beaec2ab4ad2407ce94354c5224e2982196577d6bf4581",
"x86_64-apple-darwin-0.11.12":
"32fb217e6181384bf6534b31adcc66cd552eff98643c4bb35832be8552486912",
"x86_64-pc-windows-msvc-0.11.12":
"e46956a6b088a0382101c797eef945c1b03826e629e968d434cf838d42d85b6b",
"x86_64-unknown-linux-gnu-0.11.12":
"9acdecddacba550ee616c02bb4616d894352022550c5977524556fd5077ce1d4",
"x86_64-unknown-linux-musl-0.11.12":
"591a7557f5ba7e51565f338dd4c50cebc12820ec2ebb8403a4304685f8d53ab9",
"aarch64-apple-darwin-0.11.11":
"3a185bf8f46a7b7c8b910d111825907b1638d0ae503cb3c333ae205772354046",
"aarch64-pc-windows-msvc-0.11.11":
"3d8f05de7ed9de885299565f78832a13e443be51de86260f25edb7cfd0fa05f6",
"aarch64-unknown-linux-gnu-0.11.11":
"155fe4d3b3cb4bfce118ab4b1380f71515ae874d13d9858171b4f9c26e16684d",
"aarch64-unknown-linux-musl-0.11.11":
"0fc9a49b3900f77ffaccf3ff69a70ddbc1d479e70ac5d8fd6416a7577b03c5a1",
"arm-unknown-linux-musleabihf-0.11.11":
"ef98cbcd50a62d063958740194497a44fc1dc07867b6fe001db1ab2e621f1f2e",
"armv7-unknown-linux-gnueabihf-0.11.11":
"c102609d34c06bdec87896d738a0e91df21f71faf21ae4379c7a1d7c961879e1",
"armv7-unknown-linux-musleabihf-0.11.11":
"6660651927263c587769697572f4843ac6ea91b2b2d24be1b9c8465e87d05b46",
"i686-pc-windows-msvc-0.11.11":
"c230fccbe5737e1a54a2f77ff3116c88fbee21c9b437323907618931b767410e",
"i686-unknown-linux-gnu-0.11.11":
"4be5e9901e87f90a9eb5ee11a08a8df2f637df76f3a2dcb11778991b7db9d9a2",
"i686-unknown-linux-musl-0.11.11":
"d2ded13fbaf59f5f1d3363c47a7cafb73cb7454db1e16cea13365bc28c75522d",
"powerpc64le-unknown-linux-gnu-0.11.11":
"5348415c8606e5efac5cb293d83d2ae71e43a2dcabf677c6a4cac965c1982c74",
"riscv64gc-unknown-linux-gnu-0.11.11":
"0eadf068918b960e7bf62eda83613c08d99f0d002b8d475d3383993191554d04",
"riscv64gc-unknown-linux-musl-0.11.11":
"0ee27ce77e32496bc46e01f1cbb730d13647cbca41934a5871bf2fe5fdc5ba39",
"s390x-unknown-linux-gnu-0.11.11":
"f19c950a93b1f5af4108267743f3de61346250b35c60cc552fb4187b534af770",
"x86_64-apple-darwin-0.11.11":
"57a1a8085b4088fbcbd5080c0c30723ba6d0692c89cd071c08a4209e8da602d1",
"x86_64-pc-windows-msvc-0.11.11":
"2f75a0db2c3530b6b3c24434dc38137f61ff1f4e5f2d7b4ddc5bcd142cf58b65",
"x86_64-unknown-linux-gnu-0.11.11":
"a767848254391855c96df271e9ca8b7f72dd172d310460447853d25d907b9ae0",
"x86_64-unknown-linux-musl-0.11.11":
"80521f18ba83109acd17e0730bd8ff898c3426aa62252c627d63418b353e788a",
"aarch64-apple-darwin-0.11.10":
"e93d6af7dfff7071edd16342ba9eeccfc28d8a7deaa5707efeecf63a63a74453",
"aarch64-pc-windows-msvc-0.11.10":
"3d5878cfc55106083ada1e41cccdde477413701eb9d34767e8ad973bb0863de6",
"aarch64-unknown-linux-gnu-0.11.10":
"91d5f4583539640765662ef86edcf3bf4db07439b622c7bed50c961240162046",
"aarch64-unknown-linux-musl-0.11.10":
"14c21bef6b54d268c6583d851095a543e6cb03a8e4bdca9a44ab91532b14cbc2",
"arm-unknown-linux-musleabihf-0.11.10":
"bea66b5dcfb3460a9a2c399033b071ec4a825ff3bf27c3fedc666dcbdc2354dd",
"armv7-unknown-linux-gnueabihf-0.11.10":
"ba259f6c14b5653f1b36400fb8c7862e499a4537201edda76991f2b044014fdb",
"armv7-unknown-linux-musleabihf-0.11.10":
"9d6e2ea60fae542e2bd9b36f44672e99fd941f7da0898533bc274329b001a055",
"i686-pc-windows-msvc-0.11.10":
"d56ad43d355d6c40fee4009d0fb7e6710416ce9b25bebf12a4127e51b3595b3c",
"i686-unknown-linux-gnu-0.11.10":
"ade0a830fd0b4b67c373c8ed1e46e5af2e312032ebbe15438beddeb5b1e4d8f3",
"i686-unknown-linux-musl-0.11.10":
"fb2ba8c938247f82908acf6ad41a19935b36d0fe7bbe6945ac1ba1f6044756fc",
"powerpc64le-unknown-linux-gnu-0.11.10":
"dfe5b338e2ebc1e5a2850a17bce35edb8e47550c221d9245c007eaf3003cb6ed",
"riscv64gc-unknown-linux-gnu-0.11.10":
"0c8776a0814bf7e32e025d13c733c3a800171a16fba77d1c21e6f10be6a28d8b",
"riscv64gc-unknown-linux-musl-0.11.10":
"8ae35c10dfcae262dee07c93a3d8d10c2ce597d4a152ba1a2f1385395a286ec3",
"s390x-unknown-linux-gnu-0.11.10":
"66dfdc5a216a9fbd7c2541a66f753544dddbcbb2f7a597c9bbc91d10af534c7d",
"x86_64-apple-darwin-0.11.10":
"8fd091211089973f528e147166e3af683ab4ecebd4312a55d0d17d87adbde67a",
"x86_64-pc-windows-msvc-0.11.10":
"7a0c424c7bc55a74751f13592235953ebbe182fa00355f7ae3fb7ab734a51638",
"x86_64-unknown-linux-gnu-0.11.10":
"077e1a0777bcf516e02f4ef245e269c8d1baa780438e4c50e09c5c997f85538a",
"x86_64-unknown-linux-musl-0.11.10":
"e3e78e7698d72c133c5ce851a6d60ee83afdc4c0edced382af9fd1f8e11d0105",
"aarch64-apple-darwin-0.11.9":
"7d02e5f206dcfb555284f8f6b8547890f0b8eb8987f44e9a0a2378cd23338733",
"aarch64-pc-windows-msvc-0.11.9":
"93de7822f6214c704ec15db1b4d33eabd3709a0303ec068723d9f5f5aa99e9e7",
"aarch64-unknown-linux-gnu-0.11.9":
"6d22be8d0d675668f657cee802a1344ea7941403f59eb2a6645ef316f69b4309",
"aarch64-unknown-linux-musl-0.11.9":
"31abb258d8ec2196993b82e746365717a86e3d3d55502b4c60f384540bf16306",
"arm-unknown-linux-musleabihf-0.11.9":
"60fd2f75fa0a927ce0373a9289e9490351be3142b00fb0e8da082ed652c7f23c",
"armv7-unknown-linux-gnueabihf-0.11.9":
"074f216882a79506f56f65413932dba9032ca6100285a562c48965688857970e",
"armv7-unknown-linux-musleabihf-0.11.9":
"0ebca62577232bab2c152fdd0fa81f78a28f8fd1f4f09689347759332aae996d",
"i686-pc-windows-msvc-0.11.9":
"9dbb9bf746f00dd379e7e1bd544a5e1b48a5f36408f75a7f8c6c89a7a5e5506a",
"i686-unknown-linux-gnu-0.11.9":
"84418c97aeadbbdb0b80090c43e29149c3d5c4a70c76ecffb738cd4a05d515d2",
"i686-unknown-linux-musl-0.11.9":
"f724d184888a52714229584536a3219f0c2fa416944fd476b52c7f597d9b3625",
"powerpc64le-unknown-linux-gnu-0.11.9":
"cbcdb1b6ee99ca69a572b75544dab484cd34e29109962f5945bb95ccd85d0d52",
"riscv64gc-unknown-linux-gnu-0.11.9":
"a825d1e6b62ca69971c50e6e356ebe478f7616a7873d9f7d7e17fb3efacabef2",
"riscv64gc-unknown-linux-musl-0.11.9":
"486b67c16381bb75d74daa86c091b36273cde617e0a2678e0b685b89047a6e6f",
"s390x-unknown-linux-gnu-0.11.9":
"caa3a59d49003d52c841625885bd60c87a957ed6173070af59c2ef7b4845b727",
"x86_64-apple-darwin-0.11.9":
"a974a0226ac5d3706ebaf660d3587b0dfb93ef9cf1fd146f97d40cd4ad69db98",
"x86_64-pc-windows-msvc-0.11.9":
"facbf9637c373761a96fa63c537d6c46581d357a65af01eacfd8c6319e6fb14e",
"x86_64-unknown-linux-gnu-0.11.9":
"5c43f82077ff0cd5aec588286cbabd89913e4d045bd4e8aa60b20b3ecffc36e3",
"x86_64-unknown-linux-musl-0.11.9":
"ac3e5051edbf30613b0f90d1c18d4807fea6b246f37490799fee0c1284a658b2",
"aarch64-apple-darwin-0.11.8":
"c729adb365114e844dd7f9316313a7ed6443b89bb5681d409eebac78b0bd06c8",
"aarch64-pc-windows-msvc-0.11.8":
"bb48716e74e4998993f15bc57a55e4d0d73ccbd27a66d7cbed37605f7c67d747",
"aarch64-unknown-linux-gnu-0.11.8":
"eee8dd658d20e5ac85fec9c2326b6cbc9d83a1eef09ef07433e58698ac849591",
"aarch64-unknown-linux-musl-0.11.8":
"29418befb64f926a2dba3473e8e69acd00b36fb845d85344ef11321a993ad8f5",
"arm-unknown-linux-musleabihf-0.11.8":
"858f50a1164e9d2e3d1641a5f9d81a8b098025bd4f40011882df4f6b7d6ee393",
"armv7-unknown-linux-gnueabihf-0.11.8":
"b0674ede45b797362f34af0a75d6391e844992ae92a9c181a353e3892af4c325",
"armv7-unknown-linux-musleabihf-0.11.8":
"eda6e549a1d3bea67de6550e84b05d75e5538350bf50ba229840ec92063f153e",
"i686-pc-windows-msvc-0.11.8":
"59520c34c3c29a901bb490d4bec55a8e1d46c75d2fbad238871e18de733b4201",
"i686-unknown-linux-gnu-0.11.8":
"4a82441b70adc3886a4f9c29a1070f104ed73c7e68d14cfa6d6343a8ce0c4ccc",
"i686-unknown-linux-musl-0.11.8":
"56b8e8874ba09194c580583697c09cbe6c31626e5bb4cfb1f8bfbf4998a8d6c6",
"powerpc64le-unknown-linux-gnu-0.11.8":
"7b66bcc99237d19fb25d8b1bcbc1f973f735027d49e7cb9ffa22cd539fefccbc",
"riscv64gc-unknown-linux-gnu-0.11.8":
"dd43289c567fda3ca59ec714ffca09125f1149289448667f36a4bb7c29c859be",
"riscv64gc-unknown-linux-musl-0.11.8":
"c06b5bbbfecb258f869b18168abb46ef974a76c786fa9350923b1cf38d1661a0",
"s390x-unknown-linux-gnu-0.11.8":
"068eb3f47d0760d50cd2e0fc59cc2c09eb12a4ec8bb12c269f3aef706bf4dc1a",
"x86_64-apple-darwin-0.11.8":
"c59d73bf34b58bc8e33a11629f7a255c11789fd00f03cd3e68ab2d1603645de9",
"x86_64-pc-windows-msvc-0.11.8":
"c84629a56e0706b69a47ea35862208af827cb6fbfa1d0ca763c52c67594637e8",
"x86_64-unknown-linux-gnu-0.11.8":
"56dd1b66701ecb62fe896abb919444e4b83c5e8645cca953e6ddd496ff8a0feb",
"x86_64-unknown-linux-musl-0.11.8":
"de82507d12e31cfc86c1c776238f7c248e48e40d996dedc812d64fdd31c6ed12",
"aarch64-apple-darwin-0.11.7":
"66e37d91f839e12481d7b932a1eccbfe732560f42c1cfb89faddfa2454534ba8",
"aarch64-pc-windows-msvc-0.11.7":
"1387e1c94e15196351196b79fce4c1e6f4b30f19cdaaf9ff85fbd6b046018aa2",
"aarch64-unknown-linux-gnu-0.11.7":
"f2ee1cde9aabb4c6e43bd3f341dadaf42189a54e001e521346dc31547310e284",
"aarch64-unknown-linux-musl-0.11.7":
"46647dc16cbb7d6700f762fdd7a67d220abe18570914732bc310adc91308d272",
"arm-unknown-linux-musleabihf-0.11.7":
"238974610607541ccdb3b8f4ad161d4f2a4b018d749dc9d358b0965d9a1ddd0f",
"armv7-unknown-linux-gnueabihf-0.11.7":
"7aa9ddc128f58c0e667227feb84e0aac3bb65301604c5f6f2ab0f442aaaafd99",
"armv7-unknown-linux-musleabihf-0.11.7":
"77a237761579125b822d604973a2d4afb62b10a8f066db4f793906deec66b017",
"i686-pc-windows-msvc-0.11.7":
"04652b46b1be90a753e686b839e109a79af3d032ba96d3616c162dffdbe89e5c",
"i686-unknown-linux-gnu-0.11.7":
"9c77e5b5f2ad4151c6dc29db5511af549e205dbd6e836e544c80ebfadd7a07ec",
"i686-unknown-linux-musl-0.11.7":
"b067ce3e92d04425bc11b84dc350f97447d3e8dffafccb7ebebde54a56bfc619",
"powerpc64le-unknown-linux-gnu-0.11.7":
"6ac23c519d1b06297e1e8753c96911fadee5abab4ca35b8c17da30e3e927d8ac",
"riscv64gc-unknown-linux-gnu-0.11.7":
"2052356c7388d26dc4dfcf2d44e28b3f800785371f37c5f37d179181fe377659",
"riscv64gc-unknown-linux-musl-0.11.7":
"219a25e413efb62c8ef3efb3593f1f01d9a3c22d1facf3b9c0d80b7caf3a5e56",
"s390x-unknown-linux-gnu-0.11.7":
"760152aa9e769712d52b6c65a8d7b86ed3aac25a24892cf5998a522d84942f9e",
"x86_64-apple-darwin-0.11.7":
"0a4bc8fcde4974ea3560be21772aeecab600a6f43fa6e58169f9fa7b3b71d302",
"x86_64-pc-windows-msvc-0.11.7":
"fe0c7815acf4fc45f8a5eff58ed3cf7ae2e15c3cf1dceadbd10c816ec1690cc1",
"x86_64-unknown-linux-gnu-0.11.7":
"6681d691eb7f9c00ac6a3af54252f7ab29ae72f0c8f95bdc7f9d1401c23ea868",
"x86_64-unknown-linux-musl-0.11.7":
"64ddb5f1087649e3f75aa50d139aa4f36ddde728a5295a141e0fa9697bfb7b0f",
"aarch64-apple-darwin-0.11.6":
"4b69a4e366ec38cd5f305707de95e12951181c448679a00dce2a78868dfc9f5b",
"aarch64-pc-windows-msvc-0.11.6":
"bee7b25a7a999f17291810242b47565c3ef2b9205651a0fd02a086f261a7e167",
"aarch64-unknown-linux-gnu-0.11.6":
"d5be4bf7015ea000378cb3c3aba53ba81a8673458ace9c7fa25a0be005b74802",
"aarch64-unknown-linux-musl-0.11.6":
"d14ebd6f200047264152daaf97b8bd36c7885a5033e9e8bba8366cb0049c0d00",
"arm-unknown-linux-musleabihf-0.11.6":
"4410a9489e0a29ce8f86fc8604b75a3dd821e9e52734282cbb413b4e19c5c70a",
"armv7-unknown-linux-gnueabihf-0.11.6":
"9758d49c200c211ccb2c9cbf43877102031c3457e80b6c3cb9da1e4c00119d2a",
"armv7-unknown-linux-musleabihf-0.11.6":
"0677423d98cea5011d346d7d4a33a53360b99a51a04df4b45f67d43a8308c831",
"i686-pc-windows-msvc-0.11.6":
"c5569da150166363389a719553d87f99e0c29e542b2c31bc8bd4aeeb8eb83d99",
"i686-unknown-linux-gnu-0.11.6":
"b4bf8d78478b573c1816b17ec86da7ade14242cd68ac092c1701c5b4a75dc228",
"i686-unknown-linux-musl-0.11.6":
"ca31705d93f48313d5ffdc23da165e680c6c5389d9a2cc62b85a1ed495e0331f",
"powerpc64le-unknown-linux-gnu-0.11.6":
"153397d3d82e45e68fb1f4a40ee9898245ec8ed86fd03fcaacaf6e793316acf7",
"riscv64gc-unknown-linux-gnu-0.11.6":
"0e3ead8667b51b07b5fb9d114bcd1914a5fe3159e6959a584dc2f89c6724e123",
"riscv64gc-unknown-linux-musl-0.11.6":
"87d5932bffef3b7b9cba4a2a042f95edf75cd34555fc80cfa98cc5a4426635f9",
"s390x-unknown-linux-gnu-0.11.6":
"6e3d4338da2db2c63326721f1eb3b4f32d9bde24aeff11208d397e1aeba8678e",
"x86_64-apple-darwin-0.11.6":
"8e0ed5035eaa28c7c8cd2a46b5b9a05bfff1ef01dbdc090a010eb8fdf193a457",
"x86_64-pc-windows-msvc-0.11.6":
"99aa60edd017a256dbf378f372d1cff3292dbc6696e0ea01716d9158d773ab77",
"x86_64-unknown-linux-gnu-0.11.6":
"0c6bab77a67a445dc849ed5e8ee8d3cb333b6e2eba863643ce1e228075f27943",
"x86_64-unknown-linux-musl-0.11.6":
"aa342a53abe42364093506d7704214d2cdca30b916843e520bc67759a5d20132",
"aarch64-apple-darwin-0.11.5":
"470993e87503874c7c48861daa308b48a7c367e117235bbecf19368b9fdd35b2",
"aarch64-pc-windows-msvc-0.11.5":
"9b9b99a985cccf249225aaad76412823e9d9736d605dc2252151172a7f6ab3db",
"aarch64-unknown-linux-gnu-0.11.5":
"3e9b525d686ae4f3682412bce21536366a5c79616a41055530319c501c883169",
"aarch64-unknown-linux-musl-0.11.5":
"d73860013061c62d6a89f3370527d4c407214038af331147773ae2fd8f6394c1",
"arm-unknown-linux-musleabihf-0.11.5":
"dcfb4dc15f46eae90ac6d64e7dfc91d8bc0b16816f53b9f8d58ccc8a1220dbb8",
"armv7-unknown-linux-gnueabihf-0.11.5":
"818d86386fb57ca4182f39df25dd6160e97300d5ba362bc44e25d8adc904776c",
"armv7-unknown-linux-musleabihf-0.11.5":
"2cae8baae2c1b42249e656e16f5fe733189b0760ee93995be024f9cc5e72eb19",
"i686-pc-windows-msvc-0.11.5":
"2057ccf3dba9ed23755df92318a08ab221e9e088385c667292acc09d9cc477c6",
"i686-unknown-linux-gnu-0.11.5":
"2d340e2e5b3354ee7208bb8f2bbf4d2347d7ffdf2af733c21bee98746e34076d",
"i686-unknown-linux-musl-0.11.5":
"ffe2bc9e0c4fdc18f69b7c5bc016a03fa17028d42620ab2b024ad5bb22cd3f3d",
"powerpc64le-unknown-linux-gnu-0.11.5":
"c4dabaaa36a13989ab04389263064ca5c27093eb2e7c851ab62d50b6312d9800",
"riscv64gc-unknown-linux-gnu-0.11.5":
"6ae3ec3cf1aab72604bc6aa8486faf4b473066422c49d9c42ea8366ff3039de4",
"riscv64gc-unknown-linux-musl-0.11.5":
"d4686fb144563a40e791fc3f010a91e57fdce9cac7a03b8a14a972c25be4464c",
"s390x-unknown-linux-gnu-0.11.5":
"1309f1e462462dab2da6a55c37012a228d1c06a55c5b43f8ef901ba1599d9e12",
"x86_64-apple-darwin-0.11.5":
"b8964bed538143f9016d807e421e28f0237a29589851fc79e8159751ac64779a",
"x86_64-pc-windows-msvc-0.11.5":
"3fa5b6ea9de9256a035e0471f5ef0bb5d95344659723d6eb063e27c76431515d",
"x86_64-unknown-linux-gnu-0.11.5":
"0d87793f733f327849ebf9cf51b576cfb08328e22af73061405e4bec96ae84d1",
"x86_64-unknown-linux-musl-0.11.5":
"ee8a52743ce3979e52872b49c5e58ffa541048cb95132142bff23fe5608d73ea",
"aarch64-apple-darwin-0.11.4":
"9b9cb6c6f58c3246dbf3351ed4e97c500bc3266f5f237d2fd620b66e1c31dc56",
"aarch64-pc-windows-msvc-0.11.4":
"708b1c210109e50ff520bcd9b6d29cbd8cee584bb55e84d3d1941bf75ab0893d",
"aarch64-unknown-linux-gnu-0.11.4":
"f5aa91bba0b98d85a4e5262e2847f9ab2273c754f6374dff62b37ef18c65a2e7",
"aarch64-unknown-linux-musl-0.11.4":
"a02ec7667d7bb1d33cdb7e1de22f7e4242967e3df7e350bac6212515e3bce8ac",
"arm-unknown-linux-musleabihf-0.11.4":
"5bbc59d8c3d5fdade88fca47e4c18298e44a367e178e97e11466b22e992edae2",
"armv7-unknown-linux-gnueabihf-0.11.4":
"9d2299155b65988643a55777c638408a0df8e65f606933d1e44691ada72ff106",
"armv7-unknown-linux-musleabihf-0.11.4":
"43b1e02f8f4b27fd1d085fb14a246638bb607af32408cb13c5c3b3fb47db027f",
"i686-pc-windows-msvc-0.11.4":
"661588b3607e6d5bb78551f596772a0d04a930ce128189c90800d07f6fca1998",
"i686-unknown-linux-gnu-0.11.4":
"4248773a2574c3b697588655d7bf14f97baa744c3e156585230e5c711befa6ff",
"i686-unknown-linux-musl-0.11.4":
"0323c08c1e7455cdf65c89296eda28bad9051cb09d16ea3ce1d0bf718143449e",
"powerpc64le-unknown-linux-gnu-0.11.4":
"3ddb764538a5dcb4967d7375fde193ce5391e37ddd4d1242012d04cf3848479f",
"riscv64gc-unknown-linux-gnu-0.11.4":
"93db93607a824d677c47003ee828936913cfdeb2c871bb34cd79c3ec4481e2b1",
"riscv64gc-unknown-linux-musl-0.11.4":
"78f0d7f92244ce3d7a7a0df5fab2495450bcb18600b59acf1755e77cafed2300",
"s390x-unknown-linux-gnu-0.11.4":
"07361e1fb32e870841a27d3d7b0b20c4a81e0cc25eeb8b9115425bfd227d2d05",
"x86_64-apple-darwin-0.11.4":
"c326edaf3fd492f53d1c58777f3459c0d87bf9dae8d89e80aec4b0da6622dcf3",
"x86_64-pc-windows-msvc-0.11.4":
"26d84455a40b0272b2ab4785cad298ff2c89cd0765b482e9f85b5a1bd880a863",
"x86_64-unknown-linux-gnu-0.11.4":
"12f9a192bb32d70470aa22cbd2a193d1323a3f58f6ac5f9e3866aaca760c98c6",
"x86_64-unknown-linux-musl-0.11.4":
"36ce1c5d8997db9b6a24d0f41646d5509b6d1d8b9448c7325f8248a6ea5d4b00",
"aarch64-apple-darwin-0.11.3":
"2bc3d0c7bf2bd08325b1e170abac6f7e5b3346e1d4eab3370d17cefec934996f",
"aarch64-pc-windows-msvc-0.11.3":
"e99c56f9ab5e1e1ddcaea3e2389990c94baf38e0d7cb2148de08baf2d3261d49",
"aarch64-unknown-linux-gnu-0.11.3":
"711382e3158433f06b11d99afb440f4416359fc3c84558886d8ed8826a921bff",
"aarch64-unknown-linux-musl-0.11.3":
"8ecec82cb9a744d5fabff6d16d7777218a7730f699d2aa0d2f751c17858e2efa",
"arm-unknown-linux-musleabihf-0.11.3":
"3d021046a94ad11f12b9d83f36442a1a28e92e7149c3f79ba2951c96653dafac",
"armv7-unknown-linux-gnueabihf-0.11.3":
"13c9a0f5f624275ccd36db2896607f4fee3585f420734b16f6c66d70e32aa458",
"armv7-unknown-linux-musleabihf-0.11.3":
"260a88e2f00daab0363a745fde036a7881002d7a81094388f31925acb284110b",
"i686-pc-windows-msvc-0.11.3":
"036fa39fa5ea3cb86c127324924b913b5858e8d91c4cb413edacfc3123001696",
"i686-unknown-linux-gnu-0.11.3":
"b9410c8dae2fa0d4939af5b0ee7272d5591bd55890e8274dcf7f1aea84bfe043",
"i686-unknown-linux-musl-0.11.3":
"afe533fd409105e753d844490c65a4375e75bfb3812e49122684f996bed9e90a",
"powerpc64le-unknown-linux-gnu-0.11.3":
"5cdcadf4d50a5354312bc8ef37c2a6cfab4e2f13ccdf8380d3012b927b4ded95",
"riscv64gc-unknown-linux-gnu-0.11.3":
"8271e07ed9695870f4b0ae5ec722e3ae08fff280068f08bc6a8ca76c67d7fefa",
"riscv64gc-unknown-linux-musl-0.11.3":
"b750fc8393ced9939448849b05e94de6bf1e998bb7030c4ebe744b47b372bce9",
"s390x-unknown-linux-gnu-0.11.3":
"6dc4f555a5f6515f7fddb281422d2a8a3943853dae5de837bbb5d996d7576c71",
"x86_64-apple-darwin-0.11.3":
"b0e05e0b43a000fdc2132ee3f3400ba5dee427bc2337d3ec4eb8cf4f3d5722af",
"x86_64-pc-windows-msvc-0.11.3":
"ae681c0aaec7cc96af184648cb88d73f8393ed60fa5880abdd6bdb910f9b227c",
"x86_64-unknown-linux-gnu-0.11.3":
"c0f3236f146e55472663cfbcc9be3042a9f1092275bbe3fe2a56a6cbfd3da5ce",
"x86_64-unknown-linux-musl-0.11.3":
"8b40cf16b849634b81a530a3d0a0bcae5f24996ef9ae782976fd69b6266d3b8e",
"aarch64-apple-darwin-0.11.2":
"4beaa9550f93ef7f0fc02f7c28c9c48cd61fe30db00f5ac8947e0a425c3fb282",
"aarch64-pc-windows-msvc-0.11.2":
"ffdded8338205f53727b51d404563a5ac8eaa9aea53279a7b7c42177e11d478c",
"aarch64-unknown-linux-gnu-0.11.2":
"04792cac761c4a6ba78267f36f2af541b7f92196d42ac55d21d3ff6b0f5ab6a5",
"aarch64-unknown-linux-musl-0.11.2":
"275d91dd1f1955136591e7ec5e1fa21e84d0d37ead7da7c35c3683df748d9855",
"arm-unknown-linux-musleabihf-0.11.2":
"ce572dac1a8f9a92960f89e99351352fae068d34b24bed86fb88e75fd5dd67d9",
"armv7-unknown-linux-gnueabihf-0.11.2":
"3e90d7de9e3a4e2d8d1bd9ce164362fce22248474986e712039479fb6fd73136",
"armv7-unknown-linux-musleabihf-0.11.2":
"5222cdd7c7dd3263f8c243831606a9f01a1a07a40ffc3c26c03afb34491075c2",
"i686-pc-windows-msvc-0.11.2":
"506f8274b253b2386881a121f3b7d915b637019bda15876bbd1357235305cf12",
"i686-unknown-linux-gnu-0.11.2":
"c7ec378bab887443a70786382e58d76489da14a7e33b155915d648cca4bdb46c",
"i686-unknown-linux-musl-0.11.2":
"ade8714be45457899568c5b03ef885a0cc94476c07a0bdbe34531ba84231bab2",
"powerpc64le-unknown-linux-gnu-0.11.2":
"3f3a50e99364efc8ff7add10e79757a2b8458700a38180ec5f313524481b9fbc",
"riscv64gc-unknown-linux-gnu-0.11.2":
"e56a93f0ff21d6908461a6ecbf465beae19ae22719f900284abb7680bd07ec41",
"riscv64gc-unknown-linux-musl-0.11.2":
"4f263571bb457a16a31cb38fba4fcc9cf1059d1d32c5b2e54c43175fcd59205d",
"s390x-unknown-linux-gnu-0.11.2":
"42ebe40775f2a77a514fa47399fde86473bf35bd33b6896c6410a0309fc4d205",
"x86_64-apple-darwin-0.11.2":
"a9c3653245031304c50dd60ac0301bf6c112e12c38c32302a71d4fa6a63ba2cb",
"x86_64-pc-windows-msvc-0.11.2":
"171b7ccda1bbd562da6babeffcf533a1c6cc7862cf998da826e1db534fc43e48",
"x86_64-unknown-linux-gnu-0.11.2":
"7ac2ca0449c8d68dae9b99e635cd3bc9b22a4cb1de64b7c43716398447d42981",
"x86_64-unknown-linux-musl-0.11.2":
"4700d9fc75734247587deb3e25dd2c6c24f4ac69e8fe91d6acad4a6013115c06",
"aarch64-apple-darwin-0.11.1":
"f7815f739ed5d0e4202e6292acedb8659b9ae7de663d07188d8c6cbd7f96303f",
"aarch64-pc-windows-msvc-0.11.1":
"b789db0c1504dd3b02c090bd5783487497cc46cc2eb71754874cdd1ef59eb52a",
"aarch64-unknown-linux-gnu-0.11.1":
"1340e62da1ee3c1109764340e1247e8a1a232c30dde4a0f0548976dcaa90f06d",
"aarch64-unknown-linux-musl-0.11.1":
"bd04ffce77ee8d77f39823c13606183581847c2f5dcd704f2ea0f15e376b1a27",
"arm-unknown-linux-musleabihf-0.11.1":
"625c0e756e2374fce864ceaa6beedd5821e276e2b6307f2b719f2d62b449b89c",
"armv7-unknown-linux-gnueabihf-0.11.1":
"baf8daaab20b0502d1853dbfd916afb0762c024ae7f0df1c2deb2a1a1c1c3467",
"armv7-unknown-linux-musleabihf-0.11.1":
"684c25b74e83bcb1b177152379cfe2c974ba731aa5af278e1d161e41709f8bcf",
"i686-pc-windows-msvc-0.11.1":
"3c07858a08c54e4e5753239354c7b07ae69071b2b6f5aa2cc970e612adcb4740",
"i686-unknown-linux-gnu-0.11.1":
"6e83167c05708570563b10b6cc7e8c289daef5f51fde0b152e41af2a7ef70813",
"i686-unknown-linux-musl-0.11.1":
"b0d5152635c257fec76f95cb9268112b47ff70bd33a23866295a4f2ed9f46b7f",
"powerpc64le-unknown-linux-gnu-0.11.1":
"e42d2abfac46f57564789e2bfa6dbea4ae3135892e36ae066ba0ae77b69bb676",
"riscv64gc-unknown-linux-gnu-0.11.1":
"5e2c757b35dab015ad37f74ee3e060208390b5f4defb6684876f1be0664f3f6e",
"riscv64gc-unknown-linux-musl-0.11.1":
"6f590a824aed363cbec4079f7ddab87b5685119e0f5f0e71cd114c7b7c326199",
"s390x-unknown-linux-gnu-0.11.1":
"4208173c74e29572b799178709b5ed5828b24888659f944a4b47c0aaf78b42d2",
"x86_64-apple-darwin-0.11.1":
"2103670e8e949605e51926c7b953923ff6f6befbfb55aee928f5e760c9c910f8",
"x86_64-pc-windows-msvc-0.11.1":
"6659250cebbd3bb6ee48bcb21a3f0c6656450d63fb97f0f069bcb532bdb688ed",
"x86_64-unknown-linux-gnu-0.11.1":
"7c0c8069053e6e99e5911ff32b916be571f3419cd8e11bd28fb7da2c7dcaa553",
"x86_64-unknown-linux-musl-0.11.1":
"4e949471a95b37088a1ff1a585f69abed4d3cd3f921f50709a46b6ba62986d38",
"aarch64-apple-darwin-0.11.0":
"0c0f32c6a3473c5928aff96c3233715edfc79290e892f255cac93710cde7b91a",
"aarch64-pc-windows-msvc-0.11.0":
"95419e04a3ef5f13fb2a06bd6d787ba80a9d8981d6f097780e5a979817a2879d",
"aarch64-unknown-linux-gnu-0.11.0":
"8e179ca110343a17f801444ff9ef117dba56ef5fc9f6a4c9bb77b318ddba5f24",
"aarch64-unknown-linux-musl-0.11.0":
"658be4b8ec905635f1295468d4d5120d9e1ab1722eec9a104473ce993590babe",
"arm-unknown-linux-musleabihf-0.11.0":
"bfdcbd5fa41c8a9877a72c2b55a95da2bc79933885ef56c699b65bb2ed9cea91",
"armv7-unknown-linux-gnueabihf-0.11.0":
"0cad4e1b6769e48aa1e80cf639ddcc7c1bfe9ed017e95868fed185a8d818c949",
"armv7-unknown-linux-musleabihf-0.11.0":
"2aa9da83c6c0cf8a06bc9df14d51056284fa067ef5390b4db79998ff12f3bee7",
"i686-pc-windows-msvc-0.11.0":
"3b09d70e686087e096dbd8a2af21b922a2cac7d613dc053c3281c3ddbb961961",
"i686-unknown-linux-gnu-0.11.0":
"59928a0267501c20d9f9942f5f1d81a991ec55e29a19e002ae3d5c178c674c89",
"i686-unknown-linux-musl-0.11.0":
"1f438d6f6f851f0dabad3307ce7fd46541ecc5c42ebb664f382eb6c9a424a67d",
"powerpc64le-unknown-linux-gnu-0.11.0":
"29f17fb43595492b1a36cda57df7adad74183132df32799d32897268ff4e26dd",
"riscv64gc-unknown-linux-gnu-0.11.0":
"84ef37dda1003c5b65fa6c8f84242d35a7fcc84cc5ea9490d702edc36cad1f67",
"s390x-unknown-linux-gnu-0.11.0":
"b25be62f3b642348a2fece5c658624586661b8d1103891ab6903768b0529edc4",
"x86_64-apple-darwin-0.11.0":
"31aaec764166af8885cf99321fd6ed24fef80225a6f26ed1ae8ce04111688a7e",
"x86_64-pc-windows-msvc-0.11.0":
"e21d00b172df83531564a95e75a2bdc0c59b471dbb3515f0c1b4d6ef657dc451",
"x86_64-unknown-linux-gnu-0.11.0":
"cc0fbb42b3642125f600a55b0b095bea65cddaadb94c6ea2b6ba5d79c5825089",
"x86_64-unknown-linux-musl-0.11.0":
"bf6b0757c73d1726faa2a819b155d4d864919a95766720215d78fdcd09d42d26",
"aarch64-apple-darwin-0.10.12":
"ae738b5661a900579ec621d3918c0ef17bdec0da2a8a6d8b161137cd15f25414",
"aarch64-pc-windows-msvc-0.10.12":
"e79881e2c4f98a0f3a37b8770bf224e8fee70f6dcf8fc17055d8291bb1b0b867",
"aarch64-unknown-linux-gnu-0.10.12":
"0ed7d20f49f6b9b60d45fdfcac28f3ac01a671a6ef08672401ed2833423fea2a",
"aarch64-unknown-linux-musl-0.10.12":
"55bd1c1c10ec8b95a8c184f5e18b566703c6ab105f0fc118aaa4d748aabf28e4",
"arm-unknown-linux-musleabihf-0.10.12":
"9714e5059b05110a1c7ddbc18c971c13e0260e10551b7b77d82cbf907a4ebd9b",
"armv7-unknown-linux-gnueabihf-0.10.12":
"eaa02f36d5112029601b18ac3d1a0c03a83bb20cb4154c2f5345f777fa6c4101",
"armv7-unknown-linux-musleabihf-0.10.12":
"bd735652298c6e62cdd2ac939babe176a3356613e6803baa33d0bc10e8d9e4ed",
"i686-pc-windows-msvc-0.10.12":
"2312e75b9c77befdc1bff30da18f16df03083452852952553bee91da362c1a1d",
"i686-unknown-linux-gnu-0.10.12":
"8501844b34e3a28cfbba5a4b857eebd696d952e0bb4160357451ad80f3f49db8",
"i686-unknown-linux-musl-0.10.12":
"56cad78abcf5b710d2f7b9f774fcfd6bbed340d2aa9d9fc9e3b515542ec5e953",
"powerpc64le-unknown-linux-gnu-0.10.12":
"3c8017d9112221c83f43e8a15a58099663c0b2bdeabc8b43bb800413dfa21218",
"riscv64gc-unknown-linux-gnu-0.10.12":
"b1ca482b6b5dd7bf6ab733a3695cb0ab5b8e992ca96527efae93aa78fcc52a9b",
"s390x-unknown-linux-gnu-0.10.12":
"e1a0345eefe6fd3300948cd6f18aab092f9b88a243782113e645ce96530a6693",
"x86_64-apple-darwin-0.10.12":
"17443e293f2ae407bb2d8d34b875ebfe0ae01cf1296de5647e69e7b2e2b428f0",
"x86_64-pc-windows-msvc-0.10.12":
"4c1d55501869b3330d4aabf45ad6024ce2367e0f3af83344395702d272c22e88",
"x86_64-unknown-linux-gnu-0.10.12":
"ec72570c9d1f33021aa80b176d7baba390de2cfeb1abcbefca346d563bf17484",
"x86_64-unknown-linux-musl-0.10.12":
"adccf40b5d1939a5e0093081ec2307ea24235adf7c2d96b122c561fa37711c46",
"aarch64-apple-darwin-0.10.11":
"437a7d498dd6564d5bf986074249ba1fc600e73da55ae04d7bd4c24d5f149b95",
"aarch64-pc-windows-msvc-0.10.11":
"6a3eec4105c775dd87c11ef8ec41564648273751ff807c8955c24ddbcc636d03",
"aarch64-unknown-linux-gnu-0.10.11":
"23003df007937dd607409c8ddf010baa82bad2673e60e254632ca5b04edcce13",
"aarch64-unknown-linux-musl-0.10.11":
"5d80a7f6343d2676dfde1e5126582070a2bbc62df6f60d5527a169be3788532a",
"arm-unknown-linux-musleabihf-0.10.11":
"d3c248497c450d22a39c1d43a4a358c0c852e6056f5f49be96495eea41afb96c",
"armv7-unknown-linux-gnueabihf-0.10.11":
"7895a6470dfba051af4e74253599482fc0b37141b5d229956b383365e1a22902",
"armv7-unknown-linux-musleabihf-0.10.11":
"d2880c08acfdaef0985488972c8b14969f7139c27545046e2f6202f0e0f4d9d8",
"i686-pc-windows-msvc-0.10.11":
"c17f3dc3b2c47490057f17a1f0c37270f11a7b7cedf9bf2c0f841ce02bc7001b",
"i686-unknown-linux-gnu-0.10.11":
"1ab69ff7dd104a902731758ee05b782dfd9bdb263384e61650de638f33f586df",
"i686-unknown-linux-musl-0.10.11":
"cffb80d303fc1655e259d0b769c489f452e97425a6b6d3393d766413783a1d8c",
"powerpc64le-unknown-linux-gnu-0.10.11":
"ddc6a20670e60219e947b1b04813be80d7e9f4c4a0234231c8ed9298eec04aa6",
"riscv64gc-unknown-linux-gnu-0.10.11":
"c0719473cf5f8b475e917b8dfef6ae5d876b86a00a82ef91e47a02f561399f4f",
"s390x-unknown-linux-gnu-0.10.11":
"305ee734c585918515a22fe43b7cf253c38d468771373a0c02364d67498e07b2",
"x86_64-apple-darwin-0.10.11":
"ff90020b554cf02ef8008535c9aab6ef27bb7be6b075359300dec79c361df897",
"x86_64-pc-windows-msvc-0.10.11":
"9ee74df98582f37fdd6069e1caac80d2616f9a489f5dbb2b1c152f30be69c58e",
"x86_64-unknown-linux-gnu-0.10.11":
"5a360b0de092ddf4131f5313d0411b48c4e95e8107e40c3f8f2e9fcb636b3583",
"x86_64-unknown-linux-musl-0.10.11":
"d78246139dc6cf3ed6d03c84da762686bced7ad1de67977ee372a45b95a1f6d0",
"aarch64-apple-darwin-0.10.10": "aarch64-apple-darwin-0.10.10":
"8a09f0ef51ee7f7170731b4cb8bde5bf9ba6da5304f49a7df6cdab42a1f37b5d", "8a09f0ef51ee7f7170731b4cb8bde5bf9ba6da5304f49a7df6cdab42a1f37b5d",
"aarch64-pc-windows-msvc-0.10.10": "aarch64-pc-windows-msvc-0.10.10":

View File

@@ -2,18 +2,22 @@ import { promises as fs } from "node:fs";
import * as path from "node:path"; import * as path from "node:path";
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as tc from "@actions/tool-cache"; import * as tc from "@actions/tool-cache";
import { import * as pep440 from "@renovatebot/pep440";
ASTRAL_MIRROR_PREFIX, import * as semver from "semver";
GITHUB_RELEASES_PREFIX, import { TOOL_CACHE_NAME, VERSIONS_NDJSON_URL } from "../utils/constants";
TOOL_CACHE_NAME,
VERSIONS_MANIFEST_URL,
} from "../utils/constants";
import * as log from "../utils/logging";
import type { Architecture, Platform } from "../utils/platforms"; import type { Architecture, Platform } from "../utils/platforms";
import { validateChecksum } from "./checksum/checksum"; import { validateChecksum } from "./checksum/checksum";
import { getArtifact } from "./manifest"; import {
getAllVersions as getAllManifestVersions,
export { resolveVersion } from "../version/resolve"; getLatestKnownVersion as getLatestVersionInManifest,
getManifestArtifact,
} from "./version-manifest";
import {
getAllVersions as getAllVersionsFromNdjson,
getArtifact as getArtifactFromNdjson,
getHighestSatisfyingVersion as getHighestSatisfyingVersionFromNdjson,
getLatestVersion as getLatestVersionFromNdjson,
} from "./versions-client";
export function tryGetFromToolCache( export function tryGetFromToolCache(
arch: Architecture, arch: Architecture,
@@ -30,101 +34,75 @@ export function tryGetFromToolCache(
return { installedPath, version: resolvedVersion }; return { installedPath, version: resolvedVersion };
} }
export async function downloadVersion( export async function downloadVersionFromNdjson(
platform: Platform, platform: Platform,
arch: Architecture, arch: Architecture,
version: string, version: string,
checksum: string | undefined, checkSum: string | undefined,
githubToken: string, githubToken: string,
manifestUrl?: string,
downloadFromAstralMirror = true,
): Promise<{ version: string; cachedToolDir: string }> { ): Promise<{ version: string; cachedToolDir: string }> {
const artifact = await getArtifact(version, arch, platform, manifestUrl); const artifact = await getArtifactFromNdjson(version, arch, platform);
if (!artifact) { if (!artifact) {
throw new Error( throw new Error(
getMissingArtifactMessage(version, arch, platform, manifestUrl), `Could not find artifact for version ${version}, arch ${arch}, platform ${platform} in ${VERSIONS_NDJSON_URL} .`,
); );
} }
// For the default astral-sh/versions source, checksum validation relies on // For the default astral-sh/versions source, checksum validation relies on
// user input or the built-in KNOWN_CHECKSUMS table, not manifest sha256 values. // user input or the built-in KNOWN_CHECKSUMS table, not NDJSON sha256 values.
const resolvedChecksum = return await downloadVersion(
manifestUrl === undefined artifact.url,
? checksum `uv-${arch}-${platform}`,
: resolveChecksum(checksum, artifact.checksum); platform,
arch,
const mirrorUrl = downloadFromAstralMirror version,
? rewriteToMirror(artifact.downloadUrl) checkSum,
: undefined; githubToken,
const downloadUrl = mirrorUrl ?? artifact.downloadUrl; );
try {
return await downloadArtifact(
downloadUrl,
`uv-${arch}-${platform}`,
platform,
arch,
version,
resolvedChecksum,
githubTokenForUrl(downloadUrl, githubToken),
);
} catch (err) {
if (mirrorUrl === undefined) {
throw err;
}
log.warning(
`Failed to download from mirror, falling back to GitHub Releases: ${(err as Error).message}`,
);
return await downloadArtifact(
artifact.downloadUrl,
`uv-${arch}-${platform}`,
platform,
arch,
version,
resolvedChecksum,
githubTokenForUrl(artifact.downloadUrl, githubToken),
);
}
} }
/** export async function downloadVersionFromManifest(
* Rewrite a GitHub Releases URL to the Astral mirror. manifestUrl: string,
* Returns `undefined` if the URL does not match the expected GitHub prefix. platform: Platform,
*/ arch: Architecture,
export function rewriteToMirror(url: string): string | undefined { version: string,
if (!url.startsWith(GITHUB_RELEASES_PREFIX)) { checkSum: string | undefined,
return undefined;
}
return ASTRAL_MIRROR_PREFIX + url.slice(GITHUB_RELEASES_PREFIX.length);
}
function githubTokenForUrl(
downloadUrl: string,
githubToken: string, githubToken: string,
): string | undefined { ): Promise<{ version: string; cachedToolDir: string }> {
try { const artifact = await getManifestArtifact(
return new URL(downloadUrl).origin === "https://github.com" manifestUrl,
? githubToken version,
: undefined; arch,
} catch { platform,
return undefined; );
if (!artifact) {
throw new Error(
`manifest-file does not contain version ${version}, arch ${arch}, platform ${platform}.`,
);
} }
return await downloadVersion(
artifact.downloadUrl,
`uv-${arch}-${platform}`,
platform,
arch,
version,
resolveChecksum(checkSum, artifact.checksum),
githubToken,
);
} }
async function downloadArtifact( async function downloadVersion(
downloadUrl: string, downloadUrl: string,
artifactName: string, artifactName: string,
platform: Platform, platform: Platform,
arch: Architecture, arch: Architecture,
version: string, version: string,
checksum: string | undefined, checksum: string | undefined,
githubToken: string | undefined, githubToken: string,
): Promise<{ version: string; cachedToolDir: string }> { ): Promise<{ version: string; cachedToolDir: string }> {
log.info(`Downloading uv from "${downloadUrl}" ...`); core.info(`Downloading uv from "${downloadUrl}" ...`);
const downloadPath = await tc.downloadTool( const downloadPath = await tc.downloadTool(
downloadUrl, downloadUrl,
undefined, undefined,
@@ -140,7 +118,7 @@ async function downloadArtifact(
// so this may fail if another tar, like gnu tar, ends up being used. // so this may fail if another tar, like gnu tar, ends up being used.
uvDir = await tc.extractTar(downloadPath, undefined, "x"); uvDir = await tc.extractTar(downloadPath, undefined, "x");
} catch (err) { } catch (err) {
log.info( core.info(
`Extracting with tar failed, falling back to zip extraction: ${(err as Error).message}`, `Extracting with tar failed, falling back to zip extraction: ${(err as Error).message}`,
); );
const extension = getExtension(platform); const extension = getExtension(platform);
@@ -159,31 +137,132 @@ async function downloadArtifact(
version, version,
arch, arch,
); );
return { cachedToolDir, version }; return { cachedToolDir, version: version };
}
function getMissingArtifactMessage(
version: string,
arch: Architecture,
platform: Platform,
manifestUrl?: string,
): string {
if (manifestUrl === undefined) {
return `Could not find artifact for version ${version}, arch ${arch}, platform ${platform} in ${VERSIONS_MANIFEST_URL} .`;
}
return `manifest-file does not contain version ${version}, arch ${arch}, platform ${platform}.`;
} }
function resolveChecksum( function resolveChecksum(
checksum: string | undefined, checkSum: string | undefined,
manifestChecksum: string, manifestChecksum?: string,
): string { ): string | undefined {
return checksum !== undefined && checksum !== "" return checkSum !== undefined && checkSum !== ""
? checksum ? checkSum
: manifestChecksum; : manifestChecksum;
} }
function getExtension(platform: Platform): string { function getExtension(platform: Platform): string {
return platform === "pc-windows-msvc" ? ".zip" : ".tar.gz"; return platform === "pc-windows-msvc" ? ".zip" : ".tar.gz";
} }
export async function resolveVersion(
versionInput: string,
manifestUrl: string | undefined,
resolutionStrategy: "highest" | "lowest" = "highest",
): Promise<string> {
core.debug(`Resolving version: ${versionInput}`);
let version: string;
const isSimpleMinimumVersionSpecifier =
versionInput.includes(">") && !versionInput.includes(",");
const resolveVersionSpecifierToLatest =
isSimpleMinimumVersionSpecifier && resolutionStrategy === "highest";
if (resolveVersionSpecifierToLatest) {
core.info("Found minimum version specifier, using latest version");
}
if (manifestUrl !== undefined) {
version =
versionInput === "latest" || resolveVersionSpecifierToLatest
? await getLatestVersionInManifest(manifestUrl)
: versionInput;
} else {
version =
versionInput === "latest" || resolveVersionSpecifierToLatest
? await getLatestVersionFromNdjson()
: versionInput;
}
if (tc.isExplicitVersion(version)) {
core.debug(`Version ${version} is an explicit version.`);
if (resolveVersionSpecifierToLatest) {
if (!pep440.satisfies(version, versionInput)) {
throw new Error(`No version found for ${versionInput}`);
}
}
return version;
}
if (manifestUrl === undefined && resolutionStrategy === "highest") {
const resolvedVersion =
await getHighestSatisfyingVersionFromNdjson(version);
if (resolvedVersion !== undefined) {
core.debug(`Resolved version from NDJSON stream: ${resolvedVersion}`);
return resolvedVersion;
}
throw new Error(`No version found for ${version}`);
}
const availableVersions = await getAvailableVersions(manifestUrl);
core.debug(`Available versions: ${availableVersions}`);
const resolvedVersion =
resolutionStrategy === "lowest"
? minSatisfying(availableVersions, version)
: maxSatisfying(availableVersions, version);
if (resolvedVersion === undefined) {
throw new Error(`No version found for ${version}`);
}
return resolvedVersion;
}
async function getAvailableVersions(
manifestUrl: string | undefined,
): Promise<string[]> {
if (manifestUrl !== undefined) {
core.info(
`Getting available versions from manifest-file ${manifestUrl} ...`,
);
return await getAllManifestVersions(manifestUrl);
}
core.info(`Getting available versions from ${VERSIONS_NDJSON_URL} ...`);
return await getAllVersionsFromNdjson();
}
function maxSatisfying(
versions: string[],
version: string,
): string | undefined {
const maxSemver = tc.evaluateVersions(versions, version);
if (maxSemver !== "") {
core.debug(`Found a version that satisfies the semver range: ${maxSemver}`);
return maxSemver;
}
const maxPep440 = pep440.maxSatisfying(versions, version);
if (maxPep440 !== null) {
core.debug(
`Found a version that satisfies the pep440 specifier: ${maxPep440}`,
);
return maxPep440;
}
return undefined;
}
function minSatisfying(
versions: string[],
version: string,
): string | undefined {
// For semver, we need to use a different approach since tc.evaluateVersions only returns max
// Let's use semver directly for min satisfying
const minSemver = semver.minSatisfying(versions, version);
if (minSemver !== null) {
core.debug(`Found a version that satisfies the semver range: ${minSemver}`);
return minSemver;
}
const minPep440 = pep440.minSatisfying(versions, version);
if (minPep440 !== null) {
core.debug(
`Found a version that satisfies the pep440 specifier: ${minPep440}`,
);
return minPep440;
}
return undefined;
}

View File

@@ -0,0 +1,80 @@
import * as core from "@actions/core";
export interface ManifestEntry {
arch: string;
platform: string;
version: string;
downloadUrl: string;
checksum?: string;
variant?: string;
archiveFormat?: string;
}
interface LegacyManifestEntry {
arch: string;
platform: string;
version: string;
downloadUrl: string;
checksum?: string;
}
const warnedLegacyManifestUrls = new Set<string>();
export function parseLegacyManifestEntries(
parsedEntries: unknown[],
manifestUrl: string,
): ManifestEntry[] {
warnAboutLegacyManifestFormat(manifestUrl);
return parsedEntries.map((entry, index) => {
if (!isLegacyManifestEntry(entry)) {
throw new Error(
`Invalid legacy manifest-file entry at index ${index} in ${manifestUrl}.`,
);
}
return {
arch: entry.arch,
checksum: entry.checksum,
downloadUrl: entry.downloadUrl,
platform: entry.platform,
version: entry.version,
};
});
}
export function clearLegacyManifestWarnings(): void {
warnedLegacyManifestUrls.clear();
}
function warnAboutLegacyManifestFormat(manifestUrl: string): void {
if (warnedLegacyManifestUrls.has(manifestUrl)) {
return;
}
warnedLegacyManifestUrls.add(manifestUrl);
core.warning(
`manifest-file ${manifestUrl} uses the legacy JSON array format, which is deprecated. Please migrate to the astral-sh/versions NDJSON format before the next major release.`,
);
}
function isLegacyManifestEntry(value: unknown): value is LegacyManifestEntry {
if (!isRecord(value)) {
return false;
}
const checksumIsValid =
typeof value.checksum === "string" || value.checksum === undefined;
return (
typeof value.arch === "string" &&
checksumIsValid &&
typeof value.downloadUrl === "string" &&
typeof value.platform === "string" &&
typeof value.version === "string"
);
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}

View File

@@ -1,211 +0,0 @@
import * as core from "@actions/core";
import { VERSIONS_MANIFEST_URL } from "../utils/constants";
import { fetch } from "../utils/fetch";
import * as log from "../utils/logging";
import { selectDefaultVariant } from "./variant-selection";
export interface ManifestArtifact {
platform: string;
variant?: string;
url: string;
archive_format: string;
sha256: string;
}
export interface ManifestVersion {
version: string;
artifacts: ManifestArtifact[];
}
export interface ArtifactResult {
archiveFormat: string;
checksum: string;
downloadUrl: string;
}
const cachedManifestData = new Map<string, ManifestVersion[]>();
export async function fetchManifest(
manifestUrl: string = VERSIONS_MANIFEST_URL,
): Promise<ManifestVersion[]> {
const cachedVersions = cachedManifestData.get(manifestUrl);
if (cachedVersions !== undefined) {
core.debug(`Using cached manifest data from ${manifestUrl}`);
return cachedVersions;
}
log.info(`Fetching manifest data from ${manifestUrl} ...`);
const response = await fetch(manifestUrl, {});
if (!response.ok) {
throw new Error(
`Failed to fetch manifest data: ${response.status} ${response.statusText}`,
);
}
const body = await response.text();
const versions = parseManifest(body, manifestUrl);
cachedManifestData.set(manifestUrl, versions);
return versions;
}
export function parseManifest(
data: string,
sourceDescription: string,
): ManifestVersion[] {
const trimmed = data.trim();
if (trimmed === "") {
throw new Error(`Manifest at ${sourceDescription} is empty.`);
}
if (trimmed.startsWith("[")) {
throw new Error(
`Legacy JSON array manifests are no longer supported in ${sourceDescription}. Use the astral-sh/versions manifest format instead.`,
);
}
const versions: ManifestVersion[] = [];
for (const [index, line] of data.split("\n").entries()) {
const record = line.trim();
if (record === "") {
continue;
}
let parsed: unknown;
try {
parsed = JSON.parse(record);
} catch (error) {
throw new Error(
`Failed to parse manifest data from ${sourceDescription} at line ${index + 1}: ${(error as Error).message}`,
);
}
if (!isManifestVersion(parsed)) {
throw new Error(
`Invalid manifest record in ${sourceDescription} at line ${index + 1}.`,
);
}
versions.push(parsed);
}
if (versions.length === 0) {
throw new Error(`No manifest data found in ${sourceDescription}.`);
}
return versions;
}
export async function getLatestVersion(
manifestUrl: string = VERSIONS_MANIFEST_URL,
): Promise<string> {
const latestVersion = (await fetchManifest(manifestUrl))[0]?.version;
if (latestVersion === undefined) {
throw new Error("No versions found in manifest data");
}
core.debug(`Latest version from manifest: ${latestVersion}`);
return latestVersion;
}
export async function getAllVersions(
manifestUrl: string = VERSIONS_MANIFEST_URL,
): Promise<string[]> {
log.info(
`Getting available versions from ${manifestSource(manifestUrl)} ...`,
);
const versions = await fetchManifest(manifestUrl);
return versions.map((versionData) => versionData.version);
}
export async function getArtifact(
version: string,
arch: string,
platform: string,
manifestUrl: string = VERSIONS_MANIFEST_URL,
): Promise<ArtifactResult | undefined> {
const versions = await fetchManifest(manifestUrl);
const versionData = versions.find(
(candidate) => candidate.version === version,
);
if (!versionData) {
core.debug(`Version ${version} not found in manifest ${manifestUrl}`);
return undefined;
}
const targetPlatform = `${arch}-${platform}`;
const matchingArtifacts = versionData.artifacts.filter(
(candidate) => candidate.platform === targetPlatform,
);
if (matchingArtifacts.length === 0) {
core.debug(
`Artifact for ${targetPlatform} not found in version ${version}. Available platforms: ${versionData.artifacts
.map((candidate) => candidate.platform)
.join(", ")}`,
);
return undefined;
}
const artifact = selectDefaultVariant(
matchingArtifacts,
`Multiple artifacts found for ${targetPlatform} in version ${version}`,
);
return {
archiveFormat: artifact.archive_format,
checksum: artifact.sha256,
downloadUrl: artifact.url,
};
}
export function clearManifestCache(manifestUrl?: string): void {
if (manifestUrl === undefined) {
cachedManifestData.clear();
return;
}
cachedManifestData.delete(manifestUrl);
}
function manifestSource(manifestUrl: string): string {
if (manifestUrl === VERSIONS_MANIFEST_URL) {
return VERSIONS_MANIFEST_URL;
}
return `manifest-file ${manifestUrl}`;
}
function isManifestVersion(value: unknown): value is ManifestVersion {
if (!isRecord(value)) {
return false;
}
if (typeof value.version !== "string" || !Array.isArray(value.artifacts)) {
return false;
}
return value.artifacts.every(isManifestArtifact);
}
function isManifestArtifact(value: unknown): value is ManifestArtifact {
if (!isRecord(value)) {
return false;
}
const variantIsValid =
typeof value.variant === "string" || value.variant === undefined;
return (
typeof value.archive_format === "string" &&
typeof value.platform === "string" &&
typeof value.sha256 === "string" &&
typeof value.url === "string" &&
variantIsValid
);
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}

View File

@@ -0,0 +1,169 @@
import * as core from "@actions/core";
import * as semver from "semver";
import { fetch } from "../utils/fetch";
import {
clearLegacyManifestWarnings,
type ManifestEntry,
parseLegacyManifestEntries,
} from "./legacy-version-manifest";
import { selectDefaultVariant } from "./variant-selection";
import { type NdjsonVersion, parseVersionData } from "./versions-client";
export interface ManifestArtifact {
downloadUrl: string;
checksum?: string;
archiveFormat?: string;
}
const cachedManifestEntries = new Map<string, ManifestEntry[]>();
export async function getLatestKnownVersion(
manifestUrl: string,
): Promise<string> {
const versions = await getAllVersions(manifestUrl);
const latestVersion = versions.reduce((latest, current) =>
semver.gt(current, latest) ? current : latest,
);
return latestVersion;
}
export async function getAllVersions(manifestUrl: string): Promise<string[]> {
const manifestEntries = await getManifestEntries(manifestUrl);
return [...new Set(manifestEntries.map((entry) => entry.version))];
}
export async function getManifestArtifact(
manifestUrl: string,
version: string,
arch: string,
platform: string,
): Promise<ManifestArtifact | undefined> {
const manifestEntries = await getManifestEntries(manifestUrl);
const entry = selectManifestEntry(
manifestEntries,
manifestUrl,
version,
arch,
platform,
);
if (!entry) {
return undefined;
}
return {
archiveFormat: entry.archiveFormat,
checksum: entry.checksum,
downloadUrl: entry.downloadUrl,
};
}
export function clearManifestCache(): void {
cachedManifestEntries.clear();
clearLegacyManifestWarnings();
}
async function getManifestEntries(
manifestUrl: string,
): Promise<ManifestEntry[]> {
const cachedEntries = cachedManifestEntries.get(manifestUrl);
if (cachedEntries !== undefined) {
core.debug(`Using cached manifest-file from: ${manifestUrl}`);
return cachedEntries;
}
core.info(`Fetching manifest-file from: ${manifestUrl}`);
const response = await fetch(manifestUrl, {});
if (!response.ok) {
throw new Error(
`Failed to fetch manifest-file: ${response.status} ${response.statusText}`,
);
}
const data = await response.text();
const parsedEntries = parseManifestEntries(data, manifestUrl);
cachedManifestEntries.set(manifestUrl, parsedEntries);
return parsedEntries;
}
function parseManifestEntries(
data: string,
manifestUrl: string,
): ManifestEntry[] {
const trimmed = data.trim();
if (trimmed === "") {
throw new Error(`manifest-file at ${manifestUrl} is empty.`);
}
const parsedAsJson = tryParseJson(trimmed);
if (Array.isArray(parsedAsJson)) {
return parseLegacyManifestEntries(parsedAsJson, manifestUrl);
}
const versions = parseVersionData(trimmed, manifestUrl);
return mapNdjsonVersionsToManifestEntries(versions, manifestUrl);
}
function mapNdjsonVersionsToManifestEntries(
versions: NdjsonVersion[],
manifestUrl: string,
): ManifestEntry[] {
const manifestEntries: ManifestEntry[] = [];
for (const versionData of versions) {
for (const artifact of versionData.artifacts) {
const [arch, ...platformParts] = artifact.platform.split("-");
if (arch === undefined || platformParts.length === 0) {
throw new Error(
`Invalid artifact platform '${artifact.platform}' in manifest-file ${manifestUrl}.`,
);
}
manifestEntries.push({
arch,
archiveFormat: artifact.archive_format,
checksum: artifact.sha256,
downloadUrl: artifact.url,
platform: platformParts.join("-"),
variant: artifact.variant,
version: versionData.version,
});
}
}
return manifestEntries;
}
function selectManifestEntry(
manifestEntries: ManifestEntry[],
manifestUrl: string,
version: string,
arch: string,
platform: string,
): ManifestEntry | undefined {
const matches = manifestEntries.filter(
(candidate) =>
candidate.version === version &&
candidate.arch === arch &&
candidate.platform === platform,
);
if (matches.length === 0) {
return undefined;
}
return selectDefaultVariant(
matches,
`manifest-file ${manifestUrl} contains multiple artifacts for version ${version}, arch ${arch}, platform ${platform}`,
);
}
function tryParseJson(value: string): unknown {
try {
return JSON.parse(value);
} catch {
return undefined;
}
}

View File

@@ -0,0 +1,380 @@
import * as core from "@actions/core";
import * as pep440 from "@renovatebot/pep440";
import * as semver from "semver";
import { VERSIONS_NDJSON_URL } from "../utils/constants";
import { fetch } from "../utils/fetch";
import { selectDefaultVariant } from "./variant-selection";
export interface NdjsonArtifact {
platform: string;
variant?: string;
url: string;
archive_format: string;
sha256: string;
}
export interface NdjsonVersion {
version: string;
artifacts: NdjsonArtifact[];
}
export interface ArtifactResult {
url: string;
sha256: string;
archiveFormat: string;
}
const cachedVersionData = new Map<string, NdjsonVersion[]>();
const cachedLatestVersionData = new Map<string, NdjsonVersion>();
const cachedVersionLookup = new Map<string, Map<string, NdjsonVersion>>();
export async function fetchVersionData(
url: string = VERSIONS_NDJSON_URL,
): Promise<NdjsonVersion[]> {
const cachedVersions = cachedVersionData.get(url);
if (cachedVersions !== undefined) {
core.debug(`Using cached NDJSON version data from ${url}`);
return cachedVersions;
}
core.info(`Fetching version data from ${url} ...`);
const { versions } = await readVersionData(url);
cacheCompleteVersionData(url, versions);
return versions;
}
export function parseVersionData(
data: string,
sourceDescription: string,
): NdjsonVersion[] {
const versions: NdjsonVersion[] = [];
for (const [index, line] of data.split("\n").entries()) {
const trimmed = line.trim();
if (trimmed === "") {
continue;
}
versions.push(parseVersionLine(trimmed, sourceDescription, index + 1));
}
if (versions.length === 0) {
throw new Error(`No version data found in ${sourceDescription}.`);
}
return versions;
}
export async function getLatestVersion(): Promise<string> {
const cachedVersions = cachedVersionData.get(VERSIONS_NDJSON_URL);
const cachedLatestVersion =
cachedVersions?.[0] ?? cachedLatestVersionData.get(VERSIONS_NDJSON_URL);
if (cachedLatestVersion !== undefined) {
core.debug(
`Latest version from NDJSON cache: ${cachedLatestVersion.version}`,
);
return cachedLatestVersion.version;
}
const latestVersion = await findVersionData(() => true);
if (!latestVersion) {
throw new Error("No versions found in NDJSON data");
}
core.debug(`Latest version from NDJSON: ${latestVersion.version}`);
return latestVersion.version;
}
export async function getAllVersions(): Promise<string[]> {
const versions = await fetchVersionData();
return versions.map((versionData) => versionData.version);
}
export async function getHighestSatisfyingVersion(
versionSpecifier: string,
url: string = VERSIONS_NDJSON_URL,
): Promise<string | undefined> {
const matchedVersion = await findVersionData(
(candidate) => versionSatisfies(candidate.version, versionSpecifier),
url,
);
return matchedVersion?.version;
}
export async function getArtifact(
version: string,
arch: string,
platform: string,
): Promise<ArtifactResult | undefined> {
const versionData = await getVersionData(version);
if (!versionData) {
core.debug(`Version ${version} not found in NDJSON data`);
return undefined;
}
const targetPlatform = `${arch}-${platform}`;
const matchingArtifacts = versionData.artifacts.filter(
(candidate) => candidate.platform === targetPlatform,
);
if (matchingArtifacts.length === 0) {
core.debug(
`Artifact for ${targetPlatform} not found in version ${version}. Available platforms: ${versionData.artifacts
.map((candidate) => candidate.platform)
.join(", ")}`,
);
return undefined;
}
const artifact = selectArtifact(matchingArtifacts, version, targetPlatform);
return {
archiveFormat: artifact.archive_format,
sha256: artifact.sha256,
url: artifact.url,
};
}
export function clearCache(url?: string): void {
if (url === undefined) {
cachedVersionData.clear();
cachedLatestVersionData.clear();
cachedVersionLookup.clear();
return;
}
cachedVersionData.delete(url);
cachedLatestVersionData.delete(url);
cachedVersionLookup.delete(url);
}
function selectArtifact(
artifacts: NdjsonArtifact[],
version: string,
targetPlatform: string,
): NdjsonArtifact {
return selectDefaultVariant(
artifacts,
`Multiple artifacts found for ${targetPlatform} in version ${version}`,
);
}
async function getVersionData(
version: string,
url: string = VERSIONS_NDJSON_URL,
): Promise<NdjsonVersion | undefined> {
const cachedVersions = cachedVersionData.get(url);
if (cachedVersions !== undefined) {
return cachedVersions.find((candidate) => candidate.version === version);
}
const cachedVersion = cachedVersionLookup.get(url)?.get(version);
if (cachedVersion !== undefined) {
return cachedVersion;
}
return await findVersionData(
(candidate) => candidate.version === version,
url,
);
}
async function findVersionData(
predicate: (versionData: NdjsonVersion) => boolean,
url: string = VERSIONS_NDJSON_URL,
): Promise<NdjsonVersion | undefined> {
const cachedVersions = cachedVersionData.get(url);
if (cachedVersions !== undefined) {
return cachedVersions.find(predicate);
}
const { matchedVersion, versions, complete } = await readVersionData(
url,
predicate,
);
if (complete) {
cacheCompleteVersionData(url, versions);
}
return matchedVersion;
}
async function readVersionData(
url: string,
stopWhen?: (versionData: NdjsonVersion) => boolean,
): Promise<{
complete: boolean;
matchedVersion: NdjsonVersion | undefined;
versions: NdjsonVersion[];
}> {
const response = await fetch(url, {});
if (!response.ok) {
throw new Error(
`Failed to fetch version data: ${response.status} ${response.statusText}`,
);
}
if (response.body === null) {
const body = await response.text();
const versions = parseVersionData(body, url);
const matchedVersion = stopWhen
? versions.find((candidate) => stopWhen(candidate))
: undefined;
return { complete: true, matchedVersion, versions };
}
const versions: NdjsonVersion[] = [];
let lineNumber = 0;
let matchedVersion: NdjsonVersion | undefined;
let buffer = "";
const decoder = new TextDecoder();
const reader = response.body.getReader();
const processLine = (line: string): boolean => {
const trimmed = line.trim();
if (trimmed === "") {
return false;
}
lineNumber += 1;
const versionData = parseVersionLine(trimmed, url, lineNumber);
if (versions.length === 0) {
cachedLatestVersionData.set(url, versionData);
}
versions.push(versionData);
cacheVersion(url, versionData);
if (stopWhen?.(versionData) === true) {
matchedVersion = versionData;
return true;
}
return false;
};
while (true) {
const { done, value } = await reader.read();
if (done) {
buffer += decoder.decode();
break;
}
buffer += decoder.decode(value, { stream: true });
let newlineIndex = buffer.indexOf("\n");
while (newlineIndex !== -1) {
const line = buffer.slice(0, newlineIndex);
buffer = buffer.slice(newlineIndex + 1);
if (processLine(line)) {
await reader.cancel();
return { complete: false, matchedVersion, versions };
}
newlineIndex = buffer.indexOf("\n");
}
}
if (buffer.trim() !== "" && processLine(buffer)) {
return { complete: true, matchedVersion, versions };
}
if (versions.length === 0) {
throw new Error(`No version data found in ${url}.`);
}
return { complete: true, matchedVersion, versions };
}
function cacheCompleteVersionData(
url: string,
versions: NdjsonVersion[],
): void {
cachedVersionData.set(url, versions);
if (versions[0] !== undefined) {
cachedLatestVersionData.set(url, versions[0]);
}
const versionLookup = new Map<string, NdjsonVersion>();
for (const versionData of versions) {
versionLookup.set(versionData.version, versionData);
}
cachedVersionLookup.set(url, versionLookup);
}
function cacheVersion(url: string, versionData: NdjsonVersion): void {
let versionLookup = cachedVersionLookup.get(url);
if (versionLookup === undefined) {
versionLookup = new Map<string, NdjsonVersion>();
cachedVersionLookup.set(url, versionLookup);
}
versionLookup.set(versionData.version, versionData);
}
function parseVersionLine(
line: string,
sourceDescription: string,
lineNumber: number,
): NdjsonVersion {
let parsed: unknown;
try {
parsed = JSON.parse(line);
} catch (error) {
throw new Error(
`Failed to parse version data from ${sourceDescription} at line ${lineNumber}: ${(error as Error).message}`,
);
}
if (!isNdjsonVersion(parsed)) {
throw new Error(
`Invalid NDJSON record in ${sourceDescription} at line ${lineNumber}.`,
);
}
return parsed;
}
function versionSatisfies(version: string, versionSpecifier: string): boolean {
return (
semver.satisfies(version, versionSpecifier) ||
pep440.satisfies(version, versionSpecifier)
);
}
function isNdjsonVersion(value: unknown): value is NdjsonVersion {
if (!isRecord(value)) {
return false;
}
if (typeof value.version !== "string" || !Array.isArray(value.artifacts)) {
return false;
}
return value.artifacts.every(isNdjsonArtifact);
}
function isNdjsonArtifact(value: unknown): value is NdjsonArtifact {
if (!isRecord(value)) {
return false;
}
const variantIsValid =
typeof value.variant === "string" || value.variant === undefined;
return (
typeof value.archive_format === "string" &&
typeof value.platform === "string" &&
typeof value.sha256 === "string" &&
typeof value.url === "string" &&
variantIsValid
);
}
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === "object" && value !== null;
}

View File

@@ -2,8 +2,8 @@ import * as crypto from "node:crypto";
import * as fs from "node:fs"; import * as fs from "node:fs";
import * as stream from "node:stream"; import * as stream from "node:stream";
import * as util from "node:util"; import * as util from "node:util";
import * as core from "@actions/core";
import { create } from "@actions/glob"; import { create } from "@actions/glob";
import * as log from "../utils/logging";
/** /**
* Hashes files matching the given glob pattern. * Hashes files matching the given glob pattern.
@@ -19,7 +19,7 @@ export async function hashFiles(
): Promise<string> { ): Promise<string> {
const globber = await create(pattern); const globber = await create(pattern);
let hasMatch = false; let hasMatch = false;
const writeDelegate = verbose ? log.info : log.debug; const writeDelegate = verbose ? core.info : core.debug;
const result = crypto.createHash("sha256"); const result = crypto.createHash("sha256");
let count = 0; let count = 0;
for await (const file of globber.globGenerator()) { for await (const file of globber.globGenerator()) {

View File

@@ -9,40 +9,26 @@ import {
STATE_PYTHON_CACHE_MATCHED_KEY, STATE_PYTHON_CACHE_MATCHED_KEY,
} from "./cache/restore-cache"; } from "./cache/restore-cache";
import { STATE_UV_PATH, STATE_UV_VERSION } from "./utils/constants"; import { STATE_UV_PATH, STATE_UV_VERSION } from "./utils/constants";
import { loadInputs, type SetupInputs } from "./utils/inputs"; import {
import * as log from "./utils/logging"; cacheLocalPath,
cachePython,
function formatUnexpectedFailure(error: unknown): string { enableCache,
if (error instanceof Error) { ignoreNothingToCache,
return error.stack ?? error.message; pythonDir,
} pruneCache as shouldPruneCache,
return String(error); saveCache as shouldSaveCache,
} } from "./utils/inputs";
function failUnexpectedly(event: string, error: unknown): never {
core.setFailed(`${event}: ${formatUnexpectedFailure(error)}`);
process.exit(1);
}
process.on("uncaughtException", (error) => {
failUnexpectedly("Uncaught exception", error);
});
process.on("unhandledRejection", (reason) => {
failUnexpectedly("Unhandled promise rejection", reason);
});
export async function run(): Promise<void> { export async function run(): Promise<void> {
try { try {
const inputs = loadInputs(); if (enableCache) {
if (inputs.enableCache) { if (shouldSaveCache) {
if (inputs.saveCache) { await saveCache();
await saveCache(inputs);
} else { } else {
log.info("save-cache is false. Skipping save cache step."); core.info("save-cache is false. Skipping save cache step.");
} }
// https://github.com/nodejs/node/issues/56645#issuecomment-3924958861 // https://github.com/nodejs/node/issues/56645#issuecomment-3077594952
await new Promise((resolve) => setTimeout(resolve, 100)); await new Promise((resolve) => setTimeout(resolve, 50));
// node will stay alive if any promises are not resolved, // node will stay alive if any promises are not resolved,
// which is a possibility if HTTP requests are dangling // which is a possibility if HTTP requests are dangling
@@ -57,25 +43,25 @@ export async function run(): Promise<void> {
} }
} }
async function saveCache(inputs: SetupInputs): Promise<void> { async function saveCache(): Promise<void> {
const cacheKey = core.getState(STATE_CACHE_KEY); const cacheKey = core.getState(STATE_CACHE_KEY);
const matchedKey = core.getState(STATE_CACHE_MATCHED_KEY); const matchedKey = core.getState(STATE_CACHE_MATCHED_KEY);
if (!cacheKey) { if (!cacheKey) {
log.warning("Error retrieving cache key from state."); core.warning("Error retrieving cache key from state.");
return; return;
} }
if (matchedKey === cacheKey) { if (matchedKey === cacheKey) {
log.info(`Cache hit occurred on key ${cacheKey}, not saving cache.`); core.info(`Cache hit occurred on key ${cacheKey}, not saving cache.`);
} else { } else {
if (inputs.pruneCache) { if (shouldPruneCache) {
await pruneCache(); await pruneCache();
} }
const actualCachePath = getUvCachePath(inputs); const actualCachePath = getUvCachePath();
if (!fs.existsSync(actualCachePath)) { if (!fs.existsSync(actualCachePath)) {
if (inputs.ignoreNothingToCache) { if (ignoreNothingToCache) {
log.info( core.info(
"No cacheable uv cache paths were found. Ignoring because ignore-nothing-to-cache is enabled.", "No cacheable uv cache paths were found. Ignoring because ignore-nothing-to-cache is enabled.",
); );
} else { } else {
@@ -93,10 +79,10 @@ async function saveCache(inputs: SetupInputs): Promise<void> {
} }
} }
if (inputs.cachePython) { if (cachePython) {
if (!fs.existsSync(inputs.pythonDir)) { if (!fs.existsSync(pythonDir)) {
log.warning( core.warning(
`Python cache path ${inputs.pythonDir} does not exist on disk. Skipping Python cache save because no managed Python installation was found. If you want uv to install managed Python instead of using a system interpreter, set UV_PYTHON_PREFERENCE=only-managed.`, `Python cache path ${pythonDir} does not exist on disk. Skipping Python cache save because no managed Python installation was found. If you want uv to install managed Python instead of using a system interpreter, set UV_PYTHON_PREFERENCE=only-managed.`,
); );
return; return;
} }
@@ -104,7 +90,7 @@ async function saveCache(inputs: SetupInputs): Promise<void> {
const pythonCacheKey = `${cacheKey}-python`; const pythonCacheKey = `${cacheKey}-python`;
await saveCacheToKey( await saveCacheToKey(
pythonCacheKey, pythonCacheKey,
inputs.pythonDir, pythonDir,
STATE_PYTHON_CACHE_MATCHED_KEY, STATE_PYTHON_CACHE_MATCHED_KEY,
"Python cache", "Python cache",
); );
@@ -122,27 +108,27 @@ async function pruneCache(): Promise<void> {
execArgs.push("--force"); execArgs.push("--force");
} }
log.info("Pruning cache..."); core.info("Pruning cache...");
const uvPath = core.getState(STATE_UV_PATH); const uvPath = core.getState(STATE_UV_PATH);
await exec.exec(uvPath, execArgs, options); await exec.exec(uvPath, execArgs, options);
} }
function getUvCachePath(inputs: SetupInputs): string { function getUvCachePath(): string {
if (inputs.cacheLocalPath === undefined) { if (cacheLocalPath === undefined) {
throw new Error( throw new Error(
"cache-local-path is not set. Cannot save cache without a valid cache path.", "cache-local-path is not set. Cannot save cache without a valid cache path.",
); );
} }
if ( if (
process.env.UV_CACHE_DIR && process.env.UV_CACHE_DIR &&
process.env.UV_CACHE_DIR !== inputs.cacheLocalPath.path process.env.UV_CACHE_DIR !== cacheLocalPath.path
) { ) {
log.warning( core.warning(
`The environment variable UV_CACHE_DIR has been changed to "${process.env.UV_CACHE_DIR}", by an action or step running after astral-sh/setup-uv. This can lead to unexpected behavior. If you expected this to happen set the cache-local-path input to "${process.env.UV_CACHE_DIR}" instead of "${inputs.cacheLocalPath.path}".`, `The environment variable UV_CACHE_DIR has been changed to "${process.env.UV_CACHE_DIR}", by an action or step running after astral-sh/setup-uv. This can lead to unexpected behavior. If you expected this to happen set the cache-local-path input to "${process.env.UV_CACHE_DIR}" instead of "${cacheLocalPath.path}".`,
); );
return process.env.UV_CACHE_DIR; return process.env.UV_CACHE_DIR;
} }
return inputs.cacheLocalPath.path; return cacheLocalPath.path;
} }
async function saveCacheToKey( async function saveCacheToKey(
@@ -154,13 +140,15 @@ async function saveCacheToKey(
const matchedKey = core.getState(stateKey); const matchedKey = core.getState(stateKey);
if (matchedKey === cacheKey) { if (matchedKey === cacheKey) {
log.info(`${cacheName} hit occurred on key ${cacheKey}, not saving cache.`); core.info(
`${cacheName} hit occurred on key ${cacheKey}, not saving cache.`,
);
return; return;
} }
log.info(`Including ${cacheName} path: ${cachePath}`); core.info(`Including ${cacheName} path: ${cachePath}`);
await cache.saveCache([cachePath], cacheKey); await cache.saveCache([cachePath], cacheKey);
log.info(`${cacheName} saved with key: ${cacheKey}`); core.info(`${cacheName} saved with key: ${cacheKey}`);
} }
run(); run();

View File

@@ -4,45 +4,45 @@ import * as core from "@actions/core";
import * as exec from "@actions/exec"; import * as exec from "@actions/exec";
import { restoreCache } from "./cache/restore-cache"; import { restoreCache } from "./cache/restore-cache";
import { import {
downloadVersion, downloadVersionFromManifest,
downloadVersionFromNdjson,
resolveVersion,
tryGetFromToolCache, tryGetFromToolCache,
} from "./download/download-version"; } from "./download/download-version";
import { STATE_UV_PATH, STATE_UV_VERSION } from "./utils/constants"; import { STATE_UV_PATH, STATE_UV_VERSION } from "./utils/constants";
import { CacheLocalSource, loadInputs, type SetupInputs } from "./utils/inputs"; import {
import * as log from "./utils/logging"; activateEnvironment as activateEnvironmentInput,
addProblemMatchers,
CacheLocalSource,
cacheLocalPath,
checkSum,
enableCache,
githubToken,
ignoreEmptyWorkdir,
manifestFile,
pythonDir,
pythonVersion,
resolutionStrategy,
toolBinDir,
toolDir,
venvPath,
versionFile as versionFileInput,
version as versionInput,
workingDirectory,
} from "./utils/inputs";
import { import {
type Architecture, type Architecture,
getArch, getArch,
getPlatform, getPlatform,
type Platform, type Platform,
} from "./utils/platforms"; } from "./utils/platforms";
import { resolveUvVersion } from "./version/resolve"; import { getUvVersionFromFile } from "./version/resolve";
const sourceDir = __dirname; const sourceDir = __dirname;
function formatUnexpectedFailure(error: unknown): string { async function getPythonVersion(): Promise<string> {
if (error instanceof Error) { if (pythonVersion !== "") {
return error.stack ?? error.message; return pythonVersion;
}
return String(error);
}
function failUnexpectedly(event: string, error: unknown): never {
core.setFailed(`${event}: ${formatUnexpectedFailure(error)}`);
process.exit(1);
}
process.on("uncaughtException", (error) => {
failUnexpectedly("Uncaught exception", error);
});
process.on("unhandledRejection", (reason) => {
failUnexpectedly("Unhandled promise rejection", reason);
});
async function getPythonVersion(inputs: SetupInputs): Promise<string> {
if (inputs.pythonVersion !== "") {
return inputs.pythonVersion;
} }
let output = ""; let output = "";
@@ -56,7 +56,7 @@ async function getPythonVersion(inputs: SetupInputs): Promise<string> {
}; };
try { try {
const execArgs = ["python", "find", "--directory", inputs.workingDirectory]; const execArgs = ["python", "find", "--directory", workingDirectory];
await exec.exec("uv", execArgs, options); await exec.exec("uv", execArgs, options);
const pythonPath = output.trim(); const pythonPath = output.trim();
@@ -72,55 +72,54 @@ async function getPythonVersion(inputs: SetupInputs): Promise<string> {
} }
async function run(): Promise<void> { async function run(): Promise<void> {
try { detectEmptyWorkdir();
const inputs = loadInputs(); const platform = await getPlatform();
detectEmptyWorkdir(inputs); const arch = getArch();
const platform = await getPlatform();
const arch = getArch();
try {
if (platform === undefined) { if (platform === undefined) {
throw new Error(`Unsupported platform: ${process.platform}`); throw new Error(`Unsupported platform: ${process.platform}`);
} }
if (arch === undefined) { if (arch === undefined) {
throw new Error(`Unsupported architecture: ${process.arch}`); throw new Error(`Unsupported architecture: ${process.arch}`);
} }
const setupResult = await setupUv(inputs, platform, arch); const setupResult = await setupUv(platform, arch, checkSum, githubToken);
addToolBinToPath(inputs); addToolBinToPath();
addUvToPathAndOutput(setupResult.uvDir); addUvToPathAndOutput(setupResult.uvDir);
setToolDir(inputs); setToolDir();
addPythonDirToPath(inputs); addPythonDirToPath();
setupPython(inputs); setupPython();
await activateEnvironment(inputs); await activateEnvironment();
addMatchers(inputs); addMatchers();
setCacheDir(inputs); setCacheDir();
core.setOutput("uv-version", setupResult.version); core.setOutput("uv-version", setupResult.version);
core.saveState(STATE_UV_VERSION, setupResult.version); core.saveState(STATE_UV_VERSION, setupResult.version);
log.info(`Successfully installed uv version ${setupResult.version}`); core.info(`Successfully installed uv version ${setupResult.version}`);
const detectedPythonVersion = await getPythonVersion(inputs); const pythonVersion = await getPythonVersion();
core.setOutput("python-version", detectedPythonVersion); core.setOutput("python-version", pythonVersion);
if (inputs.enableCache) { if (enableCache) {
await restoreCache(inputs, detectedPythonVersion); await restoreCache(pythonVersion);
} }
// https://github.com/nodejs/node/issues/56645#issuecomment-3924958861 // https://github.com/nodejs/node/issues/56645#issuecomment-3077594952
await new Promise((resolve) => setTimeout(resolve, 100)); await new Promise((resolve) => setTimeout(resolve, 50));
process.exit(0); process.exit(0);
} catch (err) { } catch (err) {
core.setFailed((err as Error).message); core.setFailed((err as Error).message);
} }
} }
function detectEmptyWorkdir(inputs: SetupInputs): void { function detectEmptyWorkdir(): void {
if (fs.readdirSync(inputs.workingDirectory).length === 0) { if (fs.readdirSync(workingDirectory).length === 0) {
if (inputs.ignoreEmptyWorkdir) { if (ignoreEmptyWorkdir) {
log.info( core.info(
"Empty workdir detected. Ignoring because ignore-empty-workdir is enabled", "Empty workdir detected. Ignoring because ignore-empty-workdir is enabled",
); );
} else { } else {
log.warning( core.warning(
"Empty workdir detected. This may cause unexpected behavior. You can enable ignore-empty-workdir to mute this warning.", "Empty workdir detected. This may cause unexpected behavior. You can enable ignore-empty-workdir to mute this warning.",
); );
} }
@@ -128,155 +127,189 @@ function detectEmptyWorkdir(inputs: SetupInputs): void {
} }
async function setupUv( async function setupUv(
inputs: SetupInputs,
platform: Platform, platform: Platform,
arch: Architecture, arch: Architecture,
checkSum: string | undefined,
githubToken: string,
): Promise<{ uvDir: string; version: string }> { ): Promise<{ uvDir: string; version: string }> {
const resolvedVersion = await resolveUvVersion({ const resolvedVersion = await determineVersion(manifestFile);
manifestFile: inputs.manifestFile,
resolutionStrategy: inputs.resolutionStrategy,
version: inputs.version,
versionFile: inputs.versionFile,
workingDirectory: inputs.workingDirectory,
});
const toolCacheResult = tryGetFromToolCache(arch, resolvedVersion); const toolCacheResult = tryGetFromToolCache(arch, resolvedVersion);
if (toolCacheResult.installedPath) { if (toolCacheResult.installedPath) {
log.info(`Found uv in tool-cache for ${toolCacheResult.version}`); core.info(`Found uv in tool-cache for ${toolCacheResult.version}`);
return { return {
uvDir: toolCacheResult.installedPath, uvDir: toolCacheResult.installedPath,
version: toolCacheResult.version, version: toolCacheResult.version,
}; };
} }
const downloadResult = await downloadVersion( const downloadVersionResult =
platform, manifestFile !== undefined
arch, ? await downloadVersionFromManifest(
resolvedVersion, manifestFile,
inputs.checksum, platform,
inputs.githubToken, arch,
inputs.manifestFile, resolvedVersion,
inputs.downloadFromAstralMirror, checkSum,
); githubToken,
)
: await downloadVersionFromNdjson(
platform,
arch,
resolvedVersion,
checkSum,
githubToken,
);
return { return {
uvDir: downloadResult.cachedToolDir, uvDir: downloadVersionResult.cachedToolDir,
version: downloadResult.version, version: downloadVersionResult.version,
}; };
} }
async function determineVersion(
manifestFile: string | undefined,
): Promise<string> {
if (versionInput !== "") {
return await resolveVersion(versionInput, manifestFile, resolutionStrategy);
}
if (versionFileInput !== "") {
const versionFromFile = getUvVersionFromFile(versionFileInput);
if (versionFromFile === undefined) {
throw new Error(
`Could not determine uv version from file: ${versionFileInput}`,
);
}
return await resolveVersion(
versionFromFile,
manifestFile,
resolutionStrategy,
);
}
const versionFromUvToml = getUvVersionFromFile(
`${workingDirectory}${path.sep}uv.toml`,
);
const versionFromPyproject = getUvVersionFromFile(
`${workingDirectory}${path.sep}pyproject.toml`,
);
if (versionFromUvToml === undefined && versionFromPyproject === undefined) {
core.info(
"Could not determine uv version from uv.toml or pyproject.toml. Falling back to latest.",
);
}
return await resolveVersion(
versionFromUvToml || versionFromPyproject || "latest",
manifestFile,
resolutionStrategy,
);
}
function addUvToPathAndOutput(cachedPath: string): void { function addUvToPathAndOutput(cachedPath: string): void {
core.setOutput("uv-path", `${cachedPath}${path.sep}uv`); core.setOutput("uv-path", `${cachedPath}${path.sep}uv`);
core.saveState(STATE_UV_PATH, `${cachedPath}${path.sep}uv`); core.saveState(STATE_UV_PATH, `${cachedPath}${path.sep}uv`);
core.setOutput("uvx-path", `${cachedPath}${path.sep}uvx`); core.setOutput("uvx-path", `${cachedPath}${path.sep}uvx`);
if (process.env.UV_NO_MODIFY_PATH !== undefined) { if (process.env.UV_NO_MODIFY_PATH !== undefined) {
log.info("UV_NO_MODIFY_PATH is set, not modifying PATH"); core.info("UV_NO_MODIFY_PATH is set, not modifying PATH");
} else { } else {
core.addPath(cachedPath); core.addPath(cachedPath);
log.info(`Added ${cachedPath} to the path`); core.info(`Added ${cachedPath} to the path`);
} }
} }
function addToolBinToPath(inputs: SetupInputs): void { function addToolBinToPath(): void {
if (inputs.toolBinDir !== undefined) { if (toolBinDir !== undefined) {
core.exportVariable("UV_TOOL_BIN_DIR", inputs.toolBinDir); core.exportVariable("UV_TOOL_BIN_DIR", toolBinDir);
log.info(`Set UV_TOOL_BIN_DIR to ${inputs.toolBinDir}`); core.info(`Set UV_TOOL_BIN_DIR to ${toolBinDir}`);
if (process.env.UV_NO_MODIFY_PATH !== undefined) { if (process.env.UV_NO_MODIFY_PATH !== undefined) {
log.info( core.info(`UV_NO_MODIFY_PATH is set, not adding ${toolBinDir} to path`);
`UV_NO_MODIFY_PATH is set, not adding ${inputs.toolBinDir} to path`,
);
} else { } else {
core.addPath(inputs.toolBinDir); core.addPath(toolBinDir);
log.info(`Added ${inputs.toolBinDir} to the path`); core.info(`Added ${toolBinDir} to the path`);
} }
} else { } else {
if (process.env.UV_NO_MODIFY_PATH !== undefined) { if (process.env.UV_NO_MODIFY_PATH !== undefined) {
log.info("UV_NO_MODIFY_PATH is set, not adding user local bin to path"); core.info("UV_NO_MODIFY_PATH is set, not adding user local bin to path");
return; return;
} }
if (process.env.XDG_BIN_HOME !== undefined) { if (process.env.XDG_BIN_HOME !== undefined) {
core.addPath(process.env.XDG_BIN_HOME); core.addPath(process.env.XDG_BIN_HOME);
log.info(`Added ${process.env.XDG_BIN_HOME} to the path`); core.info(`Added ${process.env.XDG_BIN_HOME} to the path`);
} else if (process.env.XDG_DATA_HOME !== undefined) { } else if (process.env.XDG_DATA_HOME !== undefined) {
core.addPath(`${process.env.XDG_DATA_HOME}/../bin`); core.addPath(`${process.env.XDG_DATA_HOME}/../bin`);
log.info(`Added ${process.env.XDG_DATA_HOME}/../bin to the path`); core.info(`Added ${process.env.XDG_DATA_HOME}/../bin to the path`);
} else { } else {
core.addPath(`${process.env.HOME}/.local/bin`); core.addPath(`${process.env.HOME}/.local/bin`);
log.info(`Added ${process.env.HOME}/.local/bin to the path`); core.info(`Added ${process.env.HOME}/.local/bin to the path`);
} }
} }
} }
function setToolDir(inputs: SetupInputs): void { function setToolDir(): void {
if (inputs.toolDir !== undefined) { if (toolDir !== undefined) {
core.exportVariable("UV_TOOL_DIR", inputs.toolDir); core.exportVariable("UV_TOOL_DIR", toolDir);
log.info(`Set UV_TOOL_DIR to ${inputs.toolDir}`); core.info(`Set UV_TOOL_DIR to ${toolDir}`);
} }
} }
function addPythonDirToPath(inputs: SetupInputs): void { function addPythonDirToPath(): void {
core.exportVariable("UV_PYTHON_INSTALL_DIR", inputs.pythonDir); core.exportVariable("UV_PYTHON_INSTALL_DIR", pythonDir);
log.info(`Set UV_PYTHON_INSTALL_DIR to ${inputs.pythonDir}`); core.info(`Set UV_PYTHON_INSTALL_DIR to ${pythonDir}`);
if (process.env.UV_NO_MODIFY_PATH !== undefined) { if (process.env.UV_NO_MODIFY_PATH !== undefined) {
log.info("UV_NO_MODIFY_PATH is set, not adding python dir to path"); core.info("UV_NO_MODIFY_PATH is set, not adding python dir to path");
} else { } else {
core.addPath(inputs.pythonDir); core.addPath(pythonDir);
log.info(`Added ${inputs.pythonDir} to the path`); core.info(`Added ${pythonDir} to the path`);
} }
} }
function setupPython(inputs: SetupInputs): void { function setupPython(): void {
if (inputs.pythonVersion !== "") { if (pythonVersion !== "") {
core.exportVariable("UV_PYTHON", inputs.pythonVersion); core.exportVariable("UV_PYTHON", pythonVersion);
log.info(`Set UV_PYTHON to ${inputs.pythonVersion}`); core.info(`Set UV_PYTHON to ${pythonVersion}`);
} }
} }
async function activateEnvironment(inputs: SetupInputs): Promise<void> { async function activateEnvironment(): Promise<void> {
if (inputs.activateEnvironment) { if (activateEnvironmentInput) {
if (process.env.UV_NO_MODIFY_PATH !== undefined) { if (process.env.UV_NO_MODIFY_PATH !== undefined) {
throw new Error( throw new Error(
"UV_NO_MODIFY_PATH and activate-environment cannot be used together.", "UV_NO_MODIFY_PATH and activate-environment cannot be used together.",
); );
} }
log.info(`Creating and activating python venv at ${inputs.venvPath}...`); core.info(`Creating and activating python venv at ${venvPath}...`);
const venvArgs = [ await exec.exec("uv", [
"venv", "venv",
inputs.venvPath, venvPath,
"--directory", "--directory",
inputs.workingDirectory, workingDirectory,
"--clear", "--clear",
]; ]);
if (inputs.noProject) {
venvArgs.push("--no-project");
}
await exec.exec("uv", venvArgs);
let venvBinPath = `${inputs.venvPath}${path.sep}bin`; let venvBinPath = `${venvPath}${path.sep}bin`;
if (process.platform === "win32") { if (process.platform === "win32") {
venvBinPath = `${inputs.venvPath}${path.sep}Scripts`; venvBinPath = `${venvPath}${path.sep}Scripts`;
} }
core.addPath(path.resolve(venvBinPath)); core.addPath(path.resolve(venvBinPath));
core.exportVariable("VIRTUAL_ENV", inputs.venvPath); core.exportVariable("VIRTUAL_ENV", venvPath);
core.setOutput("venv", inputs.venvPath); core.setOutput("venv", venvPath);
} }
} }
function setCacheDir(inputs: SetupInputs): void { function setCacheDir(): void {
if (inputs.cacheLocalPath !== undefined) { if (cacheLocalPath !== undefined) {
if (inputs.cacheLocalPath.source === CacheLocalSource.Config) { if (cacheLocalPath.source === CacheLocalSource.Config) {
log.info( core.info(
"Using cache-dir from uv config file, not modifying UV_CACHE_DIR", "Using cache-dir from uv config file, not modifying UV_CACHE_DIR",
); );
return; return;
} }
core.exportVariable("UV_CACHE_DIR", inputs.cacheLocalPath.path); core.exportVariable("UV_CACHE_DIR", cacheLocalPath.path);
log.info(`Set UV_CACHE_DIR to ${inputs.cacheLocalPath.path}`); core.info(`Set UV_CACHE_DIR to ${cacheLocalPath.path}`);
} }
} }
function addMatchers(inputs: SetupInputs): void { function addMatchers(): void {
if (inputs.addProblemMatchers) { if (addProblemMatchers) {
const matchersPath = path.join(sourceDir, "..", "..", ".github"); const matchersPath = path.join(sourceDir, "..", "..", ".github");
core.info(`##[add-matcher]${path.join(matchersPath, "python.json")}`); core.info(`##[add-matcher]${path.join(matchersPath, "python.json")}`);
} }

View File

@@ -6,11 +6,10 @@ import {
updateChecksums, updateChecksums,
} from "./download/checksum/update-known-checksums"; } from "./download/checksum/update-known-checksums";
import { import {
fetchManifest, fetchVersionData,
getLatestVersion, getLatestVersion,
type ManifestVersion, type NdjsonVersion,
} from "./download/manifest"; } from "./download/versions-client";
import * as log from "./utils/logging";
const VERSION_IN_CHECKSUM_KEY_PATTERN = const VERSION_IN_CHECKSUM_KEY_PATTERN =
/-(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/; /-(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)$/;
@@ -27,14 +26,14 @@ async function run(): Promise<void> {
const latestKnownVersion = getLatestKnownVersionFromChecksums(); const latestKnownVersion = getLatestKnownVersionFromChecksums();
if (semver.lte(latestVersion, latestKnownVersion)) { if (semver.lte(latestVersion, latestKnownVersion)) {
log.info( core.info(
`Latest release (${latestVersion}) is not newer than the latest known version (${latestKnownVersion}). Skipping update.`, `Latest release (${latestVersion}) is not newer than the latest known version (${latestKnownVersion}). Skipping update.`,
); );
return; return;
} }
const versions = await fetchManifest(); const versions = await fetchVersionData();
const checksumEntries = extractChecksumsFromManifest(versions); const checksumEntries = extractChecksumsFromNdjson(versions);
await updateChecksums(checksumFilePath, checksumEntries); await updateChecksums(checksumFilePath, checksumEntries);
core.setOutput("latest-version", latestVersion); core.setOutput("latest-version", latestVersion);
@@ -62,8 +61,8 @@ function extractVersionFromChecksumKey(key: string): string | undefined {
return key.match(VERSION_IN_CHECKSUM_KEY_PATTERN)?.[1]; return key.match(VERSION_IN_CHECKSUM_KEY_PATTERN)?.[1];
} }
function extractChecksumsFromManifest( function extractChecksumsFromNdjson(
versions: ManifestVersion[], versions: NdjsonVersion[],
): ChecksumEntry[] { ): ChecksumEntry[] {
const checksums: ChecksumEntry[] = []; const checksums: ChecksumEntry[] = [];

View File

@@ -8,19 +8,7 @@ export function getConfigValueFromTomlFile(
if (!fs.existsSync(filePath) || !filePath.endsWith(".toml")) { if (!fs.existsSync(filePath) || !filePath.endsWith(".toml")) {
return undefined; return undefined;
} }
const fileContent = fs.readFileSync(filePath, "utf-8"); const fileContent = fs.readFileSync(filePath, "utf-8");
return getConfigValueFromTomlContent(filePath, fileContent, key);
}
export function getConfigValueFromTomlContent(
filePath: string,
fileContent: string,
key: string,
): string | undefined {
if (!filePath.endsWith(".toml")) {
return undefined;
}
if (filePath.endsWith("pyproject.toml")) { if (filePath.endsWith("pyproject.toml")) {
const tomlContent = toml.parse(fileContent) as { const tomlContent = toml.parse(fileContent) as {
@@ -28,7 +16,6 @@ export function getConfigValueFromTomlContent(
}; };
return tomlContent?.tool?.uv?.[key]; return tomlContent?.tool?.uv?.[key];
} }
const tomlContent = toml.parse(fileContent) as Record< const tomlContent = toml.parse(fileContent) as Record<
string, string,
string | undefined string | undefined

View File

@@ -1,13 +1,5 @@
export const TOOL_CACHE_NAME = "uv"; export const TOOL_CACHE_NAME = "uv";
export const STATE_UV_PATH = "uv-path"; export const STATE_UV_PATH = "uv-path";
export const STATE_UV_VERSION = "uv-version"; export const STATE_UV_VERSION = "uv-version";
export const VERSIONS_MANIFEST_URL = export const VERSIONS_NDJSON_URL =
"https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson"; "https://raw.githubusercontent.com/astral-sh/versions/main/v1/uv.ndjson";
/** GitHub Releases URL prefix for uv artifacts. */
export const GITHUB_RELEASES_PREFIX =
"https://github.com/astral-sh/uv/releases/download/";
/** Astral mirror URL prefix that fronts GitHub Releases for uv artifacts. */
export const ASTRAL_MIRROR_PREFIX =
"https://releases.astral.sh/github/uv/releases/download/";

View File

@@ -14,17 +14,8 @@ export function getProxyAgent() {
return undefined; return undefined;
} }
export const fetch = async (url: string, opts: RequestInit) => { export const fetch = async (url: string, opts: RequestInit) =>
// Merge timeout signal with any existing signal from opts await undiciFetch(url, {
const timeoutSignal = AbortSignal.timeout(5_000);
const existingSignal = opts.signal;
const mergedSignal = existingSignal
? AbortSignal.any([timeoutSignal, existingSignal])
: timeoutSignal;
return await undiciFetch(url, {
dispatcher: getProxyAgent(), dispatcher: getProxyAgent(),
...opts, ...opts,
signal: mergedSignal,
}); });
};

View File

@@ -1,7 +1,6 @@
import path from "node:path"; import path from "node:path";
import * as core from "@actions/core"; import * as core from "@actions/core";
import { getConfigValueFromTomlFile } from "./config-file"; import { getConfigValueFromTomlFile } from "./config-file";
import * as log from "./logging";
export enum CacheLocalSource { export enum CacheLocalSource {
Input, Input,
@@ -10,131 +9,53 @@ export enum CacheLocalSource {
Default, Default,
} }
export interface CacheLocalPath { export const workingDirectory = core.getInput("working-directory");
path: string; export const version = core.getInput("version");
source: CacheLocalSource; export const versionFile = getVersionFile();
} export const pythonVersion = core.getInput("python-version");
export const activateEnvironment = core.getBooleanInput("activate-environment");
export const venvPath = getVenvPath();
export const checkSum = core.getInput("checksum");
export const enableCache = getEnableCache();
export const restoreCache = core.getInput("restore-cache") === "true";
export const saveCache = core.getInput("save-cache") === "true";
export const cacheSuffix = core.getInput("cache-suffix") || "";
export const cacheLocalPath = getCacheLocalPath();
export const cacheDependencyGlob = getCacheDependencyGlob();
export const pruneCache = core.getInput("prune-cache") === "true";
export const cachePython = core.getInput("cache-python") === "true";
export const ignoreNothingToCache =
core.getInput("ignore-nothing-to-cache") === "true";
export const ignoreEmptyWorkdir =
core.getInput("ignore-empty-workdir") === "true";
export const toolBinDir = getToolBinDir();
export const toolDir = getToolDir();
export const pythonDir = getUvPythonDir();
export const githubToken = core.getInput("github-token");
export const manifestFile = getManifestFile();
export const addProblemMatchers =
core.getInput("add-problem-matchers") === "true";
export const resolutionStrategy = getResolutionStrategy();
export type ResolutionStrategy = "highest" | "lowest"; function getVersionFile(): string {
export interface SetupInputs {
workingDirectory: string;
version: string;
versionFile: string;
pythonVersion: string;
activateEnvironment: boolean;
noProject: boolean;
venvPath: string;
checksum: string;
enableCache: boolean;
restoreCache: boolean;
saveCache: boolean;
cacheSuffix: string;
cacheLocalPath?: CacheLocalPath;
cacheDependencyGlob: string;
pruneCache: boolean;
cachePython: boolean;
ignoreNothingToCache: boolean;
ignoreEmptyWorkdir: boolean;
toolBinDir?: string;
toolDir?: string;
pythonDir: string;
githubToken: string;
manifestFile?: string;
downloadFromAstralMirror: boolean;
addProblemMatchers: boolean;
quiet: boolean;
resolutionStrategy: ResolutionStrategy;
}
export function loadInputs(): SetupInputs {
const workingDirectory = core.getInput("working-directory");
const version = core.getInput("version");
const versionFile = getVersionFile(workingDirectory);
const pythonVersion = core.getInput("python-version");
const activateEnvironment = core.getBooleanInput("activate-environment");
const noProject = core.getBooleanInput("no-project");
const venvPath = getVenvPath(workingDirectory, activateEnvironment);
const checksum = core.getInput("checksum");
const enableCache = getEnableCache();
const restoreCache = core.getInput("restore-cache") === "true";
const saveCache = core.getInput("save-cache") === "true";
const cacheSuffix = core.getInput("cache-suffix") || "";
const cacheLocalPath = getCacheLocalPath(
workingDirectory,
versionFile,
enableCache,
);
const cacheDependencyGlob = getCacheDependencyGlob(workingDirectory);
const pruneCache = core.getInput("prune-cache") === "true";
const cachePython = core.getInput("cache-python") === "true";
const ignoreNothingToCache =
core.getInput("ignore-nothing-to-cache") === "true";
const ignoreEmptyWorkdir = core.getInput("ignore-empty-workdir") === "true";
const toolBinDir = getToolBinDir(workingDirectory);
const toolDir = getToolDir(workingDirectory);
const pythonDir = getUvPythonDir();
const githubToken = core.getInput("github-token");
const manifestFile = getManifestFile();
const downloadFromAstralMirror =
core.getInput("download-from-astral-mirror") === "true";
const addProblemMatchers = core.getInput("add-problem-matchers") === "true";
const quiet = core.getInput("quiet") === "true";
const resolutionStrategy = getResolutionStrategy();
return {
activateEnvironment,
addProblemMatchers,
cacheDependencyGlob,
cacheLocalPath,
cachePython,
cacheSuffix,
checksum,
downloadFromAstralMirror,
enableCache,
githubToken,
ignoreEmptyWorkdir,
ignoreNothingToCache,
manifestFile,
noProject,
pruneCache,
pythonDir,
pythonVersion,
quiet,
resolutionStrategy,
restoreCache,
saveCache,
toolBinDir,
toolDir,
venvPath,
version,
versionFile,
workingDirectory,
};
}
function getVersionFile(workingDirectory: string): string {
const versionFileInput = core.getInput("version-file"); const versionFileInput = core.getInput("version-file");
if (versionFileInput !== "") { if (versionFileInput !== "") {
const tildeExpanded = expandTilde(versionFileInput); const tildeExpanded = expandTilde(versionFileInput);
return resolveRelativePath(workingDirectory, tildeExpanded); return resolveRelativePath(tildeExpanded);
} }
return versionFileInput; return versionFileInput;
} }
function getVenvPath( function getVenvPath(): string {
workingDirectory: string,
activateEnvironment: boolean,
): string {
const venvPathInput = core.getInput("venv-path"); const venvPathInput = core.getInput("venv-path");
if (venvPathInput !== "") { if (venvPathInput !== "") {
if (!activateEnvironment) { if (!activateEnvironment) {
log.warning("venv-path is only used when activate-environment is true"); core.warning("venv-path is only used when activate-environment is true");
} }
const tildeExpanded = expandTilde(venvPathInput); const tildeExpanded = expandTilde(venvPathInput);
return normalizePath(resolveRelativePath(workingDirectory, tildeExpanded)); return normalizePath(resolveRelativePath(tildeExpanded));
} }
return normalizePath(resolveRelativePath(workingDirectory, ".venv")); return normalizePath(resolveRelativePath(".venv"));
} }
function getEnableCache(): boolean { function getEnableCache(): boolean {
@@ -145,11 +66,11 @@ function getEnableCache(): boolean {
return enableCacheInput === "true"; return enableCacheInput === "true";
} }
function getToolBinDir(workingDirectory: string): string | undefined { function getToolBinDir(): string | undefined {
const toolBinDirInput = core.getInput("tool-bin-dir"); const toolBinDirInput = core.getInput("tool-bin-dir");
if (toolBinDirInput !== "") { if (toolBinDirInput !== "") {
const tildeExpanded = expandTilde(toolBinDirInput); const tildeExpanded = expandTilde(toolBinDirInput);
return resolveRelativePath(workingDirectory, tildeExpanded); return resolveRelativePath(tildeExpanded);
} }
if (process.platform === "win32") { if (process.platform === "win32") {
if (process.env.RUNNER_TEMP !== undefined) { if (process.env.RUNNER_TEMP !== undefined) {
@@ -162,11 +83,11 @@ function getToolBinDir(workingDirectory: string): string | undefined {
return undefined; return undefined;
} }
function getToolDir(workingDirectory: string): string | undefined { function getToolDir(): string | undefined {
const toolDirInput = core.getInput("tool-dir"); const toolDirInput = core.getInput("tool-dir");
if (toolDirInput !== "") { if (toolDirInput !== "") {
const tildeExpanded = expandTilde(toolDirInput); const tildeExpanded = expandTilde(toolDirInput);
return resolveRelativePath(workingDirectory, tildeExpanded); return resolveRelativePath(tildeExpanded);
} }
if (process.platform === "win32") { if (process.platform === "win32") {
if (process.env.RUNNER_TEMP !== undefined) { if (process.env.RUNNER_TEMP !== undefined) {
@@ -179,31 +100,29 @@ function getToolDir(workingDirectory: string): string | undefined {
return undefined; return undefined;
} }
function getCacheLocalPath( function getCacheLocalPath():
workingDirectory: string, | {
versionFile: string, path: string;
enableCache: boolean, source: CacheLocalSource;
): CacheLocalPath | undefined { }
| undefined {
const cacheLocalPathInput = core.getInput("cache-local-path"); const cacheLocalPathInput = core.getInput("cache-local-path");
if (cacheLocalPathInput !== "") { if (cacheLocalPathInput !== "") {
const tildeExpanded = expandTilde(cacheLocalPathInput); const tildeExpanded = expandTilde(cacheLocalPathInput);
return { return {
path: resolveRelativePath(workingDirectory, tildeExpanded), path: resolveRelativePath(tildeExpanded),
source: CacheLocalSource.Input, source: CacheLocalSource.Input,
}; };
} }
const cacheDirFromConfig = getCacheDirFromConfig( const cacheDirFromConfig = getCacheDirFromConfig();
workingDirectory,
versionFile,
);
if (cacheDirFromConfig !== undefined) { if (cacheDirFromConfig !== undefined) {
return { path: cacheDirFromConfig, source: CacheLocalSource.Config }; return { path: cacheDirFromConfig, source: CacheLocalSource.Config };
} }
if (process.env.UV_CACHE_DIR !== undefined) { if (process.env.UV_CACHE_DIR !== undefined) {
log.info(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`); core.info(`UV_CACHE_DIR is already set to ${process.env.UV_CACHE_DIR}`);
return { path: process.env.UV_CACHE_DIR, source: CacheLocalSource.Env }; return { path: process.env.UV_CACHE_DIR, source: CacheLocalSource.Env };
} }
if (enableCache) { if (getEnableCache()) {
if (process.env.RUNNER_ENVIRONMENT === "github-hosted") { if (process.env.RUNNER_ENVIRONMENT === "github-hosted") {
if (process.env.RUNNER_TEMP !== undefined) { if (process.env.RUNNER_TEMP !== undefined) {
return { return {
@@ -228,21 +147,18 @@ function getCacheLocalPath(
} }
} }
function getCacheDirFromConfig( function getCacheDirFromConfig(): string | undefined {
workingDirectory: string,
versionFile: string,
): string | undefined {
for (const filePath of [versionFile, "uv.toml", "pyproject.toml"]) { for (const filePath of [versionFile, "uv.toml", "pyproject.toml"]) {
const resolvedPath = resolveRelativePath(workingDirectory, filePath); const resolvedPath = resolveRelativePath(filePath);
try { try {
const cacheDir = getConfigValueFromTomlFile(resolvedPath, "cache-dir"); const cacheDir = getConfigValueFromTomlFile(resolvedPath, "cache-dir");
if (cacheDir !== undefined) { if (cacheDir !== undefined) {
log.info(`Found cache-dir in ${resolvedPath}: ${cacheDir}`); core.info(`Found cache-dir in ${resolvedPath}: ${cacheDir}`);
return cacheDir; return cacheDir;
} }
} catch (err) { } catch (err) {
const message = (err as Error).message; const message = (err as Error).message;
log.warning(`Error while parsing ${filePath}: ${message}`); core.warning(`Error while parsing ${filePath}: ${message}`);
return undefined; return undefined;
} }
} }
@@ -251,7 +167,7 @@ function getCacheDirFromConfig(
export function getUvPythonDir(): string { export function getUvPythonDir(): string {
if (process.env.UV_PYTHON_INSTALL_DIR !== undefined) { if (process.env.UV_PYTHON_INSTALL_DIR !== undefined) {
log.info( core.info(
`UV_PYTHON_INSTALL_DIR is already set to ${process.env.UV_PYTHON_INSTALL_DIR}`, `UV_PYTHON_INSTALL_DIR is already set to ${process.env.UV_PYTHON_INSTALL_DIR}`,
); );
return process.env.UV_PYTHON_INSTALL_DIR; return process.env.UV_PYTHON_INSTALL_DIR;
@@ -259,8 +175,9 @@ export function getUvPythonDir(): string {
if (process.env.RUNNER_ENVIRONMENT !== "github-hosted") { if (process.env.RUNNER_ENVIRONMENT !== "github-hosted") {
if (process.platform === "win32") { if (process.platform === "win32") {
return `${process.env.APPDATA}${path.sep}uv${path.sep}python`; return `${process.env.APPDATA}${path.sep}uv${path.sep}python`;
} else {
return `${process.env.HOME}${path.sep}.local${path.sep}share${path.sep}uv${path.sep}python`;
} }
return `${process.env.HOME}${path.sep}.local${path.sep}share${path.sep}uv${path.sep}python`;
} }
if (process.env.RUNNER_TEMP !== undefined) { if (process.env.RUNNER_TEMP !== undefined) {
return `${process.env.RUNNER_TEMP}${path.sep}uv-python-dir`; return `${process.env.RUNNER_TEMP}${path.sep}uv-python-dir`;
@@ -270,14 +187,14 @@ export function getUvPythonDir(): string {
); );
} }
function getCacheDependencyGlob(workingDirectory: string): string { function getCacheDependencyGlob(): string {
const cacheDependencyGlobInput = core.getInput("cache-dependency-glob"); const cacheDependencyGlobInput = core.getInput("cache-dependency-glob");
if (cacheDependencyGlobInput !== "") { if (cacheDependencyGlobInput !== "") {
return cacheDependencyGlobInput return cacheDependencyGlobInput
.split("\n") .split("\n")
.map((part) => part.trim()) .map((part) => part.trim())
.map((part) => expandTilde(part)) .map((part) => expandTilde(part))
.map((part) => resolveRelativePath(workingDirectory, part)) .map((part) => resolveRelativePath(part))
.join("\n"); .join("\n");
} }
return cacheDependencyGlobInput; return cacheDependencyGlobInput;
@@ -303,10 +220,7 @@ function normalizePath(inputPath: string): string {
return trimmed; return trimmed;
} }
function resolveRelativePath( function resolveRelativePath(inputPath: string): string {
workingDirectory: string,
inputPath: string,
): string {
const hasNegation = inputPath.startsWith("!"); const hasNegation = inputPath.startsWith("!");
const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath; const pathWithoutNegation = hasNegation ? inputPath.substring(1) : inputPath;
@@ -326,7 +240,7 @@ function getManifestFile(): string | undefined {
return undefined; return undefined;
} }
function getResolutionStrategy(): ResolutionStrategy { function getResolutionStrategy(): "highest" | "lowest" {
const resolutionStrategyInput = core.getInput("resolution-strategy"); const resolutionStrategyInput = core.getInput("resolution-strategy");
if (resolutionStrategyInput === "lowest") { if (resolutionStrategyInput === "lowest") {
return "lowest"; return "lowest";

View File

@@ -1,21 +0,0 @@
import * as core from "@actions/core";
let quiet: boolean | undefined;
function isQuiet(): boolean {
if (quiet === undefined) {
quiet =
typeof core.getInput === "function" && core.getInput("quiet") === "true";
}
return quiet;
}
export function info(msg: string): void {
if (!isQuiet()) {
core.info(msg);
}
}
export const warning = core.warning;
export const error = core.error;
export const debug = core.debug;

View File

@@ -1,101 +0,0 @@
import fs from "node:fs";
import { getConfigValueFromTomlContent } from "../utils/config-file";
import * as log from "../utils/logging";
import {
getUvVersionFromParsedPyproject,
getUvVersionFromRequirementsText,
parsePyprojectContent,
} from "./requirements-file";
import { normalizeVersionSpecifier } from "./specifier";
import { getUvVersionFromToolVersions } from "./tool-versions-file";
import type { ParsedVersionFile, VersionFileFormat } from "./types";
interface VersionFileParser {
format: VersionFileFormat;
parse(filePath: string): string | undefined;
supports(filePath: string): boolean;
}
const VERSION_FILE_PARSERS: VersionFileParser[] = [
{
format: ".tool-versions",
parse: (filePath) => getUvVersionFromToolVersions(filePath),
supports: (filePath) => filePath.endsWith(".tool-versions"),
},
{
format: "uv.toml",
parse: (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf-8");
return getConfigValueFromTomlContent(
filePath,
fileContent,
"required-version",
);
},
supports: (filePath) => filePath.endsWith("uv.toml"),
},
{
format: "pyproject.toml",
parse: (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf-8");
const pyproject = parsePyprojectContent(fileContent);
const requiredVersion = pyproject.tool?.uv?.["required-version"];
if (requiredVersion !== undefined) {
return requiredVersion;
}
return getUvVersionFromParsedPyproject(pyproject);
},
supports: (filePath) => filePath.endsWith("pyproject.toml"),
},
{
format: "requirements",
parse: (filePath) => {
const fileContent = fs.readFileSync(filePath, "utf-8");
return getUvVersionFromRequirementsText(fileContent);
},
supports: (filePath) => filePath.endsWith(".txt"),
},
];
export function getParsedVersionFile(
filePath: string,
): ParsedVersionFile | undefined {
log.info(`Trying to find version for uv in: ${filePath}`);
if (!fs.existsSync(filePath)) {
log.info(`Could not find file: ${filePath}`);
return undefined;
}
const parser = getVersionFileParser(filePath);
if (parser === undefined) {
return undefined;
}
try {
const specifier = parser.parse(filePath);
if (specifier === undefined) {
return undefined;
}
const normalizedSpecifier = normalizeVersionSpecifier(specifier);
log.info(`Found version for uv in ${filePath}: ${normalizedSpecifier}`);
return {
format: parser.format,
specifier: normalizedSpecifier,
};
} catch (error) {
log.warning(`Error while parsing ${filePath}: ${(error as Error).message}`);
return undefined;
}
}
export function getUvVersionFromFile(filePath: string): string | undefined {
return getParsedVersionFile(filePath)?.specifier;
}
function getVersionFileParser(filePath: string): VersionFileParser | undefined {
return VERSION_FILE_PARSERS.find((parser) => parser.supports(filePath));
}

View File

@@ -5,23 +5,31 @@ export function getUvVersionFromRequirementsFile(
filePath: string, filePath: string,
): string | undefined { ): string | undefined {
const fileContent = fs.readFileSync(filePath, "utf-8"); const fileContent = fs.readFileSync(filePath, "utf-8");
if (filePath.endsWith(".txt")) { if (filePath.endsWith(".txt")) {
return getUvVersionFromRequirementsText(fileContent); return getUvVersionFromAllDependencies(fileContent.split("\n"));
} }
const dependencies = parsePyprojectDependencies(fileContent);
return getUvVersionFromPyprojectContent(fileContent); return getUvVersionFromAllDependencies(dependencies);
}
function getUvVersionFromAllDependencies(
allDependencies: string[],
): string | undefined {
return allDependencies
.find((dep: string) => dep.match(/^uv[=<>~!]/))
?.match(/^uv([=<>~!]+\S*)/)?.[1]
.trim();
} }
export function getUvVersionFromRequirementsText( interface Pyproject {
fileContent: string, project?: {
): string | undefined { dependencies?: string[];
return getUvVersionFromAllDependencies(fileContent.split("\n")); "optional-dependencies"?: Record<string, string[]>;
};
"dependency-groups"?: Record<string, Array<string | object>>;
} }
export function getUvVersionFromParsedPyproject( function parsePyprojectDependencies(pyprojectContent: string): string[] {
pyproject: Pyproject, const pyproject: Pyproject = toml.parse(pyprojectContent);
): string | undefined {
const dependencies: string[] = pyproject?.project?.dependencies || []; const dependencies: string[] = pyproject?.project?.dependencies || [];
const optionalDependencies: string[] = Object.values( const optionalDependencies: string[] = Object.values(
pyproject?.project?.["optional-dependencies"] || {}, pyproject?.project?.["optional-dependencies"] || {},
@@ -31,39 +39,5 @@ export function getUvVersionFromParsedPyproject(
) )
.flat() .flat()
.filter((item: string | object) => typeof item === "string"); .filter((item: string | object) => typeof item === "string");
return dependencies.concat(optionalDependencies, devDependencies);
return getUvVersionFromAllDependencies(
dependencies.concat(optionalDependencies, devDependencies),
);
}
export function getUvVersionFromPyprojectContent(
pyprojectContent: string,
): string | undefined {
const pyproject = parsePyprojectContent(pyprojectContent);
return getUvVersionFromParsedPyproject(pyproject);
}
export interface Pyproject {
project?: {
dependencies?: string[];
"optional-dependencies"?: Record<string, string[]>;
};
"dependency-groups"?: Record<string, Array<string | object>>;
tool?: {
uv?: Record<string, string | undefined>;
};
}
export function parsePyprojectContent(pyprojectContent: string): Pyproject {
return toml.parse(pyprojectContent) as Pyproject;
}
function getUvVersionFromAllDependencies(
allDependencies: string[],
): string | undefined {
return allDependencies
.find((dep: string) => dep.match(/^uv[=<>~!]/))
?.match(/^uv([=<>~!]+\S*)/)?.[1]
.trim();
} }

View File

@@ -1,184 +1,34 @@
import fs from "node:fs";
import * as core from "@actions/core"; import * as core from "@actions/core";
import * as tc from "@actions/tool-cache"; import { getConfigValueFromTomlFile } from "../utils/config-file";
import * as pep440 from "@renovatebot/pep440"; import { getUvVersionFromRequirementsFile } from "./requirements-file";
import * as semver from "semver"; import { getUvVersionFromToolVersions } from "./tool-versions-file";
import { getAllVersions, getLatestVersion } from "../download/manifest";
import type { ResolutionStrategy } from "../utils/inputs";
import * as log from "../utils/logging";
import {
type ParsedVersionSpecifier,
parseVersionSpecifier,
} from "./specifier";
import type { ResolveUvVersionOptions } from "./types";
import { resolveVersionRequest } from "./version-request-resolver";
interface ConcreteVersionResolutionContext { export function getUvVersionFromFile(filePath: string): string | undefined {
manifestUrl?: string; core.info(`Trying to find version for uv in: ${filePath}`);
parsedSpecifier: ParsedVersionSpecifier; if (!fs.existsSync(filePath)) {
resolutionStrategy: ResolutionStrategy; core.info(`Could not find file: ${filePath}`);
} return undefined;
}
interface ConcreteVersionResolver { let uvVersion: string | undefined;
resolve( try {
context: ConcreteVersionResolutionContext, uvVersion = getUvVersionFromToolVersions(filePath);
): Promise<string | undefined>; if (uvVersion === undefined) {
} uvVersion = getConfigValueFromTomlFile(filePath, "required-version");
class ExactVersionResolver implements ConcreteVersionResolver {
async resolve(
context: ConcreteVersionResolutionContext,
): Promise<string | undefined> {
if (context.parsedSpecifier.kind !== "exact") {
return undefined;
} }
if (uvVersion === undefined) {
core.debug( uvVersion = getUvVersionFromRequirementsFile(filePath);
`Version ${context.parsedSpecifier.normalized} is an explicit version.`,
);
return context.parsedSpecifier.normalized;
}
}
class LatestVersionResolver implements ConcreteVersionResolver {
async resolve(
context: ConcreteVersionResolutionContext,
): Promise<string | undefined> {
const shouldUseLatestVersion =
context.parsedSpecifier.kind === "latest" ||
(context.parsedSpecifier.kind === "range" &&
context.parsedSpecifier.isSimpleMinimumVersionSpecifier &&
context.resolutionStrategy === "highest");
if (!shouldUseLatestVersion) {
return undefined;
} }
} catch (err) {
if ( const message = (err as Error).message;
context.parsedSpecifier.kind === "range" && core.warning(`Error while parsing ${filePath}: ${message}`);
context.parsedSpecifier.isSimpleMinimumVersionSpecifier return undefined;
) {
log.info("Found minimum version specifier, using latest version");
}
const latestVersion = await getLatestVersion(context.manifestUrl);
if (
context.parsedSpecifier.kind === "range" &&
context.parsedSpecifier.isSimpleMinimumVersionSpecifier &&
!pep440.satisfies(latestVersion, context.parsedSpecifier.raw)
) {
throw new Error(`No version found for ${context.parsedSpecifier.raw}`);
}
return latestVersion;
} }
} if (uvVersion?.startsWith("==")) {
uvVersion = uvVersion.slice(2);
class RangeVersionResolver implements ConcreteVersionResolver { }
async resolve( if (uvVersion !== undefined) {
context: ConcreteVersionResolutionContext, core.info(`Found version for uv in ${filePath}: ${uvVersion}`);
): Promise<string | undefined> { }
if (context.parsedSpecifier.kind !== "range") { return uvVersion;
return undefined;
}
const availableVersions = await getAllVersions(context.manifestUrl);
core.debug(`Available versions: ${availableVersions}`);
const resolvedVersion =
context.resolutionStrategy === "lowest"
? minSatisfying(availableVersions, context.parsedSpecifier.normalized)
: maxSatisfying(availableVersions, context.parsedSpecifier.normalized);
if (resolvedVersion === undefined) {
throw new Error(`No version found for ${context.parsedSpecifier.raw}`);
}
return resolvedVersion;
}
}
const CONCRETE_VERSION_RESOLVERS: ConcreteVersionResolver[] = [
new ExactVersionResolver(),
new LatestVersionResolver(),
new RangeVersionResolver(),
];
export async function resolveUvVersion(
options: ResolveUvVersionOptions,
): Promise<string> {
const request = resolveVersionRequest(options);
const resolutionStrategy = options.resolutionStrategy ?? "highest";
const version = await resolveVersion(
request.specifier,
options.manifestFile,
resolutionStrategy,
);
return version;
}
export async function resolveVersion(
versionInput: string,
manifestUrl: string | undefined,
resolutionStrategy: ResolutionStrategy = "highest",
): Promise<string> {
core.debug(`Resolving version: ${versionInput}`);
const context: ConcreteVersionResolutionContext = {
manifestUrl,
parsedSpecifier: parseVersionSpecifier(versionInput),
resolutionStrategy,
};
for (const resolver of CONCRETE_VERSION_RESOLVERS) {
const version = await resolver.resolve(context);
if (version !== undefined) {
return version;
}
}
throw new Error(`No version found for ${versionInput}`);
}
function maxSatisfying(
versions: string[],
version: string,
): string | undefined {
const maxSemver = tc.evaluateVersions(versions, version);
if (maxSemver !== "") {
core.debug(`Found a version that satisfies the semver range: ${maxSemver}`);
return maxSemver;
}
const maxPep440 = pep440.maxSatisfying(versions, version);
if (maxPep440 !== null) {
core.debug(
`Found a version that satisfies the pep440 specifier: ${maxPep440}`,
);
return maxPep440;
}
return undefined;
}
function minSatisfying(
versions: string[],
version: string,
): string | undefined {
const minSemver = semver.minSatisfying(versions, version);
if (minSemver !== null) {
core.debug(`Found a version that satisfies the semver range: ${minSemver}`);
return minSemver;
}
const minPep440 = pep440.minSatisfying(versions, version);
if (minPep440 !== null) {
core.debug(
`Found a version that satisfies the pep440 specifier: ${minPep440}`,
);
return minPep440;
}
return undefined;
} }

View File

@@ -1,59 +0,0 @@
import * as tc from "@actions/tool-cache";
export type ParsedVersionSpecifier =
| {
kind: "exact";
normalized: string;
raw: string;
}
| {
kind: "latest";
normalized: "latest";
raw: string;
}
| {
isSimpleMinimumVersionSpecifier: boolean;
kind: "range";
normalized: string;
raw: string;
};
export function normalizeVersionSpecifier(specifier: string): string {
const trimmedSpecifier = specifier.trim();
if (trimmedSpecifier.startsWith("==")) {
return trimmedSpecifier.slice(2);
}
return trimmedSpecifier;
}
export function parseVersionSpecifier(
specifier: string,
): ParsedVersionSpecifier {
const raw = specifier.trim();
const normalized = normalizeVersionSpecifier(raw);
if (normalized === "latest") {
return {
kind: "latest",
normalized: "latest",
raw,
};
}
if (tc.isExplicitVersion(normalized)) {
return {
kind: "exact",
normalized,
raw,
};
}
return {
isSimpleMinimumVersionSpecifier: raw.includes(">") && !raw.includes(","),
kind: "range",
normalized,
raw,
};
}

View File

@@ -1,34 +0,0 @@
import type { ResolutionStrategy } from "../utils/inputs";
export type VersionSource =
| "input"
| "version-file"
| "uv.toml"
| "pyproject.toml"
| "default";
export type VersionFileFormat =
| ".tool-versions"
| "pyproject.toml"
| "requirements"
| "uv.toml";
export interface ParsedVersionFile {
format: VersionFileFormat;
specifier: string;
}
export interface ResolveUvVersionOptions {
manifestFile?: string;
resolutionStrategy?: ResolutionStrategy;
version?: string;
versionFile?: string;
workingDirectory: string;
}
export interface VersionRequest {
format?: VersionFileFormat;
source: VersionSource;
sourcePath?: string;
specifier: string;
}

View File

@@ -1,158 +0,0 @@
import * as path from "node:path";
import * as log from "../utils/logging";
import { getParsedVersionFile } from "./file-parser";
import { normalizeVersionSpecifier } from "./specifier";
import type {
ParsedVersionFile,
ResolveUvVersionOptions,
VersionRequest,
} from "./types";
export interface VersionRequestResolver {
resolve(context: VersionRequestContext): VersionRequest | undefined;
}
export class VersionRequestContext {
readonly version: string | undefined;
readonly versionFile: string | undefined;
readonly workingDirectory: string;
private readonly parsedFiles = new Map<
string,
ParsedVersionFile | undefined
>();
constructor(
version: string | undefined,
versionFile: string | undefined,
workingDirectory: string,
) {
this.version = version;
this.versionFile = versionFile;
this.workingDirectory = workingDirectory;
}
getVersionFile(filePath: string): ParsedVersionFile | undefined {
const cachedResult = this.parsedFiles.get(filePath);
if (cachedResult !== undefined || this.parsedFiles.has(filePath)) {
return cachedResult;
}
const result = getParsedVersionFile(filePath);
this.parsedFiles.set(filePath, result);
return result;
}
getWorkspaceCandidates(): Array<{
source: "pyproject.toml" | "uv.toml";
sourcePath: string;
}> {
return [
{
source: "uv.toml",
sourcePath: path.join(this.workingDirectory, "uv.toml"),
},
{
source: "pyproject.toml",
sourcePath: path.join(this.workingDirectory, "pyproject.toml"),
},
];
}
}
export class ExplicitInputVersionResolver implements VersionRequestResolver {
resolve(context: VersionRequestContext): VersionRequest | undefined {
if (context.version === undefined) {
return undefined;
}
return {
source: "input",
specifier: normalizeVersionSpecifier(context.version),
};
}
}
export class VersionFileVersionResolver implements VersionRequestResolver {
resolve(context: VersionRequestContext): VersionRequest | undefined {
if (context.versionFile === undefined) {
return undefined;
}
const versionFile = context.getVersionFile(context.versionFile);
if (versionFile === undefined) {
throw new Error(
`Could not determine uv version from file: ${context.versionFile}`,
);
}
return {
format: versionFile.format,
source: "version-file",
sourcePath: context.versionFile,
specifier: versionFile.specifier,
};
}
}
export class WorkspaceVersionResolver implements VersionRequestResolver {
resolve(context: VersionRequestContext): VersionRequest | undefined {
for (const candidate of context.getWorkspaceCandidates()) {
const versionFile = context.getVersionFile(candidate.sourcePath);
if (versionFile === undefined) {
continue;
}
return {
format: versionFile.format,
source: candidate.source,
sourcePath: candidate.sourcePath,
specifier: versionFile.specifier,
};
}
log.info(
"Could not determine uv version from uv.toml or pyproject.toml. Falling back to latest.",
);
return undefined;
}
}
export class LatestVersionResolver implements VersionRequestResolver {
resolve(): VersionRequest {
return {
source: "default",
specifier: "latest",
};
}
}
const VERSION_REQUEST_RESOLVERS: VersionRequestResolver[] = [
new ExplicitInputVersionResolver(),
new VersionFileVersionResolver(),
new WorkspaceVersionResolver(),
new LatestVersionResolver(),
];
export function resolveVersionRequest(
options: ResolveUvVersionOptions,
): VersionRequest {
const context = new VersionRequestContext(
emptyToUndefined(options.version),
emptyToUndefined(options.versionFile),
options.workingDirectory,
);
for (const resolver of VERSION_REQUEST_RESOLVERS) {
const request = resolver.resolve(context);
if (request !== undefined) {
return request;
}
}
throw new Error("Could not resolve a requested uv version.");
}
function emptyToUndefined(value: string | undefined): string | undefined {
return value === undefined || value === "" ? undefined : value;
}