scripts/check-build-status.js (115 lines of code) (raw):

/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import fs from 'fs'; import path from 'path'; import os from 'os'; // Import os module // --- Configuration --- const cliPackageDir = path.resolve('packages', 'cli'); // Base directory for the CLI package const buildTimestampPath = path.join(cliPackageDir, 'dist', '.last_build'); // Path to the timestamp file within the CLI package const sourceDirs = [path.join(cliPackageDir, 'src')]; // Source directory within the CLI package const filesToWatch = [ path.join(cliPackageDir, 'package.json'), path.join(cliPackageDir, 'tsconfig.json'), ]; // Specific files within the CLI package const buildDir = path.join(cliPackageDir, 'dist'); // Build output directory within the CLI package const warningsFilePath = path.join(os.tmpdir(), 'gemini-cli-warnings.txt'); // Temp file for warnings // --------------------- function getMtime(filePath) { try { return fs.statSync(filePath).mtimeMs; // Use mtimeMs for higher precision } catch (err) { if (err.code === 'ENOENT') { return null; // File doesn't exist } console.error(`Error getting stats for ${filePath}:`, err); process.exit(1); // Exit on unexpected errors getting stats } } function findSourceFiles(dir, allFiles = []) { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); // Simple check to avoid recursing into node_modules or build dir itself if ( entry.isDirectory() && entry.name !== 'node_modules' && fullPath !== buildDir ) { findSourceFiles(fullPath, allFiles); } else if (entry.isFile()) { allFiles.push(fullPath); } } return allFiles; } console.log('Checking build status...'); // Clean up old warnings file before check try { if (fs.existsSync(warningsFilePath)) { fs.unlinkSync(warningsFilePath); } } catch (err) { console.warn( `[Check Script] Warning: Could not delete previous warnings file: ${err.message}`, ); } const buildMtime = getMtime(buildTimestampPath); if (!buildMtime) { // If build is missing, write that as a warning and exit(0) so app can display it const errorMessage = `ERROR: Build timestamp file (${path.relative(process.cwd(), buildTimestampPath)}) not found. Run \`npm run build\` first.`; console.error(errorMessage); // Still log error here try { fs.writeFileSync(warningsFilePath, errorMessage); } catch (writeErr) { console.error( `[Check Script] Error writing missing build warning file: ${writeErr.message}`, ); } process.exit(0); // Allow app to start and show the error } let newerSourceFileFound = false; const warningMessages = []; // Collect warnings here const allSourceFiles = []; // Collect files from specified directories sourceDirs.forEach((dir) => { const dirPath = path.resolve(dir); if (fs.existsSync(dirPath)) { findSourceFiles(dirPath, allSourceFiles); } else { console.warn(`Warning: Source directory "${dir}" not found.`); } }); // Add specific files filesToWatch.forEach((file) => { const filePath = path.resolve(file); if (fs.existsSync(filePath)) { allSourceFiles.push(filePath); } else { console.warn(`Warning: Watched file "${file}" not found.`); } }); // Check modification times for (const file of allSourceFiles) { const sourceMtime = getMtime(file); const relativePath = path.relative(process.cwd(), file); const isNewer = sourceMtime && sourceMtime > buildMtime; if (isNewer) { const warning = `Warning: Source file "${relativePath}" has been modified since the last build.`; console.warn(warning); // Keep console warning for script debugging warningMessages.push(warning); newerSourceFileFound = true; // break; // Uncomment to stop checking after the first newer file } } if (newerSourceFileFound) { const finalWarning = '\nRun "npm run build" to incorporate changes before starting.'; warningMessages.push(finalWarning); console.warn(finalWarning); // Write warnings to the temp file try { fs.writeFileSync(warningsFilePath, warningMessages.join('\n')); // Removed debug log } catch (err) { console.error(`[Check Script] Error writing warnings file: ${err.message}`); // Proceed without writing, app won't show warnings } } else { console.log('Build is up-to-date.'); // Ensure no stale warning file exists if build is ok try { if (fs.existsSync(warningsFilePath)) { fs.unlinkSync(warningsFilePath); } } catch (err) { console.warn( `[Check Script] Warning: Could not delete previous warnings file: ${err.message}`, ); } } process.exit(0); // Always exit successfully so the app starts