#!/bin/bash # šŸ” Dependency Validation Script # Validates dependency integrity, checks for version drift, and security issues set -euo pipefail echo "šŸ” Validating dependencies..." # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Check if pnpm is available if ! command -v pnpm &> /dev/null; then echo -e "${RED}āŒ pnpm is not installed${NC}" exit 1 fi # 1. Validate lockfile integrity echo "šŸ“‹ Checking lockfile integrity..." if pnpm install --frozen-lockfile --ignore-scripts; then echo -e "${GREEN}āœ… Lockfile integrity validated${NC}" else echo -e "${RED}āŒ Lockfile integrity check failed${NC}" exit 1 fi # 2. Check for dependency version drift echo "šŸ” Checking for dependency version drift..." pnpm list --recursive --depth=0 --json > /tmp/deps.json node -e " const fs = require('fs'); const deps = JSON.parse(fs.readFileSync('/tmp/deps.json', 'utf8')); // depName -> Map(version -> string[]) const allDeps = new Map(); deps.forEach(pkg => { if (pkg.dependencies) { Object.entries(pkg.dependencies).forEach(([name, info]) => { const version = info.version; if (!allDeps.has(name)) allDeps.set(name, new Map()); const byVersion = allDeps.get(name); if (!byVersion.has(version)) byVersion.set(version, []); byVersion.get(version).push(pkg.name); }); } }); let hasDrift = false; allDeps.forEach((byVersion, depName) => { if (byVersion.size <= 1) return; hasDrift = true; console.log(\`āŒ Version drift detected for \${depName}:\`); for (const [version, pkgs] of [...byVersion.entries()].sort(([a], [b]) => String(a).localeCompare(String(b)))) { console.log(\` - \${version}\`); pkgs.sort().forEach(p => console.log(\` • \${p}\`)); } }); if (hasDrift) { console.log('\\nšŸ’” Fix version drift by aligning dependency versions across workspaces.'); process.exit(1); } else { console.log('āœ… No dependency version drift detected.'); } " # 2b. Ensure a single installed Zod version (lockfile-level) echo "🧩 Checking for multiple installed Zod versions..." node -e " const fs = require('fs'); const lock = fs.readFileSync('pnpm-lock.yaml', 'utf8'); const versions = new Set(); const re = /\\n\\s{2}zod@([^:\\s]+):/g; let m; while ((m = re.exec(lock)) !== null) versions.add(m[1]); if (versions.size === 0) { console.log('āš ļø No zod entries found in lockfile (unexpected).'); process.exit(1); } if (versions.size > 1) { console.log('āŒ Multiple zod versions installed:'); [...versions].sort().forEach(v => console.log(' - zod@' + v)); console.log('\\nšŸ’” Fix by aligning dependencies or adding a pnpm override for zod.'); process.exit(1); } console.log('āœ… Single zod version installed:', 'zod@' + [...versions][0]); " # 3. Security audit echo "šŸ”’ Running security audit..." if pnpm audit --audit-level moderate; then echo -e "${GREEN}āœ… Security audit passed${NC}" else echo -e "${YELLOW}āš ļø Security vulnerabilities found. Review and update dependencies.${NC}" fi # 4. Check for outdated dependencies echo "šŸ“… Checking for outdated dependencies..." pnpm outdated --recursive || echo -e "${YELLOW}āš ļø Some dependencies are outdated${NC}" # 5. Validate workspace configuration echo "āš™ļø Validating workspace configuration..." node -e " const fs = require('fs'); const path = require('path'); try { const rootPkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); console.log('āœ… Root package.json is valid'); const workspaceConfig = fs.readFileSync('pnpm-workspace.yaml', 'utf8'); console.log('āœ… pnpm-workspace.yaml is readable'); // Check that all workspace packages exist const workspaces = ['apps/*', 'packages/*']; let allValid = true; workspaces.forEach(workspace => { const workspacePath = workspace.replace('/*', ''); if (!fs.existsSync(workspacePath)) { console.log(\`āŒ Workspace path does not exist: \${workspacePath}\`); allValid = false; } }); if (!allValid) { process.exit(1); } console.log('āœ… All workspace paths are valid'); } catch (error) { console.log(\`āŒ Workspace validation failed: \${error.message}\`); process.exit(1); } " # Cleanup rm -f /tmp/deps.json echo -e "${GREEN}šŸŽ‰ Dependency validation completed successfully!${NC}"