Files
renovate/.oxlintrc.json
Jamie Tanna 134dc6cd38 chore(lint): add oxlint rule to block dev-dependency imports in production code (#45851)
As we've recently had a couple of cases where a `devDependency` has been
used in a production file, and CI hasn't caught it, we end up seeing
i.e.

    ERROR: unhandledRejection
           "err": {
             "code": "ERR_MODULE_NOT_FOUND",
             "message": "Cannot find package 'common-tags' imported from
                         /usr/local/renovate/dist/workers/repository/update/pr/index.js"
             }

(see 5ee51fdf39 and
1d33143727 for two cases this has happened
with)

One option for caching this is a linting rule, which stops runtime usage
in `lib/` on a dependency in `devDependencies`.

Co-authored-by: Claude Sonnet 5 <jamie.tanna+claude-code@mend.io>
2026-09-10 14:59:09 +00:00

426 lines
13 KiB
JSON

{
"$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
"plugins": ["import", "node", "promise", "unicorn", "typescript", "vitest"],
"jsPlugins": ["./tools/lint/rules.ts"],
"options": {
"typeAware": true
},
"env": {
"node": true,
"es2025": true
},
"categories": {
"correctness": "error"
},
"rules": {
"eqeqeq": "error",
"no-console": "error",
"no-param-reassign": "error",
"no-negated-condition": "error",
"no-template-curly-in-string": "error",
"curly": "error",
"radix": ["error"],
"import/extensions": ["error", "always", { "ignorePackages": true }],
"import/no-cycle": "error",
"promise/catch-or-return": "error",
"promise/no-callback-in-promise": "warn",
"promise/no-new-statics": "error",
"promise/no-return-in-finally": "error",
"promise/valid-params": "warn",
"import/default": "error",
"import/export": "error",
"import/named": "error",
"import/namespace": "error",
"typescript/consistent-type-imports": [
"error",
{
"disallowTypeAnnotations": false
}
],
"no-restricted-imports": [
"error",
{
"paths": [
"nock",
"parse-link-header",
"path",
{
"name": "simple-git",
"importNames": ["simpleGit"],
"message": "Use createSimpleGit instead of simpleGit."
},
{
"name": "zod",
"message": "Use zod/v4 instead of the bare zod package."
},
{
"name": "zod/v3",
"message": "Use zod/v4 instead of the zod/v3 compatibility shim."
}
]
}
],
"no-unused-vars": [
"error",
{
"vars": "all",
"args": "none",
"ignoreRestSiblings": true
}
],
"no-unassigned-vars": "error",
"no-undef": "error",
"prefer-template": "error",
"prefer-arrow-callback": ["error", { "allowUnboundThis": false }],
"func-style": ["error", "declaration"],
"no-nested-ternary": "error",
"no-else-return": ["error", { "allowElseIf": false }],
"unicorn/no-lonely-if": "error",
"renovate/enforce-ts-extension": "error",
"renovate/no-number-constructor": "error",
"renovate/prefer-json-pipe": "error",
"renovate/prefer-nullish-util": "error",
"renovate/require-regex-util": "error",
"renovate/v8-ignore-no-count": "error",
"renovate/v8-ignore-reason": "error",
"renovate/validate-config-warnings-and-errors": "error",
"renovate/zod-schema-naming": "error",
"typescript/await-thenable": "error",
"typescript/no-floating-promises": "error",
"typescript/no-misused-promises": "error",
"typescript/no-misused-spread": "error",
"typescript/no-unsafe-enum-comparison": "error",
"typescript/no-unsafe-unary-minus": "error",
"typescript/no-duplicate-type-constituents": "error",
"typescript/no-redundant-type-constituents": "error",
"typescript/prefer-promise-reject-errors": "error",
"typescript/no-array-delete": "error",
"typescript/no-base-to-string": "error",
"typescript/no-for-in-array": "error",
"typescript/no-implied-eval": "error",
"typescript/no-unnecessary-type-arguments": "error",
"typescript/no-unnecessary-type-assertion": "error",
"typescript/only-throw-error": "error",
"typescript/restrict-plus-operands": "error",
"typescript/restrict-template-expressions": [
"error",
{ "allowNumber": true, "allowBoolean": true }
],
"typescript/unbound-method": ["error", { "ignoreStatic": true }],
"typescript/require-await": "error",
"typescript/explicit-function-return-type": [
"error",
{
"allowExpressions": true,
"allowTypedFunctionExpressions": true
}
],
"typescript/no-empty-object-type": [
"error",
{
"allowInterfaces": "with-single-extends"
}
],
"typescript/dot-notation": "error",
"typescript/non-nullable-type-assertion-style": "error",
"typescript/prefer-find": "error",
"typescript/prefer-includes": "error",
"typescript/prefer-nullish-coalescing": "error",
"typescript/prefer-optional-chain": "error",
"typescript/prefer-regexp-exec": "error",
"typescript/prefer-string-starts-ends-with": "error",
"typescript/no-unsafe-argument": "off",
"typescript/no-unsafe-assignment": "off",
"typescript/no-unsafe-call": "off",
"typescript/no-unsafe-member-access": "off",
"typescript/no-unsafe-return": "off",
"vitest/no-conditional-tests": "error",
"vitest/hoisted-apis-on-top": "error",
"typescript/adjacent-overload-signatures": "error",
"typescript/array-type": "error",
"typescript/ban-tslint-comment": "error",
"typescript/class-literal-property-style": "error",
"typescript/consistent-generic-constructors": "error",
"typescript/consistent-indexed-object-style": "error",
"typescript/consistent-type-assertions": [
"error",
{
"assertionStyle": "as",
"objectLiteralTypeAssertions": "allow"
}
],
"no-empty-function": "error",
"typescript/no-inferrable-types": "error",
"typescript/prefer-for-of": "error",
"typescript/prefer-function-type": "error",
"no-case-declarations": "error",
"no-empty": "error",
"no-fallthrough": "error",
"no-prototype-builtins": "error",
"no-regex-spaces": "error",
"no-var": "error",
"prefer-const": "error",
"prefer-named-capture-group": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"typescript/ban-ts-comment": "error",
"typescript/consistent-type-definitions": "error",
"typescript/no-array-constructor": "error",
"typescript/no-confusing-non-null-assertion": "error",
"typescript/no-namespace": "error",
"typescript/no-require-imports": "error",
"typescript/no-unnecessary-type-constraint": "error",
"typescript/no-unsafe-function-type": "error",
"unicorn/no-useless-iterator-to-array": "error",
"unicorn/prefer-at": "error",
"unicorn/prefer-node-protocol": "error",
"typescript/no-useless-default-assignment": "error",
"vitest/require-mock-type-parameters": "off",
"vitest/expect-expect": [
"error",
{ "assertFunctionNames": ["expect", "expectTypeOf", "checkKeysSorted"] }
],
"vitest/no-conditional-expect": "error",
"vitest/no-restricted-matchers": [
"error",
{
"toMatchSnapshot": "Use explicit assertions such as toEqual, toMatchObject or toBe so the expected value stays visible in the test file.",
"toThrowErrorMatchingSnapshot": "Use toThrow with the expected message.",
"rejects.toThrowErrorMatchingSnapshot": "Use rejects.toThrow with the expected message.",
"resolves.toMatchSnapshot": "Use explicit assertions such as resolves.toEqual or resolves.toMatchObject so the expected value stays visible in the test file.",
"toMatchFileSnapshot": "Use explicit assertions such as toEqual, toMatchObject or toBe so the expected value stays visible in the test file."
}
],
"vitest/no-standalone-expect": "error",
"vitest/prefer-expect-resolves": "error",
"vitest/prefer-snapshot-hint": "error",
"vitest/require-to-throw-message": "error"
},
"overrides": [
{
"files": ["**/*.spec.ts", "test/**", "tools/**"],
"rules": {
"renovate/require-regex-util": "off"
}
},
{
"files": ["tools/**", "**/*.spec.ts"],
"rules": {
"node/no-sync": "error"
}
},
{
"files": ["lib/**"],
"rules": {
"renovate/logger-err-key": "error",
"renovate/logger-static-message": "error",
"renovate/no-new-url": "error",
"renovate/no-stateful-global-regex": "error",
"renovate/no-tools-import": "error",
"renovate/prefer-coerce-array": "error",
"renovate/prefer-coerce-object": "error",
"renovate/prefer-is-helpers": "error",
"renovate/prefer-is-object": "error"
}
},
{
"files": ["lib/**"],
"excludeFiles": ["**/*.spec.ts"],
"rules": {
"renovate/no-dev-dependency-import": "error",
"renovate/no-exec-shell-option": "error",
"renovate/no-hardcoded-docs-url": "error",
"renovate/no-unquoted-exec-interpolation": "error",
"renovate/prefer-fs-util": "error",
"renovate/prefer-luxon": "error"
}
},
{
"files": ["lib/modules/datasource/**"],
"excludeFiles": ["**/*.spec.ts"],
"rules": {
"renovate/no-unvalidated-pagination-url": "error"
}
},
{
"files": ["lib/modules/**"],
"excludeFiles": ["**/*.spec.ts", "**/schema.ts", "**/schema/**"],
"rules": {
"renovate/zod-schema-location": "error"
}
},
{
"files": ["lib/modules/**"],
"excludeFiles": ["**/*.spec.ts", "**/schema.ts", "**/schema/**"],
"rules": {
"renovate/types-location": "error"
}
},
{
"files": ["lib/util/url.ts"],
"rules": {
"renovate/no-new-url": "off"
}
},
{
"files": ["lib/util/exec/**"],
"rules": {
"renovate/no-exec-shell-option": "off"
}
},
{
"files": ["lib/config/options/index.ts"],
"rules": {
"renovate/no-hardcoded-docs-url": "off"
}
},
{
"files": [
"lib/config-validator.ts",
"lib/instrumentation/**",
"lib/logger/**",
"lib/util/fs/**",
"lib/util/git/**",
"lib/workers/global/**"
],
"rules": {
"renovate/prefer-fs-util": "off"
}
},
{
"files": [
"lib/util/date.ts",
"lib/util/pretty-time.ts",
"lib/util/timestamp.ts"
],
"rules": {
"renovate/prefer-luxon": "off"
}
},
{
"files": ["**/*.spec.ts", "test/**"],
"env": {
"vitest": true
},
"globals": {
"fixtures": "readonly"
},
"rules": {
"no-template-curly-in-string": "off",
"jest/valid-title": "error",
"vitest/consistent-test-it": ["error", { "fn": "it" }],
"typescript/unbound-method": "off",
"renovate/no-host-rules-mock": "error",
"renovate/logger-static-message": "off",
"renovate/codeblock-in-spec-fixtures": "error",
"renovate/inline-single-use-fixtures": "error",
"renovate/no-redundant-mock-reset": "error",
"renovate/prefer-fake-sha-in-specs": "error",
"renovate/prefer-nullish-util": "off",
"renovate/prefer-partial-in-specs": "error",
"renovate/prefer-stub-env": "error",
"renovate/test-root-describe": "error",
"typescript/explicit-function-return-type": "off"
}
},
{
"files": [
"*.config.cjs",
"*.config.cts",
"*.config.js",
"*.config.mjs",
"*.config.mts",
"*.config.ts",
"tools/**/*.cjs",
"tools/**/*.cts",
"tools/**/*.js",
"tools/**/*.mjs",
"tools/**/*.mts",
"tools/**/*.ts"
],
"rules": {
"no-console": "off"
}
},
{
"files": [
"lib/config/presets/internal/index.ts",
"lib/config/presets/internal/*.preset.ts"
],
"rules": {
"sort-keys": [
"error",
"asc",
{ "caseSensitive": false, "natural": true }
]
}
},
{
"files": ["tools/docs/test/**/*.mjs"],
"rules": {
"typescript/no-floating-promises": "off"
}
},
{
"files": ["**/*.js", "**/*.mjs", "**/*.cjs"],
"rules": {
"typescript/restrict-template-expressions": "off",
"typescript/explicit-function-return-type": "off",
"renovate/enforce-ts-extension": "off"
}
},
{
"files": [
"lib/util/git/index.ts",
"tools/**/*.mjs",
"tools/**/*.ts",
"lib/**/*.spec.ts"
],
"rules": {
"no-restricted-imports": [
"error",
{
"paths": ["nock", "parse-link-header", "path"]
}
]
}
}
],
"ignorePatterns": [
"**/node_modules",
"**/.pnpm-store",
"**/dist",
"**/coverage",
"**/__fixtures__/**/*",
"**/__mocks__/**/*",
"**/*.d.ts",
"config.js",
"**/.clinic/",
"**/.cache/",
"**/*.generated.ts",
"tools/dist",
"patches",
"**/tmp/",
"**/.venv/",
"tools/mkdocs/docs",
"tools/mkdocs/site",
".worktrees/**/*",
".markdownlint-cli2.mjs",
"tools/mkdocs/.cache",
"**/.agents/**",
"**/.claude/**",
"**/.opencode/**",
"**/AGENTS.md",
"**/CLAUDE.md"
]
}