diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 54b97f3..10f0a0f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -155,5 +155,10 @@ jobs: if [ "$UV_PYTHON" != "${{ matrix.python-version }}" ]; then exit 1 fi - - run: uv sync - working-directory: __tests__/fixtures/uv-project + - name: Verify packages can be installed + run: uv pip install --python=${{ matrix.python-version }} pip + - name: Verify python version is correct + run: | + if [ "$(python --version)" != "${{ matrix.python-version }}" ]; then + exit 1 + fi diff --git a/README.md b/README.md index e108a89..8c44d21 100644 --- a/README.md +++ b/README.md @@ -73,14 +73,16 @@ to install the latest version that satisfies the range. ### Python version You can use the input `python-version` to set the environment variable `UV_PYTHON` for the rest -of your workflow. +of your workflow and automatically create a new virtual environment with the specified python version. + This will override any python version specifications in `pyproject.toml` and `.python-version` ```yaml -- name: Install the latest version of uv and set the python version to 3.12 +- name: Install the latest version of uv and set the python version to ${{ matrix.python-version }} uses: astral-sh/setup-uv@v4 with: - python-version: "3.12" + python-version: ${{ matrix.python-version }} +- run: uv pip install --python=${{ matrix.python-version }} pip ``` You can combine this with a matrix to test multiple python versions: diff --git a/action.yml b/action.yml index a545c19..3667d0b 100644 --- a/action.yml +++ b/action.yml @@ -46,6 +46,9 @@ inputs: tool-bin-dir: description: "Custom path to set UV_TOOL_BIN_DIR to." required: false + python-install-dir: + description: "Custom path where uv will install python interpreters." + required: false outputs: uv-version: description: "The installed uv version. Useful when using latest." diff --git a/dist/save-cache/index.js b/dist/save-cache/index.js index aba2bdd..64800ef 100644 --- a/dist/save-cache/index.js +++ b/dist/save-cache/index.js @@ -91829,7 +91829,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.pythonVersion = exports.version = void 0; +exports.githubToken = exports.pythonInstallDir = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.pythonVersion = exports.version = void 0; const core = __importStar(__nccwpck_require__(7484)); const node_path_1 = __importDefault(__nccwpck_require__(6760)); exports.version = core.getInput("version"); @@ -91843,6 +91843,7 @@ exports.pruneCache = core.getInput("prune-cache") === "true"; exports.ignoreNothingToCache = core.getInput("ignore-nothing-to-cache") === "true"; exports.toolBinDir = getToolBinDir(); exports.toolDir = getToolDir(); +exports.pythonInstallDir = getPythonInstallDir(); exports.githubToken = core.getInput("github-token"); function getEnableCache() { const enableCacheInput = core.getInput("enable-cache"); @@ -91877,6 +91878,19 @@ function getToolDir() { } return undefined; } +function getPythonInstallDir() { + const pythonInstallDirInput = core.getInput("python-install-dir"); + if (pythonInstallDirInput !== "") { + return expandTilde(pythonInstallDirInput); + } + if (process.platform === "win32") { + if (process.env.RUNNER_TEMP !== undefined) { + return `${process.env.RUNNER_TEMP}${node_path_1.default.sep}uv-python-install-dir`; + } + throw Error("Could not determine UV_PYTHON_INSTALL_DIR. Please make sure RUNNER_TEMP is set or provide the python-install-dir input"); + } + return undefined; +} function getCacheLocalPath() { const cacheLocalPathInput = core.getInput("cache-local-path"); if (cacheLocalPathInput !== "") { diff --git a/dist/setup/index.js b/dist/setup/index.js index 96300d5..836d944 100644 --- a/dist/setup/index.js +++ b/dist/setup/index.js @@ -99204,6 +99204,7 @@ const download_version_1 = __nccwpck_require__(8255); const restore_cache_1 = __nccwpck_require__(7772); const platforms_1 = __nccwpck_require__(8361); const inputs_1 = __nccwpck_require__(9612); +const exec = __importStar(__nccwpck_require__(5236)); function run() { return __awaiter(this, void 0, void 0, function* () { const platform = (0, platforms_1.getPlatform)(); @@ -99219,7 +99220,8 @@ function run() { addUvToPath(setupResult.uvDir); addToolBinToPath(); setToolDir(); - setupPython(); + addUvPythonInstallDirToPath(); + yield setupPython(); addMatchers(); setCacheDir(inputs_1.cacheLocalPath); core.setOutput("uv-version", setupResult.version); @@ -99256,6 +99258,14 @@ function addUvToPath(cachedPath) { core.addPath(cachedPath); core.info(`Added ${cachedPath} to the path`); } +function addUvPythonInstallDirToPath() { + if (inputs_1.pythonInstallDir !== undefined) { + core.exportVariable("UV_PYTHON_INSTALL_DIR", inputs_1.toolBinDir); + core.info(`Set UV_PYTHON_INSTALL_DIR to ${inputs_1.toolBinDir}`); + core.addPath(inputs_1.pythonInstallDir); + core.info(`Added ${inputs_1.pythonInstallDir} to the path`); + } +} function addToolBinToPath() { if (inputs_1.toolBinDir !== undefined) { core.exportVariable("UV_TOOL_BIN_DIR", inputs_1.toolBinDir); @@ -99285,10 +99295,18 @@ function setToolDir() { } } function setupPython() { - if (inputs_1.pythonVersion !== "") { - core.exportVariable("UV_PYTHON", inputs_1.pythonVersion); - core.info(`Set UV_PYTHON to ${inputs_1.pythonVersion}`); - } + return __awaiter(this, void 0, void 0, function* () { + if (inputs_1.pythonVersion !== "") { + core.exportVariable("UV_PYTHON", inputs_1.pythonVersion); + core.info(`Set UV_PYTHON to ${inputs_1.pythonVersion}`); + const options = { + silent: !core.isDebug(), + }; + const execArgs = ["venv", "--python", inputs_1.pythonVersion]; + core.info("Activating python venv..."); + yield exec.exec("uv", execArgs, options); + } + }); } function setCacheDir(cacheLocalPath) { core.exportVariable("UV_CACHE_DIR", cacheLocalPath); @@ -99360,7 +99378,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.githubToken = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.pythonVersion = exports.version = void 0; +exports.githubToken = exports.pythonInstallDir = exports.toolDir = exports.toolBinDir = exports.ignoreNothingToCache = exports.pruneCache = exports.cacheDependencyGlob = exports.cacheLocalPath = exports.cacheSuffix = exports.enableCache = exports.checkSum = exports.pythonVersion = exports.version = void 0; const core = __importStar(__nccwpck_require__(7484)); const node_path_1 = __importDefault(__nccwpck_require__(6760)); exports.version = core.getInput("version"); @@ -99374,6 +99392,7 @@ exports.pruneCache = core.getInput("prune-cache") === "true"; exports.ignoreNothingToCache = core.getInput("ignore-nothing-to-cache") === "true"; exports.toolBinDir = getToolBinDir(); exports.toolDir = getToolDir(); +exports.pythonInstallDir = getPythonInstallDir(); exports.githubToken = core.getInput("github-token"); function getEnableCache() { const enableCacheInput = core.getInput("enable-cache"); @@ -99408,6 +99427,19 @@ function getToolDir() { } return undefined; } +function getPythonInstallDir() { + const pythonInstallDirInput = core.getInput("python-install-dir"); + if (pythonInstallDirInput !== "") { + return expandTilde(pythonInstallDirInput); + } + if (process.platform === "win32") { + if (process.env.RUNNER_TEMP !== undefined) { + return `${process.env.RUNNER_TEMP}${node_path_1.default.sep}uv-python-install-dir`; + } + throw Error("Could not determine UV_PYTHON_INSTALL_DIR. Please make sure RUNNER_TEMP is set or provide the python-install-dir input"); + } + return undefined; +} function getCacheLocalPath() { const cacheLocalPathInput = core.getInput("cache-local-path"); if (cacheLocalPathInput !== "") { diff --git a/src/setup-uv.ts b/src/setup-uv.ts index f95babc..e239b65 100644 --- a/src/setup-uv.ts +++ b/src/setup-uv.ts @@ -18,11 +18,13 @@ import { checkSum, enableCache, githubToken, + pythonInstallDir, pythonVersion, toolBinDir, toolDir, version, } from "./utils/inputs"; +import * as exec from "@actions/exec"; async function run(): Promise { const platform = getPlatform(); @@ -46,7 +48,8 @@ async function run(): Promise { addUvToPath(setupResult.uvDir); addToolBinToPath(); setToolDir(); - setupPython(); + addUvPythonInstallDirToPath(); + await setupPython(); addMatchers(); setCacheDir(cacheLocalPath); @@ -98,6 +101,15 @@ function addUvToPath(cachedPath: string): void { core.info(`Added ${cachedPath} to the path`); } +function addUvPythonInstallDirToPath(): void { + if (pythonInstallDir !== undefined) { + core.exportVariable("UV_PYTHON_INSTALL_DIR", toolBinDir); + core.info(`Set UV_PYTHON_INSTALL_DIR to ${toolBinDir}`); + core.addPath(pythonInstallDir); + core.info(`Added ${pythonInstallDir} to the path`); + } +} + function addToolBinToPath(): void { if (toolBinDir !== undefined) { core.exportVariable("UV_TOOL_BIN_DIR", toolBinDir); @@ -125,10 +137,17 @@ function setToolDir(): void { } } -function setupPython(): void { +async function setupPython(): Promise { if (pythonVersion !== "") { core.exportVariable("UV_PYTHON", pythonVersion); core.info(`Set UV_PYTHON to ${pythonVersion}`); + const options: exec.ExecOptions = { + silent: !core.isDebug(), + }; + const execArgs = ["venv", "--python", pythonVersion]; + + core.info("Activating python venv..."); + await exec.exec("uv", execArgs, options); } } diff --git a/src/utils/inputs.ts b/src/utils/inputs.ts index 470a9d9..146bca2 100644 --- a/src/utils/inputs.ts +++ b/src/utils/inputs.ts @@ -13,6 +13,7 @@ export const ignoreNothingToCache = core.getInput("ignore-nothing-to-cache") === "true"; export const toolBinDir = getToolBinDir(); export const toolDir = getToolDir(); +export const pythonInstallDir = getPythonInstallDir(); export const githubToken = core.getInput("github-token"); function getEnableCache(): boolean { @@ -55,6 +56,22 @@ function getToolDir(): string | undefined { return undefined; } +function getPythonInstallDir(): string | undefined { + const pythonInstallDirInput = core.getInput("python-install-dir"); + if (pythonInstallDirInput !== "") { + return expandTilde(pythonInstallDirInput); + } + if (process.platform === "win32") { + if (process.env.RUNNER_TEMP !== undefined) { + return `${process.env.RUNNER_TEMP}${path.sep}uv-python-install-dir`; + } + throw Error( + "Could not determine UV_PYTHON_INSTALL_DIR. Please make sure RUNNER_TEMP is set or provide the python-install-dir input", + ); + } + return undefined; +} + function getCacheLocalPath(): string { const cacheLocalPathInput = core.getInput("cache-local-path"); if (cacheLocalPathInput !== "") {