mirror of
https://github.com/astral-sh/setup-uv.git
synced 2025-06-10 22:37:44 +00:00
Compare commits
No commits in common. "main" and "v5.0.0" have entirely different histories.
9
.github/actionlint.yaml
vendored
9
.github/actionlint.yaml
vendored
@ -1,9 +0,0 @@
|
||||
self-hosted-runner:
|
||||
# Custom labels of self-hosted or large GitHub hosted runners
|
||||
# so that actionlint knows that they are not a typo
|
||||
labels:
|
||||
- selfhosted-ubuntu-arm64
|
||||
# Configuration variables in array of strings defined in your repository or
|
||||
# organization. `null` means disabling configuration variables check.
|
||||
# Empty array means no configuration variable is allowed.
|
||||
config-variables: null
|
2
.github/release-drafter.yml
vendored
2
.github/release-drafter.yml
vendored
@ -19,7 +19,7 @@ categories:
|
||||
labels:
|
||||
- "maintenance"
|
||||
- "ci"
|
||||
- "update-known-versions"
|
||||
- "update-known-checksums"
|
||||
- title: "📚 Documentation"
|
||||
labels:
|
||||
- "documentation"
|
||||
|
35
.github/scripts/check-all-tests-passed-needs.ts
vendored
35
.github/scripts/check-all-tests-passed-needs.ts
vendored
@ -1,35 +0,0 @@
|
||||
import * as fs from "node:fs";
|
||||
import * as yaml from "js-yaml";
|
||||
|
||||
interface WorkflowJob {
|
||||
needs?: string[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
interface Workflow {
|
||||
jobs: Record<string, WorkflowJob>;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
const workflow = yaml.load(
|
||||
fs.readFileSync("../workflows/test.yml", "utf8"),
|
||||
) as Workflow;
|
||||
const jobs = Object.keys(workflow.jobs);
|
||||
const allTestsPassed = workflow.jobs["all-tests-passed"];
|
||||
const needs: string[] = allTestsPassed.needs || [];
|
||||
|
||||
const expectedNeeds = jobs.filter((j) => j !== "all-tests-passed");
|
||||
const missing = expectedNeeds.filter((j) => !needs.includes(j));
|
||||
|
||||
if (missing.length > 0) {
|
||||
console.error(
|
||||
`Missing jobs in all-tests-passed needs: ${missing.join(", ")}`,
|
||||
);
|
||||
console.info(
|
||||
"Please add the missing jobs to the needs section of all-tests-passed in test.yml.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(
|
||||
"All jobs in test.yml are in the needs section of all-tests-passed.",
|
||||
);
|
49
.github/workflows/check-dist.yml
vendored
Normal file
49
.github/workflows/check-dist.yml
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
name: Check dist/
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Rebuild the dist/ directory
|
||||
run: |
|
||||
npm run build
|
||||
npm run package
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff --text -v
|
||||
exit 1
|
||||
fi
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
9
.github/workflows/codeql-analysis.yml
vendored
9
.github/workflows/codeql-analysis.yml
vendored
@ -12,14 +12,13 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
branches: [main]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches:
|
||||
- main
|
||||
branches: [main]
|
||||
schedule:
|
||||
- cron: "31 7 * * 3"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
|
9
.github/workflows/release-drafter.yml
vendored
9
.github/workflows/release-drafter.yml
vendored
@ -3,20 +3,17 @@ name: Release Drafter
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update_release_draft:
|
||||
name: ✏️ Draft release
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: read
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 🚀 Run Release Drafter
|
||||
uses: release-drafter/release-drafter@v6.1.0
|
||||
uses: release-drafter/release-drafter@v6.0.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
43
.github/workflows/test-cache-windows.yml
vendored
Normal file
43
.github/workflows/test-cache-windows.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
name: "test-cache-windows"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-setup-cache:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__\fixtures\uv-project
|
||||
test-restore-cache:
|
||||
runs-on: windows-latest
|
||||
needs: test-setup-cache
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}
|
||||
- name: Cache was hit
|
||||
run: |
|
||||
if ($env:CACHE_HIT -ne "true") {
|
||||
exit 1
|
||||
}
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__\fixtures\uv-project
|
229
.github/workflows/test-cache.yml
vendored
Normal file
229
.github/workflows/test-cache.yml
vendored
Normal file
@ -0,0 +1,229 @@
|
||||
name: "test-cache"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-setup-cache:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
enable-cache: [ "true", "false", "auto" ]
|
||||
os: ["ubuntu-latest", "selfhosted-ubuntu-arm64"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: ${{ matrix.enable-cache }}
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-${{ matrix.os }}-${{ matrix.enable-cache }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
test-restore-cache:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
enable-cache: [ "true", "false", "auto" ]
|
||||
os: [ "ubuntu-latest", "selfhosted-ubuntu-arm64" ]
|
||||
needs: test-setup-cache
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: ${{ matrix.enable-cache }}
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-${{ matrix.os }}-${{ matrix.enable-cache }}
|
||||
- name: Cache was hit
|
||||
if: ${{ matrix.enable-cache == 'true' || (matrix.enable-cache == 'auto' && matrix.os == 'ubuntu-latest') }}
|
||||
run: |
|
||||
if [ "$CACHE_HIT" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- name: Cache was not hit
|
||||
if: ${{ matrix.enable-cache == 'false' || (matrix.enable-cache == 'auto' && matrix.os == 'selfhosted-ubuntu-arm64') }}
|
||||
run: |
|
||||
if [ "$CACHE_HIT" == "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
test-setup-cache-requirements-txt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-requirements-txt
|
||||
- run: |
|
||||
uv venv
|
||||
uv pip install -r requirements.txt
|
||||
working-directory: __tests__/fixtures/requirements-txt-project
|
||||
test-restore-cache-requirements-txt:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-setup-cache
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-requirements-txt
|
||||
- name: Cache was hit
|
||||
run: |
|
||||
if [ "$CACHE_HIT" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- run: |
|
||||
uv venv
|
||||
uv pip install -r requirements.txt
|
||||
working-directory: __tests__/fixtures/requirements-txt-project
|
||||
|
||||
test-setup-cache-dependency-glob:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
__tests__/fixtures/uv-project/uv.lock
|
||||
**/pyproject.toml
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
test-restore-cache-dependency-glob:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-setup-cache-dependency-glob
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Change pyproject.toml
|
||||
run: |
|
||||
echo '[tool.uv]' >> __tests__/fixtures/uv-project/pyproject.toml
|
||||
echo 'dev-dependencies = []' >> __tests__/fixtures/uv-project/pyproject.toml
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
__tests__/fixtures/uv-project/uv.lock
|
||||
**/pyproject.toml
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob
|
||||
ignore-nothing-to-cache: true
|
||||
- name: Cache was not hit
|
||||
run: |
|
||||
if [ "$CACHE_HIT" == "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
|
||||
test-setup-cache-local:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local
|
||||
cache-local-path: /tmp/uv-cache
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
test-restore-cache-local:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
needs: test-setup-cache-local
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local
|
||||
cache-local-path: /tmp/uv-cache
|
||||
- name: Cache was hit
|
||||
run: |
|
||||
if [ "$CACHE_HIT" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-tilde-expansion-cache-local-path:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Create cache directory
|
||||
run: mkdir -p ~/uv-cache
|
||||
shell: bash
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
cache-local-path: ~/uv-cache/cache-local-path
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-tilde-expansion-cache-dependency-glob:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Create cache directory
|
||||
run: mkdir -p ~/uv-cache
|
||||
shell: bash
|
||||
- name: Create cache dependency glob file
|
||||
run: touch ~/uv-cache.glob
|
||||
shell: bash
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-local-path: ~/uv-cache/cache-dependency-glob
|
||||
cache-dependency-glob: "~/uv-cache.glob"
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
cleanup-tilde-expansion-tests:
|
||||
needs:
|
||||
- test-tilde-expansion-cache-local-path
|
||||
- test-tilde-expansion-cache-dependency-glob
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- name: Remove cache directory
|
||||
run: rm -rf ~/uv-cache
|
||||
shell: bash
|
||||
- name: Remove cache dependency glob file
|
||||
run: rm -f ~/uv-cache.glob
|
||||
shell: bash
|
||||
|
||||
test-no-python-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Fake pyproject.toml at root
|
||||
run: cp __tests__/fixtures/old-python-constraint-project/pyproject.toml pyproject.toml
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/old-python-constraint-project
|
27
.github/workflows/test-windows.yml
vendored
Normal file
27
.github/workflows/test-windows.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
name: "test-windows"
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test-default-version:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Should not be on path
|
||||
run: |
|
||||
if (!(Get-Command -Name "uv" -ErrorAction SilentlyContinue)) {
|
||||
exit 0
|
||||
} else {
|
||||
exit 1
|
||||
}
|
||||
- name: Setup uv
|
||||
uses: ./
|
||||
- run: uv sync
|
||||
working-directory: __tests__\fixtures\uv-project
|
433
.github/workflows/test.yml
vendored
433
.github/workflows/test.yml
vendored
@ -1,9 +1,6 @@
|
||||
name: "test"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
@ -12,16 +9,11 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Actionlint
|
||||
uses: eifinger/actionlint-action@23c85443d840cd73bbecb9cddfc933cc21649a38 # v1.9.1
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
@ -29,33 +21,20 @@ jobs:
|
||||
npm install
|
||||
- run: |
|
||||
npm run all
|
||||
- name: Check all jobs are in all-tests-passed.needs
|
||||
run: |
|
||||
tsc check-all-tests-passed-needs.ts
|
||||
node check-all-tests-passed-needs.js
|
||||
working-directory: .github/scripts
|
||||
- name: Make sure no changes from linters are detected
|
||||
run: |
|
||||
git diff --exit-code || (echo "::error::Please run 'npm run all' to fix the issues" && exit 1)
|
||||
|
||||
git diff --exit-code
|
||||
test-default-version:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, macos-14, windows-latest]
|
||||
os: [ubuntu-latest, macos-latest, macos-14]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install latest version
|
||||
id: setup-uv
|
||||
uses: ./
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
shell: bash
|
||||
- name: Check uv-path is set
|
||||
run: ${{ steps.setup-uv.outputs.uv-path }} --version
|
||||
- name: Check uvx-path is set
|
||||
run: ${{ steps.setup-uv.outputs.uvx-path }} --version
|
||||
|
||||
test-specific-version:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
@ -69,12 +48,8 @@ jobs:
|
||||
version: ${{ matrix.uv-version }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-semver-range:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, selfhosted-ubuntu-arm64 ]
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install version 0.3
|
||||
@ -83,85 +58,23 @@ jobs:
|
||||
with:
|
||||
version: "0.3"
|
||||
- name: Correct version gets installed
|
||||
run: |
|
||||
if [ "$(uv --version)" != "uv 0.3.5" ]; then
|
||||
echo "Wrong uv version: $(uv --version)"
|
||||
exit 1
|
||||
fi
|
||||
- name: Output has correct version
|
||||
run: |
|
||||
if [ "$UV_VERSION" != "0.3.5" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
UV_VERSION: ${{ steps.setup-uv.outputs.uv-version }}
|
||||
|
||||
test-pep440-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install version 0.4.30
|
||||
id: setup-uv
|
||||
uses: ./
|
||||
with:
|
||||
version: ">=0.4.25,<0.5"
|
||||
- name: Correct version gets installed
|
||||
run: |
|
||||
if [ "$(uv --version)" != "uv 0.4.30" ]; then
|
||||
echo "Wrong uv version: $(uv --version)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-pyproject-file-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install version 0.5.14
|
||||
id: setup-uv
|
||||
uses: ./
|
||||
with:
|
||||
working-directory: "__tests__/fixtures/pyproject-toml-project"
|
||||
- name: Correct version gets installed
|
||||
run: |
|
||||
if [ "$(uv --version)" != "uv 0.5.14" ]; then
|
||||
echo "Wrong uv version: $(uv --version)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-malformed-pyproject-file-fallback:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install using malformed pyproject.toml
|
||||
id: setup-uv
|
||||
uses: ./
|
||||
with:
|
||||
working-directory: "__tests__/fixtures/malformed-pyproject-toml-project"
|
||||
- run: uv --help
|
||||
|
||||
test-uv-file-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install version 0.5.15
|
||||
id: setup-uv
|
||||
uses: ./
|
||||
with:
|
||||
working-directory: "__tests__/fixtures/uv-toml-project"
|
||||
- name: Correct version gets installed
|
||||
run: |
|
||||
if [ "$(uv --version)" != "uv 0.5.15" ]; then
|
||||
echo "Wrong uv version: $(uv --version)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-checksum:
|
||||
runs-on: ${{ matrix.inputs.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
inputs:
|
||||
- os: ubuntu-latest
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
checksum:
|
||||
["4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd"]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
checksum: "4d9279ad5ca596b1e2d703901d508430eb07564dc4d8837de9e2fca9c90f8ecd"
|
||||
include:
|
||||
- os: macos-latest
|
||||
checksum: "a70cbfbf3bb5c08b2f84963b4f12c94e08fbb2468ba418a3bfe1066fbe9e7218"
|
||||
steps:
|
||||
@ -170,10 +83,9 @@ jobs:
|
||||
uses: ./
|
||||
with:
|
||||
version: "0.3.2"
|
||||
checksum: ${{ matrix.inputs.checksum }}
|
||||
checksum: ${{ matrix.checksum }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-with-explicit-token:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -184,7 +96,6 @@ jobs:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-uvx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -192,7 +103,6 @@ jobs:
|
||||
- name: Install default version
|
||||
uses: ./
|
||||
- run: uvx ruff --version
|
||||
|
||||
test-tool-install:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
@ -210,7 +120,6 @@ jobs:
|
||||
uses: ./
|
||||
- run: uv tool install ruff
|
||||
- run: ruff --version
|
||||
|
||||
test-tilde-expansion-tool-dirs:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
@ -230,9 +139,8 @@ jobs:
|
||||
echo "UV_TOOL_DIR does not contain /home/ubuntu/tool-dir: $UV_TOOL_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
test-python-version:
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
@ -249,23 +157,8 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-activate-environment:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ ubuntu-latest, macos-latest, windows-latest ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install latest version
|
||||
uses: ./
|
||||
with:
|
||||
python-version: 3.13.1t
|
||||
activate-environment: true
|
||||
- name: Verify packages can be installed
|
||||
run: uv pip install pip
|
||||
run: uv pip install --python=3.13.1t pip
|
||||
shell: bash
|
||||
- name: Verify python version is correct
|
||||
run: |
|
||||
@ -274,301 +167,3 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
test-musl:
|
||||
runs-on: ubuntu-latest
|
||||
container: alpine
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install latest version
|
||||
uses: ./
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-setup-cache:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
enable-cache: [ "true", "false", "auto" ]
|
||||
os: [ "ubuntu-latest", "selfhosted-ubuntu-arm64", "windows-latest" ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: ${{ matrix.enable-cache }}
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-${{ matrix.os }}-${{ matrix.enable-cache }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
shell: bash
|
||||
test-restore-cache:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
enable-cache: [ "true", "false", "auto" ]
|
||||
os: [ "ubuntu-latest", "selfhosted-ubuntu-arm64", "windows-latest" ]
|
||||
needs: test-setup-cache
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: ${{ matrix.enable-cache }}
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-${{ matrix.os }}-${{ matrix.enable-cache }}
|
||||
- name: Cache was hit
|
||||
if: ${{ matrix.enable-cache == 'true' || (matrix.enable-cache == 'auto' && matrix.os == 'ubuntu-latest') }}
|
||||
run: |
|
||||
if [ "$CACHE_HIT" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
shell: bash
|
||||
- name: Cache was not hit
|
||||
if: ${{ matrix.enable-cache == 'false' || (matrix.enable-cache == 'auto' && matrix.os == 'selfhosted-ubuntu-arm64') }}
|
||||
run: |
|
||||
if [ "$CACHE_HIT" == "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
shell: bash
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
shell: bash
|
||||
|
||||
test-setup-cache-requirements-txt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-requirements-txt
|
||||
- run: |
|
||||
uv venv
|
||||
uv pip install -r requirements.txt
|
||||
working-directory: __tests__/fixtures/requirements-txt-project
|
||||
test-restore-cache-requirements-txt:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-setup-cache
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-requirements-txt
|
||||
- name: Cache was hit
|
||||
run: |
|
||||
if [ "$CACHE_HIT" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- run: |
|
||||
uv venv
|
||||
uv pip install -r requirements.txt
|
||||
working-directory: __tests__/fixtures/requirements-txt-project
|
||||
|
||||
test-setup-cache-dependency-glob:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
__tests__/fixtures/uv-project/uv.lock
|
||||
**/pyproject.toml
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
test-restore-cache-dependency-glob:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test-setup-cache-dependency-glob
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Change pyproject.toml
|
||||
run: |
|
||||
echo '[tool.uv]' >> __tests__/fixtures/uv-project/pyproject.toml
|
||||
echo 'dev-dependencies = []' >> __tests__/fixtures/uv-project/pyproject.toml
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
__tests__/fixtures/uv-project/uv.lock
|
||||
**/pyproject.toml
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-dependency-glob
|
||||
ignore-nothing-to-cache: true
|
||||
- name: Cache was not hit
|
||||
run: |
|
||||
if [ "$CACHE_HIT" == "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
|
||||
test-cache-local:
|
||||
strategy:
|
||||
matrix:
|
||||
inputs:
|
||||
- os: ubuntu-latest
|
||||
expected-cache-dir: "/home/runner/work/_temp/setup-uv-cache"
|
||||
- os: windows-latest
|
||||
expected-cache-dir: "D:\\a\\_temp\\setup-uv-cache"
|
||||
- os: selfhosted-ubuntu-arm64
|
||||
expected-cache-dir: "/home/ubuntu/.cache/uv"
|
||||
runs-on: ${{ matrix.inputs.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-cache-local
|
||||
- run: |
|
||||
if [ "$UV_CACHE_DIR" != "${{ matrix.inputs.expected-cache-dir }}" ]; then
|
||||
echo "UV_CACHE_DIR is not set to the expected value: $UV_CACHE_DIR"
|
||||
exit 1
|
||||
fi
|
||||
shell: bash
|
||||
|
||||
test-setup-cache-local:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local
|
||||
cache-local-path: /tmp/uv-cache
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
test-restore-cache-local:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
needs: test-setup-cache-local
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Restore with cache
|
||||
id: restore
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: ${{ github.run_id }}-${{ github.run_attempt }}-test-setup-cache-local
|
||||
cache-local-path: /tmp/uv-cache
|
||||
- name: Cache was hit
|
||||
run: |
|
||||
if [ "$CACHE_HIT" != "true" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-tilde-expansion-cache-local-path:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Create cache directory
|
||||
run: mkdir -p ~/uv-cache
|
||||
shell: bash
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
cache-local-path: ~/uv-cache/cache-local-path
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
test-tilde-expansion-cache-dependency-glob:
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Create cache directory
|
||||
run: mkdir -p ~/uv-cache
|
||||
shell: bash
|
||||
- name: Create cache dependency glob file
|
||||
run: touch ~/uv-cache.glob
|
||||
shell: bash
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-local-path: ~/uv-cache/cache-dependency-glob
|
||||
cache-dependency-glob: "~/uv-cache.glob"
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/uv-project
|
||||
|
||||
cleanup-tilde-expansion-tests:
|
||||
needs:
|
||||
- test-tilde-expansion-cache-local-path
|
||||
- test-tilde-expansion-cache-dependency-glob
|
||||
if: always()
|
||||
runs-on: selfhosted-ubuntu-arm64
|
||||
steps:
|
||||
- name: Remove cache directory
|
||||
run: rm -rf ~/uv-cache
|
||||
shell: bash
|
||||
- name: Remove cache dependency glob file
|
||||
run: rm -f ~/uv-cache.glob
|
||||
shell: bash
|
||||
|
||||
test-no-python-version:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Fake pyproject.toml at root
|
||||
run: cp __tests__/fixtures/old-python-constraint-project/pyproject.toml pyproject.toml
|
||||
- name: Setup with cache
|
||||
uses: ./
|
||||
with:
|
||||
enable-cache: true
|
||||
- run: uv sync
|
||||
working-directory: __tests__/fixtures/old-python-constraint-project
|
||||
|
||||
all-tests-passed:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- lint
|
||||
- test-default-version
|
||||
- test-specific-version
|
||||
- test-semver-range
|
||||
- test-pep440-version
|
||||
- test-pyproject-file-version
|
||||
- test-malformed-pyproject-file-fallback
|
||||
- test-uv-file-version
|
||||
- test-checksum
|
||||
- test-with-explicit-token
|
||||
- test-uvx
|
||||
- test-tool-install
|
||||
- test-tilde-expansion-tool-dirs
|
||||
- test-python-version
|
||||
- test-activate-environment
|
||||
- test-musl
|
||||
- test-cache-local
|
||||
- test-setup-cache
|
||||
- test-restore-cache
|
||||
- test-setup-cache-requirements-txt
|
||||
- test-restore-cache-requirements-txt
|
||||
- test-setup-cache-dependency-glob
|
||||
- test-restore-cache-dependency-glob
|
||||
- test-setup-cache-local
|
||||
- test-restore-cache-local
|
||||
- test-tilde-expansion-cache-local-path
|
||||
- test-tilde-expansion-cache-dependency-glob
|
||||
- cleanup-tilde-expansion-tests
|
||||
- test-no-python-version
|
||||
if: always()
|
||||
steps:
|
||||
- name: All tests passed
|
||||
run: |
|
||||
echo "All jobs passed: ${{ !contains(needs.*.result, 'failure') }}"
|
||||
# shellcheck disable=SC2242
|
||||
exit ${{ contains(needs.*.result, 'failure') && 1 || 0 }}
|
||||
|
32
.github/workflows/update-known-checksums.yml
vendored
Normal file
32
.github/workflows/update-known-checksums.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
name: "Update known checksums"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
- name: Update known checksums
|
||||
id: update-known-checksums
|
||||
run:
|
||||
node dist/update-known-checksums/index.js
|
||||
src/download/checksum/known-checksums.ts ${{ secrets.GITHUB_TOKEN }}
|
||||
- run: npm install && npm run all
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
|
||||
with:
|
||||
commit-message: "chore: update known checksums"
|
||||
title:
|
||||
"chore: update known checksums for ${{
|
||||
steps.update-known-checksums.outputs.latest-version }}"
|
||||
body:
|
||||
"chore: update known checksums for ${{
|
||||
steps.update-known-checksums.outputs.latest-version }}"
|
||||
base: main
|
||||
labels: "automated-pr,update-known-checksums"
|
||||
branch: update-known-checksums-pr
|
||||
delete-branch: true
|
39
.github/workflows/update-known-versions.yml
vendored
39
.github/workflows/update-known-versions.yml
vendored
@ -1,39 +0,0 @@
|
||||
name: "Update known versions"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 4 * * *" # Run every day at 4am UTC
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
- name: Update known versions
|
||||
id: update-known-versions
|
||||
run:
|
||||
node dist/update-known-versions/index.js
|
||||
src/download/checksum/known-checksums.ts
|
||||
version-manifest.json
|
||||
${{ secrets.GITHUB_TOKEN }}
|
||||
- run: npm install && npm run all
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
|
||||
with:
|
||||
commit-message: "chore: update known versions"
|
||||
title:
|
||||
"chore: update known versions for ${{
|
||||
steps.update-known-versions.outputs.latest-version }}"
|
||||
body:
|
||||
"chore: update known versions for ${{
|
||||
steps.update-known-versions.outputs.latest-version }}"
|
||||
base: main
|
||||
labels: "automated-pr,update-known-versions"
|
||||
branch: update-known-versions-pr
|
||||
delete-branch: true
|
36
.github/workflows/update-major-minor-tags.yml
vendored
36
.github/workflows/update-major-minor-tags.yml
vendored
@ -1,6 +1,7 @@
|
||||
---
|
||||
name: Update Major Minor Tags
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
push:
|
||||
branches-ignore:
|
||||
@ -11,37 +12,8 @@ on:
|
||||
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
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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}"
|
||||
- name: Run Update semver
|
||||
uses: haya14busa/action-update-semver@v1.2.1
|
||||
|
201
README.md
201
README.md
@ -11,13 +11,10 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs
|
||||
## Contents
|
||||
|
||||
- [Usage](#usage)
|
||||
- [Install a required-version or latest (default)](#install-a-required-version-or-latest-default)
|
||||
- [Install the latest version](#install-the-latest-version)
|
||||
- [Install the latest version (default)](#install-the-latest-version-default)
|
||||
- [Install a specific version](#install-a-specific-version)
|
||||
- [Install a version by supplying a semver range or pep440 specifier](#install-a-version-by-supplying-a-semver-range-or-pep440-specifier)
|
||||
- [Install a version by supplying a semver range](#install-a-version-by-supplying-a-semver-range)
|
||||
- [Python version](#python-version)
|
||||
- [Activate environment](#activate-environment)
|
||||
- [Working directory](#working-directory)
|
||||
- [Validate checksum](#validate-checksum)
|
||||
- [Enable Caching](#enable-caching)
|
||||
- [Cache dependency glob](#cache-dependency-glob)
|
||||
@ -33,73 +30,59 @@ Set up your GitHub Actions workflow with a specific version of [uv](https://docs
|
||||
|
||||
## Usage
|
||||
|
||||
### Install a required-version or latest (default)
|
||||
### Install the latest version (default)
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
```
|
||||
|
||||
If you do not specify a version, this action will look for a [required-version](https://docs.astral.sh/uv/reference/settings/#required-version)
|
||||
in a `uv.toml` or `pyproject.toml` file in the repository root. If none is found, the latest version will be installed.
|
||||
|
||||
For an example workflow, see
|
||||
[here](https://github.com/charliermarsh/autobot/blob/e42c66659bf97b90ca9ff305a19cc99952d0d43f/.github/workflows/ci.yaml).
|
||||
|
||||
### Install the latest version
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
version: "latest"
|
||||
```
|
||||
|
||||
For an example workflow, see
|
||||
[here](https://github.com/charliermarsh/autobot/blob/e42c66659bf97b90ca9ff305a19cc99952d0d43f/.github/workflows/ci.yaml).
|
||||
|
||||
### Install a specific version
|
||||
|
||||
```yaml
|
||||
- name: Install a specific version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
version: "0.4.4"
|
||||
```
|
||||
|
||||
### Install a version by supplying a semver range or pep440 specifier
|
||||
### Install a version by supplying a semver range
|
||||
|
||||
You can specify a [semver range](https://github.com/npm/node-semver?tab=readme-ov-file#ranges)
|
||||
or [pep440 specifier](https://peps.python.org/pep-0440/#version-specifiers)
|
||||
to install the latest version that satisfies the range.
|
||||
|
||||
```yaml
|
||||
- name: Install a semver range of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
version: ">=0.4.0"
|
||||
```
|
||||
|
||||
```yaml
|
||||
- name: Pinning a minor version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
version: "0.4.x"
|
||||
```
|
||||
|
||||
```yaml
|
||||
- name: Install a pep440-specifier-satisfying version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
version: ">=0.4.25,<0.5"
|
||||
```
|
||||
|
||||
### Python version
|
||||
|
||||
You can use the input `python-version` to set the environment variable `UV_PYTHON` for the rest of your workflow
|
||||
You can use the input `python-version` to
|
||||
|
||||
- set the environment variable `UV_PYTHON` for the rest of your workflow
|
||||
- create a new virtual environment with the specified python version
|
||||
- activate the virtual environment for the rest of your workflow
|
||||
|
||||
This will override any python version specifications in `pyproject.toml` and `.python-version`
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv and set the python version to 3.13t
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
python-version: 3.13t
|
||||
- run: uv pip install --python=3.13t pip
|
||||
@ -117,51 +100,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install the latest version of uv and set the python version
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Test with python ${{ matrix.python-version }}
|
||||
run: uv run --frozen pytest
|
||||
```
|
||||
|
||||
### Activate environment
|
||||
|
||||
You can set `activate-environment` to `true` to automatically activate a venv.
|
||||
This allows directly using it in later steps:
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv and activate the environment
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
activate-environment: true
|
||||
- run: uv pip install pip
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> Activating the environment adds your dependencies to the `PATH`, which could break some workflows.
|
||||
> For example, if you have a dependency which requires uv, e.g., `hatch`, activating the
|
||||
> environment will shadow the `uv` binary installed by this action and may result in a different uv
|
||||
> version being used.
|
||||
>
|
||||
> We do not recommend using this setting for most use-cases. Instead, use `uv run` to execute
|
||||
> commands in the environment.
|
||||
|
||||
### Working directory
|
||||
|
||||
You can set the working directory with the `working-directory` input.
|
||||
This controls where we look for `pyproject.toml`, `uv.toml` and `.python-version` files
|
||||
which are used to determine the version of uv and python to install.
|
||||
|
||||
It also controls where [the venv gets created](#activate-environment).
|
||||
|
||||
```yaml
|
||||
- name: Install uv based on the config files in the working-directory
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
working-directory: my/subproject/dir
|
||||
```
|
||||
|
||||
### Validate checksum
|
||||
|
||||
You can specify a checksum to validate the downloaded executable. Checksums up to the default version
|
||||
@ -170,7 +115,7 @@ are automatically verified by this action. The sha256 hashes can be found on the
|
||||
|
||||
```yaml
|
||||
- name: Install a specific version and validate the checksum
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
version: "0.3.1"
|
||||
checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
|
||||
@ -180,7 +125,6 @@ are automatically verified by this action. The sha256 hashes can be found on the
|
||||
|
||||
If you enable caching, the [uv cache](https://docs.astral.sh/uv/concepts/cache/) will be uploaded to
|
||||
the GitHub Actions cache. This can speed up runs that reuse the cache by several minutes.
|
||||
Caching is enabled by default on GitHub-hosted runners.
|
||||
|
||||
> [!TIP]
|
||||
>
|
||||
@ -192,7 +136,7 @@ You can optionally define a custom cache key suffix.
|
||||
```yaml
|
||||
- name: Enable caching and define a custom cache key suffix
|
||||
id: setup-uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-suffix: "optional-suffix"
|
||||
@ -215,22 +159,16 @@ changes. If you use relative paths, they are relative to the repository root.
|
||||
|
||||
> [!NOTE]
|
||||
>
|
||||
> You can look up supported patterns [here](https://github.com/actions/toolkit/tree/main/packages/glob#patterns)
|
||||
>
|
||||
> The default is
|
||||
> ```yaml
|
||||
> cache-dependency-glob: |
|
||||
> **/*requirements*.txt
|
||||
> **/*requirements*.in
|
||||
> **/*constraints*.txt
|
||||
> **/*constraints*.in
|
||||
> **/pyproject.toml
|
||||
> **/requirements*.txt
|
||||
> **/uv.lock
|
||||
> ```
|
||||
|
||||
```yaml
|
||||
- name: Define a cache dependency glob
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "**/pyproject.toml"
|
||||
@ -238,7 +176,7 @@ changes. If you use relative paths, they are relative to the repository root.
|
||||
|
||||
```yaml
|
||||
- name: Define a list of cache dependency globs
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: |
|
||||
@ -248,7 +186,7 @@ changes. If you use relative paths, they are relative to the repository root.
|
||||
|
||||
```yaml
|
||||
- name: Define an absolute cache dependency glob
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: "/tmp/my-folder/requirements*.txt"
|
||||
@ -256,7 +194,7 @@ changes. If you use relative paths, they are relative to the repository root.
|
||||
|
||||
```yaml
|
||||
- name: Never invalidate the cache
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
cache-dependency-glob: ""
|
||||
@ -271,7 +209,7 @@ It defaults to `setup-uv-cache` in the `TMP` dir, `D:\a\_temp\uv-tool-dir` on Wi
|
||||
|
||||
```yaml
|
||||
- name: Define a custom uv cache path
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
cache-local-path: "/path/to/cache"
|
||||
```
|
||||
@ -290,7 +228,7 @@ input.
|
||||
|
||||
```yaml
|
||||
- name: Don't prune the cache before saving it
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
prune-cache: false
|
||||
@ -303,26 +241,12 @@ If you want to ignore this, set the `ignore-nothing-to-cache` input to `true`.
|
||||
|
||||
```yaml
|
||||
- name: Ignore nothing to cache
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
ignore-nothing-to-cache: true
|
||||
```
|
||||
|
||||
### Ignore empty workdir
|
||||
|
||||
By default, the action will warn if the workdir is empty, because this is usually the case when
|
||||
`actions/checkout` is configured to run after `setup-uv`, which is not supported.
|
||||
|
||||
If you want to ignore this, set the `ignore-empty-workdir` input to `true`.
|
||||
|
||||
```yaml
|
||||
- name: Ignore empty workdir
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
ignore-empty-workdir: true
|
||||
```
|
||||
|
||||
### GitHub authentication token
|
||||
|
||||
This action uses the GitHub API to fetch the uv release artifacts. To avoid hitting the GitHub API
|
||||
@ -335,7 +259,7 @@ are not sufficient, you can provide a custom GitHub token with the necessary per
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv with a custom GitHub token
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
github-token: ${{ secrets.CUSTOM_GITHUB_TOKEN }}
|
||||
```
|
||||
@ -353,7 +277,7 @@ input:
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv with a custom tool dir
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
tool-dir: "/path/to/tool/dir"
|
||||
```
|
||||
@ -372,7 +296,7 @@ If you want to change this behaviour (especially on self-hosted runners) you can
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv with a custom tool bin dir
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
tool-bin-dir: "/path/to/tool-bin/dir"
|
||||
```
|
||||
@ -388,7 +312,7 @@ This action supports expanding the `~` character to the user's home directory fo
|
||||
|
||||
```yaml
|
||||
- name: Expand the tilde character
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
cache-local-path: "~/path/to/cache"
|
||||
tool-dir: "~/path/to/tool/dir"
|
||||
@ -403,29 +327,28 @@ This action downloads uv from the uv repo's official
|
||||
[GitHub Actions Toolkit](https://github.com/actions/toolkit) to cache it as a tool to speed up
|
||||
consecutive runs on self-hosted runners.
|
||||
|
||||
The installed version of uv is then added to the runner PATH, enabling later steps to invoke it
|
||||
The installed version of uv is then added to the runner PATH, enabling subsequent steps to invoke it
|
||||
by name (`uv`).
|
||||
|
||||
## FAQ
|
||||
|
||||
### Do I still need `actions/setup-python` alongside `setup-uv`?
|
||||
|
||||
With `setup-uv`, you can install a specific version of Python using `uv python install` rather than
|
||||
No. This action is modelled as a drop-in replacement for `actions/setup-python` when using uv. With
|
||||
`setup-uv`, you can install a specific version of Python using `uv python install` rather than
|
||||
relying on `actions/setup-python`.
|
||||
|
||||
Using `actions/setup-python` can be faster, because GitHub caches the Python versions alongside the runner.
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@main
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Test
|
||||
run: uv run --frozen pytest # Uses the Python version automatically installed by uv
|
||||
run: uv run --frozen pytest
|
||||
```
|
||||
|
||||
To install a specific version of Python, use
|
||||
@ -433,7 +356,7 @@ To install a specific version of Python, use
|
||||
|
||||
```yaml
|
||||
- name: Install the latest version of uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Install Python 3.12
|
||||
@ -452,57 +375,11 @@ output:
|
||||
uses: actions/checkout@main
|
||||
- name: Install the default version of uv
|
||||
id: setup-uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
uses: astral-sh/setup-uv@v4
|
||||
- name: Print the installed version
|
||||
run: echo "Installed uv version is ${{ steps.setup-uv.outputs.uv-version }}"
|
||||
```
|
||||
|
||||
### Should I include the resolution strategy in the cache key?
|
||||
|
||||
**Yes!**
|
||||
|
||||
The cache key gets computed by using the [cache-dependency-glob](#cache-dependency-glob).
|
||||
|
||||
If you
|
||||
have jobs which use the same dependency definitions from `requirements.txt` or
|
||||
`pyproject.toml` but different
|
||||
[resolution strategies](https://docs.astral.sh/uv/concepts/resolution/#resolution-strategy),
|
||||
each job will have different dependencies or dependency versions.
|
||||
But if you do not add the resolution strategy as a [cache-suffix](#enable-caching),
|
||||
they will have the same cache key.
|
||||
|
||||
This means the first job which starts uploading its cache will win and all other job will fail
|
||||
uploading the cache,
|
||||
because they try to upload with the same cache key.
|
||||
|
||||
You might see errors like
|
||||
`Failed to save: Failed to CreateCacheEntry: Received non-retryable error: Failed request: (409) Conflict: cache entry with the same key, version, and scope already exists`
|
||||
|
||||
### Why do I see warnings like `No GitHub Actions cache found for key`
|
||||
|
||||
When a workflow runs for the first time on a branch and has a new cache key, because the
|
||||
[cache-dependency-glob](#cache-dependency-glob) found changed files (changed dependencies),
|
||||
the cache will not be found and the warning `No GitHub Actions cache found for key` will be printed.
|
||||
|
||||
While this might be irritating at first, it is expected behaviour and the cache will be created
|
||||
and reused in later workflows.
|
||||
|
||||
The reason for the warning is, that we have to way to know if this is the first run of a new
|
||||
cache key or the user accidentally misconfigured the [cache-dependency-glob](#cache-dependency-glob)
|
||||
or [cache-suffix](#enable-caching) and the cache never gets used.
|
||||
|
||||
### Do I have to run `actions/checkout` before or after `setup-uv`?
|
||||
|
||||
Some workflows need uv but do not need to access the repository content.
|
||||
|
||||
But **if** you need to access the repository content, you have run `actions/checkout` before running `setup-uv`.
|
||||
Running `actions/checkout` after `setup-uv` **is not supported**.
|
||||
|
||||
### Does `setup-uv` also install my project or its dependencies automatically?
|
||||
|
||||
No, `setup-uv` alone wont install any libraries from your `pyproject.toml` or `requirements.txt`, it only sets up `uv`.
|
||||
You should run `uv sync` or `uv pip install .` separately, or use `uv run ...` to ensure necessary dependencies are installed.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
`setup-uv` was initially written and published by [Kevin Stillhammer](https://github.com/eifinger)
|
||||
|
@ -1 +0,0 @@
|
||||
3.11
|
@ -1,6 +0,0 @@
|
||||
def main():
|
||||
print("Hello from malformed-pyproject-toml-project!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,9 +0,0 @@
|
||||
[project]
|
||||
name = "malformed-pyproject-toml-project"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = []
|
||||
|
||||
[malformed-toml
|
@ -1 +0,0 @@
|
||||
3.11
|
@ -1,6 +0,0 @@
|
||||
def main():
|
||||
print("Hello from pyproject-toml-project!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,19 +0,0 @@
|
||||
[project]
|
||||
name = "pyproject-toml-project"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = []
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"reuse==5.0.2",
|
||||
{include-group = "lint"},
|
||||
]
|
||||
lint = [
|
||||
"flake8==4.0.1",
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
required-version = "==0.5.14"
|
@ -1 +0,0 @@
|
||||
3.11
|
@ -1,6 +0,0 @@
|
||||
def main():
|
||||
print("Hello from uv-toml-project!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,10 +0,0 @@
|
||||
[project]
|
||||
name = "uv-toml-project"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = []
|
||||
|
||||
[tool.uv]
|
||||
required-version = "==0.5.14"
|
@ -1 +0,0 @@
|
||||
required-version = "==0.5.15"
|
29
action.yml
29
action.yml
@ -4,43 +4,29 @@ description:
|
||||
author: "astral-sh"
|
||||
inputs:
|
||||
version:
|
||||
description: "The version of uv to install e.g., `0.5.0` Defaults to the version in pyproject.toml or 'latest'."
|
||||
default: ""
|
||||
description: "The version of uv to install"
|
||||
default: "latest"
|
||||
python-version:
|
||||
description: "The version of Python to set UV_PYTHON to"
|
||||
required: false
|
||||
activate-environment:
|
||||
description: "Use uv venv to activate a venv ready to be used by later steps. "
|
||||
default: "false"
|
||||
working-directory:
|
||||
description: "The directory to execute all commands in and look for files such as pyproject.toml"
|
||||
default: ${{ github.workspace }}
|
||||
checksum:
|
||||
description: "The checksum of the uv version to install"
|
||||
required: false
|
||||
server-url:
|
||||
description: "The server url to use when downloading uv"
|
||||
required: false
|
||||
default: "https://github.com"
|
||||
github-token:
|
||||
description:
|
||||
"Used to increase the rate limit when retrieving versions and downloading uv."
|
||||
required: false
|
||||
default: ${{ github.token }}
|
||||
enable-cache:
|
||||
description: "Enable uploading of the uv cache"
|
||||
description: "Enable caching of the uv cache"
|
||||
default: "auto"
|
||||
cache-dependency-glob:
|
||||
description:
|
||||
"Glob pattern to match files relative to the repository root to control
|
||||
the cache."
|
||||
default: |
|
||||
**/*requirements*.txt
|
||||
**/*requirements*.in
|
||||
**/*constraints*.txt
|
||||
**/*constraints*.in
|
||||
**/pyproject.toml
|
||||
**/uv.lock
|
||||
**/requirements*.txt
|
||||
cache-suffix:
|
||||
description: "Suffix for the cache key"
|
||||
required: false
|
||||
@ -53,9 +39,6 @@ inputs:
|
||||
ignore-nothing-to-cache:
|
||||
description: "Ignore when nothing is found to cache."
|
||||
default: "false"
|
||||
ignore-empty-workdir:
|
||||
description: "Ignore when the working directory is empty."
|
||||
default: "false"
|
||||
tool-dir:
|
||||
description: "Custom path to set UV_TOOL_DIR to."
|
||||
required: false
|
||||
@ -65,10 +48,6 @@ inputs:
|
||||
outputs:
|
||||
uv-version:
|
||||
description: "The installed uv version. Useful when using latest."
|
||||
uv-path:
|
||||
description: "The path to the installed uv binary."
|
||||
uvx-path:
|
||||
description: "The path to the installed uvx binary."
|
||||
cache-hit:
|
||||
description: "A boolean value to indicate a cache entry was found"
|
||||
runs:
|
||||
|
47807
dist/save-cache/index.js
generated
vendored
47807
dist/save-cache/index.js
generated
vendored
File diff suppressed because one or more lines are too long
71146
dist/setup/index.js
generated
vendored
71146
dist/setup/index.js
generated
vendored
File diff suppressed because one or more lines are too long
47786
dist/update-known-versions/index.js → dist/update-known-checksums/index.js
generated
vendored
47786
dist/update-known-versions/index.js → dist/update-known-checksums/index.js
generated
vendored
File diff suppressed because one or more lines are too long
1593
package-lock.json
generated
1593
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
25
package.json
25
package.json
@ -9,10 +9,10 @@
|
||||
"format": "biome format --fix",
|
||||
"format-check": "biome format",
|
||||
"lint": "biome lint --fix",
|
||||
"package": "ncc build -o dist/setup src/setup-uv.ts && ncc build -o dist/save-cache src/save-cache.ts && ncc build -o dist/update-known-versions src/update-known-versions.ts",
|
||||
"package": "ncc build -o dist/setup src/setup-uv.ts && ncc build -o dist/save-cache src/save-cache.ts && ncc build -o dist/update-known-checksums src/update-known-checksums.ts",
|
||||
"test": "jest",
|
||||
"act": "act pull_request -W .github/workflows/test.yml --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(gh auth token)\"",
|
||||
"update-known-versions": "RUNNER_TEMP=known_versions node dist/update-known-versions/index.js src/download/checksum/known-versions.ts \"$(gh auth token)\"",
|
||||
"update-known-checksums": "RUNNER_TEMP=known_checksums node dist/update-known-checksums/index.js src/download/checksum/known-checksums.ts \"$(gh auth token)\"",
|
||||
"all": "npm run build && npm run format && npm run lint && npm run package && npm test"
|
||||
},
|
||||
"repository": {
|
||||
@ -23,28 +23,23 @@
|
||||
"author": "@eifinger",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^4.0.3",
|
||||
"@actions/cache": "^4.0.0",
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@actions/io": "^1.1.3",
|
||||
"@actions/tool-cache": "^2.0.2",
|
||||
"@octokit/core": "^7.0.2",
|
||||
"@octokit/plugin-paginate-rest": "^12.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^14.0.0",
|
||||
"@renovatebot/pep440": "^4.1.0",
|
||||
"smol-toml": "^1.3.4",
|
||||
"undici": "^7.10.0"
|
||||
"@actions/tool-cache": "^2.0.1",
|
||||
"@octokit/rest": "^21.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "1.9.4",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
"@types/node": "^22.15.21",
|
||||
"@types/semver": "^7.7.0",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"jest": "^29.7.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"ts-jest": "^29.3.2",
|
||||
"typescript": "^5.8.3"
|
||||
"ts-jest": "^29.2.5",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
|
23
src/cache/restore-cache.ts
vendored
23
src/cache/restore-cache.ts
vendored
@ -4,9 +4,7 @@ import {
|
||||
cacheDependencyGlob,
|
||||
cacheLocalPath,
|
||||
cacheSuffix,
|
||||
pruneCache,
|
||||
pythonVersion as pythonVersionInput,
|
||||
workingDirectory,
|
||||
} from "../utils/inputs";
|
||||
import { getArch, getPlatform } from "../utils/platforms";
|
||||
import { hashFiles } from "../hash/hash-files";
|
||||
@ -16,8 +14,8 @@ export const STATE_CACHE_KEY = "cache-key";
|
||||
export const STATE_CACHE_MATCHED_KEY = "cache-matched-key";
|
||||
const CACHE_VERSION = "1";
|
||||
|
||||
export async function restoreCache(): Promise<void> {
|
||||
const cacheKey = await computeKeys();
|
||||
export async function restoreCache(version: string): Promise<void> {
|
||||
const cacheKey = await computeKeys(version);
|
||||
|
||||
let matchedKey: string | undefined;
|
||||
core.info(
|
||||
@ -37,7 +35,7 @@ export async function restoreCache(): Promise<void> {
|
||||
handleMatchResult(matchedKey, cacheKey);
|
||||
}
|
||||
|
||||
async function computeKeys(): Promise<string> {
|
||||
async function computeKeys(version: string): Promise<string> {
|
||||
let cacheDependencyPathHash = "-";
|
||||
if (cacheDependencyGlob !== "") {
|
||||
core.info(
|
||||
@ -45,19 +43,16 @@ async function computeKeys(): Promise<string> {
|
||||
);
|
||||
cacheDependencyPathHash += await hashFiles(cacheDependencyGlob, true);
|
||||
if (cacheDependencyPathHash === "-") {
|
||||
core.warning(
|
||||
`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.`,
|
||||
throw new Error(
|
||||
`No file matched to [${cacheDependencyGlob.split("\n").join(",")}], make sure you have checked out the target repository and configured the cache-dependency-glob input correctly.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (cacheDependencyPathHash === "-") {
|
||||
cacheDependencyPathHash = "-no-dependency-glob";
|
||||
} else {
|
||||
cacheDependencyPathHash += "no-dependency-glob";
|
||||
}
|
||||
const suffix = cacheSuffix ? `-${cacheSuffix}` : "";
|
||||
const pythonVersion = await getPythonVersion();
|
||||
const platform = await getPlatform();
|
||||
const pruned = pruneCache ? "-pruned" : "";
|
||||
return `setup-uv-${CACHE_VERSION}-${getArch()}-${platform}-${pythonVersion}${pruned}${cacheDependencyPathHash}${suffix}`;
|
||||
return `setup-uv-${CACHE_VERSION}-${getArch()}-${getPlatform()}-${version}-${pythonVersion}${cacheDependencyPathHash}${suffix}`;
|
||||
}
|
||||
|
||||
async function getPythonVersion(): Promise<string> {
|
||||
@ -76,7 +71,7 @@ async function getPythonVersion(): Promise<string> {
|
||||
};
|
||||
|
||||
try {
|
||||
const execArgs = ["python", "find", "--directory", workingDirectory];
|
||||
const execArgs = ["python", "find"];
|
||||
await exec.exec("uv", execArgs, options);
|
||||
const pythonPath = output.trim();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,12 +1,16 @@
|
||||
import * as core from "@actions/core";
|
||||
import * as tc from "@actions/tool-cache";
|
||||
import * as path from "node:path";
|
||||
import * as pep440 from "@renovatebot/pep440";
|
||||
import { promises as fs } from "node:fs";
|
||||
import { OWNER, REPO, TOOL_CACHE_NAME } from "../utils/constants";
|
||||
import {
|
||||
GITHUB_COM_API,
|
||||
OWNER,
|
||||
REPO,
|
||||
TOOL_CACHE_NAME,
|
||||
} from "../utils/constants";
|
||||
import type { Architecture, Platform } from "../utils/platforms";
|
||||
import { validateChecksum } from "./checksum/checksum";
|
||||
import { Octokit } from "../utils/octokit";
|
||||
import * as github from "@actions/github";
|
||||
|
||||
export function tryGetFromToolCache(
|
||||
arch: Architecture,
|
||||
@ -24,7 +28,6 @@ export function tryGetFromToolCache(
|
||||
}
|
||||
|
||||
export async function downloadVersion(
|
||||
serverUrl: string,
|
||||
platform: Platform,
|
||||
arch: Architecture,
|
||||
version: string,
|
||||
@ -37,7 +40,7 @@ export async function downloadVersion(
|
||||
if (platform === "pc-windows-msvc") {
|
||||
extension = ".zip";
|
||||
}
|
||||
const downloadUrl = `${serverUrl}/${OWNER}/${REPO}/releases/download/${resolvedVersion}/${artifact}${extension}`;
|
||||
const downloadUrl = `https://github.com/${OWNER}/${REPO}/releases/download/${resolvedVersion}/${artifact}${extension}`;
|
||||
core.info(`Downloading uv from "${downloadUrl}" ...`);
|
||||
|
||||
const downloadPath = await tc.downloadTool(
|
||||
@ -76,7 +79,6 @@ export async function resolveVersion(
|
||||
versionInput: string,
|
||||
githubToken: string,
|
||||
): Promise<string> {
|
||||
core.debug(`Resolving version: ${versionInput}`);
|
||||
const version =
|
||||
versionInput === "latest"
|
||||
? await getLatestVersion(githubToken)
|
||||
@ -86,35 +88,16 @@ export async function resolveVersion(
|
||||
return version;
|
||||
}
|
||||
const availableVersions = await getAvailableVersions(githubToken);
|
||||
core.debug(`Available versions: ${availableVersions}`);
|
||||
const resolvedVersion = maxSatisfying(availableVersions, version);
|
||||
if (resolvedVersion === undefined) {
|
||||
const resolvedVersion = tc.evaluateVersions(availableVersions, version);
|
||||
if (resolvedVersion === "") {
|
||||
throw new Error(`No version found for ${version}`);
|
||||
}
|
||||
return resolvedVersion;
|
||||
}
|
||||
|
||||
async function getAvailableVersions(githubToken: string): Promise<string[]> {
|
||||
try {
|
||||
const octokit = new Octokit({
|
||||
auth: githubToken,
|
||||
});
|
||||
return await getReleaseTagNames(octokit);
|
||||
} catch (err) {
|
||||
if ((err as Error).message.includes("Bad credentials")) {
|
||||
core.info(
|
||||
"No (valid) GitHub token provided. Falling back to anonymous. Requests might be rate limited.",
|
||||
);
|
||||
const octokit = new Octokit();
|
||||
return await getReleaseTagNames(octokit);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
const octokit = github.getOctokit(githubToken, { baseUrl: GITHUB_COM_API });
|
||||
|
||||
async function getReleaseTagNames(
|
||||
octokit: InstanceType<typeof Octokit>,
|
||||
): Promise<string[]> {
|
||||
const response = await octokit.paginate(octokit.rest.repos.listReleases, {
|
||||
owner: OWNER,
|
||||
repo: REPO,
|
||||
@ -123,55 +106,15 @@ async function getReleaseTagNames(
|
||||
}
|
||||
|
||||
async function getLatestVersion(githubToken: string) {
|
||||
core.debug("Getting latest version...");
|
||||
const octokit = new Octokit({
|
||||
auth: githubToken,
|
||||
});
|
||||
const octokit = github.getOctokit(githubToken, { baseUrl: GITHUB_COM_API });
|
||||
|
||||
let latestRelease: { tag_name: string } | undefined;
|
||||
try {
|
||||
latestRelease = await getLatestRelease(octokit);
|
||||
} catch (err) {
|
||||
core.info(
|
||||
"No (valid) GitHub token provided. Falling back to anonymous. Requests might be rate limited.",
|
||||
);
|
||||
if (err instanceof Error) {
|
||||
core.debug(err.message);
|
||||
}
|
||||
const octokit = new Octokit();
|
||||
latestRelease = await getLatestRelease(octokit);
|
||||
}
|
||||
|
||||
if (!latestRelease) {
|
||||
throw new Error("Could not determine latest release.");
|
||||
}
|
||||
core.debug(`Latest version: ${latestRelease.tag_name}`);
|
||||
return latestRelease.tag_name;
|
||||
}
|
||||
|
||||
async function getLatestRelease(octokit: InstanceType<typeof Octokit>) {
|
||||
const { data: latestRelease } = await octokit.rest.repos.getLatestRelease({
|
||||
owner: OWNER,
|
||||
repo: REPO,
|
||||
});
|
||||
return latestRelease;
|
||||
}
|
||||
|
||||
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;
|
||||
if (!latestRelease) {
|
||||
throw new Error("Could not determine latest release.");
|
||||
}
|
||||
const maxPep440 = pep440.maxSatisfying(versions, version);
|
||||
if (maxPep440 !== null) {
|
||||
core.debug(
|
||||
`Found a version that satisfies the pep440 specifier: ${maxPep440}`,
|
||||
);
|
||||
return maxPep440;
|
||||
}
|
||||
return undefined;
|
||||
return latestRelease.tag_name;
|
||||
}
|
||||
|
@ -1,52 +0,0 @@
|
||||
import { promises as fs } from "node:fs";
|
||||
import * as core from "@actions/core";
|
||||
import * as semver from "semver";
|
||||
|
||||
interface VersionManifestEntry {
|
||||
version: string;
|
||||
artifactName: string;
|
||||
arch: string;
|
||||
platform: string;
|
||||
downloadUrl: string;
|
||||
}
|
||||
|
||||
export async function getLatestKnownVersion(
|
||||
versionManifestFile: string,
|
||||
): Promise<string> {
|
||||
const data = await fs.readFile(versionManifestFile);
|
||||
const versionManifestEntries: VersionManifestEntry[] = JSON.parse(
|
||||
data.toString(),
|
||||
);
|
||||
return versionManifestEntries.reduce((a, b) =>
|
||||
semver.gt(a.version, b.version) ? a : b,
|
||||
).version;
|
||||
}
|
||||
|
||||
export async function updateVersionManifest(
|
||||
versionManifestFile: string,
|
||||
downloadUrls: string[],
|
||||
): Promise<void> {
|
||||
const versionManifest: VersionManifestEntry[] = [];
|
||||
|
||||
for (const downloadUrl of downloadUrls) {
|
||||
const urlParts = downloadUrl.split("/");
|
||||
const version = urlParts[urlParts.length - 2];
|
||||
const artifactName = urlParts[urlParts.length - 1];
|
||||
if (!artifactName.startsWith("uv-")) {
|
||||
continue;
|
||||
}
|
||||
if (artifactName.startsWith("uv-installer")) {
|
||||
continue;
|
||||
}
|
||||
const artifactParts = artifactName.split(".")[0].split("-");
|
||||
versionManifest.push({
|
||||
version: version,
|
||||
artifactName: artifactName,
|
||||
arch: artifactParts[1],
|
||||
platform: artifactName.split(`uv-${artifactParts[1]}-`)[1].split(".")[0],
|
||||
downloadUrl: downloadUrl,
|
||||
});
|
||||
}
|
||||
core.debug(`Updating version manifest: ${JSON.stringify(versionManifest)}`);
|
||||
await fs.writeFile(versionManifestFile, JSON.stringify(versionManifest));
|
||||
}
|
@ -14,26 +14,19 @@ import {
|
||||
type Platform,
|
||||
} from "./utils/platforms";
|
||||
import {
|
||||
activateEnvironment as activateEnvironmentInput,
|
||||
cacheLocalPath,
|
||||
checkSum,
|
||||
ignoreEmptyWorkdir,
|
||||
enableCache,
|
||||
githubToken,
|
||||
pythonVersion,
|
||||
toolBinDir,
|
||||
toolDir,
|
||||
version as versionInput,
|
||||
workingDirectory,
|
||||
serverUrl,
|
||||
version,
|
||||
} from "./utils/inputs";
|
||||
import * as exec from "@actions/exec";
|
||||
import fs from "node:fs";
|
||||
import { getUvVersionFromConfigFile } from "./utils/config-file";
|
||||
|
||||
async function run(): Promise<void> {
|
||||
detectEmptyWorkdir();
|
||||
const platform = await getPlatform();
|
||||
const platform = getPlatform();
|
||||
const arch = getArch();
|
||||
|
||||
try {
|
||||
@ -43,13 +36,18 @@ async function run(): Promise<void> {
|
||||
if (arch === undefined) {
|
||||
throw new Error(`Unsupported architecture: ${process.arch}`);
|
||||
}
|
||||
const setupResult = await setupUv(platform, arch, checkSum, githubToken);
|
||||
const setupResult = await setupUv(
|
||||
platform,
|
||||
arch,
|
||||
version,
|
||||
checkSum,
|
||||
githubToken,
|
||||
);
|
||||
|
||||
addUvToPath(setupResult.uvDir);
|
||||
addToolBinToPath();
|
||||
addUvToPathAndOutput(setupResult.uvDir);
|
||||
setToolDir();
|
||||
setupPython();
|
||||
await activateEnvironment();
|
||||
await setupPython();
|
||||
addMatchers();
|
||||
setCacheDir(cacheLocalPath);
|
||||
|
||||
@ -57,7 +55,7 @@ async function run(): Promise<void> {
|
||||
core.info(`Successfully installed uv version ${setupResult.version}`);
|
||||
|
||||
if (enableCache) {
|
||||
await restoreCache();
|
||||
await restoreCache(setupResult.version);
|
||||
}
|
||||
process.exit(0);
|
||||
} catch (err) {
|
||||
@ -65,27 +63,14 @@ async function run(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
function detectEmptyWorkdir(): void {
|
||||
if (fs.readdirSync(".").length === 0) {
|
||||
if (ignoreEmptyWorkdir) {
|
||||
core.info(
|
||||
"Empty workdir detected. Ignoring because ignore-empty-workdir is enabled",
|
||||
);
|
||||
} else {
|
||||
core.warning(
|
||||
"Empty workdir detected. This may cause unexpected behavior. You can enable ignore-empty-workdir to mute this warning.",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function setupUv(
|
||||
platform: Platform,
|
||||
arch: Architecture,
|
||||
versionInput: string,
|
||||
checkSum: string | undefined,
|
||||
githubToken: string,
|
||||
): Promise<{ uvDir: string; version: string }> {
|
||||
const resolvedVersion = await determineVersion();
|
||||
const resolvedVersion = await resolveVersion(versionInput, githubToken);
|
||||
const toolCacheResult = tryGetFromToolCache(arch, resolvedVersion);
|
||||
if (toolCacheResult.installedPath) {
|
||||
core.info(`Found uv in tool-cache for ${toolCacheResult.version}`);
|
||||
@ -96,7 +81,6 @@ async function setupUv(
|
||||
}
|
||||
|
||||
const downloadVersionResult = await downloadVersion(
|
||||
serverUrl,
|
||||
platform,
|
||||
arch,
|
||||
resolvedVersion,
|
||||
@ -110,30 +94,7 @@ async function setupUv(
|
||||
};
|
||||
}
|
||||
|
||||
async function determineVersion(): Promise<string> {
|
||||
if (versionInput !== "") {
|
||||
return await resolveVersion(versionInput, githubToken);
|
||||
}
|
||||
const versionFromUvToml = getUvVersionFromConfigFile(
|
||||
`${workingDirectory}${path.sep}uv.toml`,
|
||||
);
|
||||
const versionFromPyproject = getUvVersionFromConfigFile(
|
||||
`${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",
|
||||
githubToken,
|
||||
);
|
||||
}
|
||||
|
||||
function addUvToPathAndOutput(cachedPath: string): void {
|
||||
core.setOutput("uv-path", `${cachedPath}${path.sep}uv`);
|
||||
core.setOutput("uvx-path", `${cachedPath}${path.sep}uvx`);
|
||||
function addUvToPath(cachedPath: string): void {
|
||||
core.addPath(cachedPath);
|
||||
core.info(`Added ${cachedPath} to the path`);
|
||||
}
|
||||
@ -165,29 +126,24 @@ function setToolDir(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function setupPython(): void {
|
||||
async function setupPython(): Promise<void> {
|
||||
if (pythonVersion !== "") {
|
||||
core.exportVariable("UV_PYTHON", pythonVersion);
|
||||
core.info(`Set UV_PYTHON to ${pythonVersion}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function activateEnvironment(): Promise<void> {
|
||||
if (activateEnvironmentInput) {
|
||||
const execArgs = ["venv", ".venv", "--directory", workingDirectory];
|
||||
const options: exec.ExecOptions = {
|
||||
silent: !core.isDebug(),
|
||||
};
|
||||
const execArgs = ["venv", "--python", pythonVersion];
|
||||
|
||||
core.info("Activating python venv...");
|
||||
await exec.exec("uv", execArgs);
|
||||
await exec.exec("uv", execArgs, options);
|
||||
|
||||
let venvBinPath = `${workingDirectory}${path.sep}.venv${path.sep}bin`;
|
||||
let venvBinPath = ".venv/bin";
|
||||
if (process.platform === "win32") {
|
||||
venvBinPath = `${workingDirectory}${path.sep}.venv${path.sep}Scripts`;
|
||||
venvBinPath = ".venv/Scripts";
|
||||
}
|
||||
core.addPath(path.resolve(venvBinPath));
|
||||
core.exportVariable(
|
||||
"VIRTUAL_ENV",
|
||||
path.resolve(`${workingDirectory}${path.sep}.venv`),
|
||||
);
|
||||
core.addPath(venvBinPath);
|
||||
core.exportVariable("VIRTUAL_ENV", venvBinPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
32
src/update-known-checksums.ts
Normal file
32
src/update-known-checksums.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import * as github from "@actions/github";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { GITHUB_COM_API, OWNER, REPO } from "./utils/constants";
|
||||
import * as semver from "semver";
|
||||
|
||||
import { updateChecksums } from "./download/checksum/update-known-checksums";
|
||||
|
||||
async function run(): Promise<void> {
|
||||
const checksumFilePath = process.argv.slice(2)[0];
|
||||
const github_token = process.argv.slice(2)[1];
|
||||
|
||||
const octokit = github.getOctokit(github_token, { baseUrl: GITHUB_COM_API });
|
||||
|
||||
const response = await octokit.paginate(octokit.rest.repos.listReleases, {
|
||||
owner: OWNER,
|
||||
repo: REPO,
|
||||
});
|
||||
const downloadUrls: string[] = response.flatMap((release) =>
|
||||
release.assets
|
||||
.filter((asset) => asset.name.endsWith(".sha256"))
|
||||
.map((asset) => asset.browser_download_url),
|
||||
);
|
||||
await updateChecksums(checksumFilePath, downloadUrls);
|
||||
|
||||
const latestVersion = response
|
||||
.map((release) => release.tag_name)
|
||||
.sort(semver.rcompare)[0];
|
||||
core.setOutput("latest-version", latestVersion);
|
||||
}
|
||||
|
||||
run();
|
@ -1,60 +0,0 @@
|
||||
import * as semver from "semver";
|
||||
import * as core from "@actions/core";
|
||||
import { Octokit } from "./utils/octokit";
|
||||
|
||||
import { OWNER, REPO } from "./utils/constants";
|
||||
|
||||
import { updateChecksums } from "./download/checksum/update-known-checksums";
|
||||
import {
|
||||
updateVersionManifest,
|
||||
getLatestKnownVersion,
|
||||
} from "./download/version-manifest";
|
||||
|
||||
async function run(): Promise<void> {
|
||||
const checksumFilePath = process.argv.slice(2)[0];
|
||||
const versionsManifestFilePath = process.argv.slice(2)[1];
|
||||
const githubToken = process.argv.slice(2)[2];
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: githubToken,
|
||||
});
|
||||
|
||||
const { data: latestRelease } = await octokit.rest.repos.getLatestRelease({
|
||||
owner: OWNER,
|
||||
repo: REPO,
|
||||
});
|
||||
|
||||
const latestKnownVersion = await getLatestKnownVersion(
|
||||
versionsManifestFilePath,
|
||||
);
|
||||
|
||||
if (semver.lte(latestRelease.tag_name, latestKnownVersion)) {
|
||||
core.info(
|
||||
`Latest release (${latestRelease.tag_name}) is not newer than the latest known version (${latestKnownVersion}). Skipping update.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const releases = await octokit.paginate(octokit.rest.repos.listReleases, {
|
||||
owner: OWNER,
|
||||
repo: REPO,
|
||||
});
|
||||
const checksumDownloadUrls: string[] = releases.flatMap((release) =>
|
||||
release.assets
|
||||
.filter((asset) => asset.name.endsWith(".sha256"))
|
||||
.map((asset) => asset.browser_download_url),
|
||||
);
|
||||
await updateChecksums(checksumFilePath, checksumDownloadUrls);
|
||||
|
||||
const artifactDownloadUrls: string[] = releases.flatMap((release) =>
|
||||
release.assets
|
||||
.filter((asset) => !asset.name.endsWith(".sha256"))
|
||||
.map((asset) => asset.browser_download_url),
|
||||
);
|
||||
|
||||
await updateVersionManifest(versionsManifestFilePath, artifactDownloadUrls);
|
||||
|
||||
core.setOutput("latest-version", latestRelease.tag_name);
|
||||
}
|
||||
|
||||
run();
|
@ -1,46 +0,0 @@
|
||||
import fs from "node:fs";
|
||||
import * as core from "@actions/core";
|
||||
import * as toml from "smol-toml";
|
||||
|
||||
export function getUvVersionFromConfigFile(
|
||||
filePath: string,
|
||||
): string | undefined {
|
||||
core.info(`Trying to find required-version for uv in: ${filePath}`);
|
||||
if (!fs.existsSync(filePath)) {
|
||||
core.info(`Could not find file: ${filePath}`);
|
||||
return undefined;
|
||||
}
|
||||
let requiredVersion: string | undefined;
|
||||
try {
|
||||
requiredVersion = getRequiredVersion(filePath);
|
||||
} catch (err) {
|
||||
const message = (err as Error).message;
|
||||
core.warning(`Error while parsing ${filePath}: ${message}`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (requiredVersion?.startsWith("==")) {
|
||||
requiredVersion = requiredVersion.slice(2);
|
||||
}
|
||||
if (requiredVersion !== undefined) {
|
||||
core.info(
|
||||
`Found required-version for uv in ${filePath}: ${requiredVersion}`,
|
||||
);
|
||||
}
|
||||
return requiredVersion;
|
||||
}
|
||||
|
||||
function getRequiredVersion(filePath: string): string | undefined {
|
||||
const fileContent = fs.readFileSync(filePath, "utf-8");
|
||||
|
||||
if (filePath.endsWith("pyproject.toml")) {
|
||||
const tomlContent = toml.parse(fileContent) as {
|
||||
tool?: { uv?: { "required-version"?: string } };
|
||||
};
|
||||
return tomlContent?.tool?.uv?.["required-version"];
|
||||
}
|
||||
const tomlContent = toml.parse(fileContent) as {
|
||||
"required-version"?: string;
|
||||
};
|
||||
return tomlContent["required-version"];
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
export const REPO = "uv";
|
||||
export const OWNER = "astral-sh";
|
||||
export const TOOL_CACHE_NAME = "uv";
|
||||
export const GITHUB_COM_API = "https://api.github.com";
|
||||
|
@ -3,8 +3,6 @@ import path from "node:path";
|
||||
|
||||
export const version = core.getInput("version");
|
||||
export const pythonVersion = core.getInput("python-version");
|
||||
export const activateEnvironment = core.getBooleanInput("activate-environment");
|
||||
export const workingDirectory = core.getInput("working-directory");
|
||||
export const checkSum = core.getInput("checksum");
|
||||
export const enableCache = getEnableCache();
|
||||
export const cacheSuffix = core.getInput("cache-suffix") || "";
|
||||
@ -13,11 +11,8 @@ export const cacheDependencyGlob = core.getInput("cache-dependency-glob");
|
||||
export const pruneCache = core.getInput("prune-cache") === "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 serverUrl = core.getInput("server-url");
|
||||
export const githubToken = core.getInput("github-token");
|
||||
|
||||
function getEnableCache(): boolean {
|
||||
@ -65,18 +60,12 @@ function getCacheLocalPath(): string {
|
||||
if (cacheLocalPathInput !== "") {
|
||||
return expandTilde(cacheLocalPathInput);
|
||||
}
|
||||
if (process.env.RUNNER_ENVIRONMENT === "github-hosted") {
|
||||
if (process.env.RUNNER_TEMP !== undefined) {
|
||||
return `${process.env.RUNNER_TEMP}${path.sep}setup-uv-cache`;
|
||||
}
|
||||
throw Error(
|
||||
"Could not determine UV_CACHE_DIR. Please make sure RUNNER_TEMP is set or provide the cache-local-path input",
|
||||
);
|
||||
if (process.env.RUNNER_TEMP !== undefined) {
|
||||
return `${process.env.RUNNER_TEMP}${path.sep}setup-uv-cache`;
|
||||
}
|
||||
if (process.platform === "win32") {
|
||||
return `${process.env.APPDATA}${path.sep}uv${path.sep}cache`;
|
||||
}
|
||||
return `${process.env.HOME}${path.sep}.cache${path.sep}uv`;
|
||||
throw Error(
|
||||
"Could not determine UV_CACHE_DIR. Please make sure RUNNER_TEMP is set or provide the cache-local-path input",
|
||||
);
|
||||
}
|
||||
|
||||
function expandTilde(input: string): string {
|
||||
|
@ -1,58 +0,0 @@
|
||||
import { Octokit as Core } from "@octokit/core";
|
||||
import type {
|
||||
Constructor,
|
||||
OctokitOptions,
|
||||
} from "@octokit/core/dist-types/types";
|
||||
import {
|
||||
paginateRest,
|
||||
type PaginateInterface,
|
||||
} from "@octokit/plugin-paginate-rest";
|
||||
import { legacyRestEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
|
||||
import { fetch as undiciFetch, ProxyAgent, type RequestInit } from "undici";
|
||||
|
||||
export type { RestEndpointMethodTypes } from "@octokit/plugin-rest-endpoint-methods";
|
||||
|
||||
const DEFAULTS = {
|
||||
baseUrl: "https://api.github.com",
|
||||
userAgent: "setup-uv",
|
||||
};
|
||||
|
||||
export function getProxyAgent() {
|
||||
const httpProxy = process.env.HTTP_PROXY || process.env.http_prox;
|
||||
if (httpProxy) {
|
||||
return new ProxyAgent(httpProxy);
|
||||
}
|
||||
|
||||
const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
||||
if (httpsProxy) {
|
||||
return new ProxyAgent(httpsProxy);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export const customFetch = async (url: string, opts: RequestInit) =>
|
||||
await undiciFetch(url, {
|
||||
dispatcher: getProxyAgent(),
|
||||
...opts,
|
||||
});
|
||||
|
||||
export const Octokit: typeof Core &
|
||||
Constructor<
|
||||
{
|
||||
paginate: PaginateInterface;
|
||||
} & ReturnType<typeof legacyRestEndpointMethods>
|
||||
> = Core.plugin(paginateRest, legacyRestEndpointMethods).defaults(
|
||||
function buildDefaults(options: OctokitOptions): OctokitOptions {
|
||||
return {
|
||||
...DEFAULTS,
|
||||
...options,
|
||||
request: {
|
||||
fetch: customFetch,
|
||||
...options.request,
|
||||
},
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
export type Octokit = InstanceType<typeof Octokit>;
|
@ -1,17 +1,10 @@
|
||||
import * as exec from "@actions/exec";
|
||||
import * as core from "@actions/core";
|
||||
export type Platform =
|
||||
| "unknown-linux-gnu"
|
||||
| "unknown-linux-musl"
|
||||
| "unknown-linux-musleabihf"
|
||||
| "apple-darwin"
|
||||
| "pc-windows-msvc";
|
||||
export type Architecture =
|
||||
| "i686"
|
||||
| "x86_64"
|
||||
| "aarch64"
|
||||
| "s390x"
|
||||
| "powerpc64le";
|
||||
export type Architecture = "i686" | "x86_64" | "aarch64";
|
||||
|
||||
export function getArch(): Architecture | undefined {
|
||||
const arch = process.arch;
|
||||
@ -19,8 +12,6 @@ export function getArch(): Architecture | undefined {
|
||||
ia32: "i686",
|
||||
x64: "x86_64",
|
||||
arm64: "aarch64",
|
||||
s390x: "s390x",
|
||||
ppc64: "powerpc64le",
|
||||
};
|
||||
|
||||
if (arch in archMapping) {
|
||||
@ -28,49 +19,15 @@ export function getArch(): Architecture | undefined {
|
||||
}
|
||||
}
|
||||
|
||||
export async function getPlatform(): Promise<Platform | undefined> {
|
||||
const processPlatform = process.platform;
|
||||
export function getPlatform(): Platform | undefined {
|
||||
const platform = process.platform;
|
||||
const platformMapping: { [key: string]: Platform } = {
|
||||
linux: "unknown-linux-gnu",
|
||||
darwin: "apple-darwin",
|
||||
win32: "pc-windows-msvc",
|
||||
};
|
||||
|
||||
if (processPlatform in platformMapping) {
|
||||
const platform = platformMapping[processPlatform];
|
||||
if (platform === "unknown-linux-gnu") {
|
||||
const isMusl = await isMuslOs();
|
||||
return isMusl ? "unknown-linux-musl" : platform;
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
}
|
||||
|
||||
async function isMuslOs(): Promise<boolean> {
|
||||
let stdOutput = "";
|
||||
let errOutput = "";
|
||||
const options: exec.ExecOptions = {
|
||||
silent: !core.isDebug(),
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
stdOutput += data.toString();
|
||||
},
|
||||
stderr: (data: Buffer) => {
|
||||
errOutput += data.toString();
|
||||
},
|
||||
},
|
||||
ignoreReturnCode: true,
|
||||
};
|
||||
|
||||
try {
|
||||
const execArgs = ["--version"];
|
||||
await exec.exec("ldd", execArgs, options);
|
||||
return stdOutput.includes("musl") || errOutput.includes("musl");
|
||||
} catch (error) {
|
||||
const err = error as Error;
|
||||
core.warning(
|
||||
`Failed to determine glibc or musl. Falling back to glibc. Error: ${err.message}`,
|
||||
);
|
||||
return false;
|
||||
if (platform in platformMapping) {
|
||||
return platformMapping[platform];
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||
"target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
|
||||
"outDir": "./lib" /* Redirect output structure to the directory. */,
|
||||
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
|
||||
|
21359
version-manifest.json
21359
version-manifest.json
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user