flowgram.ai/common/autoinstallers/rush-commands/check-circular-dependency.mjs
dragooncjw d7bdf8a078 feat: init flowgram.ai
Co-Authored-By: xiamidaxia <xiamidaxia@icloud.com>
2025-02-21 16:26:12 +08:00

84 lines
2.5 KiB
JavaScript

import RushSdk from '@rushstack/rush-sdk';
const rushConfig = RushSdk.RushConfiguration.loadFromDefaultLocation();
function getPackageDependencies(packageName, depsMap) {
const projectInfo = rushConfig.getProjectByName(packageName);
if (!projectInfo || depsMap[packageName]) return;
// eslint-disable-next-line no-param-reassign
depsMap[packageName] = [...projectInfo.dependencyProjects].map(
p => p.packageName,
);
for (const dep of depsMap[packageName]) {
getPackageDependencies(dep, depsMap);
}
}
function main() {
const { projects } = rushConfig;
const depsMap = {};
for (const project of projects) {
getPackageDependencies(project.packageName, depsMap);
}
// 定义一个函数来进行深度优先搜索
function dfs(node, visited, stack, graph, cycles) {
visited.add(node); // 将当前节点标记为已访问
stack.push(node); // 将当前节点添加到栈中
// 遍历当前节点的所有邻居
for (const neighbor of graph[node]) {
// 如果邻居节点未被访问,则进行深度优先搜索
if (!visited.has(neighbor)) {
dfs(neighbor, visited, stack, graph, cycles);
}
// 如果邻居节点已经被访问,并且在栈中,则说明存在循环依赖
else if (stack.includes(neighbor)) {
cycles.push([...stack.slice(stack.indexOf(neighbor)), neighbor]); // 将循环依赖添加到数组中
}
}
// 将当前节点从栈中弹出,回溯到上一个节点
stack.pop();
}
// 定义一个函数来查找所有循环依赖
function findCycles(graph) {
const visited = new Set(); // 用于存储已经访问过的节点
const stack = []; // 用于存储遍历过程中经过的节点
const cycles = []; // 用于存储所有循环依赖
// 遍历图中的所有节点
for (const node in graph) {
// 如果当前节点未被访问,则进行深度优先搜索
if (!visited.has(node)) {
dfs(node, visited, stack, graph, cycles);
}
}
// 返回所有循环依赖
return cycles;
}
const cycles = findCycles(depsMap);
if (cycles.length) {
for (const chain of cycles) {
console.log('Circular dependency detected:');
console.log(chain.join('\n->'));
console.log('\n');
if (process.env.CI === 'true') {
console.log(
`::add-message level=error::**检测到循环依赖:**${chain.join('->')}`,
);
}
}
process.exitCode = 1;
}
}
main();