mirror of
https://github.com/astral-sh/ruff-action.git
synced 2026-08-08 18:27:03 +00:00
Migrate to ESMBundler and node 24 (#345)
This commit is contained in:
+7
-6
@@ -136,16 +136,17 @@ function setOutputFormat() {
|
||||
}
|
||||
|
||||
function addMatchers(): void {
|
||||
const matchersPath = path.join(
|
||||
__dirname,
|
||||
`..${path.sep}..`,
|
||||
".github",
|
||||
"matchers",
|
||||
);
|
||||
const actionRoot = getActionRoot();
|
||||
const matchersPath = path.join(actionRoot, ".github", "matchers");
|
||||
core.info(`##[add-matcher]${path.join(matchersPath, "check.json")}`);
|
||||
core.info(`##[add-matcher]${path.join(matchersPath, "format.json")}`);
|
||||
}
|
||||
|
||||
function getActionRoot(): string {
|
||||
const entrypoint = process.argv[1] ?? process.cwd();
|
||||
return path.resolve(path.dirname(entrypoint), "..", "..");
|
||||
}
|
||||
|
||||
async function runRuff(
|
||||
ruffExecutablePath: string,
|
||||
args: string[],
|
||||
|
||||
@@ -10,9 +10,9 @@ const PaginatingOctokit = Octokit.plugin(paginateRest, restEndpointMethods);
|
||||
|
||||
async function run(): Promise<void> {
|
||||
const checksumFilePath = process.argv.slice(2)[0];
|
||||
const github_token = process.argv.slice(2)[1];
|
||||
const githubToken = process.argv.slice(2)[1];
|
||||
|
||||
const octokit = new PaginatingOctokit({ auth: github_token });
|
||||
const octokit = new PaginatingOctokit({ auth: githubToken });
|
||||
|
||||
const response = await octokit.paginate(octokit.rest.repos.listReleases, {
|
||||
owner: OWNER,
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
import * as path from "node:path";
|
||||
import * as core from "@actions/core";
|
||||
import { findPyprojectToml } from "./pyproject-finder";
|
||||
|
||||
jest.mock("@actions/core", () => ({
|
||||
debug: jest.fn(),
|
||||
info: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("findPyprojectToml", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("when pyproject.toml exists in src directory", () => {
|
||||
it("should return the exact path", () => {
|
||||
const fixturesDir = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
);
|
||||
const workspaceRoot = path.join(__dirname, "..", "..");
|
||||
|
||||
const result = findPyprojectToml(fixturesDir, workspaceRoot);
|
||||
|
||||
expect(result).toContain("pyproject.toml");
|
||||
expect(result).toContain("fixtures");
|
||||
expect(core.info).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when pyproject.toml exists only in parent directory", () => {
|
||||
it("should search upwards and find the parent's pyproject.toml", () => {
|
||||
// subproject doesn't have a pyproject.toml, but its parent (parent-config-project) does
|
||||
const subprojectDir = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
"parent-config-project",
|
||||
"subproject",
|
||||
);
|
||||
const workspaceRoot = path.join(__dirname, "..", "..");
|
||||
|
||||
const result = findPyprojectToml(subprojectDir, workspaceRoot);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toContain("pyproject.toml");
|
||||
expect(result).toContain("parent-config-project");
|
||||
expect(core.info).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("boundary conditions", () => {
|
||||
it("should stop searching at workspace root and return undefined when not found", () => {
|
||||
// Create a path that won't have pyproject.toml above it
|
||||
const nodeModulesDir = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"node_modules",
|
||||
"@actions",
|
||||
);
|
||||
const workspaceRoot = path.join(__dirname, "..", "..");
|
||||
|
||||
const result = findPyprojectToml(nodeModulesDir, workspaceRoot);
|
||||
|
||||
// Should return undefined since there's no pyproject.toml in the search path
|
||||
expect(result).toBeUndefined();
|
||||
expect(core.info).not.toHaveBeenCalledWith(
|
||||
expect.stringContaining("Found pyproject.toml"),
|
||||
);
|
||||
});
|
||||
|
||||
it("should find pyproject.toml when it exists at workspace root", () => {
|
||||
// Use parent-config-project as the "workspace root" for this test
|
||||
// Start from subproject (which has no pyproject.toml) to search up to workspace root
|
||||
const subprojectDir = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
"parent-config-project",
|
||||
"subproject",
|
||||
);
|
||||
const workspaceRoot = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
"parent-config-project",
|
||||
);
|
||||
|
||||
const result = findPyprojectToml(subprojectDir, workspaceRoot);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toContain("pyproject.toml");
|
||||
expect(result).toContain("parent-config-project");
|
||||
});
|
||||
|
||||
it("should stop at workspace root even if searching from it", () => {
|
||||
const workspaceRoot = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
);
|
||||
|
||||
const result = findPyprojectToml(workspaceRoot, workspaceRoot);
|
||||
|
||||
// Should find pyproject.toml at workspace root
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toContain("pyproject.toml");
|
||||
expect(result).toContain("fixtures");
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases", () => {
|
||||
it("should handle relative paths", () => {
|
||||
const srcDir = "./__tests__/fixtures";
|
||||
const workspaceRoot = ".";
|
||||
|
||||
const result = findPyprojectToml(srcDir, workspaceRoot);
|
||||
|
||||
// Should work with relative paths
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toContain("pyproject.toml");
|
||||
});
|
||||
|
||||
it("should handle when src equals workspace root", () => {
|
||||
const workspaceRoot = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
);
|
||||
const result = findPyprojectToml(workspaceRoot, workspaceRoot);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toContain("pyproject.toml");
|
||||
expect(result).toContain("fixtures");
|
||||
});
|
||||
|
||||
it("should log debug messages for each checked path", () => {
|
||||
const pythonProjectDir = path.join(
|
||||
__dirname,
|
||||
"..",
|
||||
"..",
|
||||
"__tests__",
|
||||
"fixtures",
|
||||
"python-project",
|
||||
);
|
||||
const workspaceRoot = path.join(__dirname, "..", "..");
|
||||
|
||||
findPyprojectToml(pythonProjectDir, workspaceRoot);
|
||||
|
||||
expect(core.debug).toHaveBeenCalled();
|
||||
const debugCalls = (core.debug as jest.Mock).mock.calls;
|
||||
expect(debugCalls.length).toBeGreaterThan(0);
|
||||
|
||||
// First debug call should be for the starting directory
|
||||
expect(debugCalls[0][0]).toContain("Checking for");
|
||||
expect(debugCalls[0][0]).toContain("python-project");
|
||||
});
|
||||
|
||||
it("should handle paths with trailing slashes", () => {
|
||||
const fixturesDir = `${path.join(__dirname, "..", "..", "__tests__", "fixtures")}/`;
|
||||
const workspaceRoot = path.join(__dirname, "..", "..");
|
||||
|
||||
const result = findPyprojectToml(fixturesDir, workspaceRoot);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toContain("pyproject.toml");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -26,30 +26,20 @@ export function findPyprojectToml(
|
||||
core.info(`Found pyproject.toml at ${pyprojectPath}`);
|
||||
return pyprojectPath;
|
||||
}
|
||||
|
||||
// Check if we've reached the workspace root
|
||||
if (currentDir === resolvedWorkspaceRoot) {
|
||||
// If we're at workspace root and didn't find it, stop searching
|
||||
break;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Move up to parent directory
|
||||
const parentDir = path.dirname(currentDir);
|
||||
|
||||
// If parent is the same as current, we've reached the filesystem root
|
||||
if (parentDir === currentDir) {
|
||||
break;
|
||||
if (
|
||||
parentDir === currentDir ||
|
||||
!isPathWithinWorkspace(parentDir, resolvedWorkspaceRoot)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
currentDir = parentDir;
|
||||
|
||||
// If we've gone past the workspace root, stop searching
|
||||
if (isPathWithinWorkspace(currentDir, resolvedWorkspaceRoot) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,18 +52,7 @@ export function findPyprojectToml(
|
||||
function isPathWithinWorkspace(
|
||||
checkPath: string,
|
||||
workspaceRoot: string,
|
||||
): boolean | undefined {
|
||||
try {
|
||||
const checkPathResolved = path.resolve(checkPath);
|
||||
const workspaceRootResolved = path.resolve(workspaceRoot);
|
||||
|
||||
// Check if checkPath starts with workspaceRoot (case-insensitive on Windows)
|
||||
const relativePath = path.relative(
|
||||
workspaceRootResolved,
|
||||
checkPathResolved,
|
||||
);
|
||||
return !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
): boolean {
|
||||
const relativePath = path.relative(workspaceRoot, checkPath);
|
||||
return !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
|
||||
}
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
import * as core from "@actions/core";
|
||||
import { findRuffVersionInSpec } from "./pyproject";
|
||||
|
||||
jest.mock("@actions/core", () => ({
|
||||
info: jest.fn(),
|
||||
warning: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("findRuffVersionInSpec", () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe("ruff dependency strings", () => {
|
||||
it("should extract version from 'ruff==0.9.3'", () => {
|
||||
const result = findRuffVersionInSpec("ruff==0.9.3");
|
||||
expect(result).toBe("0.9.3");
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
"Found ruff version in requirements file: 0.9.3",
|
||||
);
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should extract version from 'ruff>=0.14'", () => {
|
||||
const result = findRuffVersionInSpec("ruff>=0.14");
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should extract version from 'ruff ~=1.0.0'", () => {
|
||||
const result = findRuffVersionInSpec("ruff ~=1.0.0");
|
||||
expect(result).toBe("~=1.0.0");
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should extract version from 'ruff>=0.14,<1.0'", () => {
|
||||
const result = findRuffVersionInSpec("ruff>=0.14,<1.0");
|
||||
expect(result).toBe(">=0.14,<1.0");
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should extract version from 'ruff>=0.14,<2.0,!=1.5.0'", () => {
|
||||
const result = findRuffVersionInSpec("ruff>=0.14,<2.0,!=1.5.0");
|
||||
expect(result).toBe(">=0.14,<2.0,!=1.5.0");
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return undefined for non-ruff dependency 'another-dep 0.1.6'", () => {
|
||||
const result = findRuffVersionInSpec("another-dep 0.1.6");
|
||||
expect(result).toBeUndefined();
|
||||
expect(core.info).not.toHaveBeenCalled();
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return undefined for non-ruff dependency 'another-dep==0.1.6'", () => {
|
||||
const result = findRuffVersionInSpec("another-dep==0.1.6");
|
||||
expect(result).toBeUndefined();
|
||||
expect(core.info).not.toHaveBeenCalled();
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should strip trailing backslash", () => {
|
||||
const result = findRuffVersionInSpec("ruff==0.9.3 \\");
|
||||
expect(result).toBe("0.9.3");
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
"Found ruff version in requirements file: 0.9.3",
|
||||
);
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should strip trailing backslash with whitespace", () => {
|
||||
const result = findRuffVersionInSpec(" ruff==0.9.3 \\ ");
|
||||
expect(result).toBe("0.9.3");
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("environment markers", () => {
|
||||
it("should strip python_version environment marker", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
'ruff>=0.14 ; python_version >= "3.11"',
|
||||
);
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
"Found ruff version in requirements file: >=0.14",
|
||||
);
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
"Environment markers are ignored. ruff is a standalone tool that works independently of Python version.",
|
||||
);
|
||||
});
|
||||
|
||||
it("should strip sys_platform environment marker", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
"ruff==0.9.3 ; sys_platform == 'linux'",
|
||||
);
|
||||
expect(result).toBe("0.9.3");
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
"Environment markers are ignored. ruff is a standalone tool that works independently of Python version.",
|
||||
);
|
||||
});
|
||||
|
||||
it("should strip multiple environment markers", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
'ruff>=0.14 ; python_version >= "3.11" and sys_platform == "linux"',
|
||||
);
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
"Environment markers are ignored. ruff is a standalone tool that works independently of Python version.",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle environment markers with multiple constraints", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
'ruff>=0.14,<1.0 ; python_version >= "3.11"',
|
||||
);
|
||||
expect(result).toBe(">=0.14,<1.0");
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
"Environment markers are ignored. ruff is a standalone tool that works independently of Python version.",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("edge cases", () => {
|
||||
it("should handle whitespace", () => {
|
||||
const result = findRuffVersionInSpec(" ruff >=0.14 ");
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle whitespace with environment markers", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
" ruff >=0.14 ; python_version >= '3.11' ",
|
||||
);
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.warning).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return undefined for empty string", () => {
|
||||
const result = findRuffVersionInSpec("");
|
||||
expect(result).toBeUndefined();
|
||||
expect(core.info).not.toHaveBeenCalled();
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return undefined for whitespace only", () => {
|
||||
const result = findRuffVersionInSpec(" ");
|
||||
expect(result).toBeUndefined();
|
||||
expect(core.info).not.toHaveBeenCalled();
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should return undefined for just semicolon", () => {
|
||||
const result = findRuffVersionInSpec(";");
|
||||
expect(result).toBeUndefined();
|
||||
expect(core.info).not.toHaveBeenCalled();
|
||||
expect(core.warning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle exact example from issue #256", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
'ruff>=0.14 ; python_version >= "3.11"',
|
||||
);
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.info).toHaveBeenCalledWith(
|
||||
"Found ruff version in requirements file: >=0.14",
|
||||
);
|
||||
expect(core.warning).toHaveBeenCalledWith(
|
||||
"Environment markers are ignored. ruff is a standalone tool that works independently of Python version.",
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle single-quoted environment markers", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
"ruff>=0.14 ; python_version >= '3.11'",
|
||||
);
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.warning).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle double-quoted environment markers", () => {
|
||||
const result = findRuffVersionInSpec(
|
||||
'ruff>=0.14 ; python_version >= "3.11"',
|
||||
);
|
||||
expect(result).toBe(">=0.14");
|
||||
expect(core.warning).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user