@crossplatformai/dependency-graph 0.11.0-next.0 → 0.11.0-next.1
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/dist/index-cli.js +56 -12
- package/dist/index-cli.js.map +1 -1
- package/dist/index.js +47 -3
- package/dist/index.js.map +1 -1
- package/dist/workflow/types.d.ts +1 -1
- package/dist/workflow/types.d.ts.map +1 -1
- package/dist/workflow/validator.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index-cli.js
CHANGED
|
@@ -381,6 +381,7 @@ function getWorkflowImpacts(rootDir, packages, changedPaths, policyOverrides) {
|
|
|
381
381
|
// src/workflow/validator.ts
|
|
382
382
|
import { existsSync as existsSync4 } from "fs";
|
|
383
383
|
import { readFile } from "fs/promises";
|
|
384
|
+
import { join as join5 } from "path";
|
|
384
385
|
import { glob } from "glob";
|
|
385
386
|
import { parse as parseYaml2 } from "yaml";
|
|
386
387
|
|
|
@@ -423,6 +424,23 @@ function buildBroadWildcards(workspaceRoots) {
|
|
|
423
424
|
}
|
|
424
425
|
return wildcards;
|
|
425
426
|
}
|
|
427
|
+
function hasGlobSyntax(path) {
|
|
428
|
+
return /[*?[\]{}]/.test(path);
|
|
429
|
+
}
|
|
430
|
+
function getStalePathCheckBase(path, allowedRootPaths, workflowPath) {
|
|
431
|
+
if (path === workflowPath || allowedRootPaths.includes(path) || path.startsWith("!")) {
|
|
432
|
+
return null;
|
|
433
|
+
}
|
|
434
|
+
const trailingGlobSuffix = path.endsWith("/**") ? "/**" : path.endsWith("/*") ? "/*" : null;
|
|
435
|
+
const checkBase = trailingGlobSuffix ? path.slice(0, -trailingGlobSuffix.length) : path;
|
|
436
|
+
if (!checkBase || hasGlobSyntax(checkBase)) {
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
439
|
+
if (!trailingGlobSuffix && hasGlobSyntax(path)) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
return checkBase;
|
|
443
|
+
}
|
|
426
444
|
function splitActualPaths(paths, workspaceRoots, allowedRootPaths, workflowPath) {
|
|
427
445
|
const workspacePaths = [];
|
|
428
446
|
const ignoredPaths = [];
|
|
@@ -455,7 +473,7 @@ function isCoveredByExpectedPath(actualPath, expectedPaths) {
|
|
|
455
473
|
return actualPath.startsWith(`${expectedPrefix}/`);
|
|
456
474
|
});
|
|
457
475
|
}
|
|
458
|
-
function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPaths, broadWildcards) {
|
|
476
|
+
function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPaths, broadWildcards, additionalIssues = []) {
|
|
459
477
|
const issues = [];
|
|
460
478
|
const missing = expectedPaths.filter((path) => !actualPaths.includes(path));
|
|
461
479
|
const unnecessary = actualPaths.filter(
|
|
@@ -484,6 +502,7 @@ function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPa
|
|
|
484
502
|
});
|
|
485
503
|
}
|
|
486
504
|
}
|
|
505
|
+
issues.push(...additionalIssues);
|
|
487
506
|
return {
|
|
488
507
|
workflow,
|
|
489
508
|
targetPackage,
|
|
@@ -495,6 +514,25 @@ function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPa
|
|
|
495
514
|
issues
|
|
496
515
|
};
|
|
497
516
|
}
|
|
517
|
+
function getStalePathIssues(ignoredPaths, rootDir, allowedRootPaths, workflowPath) {
|
|
518
|
+
return ignoredPaths.flatMap((path) => {
|
|
519
|
+
const checkBase = getStalePathCheckBase(
|
|
520
|
+
path,
|
|
521
|
+
allowedRootPaths,
|
|
522
|
+
workflowPath
|
|
523
|
+
);
|
|
524
|
+
if (!checkBase || existsSync4(join5(rootDir, checkBase))) {
|
|
525
|
+
return [];
|
|
526
|
+
}
|
|
527
|
+
return [
|
|
528
|
+
{
|
|
529
|
+
kind: "stale-path",
|
|
530
|
+
path,
|
|
531
|
+
message: `Stale path '${path}' does not exist`
|
|
532
|
+
}
|
|
533
|
+
];
|
|
534
|
+
});
|
|
535
|
+
}
|
|
498
536
|
async function validateWorkflows(rootDir, policyOverrides) {
|
|
499
537
|
const discoveredPackages = await discoverWorkspaces(rootDir, {
|
|
500
538
|
fs: {
|
|
@@ -561,7 +599,7 @@ async function validateWorkflows(rootDir, policyOverrides) {
|
|
|
561
599
|
issues: []
|
|
562
600
|
};
|
|
563
601
|
}
|
|
564
|
-
const { workspacePaths: actualPaths } = splitActualPaths(
|
|
602
|
+
const { workspacePaths: actualPaths, ignoredPaths } = splitActualPaths(
|
|
565
603
|
parsedWorkflow.paths,
|
|
566
604
|
workspaceRoots,
|
|
567
605
|
policy.allowedRootPaths,
|
|
@@ -578,7 +616,13 @@ async function validateWorkflows(rootDir, policyOverrides) {
|
|
|
578
616
|
workflowTarget.targetPackage,
|
|
579
617
|
expectedPaths,
|
|
580
618
|
actualPaths,
|
|
581
|
-
broadWildcards
|
|
619
|
+
broadWildcards,
|
|
620
|
+
getStalePathIssues(
|
|
621
|
+
ignoredPaths,
|
|
622
|
+
rootDir,
|
|
623
|
+
policy.allowedRootPaths,
|
|
624
|
+
workflowTarget.workflowPath
|
|
625
|
+
)
|
|
582
626
|
);
|
|
583
627
|
} catch (error) {
|
|
584
628
|
return {
|
|
@@ -918,10 +962,10 @@ if (import.meta.url === new URL(process.argv[1] ?? "", "file:").href) {
|
|
|
918
962
|
|
|
919
963
|
// src/cli/validate-workflows.ts
|
|
920
964
|
import { existsSync as existsSync5, readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
|
|
921
|
-
import { join as
|
|
965
|
+
import { join as join6, resolve as resolve3 } from "path";
|
|
922
966
|
import { parse as parseYaml4 } from "yaml";
|
|
923
967
|
function discoverPnpmWorkflows(rootDir) {
|
|
924
|
-
const workflowsDir =
|
|
968
|
+
const workflowsDir = join6(rootDir, ".github/workflows");
|
|
925
969
|
if (!existsSync5(workflowsDir)) {
|
|
926
970
|
return [];
|
|
927
971
|
}
|
|
@@ -930,7 +974,7 @@ function discoverPnpmWorkflows(rootDir) {
|
|
|
930
974
|
(file) => file.endsWith(".yml")
|
|
931
975
|
);
|
|
932
976
|
for (const file of files) {
|
|
933
|
-
const content = readFileSync3(
|
|
977
|
+
const content = readFileSync3(join6(workflowsDir, file), "utf-8");
|
|
934
978
|
if (content.includes("pnpm/action-setup")) {
|
|
935
979
|
workflows.push(file);
|
|
936
980
|
}
|
|
@@ -943,12 +987,12 @@ function discoverPnpmDockerfiles(rootDir) {
|
|
|
943
987
|
if (!entry.startsWith("Dockerfile")) {
|
|
944
988
|
continue;
|
|
945
989
|
}
|
|
946
|
-
const content = readFileSync3(
|
|
990
|
+
const content = readFileSync3(join6(rootDir, entry), "utf-8");
|
|
947
991
|
if (content.includes("pnpm@")) {
|
|
948
992
|
dockerfiles.push(entry);
|
|
949
993
|
}
|
|
950
994
|
}
|
|
951
|
-
const appsDir =
|
|
995
|
+
const appsDir = join6(rootDir, "apps");
|
|
952
996
|
if (!existsSync5(appsDir)) {
|
|
953
997
|
return dockerfiles;
|
|
954
998
|
}
|
|
@@ -956,7 +1000,7 @@ function discoverPnpmDockerfiles(rootDir) {
|
|
|
956
1000
|
if (!entry.isDirectory()) {
|
|
957
1001
|
continue;
|
|
958
1002
|
}
|
|
959
|
-
const dockerfilePath =
|
|
1003
|
+
const dockerfilePath = join6(appsDir, entry.name, "Dockerfile");
|
|
960
1004
|
if (!existsSync5(dockerfilePath)) {
|
|
961
1005
|
continue;
|
|
962
1006
|
}
|
|
@@ -969,7 +1013,7 @@ function discoverPnpmDockerfiles(rootDir) {
|
|
|
969
1013
|
}
|
|
970
1014
|
function getExpectedPnpmVersion(rootDir) {
|
|
971
1015
|
const packageJson = JSON.parse(
|
|
972
|
-
readFileSync3(
|
|
1016
|
+
readFileSync3(join6(rootDir, "package.json"), "utf-8")
|
|
973
1017
|
);
|
|
974
1018
|
const packageManager = packageJson.packageManager;
|
|
975
1019
|
if (!packageManager?.startsWith("pnpm@")) {
|
|
@@ -978,7 +1022,7 @@ function getExpectedPnpmVersion(rootDir) {
|
|
|
978
1022
|
return packageManager.replace("pnpm@", "");
|
|
979
1023
|
}
|
|
980
1024
|
function checkWorkflowPnpmVersion(workflowFile, rootDir) {
|
|
981
|
-
const workflowPath =
|
|
1025
|
+
const workflowPath = join6(rootDir, ".github/workflows", workflowFile);
|
|
982
1026
|
if (!existsSync5(workflowPath)) {
|
|
983
1027
|
return { valid: true };
|
|
984
1028
|
}
|
|
@@ -1001,7 +1045,7 @@ function checkWorkflowPnpmVersion(workflowFile, rootDir) {
|
|
|
1001
1045
|
return { valid: true };
|
|
1002
1046
|
}
|
|
1003
1047
|
function checkDockerfilePnpmVersion(dockerfile, expectedVersion, rootDir) {
|
|
1004
|
-
const dockerfilePath =
|
|
1048
|
+
const dockerfilePath = join6(rootDir, dockerfile);
|
|
1005
1049
|
if (!existsSync5(dockerfilePath)) {
|
|
1006
1050
|
return { valid: true };
|
|
1007
1051
|
}
|
package/dist/index-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/pr-preview.ts","../src/graph/builder.ts","../src/graph/traversal.ts","../src/workspace/discovery.ts","../src/workspace/package-map.ts","../src/workflow/policy.ts","../src/workflow/discovery.ts","../src/workflow/expected-paths.ts","../src/workflow/impact.ts","../src/workflow/validator.ts","../src/workflow/parser.ts","../src/cli/validate-workflows.ts","../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { glob } from 'glob';\nimport { parse as parseYaml } from 'yaml';\n\n// Import dependency graph functions from parent module\nimport {\n discoverWorkspaces,\n buildDependencyGraph,\n findAffectedPackages,\n getWorkflowImpacts,\n validateWorkflows,\n type WorkspacePackage,\n type WorkflowValidationResult,\n} from '../index';\n\ninterface ChangedFile {\n path: string;\n status: 'modified' | 'added' | 'deleted';\n}\n\ninterface DeploymentIndicator {\n file?: string;\n field?: string;\n dependency?: string;\n}\n\ninterface PlatformDetection {\n platform: string;\n indicators: DeploymentIndicator[];\n}\n\n// Convention-based deployment detection (order matters - most specific first)\nconst PLATFORM_INDICATORS: PlatformDetection[] = [\n {\n platform: 'cloudflare-workers',\n indicators: [{ file: 'wrangler.toml' }],\n },\n {\n platform: 'expo',\n indicators: [{ file: 'app.json' }, { file: 'eas.json' }],\n },\n {\n platform: 'npm-package',\n indicators: [{ field: 'bin' }],\n },\n {\n platform: 'electron',\n indicators: [\n { dependency: 'electron' },\n { dependency: 'electron-builder' },\n ],\n },\n {\n platform: 'next.js',\n indicators: [\n { file: 'next.config.js' },\n { file: 'next.config.mjs' },\n { file: 'next.config.ts' },\n { dependency: 'next' },\n ],\n },\n {\n platform: 'node.js',\n indicators: [\n { field: 'start' }, // has start script\n ],\n },\n];\n\nconst DEFAULT_APP_DIRECTORIES = ['apps'];\n\nexport function formatWorkflowPathDrift(\n validationResults: WorkflowValidationResult[],\n): string[] {\n const invalidResults = validationResults.filter((result) => !result.valid);\n if (invalidResults.length === 0) {\n return [];\n }\n\n const lines = [\n '⚠️ Workflow path drift (advisory - does not affect impact above):',\n ];\n\n for (const result of invalidResults) {\n lines.push(` ${result.workflow} (${result.targetPackage}):`);\n\n for (const issue of result.issues) {\n if (issue.kind === 'missing') {\n lines.push(` + ${issue.message}`);\n } else if (issue.kind === 'unnecessary') {\n lines.push(` - ${issue.message}`);\n } else {\n lines.push(` ! ${issue.message}`);\n }\n }\n }\n\n return lines;\n}\n\nfunction isDeployableApp(pkg: WorkspacePackage): {\n deployable: boolean;\n platform?: string;\n} {\n // Check if package is in apps directory (configurable in future)\n const isInAppDirectory = DEFAULT_APP_DIRECTORIES.some(\n (dir) => pkg.path.includes(`/${dir}/`) || pkg.path.endsWith(`/${dir}`),\n );\n\n if (!isInAppDirectory) {\n return { deployable: false };\n }\n\n // Detect platform based on indicators\n for (const platformDetection of PLATFORM_INDICATORS) {\n const hasIndicators = platformDetection.indicators.some((indicator) => {\n if (indicator.file) {\n try {\n const filePath = resolve(pkg.path, indicator.file);\n readFileSync(filePath, 'utf-8');\n return true;\n } catch {\n return false;\n }\n }\n\n if (indicator.field) {\n const scripts = pkg.packageJson.scripts as\n | Record<string, string>\n | undefined;\n if (indicator.field === 'start' && scripts?.start) {\n return true;\n }\n const packageJsonField =\n pkg.packageJson[indicator.field as keyof typeof pkg.packageJson];\n if (indicator.field !== 'start' && packageJsonField) {\n return true;\n }\n }\n\n if (indicator.dependency) {\n return !!(\n pkg.dependencies[indicator.dependency] ||\n pkg.devDependencies[indicator.dependency]\n );\n }\n\n return false;\n });\n\n if (hasIndicators) {\n return { deployable: true, platform: platformDetection.platform };\n }\n }\n\n // If in apps directory but no specific platform detected, not deployable\n return { deployable: false };\n}\n\nasync function getChangedFiles(): Promise<ChangedFile[]> {\n const { execSync } = await import('node:child_process');\n\n try {\n // Try local production first, then fall back to origin/production\n let baseBranch = 'production';\n try {\n execSync('git rev-parse production', {\n encoding: 'utf-8',\n stdio: 'pipe',\n });\n } catch {\n baseBranch = 'origin/production';\n }\n\n const output = execSync(`git diff --name-status ${baseBranch}...HEAD`, {\n encoding: 'utf-8',\n });\n\n return output\n .trim()\n .split('\\n')\n .filter((line) => line)\n .map((line) => {\n const [status, path] = line.split('\\t');\n\n return {\n path: path ?? '',\n status:\n status === 'D' ? 'deleted' : status === 'A' ? 'added' : 'modified',\n };\n })\n .filter((file): file is ChangedFile => file.path !== '');\n } catch {\n console.error(\n 'Failed to get changed files. Ensure you are on a branch with commits compared to production.',\n );\n process.exit(1);\n }\n}\n\nexport async function runPrPreview(): Promise<void> {\n try {\n const rootDir = resolve(process.cwd());\n const changedFiles = await getChangedFiles();\n\n console.log(\n `\\n📦 Release Preview - Changed Files: ${changedFiles.length}\\n`,\n );\n\n changedFiles.forEach((file) => {\n console.log(` ${file.status === 'deleted' ? '❌' : '📝'} ${file.path}`);\n });\n\n const packages = await discoverWorkspaces(rootDir, {\n fs: {\n readFile: (path) => {\n try {\n return Promise.resolve(readFileSync(path, 'utf-8'));\n } catch {\n return Promise.reject(new Error(`Failed to read file: ${path}`));\n }\n },\n exists: (path) => {\n try {\n readFileSync(path, 'utf-8');\n return Promise.resolve(true);\n } catch {\n return Promise.resolve(false);\n }\n },\n },\n glob: {\n glob: async (pattern, options) => glob(pattern, options),\n },\n yaml: {\n parse: (content) => parseYaml(content) as Record<string, unknown>,\n },\n });\n\n const graph = buildDependencyGraph(packages);\n const changedPackages = new Set<string>();\n\n for (const file of changedFiles) {\n if (file.status === 'deleted') continue;\n\n // Convert absolute package paths to relative for comparison\n const pkg = packages.find((p) => {\n const relativePkgPath = p.path.replace(rootDir + '/', '');\n return file.path.startsWith(relativePkgPath);\n });\n\n if (pkg) {\n changedPackages.add(pkg.name);\n }\n }\n\n const workflowImpacts = getWorkflowImpacts(\n rootDir,\n packages,\n changedFiles.map((file) => file.path),\n );\n const workflowDriftLines = formatWorkflowPathDrift(\n await validateWorkflows(rootDir),\n );\n\n const workflowAffectedApps = new Set(\n workflowImpacts.map(\n (workflowImpact) =>\n workflowImpact.targetPackage ?? workflowImpact.targetSlug,\n ),\n );\n\n console.log(\n `\\n📦 Changed packages: ${Array.from(changedPackages).join(', ') || 'none'}\\n`,\n );\n\n if (changedPackages.size === 0 && workflowAffectedApps.size === 0) {\n console.log(\n '\\n✨ No packages or workflow filters changed - no deployments needed\\n',\n );\n if (workflowDriftLines.length > 0) {\n console.log(workflowDriftLines.join('\\n'));\n console.log('');\n }\n return;\n }\n\n const affected = findAffectedPackages(changedPackages, graph, {\n direction: 'upstream',\n respectAffectsUpstream: true,\n });\n\n // Find all deployable apps (affected and unaffected)\n const allDeployableApps = packages\n .map((pkg) => {\n const detection = isDeployableApp(pkg);\n return detection.deployable\n ? { name: pkg.name, pkg, platform: detection.platform }\n : null;\n })\n .filter(\n (\n item,\n ): item is {\n name: string;\n pkg: WorkspacePackage;\n platform: string | undefined;\n } => item !== null,\n );\n\n // Categorize apps by deployment type\n const affectedApps = allDeployableApps.filter(\n (app): app is NonNullable<typeof app> =>\n affected.has(app.name) || workflowAffectedApps.has(app.name),\n );\n const unaffectedApps = allDeployableApps.filter(\n (app): app is NonNullable<typeof app> =>\n !affected.has(app.name) && !workflowAffectedApps.has(app.name),\n );\n\n // Separate deploys (web-based) vs releases (installed)\n const getAppCategory = (platform?: string) => {\n switch (platform) {\n case 'next.js':\n case 'cloudflare-workers':\n case 'node.js':\n return 'deploy';\n case 'expo':\n case 'electron':\n case 'npm-package':\n return 'release';\n default:\n return 'deploy'; // default to deploy for generic\n }\n };\n\n const getAppIcon = (platform?: string) => {\n switch (platform) {\n case 'next.js':\n case 'cloudflare-workers':\n case 'node.js':\n return '🌐';\n case 'expo':\n return '📱';\n case 'electron':\n return '🖥️';\n case 'npm-package':\n return '⚡';\n default:\n return '🌐';\n }\n };\n\n const affectedDeploys = affectedApps.filter(\n (app): app is NonNullable<typeof app> =>\n getAppCategory(app.platform) === 'deploy',\n );\n const affectedReleases = affectedApps.filter(\n (app): app is NonNullable<typeof app> =>\n getAppCategory(app.platform) === 'release',\n );\n\n console.log(`\\n🚀 PR Preview\\n`);\n\n if (affectedApps.length === 0) {\n console.log('No apps affected by changes.\\n');\n } else {\n if (affectedDeploys.length > 0) {\n console.log('📋 Apps that will be DEPLOYED:');\n for (const item of affectedDeploys) {\n const platformDisplay =\n item.platform === 'generic' ? '' : ` (${item.platform})`;\n const icon = getAppIcon(item.platform);\n console.log(`${icon} ${item.name}${platformDisplay}`);\n }\n console.log('');\n }\n\n if (affectedReleases.length > 0) {\n console.log('📋 Apps that will be RELEASED:');\n for (const item of affectedReleases) {\n const platformDisplay =\n item.platform === 'generic' ? '' : ` (${item.platform})`;\n const icon = getAppIcon(item.platform);\n console.log(`${icon} ${item.name}${platformDisplay}`);\n }\n console.log('');\n }\n }\n\n if (unaffectedApps.length > 0) {\n console.log(`📋 Apps that will NOT be affected:`);\n for (const item of unaffectedApps) {\n const platformDisplay =\n item.platform === 'generic' ? '' : ` (${item.platform})`;\n console.log(`⏭️ ${item.name}${platformDisplay}`);\n }\n console.log('');\n }\n\n console.log(`Legend:`);\n console.log(`🌐 = Deploy (web-based, instant updates)`);\n console.log(`📱 = Release (mobile app, user installs)`);\n console.log(`🖥️ = Release (desktop app, user installs)`);\n console.log(`⚡ = Release (CLI tool, user installs)`);\n console.log(`⏭️ = Unaffected (no changes needed)`);\n console.log(`📝 = File changed`);\n console.log(`❌ = File deleted\\n`);\n\n if (workflowDriftLines.length > 0) {\n console.log(workflowDriftLines.join('\\n'));\n console.log('');\n }\n } catch (error) {\n console.error(\n 'Error:',\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n}\n\nif (import.meta.url === new URL(process.argv[1] ?? '', 'file:').href) {\n void runPrPreview();\n}\n","import type { WorkspacePackage, DependencyGraph } from './types';\n\nexport function buildDependencyGraph(\n packages: WorkspacePackage[],\n): DependencyGraph {\n const graph: DependencyGraph = {\n packages: new Map(),\n dependsOn: new Map(),\n dependedBy: new Map(),\n };\n\n for (const pkg of packages) {\n graph.packages.set(pkg.name, pkg);\n graph.dependsOn.set(pkg.name, new Set());\n graph.dependedBy.set(pkg.name, new Set());\n }\n\n for (const pkg of packages) {\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n for (const depName of Object.keys(allDeps)) {\n const matchedPkg = findMatchingPackage(depName, packages);\n\n if (matchedPkg) {\n graph.dependsOn.get(pkg.name)!.add(matchedPkg.name);\n graph.dependedBy.get(matchedPkg.name)!.add(pkg.name);\n }\n }\n }\n\n return graph;\n}\n\nfunction findMatchingPackage(\n depName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((p) => p.name === depName);\n if (match) return match;\n\n match = packages.find((p) => p.name === `@repo/${depName}`);\n if (match) return match;\n\n const nameWithoutRepo = depName.replace(/^@repo\\//, '');\n match = packages.find((p) => p.name === nameWithoutRepo);\n if (match) return match;\n\n return undefined;\n}\n","import type { DependencyGraph, TraversalOptions } from './types';\n\nexport function findAffectedPackages(\n startingPackages: Set<string>,\n graph: DependencyGraph,\n options: TraversalOptions = {},\n): Set<string> {\n const {\n direction = 'upstream',\n maxDepth = Infinity,\n filter,\n respectAffectsUpstream = false,\n } = options;\n\n const affected = new Set<string>(startingPackages);\n const queue: Array<{ name: string; depth: number }> = Array.from(\n startingPackages,\n ).map((name) => ({ name, depth: 0 }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (visited.has(current.name)) continue;\n visited.add(current.name);\n\n if (current.depth >= maxDepth) {\n continue;\n }\n\n const pkg = graph.packages.get(current.name);\n if (!pkg) continue;\n\n if (respectAffectsUpstream && direction === 'upstream') {\n const release = pkg.packageJson.release;\n if (release && release.affectsUpstream === false) {\n continue;\n }\n }\n\n const nextPackages = new Set<string>();\n\n if (direction === 'upstream' || direction === 'both') {\n const upstream = graph.dependedBy.get(current.name) || new Set();\n upstream.forEach((p) => nextPackages.add(p));\n }\n\n if (direction === 'downstream' || direction === 'both') {\n const downstream = graph.dependsOn.get(current.name) || new Set();\n downstream.forEach((p) => nextPackages.add(p));\n }\n\n for (const pkgName of nextPackages) {\n const nextPkg = graph.packages.get(pkgName);\n\n if (filter && nextPkg && !filter(nextPkg)) {\n continue;\n }\n\n if (!affected.has(pkgName)) {\n affected.add(pkgName);\n queue.push({ name: pkgName, depth: current.depth + 1 });\n }\n }\n }\n\n return affected;\n}\n\nexport function findDependencyPath(\n from: string,\n to: string,\n graph: DependencyGraph,\n): string[] | null {\n const queue: string[][] = [[from]];\n const visited = new Set<string>([from]);\n\n while (queue.length > 0) {\n const path = queue.shift()!;\n const current = path[path.length - 1];\n\n if (!current) {\n continue;\n }\n\n if (current === to) {\n return path;\n }\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n if (!visited.has(dependent)) {\n visited.add(dependent);\n queue.push([...path, dependent]);\n }\n }\n }\n\n return null;\n}\n\nexport function findAllPaths(\n from: string,\n to: string,\n graph: DependencyGraph,\n maxPaths = 10,\n): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n function dfs(current: string, path: string[]): void {\n if (paths.length >= maxPaths) return;\n\n if (current === to) {\n paths.push([...path]);\n return;\n }\n\n if (visited.has(current)) return;\n visited.add(current);\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n dfs(dependent, [...path, dependent]);\n }\n\n visited.delete(current);\n }\n\n dfs(from, [from]);\n return paths;\n}\n","import { join, resolve } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport type {\n FileSystemClient,\n GlobClient,\n YamlClient,\n} from '../types/clients';\n\nexport interface WorkspaceConfig {\n packages: string[];\n}\n\nexport interface WorkspaceDiscoveryConfig {\n fs: FileSystemClient;\n glob: GlobClient;\n yaml: YamlClient;\n}\n\nexport async function discoverWorkspaces(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspacePackage[]> {\n const workspaceConfig = await loadWorkspaceConfig(rootDir, config);\n const packages: WorkspacePackage[] = [];\n\n for (const pattern of workspaceConfig.packages) {\n if (pattern.startsWith('!')) continue;\n\n const pkgDirs = await findPackageDirectories(rootDir, pattern, config);\n\n for (const pkgDir of pkgDirs) {\n const pkgJsonPath = join(pkgDir, 'package.json');\n\n try {\n const pkgJsonContent: string = await config.fs.readFile(\n pkgJsonPath,\n 'utf-8',\n );\n const pkgJson = JSON.parse(pkgJsonContent) as {\n name: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n };\n\n packages.push({\n name: pkgJson.name,\n version: pkgJson.version || '0.0.0',\n path: pkgDir,\n packageJson: pkgJson,\n dependencies: pkgJson.dependencies || {},\n devDependencies: pkgJson.devDependencies || {},\n });\n } catch {\n continue;\n }\n }\n }\n\n return packages;\n}\n\nasync function loadWorkspaceConfig(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspaceConfig> {\n const workspaceFilePath = join(rootDir, 'pnpm-workspace.yaml');\n\n try {\n const content: string = await config.fs.readFile(\n workspaceFilePath,\n 'utf-8',\n );\n const parsed = config.yaml.parse(content) as WorkspaceConfig;\n return parsed;\n } catch {\n return { packages: [] };\n }\n}\n\nasync function findPackageDirectories(\n rootDir: string,\n pattern: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<string[]> {\n const matches: string[] = await config.glob.glob(pattern, {\n cwd: rootDir,\n absolute: false,\n ignore: ['**/node_modules/**', '**/.next/**', '**/dist/**'],\n });\n\n return matches.map((match: string) => resolve(rootDir, match));\n}\n","import { existsSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\n\nexport interface MappedWorkspacePath {\n filesystemPath: string;\n workflowPath: string | null;\n}\n\nexport interface WorkspacePackageMap {\n packageMap: Map<string, MappedWorkspacePath>;\n workspaceRoots: Set<string>;\n}\n\nexport function normalizeRelativePath(path: string): string {\n return path.split(sep).join('/');\n}\n\nfunction resolveWorkflowPath(\n relativePath: string,\n rootDir: string,\n): string | null {\n if (!relativePath.startsWith('../')) {\n return relativePath;\n }\n\n const segments = relativePath.split('/');\n\n for (let index = 0; index < segments.length; index += 1) {\n const candidateSegments = segments.slice(index);\n if (candidateSegments.length === 0 || candidateSegments[0] === '..') {\n continue;\n }\n\n const candidatePath = candidateSegments.join('/');\n if (existsSync(join(rootDir, candidatePath))) {\n return candidatePath;\n }\n }\n\n return null;\n}\n\nexport function buildPackageMap(\n packages: WorkspacePackage[],\n rootDir: string,\n): WorkspacePackageMap {\n const packageMap = new Map<string, MappedWorkspacePath>();\n const workspaceRoots = new Set<string>();\n\n for (const pkg of packages) {\n const relativePath = normalizeRelativePath(relative(rootDir, pkg.path));\n const workflowPath = resolveWorkflowPath(relativePath, rootDir);\n\n packageMap.set(pkg.name, {\n filesystemPath: relativePath,\n workflowPath,\n });\n\n if (!workflowPath) {\n continue;\n }\n\n const [workspaceRoot] = workflowPath.split('/');\n if (workspaceRoot) {\n workspaceRoots.add(workspaceRoot);\n }\n }\n\n return {\n packageMap,\n workspaceRoots,\n };\n}\n","import type { WorkflowValidationPolicy } from './types';\n\nexport const defaultWorkflowValidationPolicy: WorkflowValidationPolicy = {\n workflowFilePatterns: ['deploy-*.yml', 'release-*.yml'],\n allowedRootPaths: [\n 'package.json',\n 'pnpm-lock.yaml',\n 'pnpm-workspace.yaml',\n 'turbo.json',\n ],\n includeDevDependenciesForRootPackage: true,\n includeDevDependenciesTransitively: false,\n};\n","import { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\nfunction patternToRegExp(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp(`^${escaped.replace(/\\*/g, '.*')}$`);\n}\n\nexport function discoverWorkflowTargets(\n rootDir: string,\n packages: WorkspacePackage[],\n policy: WorkflowValidationPolicy,\n): WorkflowTarget[] {\n const workflowsDir = join(rootDir, '.github/workflows');\n if (!existsSync(workflowsDir)) {\n return [];\n }\n\n const { packageMap } = buildPackageMap(packages, rootDir);\n const appPackages = packages.filter((pkg) =>\n packageMap.get(pkg.name)?.workflowPath?.startsWith('apps/'),\n );\n const bySlug = new Map<string, string>();\n\n for (const pkg of appPackages) {\n const relativePath = packageMap.get(pkg.name)?.workflowPath;\n if (!relativePath) {\n continue;\n }\n\n const slug = relativePath.split('/').at(-1);\n if (slug) {\n bySlug.set(slug, pkg.name);\n }\n }\n\n const allowedPatterns = policy.workflowFilePatterns.map(patternToRegExp);\n const files = readdirSync(workflowsDir)\n .filter((file) => file.endsWith('.yml'))\n .filter((file) => allowedPatterns.some((pattern) => pattern.test(file)));\n\n return files\n .map((workflowFile) => {\n const match = /^(?:deploy|release)-(.+)\\.yml$/.exec(workflowFile);\n const targetSlug = match?.[1] ?? workflowFile.replace(/\\.yml$/, '');\n\n return {\n workflowFile,\n workflowPath: `.github/workflows/${workflowFile}`,\n targetSlug,\n targetPackage: bySlug.get(targetSlug) ?? null,\n };\n })\n .sort((a, b) => a.workflowFile.localeCompare(b.workflowFile));\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\ninterface ExpectedPathsOptions {\n workflowTarget: WorkflowTarget;\n packages: WorkspacePackage[];\n packageMap: Map<string, { workflowPath: string | null }>;\n policy: WorkflowValidationPolicy;\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction resolveWorkspaceDependency(\n dependencyName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((pkg) => pkg.name === dependencyName);\n if (match) {\n return match;\n }\n\n match = packages.find((pkg) => pkg.name === `@repo/${dependencyName}`);\n if (match) {\n return match;\n }\n\n const nameWithoutRepo = dependencyName.replace(/^@repo\\//, '');\n return packages.find((pkg) => pkg.name === nameWithoutRepo);\n}\n\nfunction collectWorkspaceDependencyNames(\n pkg: WorkspacePackage,\n packages: WorkspacePackage[],\n visited: Set<string>,\n includeDevDependencies: boolean,\n includeDevDependenciesTransitively: boolean,\n): Set<string> {\n const collected = new Set<string>();\n const dependencyEntries = Object.entries(pkg.dependencies);\n const devDependencyEntries = includeDevDependencies\n ? Object.entries(pkg.devDependencies)\n : [];\n\n for (const [dependencyName] of [\n ...dependencyEntries,\n ...devDependencyEntries,\n ]) {\n const dependency = resolveWorkspaceDependency(dependencyName, packages);\n if (!dependency || visited.has(dependency.name)) {\n continue;\n }\n\n visited.add(dependency.name);\n collected.add(dependency.name);\n\n const nestedDependencies = collectWorkspaceDependencyNames(\n dependency,\n packages,\n visited,\n includeDevDependenciesTransitively,\n includeDevDependenciesTransitively,\n );\n\n for (const nestedDependency of nestedDependencies) {\n collected.add(nestedDependency);\n }\n }\n\n return collected;\n}\n\nexport function getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n}: ExpectedPathsOptions): string[] {\n const targetPackageName = workflowTarget.targetPackage;\n if (!targetPackageName) {\n return [];\n }\n\n const targetPackage = packages.find((pkg) => pkg.name === targetPackageName);\n if (!targetPackage) {\n return [];\n }\n\n const dependencyNames = collectWorkspaceDependencyNames(\n targetPackage,\n packages,\n new Set<string>(),\n policy.includeDevDependenciesForRootPackage,\n policy.includeDevDependenciesTransitively,\n );\n\n const expectedPaths: string[] = [];\n const targetPackagePath = packageMap.get(targetPackageName)?.workflowPath;\n if (targetPackagePath) {\n expectedPaths.push(`${targetPackagePath}/**`);\n }\n\n for (const dependencyName of dependencyNames) {\n const dependencyPath = packageMap.get(dependencyName)?.workflowPath;\n if (dependencyPath) {\n expectedPaths.push(`${dependencyPath}/**`);\n }\n }\n\n return uniqueSorted(expectedPaths);\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { defaultWorkflowValidationPolicy } from './policy';\nimport type { WorkflowImpact, WorkflowValidationPolicy } from './types';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction mergeWorkflowPolicy(\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowValidationPolicy {\n return {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n}\n\n// Path matching intentionally only supports exact paths and /** prefix matching\n// because that mirrors the workflow filters currently used in these repos.\nexport function matchesWorkflowPathFilter(\n changedPath: string,\n workflowPathFilter: string,\n): boolean {\n if (workflowPathFilter === changedPath) {\n return true;\n }\n\n if (!workflowPathFilter.endsWith('/**')) {\n return false;\n }\n\n const workflowPrefix = workflowPathFilter.slice(0, -3);\n return changedPath.startsWith(`${workflowPrefix}/`);\n}\n\nexport function getWorkflowImpacts(\n rootDir: string,\n packages: WorkspacePackage[],\n changedPaths: string[],\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowImpact[] {\n const policy = mergeWorkflowPolicy(policyOverrides);\n const workflowTargets = discoverWorkflowTargets(rootDir, packages, policy);\n const { packageMap } = buildPackageMap(packages, rootDir);\n\n return workflowTargets\n .map((workflowTarget) => {\n const calculatedPaths = uniqueSorted([\n ...getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n }),\n ...policy.allowedRootPaths,\n workflowTarget.workflowPath,\n ]);\n const matchedPaths = calculatedPaths.filter((calculatedPath) =>\n changedPaths.some((changedPath) =>\n matchesWorkflowPathFilter(changedPath, calculatedPath),\n ),\n );\n\n return {\n ...workflowTarget,\n matchedPaths: uniqueSorted(matchedPaths),\n } satisfies WorkflowImpact;\n })\n .filter((workflowImpact) => workflowImpact.matchedPaths.length > 0);\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { glob } from 'glob';\nimport { parse as parseYaml } from 'yaml';\nimport { discoverWorkspaces } from '../workspace/discovery';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type {\n WorkflowValidationIssue,\n WorkflowValidationPolicy,\n WorkflowValidationResult,\n} from './types';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { parseWorkflowFile } from './parser';\nimport { defaultWorkflowValidationPolicy } from './policy';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction buildBroadWildcards(workspaceRoots: Set<string>): Set<string> {\n const wildcards = new Set<string>();\n\n for (const root of workspaceRoots) {\n wildcards.add(`${root}/*`);\n wildcards.add(`${root}/**`);\n }\n\n return wildcards;\n}\n\nfunction splitActualPaths(\n paths: string[],\n workspaceRoots: Set<string>,\n allowedRootPaths: string[],\n workflowPath: string,\n): { workspacePaths: string[]; ignoredPaths: string[] } {\n const workspacePaths: string[] = [];\n const ignoredPaths: string[] = [];\n\n for (const path of paths) {\n if (path === workflowPath || allowedRootPaths.includes(path)) {\n ignoredPaths.push(path);\n continue;\n }\n\n const [rootSegment] = path.split('/');\n if (rootSegment && workspaceRoots.has(rootSegment)) {\n workspacePaths.push(path);\n continue;\n }\n\n ignoredPaths.push(path);\n }\n\n return {\n workspacePaths: uniqueSorted(workspacePaths),\n ignoredPaths: uniqueSorted(ignoredPaths),\n };\n}\n\nfunction isCoveredByExpectedPath(\n actualPath: string,\n expectedPaths: string[],\n): boolean {\n return expectedPaths.some((expectedPath) => {\n if (expectedPath === actualPath) {\n return true;\n }\n\n if (!expectedPath.endsWith('/**')) {\n return false;\n }\n\n const expectedPrefix = expectedPath.slice(0, -3);\n return actualPath.startsWith(`${expectedPrefix}/`);\n });\n}\n\nfunction validateWorkflowResult(\n workflow: string,\n targetPackage: string,\n expectedPaths: string[],\n actualPaths: string[],\n broadWildcards: Set<string>,\n): WorkflowValidationResult {\n const issues: WorkflowValidationIssue[] = [];\n const missing = expectedPaths.filter((path) => !actualPaths.includes(path));\n const unnecessary = actualPaths.filter(\n (path) => !isCoveredByExpectedPath(path, expectedPaths),\n );\n\n for (const path of missing) {\n issues.push({\n kind: 'missing',\n path,\n message: `Missing path '${path}'`,\n });\n }\n\n for (const path of unnecessary) {\n issues.push({\n kind: 'unnecessary',\n path,\n message: `Unnecessary path '${path}'`,\n });\n }\n\n for (const path of actualPaths) {\n if (broadWildcards.has(path)) {\n issues.push({\n kind: 'broad-wildcard',\n path,\n message: `Uses broad wildcard '${path}' which triggers on all workspace changes under that root`,\n });\n }\n }\n\n return {\n workflow,\n targetPackage,\n valid: issues.length === 0,\n expectedPaths,\n actualPaths,\n missing,\n unnecessary,\n issues,\n };\n}\n\nexport async function validateWorkflows(\n rootDir: string,\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): Promise<WorkflowValidationResult[]> {\n const discoveredPackages = await discoverWorkspaces(rootDir, {\n fs: {\n readFile: (path, encoding) => readFile(path, encoding),\n exists: (path) => Promise.resolve(existsSync(path)),\n },\n glob: {\n glob: (pattern, options) => glob(pattern, options),\n },\n yaml: {\n parse: (content): unknown => parseYaml(content),\n },\n });\n\n const policy: WorkflowValidationPolicy = {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n\n const { packageMap, workspaceRoots } = buildPackageMap(\n discoveredPackages,\n rootDir,\n );\n const workflowTargets = discoverWorkflowTargets(\n rootDir,\n discoveredPackages,\n policy,\n );\n const broadWildcards = buildBroadWildcards(workspaceRoots);\n\n return workflowTargets.map((workflowTarget) => {\n if (!workflowTarget.targetPackage) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetSlug,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'config-error',\n message: `Could not resolve workflow target package for '${workflowTarget.workflowFile}'`,\n },\n ],\n };\n }\n\n try {\n const parsedWorkflow = parseWorkflowFile(\n workflowTarget.workflowFile,\n rootDir,\n );\n\n if (parsedWorkflow.paths.length === 0) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: true,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [],\n };\n }\n\n const { workspacePaths: actualPaths } = splitActualPaths(\n parsedWorkflow.paths,\n workspaceRoots,\n policy.allowedRootPaths,\n workflowTarget.workflowPath,\n );\n const expectedPaths = getExpectedWorkflowPaths({\n workflowTarget,\n packages: discoveredPackages,\n packageMap,\n policy,\n });\n\n return validateWorkflowResult(\n workflowTarget.workflowFile,\n workflowTarget.targetPackage,\n expectedPaths,\n actualPaths,\n broadWildcards,\n );\n } catch (error) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'parse-error',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { ParsedWorkflow } from './types';\n\ninterface WorkflowConfig {\n name?: string;\n on?: {\n push?: {\n paths?: string[];\n };\n pull_request?: {\n paths?: string[];\n };\n };\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nexport function parseWorkflowFile(\n workflowFile: string,\n rootDir: string,\n): ParsedWorkflow {\n const workflowPath = join(rootDir, '.github/workflows', workflowFile);\n\n if (!existsSync(workflowPath)) {\n throw new Error(`Workflow file not found: ${workflowFile}`);\n }\n\n const content = readFileSync(workflowPath, 'utf-8');\n const workflow = parseYaml(content) as WorkflowConfig;\n const pushPaths = workflow.on?.push?.paths ?? [];\n const pullRequestPaths = workflow.on?.pull_request?.paths ?? [];\n\n const parsedWorkflow: ParsedWorkflow = {\n pushPaths: uniqueSorted(pushPaths),\n pullRequestPaths: uniqueSorted(pullRequestPaths),\n paths: uniqueSorted([...pushPaths, ...pullRequestPaths]),\n };\n\n if (workflow.name) {\n parsedWorkflow.name = workflow.name;\n }\n\n return parsedWorkflow;\n}\n","#!/usr/bin/env node\n\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { validateWorkflows } from '../workflow/validator';\nimport type { WorkflowValidationResult } from '../workflow/types';\n\ninterface PackageJson {\n packageManager?: string;\n}\n\ninterface PnpmValidationResult {\n valid: boolean;\n workflowIssues: { workflow: string; issue: string }[];\n dockerfileIssues: { dockerfile: string; issue: string }[];\n}\n\nfunction discoverPnpmWorkflows(rootDir: string): string[] {\n const workflowsDir = join(rootDir, '.github/workflows');\n if (!existsSync(workflowsDir)) {\n return [];\n }\n\n const workflows: string[] = [];\n const files = readdirSync(workflowsDir).filter((file) =>\n file.endsWith('.yml'),\n );\n\n for (const file of files) {\n const content = readFileSync(join(workflowsDir, file), 'utf-8');\n if (content.includes('pnpm/action-setup')) {\n workflows.push(file);\n }\n }\n\n return workflows;\n}\n\nfunction discoverPnpmDockerfiles(rootDir: string): string[] {\n const dockerfiles: string[] = [];\n\n for (const entry of readdirSync(rootDir)) {\n if (!entry.startsWith('Dockerfile')) {\n continue;\n }\n\n const content = readFileSync(join(rootDir, entry), 'utf-8');\n if (content.includes('pnpm@')) {\n dockerfiles.push(entry);\n }\n }\n\n const appsDir = join(rootDir, 'apps');\n if (!existsSync(appsDir)) {\n return dockerfiles;\n }\n\n for (const entry of readdirSync(appsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const dockerfilePath = join(appsDir, entry.name, 'Dockerfile');\n if (!existsSync(dockerfilePath)) {\n continue;\n }\n\n const content = readFileSync(dockerfilePath, 'utf-8');\n if (content.includes('pnpm@')) {\n dockerfiles.push(`apps/${entry.name}/Dockerfile`);\n }\n }\n\n return dockerfiles;\n}\n\nfunction getExpectedPnpmVersion(rootDir: string): string {\n const packageJson = JSON.parse(\n readFileSync(join(rootDir, 'package.json'), 'utf-8'),\n ) as PackageJson;\n const packageManager = packageJson.packageManager;\n\n if (!packageManager?.startsWith('pnpm@')) {\n throw new Error('packageManager field must specify pnpm version');\n }\n\n return packageManager.replace('pnpm@', '');\n}\n\nfunction checkWorkflowPnpmVersion(\n workflowFile: string,\n rootDir: string,\n): { valid: boolean; issue?: string } {\n const workflowPath = join(rootDir, '.github/workflows', workflowFile);\n if (!existsSync(workflowPath)) {\n return { valid: true };\n }\n\n const content = readFileSync(workflowPath, 'utf-8');\n const workflow = parseYaml(content) as {\n jobs?: Record<\n string,\n { steps?: Array<{ uses?: string; with?: { version?: string | number } }> }\n >;\n };\n\n for (const job of Object.values(workflow.jobs ?? {})) {\n for (const step of job.steps ?? []) {\n if (!step.uses?.startsWith('pnpm/action-setup')) {\n continue;\n }\n\n const version = step.with?.version;\n if (version !== undefined && !/^\\d+$/.test(String(version))) {\n return {\n valid: false,\n issue: `Hardcoded pnpm version '${version}' - remove 'version' key to auto-detect from packageManager`,\n };\n }\n }\n }\n\n return { valid: true };\n}\n\nfunction checkDockerfilePnpmVersion(\n dockerfile: string,\n expectedVersion: string,\n rootDir: string,\n): { valid: boolean; issue?: string } {\n const dockerfilePath = join(rootDir, dockerfile);\n if (!existsSync(dockerfilePath)) {\n return { valid: true };\n }\n\n const content = readFileSync(dockerfilePath, 'utf-8');\n const matches = content.matchAll(/npm install -g pnpm@([\\d.]+)/g);\n\n for (const match of matches) {\n if (match[1] !== expectedVersion) {\n return {\n valid: false,\n issue: `${dockerfile} uses pnpm@${match[1]} but package.json specifies pnpm@${expectedVersion}`,\n };\n }\n }\n\n return { valid: true };\n}\n\nfunction validatePnpmVersions(rootDir: string): PnpmValidationResult {\n const result: PnpmValidationResult = {\n valid: true,\n workflowIssues: [],\n dockerfileIssues: [],\n };\n\n for (const workflowFile of discoverPnpmWorkflows(rootDir)) {\n const check = checkWorkflowPnpmVersion(workflowFile, rootDir);\n if (!check.valid && check.issue) {\n result.valid = false;\n result.workflowIssues.push({\n workflow: workflowFile,\n issue: check.issue,\n });\n }\n }\n\n const expectedVersion = getExpectedPnpmVersion(rootDir);\n for (const dockerfile of discoverPnpmDockerfiles(rootDir)) {\n const check = checkDockerfilePnpmVersion(\n dockerfile,\n expectedVersion,\n rootDir,\n );\n if (!check.valid && check.issue) {\n result.valid = false;\n result.dockerfileIssues.push({ dockerfile, issue: check.issue });\n }\n }\n\n return result;\n}\n\nfunction printResult(result: WorkflowValidationResult): void {\n const icon = result.valid ? '✅' : '❌';\n console.log(`\\n${icon} ${result.workflow} (${result.targetPackage})`);\n\n if (result.valid) {\n console.log(' All paths match dependencies');\n return;\n }\n\n const extraIssues = result.issues.filter(\n (issue) => issue.kind !== 'missing' && issue.kind !== 'unnecessary',\n );\n\n if (extraIssues.length > 0) {\n console.log(' Issues:');\n for (const issue of extraIssues) {\n console.log(` ⚠️ ${issue.message}`);\n }\n }\n\n if (result.missing.length > 0) {\n console.log(' Missing paths:');\n for (const path of result.missing) {\n console.log(` - ${path}`);\n }\n }\n\n if (result.unnecessary.length > 0) {\n console.log(' Unnecessary paths:');\n for (const path of result.unnecessary) {\n console.log(` - ${path}`);\n }\n }\n}\n\nexport async function runValidateWorkflows(): Promise<void> {\n const rootDir = resolve(process.cwd());\n let hasErrors = false;\n\n console.log(\n '🔍 Validating GitHub Actions workflows against dependencies...\\n',\n );\n const results = await validateWorkflows(rootDir);\n console.log(`Found ${results.length} workflow(s) to validate\\n`);\n\n if (results.length === 0) {\n console.log('No deploy-*.yml or release-*.yml workflows found.\\n');\n }\n\n for (const result of results) {\n printResult(result);\n }\n\n const validCount = results.filter((result) => result.valid).length;\n const invalidCount = results.length - validCount;\n\n console.log('\\n' + '='.repeat(60));\n console.log(\n `\\n📊 Path validation: ${validCount} valid, ${invalidCount} invalid\\n`,\n );\n\n if (invalidCount > 0) {\n console.log('❌ Some workflows need updates to match dependencies');\n console.log('\\nTo fix:');\n console.log('1. Update workflow path filters to match missing paths');\n console.log('2. Remove unnecessary paths');\n console.log('3. Replace broad workspace wildcards with specific paths\\n');\n hasErrors = true;\n } else if (results.length > 0) {\n console.log('✅ All workflows match their dependencies!\\n');\n }\n\n console.log('='.repeat(60));\n console.log('\\n🔍 Validating pnpm version consistency...\\n');\n\n const pnpmResult = validatePnpmVersions(rootDir);\n if (!pnpmResult.valid) {\n console.log('❌ PNPM version issues found:\\n');\n for (const { workflow, issue } of pnpmResult.workflowIssues) {\n console.log(` ⚠️ ${workflow}: ${issue}`);\n }\n for (const { issue } of pnpmResult.dockerfileIssues) {\n console.log(` ⚠️ ${issue}`);\n }\n console.log('\\nTo fix:');\n console.log(\n '1. Remove hardcoded pnpm versions from workflows (let pnpm/action-setup auto-detect from packageManager)',\n );\n console.log(\n '2. Update Dockerfile pnpm versions to match package.json packageManager field\\n',\n );\n hasErrors = true;\n } else {\n console.log('✅ PNPM versions are consistent!\\n');\n }\n\n if (hasErrors) {\n process.exit(1);\n }\n}\n\nif (import.meta.url === new URL(process.argv[1] ?? '', 'file:').href) {\n void runValidateWorkflows();\n}\n","#!/usr/bin/env node\n\nimport { runPrPreview } from './pr-preview';\nimport { runValidateWorkflows } from './validate-workflows';\n\nfunction printHelp(): void {\n console.log(`dependency-graph <command>\n\nCommands:\n pr-preview Show affected deploys and releases for the current branch\n validate-workflows Validate workflow path filters and pnpm version consistency`);\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2];\n\n switch (command) {\n case 'pr-preview':\n await runPrPreview();\n return;\n case 'validate-workflows':\n await runValidateWorkflows();\n return;\n case '--help':\n case '-h':\n case undefined:\n printHelp();\n return;\n default:\n console.error(`Unknown dependency-graph command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nvoid main();\n"],"mappings":"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","names":["readFileSync","resolve","glob","parseYaml","join","existsSync","join","join","existsSync","uniqueSorted","existsSync","parseYaml","existsSync","join","uniqueSorted","uniqueSorted","existsSync","parseYaml","resolve","readFileSync","glob","parseYaml","existsSync","readFileSync","readdirSync","join","resolve","parseYaml","join","existsSync","readdirSync","readFileSync","parseYaml","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/pr-preview.ts","../src/graph/builder.ts","../src/graph/traversal.ts","../src/workspace/discovery.ts","../src/workspace/package-map.ts","../src/workflow/policy.ts","../src/workflow/discovery.ts","../src/workflow/expected-paths.ts","../src/workflow/impact.ts","../src/workflow/validator.ts","../src/workflow/parser.ts","../src/cli/validate-workflows.ts","../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { glob } from 'glob';\nimport { parse as parseYaml } from 'yaml';\n\n// Import dependency graph functions from parent module\nimport {\n discoverWorkspaces,\n buildDependencyGraph,\n findAffectedPackages,\n getWorkflowImpacts,\n validateWorkflows,\n type WorkspacePackage,\n type WorkflowValidationResult,\n} from '../index';\n\ninterface ChangedFile {\n path: string;\n status: 'modified' | 'added' | 'deleted';\n}\n\ninterface DeploymentIndicator {\n file?: string;\n field?: string;\n dependency?: string;\n}\n\ninterface PlatformDetection {\n platform: string;\n indicators: DeploymentIndicator[];\n}\n\n// Convention-based deployment detection (order matters - most specific first)\nconst PLATFORM_INDICATORS: PlatformDetection[] = [\n {\n platform: 'cloudflare-workers',\n indicators: [{ file: 'wrangler.toml' }],\n },\n {\n platform: 'expo',\n indicators: [{ file: 'app.json' }, { file: 'eas.json' }],\n },\n {\n platform: 'npm-package',\n indicators: [{ field: 'bin' }],\n },\n {\n platform: 'electron',\n indicators: [\n { dependency: 'electron' },\n { dependency: 'electron-builder' },\n ],\n },\n {\n platform: 'next.js',\n indicators: [\n { file: 'next.config.js' },\n { file: 'next.config.mjs' },\n { file: 'next.config.ts' },\n { dependency: 'next' },\n ],\n },\n {\n platform: 'node.js',\n indicators: [\n { field: 'start' }, // has start script\n ],\n },\n];\n\nconst DEFAULT_APP_DIRECTORIES = ['apps'];\n\nexport function formatWorkflowPathDrift(\n validationResults: WorkflowValidationResult[],\n): string[] {\n const invalidResults = validationResults.filter((result) => !result.valid);\n if (invalidResults.length === 0) {\n return [];\n }\n\n const lines = [\n '⚠️ Workflow path drift (advisory - does not affect impact above):',\n ];\n\n for (const result of invalidResults) {\n lines.push(` ${result.workflow} (${result.targetPackage}):`);\n\n for (const issue of result.issues) {\n if (issue.kind === 'missing') {\n lines.push(` + ${issue.message}`);\n } else if (issue.kind === 'unnecessary') {\n lines.push(` - ${issue.message}`);\n } else {\n lines.push(` ! ${issue.message}`);\n }\n }\n }\n\n return lines;\n}\n\nfunction isDeployableApp(pkg: WorkspacePackage): {\n deployable: boolean;\n platform?: string;\n} {\n // Check if package is in apps directory (configurable in future)\n const isInAppDirectory = DEFAULT_APP_DIRECTORIES.some(\n (dir) => pkg.path.includes(`/${dir}/`) || pkg.path.endsWith(`/${dir}`),\n );\n\n if (!isInAppDirectory) {\n return { deployable: false };\n }\n\n // Detect platform based on indicators\n for (const platformDetection of PLATFORM_INDICATORS) {\n const hasIndicators = platformDetection.indicators.some((indicator) => {\n if (indicator.file) {\n try {\n const filePath = resolve(pkg.path, indicator.file);\n readFileSync(filePath, 'utf-8');\n return true;\n } catch {\n return false;\n }\n }\n\n if (indicator.field) {\n const scripts = pkg.packageJson.scripts as\n | Record<string, string>\n | undefined;\n if (indicator.field === 'start' && scripts?.start) {\n return true;\n }\n const packageJsonField =\n pkg.packageJson[indicator.field as keyof typeof pkg.packageJson];\n if (indicator.field !== 'start' && packageJsonField) {\n return true;\n }\n }\n\n if (indicator.dependency) {\n return !!(\n pkg.dependencies[indicator.dependency] ||\n pkg.devDependencies[indicator.dependency]\n );\n }\n\n return false;\n });\n\n if (hasIndicators) {\n return { deployable: true, platform: platformDetection.platform };\n }\n }\n\n // If in apps directory but no specific platform detected, not deployable\n return { deployable: false };\n}\n\nasync function getChangedFiles(): Promise<ChangedFile[]> {\n const { execSync } = await import('node:child_process');\n\n try {\n // Try local production first, then fall back to origin/production\n let baseBranch = 'production';\n try {\n execSync('git rev-parse production', {\n encoding: 'utf-8',\n stdio: 'pipe',\n });\n } catch {\n baseBranch = 'origin/production';\n }\n\n const output = execSync(`git diff --name-status ${baseBranch}...HEAD`, {\n encoding: 'utf-8',\n });\n\n return output\n .trim()\n .split('\\n')\n .filter((line) => line)\n .map((line) => {\n const [status, path] = line.split('\\t');\n\n return {\n path: path ?? '',\n status:\n status === 'D' ? 'deleted' : status === 'A' ? 'added' : 'modified',\n };\n })\n .filter((file): file is ChangedFile => file.path !== '');\n } catch {\n console.error(\n 'Failed to get changed files. Ensure you are on a branch with commits compared to production.',\n );\n process.exit(1);\n }\n}\n\nexport async function runPrPreview(): Promise<void> {\n try {\n const rootDir = resolve(process.cwd());\n const changedFiles = await getChangedFiles();\n\n console.log(\n `\\n📦 Release Preview - Changed Files: ${changedFiles.length}\\n`,\n );\n\n changedFiles.forEach((file) => {\n console.log(` ${file.status === 'deleted' ? '❌' : '📝'} ${file.path}`);\n });\n\n const packages = await discoverWorkspaces(rootDir, {\n fs: {\n readFile: (path) => {\n try {\n return Promise.resolve(readFileSync(path, 'utf-8'));\n } catch {\n return Promise.reject(new Error(`Failed to read file: ${path}`));\n }\n },\n exists: (path) => {\n try {\n readFileSync(path, 'utf-8');\n return Promise.resolve(true);\n } catch {\n return Promise.resolve(false);\n }\n },\n },\n glob: {\n glob: async (pattern, options) => glob(pattern, options),\n },\n yaml: {\n parse: (content) => parseYaml(content) as Record<string, unknown>,\n },\n });\n\n const graph = buildDependencyGraph(packages);\n const changedPackages = new Set<string>();\n\n for (const file of changedFiles) {\n if (file.status === 'deleted') continue;\n\n // Convert absolute package paths to relative for comparison\n const pkg = packages.find((p) => {\n const relativePkgPath = p.path.replace(rootDir + '/', '');\n return file.path.startsWith(relativePkgPath);\n });\n\n if (pkg) {\n changedPackages.add(pkg.name);\n }\n }\n\n const workflowImpacts = getWorkflowImpacts(\n rootDir,\n packages,\n changedFiles.map((file) => file.path),\n );\n const workflowDriftLines = formatWorkflowPathDrift(\n await validateWorkflows(rootDir),\n );\n\n const workflowAffectedApps = new Set(\n workflowImpacts.map(\n (workflowImpact) =>\n workflowImpact.targetPackage ?? workflowImpact.targetSlug,\n ),\n );\n\n console.log(\n `\\n📦 Changed packages: ${Array.from(changedPackages).join(', ') || 'none'}\\n`,\n );\n\n if (changedPackages.size === 0 && workflowAffectedApps.size === 0) {\n console.log(\n '\\n✨ No packages or workflow filters changed - no deployments needed\\n',\n );\n if (workflowDriftLines.length > 0) {\n console.log(workflowDriftLines.join('\\n'));\n console.log('');\n }\n return;\n }\n\n const affected = findAffectedPackages(changedPackages, graph, {\n direction: 'upstream',\n respectAffectsUpstream: true,\n });\n\n // Find all deployable apps (affected and unaffected)\n const allDeployableApps = packages\n .map((pkg) => {\n const detection = isDeployableApp(pkg);\n return detection.deployable\n ? { name: pkg.name, pkg, platform: detection.platform }\n : null;\n })\n .filter(\n (\n item,\n ): item is {\n name: string;\n pkg: WorkspacePackage;\n platform: string | undefined;\n } => item !== null,\n );\n\n // Categorize apps by deployment type\n const affectedApps = allDeployableApps.filter(\n (app): app is NonNullable<typeof app> =>\n affected.has(app.name) || workflowAffectedApps.has(app.name),\n );\n const unaffectedApps = allDeployableApps.filter(\n (app): app is NonNullable<typeof app> =>\n !affected.has(app.name) && !workflowAffectedApps.has(app.name),\n );\n\n // Separate deploys (web-based) vs releases (installed)\n const getAppCategory = (platform?: string) => {\n switch (platform) {\n case 'next.js':\n case 'cloudflare-workers':\n case 'node.js':\n return 'deploy';\n case 'expo':\n case 'electron':\n case 'npm-package':\n return 'release';\n default:\n return 'deploy'; // default to deploy for generic\n }\n };\n\n const getAppIcon = (platform?: string) => {\n switch (platform) {\n case 'next.js':\n case 'cloudflare-workers':\n case 'node.js':\n return '🌐';\n case 'expo':\n return '📱';\n case 'electron':\n return '🖥️';\n case 'npm-package':\n return '⚡';\n default:\n return '🌐';\n }\n };\n\n const affectedDeploys = affectedApps.filter(\n (app): app is NonNullable<typeof app> =>\n getAppCategory(app.platform) === 'deploy',\n );\n const affectedReleases = affectedApps.filter(\n (app): app is NonNullable<typeof app> =>\n getAppCategory(app.platform) === 'release',\n );\n\n console.log(`\\n🚀 PR Preview\\n`);\n\n if (affectedApps.length === 0) {\n console.log('No apps affected by changes.\\n');\n } else {\n if (affectedDeploys.length > 0) {\n console.log('📋 Apps that will be DEPLOYED:');\n for (const item of affectedDeploys) {\n const platformDisplay =\n item.platform === 'generic' ? '' : ` (${item.platform})`;\n const icon = getAppIcon(item.platform);\n console.log(`${icon} ${item.name}${platformDisplay}`);\n }\n console.log('');\n }\n\n if (affectedReleases.length > 0) {\n console.log('📋 Apps that will be RELEASED:');\n for (const item of affectedReleases) {\n const platformDisplay =\n item.platform === 'generic' ? '' : ` (${item.platform})`;\n const icon = getAppIcon(item.platform);\n console.log(`${icon} ${item.name}${platformDisplay}`);\n }\n console.log('');\n }\n }\n\n if (unaffectedApps.length > 0) {\n console.log(`📋 Apps that will NOT be affected:`);\n for (const item of unaffectedApps) {\n const platformDisplay =\n item.platform === 'generic' ? '' : ` (${item.platform})`;\n console.log(`⏭️ ${item.name}${platformDisplay}`);\n }\n console.log('');\n }\n\n console.log(`Legend:`);\n console.log(`🌐 = Deploy (web-based, instant updates)`);\n console.log(`📱 = Release (mobile app, user installs)`);\n console.log(`🖥️ = Release (desktop app, user installs)`);\n console.log(`⚡ = Release (CLI tool, user installs)`);\n console.log(`⏭️ = Unaffected (no changes needed)`);\n console.log(`📝 = File changed`);\n console.log(`❌ = File deleted\\n`);\n\n if (workflowDriftLines.length > 0) {\n console.log(workflowDriftLines.join('\\n'));\n console.log('');\n }\n } catch (error) {\n console.error(\n 'Error:',\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n}\n\nif (import.meta.url === new URL(process.argv[1] ?? '', 'file:').href) {\n void runPrPreview();\n}\n","import type { WorkspacePackage, DependencyGraph } from './types';\n\nexport function buildDependencyGraph(\n packages: WorkspacePackage[],\n): DependencyGraph {\n const graph: DependencyGraph = {\n packages: new Map(),\n dependsOn: new Map(),\n dependedBy: new Map(),\n };\n\n for (const pkg of packages) {\n graph.packages.set(pkg.name, pkg);\n graph.dependsOn.set(pkg.name, new Set());\n graph.dependedBy.set(pkg.name, new Set());\n }\n\n for (const pkg of packages) {\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n for (const depName of Object.keys(allDeps)) {\n const matchedPkg = findMatchingPackage(depName, packages);\n\n if (matchedPkg) {\n graph.dependsOn.get(pkg.name)!.add(matchedPkg.name);\n graph.dependedBy.get(matchedPkg.name)!.add(pkg.name);\n }\n }\n }\n\n return graph;\n}\n\nfunction findMatchingPackage(\n depName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((p) => p.name === depName);\n if (match) return match;\n\n match = packages.find((p) => p.name === `@repo/${depName}`);\n if (match) return match;\n\n const nameWithoutRepo = depName.replace(/^@repo\\//, '');\n match = packages.find((p) => p.name === nameWithoutRepo);\n if (match) return match;\n\n return undefined;\n}\n","import type { DependencyGraph, TraversalOptions } from './types';\n\nexport function findAffectedPackages(\n startingPackages: Set<string>,\n graph: DependencyGraph,\n options: TraversalOptions = {},\n): Set<string> {\n const {\n direction = 'upstream',\n maxDepth = Infinity,\n filter,\n respectAffectsUpstream = false,\n } = options;\n\n const affected = new Set<string>(startingPackages);\n const queue: Array<{ name: string; depth: number }> = Array.from(\n startingPackages,\n ).map((name) => ({ name, depth: 0 }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (visited.has(current.name)) continue;\n visited.add(current.name);\n\n if (current.depth >= maxDepth) {\n continue;\n }\n\n const pkg = graph.packages.get(current.name);\n if (!pkg) continue;\n\n if (respectAffectsUpstream && direction === 'upstream') {\n const release = pkg.packageJson.release;\n if (release && release.affectsUpstream === false) {\n continue;\n }\n }\n\n const nextPackages = new Set<string>();\n\n if (direction === 'upstream' || direction === 'both') {\n const upstream = graph.dependedBy.get(current.name) || new Set();\n upstream.forEach((p) => nextPackages.add(p));\n }\n\n if (direction === 'downstream' || direction === 'both') {\n const downstream = graph.dependsOn.get(current.name) || new Set();\n downstream.forEach((p) => nextPackages.add(p));\n }\n\n for (const pkgName of nextPackages) {\n const nextPkg = graph.packages.get(pkgName);\n\n if (filter && nextPkg && !filter(nextPkg)) {\n continue;\n }\n\n if (!affected.has(pkgName)) {\n affected.add(pkgName);\n queue.push({ name: pkgName, depth: current.depth + 1 });\n }\n }\n }\n\n return affected;\n}\n\nexport function findDependencyPath(\n from: string,\n to: string,\n graph: DependencyGraph,\n): string[] | null {\n const queue: string[][] = [[from]];\n const visited = new Set<string>([from]);\n\n while (queue.length > 0) {\n const path = queue.shift()!;\n const current = path[path.length - 1];\n\n if (!current) {\n continue;\n }\n\n if (current === to) {\n return path;\n }\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n if (!visited.has(dependent)) {\n visited.add(dependent);\n queue.push([...path, dependent]);\n }\n }\n }\n\n return null;\n}\n\nexport function findAllPaths(\n from: string,\n to: string,\n graph: DependencyGraph,\n maxPaths = 10,\n): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n function dfs(current: string, path: string[]): void {\n if (paths.length >= maxPaths) return;\n\n if (current === to) {\n paths.push([...path]);\n return;\n }\n\n if (visited.has(current)) return;\n visited.add(current);\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n dfs(dependent, [...path, dependent]);\n }\n\n visited.delete(current);\n }\n\n dfs(from, [from]);\n return paths;\n}\n","import { join, resolve } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport type {\n FileSystemClient,\n GlobClient,\n YamlClient,\n} from '../types/clients';\n\nexport interface WorkspaceConfig {\n packages: string[];\n}\n\nexport interface WorkspaceDiscoveryConfig {\n fs: FileSystemClient;\n glob: GlobClient;\n yaml: YamlClient;\n}\n\nexport async function discoverWorkspaces(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspacePackage[]> {\n const workspaceConfig = await loadWorkspaceConfig(rootDir, config);\n const packages: WorkspacePackage[] = [];\n\n for (const pattern of workspaceConfig.packages) {\n if (pattern.startsWith('!')) continue;\n\n const pkgDirs = await findPackageDirectories(rootDir, pattern, config);\n\n for (const pkgDir of pkgDirs) {\n const pkgJsonPath = join(pkgDir, 'package.json');\n\n try {\n const pkgJsonContent: string = await config.fs.readFile(\n pkgJsonPath,\n 'utf-8',\n );\n const pkgJson = JSON.parse(pkgJsonContent) as {\n name: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n };\n\n packages.push({\n name: pkgJson.name,\n version: pkgJson.version || '0.0.0',\n path: pkgDir,\n packageJson: pkgJson,\n dependencies: pkgJson.dependencies || {},\n devDependencies: pkgJson.devDependencies || {},\n });\n } catch {\n continue;\n }\n }\n }\n\n return packages;\n}\n\nasync function loadWorkspaceConfig(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspaceConfig> {\n const workspaceFilePath = join(rootDir, 'pnpm-workspace.yaml');\n\n try {\n const content: string = await config.fs.readFile(\n workspaceFilePath,\n 'utf-8',\n );\n const parsed = config.yaml.parse(content) as WorkspaceConfig;\n return parsed;\n } catch {\n return { packages: [] };\n }\n}\n\nasync function findPackageDirectories(\n rootDir: string,\n pattern: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<string[]> {\n const matches: string[] = await config.glob.glob(pattern, {\n cwd: rootDir,\n absolute: false,\n ignore: ['**/node_modules/**', '**/.next/**', '**/dist/**'],\n });\n\n return matches.map((match: string) => resolve(rootDir, match));\n}\n","import { existsSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\n\nexport interface MappedWorkspacePath {\n filesystemPath: string;\n workflowPath: string | null;\n}\n\nexport interface WorkspacePackageMap {\n packageMap: Map<string, MappedWorkspacePath>;\n workspaceRoots: Set<string>;\n}\n\nexport function normalizeRelativePath(path: string): string {\n return path.split(sep).join('/');\n}\n\nfunction resolveWorkflowPath(\n relativePath: string,\n rootDir: string,\n): string | null {\n if (!relativePath.startsWith('../')) {\n return relativePath;\n }\n\n const segments = relativePath.split('/');\n\n for (let index = 0; index < segments.length; index += 1) {\n const candidateSegments = segments.slice(index);\n if (candidateSegments.length === 0 || candidateSegments[0] === '..') {\n continue;\n }\n\n const candidatePath = candidateSegments.join('/');\n if (existsSync(join(rootDir, candidatePath))) {\n return candidatePath;\n }\n }\n\n return null;\n}\n\nexport function buildPackageMap(\n packages: WorkspacePackage[],\n rootDir: string,\n): WorkspacePackageMap {\n const packageMap = new Map<string, MappedWorkspacePath>();\n const workspaceRoots = new Set<string>();\n\n for (const pkg of packages) {\n const relativePath = normalizeRelativePath(relative(rootDir, pkg.path));\n const workflowPath = resolveWorkflowPath(relativePath, rootDir);\n\n packageMap.set(pkg.name, {\n filesystemPath: relativePath,\n workflowPath,\n });\n\n if (!workflowPath) {\n continue;\n }\n\n const [workspaceRoot] = workflowPath.split('/');\n if (workspaceRoot) {\n workspaceRoots.add(workspaceRoot);\n }\n }\n\n return {\n packageMap,\n workspaceRoots,\n };\n}\n","import type { WorkflowValidationPolicy } from './types';\n\nexport const defaultWorkflowValidationPolicy: WorkflowValidationPolicy = {\n workflowFilePatterns: ['deploy-*.yml', 'release-*.yml'],\n allowedRootPaths: [\n 'package.json',\n 'pnpm-lock.yaml',\n 'pnpm-workspace.yaml',\n 'turbo.json',\n ],\n includeDevDependenciesForRootPackage: true,\n includeDevDependenciesTransitively: false,\n};\n","import { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\nfunction patternToRegExp(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp(`^${escaped.replace(/\\*/g, '.*')}$`);\n}\n\nexport function discoverWorkflowTargets(\n rootDir: string,\n packages: WorkspacePackage[],\n policy: WorkflowValidationPolicy,\n): WorkflowTarget[] {\n const workflowsDir = join(rootDir, '.github/workflows');\n if (!existsSync(workflowsDir)) {\n return [];\n }\n\n const { packageMap } = buildPackageMap(packages, rootDir);\n const appPackages = packages.filter((pkg) =>\n packageMap.get(pkg.name)?.workflowPath?.startsWith('apps/'),\n );\n const bySlug = new Map<string, string>();\n\n for (const pkg of appPackages) {\n const relativePath = packageMap.get(pkg.name)?.workflowPath;\n if (!relativePath) {\n continue;\n }\n\n const slug = relativePath.split('/').at(-1);\n if (slug) {\n bySlug.set(slug, pkg.name);\n }\n }\n\n const allowedPatterns = policy.workflowFilePatterns.map(patternToRegExp);\n const files = readdirSync(workflowsDir)\n .filter((file) => file.endsWith('.yml'))\n .filter((file) => allowedPatterns.some((pattern) => pattern.test(file)));\n\n return files\n .map((workflowFile) => {\n const match = /^(?:deploy|release)-(.+)\\.yml$/.exec(workflowFile);\n const targetSlug = match?.[1] ?? workflowFile.replace(/\\.yml$/, '');\n\n return {\n workflowFile,\n workflowPath: `.github/workflows/${workflowFile}`,\n targetSlug,\n targetPackage: bySlug.get(targetSlug) ?? null,\n };\n })\n .sort((a, b) => a.workflowFile.localeCompare(b.workflowFile));\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\ninterface ExpectedPathsOptions {\n workflowTarget: WorkflowTarget;\n packages: WorkspacePackage[];\n packageMap: Map<string, { workflowPath: string | null }>;\n policy: WorkflowValidationPolicy;\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction resolveWorkspaceDependency(\n dependencyName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((pkg) => pkg.name === dependencyName);\n if (match) {\n return match;\n }\n\n match = packages.find((pkg) => pkg.name === `@repo/${dependencyName}`);\n if (match) {\n return match;\n }\n\n const nameWithoutRepo = dependencyName.replace(/^@repo\\//, '');\n return packages.find((pkg) => pkg.name === nameWithoutRepo);\n}\n\nfunction collectWorkspaceDependencyNames(\n pkg: WorkspacePackage,\n packages: WorkspacePackage[],\n visited: Set<string>,\n includeDevDependencies: boolean,\n includeDevDependenciesTransitively: boolean,\n): Set<string> {\n const collected = new Set<string>();\n const dependencyEntries = Object.entries(pkg.dependencies);\n const devDependencyEntries = includeDevDependencies\n ? Object.entries(pkg.devDependencies)\n : [];\n\n for (const [dependencyName] of [\n ...dependencyEntries,\n ...devDependencyEntries,\n ]) {\n const dependency = resolveWorkspaceDependency(dependencyName, packages);\n if (!dependency || visited.has(dependency.name)) {\n continue;\n }\n\n visited.add(dependency.name);\n collected.add(dependency.name);\n\n const nestedDependencies = collectWorkspaceDependencyNames(\n dependency,\n packages,\n visited,\n includeDevDependenciesTransitively,\n includeDevDependenciesTransitively,\n );\n\n for (const nestedDependency of nestedDependencies) {\n collected.add(nestedDependency);\n }\n }\n\n return collected;\n}\n\nexport function getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n}: ExpectedPathsOptions): string[] {\n const targetPackageName = workflowTarget.targetPackage;\n if (!targetPackageName) {\n return [];\n }\n\n const targetPackage = packages.find((pkg) => pkg.name === targetPackageName);\n if (!targetPackage) {\n return [];\n }\n\n const dependencyNames = collectWorkspaceDependencyNames(\n targetPackage,\n packages,\n new Set<string>(),\n policy.includeDevDependenciesForRootPackage,\n policy.includeDevDependenciesTransitively,\n );\n\n const expectedPaths: string[] = [];\n const targetPackagePath = packageMap.get(targetPackageName)?.workflowPath;\n if (targetPackagePath) {\n expectedPaths.push(`${targetPackagePath}/**`);\n }\n\n for (const dependencyName of dependencyNames) {\n const dependencyPath = packageMap.get(dependencyName)?.workflowPath;\n if (dependencyPath) {\n expectedPaths.push(`${dependencyPath}/**`);\n }\n }\n\n return uniqueSorted(expectedPaths);\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { defaultWorkflowValidationPolicy } from './policy';\nimport type { WorkflowImpact, WorkflowValidationPolicy } from './types';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction mergeWorkflowPolicy(\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowValidationPolicy {\n return {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n}\n\n// Path matching intentionally only supports exact paths and /** prefix matching\n// because that mirrors the workflow filters currently used in these repos.\nexport function matchesWorkflowPathFilter(\n changedPath: string,\n workflowPathFilter: string,\n): boolean {\n if (workflowPathFilter === changedPath) {\n return true;\n }\n\n if (!workflowPathFilter.endsWith('/**')) {\n return false;\n }\n\n const workflowPrefix = workflowPathFilter.slice(0, -3);\n return changedPath.startsWith(`${workflowPrefix}/`);\n}\n\nexport function getWorkflowImpacts(\n rootDir: string,\n packages: WorkspacePackage[],\n changedPaths: string[],\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowImpact[] {\n const policy = mergeWorkflowPolicy(policyOverrides);\n const workflowTargets = discoverWorkflowTargets(rootDir, packages, policy);\n const { packageMap } = buildPackageMap(packages, rootDir);\n\n return workflowTargets\n .map((workflowTarget) => {\n const calculatedPaths = uniqueSorted([\n ...getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n }),\n ...policy.allowedRootPaths,\n workflowTarget.workflowPath,\n ]);\n const matchedPaths = calculatedPaths.filter((calculatedPath) =>\n changedPaths.some((changedPath) =>\n matchesWorkflowPathFilter(changedPath, calculatedPath),\n ),\n );\n\n return {\n ...workflowTarget,\n matchedPaths: uniqueSorted(matchedPaths),\n } satisfies WorkflowImpact;\n })\n .filter((workflowImpact) => workflowImpact.matchedPaths.length > 0);\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { glob } from 'glob';\nimport { parse as parseYaml } from 'yaml';\nimport { discoverWorkspaces } from '../workspace/discovery';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type {\n WorkflowValidationIssue,\n WorkflowValidationPolicy,\n WorkflowValidationResult,\n} from './types';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { parseWorkflowFile } from './parser';\nimport { defaultWorkflowValidationPolicy } from './policy';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction buildBroadWildcards(workspaceRoots: Set<string>): Set<string> {\n const wildcards = new Set<string>();\n\n for (const root of workspaceRoots) {\n wildcards.add(`${root}/*`);\n wildcards.add(`${root}/**`);\n }\n\n return wildcards;\n}\n\nfunction hasGlobSyntax(path: string): boolean {\n return /[*?[\\]{}]/.test(path);\n}\n\nfunction getStalePathCheckBase(\n path: string,\n allowedRootPaths: string[],\n workflowPath: string,\n): string | null {\n if (\n path === workflowPath ||\n allowedRootPaths.includes(path) ||\n path.startsWith('!')\n ) {\n return null;\n }\n\n const trailingGlobSuffix = path.endsWith('/**')\n ? '/**'\n : path.endsWith('/*')\n ? '/*'\n : null;\n const checkBase = trailingGlobSuffix\n ? path.slice(0, -trailingGlobSuffix.length)\n : path;\n\n if (!checkBase || hasGlobSyntax(checkBase)) {\n return null;\n }\n\n if (!trailingGlobSuffix && hasGlobSyntax(path)) {\n return null;\n }\n\n return checkBase;\n}\n\nfunction splitActualPaths(\n paths: string[],\n workspaceRoots: Set<string>,\n allowedRootPaths: string[],\n workflowPath: string,\n): { workspacePaths: string[]; ignoredPaths: string[] } {\n const workspacePaths: string[] = [];\n const ignoredPaths: string[] = [];\n\n for (const path of paths) {\n if (path === workflowPath || allowedRootPaths.includes(path)) {\n ignoredPaths.push(path);\n continue;\n }\n\n const [rootSegment] = path.split('/');\n if (rootSegment && workspaceRoots.has(rootSegment)) {\n workspacePaths.push(path);\n continue;\n }\n\n ignoredPaths.push(path);\n }\n\n return {\n workspacePaths: uniqueSorted(workspacePaths),\n ignoredPaths: uniqueSorted(ignoredPaths),\n };\n}\n\nfunction isCoveredByExpectedPath(\n actualPath: string,\n expectedPaths: string[],\n): boolean {\n return expectedPaths.some((expectedPath) => {\n if (expectedPath === actualPath) {\n return true;\n }\n\n if (!expectedPath.endsWith('/**')) {\n return false;\n }\n\n const expectedPrefix = expectedPath.slice(0, -3);\n return actualPath.startsWith(`${expectedPrefix}/`);\n });\n}\n\nfunction validateWorkflowResult(\n workflow: string,\n targetPackage: string,\n expectedPaths: string[],\n actualPaths: string[],\n broadWildcards: Set<string>,\n additionalIssues: WorkflowValidationIssue[] = [],\n): WorkflowValidationResult {\n const issues: WorkflowValidationIssue[] = [];\n const missing = expectedPaths.filter((path) => !actualPaths.includes(path));\n const unnecessary = actualPaths.filter(\n (path) => !isCoveredByExpectedPath(path, expectedPaths),\n );\n\n for (const path of missing) {\n issues.push({\n kind: 'missing',\n path,\n message: `Missing path '${path}'`,\n });\n }\n\n for (const path of unnecessary) {\n issues.push({\n kind: 'unnecessary',\n path,\n message: `Unnecessary path '${path}'`,\n });\n }\n\n for (const path of actualPaths) {\n if (broadWildcards.has(path)) {\n issues.push({\n kind: 'broad-wildcard',\n path,\n message: `Uses broad wildcard '${path}' which triggers on all workspace changes under that root`,\n });\n }\n }\n\n issues.push(...additionalIssues);\n\n return {\n workflow,\n targetPackage,\n valid: issues.length === 0,\n expectedPaths,\n actualPaths,\n missing,\n unnecessary,\n issues,\n };\n}\n\nfunction getStalePathIssues(\n ignoredPaths: string[],\n rootDir: string,\n allowedRootPaths: string[],\n workflowPath: string,\n): WorkflowValidationIssue[] {\n return ignoredPaths.flatMap((path) => {\n const checkBase = getStalePathCheckBase(\n path,\n allowedRootPaths,\n workflowPath,\n );\n\n if (!checkBase || existsSync(join(rootDir, checkBase))) {\n return [];\n }\n\n return [\n {\n kind: 'stale-path',\n path,\n message: `Stale path '${path}' does not exist`,\n },\n ];\n });\n}\n\nexport async function validateWorkflows(\n rootDir: string,\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): Promise<WorkflowValidationResult[]> {\n const discoveredPackages = await discoverWorkspaces(rootDir, {\n fs: {\n readFile: (path, encoding) => readFile(path, encoding),\n exists: (path) => Promise.resolve(existsSync(path)),\n },\n glob: {\n glob: (pattern, options) => glob(pattern, options),\n },\n yaml: {\n parse: (content): unknown => parseYaml(content),\n },\n });\n\n const policy: WorkflowValidationPolicy = {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n\n const { packageMap, workspaceRoots } = buildPackageMap(\n discoveredPackages,\n rootDir,\n );\n const workflowTargets = discoverWorkflowTargets(\n rootDir,\n discoveredPackages,\n policy,\n );\n const broadWildcards = buildBroadWildcards(workspaceRoots);\n\n return workflowTargets.map((workflowTarget) => {\n if (!workflowTarget.targetPackage) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetSlug,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'config-error',\n message: `Could not resolve workflow target package for '${workflowTarget.workflowFile}'`,\n },\n ],\n };\n }\n\n try {\n const parsedWorkflow = parseWorkflowFile(\n workflowTarget.workflowFile,\n rootDir,\n );\n\n if (parsedWorkflow.paths.length === 0) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: true,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [],\n };\n }\n\n const { workspacePaths: actualPaths, ignoredPaths } = splitActualPaths(\n parsedWorkflow.paths,\n workspaceRoots,\n policy.allowedRootPaths,\n workflowTarget.workflowPath,\n );\n const expectedPaths = getExpectedWorkflowPaths({\n workflowTarget,\n packages: discoveredPackages,\n packageMap,\n policy,\n });\n\n return validateWorkflowResult(\n workflowTarget.workflowFile,\n workflowTarget.targetPackage,\n expectedPaths,\n actualPaths,\n broadWildcards,\n getStalePathIssues(\n ignoredPaths,\n rootDir,\n policy.allowedRootPaths,\n workflowTarget.workflowPath,\n ),\n );\n } catch (error) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'parse-error',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { ParsedWorkflow } from './types';\n\ninterface WorkflowConfig {\n name?: string;\n on?: {\n push?: {\n paths?: string[];\n };\n pull_request?: {\n paths?: string[];\n };\n };\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nexport function parseWorkflowFile(\n workflowFile: string,\n rootDir: string,\n): ParsedWorkflow {\n const workflowPath = join(rootDir, '.github/workflows', workflowFile);\n\n if (!existsSync(workflowPath)) {\n throw new Error(`Workflow file not found: ${workflowFile}`);\n }\n\n const content = readFileSync(workflowPath, 'utf-8');\n const workflow = parseYaml(content) as WorkflowConfig;\n const pushPaths = workflow.on?.push?.paths ?? [];\n const pullRequestPaths = workflow.on?.pull_request?.paths ?? [];\n\n const parsedWorkflow: ParsedWorkflow = {\n pushPaths: uniqueSorted(pushPaths),\n pullRequestPaths: uniqueSorted(pullRequestPaths),\n paths: uniqueSorted([...pushPaths, ...pullRequestPaths]),\n };\n\n if (workflow.name) {\n parsedWorkflow.name = workflow.name;\n }\n\n return parsedWorkflow;\n}\n","#!/usr/bin/env node\n\nimport { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport { validateWorkflows } from '../workflow/validator';\nimport type { WorkflowValidationResult } from '../workflow/types';\n\ninterface PackageJson {\n packageManager?: string;\n}\n\ninterface PnpmValidationResult {\n valid: boolean;\n workflowIssues: { workflow: string; issue: string }[];\n dockerfileIssues: { dockerfile: string; issue: string }[];\n}\n\nfunction discoverPnpmWorkflows(rootDir: string): string[] {\n const workflowsDir = join(rootDir, '.github/workflows');\n if (!existsSync(workflowsDir)) {\n return [];\n }\n\n const workflows: string[] = [];\n const files = readdirSync(workflowsDir).filter((file) =>\n file.endsWith('.yml'),\n );\n\n for (const file of files) {\n const content = readFileSync(join(workflowsDir, file), 'utf-8');\n if (content.includes('pnpm/action-setup')) {\n workflows.push(file);\n }\n }\n\n return workflows;\n}\n\nfunction discoverPnpmDockerfiles(rootDir: string): string[] {\n const dockerfiles: string[] = [];\n\n for (const entry of readdirSync(rootDir)) {\n if (!entry.startsWith('Dockerfile')) {\n continue;\n }\n\n const content = readFileSync(join(rootDir, entry), 'utf-8');\n if (content.includes('pnpm@')) {\n dockerfiles.push(entry);\n }\n }\n\n const appsDir = join(rootDir, 'apps');\n if (!existsSync(appsDir)) {\n return dockerfiles;\n }\n\n for (const entry of readdirSync(appsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) {\n continue;\n }\n\n const dockerfilePath = join(appsDir, entry.name, 'Dockerfile');\n if (!existsSync(dockerfilePath)) {\n continue;\n }\n\n const content = readFileSync(dockerfilePath, 'utf-8');\n if (content.includes('pnpm@')) {\n dockerfiles.push(`apps/${entry.name}/Dockerfile`);\n }\n }\n\n return dockerfiles;\n}\n\nfunction getExpectedPnpmVersion(rootDir: string): string {\n const packageJson = JSON.parse(\n readFileSync(join(rootDir, 'package.json'), 'utf-8'),\n ) as PackageJson;\n const packageManager = packageJson.packageManager;\n\n if (!packageManager?.startsWith('pnpm@')) {\n throw new Error('packageManager field must specify pnpm version');\n }\n\n return packageManager.replace('pnpm@', '');\n}\n\nfunction checkWorkflowPnpmVersion(\n workflowFile: string,\n rootDir: string,\n): { valid: boolean; issue?: string } {\n const workflowPath = join(rootDir, '.github/workflows', workflowFile);\n if (!existsSync(workflowPath)) {\n return { valid: true };\n }\n\n const content = readFileSync(workflowPath, 'utf-8');\n const workflow = parseYaml(content) as {\n jobs?: Record<\n string,\n { steps?: Array<{ uses?: string; with?: { version?: string | number } }> }\n >;\n };\n\n for (const job of Object.values(workflow.jobs ?? {})) {\n for (const step of job.steps ?? []) {\n if (!step.uses?.startsWith('pnpm/action-setup')) {\n continue;\n }\n\n const version = step.with?.version;\n if (version !== undefined && !/^\\d+$/.test(String(version))) {\n return {\n valid: false,\n issue: `Hardcoded pnpm version '${version}' - remove 'version' key to auto-detect from packageManager`,\n };\n }\n }\n }\n\n return { valid: true };\n}\n\nfunction checkDockerfilePnpmVersion(\n dockerfile: string,\n expectedVersion: string,\n rootDir: string,\n): { valid: boolean; issue?: string } {\n const dockerfilePath = join(rootDir, dockerfile);\n if (!existsSync(dockerfilePath)) {\n return { valid: true };\n }\n\n const content = readFileSync(dockerfilePath, 'utf-8');\n const matches = content.matchAll(/npm install -g pnpm@([\\d.]+)/g);\n\n for (const match of matches) {\n if (match[1] !== expectedVersion) {\n return {\n valid: false,\n issue: `${dockerfile} uses pnpm@${match[1]} but package.json specifies pnpm@${expectedVersion}`,\n };\n }\n }\n\n return { valid: true };\n}\n\nfunction validatePnpmVersions(rootDir: string): PnpmValidationResult {\n const result: PnpmValidationResult = {\n valid: true,\n workflowIssues: [],\n dockerfileIssues: [],\n };\n\n for (const workflowFile of discoverPnpmWorkflows(rootDir)) {\n const check = checkWorkflowPnpmVersion(workflowFile, rootDir);\n if (!check.valid && check.issue) {\n result.valid = false;\n result.workflowIssues.push({\n workflow: workflowFile,\n issue: check.issue,\n });\n }\n }\n\n const expectedVersion = getExpectedPnpmVersion(rootDir);\n for (const dockerfile of discoverPnpmDockerfiles(rootDir)) {\n const check = checkDockerfilePnpmVersion(\n dockerfile,\n expectedVersion,\n rootDir,\n );\n if (!check.valid && check.issue) {\n result.valid = false;\n result.dockerfileIssues.push({ dockerfile, issue: check.issue });\n }\n }\n\n return result;\n}\n\nfunction printResult(result: WorkflowValidationResult): void {\n const icon = result.valid ? '✅' : '❌';\n console.log(`\\n${icon} ${result.workflow} (${result.targetPackage})`);\n\n if (result.valid) {\n console.log(' All paths match dependencies');\n return;\n }\n\n const extraIssues = result.issues.filter(\n (issue) => issue.kind !== 'missing' && issue.kind !== 'unnecessary',\n );\n\n if (extraIssues.length > 0) {\n console.log(' Issues:');\n for (const issue of extraIssues) {\n console.log(` ⚠️ ${issue.message}`);\n }\n }\n\n if (result.missing.length > 0) {\n console.log(' Missing paths:');\n for (const path of result.missing) {\n console.log(` - ${path}`);\n }\n }\n\n if (result.unnecessary.length > 0) {\n console.log(' Unnecessary paths:');\n for (const path of result.unnecessary) {\n console.log(` - ${path}`);\n }\n }\n}\n\nexport async function runValidateWorkflows(): Promise<void> {\n const rootDir = resolve(process.cwd());\n let hasErrors = false;\n\n console.log(\n '🔍 Validating GitHub Actions workflows against dependencies...\\n',\n );\n const results = await validateWorkflows(rootDir);\n console.log(`Found ${results.length} workflow(s) to validate\\n`);\n\n if (results.length === 0) {\n console.log('No deploy-*.yml or release-*.yml workflows found.\\n');\n }\n\n for (const result of results) {\n printResult(result);\n }\n\n const validCount = results.filter((result) => result.valid).length;\n const invalidCount = results.length - validCount;\n\n console.log('\\n' + '='.repeat(60));\n console.log(\n `\\n📊 Path validation: ${validCount} valid, ${invalidCount} invalid\\n`,\n );\n\n if (invalidCount > 0) {\n console.log('❌ Some workflows need updates to match dependencies');\n console.log('\\nTo fix:');\n console.log('1. Update workflow path filters to match missing paths');\n console.log('2. Remove unnecessary paths');\n console.log('3. Replace broad workspace wildcards with specific paths\\n');\n hasErrors = true;\n } else if (results.length > 0) {\n console.log('✅ All workflows match their dependencies!\\n');\n }\n\n console.log('='.repeat(60));\n console.log('\\n🔍 Validating pnpm version consistency...\\n');\n\n const pnpmResult = validatePnpmVersions(rootDir);\n if (!pnpmResult.valid) {\n console.log('❌ PNPM version issues found:\\n');\n for (const { workflow, issue } of pnpmResult.workflowIssues) {\n console.log(` ⚠️ ${workflow}: ${issue}`);\n }\n for (const { issue } of pnpmResult.dockerfileIssues) {\n console.log(` ⚠️ ${issue}`);\n }\n console.log('\\nTo fix:');\n console.log(\n '1. Remove hardcoded pnpm versions from workflows (let pnpm/action-setup auto-detect from packageManager)',\n );\n console.log(\n '2. Update Dockerfile pnpm versions to match package.json packageManager field\\n',\n );\n hasErrors = true;\n } else {\n console.log('✅ PNPM versions are consistent!\\n');\n }\n\n if (hasErrors) {\n process.exit(1);\n }\n}\n\nif (import.meta.url === new URL(process.argv[1] ?? '', 'file:').href) {\n void runValidateWorkflows();\n}\n","#!/usr/bin/env node\n\nimport { runPrPreview } from './pr-preview';\nimport { runValidateWorkflows } from './validate-workflows';\n\nfunction printHelp(): void {\n console.log(`dependency-graph <command>\n\nCommands:\n pr-preview Show affected deploys and releases for the current branch\n validate-workflows Validate workflow path filters and pnpm version consistency`);\n}\n\nasync function main(): Promise<void> {\n const command = process.argv[2];\n\n switch (command) {\n case 'pr-preview':\n await runPrPreview();\n return;\n case 'validate-workflows':\n await runValidateWorkflows();\n return;\n case '--help':\n case '-h':\n case undefined:\n printHelp();\n return;\n default:\n console.error(`Unknown dependency-graph command: ${command}`);\n printHelp();\n process.exit(1);\n }\n}\n\nvoid main();\n"],"mappings":"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","names":["readFileSync","resolve","glob","parseYaml","join","existsSync","join","join","existsSync","uniqueSorted","existsSync","join","parseYaml","existsSync","join","uniqueSorted","uniqueSorted","existsSync","join","parseYaml","resolve","readFileSync","glob","parseYaml","existsSync","readFileSync","readdirSync","join","resolve","parseYaml","join","existsSync","readdirSync","readFileSync","parseYaml","resolve"]}
|
package/dist/index.js
CHANGED
|
@@ -551,6 +551,7 @@ function getWorkflowImpacts(rootDir, packages, changedPaths, policyOverrides) {
|
|
|
551
551
|
// src/workflow/validator.ts
|
|
552
552
|
import { existsSync as existsSync4 } from "fs";
|
|
553
553
|
import { readFile } from "fs/promises";
|
|
554
|
+
import { join as join5 } from "path";
|
|
554
555
|
import { glob } from "glob";
|
|
555
556
|
import { parse as parseYaml2 } from "yaml";
|
|
556
557
|
|
|
@@ -593,6 +594,23 @@ function buildBroadWildcards(workspaceRoots) {
|
|
|
593
594
|
}
|
|
594
595
|
return wildcards;
|
|
595
596
|
}
|
|
597
|
+
function hasGlobSyntax(path) {
|
|
598
|
+
return /[*?[\]{}]/.test(path);
|
|
599
|
+
}
|
|
600
|
+
function getStalePathCheckBase(path, allowedRootPaths, workflowPath) {
|
|
601
|
+
if (path === workflowPath || allowedRootPaths.includes(path) || path.startsWith("!")) {
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
const trailingGlobSuffix = path.endsWith("/**") ? "/**" : path.endsWith("/*") ? "/*" : null;
|
|
605
|
+
const checkBase = trailingGlobSuffix ? path.slice(0, -trailingGlobSuffix.length) : path;
|
|
606
|
+
if (!checkBase || hasGlobSyntax(checkBase)) {
|
|
607
|
+
return null;
|
|
608
|
+
}
|
|
609
|
+
if (!trailingGlobSuffix && hasGlobSyntax(path)) {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
return checkBase;
|
|
613
|
+
}
|
|
596
614
|
function splitActualPaths(paths, workspaceRoots, allowedRootPaths, workflowPath) {
|
|
597
615
|
const workspacePaths = [];
|
|
598
616
|
const ignoredPaths = [];
|
|
@@ -625,7 +643,7 @@ function isCoveredByExpectedPath(actualPath, expectedPaths) {
|
|
|
625
643
|
return actualPath.startsWith(`${expectedPrefix}/`);
|
|
626
644
|
});
|
|
627
645
|
}
|
|
628
|
-
function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPaths, broadWildcards) {
|
|
646
|
+
function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPaths, broadWildcards, additionalIssues = []) {
|
|
629
647
|
const issues = [];
|
|
630
648
|
const missing = expectedPaths.filter((path) => !actualPaths.includes(path));
|
|
631
649
|
const unnecessary = actualPaths.filter(
|
|
@@ -654,6 +672,7 @@ function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPa
|
|
|
654
672
|
});
|
|
655
673
|
}
|
|
656
674
|
}
|
|
675
|
+
issues.push(...additionalIssues);
|
|
657
676
|
return {
|
|
658
677
|
workflow,
|
|
659
678
|
targetPackage,
|
|
@@ -665,6 +684,25 @@ function validateWorkflowResult(workflow, targetPackage, expectedPaths, actualPa
|
|
|
665
684
|
issues
|
|
666
685
|
};
|
|
667
686
|
}
|
|
687
|
+
function getStalePathIssues(ignoredPaths, rootDir, allowedRootPaths, workflowPath) {
|
|
688
|
+
return ignoredPaths.flatMap((path) => {
|
|
689
|
+
const checkBase = getStalePathCheckBase(
|
|
690
|
+
path,
|
|
691
|
+
allowedRootPaths,
|
|
692
|
+
workflowPath
|
|
693
|
+
);
|
|
694
|
+
if (!checkBase || existsSync4(join5(rootDir, checkBase))) {
|
|
695
|
+
return [];
|
|
696
|
+
}
|
|
697
|
+
return [
|
|
698
|
+
{
|
|
699
|
+
kind: "stale-path",
|
|
700
|
+
path,
|
|
701
|
+
message: `Stale path '${path}' does not exist`
|
|
702
|
+
}
|
|
703
|
+
];
|
|
704
|
+
});
|
|
705
|
+
}
|
|
668
706
|
async function validateWorkflows(rootDir, policyOverrides) {
|
|
669
707
|
const discoveredPackages = await discoverWorkspaces(rootDir, {
|
|
670
708
|
fs: {
|
|
@@ -731,7 +769,7 @@ async function validateWorkflows(rootDir, policyOverrides) {
|
|
|
731
769
|
issues: []
|
|
732
770
|
};
|
|
733
771
|
}
|
|
734
|
-
const { workspacePaths: actualPaths } = splitActualPaths(
|
|
772
|
+
const { workspacePaths: actualPaths, ignoredPaths } = splitActualPaths(
|
|
735
773
|
parsedWorkflow.paths,
|
|
736
774
|
workspaceRoots,
|
|
737
775
|
policy.allowedRootPaths,
|
|
@@ -748,7 +786,13 @@ async function validateWorkflows(rootDir, policyOverrides) {
|
|
|
748
786
|
workflowTarget.targetPackage,
|
|
749
787
|
expectedPaths,
|
|
750
788
|
actualPaths,
|
|
751
|
-
broadWildcards
|
|
789
|
+
broadWildcards,
|
|
790
|
+
getStalePathIssues(
|
|
791
|
+
ignoredPaths,
|
|
792
|
+
rootDir,
|
|
793
|
+
policy.allowedRootPaths,
|
|
794
|
+
workflowTarget.workflowPath
|
|
795
|
+
)
|
|
752
796
|
);
|
|
753
797
|
} catch (error) {
|
|
754
798
|
return {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/graph/builder.ts","../src/graph/traversal.ts","../src/graph/analysis.ts","../src/workspace/discovery.ts","../src/workspace/package-map.ts","../src/workspace/file-mapping.ts","../src/workflow/policy.ts","../src/workflow/discovery.ts","../src/workflow/expected-paths.ts","../src/workflow/impact.ts","../src/workflow/validator.ts","../src/workflow/parser.ts"],"sourcesContent":["import type { WorkspacePackage, DependencyGraph } from './types';\n\nexport function buildDependencyGraph(\n packages: WorkspacePackage[],\n): DependencyGraph {\n const graph: DependencyGraph = {\n packages: new Map(),\n dependsOn: new Map(),\n dependedBy: new Map(),\n };\n\n for (const pkg of packages) {\n graph.packages.set(pkg.name, pkg);\n graph.dependsOn.set(pkg.name, new Set());\n graph.dependedBy.set(pkg.name, new Set());\n }\n\n for (const pkg of packages) {\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n for (const depName of Object.keys(allDeps)) {\n const matchedPkg = findMatchingPackage(depName, packages);\n\n if (matchedPkg) {\n graph.dependsOn.get(pkg.name)!.add(matchedPkg.name);\n graph.dependedBy.get(matchedPkg.name)!.add(pkg.name);\n }\n }\n }\n\n return graph;\n}\n\nfunction findMatchingPackage(\n depName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((p) => p.name === depName);\n if (match) return match;\n\n match = packages.find((p) => p.name === `@repo/${depName}`);\n if (match) return match;\n\n const nameWithoutRepo = depName.replace(/^@repo\\//, '');\n match = packages.find((p) => p.name === nameWithoutRepo);\n if (match) return match;\n\n return undefined;\n}\n","import type { DependencyGraph, TraversalOptions } from './types';\n\nexport function findAffectedPackages(\n startingPackages: Set<string>,\n graph: DependencyGraph,\n options: TraversalOptions = {},\n): Set<string> {\n const {\n direction = 'upstream',\n maxDepth = Infinity,\n filter,\n respectAffectsUpstream = false,\n } = options;\n\n const affected = new Set<string>(startingPackages);\n const queue: Array<{ name: string; depth: number }> = Array.from(\n startingPackages,\n ).map((name) => ({ name, depth: 0 }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (visited.has(current.name)) continue;\n visited.add(current.name);\n\n if (current.depth >= maxDepth) {\n continue;\n }\n\n const pkg = graph.packages.get(current.name);\n if (!pkg) continue;\n\n if (respectAffectsUpstream && direction === 'upstream') {\n const release = pkg.packageJson.release;\n if (release && release.affectsUpstream === false) {\n continue;\n }\n }\n\n const nextPackages = new Set<string>();\n\n if (direction === 'upstream' || direction === 'both') {\n const upstream = graph.dependedBy.get(current.name) || new Set();\n upstream.forEach((p) => nextPackages.add(p));\n }\n\n if (direction === 'downstream' || direction === 'both') {\n const downstream = graph.dependsOn.get(current.name) || new Set();\n downstream.forEach((p) => nextPackages.add(p));\n }\n\n for (const pkgName of nextPackages) {\n const nextPkg = graph.packages.get(pkgName);\n\n if (filter && nextPkg && !filter(nextPkg)) {\n continue;\n }\n\n if (!affected.has(pkgName)) {\n affected.add(pkgName);\n queue.push({ name: pkgName, depth: current.depth + 1 });\n }\n }\n }\n\n return affected;\n}\n\nexport function findDependencyPath(\n from: string,\n to: string,\n graph: DependencyGraph,\n): string[] | null {\n const queue: string[][] = [[from]];\n const visited = new Set<string>([from]);\n\n while (queue.length > 0) {\n const path = queue.shift()!;\n const current = path[path.length - 1];\n\n if (!current) {\n continue;\n }\n\n if (current === to) {\n return path;\n }\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n if (!visited.has(dependent)) {\n visited.add(dependent);\n queue.push([...path, dependent]);\n }\n }\n }\n\n return null;\n}\n\nexport function findAllPaths(\n from: string,\n to: string,\n graph: DependencyGraph,\n maxPaths = 10,\n): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n function dfs(current: string, path: string[]): void {\n if (paths.length >= maxPaths) return;\n\n if (current === to) {\n paths.push([...path]);\n return;\n }\n\n if (visited.has(current)) return;\n visited.add(current);\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n dfs(dependent, [...path, dependent]);\n }\n\n visited.delete(current);\n }\n\n dfs(from, [from]);\n return paths;\n}\n","import type { DependencyGraph, GraphStats } from './types';\n\nexport function analyzeGraph(graph: DependencyGraph): GraphStats {\n const leafNodes: string[] = [];\n const rootNodes: string[] = [];\n let totalEdges = 0;\n\n for (const [pkgName, dependents] of graph.dependedBy.entries()) {\n if (dependents.size === 0) {\n leafNodes.push(pkgName);\n }\n totalEdges += dependents.size;\n }\n\n for (const [pkgName, dependencies] of graph.dependsOn.entries()) {\n if (dependencies.size === 0) {\n rootNodes.push(pkgName);\n }\n }\n\n const maxDepth = calculateMaxDepth(graph);\n const cycles = detectCycles(graph);\n\n return {\n totalPackages: graph.packages.size,\n totalEdges,\n maxDepth,\n leafNodes,\n rootNodes,\n cycles,\n };\n}\n\nfunction calculateMaxDepth(graph: DependencyGraph): number {\n let maxDepth = 0;\n\n for (const pkgName of graph.packages.keys()) {\n const depth = getPackageDepth(pkgName, graph);\n if (depth > maxDepth) {\n maxDepth = depth;\n }\n }\n\n return maxDepth;\n}\n\nfunction getPackageDepth(\n pkgName: string,\n graph: DependencyGraph,\n visited = new Set<string>(),\n): number {\n if (visited.has(pkgName)) return 0;\n visited.add(pkgName);\n\n const dependencies = graph.dependsOn.get(pkgName) || new Set();\n if (dependencies.size === 0) return 0;\n\n let maxDepth = 0;\n for (const dep of dependencies) {\n const depth = getPackageDepth(dep, graph, new Set(visited));\n if (depth > maxDepth) {\n maxDepth = depth;\n }\n }\n\n return maxDepth + 1;\n}\n\nexport function detectCycles(graph: DependencyGraph): string[][] {\n const cycles: string[][] = [];\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n\n function dfs(pkgName: string, path: string[]): void {\n visited.add(pkgName);\n recursionStack.add(pkgName);\n path.push(pkgName);\n\n const dependencies = graph.dependsOn.get(pkgName) || new Set();\n for (const dep of dependencies) {\n if (!visited.has(dep)) {\n dfs(dep, [...path]);\n } else if (recursionStack.has(dep)) {\n const cycleStart = path.indexOf(dep);\n if (cycleStart !== -1) {\n const cycle = path.slice(cycleStart);\n cycle.push(dep);\n cycles.push(cycle);\n }\n }\n }\n\n recursionStack.delete(pkgName);\n }\n\n for (const pkgName of graph.packages.keys()) {\n if (!visited.has(pkgName)) {\n dfs(pkgName, []);\n }\n }\n\n return cycles;\n}\n\nexport function getTransitiveDependencies(\n pkgName: string,\n graph: DependencyGraph,\n): Set<string> {\n const transitive = new Set<string>();\n const visited = new Set<string>();\n\n function collect(current: string): void {\n if (visited.has(current)) return;\n visited.add(current);\n\n const deps = graph.dependsOn.get(current) || new Set();\n for (const dep of deps) {\n transitive.add(dep);\n collect(dep);\n }\n }\n\n collect(pkgName);\n return transitive;\n}\n\nexport function getTransitiveDependents(\n pkgName: string,\n graph: DependencyGraph,\n): Set<string> {\n const transitive = new Set<string>();\n const visited = new Set<string>();\n\n function collect(current: string): void {\n if (visited.has(current)) return;\n visited.add(current);\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n transitive.add(dependent);\n collect(dependent);\n }\n }\n\n collect(pkgName);\n return transitive;\n}\n","import { join, resolve } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport type {\n FileSystemClient,\n GlobClient,\n YamlClient,\n} from '../types/clients';\n\nexport interface WorkspaceConfig {\n packages: string[];\n}\n\nexport interface WorkspaceDiscoveryConfig {\n fs: FileSystemClient;\n glob: GlobClient;\n yaml: YamlClient;\n}\n\nexport async function discoverWorkspaces(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspacePackage[]> {\n const workspaceConfig = await loadWorkspaceConfig(rootDir, config);\n const packages: WorkspacePackage[] = [];\n\n for (const pattern of workspaceConfig.packages) {\n if (pattern.startsWith('!')) continue;\n\n const pkgDirs = await findPackageDirectories(rootDir, pattern, config);\n\n for (const pkgDir of pkgDirs) {\n const pkgJsonPath = join(pkgDir, 'package.json');\n\n try {\n const pkgJsonContent: string = await config.fs.readFile(\n pkgJsonPath,\n 'utf-8',\n );\n const pkgJson = JSON.parse(pkgJsonContent) as {\n name: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n };\n\n packages.push({\n name: pkgJson.name,\n version: pkgJson.version || '0.0.0',\n path: pkgDir,\n packageJson: pkgJson,\n dependencies: pkgJson.dependencies || {},\n devDependencies: pkgJson.devDependencies || {},\n });\n } catch {\n continue;\n }\n }\n }\n\n return packages;\n}\n\nasync function loadWorkspaceConfig(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspaceConfig> {\n const workspaceFilePath = join(rootDir, 'pnpm-workspace.yaml');\n\n try {\n const content: string = await config.fs.readFile(\n workspaceFilePath,\n 'utf-8',\n );\n const parsed = config.yaml.parse(content) as WorkspaceConfig;\n return parsed;\n } catch {\n return { packages: [] };\n }\n}\n\nasync function findPackageDirectories(\n rootDir: string,\n pattern: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<string[]> {\n const matches: string[] = await config.glob.glob(pattern, {\n cwd: rootDir,\n absolute: false,\n ignore: ['**/node_modules/**', '**/.next/**', '**/dist/**'],\n });\n\n return matches.map((match: string) => resolve(rootDir, match));\n}\n","import { existsSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\n\nexport interface MappedWorkspacePath {\n filesystemPath: string;\n workflowPath: string | null;\n}\n\nexport interface WorkspacePackageMap {\n packageMap: Map<string, MappedWorkspacePath>;\n workspaceRoots: Set<string>;\n}\n\nexport function normalizeRelativePath(path: string): string {\n return path.split(sep).join('/');\n}\n\nfunction resolveWorkflowPath(\n relativePath: string,\n rootDir: string,\n): string | null {\n if (!relativePath.startsWith('../')) {\n return relativePath;\n }\n\n const segments = relativePath.split('/');\n\n for (let index = 0; index < segments.length; index += 1) {\n const candidateSegments = segments.slice(index);\n if (candidateSegments.length === 0 || candidateSegments[0] === '..') {\n continue;\n }\n\n const candidatePath = candidateSegments.join('/');\n if (existsSync(join(rootDir, candidatePath))) {\n return candidatePath;\n }\n }\n\n return null;\n}\n\nexport function buildPackageMap(\n packages: WorkspacePackage[],\n rootDir: string,\n): WorkspacePackageMap {\n const packageMap = new Map<string, MappedWorkspacePath>();\n const workspaceRoots = new Set<string>();\n\n for (const pkg of packages) {\n const relativePath = normalizeRelativePath(relative(rootDir, pkg.path));\n const workflowPath = resolveWorkflowPath(relativePath, rootDir);\n\n packageMap.set(pkg.name, {\n filesystemPath: relativePath,\n workflowPath,\n });\n\n if (!workflowPath) {\n continue;\n }\n\n const [workspaceRoot] = workflowPath.split('/');\n if (workspaceRoot) {\n workspaceRoots.add(workspaceRoot);\n }\n }\n\n return {\n packageMap,\n workspaceRoots,\n };\n}\n","import type { WorkspacePackage } from '../graph/types';\n\nexport function findPackageForFile(\n filePath: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n const sorted = packages.sort((a, b) => b.path.length - a.path.length);\n\n for (const pkg of sorted) {\n if (filePath.startsWith(pkg.path + '/') || filePath === pkg.path) {\n return pkg;\n }\n }\n\n return undefined;\n}\n\nexport function mapFilesToPackages(\n files: string[],\n packages: WorkspacePackage[],\n): Map<string, string[]> {\n const fileMap = new Map<string, string[]>();\n\n for (const file of files) {\n const pkg = findPackageForFile(file, packages);\n if (pkg) {\n if (!fileMap.has(pkg.name)) {\n fileMap.set(pkg.name, []);\n }\n fileMap.get(pkg.name)!.push(file);\n }\n }\n\n return fileMap;\n}\n","import type { WorkflowValidationPolicy } from './types';\n\nexport const defaultWorkflowValidationPolicy: WorkflowValidationPolicy = {\n workflowFilePatterns: ['deploy-*.yml', 'release-*.yml'],\n allowedRootPaths: [\n 'package.json',\n 'pnpm-lock.yaml',\n 'pnpm-workspace.yaml',\n 'turbo.json',\n ],\n includeDevDependenciesForRootPackage: true,\n includeDevDependenciesTransitively: false,\n};\n","import { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\nfunction patternToRegExp(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp(`^${escaped.replace(/\\*/g, '.*')}$`);\n}\n\nexport function discoverWorkflowTargets(\n rootDir: string,\n packages: WorkspacePackage[],\n policy: WorkflowValidationPolicy,\n): WorkflowTarget[] {\n const workflowsDir = join(rootDir, '.github/workflows');\n if (!existsSync(workflowsDir)) {\n return [];\n }\n\n const { packageMap } = buildPackageMap(packages, rootDir);\n const appPackages = packages.filter((pkg) =>\n packageMap.get(pkg.name)?.workflowPath?.startsWith('apps/'),\n );\n const bySlug = new Map<string, string>();\n\n for (const pkg of appPackages) {\n const relativePath = packageMap.get(pkg.name)?.workflowPath;\n if (!relativePath) {\n continue;\n }\n\n const slug = relativePath.split('/').at(-1);\n if (slug) {\n bySlug.set(slug, pkg.name);\n }\n }\n\n const allowedPatterns = policy.workflowFilePatterns.map(patternToRegExp);\n const files = readdirSync(workflowsDir)\n .filter((file) => file.endsWith('.yml'))\n .filter((file) => allowedPatterns.some((pattern) => pattern.test(file)));\n\n return files\n .map((workflowFile) => {\n const match = /^(?:deploy|release)-(.+)\\.yml$/.exec(workflowFile);\n const targetSlug = match?.[1] ?? workflowFile.replace(/\\.yml$/, '');\n\n return {\n workflowFile,\n workflowPath: `.github/workflows/${workflowFile}`,\n targetSlug,\n targetPackage: bySlug.get(targetSlug) ?? null,\n };\n })\n .sort((a, b) => a.workflowFile.localeCompare(b.workflowFile));\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\ninterface ExpectedPathsOptions {\n workflowTarget: WorkflowTarget;\n packages: WorkspacePackage[];\n packageMap: Map<string, { workflowPath: string | null }>;\n policy: WorkflowValidationPolicy;\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction resolveWorkspaceDependency(\n dependencyName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((pkg) => pkg.name === dependencyName);\n if (match) {\n return match;\n }\n\n match = packages.find((pkg) => pkg.name === `@repo/${dependencyName}`);\n if (match) {\n return match;\n }\n\n const nameWithoutRepo = dependencyName.replace(/^@repo\\//, '');\n return packages.find((pkg) => pkg.name === nameWithoutRepo);\n}\n\nfunction collectWorkspaceDependencyNames(\n pkg: WorkspacePackage,\n packages: WorkspacePackage[],\n visited: Set<string>,\n includeDevDependencies: boolean,\n includeDevDependenciesTransitively: boolean,\n): Set<string> {\n const collected = new Set<string>();\n const dependencyEntries = Object.entries(pkg.dependencies);\n const devDependencyEntries = includeDevDependencies\n ? Object.entries(pkg.devDependencies)\n : [];\n\n for (const [dependencyName] of [\n ...dependencyEntries,\n ...devDependencyEntries,\n ]) {\n const dependency = resolveWorkspaceDependency(dependencyName, packages);\n if (!dependency || visited.has(dependency.name)) {\n continue;\n }\n\n visited.add(dependency.name);\n collected.add(dependency.name);\n\n const nestedDependencies = collectWorkspaceDependencyNames(\n dependency,\n packages,\n visited,\n includeDevDependenciesTransitively,\n includeDevDependenciesTransitively,\n );\n\n for (const nestedDependency of nestedDependencies) {\n collected.add(nestedDependency);\n }\n }\n\n return collected;\n}\n\nexport function getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n}: ExpectedPathsOptions): string[] {\n const targetPackageName = workflowTarget.targetPackage;\n if (!targetPackageName) {\n return [];\n }\n\n const targetPackage = packages.find((pkg) => pkg.name === targetPackageName);\n if (!targetPackage) {\n return [];\n }\n\n const dependencyNames = collectWorkspaceDependencyNames(\n targetPackage,\n packages,\n new Set<string>(),\n policy.includeDevDependenciesForRootPackage,\n policy.includeDevDependenciesTransitively,\n );\n\n const expectedPaths: string[] = [];\n const targetPackagePath = packageMap.get(targetPackageName)?.workflowPath;\n if (targetPackagePath) {\n expectedPaths.push(`${targetPackagePath}/**`);\n }\n\n for (const dependencyName of dependencyNames) {\n const dependencyPath = packageMap.get(dependencyName)?.workflowPath;\n if (dependencyPath) {\n expectedPaths.push(`${dependencyPath}/**`);\n }\n }\n\n return uniqueSorted(expectedPaths);\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { defaultWorkflowValidationPolicy } from './policy';\nimport type { WorkflowImpact, WorkflowValidationPolicy } from './types';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction mergeWorkflowPolicy(\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowValidationPolicy {\n return {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n}\n\n// Path matching intentionally only supports exact paths and /** prefix matching\n// because that mirrors the workflow filters currently used in these repos.\nexport function matchesWorkflowPathFilter(\n changedPath: string,\n workflowPathFilter: string,\n): boolean {\n if (workflowPathFilter === changedPath) {\n return true;\n }\n\n if (!workflowPathFilter.endsWith('/**')) {\n return false;\n }\n\n const workflowPrefix = workflowPathFilter.slice(0, -3);\n return changedPath.startsWith(`${workflowPrefix}/`);\n}\n\nexport function getWorkflowImpacts(\n rootDir: string,\n packages: WorkspacePackage[],\n changedPaths: string[],\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowImpact[] {\n const policy = mergeWorkflowPolicy(policyOverrides);\n const workflowTargets = discoverWorkflowTargets(rootDir, packages, policy);\n const { packageMap } = buildPackageMap(packages, rootDir);\n\n return workflowTargets\n .map((workflowTarget) => {\n const calculatedPaths = uniqueSorted([\n ...getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n }),\n ...policy.allowedRootPaths,\n workflowTarget.workflowPath,\n ]);\n const matchedPaths = calculatedPaths.filter((calculatedPath) =>\n changedPaths.some((changedPath) =>\n matchesWorkflowPathFilter(changedPath, calculatedPath),\n ),\n );\n\n return {\n ...workflowTarget,\n matchedPaths: uniqueSorted(matchedPaths),\n } satisfies WorkflowImpact;\n })\n .filter((workflowImpact) => workflowImpact.matchedPaths.length > 0);\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { glob } from 'glob';\nimport { parse as parseYaml } from 'yaml';\nimport { discoverWorkspaces } from '../workspace/discovery';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type {\n WorkflowValidationIssue,\n WorkflowValidationPolicy,\n WorkflowValidationResult,\n} from './types';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { parseWorkflowFile } from './parser';\nimport { defaultWorkflowValidationPolicy } from './policy';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction buildBroadWildcards(workspaceRoots: Set<string>): Set<string> {\n const wildcards = new Set<string>();\n\n for (const root of workspaceRoots) {\n wildcards.add(`${root}/*`);\n wildcards.add(`${root}/**`);\n }\n\n return wildcards;\n}\n\nfunction splitActualPaths(\n paths: string[],\n workspaceRoots: Set<string>,\n allowedRootPaths: string[],\n workflowPath: string,\n): { workspacePaths: string[]; ignoredPaths: string[] } {\n const workspacePaths: string[] = [];\n const ignoredPaths: string[] = [];\n\n for (const path of paths) {\n if (path === workflowPath || allowedRootPaths.includes(path)) {\n ignoredPaths.push(path);\n continue;\n }\n\n const [rootSegment] = path.split('/');\n if (rootSegment && workspaceRoots.has(rootSegment)) {\n workspacePaths.push(path);\n continue;\n }\n\n ignoredPaths.push(path);\n }\n\n return {\n workspacePaths: uniqueSorted(workspacePaths),\n ignoredPaths: uniqueSorted(ignoredPaths),\n };\n}\n\nfunction isCoveredByExpectedPath(\n actualPath: string,\n expectedPaths: string[],\n): boolean {\n return expectedPaths.some((expectedPath) => {\n if (expectedPath === actualPath) {\n return true;\n }\n\n if (!expectedPath.endsWith('/**')) {\n return false;\n }\n\n const expectedPrefix = expectedPath.slice(0, -3);\n return actualPath.startsWith(`${expectedPrefix}/`);\n });\n}\n\nfunction validateWorkflowResult(\n workflow: string,\n targetPackage: string,\n expectedPaths: string[],\n actualPaths: string[],\n broadWildcards: Set<string>,\n): WorkflowValidationResult {\n const issues: WorkflowValidationIssue[] = [];\n const missing = expectedPaths.filter((path) => !actualPaths.includes(path));\n const unnecessary = actualPaths.filter(\n (path) => !isCoveredByExpectedPath(path, expectedPaths),\n );\n\n for (const path of missing) {\n issues.push({\n kind: 'missing',\n path,\n message: `Missing path '${path}'`,\n });\n }\n\n for (const path of unnecessary) {\n issues.push({\n kind: 'unnecessary',\n path,\n message: `Unnecessary path '${path}'`,\n });\n }\n\n for (const path of actualPaths) {\n if (broadWildcards.has(path)) {\n issues.push({\n kind: 'broad-wildcard',\n path,\n message: `Uses broad wildcard '${path}' which triggers on all workspace changes under that root`,\n });\n }\n }\n\n return {\n workflow,\n targetPackage,\n valid: issues.length === 0,\n expectedPaths,\n actualPaths,\n missing,\n unnecessary,\n issues,\n };\n}\n\nexport async function validateWorkflows(\n rootDir: string,\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): Promise<WorkflowValidationResult[]> {\n const discoveredPackages = await discoverWorkspaces(rootDir, {\n fs: {\n readFile: (path, encoding) => readFile(path, encoding),\n exists: (path) => Promise.resolve(existsSync(path)),\n },\n glob: {\n glob: (pattern, options) => glob(pattern, options),\n },\n yaml: {\n parse: (content): unknown => parseYaml(content),\n },\n });\n\n const policy: WorkflowValidationPolicy = {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n\n const { packageMap, workspaceRoots } = buildPackageMap(\n discoveredPackages,\n rootDir,\n );\n const workflowTargets = discoverWorkflowTargets(\n rootDir,\n discoveredPackages,\n policy,\n );\n const broadWildcards = buildBroadWildcards(workspaceRoots);\n\n return workflowTargets.map((workflowTarget) => {\n if (!workflowTarget.targetPackage) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetSlug,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'config-error',\n message: `Could not resolve workflow target package for '${workflowTarget.workflowFile}'`,\n },\n ],\n };\n }\n\n try {\n const parsedWorkflow = parseWorkflowFile(\n workflowTarget.workflowFile,\n rootDir,\n );\n\n if (parsedWorkflow.paths.length === 0) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: true,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [],\n };\n }\n\n const { workspacePaths: actualPaths } = splitActualPaths(\n parsedWorkflow.paths,\n workspaceRoots,\n policy.allowedRootPaths,\n workflowTarget.workflowPath,\n );\n const expectedPaths = getExpectedWorkflowPaths({\n workflowTarget,\n packages: discoveredPackages,\n packageMap,\n policy,\n });\n\n return validateWorkflowResult(\n workflowTarget.workflowFile,\n workflowTarget.targetPackage,\n expectedPaths,\n actualPaths,\n broadWildcards,\n );\n } catch (error) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'parse-error',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { ParsedWorkflow } from './types';\n\ninterface WorkflowConfig {\n name?: string;\n on?: {\n push?: {\n paths?: string[];\n };\n pull_request?: {\n paths?: string[];\n };\n };\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nexport function parseWorkflowFile(\n workflowFile: string,\n rootDir: string,\n): ParsedWorkflow {\n const workflowPath = join(rootDir, '.github/workflows', workflowFile);\n\n if (!existsSync(workflowPath)) {\n throw new Error(`Workflow file not found: ${workflowFile}`);\n }\n\n const content = readFileSync(workflowPath, 'utf-8');\n const workflow = parseYaml(content) as WorkflowConfig;\n const pushPaths = workflow.on?.push?.paths ?? [];\n const pullRequestPaths = workflow.on?.pull_request?.paths ?? [];\n\n const parsedWorkflow: ParsedWorkflow = {\n pushPaths: uniqueSorted(pushPaths),\n pullRequestPaths: uniqueSorted(pullRequestPaths),\n paths: uniqueSorted([...pushPaths, ...pullRequestPaths]),\n };\n\n if (workflow.name) {\n parsedWorkflow.name = workflow.name;\n }\n\n return parsedWorkflow;\n}\n"],"mappings":"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","names":["join","existsSync","join","join","existsSync","uniqueSorted","existsSync","parseYaml","existsSync","join","uniqueSorted","uniqueSorted","existsSync","parseYaml"]}
|
|
1
|
+
{"version":3,"sources":["../src/graph/builder.ts","../src/graph/traversal.ts","../src/graph/analysis.ts","../src/workspace/discovery.ts","../src/workspace/package-map.ts","../src/workspace/file-mapping.ts","../src/workflow/policy.ts","../src/workflow/discovery.ts","../src/workflow/expected-paths.ts","../src/workflow/impact.ts","../src/workflow/validator.ts","../src/workflow/parser.ts"],"sourcesContent":["import type { WorkspacePackage, DependencyGraph } from './types';\n\nexport function buildDependencyGraph(\n packages: WorkspacePackage[],\n): DependencyGraph {\n const graph: DependencyGraph = {\n packages: new Map(),\n dependsOn: new Map(),\n dependedBy: new Map(),\n };\n\n for (const pkg of packages) {\n graph.packages.set(pkg.name, pkg);\n graph.dependsOn.set(pkg.name, new Set());\n graph.dependedBy.set(pkg.name, new Set());\n }\n\n for (const pkg of packages) {\n const allDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n for (const depName of Object.keys(allDeps)) {\n const matchedPkg = findMatchingPackage(depName, packages);\n\n if (matchedPkg) {\n graph.dependsOn.get(pkg.name)!.add(matchedPkg.name);\n graph.dependedBy.get(matchedPkg.name)!.add(pkg.name);\n }\n }\n }\n\n return graph;\n}\n\nfunction findMatchingPackage(\n depName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((p) => p.name === depName);\n if (match) return match;\n\n match = packages.find((p) => p.name === `@repo/${depName}`);\n if (match) return match;\n\n const nameWithoutRepo = depName.replace(/^@repo\\//, '');\n match = packages.find((p) => p.name === nameWithoutRepo);\n if (match) return match;\n\n return undefined;\n}\n","import type { DependencyGraph, TraversalOptions } from './types';\n\nexport function findAffectedPackages(\n startingPackages: Set<string>,\n graph: DependencyGraph,\n options: TraversalOptions = {},\n): Set<string> {\n const {\n direction = 'upstream',\n maxDepth = Infinity,\n filter,\n respectAffectsUpstream = false,\n } = options;\n\n const affected = new Set<string>(startingPackages);\n const queue: Array<{ name: string; depth: number }> = Array.from(\n startingPackages,\n ).map((name) => ({ name, depth: 0 }));\n const visited = new Set<string>();\n\n while (queue.length > 0) {\n const current = queue.shift()!;\n\n if (visited.has(current.name)) continue;\n visited.add(current.name);\n\n if (current.depth >= maxDepth) {\n continue;\n }\n\n const pkg = graph.packages.get(current.name);\n if (!pkg) continue;\n\n if (respectAffectsUpstream && direction === 'upstream') {\n const release = pkg.packageJson.release;\n if (release && release.affectsUpstream === false) {\n continue;\n }\n }\n\n const nextPackages = new Set<string>();\n\n if (direction === 'upstream' || direction === 'both') {\n const upstream = graph.dependedBy.get(current.name) || new Set();\n upstream.forEach((p) => nextPackages.add(p));\n }\n\n if (direction === 'downstream' || direction === 'both') {\n const downstream = graph.dependsOn.get(current.name) || new Set();\n downstream.forEach((p) => nextPackages.add(p));\n }\n\n for (const pkgName of nextPackages) {\n const nextPkg = graph.packages.get(pkgName);\n\n if (filter && nextPkg && !filter(nextPkg)) {\n continue;\n }\n\n if (!affected.has(pkgName)) {\n affected.add(pkgName);\n queue.push({ name: pkgName, depth: current.depth + 1 });\n }\n }\n }\n\n return affected;\n}\n\nexport function findDependencyPath(\n from: string,\n to: string,\n graph: DependencyGraph,\n): string[] | null {\n const queue: string[][] = [[from]];\n const visited = new Set<string>([from]);\n\n while (queue.length > 0) {\n const path = queue.shift()!;\n const current = path[path.length - 1];\n\n if (!current) {\n continue;\n }\n\n if (current === to) {\n return path;\n }\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n if (!visited.has(dependent)) {\n visited.add(dependent);\n queue.push([...path, dependent]);\n }\n }\n }\n\n return null;\n}\n\nexport function findAllPaths(\n from: string,\n to: string,\n graph: DependencyGraph,\n maxPaths = 10,\n): string[][] {\n const paths: string[][] = [];\n const visited = new Set<string>();\n\n function dfs(current: string, path: string[]): void {\n if (paths.length >= maxPaths) return;\n\n if (current === to) {\n paths.push([...path]);\n return;\n }\n\n if (visited.has(current)) return;\n visited.add(current);\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n dfs(dependent, [...path, dependent]);\n }\n\n visited.delete(current);\n }\n\n dfs(from, [from]);\n return paths;\n}\n","import type { DependencyGraph, GraphStats } from './types';\n\nexport function analyzeGraph(graph: DependencyGraph): GraphStats {\n const leafNodes: string[] = [];\n const rootNodes: string[] = [];\n let totalEdges = 0;\n\n for (const [pkgName, dependents] of graph.dependedBy.entries()) {\n if (dependents.size === 0) {\n leafNodes.push(pkgName);\n }\n totalEdges += dependents.size;\n }\n\n for (const [pkgName, dependencies] of graph.dependsOn.entries()) {\n if (dependencies.size === 0) {\n rootNodes.push(pkgName);\n }\n }\n\n const maxDepth = calculateMaxDepth(graph);\n const cycles = detectCycles(graph);\n\n return {\n totalPackages: graph.packages.size,\n totalEdges,\n maxDepth,\n leafNodes,\n rootNodes,\n cycles,\n };\n}\n\nfunction calculateMaxDepth(graph: DependencyGraph): number {\n let maxDepth = 0;\n\n for (const pkgName of graph.packages.keys()) {\n const depth = getPackageDepth(pkgName, graph);\n if (depth > maxDepth) {\n maxDepth = depth;\n }\n }\n\n return maxDepth;\n}\n\nfunction getPackageDepth(\n pkgName: string,\n graph: DependencyGraph,\n visited = new Set<string>(),\n): number {\n if (visited.has(pkgName)) return 0;\n visited.add(pkgName);\n\n const dependencies = graph.dependsOn.get(pkgName) || new Set();\n if (dependencies.size === 0) return 0;\n\n let maxDepth = 0;\n for (const dep of dependencies) {\n const depth = getPackageDepth(dep, graph, new Set(visited));\n if (depth > maxDepth) {\n maxDepth = depth;\n }\n }\n\n return maxDepth + 1;\n}\n\nexport function detectCycles(graph: DependencyGraph): string[][] {\n const cycles: string[][] = [];\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n\n function dfs(pkgName: string, path: string[]): void {\n visited.add(pkgName);\n recursionStack.add(pkgName);\n path.push(pkgName);\n\n const dependencies = graph.dependsOn.get(pkgName) || new Set();\n for (const dep of dependencies) {\n if (!visited.has(dep)) {\n dfs(dep, [...path]);\n } else if (recursionStack.has(dep)) {\n const cycleStart = path.indexOf(dep);\n if (cycleStart !== -1) {\n const cycle = path.slice(cycleStart);\n cycle.push(dep);\n cycles.push(cycle);\n }\n }\n }\n\n recursionStack.delete(pkgName);\n }\n\n for (const pkgName of graph.packages.keys()) {\n if (!visited.has(pkgName)) {\n dfs(pkgName, []);\n }\n }\n\n return cycles;\n}\n\nexport function getTransitiveDependencies(\n pkgName: string,\n graph: DependencyGraph,\n): Set<string> {\n const transitive = new Set<string>();\n const visited = new Set<string>();\n\n function collect(current: string): void {\n if (visited.has(current)) return;\n visited.add(current);\n\n const deps = graph.dependsOn.get(current) || new Set();\n for (const dep of deps) {\n transitive.add(dep);\n collect(dep);\n }\n }\n\n collect(pkgName);\n return transitive;\n}\n\nexport function getTransitiveDependents(\n pkgName: string,\n graph: DependencyGraph,\n): Set<string> {\n const transitive = new Set<string>();\n const visited = new Set<string>();\n\n function collect(current: string): void {\n if (visited.has(current)) return;\n visited.add(current);\n\n const dependents = graph.dependedBy.get(current) || new Set();\n for (const dependent of dependents) {\n transitive.add(dependent);\n collect(dependent);\n }\n }\n\n collect(pkgName);\n return transitive;\n}\n","import { join, resolve } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport type {\n FileSystemClient,\n GlobClient,\n YamlClient,\n} from '../types/clients';\n\nexport interface WorkspaceConfig {\n packages: string[];\n}\n\nexport interface WorkspaceDiscoveryConfig {\n fs: FileSystemClient;\n glob: GlobClient;\n yaml: YamlClient;\n}\n\nexport async function discoverWorkspaces(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspacePackage[]> {\n const workspaceConfig = await loadWorkspaceConfig(rootDir, config);\n const packages: WorkspacePackage[] = [];\n\n for (const pattern of workspaceConfig.packages) {\n if (pattern.startsWith('!')) continue;\n\n const pkgDirs = await findPackageDirectories(rootDir, pattern, config);\n\n for (const pkgDir of pkgDirs) {\n const pkgJsonPath = join(pkgDir, 'package.json');\n\n try {\n const pkgJsonContent: string = await config.fs.readFile(\n pkgJsonPath,\n 'utf-8',\n );\n const pkgJson = JSON.parse(pkgJsonContent) as {\n name: string;\n version?: string;\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n };\n\n packages.push({\n name: pkgJson.name,\n version: pkgJson.version || '0.0.0',\n path: pkgDir,\n packageJson: pkgJson,\n dependencies: pkgJson.dependencies || {},\n devDependencies: pkgJson.devDependencies || {},\n });\n } catch {\n continue;\n }\n }\n }\n\n return packages;\n}\n\nasync function loadWorkspaceConfig(\n rootDir: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<WorkspaceConfig> {\n const workspaceFilePath = join(rootDir, 'pnpm-workspace.yaml');\n\n try {\n const content: string = await config.fs.readFile(\n workspaceFilePath,\n 'utf-8',\n );\n const parsed = config.yaml.parse(content) as WorkspaceConfig;\n return parsed;\n } catch {\n return { packages: [] };\n }\n}\n\nasync function findPackageDirectories(\n rootDir: string,\n pattern: string,\n config: WorkspaceDiscoveryConfig,\n): Promise<string[]> {\n const matches: string[] = await config.glob.glob(pattern, {\n cwd: rootDir,\n absolute: false,\n ignore: ['**/node_modules/**', '**/.next/**', '**/dist/**'],\n });\n\n return matches.map((match: string) => resolve(rootDir, match));\n}\n","import { existsSync } from 'node:fs';\nimport { join, relative, sep } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\n\nexport interface MappedWorkspacePath {\n filesystemPath: string;\n workflowPath: string | null;\n}\n\nexport interface WorkspacePackageMap {\n packageMap: Map<string, MappedWorkspacePath>;\n workspaceRoots: Set<string>;\n}\n\nexport function normalizeRelativePath(path: string): string {\n return path.split(sep).join('/');\n}\n\nfunction resolveWorkflowPath(\n relativePath: string,\n rootDir: string,\n): string | null {\n if (!relativePath.startsWith('../')) {\n return relativePath;\n }\n\n const segments = relativePath.split('/');\n\n for (let index = 0; index < segments.length; index += 1) {\n const candidateSegments = segments.slice(index);\n if (candidateSegments.length === 0 || candidateSegments[0] === '..') {\n continue;\n }\n\n const candidatePath = candidateSegments.join('/');\n if (existsSync(join(rootDir, candidatePath))) {\n return candidatePath;\n }\n }\n\n return null;\n}\n\nexport function buildPackageMap(\n packages: WorkspacePackage[],\n rootDir: string,\n): WorkspacePackageMap {\n const packageMap = new Map<string, MappedWorkspacePath>();\n const workspaceRoots = new Set<string>();\n\n for (const pkg of packages) {\n const relativePath = normalizeRelativePath(relative(rootDir, pkg.path));\n const workflowPath = resolveWorkflowPath(relativePath, rootDir);\n\n packageMap.set(pkg.name, {\n filesystemPath: relativePath,\n workflowPath,\n });\n\n if (!workflowPath) {\n continue;\n }\n\n const [workspaceRoot] = workflowPath.split('/');\n if (workspaceRoot) {\n workspaceRoots.add(workspaceRoot);\n }\n }\n\n return {\n packageMap,\n workspaceRoots,\n };\n}\n","import type { WorkspacePackage } from '../graph/types';\n\nexport function findPackageForFile(\n filePath: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n const sorted = packages.sort((a, b) => b.path.length - a.path.length);\n\n for (const pkg of sorted) {\n if (filePath.startsWith(pkg.path + '/') || filePath === pkg.path) {\n return pkg;\n }\n }\n\n return undefined;\n}\n\nexport function mapFilesToPackages(\n files: string[],\n packages: WorkspacePackage[],\n): Map<string, string[]> {\n const fileMap = new Map<string, string[]>();\n\n for (const file of files) {\n const pkg = findPackageForFile(file, packages);\n if (pkg) {\n if (!fileMap.has(pkg.name)) {\n fileMap.set(pkg.name, []);\n }\n fileMap.get(pkg.name)!.push(file);\n }\n }\n\n return fileMap;\n}\n","import type { WorkflowValidationPolicy } from './types';\n\nexport const defaultWorkflowValidationPolicy: WorkflowValidationPolicy = {\n workflowFilePatterns: ['deploy-*.yml', 'release-*.yml'],\n allowedRootPaths: [\n 'package.json',\n 'pnpm-lock.yaml',\n 'pnpm-workspace.yaml',\n 'turbo.json',\n ],\n includeDevDependenciesForRootPackage: true,\n includeDevDependenciesTransitively: false,\n};\n","import { existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\nfunction patternToRegExp(pattern: string): RegExp {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n return new RegExp(`^${escaped.replace(/\\*/g, '.*')}$`);\n}\n\nexport function discoverWorkflowTargets(\n rootDir: string,\n packages: WorkspacePackage[],\n policy: WorkflowValidationPolicy,\n): WorkflowTarget[] {\n const workflowsDir = join(rootDir, '.github/workflows');\n if (!existsSync(workflowsDir)) {\n return [];\n }\n\n const { packageMap } = buildPackageMap(packages, rootDir);\n const appPackages = packages.filter((pkg) =>\n packageMap.get(pkg.name)?.workflowPath?.startsWith('apps/'),\n );\n const bySlug = new Map<string, string>();\n\n for (const pkg of appPackages) {\n const relativePath = packageMap.get(pkg.name)?.workflowPath;\n if (!relativePath) {\n continue;\n }\n\n const slug = relativePath.split('/').at(-1);\n if (slug) {\n bySlug.set(slug, pkg.name);\n }\n }\n\n const allowedPatterns = policy.workflowFilePatterns.map(patternToRegExp);\n const files = readdirSync(workflowsDir)\n .filter((file) => file.endsWith('.yml'))\n .filter((file) => allowedPatterns.some((pattern) => pattern.test(file)));\n\n return files\n .map((workflowFile) => {\n const match = /^(?:deploy|release)-(.+)\\.yml$/.exec(workflowFile);\n const targetSlug = match?.[1] ?? workflowFile.replace(/\\.yml$/, '');\n\n return {\n workflowFile,\n workflowPath: `.github/workflows/${workflowFile}`,\n targetSlug,\n targetPackage: bySlug.get(targetSlug) ?? null,\n };\n })\n .sort((a, b) => a.workflowFile.localeCompare(b.workflowFile));\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport type { WorkflowTarget, WorkflowValidationPolicy } from './types';\n\ninterface ExpectedPathsOptions {\n workflowTarget: WorkflowTarget;\n packages: WorkspacePackage[];\n packageMap: Map<string, { workflowPath: string | null }>;\n policy: WorkflowValidationPolicy;\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction resolveWorkspaceDependency(\n dependencyName: string,\n packages: WorkspacePackage[],\n): WorkspacePackage | undefined {\n let match = packages.find((pkg) => pkg.name === dependencyName);\n if (match) {\n return match;\n }\n\n match = packages.find((pkg) => pkg.name === `@repo/${dependencyName}`);\n if (match) {\n return match;\n }\n\n const nameWithoutRepo = dependencyName.replace(/^@repo\\//, '');\n return packages.find((pkg) => pkg.name === nameWithoutRepo);\n}\n\nfunction collectWorkspaceDependencyNames(\n pkg: WorkspacePackage,\n packages: WorkspacePackage[],\n visited: Set<string>,\n includeDevDependencies: boolean,\n includeDevDependenciesTransitively: boolean,\n): Set<string> {\n const collected = new Set<string>();\n const dependencyEntries = Object.entries(pkg.dependencies);\n const devDependencyEntries = includeDevDependencies\n ? Object.entries(pkg.devDependencies)\n : [];\n\n for (const [dependencyName] of [\n ...dependencyEntries,\n ...devDependencyEntries,\n ]) {\n const dependency = resolveWorkspaceDependency(dependencyName, packages);\n if (!dependency || visited.has(dependency.name)) {\n continue;\n }\n\n visited.add(dependency.name);\n collected.add(dependency.name);\n\n const nestedDependencies = collectWorkspaceDependencyNames(\n dependency,\n packages,\n visited,\n includeDevDependenciesTransitively,\n includeDevDependenciesTransitively,\n );\n\n for (const nestedDependency of nestedDependencies) {\n collected.add(nestedDependency);\n }\n }\n\n return collected;\n}\n\nexport function getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n}: ExpectedPathsOptions): string[] {\n const targetPackageName = workflowTarget.targetPackage;\n if (!targetPackageName) {\n return [];\n }\n\n const targetPackage = packages.find((pkg) => pkg.name === targetPackageName);\n if (!targetPackage) {\n return [];\n }\n\n const dependencyNames = collectWorkspaceDependencyNames(\n targetPackage,\n packages,\n new Set<string>(),\n policy.includeDevDependenciesForRootPackage,\n policy.includeDevDependenciesTransitively,\n );\n\n const expectedPaths: string[] = [];\n const targetPackagePath = packageMap.get(targetPackageName)?.workflowPath;\n if (targetPackagePath) {\n expectedPaths.push(`${targetPackagePath}/**`);\n }\n\n for (const dependencyName of dependencyNames) {\n const dependencyPath = packageMap.get(dependencyName)?.workflowPath;\n if (dependencyPath) {\n expectedPaths.push(`${dependencyPath}/**`);\n }\n }\n\n return uniqueSorted(expectedPaths);\n}\n","import type { WorkspacePackage } from '../graph/types';\nimport { buildPackageMap } from '../workspace/package-map';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { defaultWorkflowValidationPolicy } from './policy';\nimport type { WorkflowImpact, WorkflowValidationPolicy } from './types';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction mergeWorkflowPolicy(\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowValidationPolicy {\n return {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n}\n\n// Path matching intentionally only supports exact paths and /** prefix matching\n// because that mirrors the workflow filters currently used in these repos.\nexport function matchesWorkflowPathFilter(\n changedPath: string,\n workflowPathFilter: string,\n): boolean {\n if (workflowPathFilter === changedPath) {\n return true;\n }\n\n if (!workflowPathFilter.endsWith('/**')) {\n return false;\n }\n\n const workflowPrefix = workflowPathFilter.slice(0, -3);\n return changedPath.startsWith(`${workflowPrefix}/`);\n}\n\nexport function getWorkflowImpacts(\n rootDir: string,\n packages: WorkspacePackage[],\n changedPaths: string[],\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): WorkflowImpact[] {\n const policy = mergeWorkflowPolicy(policyOverrides);\n const workflowTargets = discoverWorkflowTargets(rootDir, packages, policy);\n const { packageMap } = buildPackageMap(packages, rootDir);\n\n return workflowTargets\n .map((workflowTarget) => {\n const calculatedPaths = uniqueSorted([\n ...getExpectedWorkflowPaths({\n workflowTarget,\n packages,\n packageMap,\n policy,\n }),\n ...policy.allowedRootPaths,\n workflowTarget.workflowPath,\n ]);\n const matchedPaths = calculatedPaths.filter((calculatedPath) =>\n changedPaths.some((changedPath) =>\n matchesWorkflowPathFilter(changedPath, calculatedPath),\n ),\n );\n\n return {\n ...workflowTarget,\n matchedPaths: uniqueSorted(matchedPaths),\n } satisfies WorkflowImpact;\n })\n .filter((workflowImpact) => workflowImpact.matchedPaths.length > 0);\n}\n","import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { glob } from 'glob';\nimport { parse as parseYaml } from 'yaml';\nimport { discoverWorkspaces } from '../workspace/discovery';\nimport { buildPackageMap } from '../workspace/package-map';\nimport type {\n WorkflowValidationIssue,\n WorkflowValidationPolicy,\n WorkflowValidationResult,\n} from './types';\nimport { discoverWorkflowTargets } from './discovery';\nimport { getExpectedWorkflowPaths } from './expected-paths';\nimport { parseWorkflowFile } from './parser';\nimport { defaultWorkflowValidationPolicy } from './policy';\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nfunction buildBroadWildcards(workspaceRoots: Set<string>): Set<string> {\n const wildcards = new Set<string>();\n\n for (const root of workspaceRoots) {\n wildcards.add(`${root}/*`);\n wildcards.add(`${root}/**`);\n }\n\n return wildcards;\n}\n\nfunction hasGlobSyntax(path: string): boolean {\n return /[*?[\\]{}]/.test(path);\n}\n\nfunction getStalePathCheckBase(\n path: string,\n allowedRootPaths: string[],\n workflowPath: string,\n): string | null {\n if (\n path === workflowPath ||\n allowedRootPaths.includes(path) ||\n path.startsWith('!')\n ) {\n return null;\n }\n\n const trailingGlobSuffix = path.endsWith('/**')\n ? '/**'\n : path.endsWith('/*')\n ? '/*'\n : null;\n const checkBase = trailingGlobSuffix\n ? path.slice(0, -trailingGlobSuffix.length)\n : path;\n\n if (!checkBase || hasGlobSyntax(checkBase)) {\n return null;\n }\n\n if (!trailingGlobSuffix && hasGlobSyntax(path)) {\n return null;\n }\n\n return checkBase;\n}\n\nfunction splitActualPaths(\n paths: string[],\n workspaceRoots: Set<string>,\n allowedRootPaths: string[],\n workflowPath: string,\n): { workspacePaths: string[]; ignoredPaths: string[] } {\n const workspacePaths: string[] = [];\n const ignoredPaths: string[] = [];\n\n for (const path of paths) {\n if (path === workflowPath || allowedRootPaths.includes(path)) {\n ignoredPaths.push(path);\n continue;\n }\n\n const [rootSegment] = path.split('/');\n if (rootSegment && workspaceRoots.has(rootSegment)) {\n workspacePaths.push(path);\n continue;\n }\n\n ignoredPaths.push(path);\n }\n\n return {\n workspacePaths: uniqueSorted(workspacePaths),\n ignoredPaths: uniqueSorted(ignoredPaths),\n };\n}\n\nfunction isCoveredByExpectedPath(\n actualPath: string,\n expectedPaths: string[],\n): boolean {\n return expectedPaths.some((expectedPath) => {\n if (expectedPath === actualPath) {\n return true;\n }\n\n if (!expectedPath.endsWith('/**')) {\n return false;\n }\n\n const expectedPrefix = expectedPath.slice(0, -3);\n return actualPath.startsWith(`${expectedPrefix}/`);\n });\n}\n\nfunction validateWorkflowResult(\n workflow: string,\n targetPackage: string,\n expectedPaths: string[],\n actualPaths: string[],\n broadWildcards: Set<string>,\n additionalIssues: WorkflowValidationIssue[] = [],\n): WorkflowValidationResult {\n const issues: WorkflowValidationIssue[] = [];\n const missing = expectedPaths.filter((path) => !actualPaths.includes(path));\n const unnecessary = actualPaths.filter(\n (path) => !isCoveredByExpectedPath(path, expectedPaths),\n );\n\n for (const path of missing) {\n issues.push({\n kind: 'missing',\n path,\n message: `Missing path '${path}'`,\n });\n }\n\n for (const path of unnecessary) {\n issues.push({\n kind: 'unnecessary',\n path,\n message: `Unnecessary path '${path}'`,\n });\n }\n\n for (const path of actualPaths) {\n if (broadWildcards.has(path)) {\n issues.push({\n kind: 'broad-wildcard',\n path,\n message: `Uses broad wildcard '${path}' which triggers on all workspace changes under that root`,\n });\n }\n }\n\n issues.push(...additionalIssues);\n\n return {\n workflow,\n targetPackage,\n valid: issues.length === 0,\n expectedPaths,\n actualPaths,\n missing,\n unnecessary,\n issues,\n };\n}\n\nfunction getStalePathIssues(\n ignoredPaths: string[],\n rootDir: string,\n allowedRootPaths: string[],\n workflowPath: string,\n): WorkflowValidationIssue[] {\n return ignoredPaths.flatMap((path) => {\n const checkBase = getStalePathCheckBase(\n path,\n allowedRootPaths,\n workflowPath,\n );\n\n if (!checkBase || existsSync(join(rootDir, checkBase))) {\n return [];\n }\n\n return [\n {\n kind: 'stale-path',\n path,\n message: `Stale path '${path}' does not exist`,\n },\n ];\n });\n}\n\nexport async function validateWorkflows(\n rootDir: string,\n policyOverrides?: Partial<WorkflowValidationPolicy>,\n): Promise<WorkflowValidationResult[]> {\n const discoveredPackages = await discoverWorkspaces(rootDir, {\n fs: {\n readFile: (path, encoding) => readFile(path, encoding),\n exists: (path) => Promise.resolve(existsSync(path)),\n },\n glob: {\n glob: (pattern, options) => glob(pattern, options),\n },\n yaml: {\n parse: (content): unknown => parseYaml(content),\n },\n });\n\n const policy: WorkflowValidationPolicy = {\n ...defaultWorkflowValidationPolicy,\n ...policyOverrides,\n allowedRootPaths: uniqueSorted([\n ...defaultWorkflowValidationPolicy.allowedRootPaths,\n ...(policyOverrides?.allowedRootPaths ?? []),\n ]),\n };\n\n const { packageMap, workspaceRoots } = buildPackageMap(\n discoveredPackages,\n rootDir,\n );\n const workflowTargets = discoverWorkflowTargets(\n rootDir,\n discoveredPackages,\n policy,\n );\n const broadWildcards = buildBroadWildcards(workspaceRoots);\n\n return workflowTargets.map((workflowTarget) => {\n if (!workflowTarget.targetPackage) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetSlug,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'config-error',\n message: `Could not resolve workflow target package for '${workflowTarget.workflowFile}'`,\n },\n ],\n };\n }\n\n try {\n const parsedWorkflow = parseWorkflowFile(\n workflowTarget.workflowFile,\n rootDir,\n );\n\n if (parsedWorkflow.paths.length === 0) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: true,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [],\n };\n }\n\n const { workspacePaths: actualPaths, ignoredPaths } = splitActualPaths(\n parsedWorkflow.paths,\n workspaceRoots,\n policy.allowedRootPaths,\n workflowTarget.workflowPath,\n );\n const expectedPaths = getExpectedWorkflowPaths({\n workflowTarget,\n packages: discoveredPackages,\n packageMap,\n policy,\n });\n\n return validateWorkflowResult(\n workflowTarget.workflowFile,\n workflowTarget.targetPackage,\n expectedPaths,\n actualPaths,\n broadWildcards,\n getStalePathIssues(\n ignoredPaths,\n rootDir,\n policy.allowedRootPaths,\n workflowTarget.workflowPath,\n ),\n );\n } catch (error) {\n return {\n workflow: workflowTarget.workflowFile,\n targetPackage: workflowTarget.targetPackage,\n valid: false,\n expectedPaths: [],\n actualPaths: [],\n missing: [],\n unnecessary: [],\n issues: [\n {\n kind: 'parse-error',\n message: error instanceof Error ? error.message : String(error),\n },\n ],\n };\n }\n });\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\nimport type { ParsedWorkflow } from './types';\n\ninterface WorkflowConfig {\n name?: string;\n on?: {\n push?: {\n paths?: string[];\n };\n pull_request?: {\n paths?: string[];\n };\n };\n}\n\nfunction uniqueSorted(values: string[]): string[] {\n return Array.from(new Set(values)).sort();\n}\n\nexport function parseWorkflowFile(\n workflowFile: string,\n rootDir: string,\n): ParsedWorkflow {\n const workflowPath = join(rootDir, '.github/workflows', workflowFile);\n\n if (!existsSync(workflowPath)) {\n throw new Error(`Workflow file not found: ${workflowFile}`);\n }\n\n const content = readFileSync(workflowPath, 'utf-8');\n const workflow = parseYaml(content) as WorkflowConfig;\n const pushPaths = workflow.on?.push?.paths ?? [];\n const pullRequestPaths = workflow.on?.pull_request?.paths ?? [];\n\n const parsedWorkflow: ParsedWorkflow = {\n pushPaths: uniqueSorted(pushPaths),\n pullRequestPaths: uniqueSorted(pullRequestPaths),\n paths: uniqueSorted([...pushPaths, ...pullRequestPaths]),\n };\n\n if (workflow.name) {\n parsedWorkflow.name = workflow.name;\n }\n\n return parsedWorkflow;\n}\n"],"mappings":"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","names":["join","existsSync","join","join","existsSync","uniqueSorted","existsSync","join","parseYaml","existsSync","join","uniqueSorted","uniqueSorted","existsSync","join","parseYaml"]}
|
package/dist/workflow/types.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface WorkflowValidationPolicy {
|
|
|
9
9
|
includeDevDependenciesTransitively: boolean;
|
|
10
10
|
}
|
|
11
11
|
export interface WorkflowValidationIssue {
|
|
12
|
-
kind: 'missing' | 'unnecessary' | 'broad-wildcard' | 'parse-error' | 'config-error';
|
|
12
|
+
kind: 'missing' | 'unnecessary' | 'stale-path' | 'broad-wildcard' | 'parse-error' | 'config-error';
|
|
13
13
|
message: string;
|
|
14
14
|
path?: string;
|
|
15
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workflow/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,oCAAoC,EAAE,OAAO,CAAC;IAC9C,kCAAkC,EAAE,OAAO,CAAC;CAC7C;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EACA,SAAS,GACT,aAAa,GACb,gBAAgB,GAChB,aAAa,GACb,cAAc,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workflow/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,wBAAwB;IACvC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B;;;OAGG;IACH,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,oCAAoC,EAAE,OAAO,CAAC;IAC9C,kCAAkC,EAAE,OAAO,CAAC;CAC7C;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EACA,SAAS,GACT,aAAa,GACb,YAAY,GACZ,gBAAgB,GAChB,aAAa,GACb,cAAc,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,MAAM,EAAE,uBAAuB,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,cAAe,SAAQ,cAAc;IACpD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/workflow/validator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/workflow/validator.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAEV,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,SAAS,CAAC;AA2LjB,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,eAAe,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAClD,OAAO,CAAC,wBAAwB,EAAE,CAAC,CAoHrC"}
|
package/package.json
CHANGED