Skip to content

run_tests_in_ci.js: fix truncated log output #7553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 8 commits into from
2 changes: 1 addition & 1 deletion config/mocha.browser.opts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@
# karma runner supports.
# This file is not converted to .mocharc.js format because karma-mocha doesn't work with it.

--timeout 20000
--timeout 60000
--retry 3
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ apiDescribe('Count queries', persistence => {
where('author', '==', 'authorA')
).withConverter(throwingConverter);
const snapshot = await getCountFromServer(query_);
expect(snapshot.data().count).to.equal(1);
expect(snapshot.data().count).to.equal(42);
});
});

Expand Down
2 changes: 1 addition & 1 deletion packages/firestore/test/integration/remote/stream.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ it('token is not invalidated once the stream is healthy', () => {
new FirestoreError(Code.UNAUTHENTICATED, '')
);
await streamListener.awaitCallback('close');
expect(credentials.observedStates).to.deep.equal(['getToken']);
expect(credentials.observedStates).to.deep.equal(['getTokenZZYZX']);
}, credentials);
});

Expand Down
61 changes: 28 additions & 33 deletions scripts/ci-test/build_changed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,41 +63,36 @@ async function buildForTests(
config: TestConfig,
{ buildAll = false }: Options
) {
try {
const testTasks = filterTasks(await getTestTasks(), config);
// print tasks for info
logTasks(testTasks);
if (testTasks.length === 0) {
console.log(chalk`{green No test tasks. Skipping all builds }`);
return;
}
const testTasks = filterTasks(await getTestTasks(), config);
// print tasks for info
logTasks(testTasks);
if (testTasks.length === 0) {
console.log(chalk`{green No test tasks. Skipping all builds }`);
return;
}

// build all and return
if (buildAll) {
await spawn('yarn', ['build'], { stdio: 'inherit', cwd: root });
return;
}
// build all and return
if (buildAll) {
await spawn('yarn', ['build'], { stdio: 'inherit', cwd: root });
return;
}

const lernaCmd = ['lerna', 'run'];
console.log(chalk`{blue Running build in:}`);
for (const task of testTasks) {
if (task.reason === TestReason.Changed) {
console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`);
} else if (task.reason === TestReason.Dependent) {
console.log(
chalk`{yellow ${task.pkgName} (depends on modified files)}`
);
} else {
console.log(chalk`{yellow ${task.pkgName} (running all tests)}`);
}
lernaCmd.push('--scope');
lernaCmd.push(task.pkgName);
const lernaCmd = ['lerna', 'run'];
console.log(chalk`{blue Running build in:}`);
for (const task of testTasks) {
if (task.reason === TestReason.Changed) {
console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`);
} else if (task.reason === TestReason.Dependent) {
console.log(
chalk`{yellow ${task.pkgName} (depends on modified files)}`
);
} else {
console.log(chalk`{yellow ${task.pkgName} (running all tests)}`);
}

lernaCmd.push('--include-dependencies', 'build');
await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root });
} catch (e) {
console.error(chalk`{red ${e}}`);
process.exit(1);
lernaCmd.push('--scope');
lernaCmd.push(task.pkgName);
}

lernaCmd.push('--include-dependencies', 'build');
await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root });
}
52 changes: 23 additions & 29 deletions scripts/ci-test/test_changed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,37 +49,31 @@ const config = testConfig[inputTestConfigName]!;
runTests(config);

async function runTests(config: TestConfig) {
try {
const testTasks = filterTasks(await getTestTasks(), config);
const testTasks = filterTasks(await getTestTasks(), config);

// print tasks for info
logTasks(testTasks);
if (testTasks.length === 0) {
chalk`{green No test tasks. Skipping all tests }`;
process.exit(0);
}
// print tasks for info
logTasks(testTasks);
if (testTasks.length === 0) {
chalk`{green No test tasks. Skipping all tests }`;
process.exit(0);
}

const lernaCmd = ['lerna', 'run', '--concurrency', '4'];
console.log(chalk`{blue Running tests in:}`);
for (const task of testTasks) {
if (task.reason === TestReason.Changed) {
console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`);
} else if (task.reason === TestReason.Dependent) {
console.log(
chalk`{yellow ${task.pkgName} (depends on modified files)}`
);
} else {
console.log(chalk`{yellow ${task.pkgName} (running all tests)}`);
}
lernaCmd.push('--scope');
lernaCmd.push(task.pkgName);
const lernaCmd = ['lerna', 'run', '--concurrency', '4'];
console.log(chalk`{blue Running tests in:}`);
for (const task of testTasks) {
if (task.reason === TestReason.Changed) {
console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`);
} else if (task.reason === TestReason.Dependent) {
console.log(
chalk`{yellow ${task.pkgName} (depends on modified files)}`
);
} else {
console.log(chalk`{yellow ${task.pkgName} (running all tests)}`);
}

lernaCmd.push(testCommand);
await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root });
process.exit(0);
} catch (e) {
console.error(chalk`{red ${e}}`);
process.exit(1);
lernaCmd.push('--scope');
lernaCmd.push(task.pkgName);
}

