* docs: prepare Vendoo 1.41.2 git-ignore boundary hotfix * fix: track native source modules with root-anchored runtime ignores
93 lines
5.4 KiB
JavaScript
93 lines
5.4 KiB
JavaScript
import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
|
|
import { join } from 'path';
|
|
|
|
const root = new URL('..', import.meta.url).pathname;
|
|
const read = rel => readFileSync(join(root, rel), 'utf8');
|
|
const failures = [];
|
|
const expect = (text, marker, label = marker) => { if (!text.includes(marker)) failures.push(`Fehlt: ${label}`); };
|
|
const forbid = (text, marker, label = marker) => { if (text.includes(marker)) failures.push(`Darf nicht enthalten sein: ${label}`); };
|
|
|
|
const pkg = JSON.parse(read('package.json'));
|
|
const lock = JSON.parse(read('package-lock.json'));
|
|
const manifest = JSON.parse(read('update-manifest.json'));
|
|
const server = read('server.mjs');
|
|
const auth = read('lib/auth.mjs');
|
|
const runtimePaths = read('lib/runtime-paths.mjs');
|
|
const dockerfile = read('Dockerfile');
|
|
const compose = read('compose.yaml');
|
|
const env = read('.env.example');
|
|
const html = read('public/index.html');
|
|
const app = read('public/app.js');
|
|
const setupPs = read('setup.ps1');
|
|
const setupSh = read('setup.sh');
|
|
const workflow = read('local-ai/workflows/vendoo_flux_schnell_api.json');
|
|
|
|
for (const [label, value] of [
|
|
['package.json', pkg.version], ['package-lock.json', lock.version],
|
|
['package-lock root', lock.packages?.['']?.version], ['update-manifest', manifest.version],
|
|
]) if (value !== '1.33.0') failures.push(`${label}-Version ist ${value}`);
|
|
|
|
for (const marker of ['content="1.33.0"', 'style.css?v=1.33.0', 'app.js?v=1.33.0']) expect(html, marker, `UI-Build ${marker}`);
|
|
if (!app.startsWith("const VENDOO_UI_BUILD = '1.33.0';")) failures.push('UI-Build ist nicht 1.33.0');
|
|
for (const marker of ["$Version = '1.33.0'", '?build=1.33.0']) expect(setupPs, marker, `Windows-Setup ${marker}`);
|
|
|
|
for (const marker of [
|
|
"app.get('/healthz'", "app.get('/readyz'", 'gracefulShutdown', "process.once('SIGTERM'",
|
|
'verifyRuntimeWritable', 'VENDOO_SETUP_TOKEN', 'VENDOO_EXTENSION_ORIGINS', 'setup_required: true',
|
|
"app.use('/uploads', requireAuth", 'allowed.includes(ext) && isImageMime',
|
|
]) expect(server, marker);
|
|
for (const marker of ['VENDOO_DATA_DIR', 'VENDOO_DB_PATH', 'VENDOO_UPLOADS_DIR', 'VENDOO_BACKUP_DIR', 'VENDOO_OPERATIONS_DIR']) expect(runtimePaths, marker);
|
|
forbid(server, 'if (isSetupMode()) return next();', 'unsichere globale Setup-Auth-Ausnahme');
|
|
|
|
for (const marker of ['FROM node:22-bookworm-slim', 'npm ci --omit=dev', 'USER node', 'HEALTHCHECK', 'ENTRYPOINT']) expect(dockerfile, marker);
|
|
for (const marker of ['read_only: true', 'no-new-privileges:true', 'cap_drop:', 'vendoo_db:', 'vendoo_uploads:', 'vendoo_backups:', '/readyz', 'pids_limit: 256', 'max-size: "10m"', 'host.docker.internal:host-gateway']) expect(compose, marker);
|
|
for (const marker of ['VENDOO_SETUP_TOKEN=', 'VENDOO_COOKIE_SECURE=', 'VENDOO_COOKIE_SAMESITE=', 'VENDOO_EXTENSION_ORIGINS=']) expect(env, marker);
|
|
if (workflow.includes('LoadImage')) failures.push('Freier FLUX-Workflow enthält LoadImage');
|
|
|
|
for (const marker of [
|
|
"Wo soll Vendoo betrieben werden?", 'Lokal auf diesem Windows-PC', 'Docker Desktop auf diesem Windows-PC',
|
|
'NAS / Portainer / Docker-Server', 'VPS / öffentlicher Linux-Server', 'Install-VendooDocker',
|
|
"Get-VendooInstallMode", "Set-VendooInstallMode 'docker'",
|
|
]) expect(setupPs, marker, `Windows-Deployment-Assistent ${marker}`);
|
|
|
|
if (!existsSync(join(root, 'setup.sh'))) failures.push('setup.sh fehlt');
|
|
for (const marker of [
|
|
'Multiplatform Deployment Assistant', 'Docker auf diesem Linux-/Docker-Host',
|
|
'NAS / Portainer / Docker-Host', 'VPS / öffentlicher Server hinter HTTPS-Reverse-Proxy',
|
|
'compose build --pull', 'VENDOO_SETUP_TOKEN', 'docker-backup.sh', 'docker-restore.sh',
|
|
]) expect(setupSh, marker, `Linux-Deployment-Assistent ${marker}`);
|
|
|
|
for (const marker of [
|
|
'id="flux-studio-reset"', 'Arbeitsbereich zurücksetzen', 'id="edit-user-email"',
|
|
'type="button" class="primary-btn" id="edit-user-save-btn"',
|
|
]) expect(html, marker, `UI-Fix ${marker}`);
|
|
for (const marker of [
|
|
'function resetFluxStudioWorkspace', "renderFluxStudioPreview(null)",
|
|
"document.getElementById('flux-studio-reset')", 'data-user-edit=',
|
|
'adminUsersCache', "button.textContent = 'Wird gespeichert …'",
|
|
]) expect(app, marker, `Frontend-Fix ${marker}`);
|
|
forbid(app, 'if (!state.fluxStudioCurrent && state.fluxStudioHistory[0])', 'automatische Auswahl des ersten FLUX-Historienbilds');
|
|
forbid(app, 'onclick="openEditUser(', 'fragile Inline-Benutzerbearbeitung');
|
|
for (const marker of ['return getUsers().find(user => Number(user.id) === Number(id)) || null;']) expect(auth, marker, 'sanitisierte Benutzerantwort nach Update');
|
|
|
|
function walk(dir, rel = '') {
|
|
const out = [];
|
|
for (const name of readdirSync(dir)) {
|
|
const path = join(dir, name); const child = join(rel, name);
|
|
if (statSync(path).isDirectory()) out.push(...walk(path, child)); else out.push(child.replaceAll('\\', '/'));
|
|
}
|
|
return out;
|
|
}
|
|
const forbiddenRuntime = walk(root).filter(rel =>
|
|
/(^|\/)(vendoo\.db|\.env|node_modules|uploads|backups|operations|logs|runtime|data)(\/|$)/i.test(rel)
|
|
&& rel !== '.env.example'
|
|
);
|
|
if (forbiddenRuntime.length) failures.push(`Verbotene Laufzeitdaten im Paket: ${forbiddenRuntime.slice(0, 10).join(', ')}`);
|
|
|
|
if (failures.length) {
|
|
console.error(`Deployment-Gate 1.33.0 fehlgeschlagen (${failures.length}):`);
|
|
failures.forEach(item => console.error(`- ${item}`));
|
|
process.exit(1);
|
|
}
|
|
console.log('Deployment-Gate 1.33.0 erfolgreich: Multiplatform-Assistent, Container-Härtung, leerer FLUX-Start, Reset und stabile Benutzerbearbeitung geprüft.');
|