71 lines
2.6 KiB
JavaScript
71 lines
2.6 KiB
JavaScript
// Build-time regression gate for the job-log line-concatenation bug.
|
|
//
|
|
// THE BUG
|
|
//
|
|
// pixl-json-stream 1.0.9 emitted the last complete line of each read chunk
|
|
// WITHOUT a trailing newline:
|
|
//
|
|
// var text = record + ((idx < len - 1) ? self.EOL : '');
|
|
//
|
|
// Cronicle's bin/shell-plugin.js appends whatever the 'text' event hands it,
|
|
// verbatim, and relies on the library to supply the terminator:
|
|
//
|
|
// fs.appendFileSync(job.log_file, line);
|
|
//
|
|
// So whenever a chunk boundary landed mid-line, the preceding complete line
|
|
// lost its newline and the next line was glued onto it. Output arriving over a
|
|
// pipe -- e.g. a job running `docker exec <container> <cmd>` -- splits mid-line
|
|
// constantly, so in practice most of the log ran together:
|
|
//
|
|
// [2026/08/11 14:00:02] EDGAR company ticker map okinfo(...): provider ...
|
|
//
|
|
// 1.0.10 restored the unconditional `record + self.EOL`.
|
|
//
|
|
// WHY THIS FILE EXISTS
|
|
//
|
|
// This was not a build-time resolution accident that "npm ci" alone prevents.
|
|
// Upstream's own package-lock.json pinned the broken version:
|
|
//
|
|
// Cronicle v0.9.74 -> pixl-json-stream 1.0.9 (broken)
|
|
// Cronicle v0.9.126 -> pixl-json-stream 1.0.10 (fixed)
|
|
//
|
|
// A lockfile delivered the bug, so a lockfile can deliver it again. The failure
|
|
// mode is silent: jobs still succeed, logs are just quietly unreadable. Running
|
|
// this during `docker build` converts that into a hard build failure.
|
|
|
|
const JSONStream = require('pixl-json-stream');
|
|
const { PassThrough } = require('stream');
|
|
|
|
const input = new PassThrough();
|
|
const stream = new JSONStream(input, new PassThrough());
|
|
|
|
let log = '';
|
|
stream.on('text', (line) => {
|
|
log += line;
|
|
});
|
|
|
|
// Chunk boundaries deliberately fall mid-line ("tw" + "o"), reproducing what a
|
|
// real pipe does. A library that only terminates non-final records will drop
|
|
// the newline after "one" and after "three".
|
|
input.write('one\ntw');
|
|
input.write('o\nthree\nfou');
|
|
input.write('r\n');
|
|
|
|
// 'text' is emitted from the stream's 'data' handler, so let the event loop
|
|
// drain before asserting.
|
|
setTimeout(() => {
|
|
const want = 'one\ntwo\nthree\nfour\n';
|
|
|
|
if (log !== want) {
|
|
console.error('FAIL: pixl-json-stream is dropping line terminators.');
|
|
console.error(' got: ' + JSON.stringify(log));
|
|
console.error(' want: ' + JSON.stringify(want));
|
|
console.error('');
|
|
console.error('Cronicle job logs would silently concatenate lines.');
|
|
console.error('See the comment at the top of this file. Refusing to build.');
|
|
process.exit(1);
|
|
}
|
|
|
|
const version = require('pixl-json-stream/package.json').version;
|
|
console.log('OK: job log line terminators intact (pixl-json-stream ' + version + ')');
|
|
}, 200);
|