@verekia/warden 0.0.0 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +7 -3
- package/src/checks/ci-workflow.ts +58 -0
- package/src/checks/config-files-present.ts +3 -2
- package/src/checks/exact-dependency-versions.ts +7 -2
- package/src/checks/matching-dependency-versions.ts +2 -2
- package/src/checks/next-config.ts +3 -3
- package/src/checks/portless-next-dev.ts +2 -2
- package/src/checks/required-scripts.ts +7 -2
- package/src/checks/tailwind-oxfmt-config.ts +1 -1
- package/src/checks/test-script-consistency.ts +12 -6
- package/src/checks/typecheck-script.ts +1 -1
- package/src/checks/warden-script.ts +7 -4
- package/src/config.ts +1 -4
- package/src/index.ts +26 -20
- package/src/types.ts +18 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verekia/warden",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Linter that checks repositories share consistent configs and tool versions.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"warden": "./src/index.ts"
|
|
@@ -41,8 +41,7 @@
|
|
|
41
41
|
"enabled": true,
|
|
42
42
|
"files": [
|
|
43
43
|
".oxfmtrc.json",
|
|
44
|
-
".oxlintrc.json"
|
|
45
|
-
".github/workflows/ci.yml"
|
|
44
|
+
".oxlintrc.json"
|
|
46
45
|
]
|
|
47
46
|
},
|
|
48
47
|
"matchingDependencyVersions": {
|
|
@@ -102,6 +101,11 @@
|
|
|
102
101
|
"wardenScript": {
|
|
103
102
|
"enabled": true,
|
|
104
103
|
"package": "@verekia/warden"
|
|
104
|
+
},
|
|
105
|
+
"ciWorkflow": {
|
|
106
|
+
"enabled": true,
|
|
107
|
+
"file": ".github/workflows/ci.yml",
|
|
108
|
+
"runs": "bun run all"
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
111
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { CheckResult, Project, WardenConfig } from '../types.ts'
|
|
2
|
+
|
|
3
|
+
type Step = { run?: unknown }
|
|
4
|
+
type Job = { steps?: unknown }
|
|
5
|
+
type Workflow = { jobs?: Record<string, unknown> }
|
|
6
|
+
|
|
7
|
+
const DEFAULT_FILE = '.github/workflows/ci.yml'
|
|
8
|
+
const DEFAULT_RUNS = 'bun run all'
|
|
9
|
+
|
|
10
|
+
const collectRunCommands = (workflow: Workflow): string[] => {
|
|
11
|
+
const commands: string[] = []
|
|
12
|
+
for (const job of Object.values(workflow.jobs ?? {})) {
|
|
13
|
+
const steps = (job as Job)?.steps
|
|
14
|
+
if (!Array.isArray(steps)) continue
|
|
15
|
+
for (const step of steps as Step[]) {
|
|
16
|
+
if (typeof step?.run === 'string') commands.push(step.run)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return commands
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const ciWorkflow = async (
|
|
23
|
+
projects: Project[],
|
|
24
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['ciWorkflow']>,
|
|
25
|
+
): Promise<CheckResult> => {
|
|
26
|
+
const messages: string[] = []
|
|
27
|
+
let passed = true
|
|
28
|
+
|
|
29
|
+
const file = options.file ?? DEFAULT_FILE
|
|
30
|
+
const runs = options.runs ?? DEFAULT_RUNS
|
|
31
|
+
|
|
32
|
+
for (const project of projects) {
|
|
33
|
+
const handle = Bun.file(`${project.path}/${file}`)
|
|
34
|
+
if (!(await handle.exists())) {
|
|
35
|
+
passed = false
|
|
36
|
+
messages.push(`${project.name}: missing ${file}`)
|
|
37
|
+
continue
|
|
38
|
+
}
|
|
39
|
+
if (!runs) continue
|
|
40
|
+
|
|
41
|
+
let workflow: Workflow
|
|
42
|
+
try {
|
|
43
|
+
workflow = Bun.YAML.parse(await handle.text()) as Workflow
|
|
44
|
+
} catch (err) {
|
|
45
|
+
passed = false
|
|
46
|
+
messages.push(`${project.name}: ${file} is not valid YAML (${(err as Error).message})`)
|
|
47
|
+
continue
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const commands = collectRunCommands(workflow)
|
|
51
|
+
if (!commands.some(cmd => cmd.includes(runs))) {
|
|
52
|
+
passed = false
|
|
53
|
+
messages.push(`${project.name}: ${file} has no step running ${JSON.stringify(runs)}`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return { name: 'ciWorkflow', passed, messages }
|
|
58
|
+
}
|
|
@@ -2,13 +2,14 @@ import type { CheckResult, Project, WardenConfig } from '../types.ts'
|
|
|
2
2
|
|
|
3
3
|
export const configFilesPresent = async (
|
|
4
4
|
projects: Project[],
|
|
5
|
-
options: NonNullable<WardenConfig['checks']['configFilesPresent']>,
|
|
5
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['configFilesPresent']>,
|
|
6
6
|
): Promise<CheckResult> => {
|
|
7
7
|
const messages: string[] = []
|
|
8
8
|
let passed = true
|
|
9
9
|
|
|
10
|
+
const files = options.files ?? []
|
|
10
11
|
for (const project of projects) {
|
|
11
|
-
for (const file of
|
|
12
|
+
for (const file of files) {
|
|
12
13
|
const exists = await Bun.file(`${project.path}/${file}`).exists()
|
|
13
14
|
if (!exists) {
|
|
14
15
|
passed = false
|
|
@@ -7,18 +7,23 @@ const EXACT_SEMVER = /^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/
|
|
|
7
7
|
|
|
8
8
|
export const exactDependencyVersions = (
|
|
9
9
|
projects: Project[],
|
|
10
|
-
options: NonNullable<WardenConfig['checks']['exactDependencyVersions']>,
|
|
10
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['exactDependencyVersions']>,
|
|
11
11
|
): CheckResult => {
|
|
12
12
|
const messages: string[] = []
|
|
13
13
|
let passed = true
|
|
14
14
|
|
|
15
|
+
const packages = Object.entries(options.packages ?? {})
|
|
16
|
+
if (packages.length === 0) {
|
|
17
|
+
return { name: 'exactDependencyVersions', passed, messages }
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
for (const project of projects) {
|
|
16
21
|
if (!project.packageJson) {
|
|
17
22
|
passed = false
|
|
18
23
|
messages.push(`${project.name}: no package.json`)
|
|
19
24
|
continue
|
|
20
25
|
}
|
|
21
|
-
for (const [name, expected] of
|
|
26
|
+
for (const [name, expected] of packages) {
|
|
22
27
|
const declared = findVersion(project.packageJson, name)
|
|
23
28
|
if (declared === undefined) {
|
|
24
29
|
passed = false
|
|
@@ -5,12 +5,12 @@ const findVersion = (pkg: PackageJson, name: string): string | undefined =>
|
|
|
5
5
|
|
|
6
6
|
export const matchingDependencyVersions = (
|
|
7
7
|
projects: Project[],
|
|
8
|
-
options: NonNullable<WardenConfig['checks']['matchingDependencyVersions']>,
|
|
8
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['matchingDependencyVersions']>,
|
|
9
9
|
): CheckResult => {
|
|
10
10
|
const messages: string[] = []
|
|
11
11
|
let passed = true
|
|
12
12
|
|
|
13
|
-
for (const packageName of options.packages) {
|
|
13
|
+
for (const packageName of options.packages ?? []) {
|
|
14
14
|
const versionToProjects = new Map<string, string[]>()
|
|
15
15
|
const missing: string[] = []
|
|
16
16
|
|
|
@@ -66,7 +66,7 @@ const loadConfigObject = async (absPath: string): Promise<Record<string, unknown
|
|
|
66
66
|
|
|
67
67
|
export const nextConfig = async (
|
|
68
68
|
projects: Project[],
|
|
69
|
-
options: NonNullable<WardenConfig['checks']['nextConfig']>,
|
|
69
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['nextConfig']>,
|
|
70
70
|
): Promise<CheckResult> => {
|
|
71
71
|
const messages: string[] = []
|
|
72
72
|
let passed = true
|
|
@@ -106,7 +106,7 @@ export const nextConfig = async (
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
if (cfg) {
|
|
109
|
-
for (const [key, expected] of Object.entries(options.options)) {
|
|
109
|
+
for (const [key, expected] of Object.entries(options.options ?? {})) {
|
|
110
110
|
if (!equal(cfg[key], expected)) {
|
|
111
111
|
passed = false
|
|
112
112
|
const actual = key in cfg ? JSON.stringify(cfg[key]) : 'missing'
|
|
@@ -118,7 +118,7 @@ export const nextConfig = async (
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
for (const [name, expected] of Object.entries(options.devDependencies)) {
|
|
121
|
+
for (const [name, expected] of Object.entries(options.devDependencies ?? {})) {
|
|
122
122
|
const declared = pkg.devDependencies?.[name]
|
|
123
123
|
if (declared !== expected) {
|
|
124
124
|
const actual = declared === undefined ? 'missing' : JSON.stringify(declared)
|
|
@@ -43,7 +43,7 @@ const collectPackageJsons = async (project: Project): Promise<Array<{ relPath: s
|
|
|
43
43
|
|
|
44
44
|
export const portlessNextDev = async (
|
|
45
45
|
projects: Project[],
|
|
46
|
-
options: NonNullable<WardenConfig['checks']['portlessNextDev']>,
|
|
46
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['portlessNextDev']>,
|
|
47
47
|
): Promise<CheckResult> => {
|
|
48
48
|
const messages: string[] = []
|
|
49
49
|
let passed = true
|
|
@@ -66,7 +66,7 @@ export const portlessNextDev = async (
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
if (usesNextDev) {
|
|
69
|
+
if (usesNextDev && options.version !== undefined) {
|
|
70
70
|
const declared = pkg.devDependencies?.portless
|
|
71
71
|
if (declared !== options.version) {
|
|
72
72
|
const actual = declared === undefined ? 'missing' : JSON.stringify(declared)
|
|
@@ -2,11 +2,16 @@ import type { CheckResult, Project, WardenConfig } from '../types.ts'
|
|
|
2
2
|
|
|
3
3
|
export const requiredScripts = (
|
|
4
4
|
projects: Project[],
|
|
5
|
-
options: NonNullable<WardenConfig['checks']['requiredScripts']>,
|
|
5
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['requiredScripts']>,
|
|
6
6
|
): CheckResult => {
|
|
7
7
|
const messages: string[] = []
|
|
8
8
|
let passed = true
|
|
9
9
|
|
|
10
|
+
const required = Object.entries(options.scripts ?? {})
|
|
11
|
+
if (required.length === 0) {
|
|
12
|
+
return { name: 'requiredScripts', passed, messages }
|
|
13
|
+
}
|
|
14
|
+
|
|
10
15
|
for (const project of projects) {
|
|
11
16
|
const scripts = project.packageJson?.scripts
|
|
12
17
|
if (!scripts) {
|
|
@@ -14,7 +19,7 @@ export const requiredScripts = (
|
|
|
14
19
|
messages.push(`${project.name}: no "scripts" in package.json`)
|
|
15
20
|
continue
|
|
16
21
|
}
|
|
17
|
-
for (const [name, expected] of
|
|
22
|
+
for (const [name, expected] of required) {
|
|
18
23
|
const actual = scripts[name]
|
|
19
24
|
if (actual === undefined) {
|
|
20
25
|
passed = false
|
|
@@ -11,7 +11,7 @@ const dependsOnTailwind = (pkg: PackageJson): boolean =>
|
|
|
11
11
|
|
|
12
12
|
export const tailwindOxfmtConfig = async (
|
|
13
13
|
projects: Project[],
|
|
14
|
-
_options: NonNullable<WardenConfig['checks']['tailwindOxfmtConfig']>,
|
|
14
|
+
_options: NonNullable<NonNullable<WardenConfig['checks']>['tailwindOxfmtConfig']>,
|
|
15
15
|
): Promise<CheckResult> => {
|
|
16
16
|
const messages: string[] = []
|
|
17
17
|
let passed = true
|
|
@@ -11,32 +11,38 @@ const projectHasTests = async (projectPath: string, pattern: string): Promise<bo
|
|
|
11
11
|
return false
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
const DEFAULT_TEST_FILE_PATTERN = '**/*.test.{ts,tsx,js,jsx}'
|
|
15
|
+
const DEFAULT_TEST_SCRIPT = 'bun test'
|
|
16
|
+
|
|
14
17
|
export const testScriptConsistency = async (
|
|
15
18
|
projects: Project[],
|
|
16
|
-
options: NonNullable<WardenConfig['checks']['testScriptConsistency']>,
|
|
19
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['testScriptConsistency']>,
|
|
17
20
|
): Promise<CheckResult> => {
|
|
18
21
|
const messages: string[] = []
|
|
19
22
|
let passed = true
|
|
20
23
|
|
|
24
|
+
const testFilePattern = options.testFilePattern ?? DEFAULT_TEST_FILE_PATTERN
|
|
25
|
+
const testScript = options.testScript ?? DEFAULT_TEST_SCRIPT
|
|
26
|
+
|
|
21
27
|
for (const project of projects) {
|
|
22
28
|
const scripts = project.packageJson?.scripts ?? {}
|
|
23
|
-
const hasTests = await projectHasTests(project.path,
|
|
29
|
+
const hasTests = await projectHasTests(project.path, testFilePattern)
|
|
24
30
|
|
|
25
31
|
if (hasTests) {
|
|
26
|
-
if (scripts.test !==
|
|
32
|
+
if (scripts.test !== testScript) {
|
|
27
33
|
passed = false
|
|
28
34
|
messages.push(
|
|
29
|
-
`${project.name}: has test files but "test" script is ${JSON.stringify(scripts.test)}, expected ${JSON.stringify(
|
|
35
|
+
`${project.name}: has test files but "test" script is ${JSON.stringify(scripts.test)}, expected ${JSON.stringify(testScript)}`,
|
|
30
36
|
)
|
|
31
37
|
}
|
|
32
|
-
if (scripts.all !== options.allWithTests) {
|
|
38
|
+
if (options.allWithTests !== undefined && scripts.all !== options.allWithTests) {
|
|
33
39
|
passed = false
|
|
34
40
|
messages.push(
|
|
35
41
|
`${project.name}: "all" is ${JSON.stringify(scripts.all)}, expected ${JSON.stringify(options.allWithTests)} (project has tests)`,
|
|
36
42
|
)
|
|
37
43
|
}
|
|
38
44
|
} else {
|
|
39
|
-
if (scripts.all !== options.allWithoutTests) {
|
|
45
|
+
if (options.allWithoutTests !== undefined && scripts.all !== options.allWithoutTests) {
|
|
40
46
|
passed = false
|
|
41
47
|
messages.push(
|
|
42
48
|
`${project.name}: "all" is ${JSON.stringify(scripts.all)}, expected ${JSON.stringify(options.allWithoutTests)} (no tests detected)`,
|
|
@@ -17,7 +17,7 @@ const readTsconfigReferences = async (projectPath: string): Promise<boolean> =>
|
|
|
17
17
|
|
|
18
18
|
export const typecheckScript = async (
|
|
19
19
|
projects: Project[],
|
|
20
|
-
options: NonNullable<WardenConfig['checks']['typecheckScript']>,
|
|
20
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['typecheckScript']>,
|
|
21
21
|
): Promise<CheckResult> => {
|
|
22
22
|
const messages: string[] = []
|
|
23
23
|
let passed = true
|
|
@@ -3,28 +3,31 @@ import type { CheckResult, PackageJson, Project, WardenConfig } from '../types.t
|
|
|
3
3
|
const dependsOn = (pkg: PackageJson, name: string): boolean =>
|
|
4
4
|
name in (pkg.dependencies ?? {}) || name in (pkg.devDependencies ?? {}) || name in (pkg.peerDependencies ?? {})
|
|
5
5
|
|
|
6
|
+
const DEFAULT_PACKAGE = '@verekia/warden'
|
|
7
|
+
|
|
6
8
|
export const wardenScript = (
|
|
7
9
|
projects: Project[],
|
|
8
|
-
options: NonNullable<WardenConfig['checks']['wardenScript']>,
|
|
10
|
+
options: NonNullable<NonNullable<WardenConfig['checks']>['wardenScript']>,
|
|
9
11
|
): CheckResult => {
|
|
10
12
|
const messages: string[] = []
|
|
11
13
|
let passed = true
|
|
14
|
+
const packageName = options.package ?? DEFAULT_PACKAGE
|
|
12
15
|
|
|
13
16
|
for (const project of projects) {
|
|
14
17
|
const pkg = project.packageJson
|
|
15
|
-
if (!pkg || !dependsOn(pkg,
|
|
18
|
+
if (!pkg || !dependsOn(pkg, packageName)) continue
|
|
16
19
|
|
|
17
20
|
const scripts = pkg.scripts ?? {}
|
|
18
21
|
if (scripts.warden !== 'warden') {
|
|
19
22
|
passed = false
|
|
20
23
|
messages.push(
|
|
21
|
-
`${project.name}: depends on ${
|
|
24
|
+
`${project.name}: depends on ${packageName} but "warden" script is ${JSON.stringify(scripts.warden)}, expected "warden"`,
|
|
22
25
|
)
|
|
23
26
|
}
|
|
24
27
|
if (!scripts.all || !scripts.all.includes('bun run warden')) {
|
|
25
28
|
passed = false
|
|
26
29
|
messages.push(
|
|
27
|
-
`${project.name}: depends on ${
|
|
30
|
+
`${project.name}: depends on ${packageName} but "all" script ${JSON.stringify(scripts.all)} is missing "bun run warden"`,
|
|
28
31
|
)
|
|
29
32
|
}
|
|
30
33
|
}
|
package/src/config.ts
CHANGED
|
@@ -9,10 +9,7 @@ export const loadConfig = async (baseDir: string): Promise<WardenConfig> => {
|
|
|
9
9
|
throw new Error(`No package.json found at ${packageJsonPath}`)
|
|
10
10
|
}
|
|
11
11
|
const pkg = (await packageJsonFile.json()) as PackageJson & { warden?: WardenConfig }
|
|
12
|
-
|
|
13
|
-
throw new Error(`No "warden" key in ${packageJsonPath}`)
|
|
14
|
-
}
|
|
15
|
-
return pkg.warden
|
|
12
|
+
return pkg.warden ?? {}
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
export const resolveProjects = async (config: WardenConfig, baseDir: string): Promise<Project[]> => {
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
import { existsSync } from 'node:fs'
|
|
3
3
|
|
|
4
|
+
import { ciWorkflow } from './checks/ci-workflow.ts'
|
|
4
5
|
import { configFilesPresent } from './checks/config-files-present.ts'
|
|
5
6
|
import { exactDependencyVersions } from './checks/exact-dependency-versions.ts'
|
|
6
7
|
import { matchingDependencyVersions } from './checks/matching-dependency-versions.ts'
|
|
@@ -46,36 +47,41 @@ const scopeNote = filterNames.length > 0 ? ` (filtered from ${allProjects.length
|
|
|
46
47
|
console.log(`warden — checking ${projects.length} project(s)${scopeNote}: ${projects.map(p => p.name).join(', ')}\n`)
|
|
47
48
|
|
|
48
49
|
const results: CheckResult[] = []
|
|
50
|
+
const checks = config.checks ?? {}
|
|
51
|
+
const enabled = (c: { enabled?: boolean } | undefined): boolean => c?.enabled !== false
|
|
49
52
|
|
|
50
|
-
if (
|
|
51
|
-
results.push(await configFilesPresent(projects,
|
|
53
|
+
if (enabled(checks.configFilesPresent)) {
|
|
54
|
+
results.push(await configFilesPresent(projects, checks.configFilesPresent ?? {}))
|
|
52
55
|
}
|
|
53
|
-
if (
|
|
54
|
-
results.push(matchingDependencyVersions(projects,
|
|
56
|
+
if (enabled(checks.matchingDependencyVersions)) {
|
|
57
|
+
results.push(matchingDependencyVersions(projects, checks.matchingDependencyVersions ?? {}))
|
|
55
58
|
}
|
|
56
|
-
if (
|
|
57
|
-
results.push(exactDependencyVersions(projects,
|
|
59
|
+
if (enabled(checks.exactDependencyVersions)) {
|
|
60
|
+
results.push(exactDependencyVersions(projects, checks.exactDependencyVersions ?? {}))
|
|
58
61
|
}
|
|
59
|
-
if (
|
|
60
|
-
results.push(requiredScripts(projects,
|
|
62
|
+
if (enabled(checks.requiredScripts)) {
|
|
63
|
+
results.push(requiredScripts(projects, checks.requiredScripts ?? {}))
|
|
61
64
|
}
|
|
62
|
-
if (
|
|
63
|
-
results.push(await typecheckScript(projects,
|
|
65
|
+
if (enabled(checks.typecheckScript)) {
|
|
66
|
+
results.push(await typecheckScript(projects, checks.typecheckScript ?? {}))
|
|
64
67
|
}
|
|
65
|
-
if (
|
|
66
|
-
results.push(await testScriptConsistency(projects,
|
|
68
|
+
if (enabled(checks.testScriptConsistency)) {
|
|
69
|
+
results.push(await testScriptConsistency(projects, checks.testScriptConsistency ?? {}))
|
|
67
70
|
}
|
|
68
|
-
if (
|
|
69
|
-
results.push(await tailwindOxfmtConfig(projects,
|
|
71
|
+
if (enabled(checks.tailwindOxfmtConfig)) {
|
|
72
|
+
results.push(await tailwindOxfmtConfig(projects, checks.tailwindOxfmtConfig ?? {}))
|
|
70
73
|
}
|
|
71
|
-
if (
|
|
72
|
-
results.push(await portlessNextDev(projects,
|
|
74
|
+
if (enabled(checks.portlessNextDev)) {
|
|
75
|
+
results.push(await portlessNextDev(projects, checks.portlessNextDev ?? {}))
|
|
73
76
|
}
|
|
74
|
-
if (
|
|
75
|
-
results.push(await nextConfig(projects,
|
|
77
|
+
if (enabled(checks.nextConfig)) {
|
|
78
|
+
results.push(await nextConfig(projects, checks.nextConfig ?? {}))
|
|
76
79
|
}
|
|
77
|
-
if (
|
|
78
|
-
results.push(wardenScript(projects,
|
|
80
|
+
if (enabled(checks.wardenScript)) {
|
|
81
|
+
results.push(wardenScript(projects, checks.wardenScript ?? {}))
|
|
82
|
+
}
|
|
83
|
+
if (enabled(checks.ciWorkflow)) {
|
|
84
|
+
results.push(await ciWorkflow(projects, checks.ciWorkflow ?? {}))
|
|
79
85
|
}
|
|
80
86
|
|
|
81
87
|
for (const result of results) {
|
package/src/types.ts
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
export type WardenConfig = {
|
|
2
2
|
projects?: string[]
|
|
3
|
-
checks
|
|
4
|
-
configFilesPresent?: { enabled
|
|
5
|
-
matchingDependencyVersions?: { enabled
|
|
6
|
-
exactDependencyVersions?: { enabled
|
|
7
|
-
requiredScripts?: { enabled
|
|
8
|
-
typecheckScript?: { enabled
|
|
3
|
+
checks?: {
|
|
4
|
+
configFilesPresent?: { enabled?: boolean; files?: string[] }
|
|
5
|
+
matchingDependencyVersions?: { enabled?: boolean; packages?: string[] }
|
|
6
|
+
exactDependencyVersions?: { enabled?: boolean; packages?: Record<string, string> }
|
|
7
|
+
requiredScripts?: { enabled?: boolean; scripts?: Record<string, string> }
|
|
8
|
+
typecheckScript?: { enabled?: boolean; modes?: Record<string, 'auto' | 'bun-filter-all'> }
|
|
9
9
|
testScriptConsistency?: {
|
|
10
|
-
enabled
|
|
11
|
-
testFilePattern
|
|
12
|
-
testScript
|
|
13
|
-
allWithoutTests
|
|
14
|
-
allWithTests
|
|
10
|
+
enabled?: boolean
|
|
11
|
+
testFilePattern?: string
|
|
12
|
+
testScript?: string
|
|
13
|
+
allWithoutTests?: string
|
|
14
|
+
allWithTests?: string
|
|
15
15
|
}
|
|
16
|
-
tailwindOxfmtConfig?: { enabled
|
|
17
|
-
portlessNextDev?: { enabled
|
|
16
|
+
tailwindOxfmtConfig?: { enabled?: boolean }
|
|
17
|
+
portlessNextDev?: { enabled?: boolean; version?: string }
|
|
18
18
|
nextConfig?: {
|
|
19
|
-
enabled
|
|
20
|
-
options
|
|
21
|
-
devDependencies
|
|
19
|
+
enabled?: boolean
|
|
20
|
+
options?: Record<string, unknown>
|
|
21
|
+
devDependencies?: Record<string, string>
|
|
22
22
|
}
|
|
23
|
-
wardenScript?: { enabled
|
|
23
|
+
wardenScript?: { enabled?: boolean; package?: string }
|
|
24
|
+
ciWorkflow?: { enabled?: boolean; file?: string; runs?: string }
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
|