setup-uv

repository·main·Indexed 21 days ago

https://github.com/astral-sh/setup-uv

A GitHub Action designed to set up the uv package manager in CI workflows. It handles installation, version resolution via semver, PEP 440, or version files (uv.lock, pyproject.toml), Python environment configuration, and optimized caching to improve workflow performance.

Tokens
10.7K
Snippets
35
Records
46
Agent score
74%

What's inside setup-uv

  1. Security Model and Trust Boundaries of setup-uv

    main

    The setup-uv GitHub Action operates within a specific security model involving several trust boundaries. Understanding these is critical for users configuring workflows:

    Trust Boundaries

    • Maintainers & GitHub Infrastructure: Trusted for source code, bundles, workflows, and the runner protocol. Compromise of these is considered an infrastructure issue, not a repository bug.
    • Consumer Workflow Authors: Control the action reference, triggers, runner, permissions, secrets, and inputs. These are trusted choices unless they are derived from untrusted event data.
    • Project/Checkout Content: When using setup-uv, the action trusts the selected checkout, project authors, and pull-request contributors. This includes project/version files (like uv.toml or pyproject.toml), discovered Python interpreters, virtual environments, and symlinks. Note: Running setup-uv on an untrusted checkout with higher authority is a consumer trust decision; code in the checkout may inherit the action's environment.
    • Remote Metadata: Official endpoints and TLS roots are trusted. If you use a custom manifest, you authorize its URLs and hashes.
    • Cache and Runner State: State produced by the same principal is trusted by default. However, lower-authority references may be able to read higher-authority caches, which can lead to confidentiality leaks.

    Security Invariants

    To ensure a secure setup, setup-uv adheres to these principles:

    • Executable Identity: The precedence for determining which uv to run is: 1. Workflow version, 2. Version file, 3. Project configuration, 4. latest.
    • Credential Protection: Tokens and URL credentials are restricted to workflow-authorized origins, redirects, paths, and logs.
    • Path Isolation: Changes to paths, environments, or virtual environments are designed to affect only authorized targets.
    • Cache Integrity: Cache keys and scopes are managed to prevent lower-to-higher authority poisoning and higher-to-lower authority disclosure.
  2. Evaluate security severity levels

    main

    The project uses a specific calibration for security findings based on the attack graph and incremental capability. Severity is determined by the threshold of impact and the prerequisite required for an attacker to succeed:

    • Critical: A low-prerequisite remote/lower-authority attacker compromises default distribution, publishes malicious artifacts, or gains broad runner control under safe defaults.
    • High: A demonstrated lower-authority input crosses a boundary (execution, confidentiality, integrity, or persistence) in a privileged job and gains substantial capability (e.g., cache poisoning in a write/OIDC job).
    • Medium: A constrained crossing causes limited impact, such as reliable remote DoS, scoped persistence, or disclosure of a usable read-only private token.
    • Low: A weak boundary causes narrow disclosure, log spoofing, or limited resource waste (e.g., bounded job failure).
  3. How the uv cache key is generated

    main

    The cache key is automatically computed to ensure compatibility and prevent issues like binary incompatibility when runner images change. It is composed of the following elements:

    • Architecture: CPU architecture (e.g., x86_64, aarch64)
    • Platform: OS platform type (e.g., unknown-linux-gnu, apple-darwin, pc-windows-msvc)
    • OS version: OS name and version (e.g., ubuntu-22.04, macos-14)
    • Python version: The Python version in use
    • Cache options: Whether pruning and Python caching are enabled
    • Dependency hash: Hash of files matching the cache-dependency-glob pattern
    • Suffix: An optional cache-suffix if provided

    The resulting key is available via the cache-key output of the setup-uv step.

    - name: Setup uv
      id: setup-uv
      uses: astral-sh/setup-uv@v9.0.0
      with:
        enable-cache: true
    - name: Print cache key
      run: echo "Cache key: ${{ steps.setup-uv.outputs.cache-key }}"
  4. Understand the attack surface and security mitigations

    main

    The setup-uv repository identifies several key attack surfaces related to its function as a setup action. Security is maintained through specific mitigations across these areas:

    • Supply Chain: Protects against unauthorized changes to published bundles or dependencies by verifying source/bundle alignment, lockfile integrity, and immutable action pins.
    • Version & Manifest Selection: Prevents malicious version or URL selection by enforcing documented precedence, rejecting malformed records, and verifying HTTPS and checksums.
    • Artifact & Tool Handling: Mitigates risks in URL, token, and checksum handling by ensuring mirror fallbacks preserve identity, stripping authorization on redirects, and requiring independent hashes before extraction.
    • Environment & Interpreter: Manages risks associated with PATH, virtual environments, and interpreters by delegating these to project authority while ensuring explicit workflow choices are bound.
    • Caching: Protects GitHub uv/Python caches by partitioning keys (platform, interpreter, dependency) to prevent cross-job persistence or unauthorized data exposure.
    • CI & Automation: Secures PR workflows and updaters by verifying effective permissions, fork behavior, and ensuring unreviewed code cannot gain write or secret authority.
    • Availability: Protects against resource exhaustion (disk/memory) and log manipulation by enforcing bounds on manifest parsing and remote string expansion.
  5. Installing project dependencies with `uv`

    main
    setup-uv only installs the uv binary; it does not automatically install your project's dependencies. To install libraries defined in your pyproject.toml or requirements.txt, you must explicitly run a command such as uv sync, uv pip install ., or use uv run ....
  6. Use tilde expansion in paths

    main

    The action supports expanding the ~ character to the user's home directory for the following inputs:

    • version-file
    • cache-local-path
    • tool-dir
    • tool-bin-dir
    • cache-dependency-glob
    - name: Expand the tilde character
      uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      with:
        cache-local-path: "~/path/to/cache"
        tool-dir: "~/path/to/tool/dir"
        tool-bin-dir: "~/path/to/tool-bin/dir"
        cache-dependency-glob: "~/my-cache-buster"
  7. Best practices for caching with different resolution strategies

    main

    When using GitHub Actions caching with setup-uv, you must include your resolution strategy in the cache key (e.g., as a cache-suffix).

    If different jobs use the same dependency files (like pyproject.toml) but different resolution strategies (e.g., highest vs lowest), they will generate different dependency sets. If the resolution strategy is not part of the cache key, multiple jobs will attempt to upload to the same cache key, resulting in a 409 Conflict error.

  8. Validate the checksum of the downloaded uv executable

    main

    To ensure the integrity of the downloaded uv executable, you can provide a checksum input. While checksums up to the default version are automatically verified, you must manually specify the checksum when installing specific versions. SHA256 hashes can be retrieved from the uv releases page.

    - name: Install a specific version and validate the checksum
      uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      with:
        version: "0.3.1"
        checksum: "e11b01402ab645392c7ad6044db63d37e4fd1e745e015306993b07695ea5f9f8"
  9. Install uv in GitHub Actions

    main

    Use astral-sh/setup-uv to install a specific version of uv or the latest version into your GitHub Actions workflow. By default, if no version is specified, the action searches for a required-version in uv.toml or pyproject.toml at the repository root. If neither is found, it installs the latest version.

    To install the latest version, use the following step in your workflow:

    - name: Install the latest version of uv
      uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
  10. Set a custom working directory

    main

    The working-directory input defines the directory where the action looks for configuration files (pyproject.toml, uv.toml, and .python-version) to determine the versions of uv and Python to install. It also determines where the virtual environment is created if activate-environment is enabled, unless a specific venv-path is provided.

    - name: Install uv based on the config files in the working-directory
      uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      with:
        working-directory: my/subproject/dir
  11. Install uv using semver ranges or PEP 440 specifiers

    main

    You can specify a version range using semver or PEP 440 syntax. The action will install the latest version that satisfies the provided constraint.

    Examples:

    • Semver range: " >=0.4.0 "
    • Pinning a minor version: "0.4.x"
    • Complex PEP 440 specifier: ">=0.4.25,<0.5"
    - name: Install a semver range of uv
      uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      with:
        version: ">=0.4.0"
  12. Install uv from a version file

    main

    Use the version-file input to automatically detect the uv version from your project configuration files. Supported files include:

    • pyproject.toml: Uses required-version or uv as a dependency.
    • uv.toml: Uses required-version.
    • uv.lock: Installs the exact pinned version for deterministic CI runs.
    • requirements.txt: Uses uv as a dependency.
    • .tool-versions: (asdf format, without the ref syntax).

    Pointing to uv.lock is recommended for deterministic builds to avoid silently upgrading uv until the lockfile is explicitly updated.

    - name: Install uv based on the version locked in uv.lock
      uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
      with:
        version-file: "uv.lock"