fix(admin): sync-sched-publish — .mappa вне паблик-сета + портативный leak-скан (gotcha 15/16, task:3059)
This commit is contained in:
@@ -60,13 +60,25 @@ function copyTree(srcFile, dstFile) {
|
||||
function collect() {
|
||||
const out = shSilent(`git -C "${DEV}" ls-files`);
|
||||
if (out === null) { fail("dev не git-репо"); return null; }
|
||||
const EXCL = /^\.wiki\/|^\.tasks\/|^\.agents\/|^AGENTS\.md$|^CLAUDE\.md$|^branding\/pora-|^pngtree-|^327274997_|^cat-clock-|^MIGRATION\.md$/;
|
||||
const EXCL = /^\.wiki\/|^\.tasks\/|^\.agents\/|^\.mappa\/|^AGENTS\.md$|^CLAUDE\.md$|^branding\/pora-|^pngtree-|^327274997_|^cat-clock-|^MIGRATION\.md$/;
|
||||
return out.split("\n").filter((f) => f && !EXCL.test(f));
|
||||
}
|
||||
|
||||
// dev-only артефакты, которые не должны жить в pub НИКОГДА (gotcha 15: .mappa/config.yaml
|
||||
// несёт внутренний реестр — tenant/mappa.vds.kzntsv.site/git.kzntsv.site; в волне 2026-09-19
|
||||
// утёк в паблик-коммит, потому что exclusion-list его не знал)
|
||||
const NEVER = [".mappa"];
|
||||
function purge() {
|
||||
for (const p of NEVER) {
|
||||
const t = `${PUB}/${p}`;
|
||||
if (fs.existsSync(t)) { fs.rmSync(t, { recursive: true, force: true }); log(`purge: удалён ${p} (dev-only)`); }
|
||||
}
|
||||
}
|
||||
|
||||
function copy(files) {
|
||||
for (const f of files) copyTree(`${DEV}/${f}`, `${PUB}/${f}`);
|
||||
log(`copy: ${files.length} файлов`);
|
||||
purge();
|
||||
}
|
||||
|
||||
// выбеливание — точечные замены, идемпотентно (эталон: верифицированный b0afd14)
|
||||
@@ -268,13 +280,32 @@ function gate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Портативный скан (gotcha 16): прежний `grep -rnE '…'` через cmd.exe на Windows НЕ работал:
|
||||
// cmd не снимает одинарные кавычки, а `|` для него — оператор pipe → команда падала,
|
||||
// shSilent возвращал null, проверка молча считалась зелёной (0 хитов). Теперь скан — на Node.
|
||||
function grepCheck() {
|
||||
const hits = shSilent(`cd "${PUB}" && grep -rnE 'git\\.kzntsv|verdaccio|vds\\.kzntsv|registry\\.kzntsv|VERDACCIO' --exclude-dir=node_modules --exclude-dir=.git .`);
|
||||
if (hits && hits.length > 0) {
|
||||
fail(`grep: остались ${hits.split("\n").length} вхождений kzntsv/verdaccio`);
|
||||
const re = /git\.kzntsv|verdaccio|vds\.kzntsv|registry\.kzntsv|VERDACCIO/i;
|
||||
const SKIP = new Set(["node_modules", ".git", ".yarn"]);
|
||||
const BIN = /\.(svg|png|webp|jpg|jpeg|gif|ico|woff2?|ttf|zip|gz)$/i;
|
||||
const hits = [];
|
||||
const walk = (dir) => {
|
||||
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const p = `${dir}/${e.name}`;
|
||||
if (e.isDirectory()) { if (!SKIP.has(e.name)) walk(p); continue; }
|
||||
if (BIN.test(p)) continue;
|
||||
let data;
|
||||
try { data = fs.readFileSync(p, "utf8"); } catch { continue; }
|
||||
data.split("\n").forEach((line, i) => {
|
||||
if (re.test(line)) hits.push(`${path.relative(PUB, p)}:${i + 1}: ${line.trim().slice(0, 140)}`);
|
||||
});
|
||||
}
|
||||
};
|
||||
walk(PUB);
|
||||
if (hits.length > 0) {
|
||||
fail(`grep: остались ${hits.length} вхождений kzntsv/verdaccio\n` + hits.slice(0, 10).join("\n"));
|
||||
return false;
|
||||
}
|
||||
log("grep: 0 вхождений kzntsv/verdaccio");
|
||||
log("grep: 0 вхождений kzntsv/verdaccio (портативный скан)");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user