lernaCmd.push(testCommand);
await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root });
}
82 changes: 46 additions & 36 deletions scripts/run_tests_in_ci.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

const yargs = require('yargs');
const path = require('path');
const { spawn } = require('child-process-promise');
const { writeFileSync } = require('fs');
const { spawn } = require('node:child_process');
const fs = require('node:fs');

const LOGDIR = process.env.CI ? process.env.HOME : '/tmp';
// Maps the packages where we should not run `test:all` and instead isolate the cross-browser tests.
Expand All @@ -30,16 +30,17 @@ const crossBrowserPackages = {
'packages/firestore-compat': 'test:browser'
};

function writeLogs(status, name, logText) {
const safeName = name.replace(/@/g, 'at_').replace(/\//g, '_');
writeFileSync(path.join(LOGDIR, `${safeName}-ci-log.txt`), logText, {
encoding: 'utf8'
function getPathSafeName(name) {
return name.replace(/@/g, 'at_').replace(/\//g, '_');
}

async function printFile(path) {
const readStream = fs.createReadStream(path);
readStream.pipe(process.stdout);
await new Promise((resolve, reject) => {
readStream.once('end', resolve);
readStream.once('error', reject);
});
writeFileSync(
path.join(LOGDIR, `${safeName}-ci-summary.txt`),
`${status}: ${name}`,
{ encoding: 'utf8' }
);
}

const argv = yargs.options({
Expand All @@ -60,34 +61,43 @@ const argv = yargs.options({
let scriptName = argv.s;
const dir = path.resolve(myPath);
const { name } = require(`${dir}/package.json`);
const testOutputFile = path.join(
LOGDIR,
`${getPathSafeName(name)}-ci-log.txt`
);

let stdout = '';
let stderr = '';
try {
if (process.env?.BROWSERS) {
for (const package in crossBrowserPackages) {
if (dir.endsWith(package)) {
scriptName = crossBrowserPackages[package];
}
if (process.env?.BROWSERS) {
for (const package in crossBrowserPackages) {
if (dir.endsWith(package)) {
scriptName = crossBrowserPackages[package];
}
}
const testProcess = spawn('yarn', ['--cwd', dir, scriptName]);
}

const testOutputFileHandle = fs.openSync(testOutputFile, 'w');
const testProcess = spawn('yarn', ['--cwd', dir, scriptName], {
stdio: ['inherit', testOutputFileHandle, testOutputFileHandle]
});

const exitCode = await new Promise((resolve, reject) => {
testProcess.once('close', resolve);
testProcess.once('error', reject);
}).finally(() => {
fs.closeSync(testOutputFileHandle);
});

testProcess.childProcess.stdout.on('data', data => {
stdout += data.toString();
});
testProcess.childProcess.stderr.on('data', data => {
stderr += data.toString();
});
const resultStr = exitCode === 0 ? 'Success' : 'Failure';
console.log(`${resultStr}: ${name}`);
await printFile(testOutputFile);

await testProcess;
console.log('Success: ' + name);
writeLogs('Success', name, stdout + '\n' + stderr);
} catch (e) {
console.error('Failure: ' + name);
console.log(stdout);
console.error(stderr);
writeLogs('Failure', name, stdout + '\n' + stderr);
process.exit(1);
}
fs.writeFileSync(
path.join(LOGDIR, `${getPathSafeName(name)}-ci-summary.txt`),
`${resultStr}: ${name}`,
{ encoding: 'utf8' }
);

// NOTE: Set `process.exitCode` rather than calling `process.exit()` because
// the latter will exit forcefully even if stdout/stderr have not been fully
// flushed, leading to truncated output.
process.exitCode = exitCode;
})();