import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { spawnSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; import { dirname } from 'node:path'; const root = dirname(dirname(fileURLToPath(import.meta.url))); const failures = []; const gitignore = readFileSync(join(root, '.gitignore'), 'utf8'); for (const required of ['/modules/', '/sessions/', '/logs/', '/backups/', '/updates/', '/runtime/']) { if (!gitignore.split(/\r?\n/).includes(required)) failures.push(`Root-verankerte Ignore-Regel fehlt: ${required}`); } for (const forbidden of ['modules/', 'sessions/', 'logs/', 'backups/', 'updates/', 'runtime/']) { if (gitignore.split(/\r?\n/).includes(forbidden)) failures.push(`Zu breite Ignore-Regel vorhanden: ${forbidden}`); } const temp = mkdtempSync(join(tmpdir(), 'vendoo-ignore-boundary-')); const write = (rel, value = rel) => { const target = join(temp, rel); mkdirSync(dirname(target), { recursive: true }); writeFileSync(target, value, 'utf8'); }; const git = (...args) => spawnSync('git', args, { cwd: temp, encoding: 'utf8' }); try { copyFileSync(join(root, '.gitignore'), join(temp, '.gitignore')); write('app/modules/listings/routes.mjs', 'export const routes = true;\n'); write('app/modules/inventory/index.mjs', 'export const inventory = true;\n'); write('app/modules/inventory/repository.mjs', 'export const repository = true;\n'); write('app/modules/inventory/routes.mjs', 'export const inventoryRoutes = true;\n'); write('app/modules/sessions/index.mjs', 'export const sessions = true;\n'); write('app/logs/source.mjs', 'export const sourceLog = true;\n'); write('modules/demo/package.vmod', '{}'); write('sessions/session.json', '{}'); write('logs/server.log', 'runtime'); write('backups/backup.txt', 'runtime'); write('updates/update.txt', 'runtime'); write('runtime/state.json', '{}'); let result = git('init', '-q'); if (result.status !== 0) failures.push(`git init fehlgeschlagen: ${result.stderr}`); git('config', 'user.email', 'ci@example.invalid'); git('config', 'user.name', 'Vendoo CI'); const sourcePaths = [ 'app/modules/listings/routes.mjs', 'app/modules/inventory/index.mjs', 'app/modules/inventory/repository.mjs', 'app/modules/inventory/routes.mjs', 'app/modules/sessions/index.mjs', 'app/logs/source.mjs', ]; const runtimePaths = [ 'modules/demo/package.vmod', 'sessions/session.json', 'logs/server.log', 'backups/backup.txt', 'updates/update.txt', 'runtime/state.json', ]; for (const rel of sourcePaths) { result = git('check-ignore', '-q', '--', rel); if (result.status === 0) { const detail = git('check-ignore', '-v', '--', rel); failures.push(`Produktiver Quellpfad wird ignoriert: ${rel} (${detail.stdout.trim()})`); } } for (const rel of runtimePaths) { result = git('check-ignore', '-q', '--', rel); if (result.status !== 0) failures.push(`Runtime-Pfad wird nicht ignoriert: ${rel}`); } result = git('add', '--all'); if (result.status !== 0) failures.push(`git add --all fehlgeschlagen: ${result.stderr}`); const tracked = new Set(git('ls-files').stdout.split(/\r?\n/).filter(Boolean)); for (const rel of sourcePaths) if (!tracked.has(rel)) failures.push(`Produktiver Quellpfad wurde nicht getrackt: ${rel}`); for (const rel of runtimePaths) if (tracked.has(rel)) failures.push(`Runtime-Pfad wurde fälschlich getrackt: ${rel}`); } finally { rmSync(temp, { recursive: true, force: true }); } if (failures.length) { console.error(`Git-Ignore-Grenzprüfung 1.41.2 fehlgeschlagen (${failures.length}):`); failures.forEach(item => console.error(`- ${item}`)); process.exit(1); } console.log('Git-Ignore-Grenzprüfung 1.41.2 erfolgreich: app/modules und app/modules/sessions werden getrackt; nur Root-Runtimeordner bleiben ausgeschlossen.');