diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa3b955..39b4750 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -118,6 +118,23 @@ jobs: fi env: RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }} + test-default-version-from-requirements: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use default version from requirements.txt + id: ruff-action + uses: ./ + with: + src: __tests__/fixtures/python-project + version-file: __tests__/fixtures/requirements.txt + - name: Correct version gets installed + run: | + if [ "$RUFF_VERSION" != "0.8.3" ]; then + exit 1 + fi + env: + RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }} test-semver-range: runs-on: ubuntu-latest steps: diff --git a/README.md b/README.md index 371453b..f437a14 100644 --- a/README.md +++ b/README.md @@ -124,13 +124,13 @@ to install the latest version that satisfies the range. #### Install a version from a specified version file You can specify a file to read the version from. -Currently `pyproject.toml` is supported. +Currently `pyproject.toml` and `requirements.txt` are supported. ```yaml - name: Install a version from a specified version file uses: astral-sh/ruff-action@v3 with: - version-file: "my-path/to/pyproject.toml" + version-file: "my-path/to/pyproject.toml-or-requirements.txt" ``` ### Validate checksum diff --git a/__tests__/fixtures/requirements.txt b/__tests__/fixtures/requirements.txt new file mode 100644 index 0000000..c5721a8 --- /dev/null +++ b/__tests__/fixtures/requirements.txt @@ -0,0 +1 @@ +ruff==0.8.3 diff --git a/dist/ruff-action/index.js b/dist/ruff-action/index.js index 866ad61..e19f6dd 100644 --- a/dist/ruff-action/index.js +++ b/dist/ruff-action/index.js @@ -30729,39 +30729,46 @@ exports.getRuffVersionFromPyproject = getRuffVersionFromPyproject; const fs = __importStar(__nccwpck_require__(3024)); const core = __importStar(__nccwpck_require__(7484)); const toml = __importStar(__nccwpck_require__(7106)); +function parseRequirements(allDependencies) { + const ruffVersionDefinition = allDependencies.find((dep) => dep.startsWith("ruff")); + if (ruffVersionDefinition) { + const ruffVersion = ruffVersionDefinition + .match(/^ruff([^A-Z0-9._-]+.*)$/)?.[1] + .trim(); + if (ruffVersion?.startsWith("==")) { + return ruffVersion.slice(2); + } + core.info(`Found ruff version in pyproject.toml: ${ruffVersion}`); + return ruffVersion; + } + return undefined; +} +function parsePyproject(pyprojectContent) { + const pyproject = toml.parse(pyprojectContent); + const dependencies = pyproject?.project?.dependencies || []; + const optionalDependencies = Object.values(pyproject?.project?.["optional-dependencies"] || {}).flat(); + const devDependencies = Object.values(pyproject?.["dependency-groups"] || {}) + .flat() + .filter((item) => typeof item === "string"); + return parseRequirements(dependencies.concat(optionalDependencies, devDependencies)); +} function getRuffVersionFromPyproject(filePath) { if (!fs.existsSync(filePath)) { core.warning(`Could not find file: ${filePath}`); return undefined; } const pyprojectContent = fs.readFileSync(filePath, "utf-8"); - let pyproject; + if (filePath.endsWith(".txt")) { + return parseRequirements(pyprojectContent.split("\n")); + } try { - pyproject = toml.parse(pyprojectContent); + return parsePyproject(pyprojectContent); } catch (err) { const message = err.message; core.warning(`Error while parsing ${filePath}: ${message}`); return undefined; } - const dependencies = pyproject?.project?.dependencies || []; - const optionalDependencies = Object.values(pyproject?.project?.["optional-dependencies"] || {}).flat(); - const devDependencies = Object.values(pyproject?.["dependency-groups"] || {}) - .flat() - .filter((item) => typeof item === "string"); - const allDependencies = dependencies.concat(optionalDependencies, devDependencies); - const ruffVersionDefinition = allDependencies.find((dep) => dep.startsWith("ruff")); - if (ruffVersionDefinition) { - const ruffVersion = ruffVersionDefinition - .match(/^ruff([^A-Z0-9._-]+.*)$/)?.[1] - .trim(); - if (ruffVersion?.startsWith("==")) { - return ruffVersion.slice(2); - } - core.info(`Found ruff version in pyproject.toml: ${ruffVersion}`); - return ruffVersion; - } - return undefined; } diff --git a/src/utils/pyproject.ts b/src/utils/pyproject.ts index ec81eba..055ffc9 100644 --- a/src/utils/pyproject.ts +++ b/src/utils/pyproject.ts @@ -2,45 +2,7 @@ import * as fs from "node:fs"; import * as core from "@actions/core"; import * as toml from "smol-toml"; -export function getRuffVersionFromPyproject( - filePath: string, -): string | undefined { - if (!fs.existsSync(filePath)) { - core.warning(`Could not find file: ${filePath}`); - return undefined; - } - const pyprojectContent = fs.readFileSync(filePath, "utf-8"); - let pyproject: - | { - project?: { - dependencies?: string[]; - "optional-dependencies"?: Map; - }; - "dependency-groups"?: Map>; - } - | undefined; - try { - pyproject = toml.parse(pyprojectContent); - } catch (err) { - const message = (err as Error).message; - core.warning(`Error while parsing ${filePath}: ${message}`); - return undefined; - } - - const dependencies: string[] = pyproject?.project?.dependencies || []; - const optionalDependencies: string[] = Object.values( - pyproject?.project?.["optional-dependencies"] || {}, - ).flat(); - const devDependencies: string[] = Object.values( - pyproject?.["dependency-groups"] || {}, - ) - .flat() - .filter((item: string | object) => typeof item === "string"); - const allDependencies: string[] = dependencies.concat( - optionalDependencies, - devDependencies, - ); - +function parseRequirements(allDependencies: string[]): string | undefined { const ruffVersionDefinition = allDependencies.find((dep: string) => dep.startsWith("ruff"), ); @@ -58,3 +20,45 @@ export function getRuffVersionFromPyproject( return undefined; } + +function parsePyproject(pyprojectContent: string): string | undefined { + const pyproject: { + project?: { + dependencies?: string[]; + "optional-dependencies"?: Map; + }; + "dependency-groups"?: Map>; + } = toml.parse(pyprojectContent); + const dependencies: string[] = pyproject?.project?.dependencies || []; + const optionalDependencies: string[] = Object.values( + pyproject?.project?.["optional-dependencies"] || {}, + ).flat(); + const devDependencies: string[] = Object.values( + pyproject?.["dependency-groups"] || {}, + ) + .flat() + .filter((item: string | object) => typeof item === "string"); + return parseRequirements( + dependencies.concat(optionalDependencies, devDependencies), + ); +} + +export function getRuffVersionFromPyproject( + filePath: string, +): string | undefined { + if (!fs.existsSync(filePath)) { + core.warning(`Could not find file: ${filePath}`); + return undefined; + } + const pyprojectContent = fs.readFileSync(filePath, "utf-8"); + if (filePath.endsWith(".txt")) { + return parseRequirements(pyprojectContent.split("\n")); + } + try { + return parsePyproject(pyprojectContent); + } catch (err) { + const message = (err as Error).message; + core.warning(`Error while parsing ${filePath}: ${message}`); + return undefined; + } +}