UNPKG

ctrlshiftleft

Version:

AI-powered toolkit for embedding QA and security testing into development workflows

253 lines (214 loc) 9.01 kB
#!/usr/bin/env node /** * Upgrade Script for AI-Enhanced ctrl.shift.left * * This script helps users upgrade to the AI-enhanced version of ctrl.shift.left * by updating the necessary files and setting up the required configurations. */ const fs = require('fs'); const path = require('path'); const { exec } = require('child_process'); const { promisify } = require('util'); const readline = require('readline'); const execAsync = promisify(exec); // ANSI color codes for terminal output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', dim: '\x1b[2m', underscore: '\x1b[4m', blink: '\x1b[5m', reverse: '\x1b[7m', hidden: '\x1b[8m', fg: { black: '\x1b[30m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', white: '\x1b[37m' }, bg: { black: '\x1b[40m', red: '\x1b[41m', green: '\x1b[42m', yellow: '\x1b[43m', blue: '\x1b[44m', magenta: '\x1b[45m', cyan: '\x1b[46m', white: '\x1b[47m' } }; // Create a readline interface for user input const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); // Prompt the user for input function prompt(question) { return new Promise((resolve) => { rl.question(question, (answer) => { resolve(answer); }); }); } // Print colored messages function printTitle(message) { console.log(`\n${colors.fg.cyan}${colors.bright}${message}${colors.reset}\n`); } function printSuccess(message) { console.log(`${colors.fg.green}${message}${colors.reset}`); } function printWarning(message) { console.log(`${colors.fg.yellow}${message}${colors.reset}`); } function printError(message) { console.log(`${colors.fg.red}${message}${colors.reset}`); } function printStep(step, message) { console.log(`${colors.fg.blue}[${step}]${colors.reset} ${message}`); } // Get the project root directory const projectRoot = path.resolve(__dirname, '..'); // Paths to relevant directories and files const vscodePath = path.join(projectRoot, 'vscode-ext-test'); const scriptsPath = path.join(projectRoot, 'scripts'); const docsPath = path.join(projectRoot, 'docs'); const binPath = path.join(projectRoot, 'bin'); // Main upgrade function async function upgrade() { printTitle('ctrl.shift.left AI Upgrade Utility'); console.log('This utility will upgrade your ctrl.shift.left installation to use AI-enhanced security analysis.\n'); try { // Step 1: Check Prerequisites printStep('1', 'Checking prerequisites...'); // Check if OpenAI API key is set const apiKey = process.env.OPENAI_API_KEY; if (!apiKey) { printWarning('OpenAI API key not found in environment variables.'); const setKey = await prompt('Would you like to set an OpenAI API key now? (y/n): '); if (setKey.toLowerCase() === 'y') { const key = await prompt('Enter your OpenAI API key: '); if (key && key.trim()) { // Set key for this session process.env.OPENAI_API_KEY = key.trim(); printSuccess('API key set for this session'); // Add to .env file const envPath = path.join(projectRoot, '.env'); try { let envContent = ''; if (fs.existsSync(envPath)) { envContent = fs.readFileSync(envPath, 'utf8'); // Check if OPENAI_API_KEY is already in the file if (envContent.includes('OPENAI_API_KEY=')) { // Replace the existing key envContent = envContent.replace(/OPENAI_API_KEY=.*/g, `OPENAI_API_KEY=${key.trim()}`); } else { // Add new key envContent += `\nOPENAI_API_KEY=${key.trim()}\n`; } } else { // Create new .env file envContent = `OPENAI_API_KEY=${key.trim()}\n`; } fs.writeFileSync(envPath, envContent); printSuccess('.env file updated with API key'); } catch (error) { printError(`Failed to update .env file: ${error.message}`); printWarning('Please manually add OPENAI_API_KEY to your .env file or environment variables'); } } else { printError('Invalid API key provided'); printWarning('AI-enhanced features will not be available without an OpenAI API key'); } } else { printWarning('Proceeding without API key. AI-enhanced features will not be available.'); } } else { printSuccess('OpenAI API key found in environment variables'); } // Step 2: Make scripts executable printStep('2', 'Making AI scripts executable...'); try { // Make the AI CLI executable await execAsync(`chmod +x ${path.join(binPath, 'ctrlshiftleft-ai')}`); await execAsync(`chmod +x ${path.join(projectRoot, 'vscode-ext-test', 'analyze-security-enhanced.js')}`); printSuccess('Scripts are now executable'); } catch (error) { printError(`Failed to make scripts executable: ${error.message}`); printWarning('You may need to manually run: chmod +x bin/ctrlshiftleft-ai'); } // Step 3: Update VS Code Extension printStep('3', 'Updating VS Code extension...'); try { // Back up original files const extensionBackupPath = path.join(vscodePath, 'extension-simple.js.bak'); const packageBackupPath = path.join(vscodePath, 'package.json.bak'); if (!fs.existsSync(extensionBackupPath)) { fs.copyFileSync(path.join(vscodePath, 'extension-simple.js'), extensionBackupPath); } if (!fs.existsSync(packageBackupPath)) { fs.copyFileSync(path.join(vscodePath, 'package.json'), packageBackupPath); } // Copy enhanced files fs.copyFileSync(path.join(vscodePath, 'package-enhanced.json'), path.join(vscodePath, 'package.json')); fs.copyFileSync(path.join(vscodePath, 'extension-enhanced.js'), path.join(vscodePath, 'extension-simple.js')); printSuccess('VS Code extension updated with AI capabilities'); printWarning('Remember to reload VS Code window after the upgrade'); } catch (error) { printError(`Failed to update VS Code extension: ${error.message}`); printWarning('You may need to manually copy the enhanced files'); } // Step 4: Test AI-enhanced security analyzer printStep('4', 'Testing AI-enhanced security analyzer...'); const shouldTest = await prompt('Would you like to test the AI-enhanced security analyzer now? (y/n): '); if (shouldTest.toLowerCase() === 'y') { try { // Check if demo file exists const demoFile = path.join(projectRoot, 'demo', 'samples', 'vulnerable-auth.js'); if (fs.existsSync(demoFile)) { console.log('\nRunning AI-enhanced security analysis on demo file...'); console.log('(This may take a few moments as it contacts the OpenAI API)\n'); const { stdout, stderr } = await execAsync(`${path.join(binPath, 'ctrlshiftleft-ai')} analyze --ai "${demoFile}"`, { cwd: projectRoot }); console.log(stdout); if (stderr) console.error(stderr); printSuccess('AI-enhanced security analyzer test complete'); } else { printWarning(`Demo file not found: ${demoFile}`); printWarning('Skipping test'); } } catch (error) { printError(`Test failed: ${error.message}`); if (error.stdout) console.log(error.stdout); if (error.stderr) console.error(error.stderr); } } else { printWarning('Skipping test'); } // Step 5: Complete printTitle('Upgrade Complete!'); console.log(`${colors.bright}Your ctrl.shift.left installation has been upgraded with AI-enhanced security analysis capabilities.${colors.reset}\n`); console.log('Documentation:'); console.log(`- AI Security Guide: ${colors.fg.cyan}${path.join(docsPath, 'AI_SECURITY_GUIDE.md')}${colors.reset}`); console.log(`- Upgrade Guide: ${colors.fg.cyan}${path.join(docsPath, 'UPGRADE_TO_AI.md')}${colors.reset}\n`); console.log('Quick Start:'); console.log(`1. ${colors.fg.green}Run AI-enhanced security analysis:${colors.reset}`); console.log(` ./bin/ctrlshiftleft-ai analyze --ai <file>\n`); console.log(`2. ${colors.fg.green}Run AI-enhanced full scan:${colors.reset}`); console.log(` ./bin/ctrlshiftleft-ai secure --ai <file>\n`); console.log(`3. ${colors.fg.green}In VS Code:${colors.reset}`); console.log(` Right-click file → Ctrl+Shift+Left: AI Security Analysis\n`); } catch (error) { printError(`Upgrade failed: ${error.message}`); console.error(error); } finally { rl.close(); } } // Run the upgrade upgrade().catch(error => { console.error('Unhandled error:', error); process.exit(1); });