All files / lib/analyzers devops-analyzer.js

100% Statements 37/37
95% Branches 19/20
100% Functions 1/1
100% Lines 37/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75          7x               7x 7x 1x 1x 1x       7x 7x 1x 1x       7x 7x 7x 1x 1x       7x 7x 1x 1x       7x 7x 1x 1x       7x 1x 1x       7x 7x 1x 1x 1x 1x           7x 7x 7x 7x   7x    
import fs from 'fs-extra';
import path from 'path';
import { recursiveGlob } from './utils.js';
 
export async function analyzeDevOps(projectPath) {
  const detected = {
    ciSystems: [],
    tools: [],
    buildTools: [],
    configFiles: []
  };
 
  // GitHub Actions
  const ghaDir = path.join(projectPath, '.github', 'workflows');
  if (await fs.pathExists(ghaDir)) {
    detected.ciSystems.push('github-actions');
    detected.tools.push('github-actions');
    detected.configFiles.push('.github/workflows/');
  }
 
  // GitLab CI
  const gitlabCiPath = path.join(projectPath, '.gitlab-ci.yml');
  if (await fs.pathExists(gitlabCiPath)) {
    detected.ciSystems.push('gitlab-ci');
    detected.configFiles.push('.gitlab-ci.yml');
  }
 
  // CircleCI
  const circleDir = path.join(projectPath, '.circleci');
  const circleConfig = path.join(circleDir, 'config.yml');
  if (await fs.pathExists(circleDir) && await fs.pathExists(circleConfig)) {
    detected.ciSystems.push('circleci');
    detected.configFiles.push('.circleci/config.yml');
  }
 
  // Jenkins
  const jenkinsfile = path.join(projectPath, 'Jenkinsfile');
  if (await fs.pathExists(jenkinsfile)) {
    detected.ciSystems.push('jenkins');
    detected.configFiles.push('Jenkinsfile');
  }
 
  // Terraform (re-use pattern from cloud analyzer but we track here as tool)
  const tfFiles = await recursiveGlob(projectPath, '**/*.tf');
  if (tfFiles.length > 0) {
    detected.tools.push('terraform');
    detected.configFiles.push(...tfFiles.slice(0, 3));
  }
 
  // Makefile
  if (await fs.pathExists(path.join(projectPath, 'Makefile'))) {
    detected.buildTools.push('make');
    detected.configFiles.push('Makefile');
  }
 
  // NPM/Yarn/PNPM scripts from package.json
  const pkgPath = path.join(projectPath, 'package.json');
  if (await fs.pathExists(pkgPath)) {
    try {
      const pkg = await fs.readJson(pkgPath);
      Eif (pkg.scripts && Object.keys(pkg.scripts).length > 0) {
        detected.buildTools.push('npm-scripts');
      }
    } catch (e) {}
  }
 
  // Deduplicate
  detected.ciSystems = [...new Set(detected.ciSystems)];
  detected.tools = [...new Set(detected.tools)];
  detected.buildTools = [...new Set(detected.buildTools)];
  detected.configFiles = [...new Set(detected.configFiles)];
 
  return detected;
}