mirror of
https://github.com/astral-sh/ruff-action.git
synced 2026-08-08 10:17:03 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7b1296fb5 | ||
|
|
097d5252c8 | ||
|
|
5f8cbe30d7 | ||
|
|
d8f577dec4 | ||
|
|
f173943ec8 | ||
|
|
d34edb0565 | ||
|
|
f14634c415 |
@@ -35,7 +35,7 @@ jobs:
|
||||
- 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:"
|
||||
echo "::error::Detected uncommitted changes after build. Run 'npm run build' and commit the changes."
|
||||
git diff --text -v
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
npm run all
|
||||
- name: Make sure no changes from linters are detected
|
||||
run: |
|
||||
git diff --exit-code
|
||||
git diff --exit-code || (echo "::error::Please run 'npm run all' to fix the issues" && exit 1)
|
||||
test-latest-version:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
@@ -51,6 +51,23 @@ jobs:
|
||||
with:
|
||||
version: ${{ matrix.ruff-version }}
|
||||
src: __tests__/fixtures/python-project
|
||||
test-version-from-version-file-pyproject:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use version from pyproject.toml
|
||||
id: ruff-action
|
||||
uses: ./
|
||||
with:
|
||||
src: __tests__/fixtures/python-project
|
||||
version-file: __tests__/fixtures/pyproject.toml
|
||||
- name: Correct version gets installed
|
||||
run: |
|
||||
if [ "$RUFF_VERSION" != "0.9.3" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
|
||||
test-default-version-from-pyproject:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -84,6 +101,57 @@ jobs:
|
||||
fi
|
||||
env:
|
||||
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
|
||||
test-default-version-from-pyproject-dependency-groups:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use default version from pyproject.toml dependency groups
|
||||
id: ruff-action
|
||||
uses: ./
|
||||
with:
|
||||
src: __tests__/fixtures/pyproject-dependency-groups-project
|
||||
version-file: __tests__/fixtures/pyproject-dependency-groups-project/pyproject.toml
|
||||
- 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-default-version-from-pyproject-optional-dependencies:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Use default version from pyproject.toml optional dependencies
|
||||
id: ruff-action
|
||||
uses: ./
|
||||
with:
|
||||
src: __tests__/fixtures/pyproject-optional-dependencies-project
|
||||
version-file: __tests__/fixtures/pyproject-optional-dependencies-project/pyproject.toml
|
||||
- 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-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.9.0" ]; then
|
||||
exit 1
|
||||
fi
|
||||
env:
|
||||
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
|
||||
test-semver-range:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
name: "Update known checksums"
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 4 * * *" # Run every day at 4am UTC
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -81,7 +81,8 @@ This action adds ruff to the PATH, so you can use it in subsequent steps.
|
||||
|
||||
By default this action looks for a pyproject.toml file in the root of the repository to determine
|
||||
the ruff version to install. If no pyproject.toml file is found, or no ruff version is defined in
|
||||
either `dependencies` or `dependency-groups.dev` the latest version is installed.
|
||||
`project.dependencies`, `project.optional-dependencies`, or `dependency-groups`,
|
||||
the latest version is installed.
|
||||
|
||||
#### Install the latest version
|
||||
|
||||
@@ -123,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
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
[project]
|
||||
name = "pyproject-dependency-groups-project"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
{ include-group = "docs" },
|
||||
{ include-group = "lint" },
|
||||
]
|
||||
docs = [
|
||||
"sphinx",
|
||||
]
|
||||
lint = [
|
||||
"ruff==0.8.3",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
def hello() -> str:
|
||||
return "Hello from python-project!"
|
||||
+1
@@ -0,0 +1 @@
|
||||
print("Hello world!")
|
||||
@@ -0,0 +1,15 @@
|
||||
[project]
|
||||
name = "pyproject-optional-dependencies-project"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[project.optional-dependencies]
|
||||
lint = [
|
||||
"ruff==0.8.3",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
def hello() -> str:
|
||||
return "Hello from python-project!"
|
||||
+1
@@ -0,0 +1 @@
|
||||
print("Hello world!")
|
||||
@@ -0,0 +1,13 @@
|
||||
[project]
|
||||
name = "pyython-project"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"ruff==0.9.3",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
@@ -0,0 +1 @@
|
||||
ruff==0.9.0
|
||||
+40
-24
@@ -30387,6 +30387,7 @@ async function downloadVersion(platform, arch, version, checkSum, githubToken) {
|
||||
return { version: version, cachedToolDir };
|
||||
}
|
||||
async function resolveVersion(versionInput, githubToken) {
|
||||
core.debug(`Resolving ${versionInput}...`);
|
||||
const version = versionInput === "latest"
|
||||
? await getLatestVersion(githubToken)
|
||||
: versionInput;
|
||||
@@ -30399,6 +30400,7 @@ async function resolveVersion(versionInput, githubToken) {
|
||||
if (resolvedVersion === "") {
|
||||
throw new Error(`No version found for ${version}`);
|
||||
}
|
||||
core.debug(`Resolved version: ${resolvedVersion}`);
|
||||
return resolvedVersion;
|
||||
}
|
||||
async function getAvailableVersions(githubToken) {
|
||||
@@ -30552,17 +30554,21 @@ async function determineVersion() {
|
||||
return await (0, download_version_1.resolveVersion)(inputs_1.version, inputs_1.githubToken);
|
||||
}
|
||||
if (inputs_1.versionFile !== "") {
|
||||
const versionFromPyproject = (0, pyproject_1.getRuffVersionFromPyproject)(inputs_1.versionFile);
|
||||
const versionFromPyproject = (0, pyproject_1.getRuffVersionFromRequirementsFile)(inputs_1.versionFile);
|
||||
if (versionFromPyproject === undefined) {
|
||||
core.warning("Could not parse version from supplied pyproject.toml. Using latest version.");
|
||||
return await (0, download_version_1.resolveVersion)("latest", inputs_1.githubToken);
|
||||
core.warning(`Could not parse version from ${inputs_1.versionFile}. Using latest version.`);
|
||||
}
|
||||
return await (0, download_version_1.resolveVersion)(versionFromPyproject || "latest", inputs_1.githubToken);
|
||||
}
|
||||
const pyProjectPath = path.join(inputs_1.src, "pyproject.toml");
|
||||
if (!fs.existsSync(pyProjectPath)) {
|
||||
core.info(`Could not find ${pyProjectPath}. Using latest version.`);
|
||||
return await (0, download_version_1.resolveVersion)("latest", inputs_1.githubToken);
|
||||
}
|
||||
const versionFromPyproject = (0, pyproject_1.getRuffVersionFromPyproject)(pyProjectPath);
|
||||
const versionFromPyproject = (0, pyproject_1.getRuffVersionFromRequirementsFile)(pyProjectPath);
|
||||
if (versionFromPyproject === undefined) {
|
||||
core.warning(`Could not parse version from ${pyProjectPath}. Using latest version.`);
|
||||
}
|
||||
return await (0, download_version_1.resolveVersion)(versionFromPyproject || "latest", inputs_1.githubToken);
|
||||
}
|
||||
function addRuffToPath(cachedPath) {
|
||||
@@ -30725,29 +30731,12 @@ var __importStar = (this && this.__importStar) || (function () {
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||
exports.getRuffVersionFromPyproject = getRuffVersionFromPyproject;
|
||||
exports.getRuffVersionFromRequirementsFile = getRuffVersionFromRequirementsFile;
|
||||
const fs = __importStar(__nccwpck_require__(3024));
|
||||
const core = __importStar(__nccwpck_require__(7484));
|
||||
const toml = __importStar(__nccwpck_require__(7106));
|
||||
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;
|
||||
try {
|
||||
pyproject = toml.parse(pyprojectContent);
|
||||
}
|
||||
catch (err) {
|
||||
const message = err.message;
|
||||
core.warning(`Error while parsing ${filePath}: ${message}`);
|
||||
return undefined;
|
||||
}
|
||||
const dependencies = pyproject?.project?.dependencies || [];
|
||||
const devDependencies = pyproject?.["dependency-groups"]?.dev || [];
|
||||
const ruffVersionDefinition = dependencies.find((dep) => dep.startsWith("ruff")) ||
|
||||
devDependencies.find((dep) => dep.startsWith("ruff"));
|
||||
function getRuffVersionFromAllDependencies(allDependencies) {
|
||||
const ruffVersionDefinition = allDependencies.find((dep) => dep.startsWith("ruff"));
|
||||
if (ruffVersionDefinition) {
|
||||
const ruffVersion = ruffVersionDefinition
|
||||
.match(/^ruff([^A-Z0-9._-]+.*)$/)?.[1]
|
||||
@@ -30760,6 +30749,33 @@ function getRuffVersionFromPyproject(filePath) {
|
||||
}
|
||||
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 getRuffVersionFromAllDependencies(dependencies.concat(optionalDependencies, devDependencies));
|
||||
}
|
||||
function getRuffVersionFromRequirementsFile(filePath) {
|
||||
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 getRuffVersionFromAllDependencies(pyprojectContent.split("\n"));
|
||||
}
|
||||
try {
|
||||
return parsePyproject(pyprojectContent);
|
||||
}
|
||||
catch (err) {
|
||||
const message = err.message;
|
||||
core.warning(`Error while parsing ${filePath}: ${message}`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
"package": "ncc build -o dist/ruff-action src/ruff-action.ts && ncc build -o dist/update-known-checksums src/update-known-checksums.ts",
|
||||
"act": "act pull_request -W .github/workflows/test.yml --container-architecture linux/amd64 -s GITHUB_TOKEN=\"$(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"
|
||||
"all": "npm install && npm run build && npm run format && npm run lint && npm run package"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -71,6 +71,7 @@ export async function resolveVersion(
|
||||
versionInput: string,
|
||||
githubToken: string,
|
||||
): Promise<string> {
|
||||
core.debug(`Resolving ${versionInput}...`);
|
||||
const version =
|
||||
versionInput === "latest"
|
||||
? await getLatestVersion(githubToken)
|
||||
@@ -84,6 +85,7 @@ export async function resolveVersion(
|
||||
if (resolvedVersion === "") {
|
||||
throw new Error(`No version found for ${version}`);
|
||||
}
|
||||
core.debug(`Resolved version: ${resolvedVersion}`);
|
||||
return resolvedVersion;
|
||||
}
|
||||
|
||||
|
||||
+13
-5
@@ -21,7 +21,7 @@ import {
|
||||
version,
|
||||
versionFile as versionFileInput,
|
||||
} from "./utils/inputs";
|
||||
import { getRuffVersionFromPyproject } from "./utils/pyproject";
|
||||
import { getRuffVersionFromRequirementsFile } from "./utils/pyproject";
|
||||
import * as fs from "node:fs";
|
||||
|
||||
async function run(): Promise<void> {
|
||||
@@ -93,19 +93,27 @@ async function determineVersion(): Promise<string> {
|
||||
return await resolveVersion(version, githubToken);
|
||||
}
|
||||
if (versionFileInput !== "") {
|
||||
const versionFromPyproject = getRuffVersionFromPyproject(versionFileInput);
|
||||
const versionFromPyproject =
|
||||
getRuffVersionFromRequirementsFile(versionFileInput);
|
||||
if (versionFromPyproject === undefined) {
|
||||
core.warning(
|
||||
"Could not parse version from supplied pyproject.toml. Using latest version.",
|
||||
`Could not parse version from ${versionFileInput}. Using latest version.`,
|
||||
);
|
||||
return await resolveVersion("latest", githubToken);
|
||||
}
|
||||
return await resolveVersion(versionFromPyproject || "latest", githubToken);
|
||||
}
|
||||
const pyProjectPath = path.join(src, "pyproject.toml");
|
||||
if (!fs.existsSync(pyProjectPath)) {
|
||||
core.info(`Could not find ${pyProjectPath}. Using latest version.`);
|
||||
return await resolveVersion("latest", githubToken);
|
||||
}
|
||||
const versionFromPyproject = getRuffVersionFromPyproject(pyProjectPath);
|
||||
const versionFromPyproject =
|
||||
getRuffVersionFromRequirementsFile(pyProjectPath);
|
||||
if (versionFromPyproject === undefined) {
|
||||
core.warning(
|
||||
`Could not parse version from ${pyProjectPath}. Using latest version.`,
|
||||
);
|
||||
}
|
||||
return await resolveVersion(versionFromPyproject || "latest", githubToken);
|
||||
}
|
||||
|
||||
|
||||
+47
-27
@@ -2,34 +2,12 @@ import * as fs from "node:fs";
|
||||
import * as core from "@actions/core";
|
||||
import * as toml from "smol-toml";
|
||||
|
||||
export function getRuffVersionFromPyproject(
|
||||
filePath: string,
|
||||
function getRuffVersionFromAllDependencies(
|
||||
allDependencies: 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[] };
|
||||
"dependency-groups"?: { dev?: string[] };
|
||||
}
|
||||
| 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 devDependencies: string[] = pyproject?.["dependency-groups"]?.dev || [];
|
||||
|
||||
const ruffVersionDefinition =
|
||||
dependencies.find((dep: string) => dep.startsWith("ruff")) ||
|
||||
devDependencies.find((dep: string) => dep.startsWith("ruff"));
|
||||
const ruffVersionDefinition = allDependencies.find((dep: string) =>
|
||||
dep.startsWith("ruff"),
|
||||
);
|
||||
|
||||
if (ruffVersionDefinition) {
|
||||
const ruffVersion = ruffVersionDefinition
|
||||
@@ -44,3 +22,45 @@ export function getRuffVersionFromPyproject(
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parsePyproject(pyprojectContent: string): string | undefined {
|
||||
const pyproject: {
|
||||
project?: {
|
||||
dependencies?: string[];
|
||||
"optional-dependencies"?: Map<string, string[]>;
|
||||
};
|
||||
"dependency-groups"?: Map<string, Array<string | object>>;
|
||||
} = 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 getRuffVersionFromAllDependencies(
|
||||
dependencies.concat(optionalDependencies, devDependencies),
|
||||
);
|
||||
}
|
||||
|
||||
export function getRuffVersionFromRequirementsFile(
|
||||
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 getRuffVersionFromAllDependencies(pyprojectContent.split("\n"));
|
||||
}
|
||||
try {
|
||||
return parsePyproject(pyprojectContent);
|
||||
} catch (err) {
|
||||
const message = (err as Error).message;
|
||||
core.warning(`Error while parsing ${filePath}: ${message}`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user