Compare commits

..
36 changed files with 589 additions and 7757 deletions
+4 -4
View File
@@ -4,12 +4,12 @@
"owner": "ruff-check",
"pattern": [
{
"code": 4,
"column": 3,
"regexp": "^Error: (.*):(\\d+):(\\d+): (\\w+) (.*)$",
"file": 1,
"line": 2,
"message": 5,
"regexp": "^Error: (.*):(\\d+):(\\d+): (\\w+) (.*)$"
"column": 3,
"code": 4,
"message": 5
}
]
}
+3 -9
View File
@@ -4,15 +4,9 @@
"owner": "ruff-format",
"pattern": [
{
"code": 2,
"column": 5,
"endColumn": 7,
"endLine": 6,
"file": 3,
"line": 4,
"message": 8,
"regexp": "^(?:(error|warning|notice))\\s+title=([^,]+),file=([^,]+),line=(\\d+),col=(\\d+)(?:,endLine=(\\d+))?(?:,endColumn=(\\d+))?::(.+)$",
"severity": 1
"regexp": "^(Would reformat):\\s*(.+)$",
"message": 1,
"file": 2
}
]
}
@@ -1,19 +1,9 @@
import * as fs from "node:fs";
import * as yaml from "js-yaml";
interface WorkflowJob {
needs?: string[];
[key: string]: unknown;
}
interface Workflow {
jobs: Record<string, WorkflowJob>;
[key: string]: unknown;
}
const workflow = yaml.load(
fs.readFileSync("../workflows/test.yml", "utf8"),
) as Workflow;
) as any;
const jobs = Object.keys(workflow.jobs);
const allTestsPassed = workflow.jobs["all-tests-passed"];
const needs: string[] = allTestsPassed.needs || [];
@@ -25,11 +15,6 @@ if (missing.length > 0) {
console.error(
`Missing jobs in all-tests-passed needs: ${missing.join(", ")}`,
);
console.info(
"Please add the missing jobs to the needs section of all-tests-passed in test.yml.",
);
process.exit(1);
}
console.log(
"All jobs in test.yml are in the needs section of all-tests-passed.",
);
console.log("All jobs in test.yml are in the needs section of all-tests-passed.");
+4 -6
View File
@@ -39,13 +39,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
source-root: src
@@ -57,7 +55,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
uses: github/codeql-action/autobuild@v3
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -71,4 +69,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@b20883b0cd1f46c72ae0ba6d1090936928f9fa30 # v4.32.0
uses: github/codeql-action/analyze@v3
+1 -1
View File
@@ -17,6 +17,6 @@ jobs:
pull-requests: read
steps:
- name: 🚀 Run Release Drafter
uses: release-drafter/release-drafter@6db134d15f3909ccc9eefd369f02bd1e9cffdf97 # v6.2.0
uses: release-drafter/release-drafter@v6.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+32 -162
View File
@@ -10,32 +10,23 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
lint:
runs-on: ubuntu-latest
permissions:
security-events: write # for zizmor
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Actionlint
uses: eifinger/actionlint-action@447fbfe7533062b7a9ea55f790f2396fba6d052a # v1.10.0
- name: Run zizmor
uses: zizmorcore/zizmor-action@135698455da5c3b3e55f73f4419e481ab68cdd95 # v0.4.1
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
uses: eifinger/actionlint-action@23c85443d840cd73bbecb9cddfc933cc21649a38 # v1.9.1
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: |
npm ci --ignore-scripts
npm install
- run: |
npm run all
- name: Check all jobs are in all-tests-passed.needs
- name: Transpile scripts
run: |
tsc check-all-tests-passed-needs.ts
node check-all-tests-passed-needs.js
tsc *.ts
working-directory: .github/scripts
- name: Make sure no changes from linters are detected
run: |
@@ -46,9 +37,7 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, macos-14, windows-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use latest version
uses: ./
with:
@@ -61,9 +50,7 @@ jobs:
ruff-version: ["0.1.7", "0.1.8", "0.4.7", "0.4.10", "0.7", "0.7.x", ">=0.7.0"]
os: [ ubuntu-latest, ubuntu-24.04-arm, macos-latest, macos-14, windows-latest ]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use version ${{ matrix.ruff-version }}
uses: ./
with:
@@ -72,9 +59,7 @@ jobs:
test-unsupported-version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Try install old version
id: install
continue-on-error: true
@@ -84,17 +69,13 @@ jobs:
src: __tests__/fixtures/python-project
- name: Check if the action failed
run: |
if [ "${INSTALL_OUTCOME}" == "success" ]; then
if [ ${{ steps.install.outcome }} == "success" ]; then
exit 1
fi
env:
INSTALL_OUTCOME: ${{ steps.install.outcome }}
test-version-from-version-file-pyproject:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use version from pyproject.toml
id: ruff-action
uses: ./
@@ -111,9 +92,7 @@ jobs:
test-default-version-from-pyproject:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version from pyproject.toml
id: ruff-action
uses: ./
@@ -129,9 +108,7 @@ jobs:
test-default-version-from-pyproject-dev-group:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version from pyproject.toml dev group
id: ruff-action
uses: ./
@@ -148,9 +125,7 @@ jobs:
test-default-version-from-pyproject-dependency-groups:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version from pyproject.toml dependency groups
id: ruff-action
uses: ./
@@ -164,52 +139,11 @@ jobs:
fi
env:
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
test-default-version-from-pyproject-dependency-groups-with-env-marker:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Use default version from pyproject.toml with environment marker
id: ruff-action
uses: ./
with:
src: __tests__/fixtures/python-project
version-file: __tests__/fixtures/pyproject-dependency-groups-with-env-marker/pyproject.toml
- name: Correct version gets installed
run: |
if [ "$RUFF_VERSION" != "0.13.3" ]; then
echo "Expected version 0.13.3 but got $RUFF_VERSION"
exit 1
fi
env:
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
test-default-version-from-pyproject-poetry-groups:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version from pyproject.toml poetry group dependencies
id: ruff-action
uses: ./
with:
src: __tests__/fixtures/pyproject-dependency-poetry-grouped-project
version-file: __tests__/fixtures/pyproject-dependency-poetry-grouped-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-poetry:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Use default version from pyproject.toml poetry dependencies
id: ruff-action
uses: ./
with:
@@ -217,7 +151,7 @@ jobs:
version-file: __tests__/fixtures/pyproject-dependency-poetry-project/pyproject.toml
- name: Correct version gets installed
run: |
if [ "$RUFF_VERSION" != "0.8.6" ]; then
if [ "$RUFF_VERSION" != "0.8.3" ]; then
exit 1
fi
env:
@@ -225,9 +159,7 @@ jobs:
test-default-version-from-pyproject-optional-dependencies:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version from pyproject.toml optional dependencies
id: ruff-action
uses: ./
@@ -244,9 +176,7 @@ jobs:
test-default-version-from-requirements:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version from requirements.txt
id: ruff-action
uses: ./
@@ -260,31 +190,10 @@ jobs:
fi
env:
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
test-default-version-from-requirements-with-hash:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Use default version from requirements-with-hash.txt
id: ruff-action
uses: ./
with:
src: __tests__/fixtures/python-project
version-file: __tests__/fixtures/requirements-with-hash.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:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use version 0.7
id: ruff-action
uses: ./
@@ -301,18 +210,16 @@ jobs:
test-pep440-version-specifier:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Install version 0.9.10
- uses: actions/checkout@v4
- name: Install version 0.11.11
id: ruff-action
uses: ./
with:
version: ">=0.9.9,<0.10.0"
version: ">=0.11.10,<0.12.0"
src: __tests__/fixtures/python-project
- name: Correct version gets installed
run: |
if [ "$RUFF_VERSION" != "0.9.10" ]; then
if [ "$RUFF_VERSION" != "0.11.11" ]; then
exit 1
fi
env:
@@ -327,9 +234,7 @@ jobs:
- os: macos-latest
checksum: "af9583bff12afbca5d5670334e0187dd60c4d91bc71317d1b2dde70cb1200ba9"
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Checksum matches expected
uses: ./
with:
@@ -339,9 +244,7 @@ jobs:
test-with-explicit-token:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use default version
uses: ./
with:
@@ -353,9 +256,7 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use args
uses: ./
with:
@@ -364,9 +265,7 @@ jobs:
test-failure:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Format should fail
id: format-should-fail
continue-on-error: true
@@ -376,11 +275,9 @@ jobs:
src: __tests__/fixtures/malformed-python-project
- name: Check if the action failed
run: |
if [ "${FORMAT_SHOULD_FAIL_OUTCOME}" == "success" ]; then
if [ ${{ steps.format-should-fail.outcome }} == "success" ]; then
exit 1
fi
env:
FORMAT_SHOULD_FAIL_OUTCOME: ${{ steps.format-should-fail.outcome }}
- name: Check should fail
id: check-should-fail
continue-on-error: true
@@ -389,20 +286,16 @@ jobs:
src: __tests__/fixtures/malformed-python-project
- name: Check if the action failed
run: |
if [ "${CHECK_SHOULD_FAIL_OUTCOME}" == "success" ]; then
if [ ${{ steps.check-should-fail.outcome }} == "success" ]; then
exit 1
fi
env:
CHECK_SHOULD_FAIL_OUTCOME: ${{ steps.check-should-fail.outcome }}
test-multiple-src:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/checkout@v4
- name: Use args
uses: ./
with:
@@ -410,25 +303,6 @@ jobs:
src: >-
__tests__/fixtures/python-project/src/python_project/__init__.py
__tests__/fixtures/python-project/src/python_project/hello_world.py
test-parent-directory-pyproject:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Use version from parent directory pyproject.toml
id: ruff-action
uses: ./
with:
src: __tests__/fixtures/parent-config-project/subproject
- name: Correct version gets installed
run: |
if [ "$RUFF_VERSION" != "0.10.0" ]; then
echo "Expected version 0.10.0 but got $RUFF_VERSION"
exit 1
fi
env:
RUFF_VERSION: ${{ steps.ruff-action.outputs.ruff-version }}
all-tests-passed:
runs-on: ubuntu-latest
@@ -441,12 +315,9 @@ jobs:
- test-default-version-from-pyproject
- test-default-version-from-pyproject-dev-group
- test-default-version-from-pyproject-dependency-groups
- test-default-version-from-pyproject-dependency-groups-with-env-marker
- test-default-version-from-pyproject-poetry-groups
- test-default-version-from-pyproject-poetry
- test-default-version-from-pyproject-optional-dependencies
- test-default-version-from-requirements
- test-default-version-from-requirements-with-hash
- test-semver-range
- test-pep440-version-specifier
- test-checksum
@@ -454,11 +325,10 @@ jobs:
- test-args
- test-failure
- test-multiple-src
- test-parent-directory-pyproject
if: always()
steps:
- name: All tests passed
run: |
echo "All jobs passed: ${{ !(contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) }}"
echo "All jobs passed: ${{ !contains(needs.*.result, 'failure') }}"
# shellcheck disable=SC2242
exit ${{ (contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')) && 1 || 0 }}
exit ${{ contains(needs.*.result, 'failure') && 1 || 0 }}
+4 -6
View File
@@ -11,10 +11,8 @@ jobs:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Update known checksums
@@ -22,9 +20,9 @@ jobs:
run:
node dist/update-known-checksums/index.js
src/download/checksum/known-checksums.ts ${{ secrets.GITHUB_TOKEN }}
- run: npm ci --ignore-scripts && npm run all
- run: npm install && npm run all
- name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
commit-message: "chore: update known checksums"
title:
@@ -16,9 +16,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: true
- uses: actions/checkout@v4
- name: Update Major Minor Tags
run: |
set -x
-3
View File
@@ -1,3 +0,0 @@
{
"recommendations": ["biomejs.biome"]
}
-16
View File
@@ -1,16 +0,0 @@
{
"editor.codeActionsOnSave": {
"source.action.useSortedAttributes.biome": "explicit",
"source.action.useSortedKeys.biome": "explicit",
"source.fixAll.biome": "explicit"
},
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"explorer.excludeGitIgnore": false,
"search.defaultViewMode": "list",
"search.exclude": {
"**/node_modules": true
},
"typescript.enablePromptUseWorkspaceTsdk": true,
"typescript.tsdk": "node_modules/typescript/lib"
}
@@ -1,13 +0,0 @@
[project]
name = "parent-config-project"
version = "0.1.0"
description = "Test fixture for parent directory pyproject.toml search"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"ruff==0.10.0",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
@@ -1,3 +0,0 @@
"""Hello world example."""
print("Hello, world!")
@@ -1,15 +0,0 @@
[project]
name = "pyproject-dependency-groups-with-env-marker"
version = "0.1.0"
description = "Test fixture for issue #256 - environment markers"
readme = "README.md"
requires-python = ">=3.12"
[dependency-groups]
dev = [
"ruff~=0.13 ; python_version >= '3.11'",
]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
@@ -1,14 +0,0 @@
[project]
name = "pyproject-dependency-poetry-grouped-project"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
[tool.poetry.group.dev.dependencies]
sphinx = "*"
ruff = "0.8.3"
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
build-backend = "poetry.core.masonry.api"
@@ -1,2 +0,0 @@
def hello() -> str:
return "Hello from python-project!"
@@ -5,9 +5,9 @@ description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
[tool.poetry.dependencies]
[tool.poetry.group.dev.dependencies]
sphinx = "*"
ruff = "~0.8.2"
ruff = "0.8.3"
[build-system]
requires = ["poetry-core>=2.0.0,<3.0.0"]
@@ -1,2 +0,0 @@
ruff==0.9.0 \
--hash=sha256:badc0de
+13 -27
View File
@@ -1,35 +1,20 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.2/schema.json",
"assist": {
"actions": {
"source": {
"organizeImports": "on",
"useSortedAttributes": "on",
"useSortedKeys": "on"
}
}
"$schema": "https://biomejs.dev/schemas/1.9.2/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"includes": [
"**",
"!**/coverage",
"!**/dist",
"!**/lib",
"!**/node_modules",
"!**/package*.json",
"!**/known-checksums.*"
]
"ignore": ["dist", "lib", "node_modules"]
},
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"trailingCommas": "all"
}
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
@@ -37,9 +22,10 @@
"recommended": true
}
},
"vcs": {
"clientKind": "git",
"enabled": true,
"useIgnoreFile": false
"javascript": {
"formatter": {
"quoteStyle": "double",
"trailingCommas": "all"
}
}
}
Generated Vendored
+224 -987
View File
File diff suppressed because it is too large Load Diff
+94 -724
View File
File diff suppressed because it is too large Load Diff
-12
View File
@@ -1,12 +0,0 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
collectCoverageFrom: ["src/**/*.ts", "!src/**/*.d.ts"],
moduleFileExtensions: ["ts", "js"],
preset: "ts-jest",
roots: ["<rootDir>/src"],
testEnvironment: "node",
testMatch: ["**/*.test.ts"],
transform: {
"^.+\\.ts$": "ts-jest",
},
};
+138 -4023
View File
File diff suppressed because it is too large Load Diff
+14 -21
View File
@@ -6,45 +6,38 @@
"main": "dist/ruff-action/index.js",
"scripts": {
"build": "tsc",
"check": "biome check --write",
"format": "biome format --fix",
"format-check": "biome format",
"lint": "biome lint --fix",
"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)\"",
"test": "jest",
"all": "npm ci --ignore-scripts && npm run build && npm run check && npm run test && npm run package"
"all": "npm install && npm run build && npm run format && npm run lint && npm run package"
},
"repository": {
"type": "git",
"url": "git+https://github.com/astral-sh/ruff-action.git"
},
"keywords": [
"actions",
"python",
"ruff",
"action"
],
"keywords": ["actions", "python", "ruff", "action"],
"author": "@eifinger",
"license": "Apache-2.0",
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/tool-cache": "^2.0.2",
"@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": "^13.1.1",
"@octokit/plugin-rest-endpoint-methods": "^16.0.0",
"@renovatebot/pep440": "^4.2.1",
"smol-toml": "^1.6.0"
"@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": {
"@biomejs/biome": "2.3.2",
"@types/jest": "^29.5.14",
"@biomejs/biome": "1.9.4",
"@types/js-yaml": "^4.0.9",
"@types/node": "^24.10.9",
"@types/semver": "^7.7.1",
"@types/node": "^22.13.10",
"@types/semver": "^7.5.8",
"@vercel/ncc": "^0.38.3",
"jest": "^29.7.0",
"js-yaml": "^4.1.0",
"ts-jest": "^29.2.5",
"typescript": "^5.9.2"
"typescript": "^5.8.2"
}
}
+3 -3
View File
@@ -1,9 +1,9 @@
import * as crypto from "node:crypto";
import * as fs from "node:fs";
import * as crypto from "node:crypto";
import * as core from "@actions/core";
import type { Architecture, Platform } from "../../utils/platforms";
import { KNOWN_CHECKSUMS } from "./known-checksums";
import type { Architecture, Platform } from "../../utils/platforms";
export async function validateChecksum(
checkSum: string | undefined,
@@ -12,7 +12,7 @@ export async function validateChecksum(
platform: Platform,
version: string,
): Promise<void> {
let isValid: boolean | undefined;
let isValid: boolean | undefined = undefined;
if (checkSum !== undefined && checkSum !== "") {
isValid = await validateFileCheckSum(downloadPath, checkSum);
} else {
File diff suppressed because it is too large Load Diff
+8 -17
View File
@@ -1,15 +1,15 @@
import { promises as fs } from "node:fs";
import * as path from "node:path";
import * as core from "@actions/core";
import * as tc from "@actions/tool-cache";
import { Octokit } from "@octokit/core";
import { paginateRest } from "@octokit/plugin-paginate-rest";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
import * as pep440 from "@renovatebot/pep440";
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";
import { Octokit } from "@octokit/core";
import { paginateRest } from "@octokit/plugin-paginate-rest";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
const PaginatingOctokit = Octokit.plugin(paginateRest, restEndpointMethods);
@@ -25,7 +25,7 @@ export function tryGetFromToolCache(
resolvedVersion = version;
}
const installedPath = tc.find(TOOL_CACHE_NAME, resolvedVersion, arch);
return { installedPath, version: resolvedVersion };
return { version: resolvedVersion, installedPath };
}
export async function downloadVersion(
@@ -65,7 +65,7 @@ export async function downloadVersion(
version,
arch,
);
return { cachedToolDir, version: version };
return { version: version, cachedToolDir };
}
function constructDownloadUrl(
@@ -158,12 +158,6 @@ async function getReleaseTagNames(
owner: OWNER,
repo: REPO,
});
const releaseTagNames = response.map((release) => release.tag_name);
if (releaseTagNames.length === 0) {
throw Error(
"Github API request failed while getting releases. Check the GitHub status page for outages. Try again later.",
);
}
return response.map((release) => release.tag_name);
}
@@ -183,9 +177,6 @@ async function getLatestVersion(githubToken: string) {
const octokit = new PaginatingOctokit();
latestRelease = await getLatestRelease(octokit);
} else {
core.error(
"Github API request failed while getting latest release. Check the GitHub status page for outages. Try again later.",
);
throw err;
}
}
+14 -16
View File
@@ -1,12 +1,18 @@
import * as path from "node:path";
import * as core from "@actions/core";
import * as exec from "@actions/exec";
import * as semver from "semver";
import * as path from "node:path";
import {
downloadVersion,
resolveVersion,
tryGetFromToolCache,
} from "./download/download-version";
import {
type Architecture,
getArch,
getPlatform,
type Platform,
} from "./utils/platforms";
import {
args,
checkSum,
@@ -15,14 +21,9 @@ import {
version,
versionFile as versionFileInput,
} from "./utils/inputs";
import {
type Architecture,
getArch,
getPlatform,
type Platform,
} from "./utils/platforms";
import { getRuffVersionFromRequirementsFile } from "./utils/pyproject";
import { findPyprojectToml } from "./utils/pyproject-finder";
import * as fs from "node:fs";
import * as semver from "semver";
async function run(): Promise<void> {
const platform = getPlatform();
@@ -107,18 +108,15 @@ async function determineVersion(): Promise<string> {
}
return await resolveVersion(versionFromPyproject || "latest", githubToken);
}
const pyProjectPath = findPyprojectToml(
src,
process.env.GITHUB_WORKSPACE || ".",
);
if (!pyProjectPath) {
core.info(`Could not find pyproject.toml. Using latest version.`);
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 =
getRuffVersionFromRequirementsFile(pyProjectPath);
if (versionFromPyproject === undefined) {
core.info(
core.warning(
`Could not parse version from ${pyProjectPath}. Using latest version.`,
);
}
+5 -3
View File
@@ -1,10 +1,12 @@
import * as core from "@actions/core";
import { Octokit } from "@octokit/core";
import * as core from "@actions/core";
import { paginateRest } from "@octokit/plugin-paginate-rest";
import { restEndpointMethods } from "@octokit/plugin-rest-endpoint-methods";
import * as semver from "semver";
import { updateChecksums } from "./download/checksum/update-known-checksums";
import { OWNER, REPO } from "./utils/constants";
import * as semver from "semver";
import { updateChecksums } from "./download/checksum/update-known-checksums";
const PaginatingOctokit = Octokit.plugin(paginateRest, restEndpointMethods);
+2 -2
View File
@@ -9,9 +9,9 @@ export type Architecture = "i686" | "x86_64" | "aarch64";
export function getArch(): Architecture | undefined {
const arch = process.arch;
const archMapping: { [key: string]: Architecture } = {
arm64: "aarch64",
ia32: "i686",
x64: "x86_64",
arm64: "aarch64",
};
if (arch in archMapping) {
@@ -22,8 +22,8 @@ export function getArch(): Architecture | undefined {
export function getPlatform(): Platform | undefined {
const platform = process.platform;
const platformMapping: { [key: string]: Platform } = {
darwin: "apple-darwin",
linux: "unknown-linux-gnu",
darwin: "apple-darwin",
win32: "pc-windows-msvc",
};
-183
View File
@@ -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");
});
});
});
-79
View File
@@ -1,79 +0,0 @@
import * as fs from "node:fs";
import * as path from "node:path";
import * as core from "@actions/core";
/**
* Search for a pyproject.toml file starting from the given directory
* and traversing upwards through parent directories until reaching
* the GitHub workspace root.
*
* @param startDir The directory to start the search from (e.g., the src input)
* @param workspaceRoot The GitHub workspace directory (GITHUB_WORKSPACE)
* @returns The path to the found pyproject.toml, or undefined if not found
*/
export function findPyprojectToml(
startDir: string,
workspaceRoot: string,
): string | undefined {
let currentDir = path.resolve(startDir);
const resolvedWorkspaceRoot = path.resolve(workspaceRoot);
while (true) {
const pyprojectPath = path.join(currentDir, "pyproject.toml");
core.debug(`Checking for ${pyprojectPath}`);
if (fs.existsSync(pyprojectPath)) {
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;
}
// 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;
}
currentDir = parentDir;
// If we've gone past the workspace root, stop searching
if (isPathWithinWorkspace(currentDir, resolvedWorkspaceRoot) === false) {
break;
}
}
return undefined;
}
/**
* Check if a given path is within or equal to the workspace root.
*
* @param checkPath The path to check
* @param workspaceRoot The workspace root directory
* @returns true if within or equal to workspace, false if outside, undefined if can't determine
*/
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;
}
}
-188
View File
@@ -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();
});
});
});
+18 -58
View File
@@ -2,58 +2,25 @@ import * as fs from "node:fs";
import * as core from "@actions/core";
import * as toml from "smol-toml";
/**
* Find ruff version in a dependency specification.
* Only handles strings that start with "ruff" (e.g., "ruff==0.9.3").
* Returns undefined for non-ruff dependencies.
* Strips environment markers (everything after ';').
* Strips leading '==' from exact version specifiers (PEP 440) for downstream compatibility.
*
* @internal This is exported for testing purposes only.
*/
export function findRuffVersionInSpec(spec: string): string | undefined {
const trimmedSpec = spec.trim();
const fullDepMatch = trimmedSpec.match(/^ruff\s*(.+)$/);
let versionSpec: string;
if (fullDepMatch) {
versionSpec = fullDepMatch[1];
} else {
return undefined;
}
// Strip trailing backslash (line continuation)
versionSpec = versionSpec.replace(/\\$/, "").trim();
// Strip environment markers (everything after ';')
const match = versionSpec.match(/^([^;]+)(?:;.*)?$/);
if (match) {
let version = match[1].trim();
if (version) {
// Strip leading '==' from exact version specifiers for compatibility with semver
if (version.startsWith("==")) {
version = version.slice(2);
}
if (trimmedSpec.includes(";")) {
core.warning(
"Environment markers are ignored. ruff is a standalone tool that works independently of Python version.",
);
}
core.info(`Found ruff version in requirements file: ${version}`);
return version;
}
}
return undefined;
}
function getRuffVersionFromAllDependencies(
allDependencies: string[],
): string | undefined {
return allDependencies
.map((dep) => findRuffVersionInSpec(dep))
.find((version) => version !== undefined);
const ruffVersionDefinition = allDependencies.find((dep: string) =>
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;
}
interface Pyproject {
@@ -64,7 +31,6 @@ interface Pyproject {
"dependency-groups"?: Record<string, Array<string | object>>;
tool?: {
poetry?: {
dependencies?: Record<string, string | object>;
group?: Record<string, { dependencies: Record<string, string | object> }>;
};
};
@@ -93,17 +59,11 @@ function getRuffVersionFromPoetryGroups(
): string | undefined {
// Special handling for Poetry until it supports PEP 735
// See: <https://github.com/python-poetry/poetry/issues/9751>
const poetry = pyproject?.tool?.poetry || {};
const poetryGroups = Object.values(poetry.group || {});
if (poetry.dependencies) {
poetryGroups.unshift({ dependencies: poetry.dependencies });
}
const poetryGroups = Object.values(pyproject?.tool?.poetry?.group || {});
return poetryGroups
.flatMap((group) => Object.entries(group.dependencies))
.map(([name, spec]) => {
if (typeof spec === "string") {
return findRuffVersionInSpec(`${name} ${spec}`);
}
if (name === "ruff" && typeof spec === "string") return spec;
return undefined;
})
.find((version) => version !== undefined);
+3 -3
View File
@@ -1,12 +1,12 @@
{
"compilerOptions": {
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"target": "ES2022" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"outDir": "./lib" /* Redirect output structure to the directory. */,
"rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
"strict": true /* Enable all strict type-checking options. */,
"target": "ES2022" /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"exclude": ["node_modules", "**/*.test.ts"]
}