diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0826dc8..fc7d18c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -203,6 +203,23 @@ jobs: fi env: RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }} + test-pep440-version-specifier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install version 0.11.11 + id: ruff-action + uses: ./ + with: + version: ">=0.11.10,<0.12.0" + src: __tests__/fixtures/python-project + - name: Correct version gets installed + run: | + if [ "$RUFF_VERSION" != "0.11.11" ]; then + exit 1 + fi + env: + RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }} test-checksum: runs-on: ${{ matrix.inputs.os }} strategy: @@ -298,6 +315,7 @@ jobs: - test-default-version-from-pyproject-optional-dependencies - test-default-version-from-requirements - test-semver-range + - test-pep440-version-specifier - test-checksum - test-with-explicit-token - test-args diff --git a/README.md b/README.md index e444b08..bbd0bd2 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A GitHub Action to run [ruff](https://github.com/astral-sh/ruff). This action is commonly used as a pass/fail test to ensure your repository stays clean, abiding the [rules](https://docs.astral.sh/ruff/rules/) specified in your -configuration. Though it runs `ruff check` by default, the action can do +configuration. Though it runs `ruff check` by default, the action can do anything `ruff` can (ex, fix). ## Contents @@ -18,7 +18,7 @@ anything `ruff` can (ex, fix). - [Install specific versions](#install-specific-versions) - [Install the latest version](#install-the-latest-version) - [Install a specific version](#install-a-specific-version) - - [Install a version by supplying a semver range](#install-a-version-by-supplying-a-semver-range) + - [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 from a specified version file](#install-a-version-from-a-specified-version-file) - [Validate checksum](#validate-checksum) - [GitHub authentication token](#github-authentication-token) @@ -116,9 +116,10 @@ the latest version is installed. version: "0.4.4" ``` -#### Install a version by supplying a semver range +#### Install a version by supplying a semver range or pep440 specifier 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 @@ -135,6 +136,13 @@ to install the latest version that satisfies the range. version: "0.4.x" ``` +```yaml +- name: Install a pep440-specifier-satisfying version of ruff + uses: astral-sh/ruff-action@v3 + with: + version: ">=0.11.10,<0.12.0" +``` + #### Install a version from a specified version file You can specify a file to read the version from. diff --git a/dist/ruff-action/index.js b/dist/ruff-action/index.js index a077264..f3bd5c5 100644 Binary files a/dist/ruff-action/index.js and b/dist/ruff-action/index.js differ diff --git a/package-lock.json b/package-lock.json index f3c6936..044d204 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@octokit/core": "^6.1.4", "@octokit/plugin-paginate-rest": "^11.4.3", "@octokit/plugin-rest-endpoint-methods": "^13.3.1", + "@renovatebot/pep440": "^4.1.0", "smol-toml": "^1.3.1" }, "devDependencies": { @@ -350,6 +351,16 @@ "@octokit/openapi-types": "^23.0.1" } }, + "node_modules/@renovatebot/pep440": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@renovatebot/pep440/-/pep440-4.1.0.tgz", + "integrity": "sha512-mo2RxnOSp78Njt1HmgMwjl6FapP4OyIS8HypJlymCvN7AIV2Xf5PmZfl/E3O1WWZ6IjKrfsEAaPWFMi8tnkq3g==", + "license": "Apache-2.0", + "engines": { + "node": "^20.9.0 || ^22.11.0", + "pnpm": "^9.0.0" + } + }, "node_modules/@types/node": { "version": "22.13.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.10.tgz", diff --git a/package.json b/package.json index 6d6eb76..809a2c7 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@octokit/core": "^6.1.4", "@octokit/plugin-paginate-rest": "^11.4.3", "@octokit/plugin-rest-endpoint-methods": "^13.3.1", + "@renovatebot/pep440": "^4.1.0", "smol-toml": "^1.3.1" }, "devDependencies": { diff --git a/src/download/download-version.ts b/src/download/download-version.ts index 0158f1e..a2440f0 100644 --- a/src/download/download-version.ts +++ b/src/download/download-version.ts @@ -3,6 +3,7 @@ import * as tc from "@actions/tool-cache"; import * as path from "node:path"; import { promises as fs } from "node:fs"; import * as semver from "semver"; +import * as pep440 from "@renovatebot/pep440"; import { OWNER, REPO, TOOL_CACHE_NAME } from "../utils/constants"; import type { Architecture, Platform } from "../utils/platforms"; import { validateChecksum } from "./checksum/checksum"; @@ -124,8 +125,8 @@ export async function resolveVersion( return version; } const availableVersions = await getAvailableVersions(githubToken); - const resolvedVersion = tc.evaluateVersions(availableVersions, version); - if (resolvedVersion === "") { + const resolvedVersion = maxSatisfying(availableVersions, version); + if (resolvedVersion === undefined) { throw new Error(`No version found for ${version}`); } core.debug(`Resolved version: ${resolvedVersion}`); @@ -195,3 +196,22 @@ async function getLatestRelease( }); 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; + } + const maxPep440 = pep440.maxSatisfying(versions, version); + if (maxPep440 !== null) { + core.debug( + `Found a version that satisfies the pep440 specifier: ${maxPep440}`, + ); + return maxPep440; + } + return undefined; +}