UNPKG

@controlplane/cli

Version:

Control Plane Corporation CLI

154 lines 6.45 kB
"use strict"; // ANCHOR - Constants Object.defineProperty(exports, "__esModule", { value: true }); exports.RemoteBuildLogFilter = void 0; // Whole vertices to drop: registry auth, cache-manifest imports, internal builder steps. const DROP_VERTEX = /\[auth\]|importing cache manifest|railpack/; // Cache export is collapsed to its header and DONE — its per-layer writes are noise. // Any phrase here classifies the vertex, so a log that begins mid-vertex still collapses it. const CACHE_EXPORT_VERTEX = /exporting cache to registry|preparing build cache|writing cache image manifest|writing (?:layer|config) sha256:/; const CACHE_EXPORT_HEADER = /exporting cache to registry/; // Error-context blocks for dropped cache steps; real build-step failures do not match. const NOISE_BLOCK = /importing cache manifest|exporting cache to registry/; // A ------ line opens and closes a failed step's error-context block. const SEPARATOR = '------'; // Every log line of a build step starts with the step's vertex number, e.g. "#15 npm ci". const VERTEX = /^#(\d+)\b/; // The line that closes a vertex, e.g. "#29 DONE 36.2s". const VERTEX_DONE = /^#\d+ DONE\b/; // ANCHOR - RemoteBuildLogFilter /** * Trims BuildKit plain-progress noise from the streamed build log while leaving real * build steps and failures untouched. Unrecognized lines always pass through, so a * change in BuildKit's wording shows more, never less. */ class RemoteBuildLogFilter { constructor() { // Start "blank" so a leading blank left by a dropped opening vertex is suppressed. this.lastBlank = true; this.block = null; this.verdicts = new Map(); this.headerShown = new Set(); } // Public Methods // /** * Filters one log line, returning the lines to actually print — usually zero or * one, or several when a buffered error-context block is released. * * @param {string} line - One BuildKit log line. * @returns {string[]} The lines to print. */ accept(line) { // Inside a ------ block, every line is buffered until the closing separator arrives. if (this.block !== null) { this.block.push(line); // The closing separator seals the block: a cache-noise block vanishes, any other block prints whole. if (line.trim() === SEPARATOR) { const buffered = this.block; this.block = null; return NOISE_BLOCK.test(buffered.join('\n')) ? [] : this.emit(buffered); } return []; } // An opening separator starts buffering — whether the block is noise is only known from its content. if (line.trim() === SEPARATOR) { this.block = [line]; return []; } const match = line.match(VERTEX); // A line outside any vertex — a blank separator or a closing error summary — passes through. if (!match) { return this.emit([line]); } // Vertex lines are judged per build step, keyed by the vertex number. return this.acceptVertexLine(Number(match[1]), line); } /** * Flushes any buffered error-context block that never closed, so no line is lost * when the log ends mid-block. * * @returns {string[]} The remaining lines to print. */ finish() { // Nothing buffered — the log ended cleanly. if (this.block === null) { return []; } // A block with no closing separator is incomplete; it prints rather than risk hiding a real failure. const buffered = this.block; this.block = null; return this.emit(buffered); } // Private Methods // /** * Classifies a vertex line and returns the lines to print for it. A vertex is * classified once, on its first line — a build step whose own output mentions a * marker phrase is never reclassified and swallowed mid-stream. * * @param {number} vertex - The vertex number. * @param {string} line - The vertex line. * @returns {string[]} The lines to print. */ acceptVertexLine(vertex, line) { // The first line seen for a vertex decides its fate; later lines never re-judge it. if (!this.verdicts.has(vertex)) { this.verdicts.set(vertex, judgeVertex(line)); } const verdict = this.verdicts.get(vertex); // A dropped vertex vanishes entirely, its DONE line included. if (verdict === 'drop') { return []; } // A normal build step prints verbatim. if (verdict !== 'collapse') { return this.emit([line]); } // The collapsed cache export keeps its DONE line — it carries the step's total time. if (VERTEX_DONE.test(line)) { return this.emit([line]); } // The header line prints once, even when the vertex restarts and repeats it. if (CACHE_EXPORT_HEADER.test(line) && !this.headerShown.has(vertex)) { this.headerShown.add(vertex); return this.emit([line]); } // Everything else in the collapsed vertex is per-layer progress noise. return []; } /** * Passes lines through, collapsing runs of blank lines that suppression can leave behind. * * @param {string[]} lines - The candidate lines. * @returns {string[]} The lines to print. */ emit(lines) { const out = []; for (const line of lines) { const blank = line.trim() === ''; // Dropping a vertex makes the blanks around it adjacent; only the first survives. if (blank && this.lastBlank) { continue; } this.lastBlank = blank; out.push(line); } return out; } } exports.RemoteBuildLogFilter = RemoteBuildLogFilter; // SECTION - Functions /** * Judges one build step from its first line: pure machinery is dropped outright, the * cache export is kept but reduced to its header and DONE, everything else prints. * * @param {string} line - The vertex's first line. * @returns {VertexVerdict} What to do with every line of this vertex. */ function judgeVertex(line) { if (DROP_VERTEX.test(line)) { return 'drop'; } return CACHE_EXPORT_VERTEX.test(line) ? 'collapse' : 'keep'; } // !SECTION //# sourceMappingURL=log-filter.js.map