Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .yarn/versions/e6b25f51.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
releases:
"@yarnpkg/builder": patch
"@yarnpkg/cli": minor
"@yarnpkg/core": minor
"@yarnpkg/doctor": patch
"@yarnpkg/extensions": patch
"@yarnpkg/nm": patch
"@yarnpkg/plugin-catalog": patch
"@yarnpkg/plugin-compat": patch
"@yarnpkg/plugin-constraints": patch
"@yarnpkg/plugin-dlx": patch
"@yarnpkg/plugin-essentials": minor
"@yarnpkg/plugin-exec": patch
"@yarnpkg/plugin-file": patch
"@yarnpkg/plugin-git": patch
"@yarnpkg/plugin-github": patch
"@yarnpkg/plugin-http": patch
"@yarnpkg/plugin-init": patch
"@yarnpkg/plugin-interactive-tools": patch
"@yarnpkg/plugin-jsr": patch
"@yarnpkg/plugin-link": patch
"@yarnpkg/plugin-nm": patch
"@yarnpkg/plugin-npm": patch
"@yarnpkg/plugin-npm-cli": patch
"@yarnpkg/plugin-pack": patch
"@yarnpkg/plugin-patch": patch
"@yarnpkg/plugin-pnp": patch
"@yarnpkg/plugin-pnpm": patch
"@yarnpkg/plugin-stage": patch
"@yarnpkg/plugin-typescript": patch
"@yarnpkg/plugin-version": patch
"@yarnpkg/plugin-workspace-tools": patch
"@yarnpkg/pnpify": patch
"@yarnpkg/sdks": patch
1 change: 1 addition & 0 deletions packages/plugin-essentials/sources/commands/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ export default class YarnCommand extends BaseCommand {

const report = await StreamReport.start({
configuration,
failOnWarnings: this.context.failOnWarnings,
json: this.json,
stdout: this.context.stdout,
forceSectionAlignment: true,
Expand Down
1 change: 1 addition & 0 deletions packages/yarnpkg-cli/sources/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function getBaseCli({cwd, pluginConfiguration}: {cwd: PortablePath, pluginConfig
...Cli.defaultContext,
cwd,
plugins: pluginConfiguration,
failOnWarnings: false,
quiet: false,
stdin: process.stdin,
stdout: process.stdout,
Expand Down
8 changes: 8 additions & 0 deletions packages/yarnpkg-cli/sources/tools/BaseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import {Command, Option, UsageError} from 'clipanion';
export abstract class BaseCommand extends Command<CommandContext> {
cwd = Option.String(`--cwd`, {hidden: true});

failOnWarnings = Option.Boolean(`--fail-on-warnings`, false, {
description: `Exit with a non-zero status code when warnings are reported`,
hidden: true,
});

abstract execute(): Promise<number | void>;

validateAndExecute(): Promise<number> {
if (typeof this.cwd !== `undefined`)
throw new UsageError(`The --cwd option is ambiguous when used anywhere else than the very first parameter provided in the command line, before even the command path`);

if (this.failOnWarnings)
this.context.failOnWarnings = true;

return super.validateAndExecute();
}
}
1 change: 1 addition & 0 deletions packages/yarnpkg-core/sources/Plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {Locator, Descriptor}
export type CommandContext = {
cwd: PortablePath;
env: Record<string, string | undefined>;
failOnWarnings: boolean;
plugins: PluginConfiguration;
quiet: boolean;
stdin: Readable;
Expand Down
16 changes: 15 additions & 1 deletion packages/yarnpkg-core/sources/StreamReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import * as formatUtils

export type StreamReportOptions = {
configuration: Configuration;
failOnWarnings?: boolean;
forceSectionAlignment?: boolean;
includeFooter?: boolean;
includeInfos?: boolean;
Expand Down Expand Up @@ -185,6 +186,7 @@ export class StreamReport extends Report {
}

private configuration: Configuration;
private failOnWarnings: boolean;
private forceSectionAlignment: boolean;
private includeNames: boolean;
private includePrefix: boolean;
Expand Down Expand Up @@ -225,6 +227,7 @@ export class StreamReport extends Report {
configuration,
stdout,
json = false,
failOnWarnings = false,
forceSectionAlignment = false,
includeNames = true,
includePrefix = true,
Expand All @@ -238,6 +241,7 @@ export class StreamReport extends Report {
formatUtils.addLogFilterSupport(this, {configuration});

this.configuration = configuration;
this.failOnWarnings = failOnWarnings;
this.forceSectionAlignment = forceSectionAlignment;
this.includeNames = includeNames;
this.includePrefix = includePrefix;
Expand All @@ -264,8 +268,18 @@ export class StreamReport extends Report {
return this.errorCount > 0;
}

hasWarnings() {
return this.warningCount > 0;
}

exitCode() {
return this.hasErrors() ? 1 : 0;
if (this.hasErrors())
return 1;

if (this.failOnWarnings && this.hasWarnings())
return 1;

return 0;
}

getRecommendedLength() {
Expand Down
34 changes: 34 additions & 0 deletions packages/yarnpkg-core/tests/StreamReport.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {PortablePath} from '@yarnpkg/fslib';
import {PassThrough} from 'stream';

import {Configuration} from '../sources/Configuration';
import {MessageName} from '../sources/MessageName';
import {StreamReport} from '../sources/StreamReport';

const configuration = Configuration.create(PortablePath.root);

describe(`StreamReport`, () => {
it.each<[string, {failOnWarnings?: boolean, reports: Array<`error` | `warning`>}, {exitCode: number, hasWarnings: boolean}]>([
[`no errors or warnings`, {reports: []}, {exitCode: 0, hasWarnings: false}],
[`errors only`, {reports: [`error`]}, {exitCode: 1, hasWarnings: false}],
[`warnings, failOnWarnings=false`, {failOnWarnings: false, reports: [`warning`]}, {exitCode: 0, hasWarnings: true}],
[`warnings, failOnWarnings=true`, {failOnWarnings: true, reports: [`warning`]}, {exitCode: 1, hasWarnings: true}],
[`errors, failOnWarnings=false`, {failOnWarnings: false, reports: [`error`]}, {exitCode: 1, hasWarnings: false}],
[`errors and warnings`, {reports: [`error`, `warning`]}, {exitCode: 1, hasWarnings: true}],
])(`%s`, async (_label, {failOnWarnings, reports}, expected) => {
const stdout = new PassThrough();

const report = await StreamReport.start({configuration, stdout, failOnWarnings}, async report => {
for (const type of reports) {
if (type === `error`) {
report.reportError(MessageName.UNNAMED, `test error`);
} else {
report.reportWarning(MessageName.UNNAMED, `test warning`);
}
}
});

expect(report.exitCode()).toEqual(expected.exitCode);
expect(report.hasWarnings()).toEqual(expected.hasWarnings);
});
});
Loading