Output validation errors on stdout, slightly prettier formatted (#4424)
diff --git a/lib/src/command/lish.dart b/lib/src/command/lish.dart
index 5a8e4a7..892dc38 100644
--- a/lib/src/command/lish.dart
+++ b/lib/src/command/lish.dart
@@ -466,7 +466,7 @@
? _publicationFromEntrypoint()
: _publicationFromArchive(_fromArchive));
if (dryRun) {
- log.warning(publication.warningsCountMessage);
+ log.message(publication.warningsCountMessage);
if (publication.warningCount != 0) {
overrideExitCode(DATA);
}
diff --git a/lib/src/validator.dart b/lib/src/validator.dart
index 80c41a0..ee69ee6 100644
--- a/lib/src/validator.dart
+++ b/lib/src/validator.dart
@@ -185,36 +185,26 @@
.addAll([for (final validator in validators) ...validator.warnings]);
errors.addAll([for (final validator in validators) ...validator.errors]);
- if (errors.isNotEmpty) {
- final s = errors.length > 1 ? 's' : '';
- log.error('Package validation found the following error$s:');
- for (var error in errors) {
- log.error("* ${error.split('\n').join('\n ')}");
- }
- log.error('');
- }
+ String presentDiagnostics(List<String> diagnostics) => diagnostics
+ .map((diagnostic) => "* ${diagnostic.split('\n').join('\n ')}\n")
+ .join('\n');
+ final sections = <String>[];
- if (warnings.isNotEmpty) {
- final s = warnings.length > 1 ? 's' : '';
- log.warning(
- 'Package validation found the following potential issue$s:',
- );
- for (var warning in warnings) {
- log.warning("* ${warning.split('\n').join('\n ')}");
+ for (final (kind, diagnostics) in [
+ ('error', errors),
+ ('potential issue', warnings),
+ ('hint', hints),
+ ]) {
+ if (diagnostics.isNotEmpty) {
+ final s = diagnostics.length > 1 ? 's' : '';
+ final count = diagnostics.length > 1 ? '${diagnostics.length} ' : '';
+ sections.add(
+ 'Package validation found the following $count$kind$s:\n'
+ '${presentDiagnostics(diagnostics)}',
+ );
}
- log.warning('');
}
-
- if (hints.isNotEmpty) {
- final s = hints.length > 1 ? 's' : '';
- log.warning(
- 'Package validation found the following hint$s:',
- );
- for (var hint in hints) {
- log.warning("* ${hint.split('\n').join('\n ')}");
- }
- log.warning('');
- }
+ log.message(sections.join('\n'));
});
}
diff --git a/lib/src/validator/dependency_override.dart b/lib/src/validator/dependency_override.dart
index edefa8c..feeea6e 100644
--- a/lib/src/validator/dependency_override.dart
+++ b/lib/src/validator/dependency_override.dart
@@ -12,7 +12,7 @@
/// absence thereof).
class DependencyOverrideValidator extends Validator {
@override
- Future validate() {
+ Future<void> validate() async {
final overridden =
MapKeySet(context.entrypoint.workspaceRoot.allOverridesInWorkspace);
final dev = MapKeySet(package.devDependencies);
@@ -31,6 +31,5 @@
Please be extra careful when publishing.''');
}
- return Future.value();
}
}
diff --git a/pubspec.lock b/pubspec.lock
index 03806cc..dff072b 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,23 +5,23 @@
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: c57b02f47e021c9d7ced6d2e28824b315e0fd585578274bc4c2a5db0626f154a
+ sha256: "45cfa8471b89fb6643fe9bf51bd7931a76b8f5ec2d65de4fb176dba8d4f22c77"
url: "https://pub.dev"
source: hosted
- version: "75.0.0"
+ version: "73.0.0"
_macros:
dependency: transitive
description: dart
source: sdk
- version: "0.3.3"
+ version: "0.3.2"
analyzer:
dependency: "direct main"
description:
name: analyzer
- sha256: ef226c581b7cd875f734125b1b9928df3db08cc85ff87ce7d9be89a677aaee23
+ sha256: "4959fec185fe70cce007c57e9ab6983101dbe593d2bf8bbfb4453aaec0cf470a"
url: "https://pub.dev"
source: hosted
- version: "6.10.0"
+ version: "6.8.0"
args:
dependency: "direct main"
description:
@@ -178,10 +178,10 @@
dependency: transitive
description:
name: lints
- sha256: "4a16b3f03741e1252fda5de3ce712666d010ba2122f8e912c94f9f7b90e1a4c3"
+ sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
url: "https://pub.dev"
source: hosted
- version: "5.1.0"
+ version: "5.0.0"
logging:
dependency: transitive
description:
@@ -194,10 +194,10 @@
dependency: transitive
description:
name: macros
- sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656"
+ sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
url: "https://pub.dev"
source: hosted
- version: "0.1.3-main.0"
+ version: "0.1.2-main.4"
matcher:
dependency: transitive
description:
@@ -479,4 +479,4 @@
source: hosted
version: "2.2.1"
sdks:
- dart: ">=3.6.0-0 <4.0.0"
+ dart: ">=3.5.0 <4.0.0"
diff --git a/test/lish/dry_run_package_validation_has_a_warning_test.dart b/test/lish/dry_run_package_validation_has_a_warning_test.dart
index b8fa476..c748a91 100644
--- a/test/lish/dry_run_package_validation_has_a_warning_test.dart
+++ b/test/lish/dry_run_package_validation_has_a_warning_test.dart
@@ -28,7 +28,7 @@
await pub.shouldExit(exit_codes.DATA);
expect(
- pub.stderr,
+ pub.stdout,
emitsThrough('Package has 1 warning.'),
);
});
diff --git a/test/lish/dry_run_package_validation_has_no_warnings_test.dart b/test/lish/dry_run_package_validation_has_no_warnings_test.dart
index 08c84e9..fabef41 100644
--- a/test/lish/dry_run_package_validation_has_no_warnings_test.dart
+++ b/test/lish/dry_run_package_validation_has_no_warnings_test.dart
@@ -18,6 +18,6 @@
final pub = await startPublish(globalServer, args: ['--dry-run']);
await pub.shouldExit(exit_codes.SUCCESS);
- expect(pub.stderr, emitsThrough('Package has 0 warnings.'));
+ expect(pub.stdout, emitsThrough('Package has 0 warnings.'));
});
}
diff --git a/test/lish/force_publishes_if_there_are_warnings_test.dart b/test/lish/force_publishes_if_there_are_warnings_test.dart
index a09b75b..49fca21 100644
--- a/test/lish/force_publishes_if_there_are_warnings_test.dart
+++ b/test/lish/force_publishes_if_there_are_warnings_test.dart
@@ -42,20 +42,17 @@
});
await pub.shouldExit(exit_codes.SUCCESS);
- final stderrLines = await pub.stderr.rest.toList();
+ final stdoutLines = await pub.stdout.rest.toList();
expect(
- stderrLines,
+ stdoutLines,
allOf([
contains('Package validation found the following potential issue:'),
contains(
'* Your dependency on "foo" should have a version constraint. '
'For example:',
),
+ contains('Message from server: Package test_pkg 1.0.0 uploaded!'),
]),
);
- expect(
- pub.stdout,
- emitsThrough('Message from server: Package test_pkg 1.0.0 uploaded!'),
- );
});
}
diff --git a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
index f773bf6..80c3a95 100644
--- a/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
+++ b/test/testdata/goldens/directory_option_test/commands taking a --directory~-C parameter work.txt
@@ -138,8 +138,8 @@
Total compressed archive size: <1 KB.
Validating package...
The server may enforce additional checks.
-[STDERR]
-[STDERR] Package has 0 warnings.
+
+Package has 0 warnings.
-------------------------------- END OF OUTPUT ---------------------------------
diff --git a/test/testdata/goldens/validator/validations_output_test/Layout of publication warnings.txt b/test/testdata/goldens/validator/validations_output_test/Layout of publication warnings.txt
new file mode 100644
index 0000000..c85af45
--- /dev/null
+++ b/test/testdata/goldens/validator/validations_output_test/Layout of publication warnings.txt
@@ -0,0 +1,65 @@
+# GENERATED BY: test/validator/validations_output_test.dart
+
+## Section 0
+$ pub publish --dry-run
+Resolving dependencies...
+Downloading packages...
+! bar 1.0.0 (overridden)
++ foo 1.0.0
+Changed 1 dependency!
+Publishing myapp 0.0.0 to http://localhost:$PORT:
+├── bin
+│ └── main.dart (<1 KB)
+└── pubspec.yaml (<1 KB)
+
+Total compressed archive size: <1 KB.
+Validating package...
+Package validation found the following 4 errors:
+* You must have a LICENSE file in the root directory.
+ An open-source license helps ensure people can legally use your code.
+
+* Your pubspec.yaml is missing a "description" field.
+
+* Your pubspec.yaml is missing a "version" field.
+
+* line 1, column 1 of bin/main.dart: foo is in the `dev_dependencies` section of `pubspec.yaml`. Packages used in bin/ must be declared in the `dependencies` section.
+ ╷
+ 1 │ import 'package:foo/foo.dart';
+ │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ ╵
+
+Package validation found the following 5 potential issues:
+* `dart analyze` found the following issue(s):
+ Analyzing bin, pubspec.yaml...
+
+ warning - bin/main.dart:1:8 - Unused import: 'package:foo/foo.dart'. Try removing the import directive. - unused_import
+
+ 1 issue found.
+
+
+* It's strongly recommended to include a "homepage" or "repository" field in your pubspec.yaml
+
+* Your dependency on "bar" should have a version constraint. For example:
+
+ dependencies:
+ bar: ^1.0.0
+
+ Without a constraint, you're promising to support all future versions of "bar".
+
+* Please add a README.md file that describes your package.
+
+* Please add a `CHANGELOG.md` to your package. See https://dart.dev/tools/pub/publishing#important-files.
+
+Package validation found the following hint:
+* Non-dev dependencies are overridden in pubspec.yaml.
+
+ This indicates you are not testing your package against the same versions of its
+ dependencies that users will have when they use it.
+
+ This might be necessary for packages with cyclic dependencies.
+
+ Please be extra careful when publishing.
+[STDERR] Sorry, your package is missing some requirements and can't be published yet.
+[STDERR] For more information, see: https://dart.dev/tools/pub/cmd/pub-lish.
+[EXIT CODE] 65
+
diff --git a/test/validator/analyze_test.dart b/test/validator/analyze_test.dart
index 02addba..6d62230 100644
--- a/test/validator/analyze_test.dart
+++ b/test/validator/analyze_test.dart
@@ -80,7 +80,7 @@
]).create();
await expectValidation(
- error: allOf([
+ message: allOf([
contains(
"The 'http' protocol shouldn't be used because it isn't secure. "
"Try using a secure protocol, such as 'https'.",
@@ -132,7 +132,7 @@
]).create();
await expectValidation(
- error: allOf([
+ message: allOf([
contains('`dart analyze` found the following issue(s):'),
contains('Analyzing bin, lib, build.dart, link.dart, pubspec.yaml...'),
contains('error -'),
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart
index 858df16..7823d45 100644
--- a/test/validator/dependency_test.dart
+++ b/test/validator/dependency_test.dart
@@ -33,12 +33,12 @@
}
Future<void> expectValidation({
- Object? error,
+ Object? message,
int exitCode = 0,
Map<String, String> environment = const {},
}) async {
await runPub(
- error: error ?? contains('Package has 0 warnings.'),
+ output: message ?? contains('Package has 0 warnings.'),
args: ['publish', '--dry-run'],
// workingDirectory: d.path(appPath),
exitCode: exitCode,
@@ -47,25 +47,25 @@
}
Future<void> expectValidationWarning(
- Object? error, {
+ Object? message, {
int count = 1,
Map<String, String> environment = const {},
}) async {
- if (error is String) error = contains(error);
+ if (message is String) message = contains(message);
await expectValidation(
- error: allOf([error, contains('Package has $count warning')]),
+ message: allOf([message, contains('Package has $count warning')]),
exitCode: DATA,
environment: environment,
);
}
Future<void> expectValidationError(
- String text, {
+ String message, {
Map<String, String> environment = const {},
}) async {
await expectValidation(
- error: allOf([
- contains(text),
+ message: allOf([
+ contains(message),
contains('Package validation found the following error:'),
]),
exitCode: DATA,
diff --git a/test/validator/file_case_test.dart b/test/validator/file_case_test.dart
index cc98a32..1762b3a 100644
--- a/test/validator/file_case_test.dart
+++ b/test/validator/file_case_test.dart
@@ -15,9 +15,9 @@
import '../descriptor.dart' as d;
import '../test_pub.dart';
-Future<void> expectValidation(Matcher error, int exitCode) async {
+Future<void> expectValidation(Matcher output, int exitCode) async {
await runPub(
- error: error,
+ output: output,
args: ['publish', '--dry-run'],
workingDirectory: d.path(appPath),
exitCode: exitCode,
@@ -30,7 +30,7 @@
await d.dir(appPath, [d.file('Pubspec.yaml')]).create();
await expectValidation(
allOf(
- contains('Package validation found the following error:'),
+ matches(r'Package validation found the following \d* ?errors?:'),
contains(
'The file ./pubspec.yaml and ./Pubspec.yaml only differ in capitalization.',
),
diff --git a/test/validator/flutter_constraint_test.dart b/test/validator/flutter_constraint_test.dart
index 95217f4..c2c63f5 100644
--- a/test/validator/flutter_constraint_test.dart
+++ b/test/validator/flutter_constraint_test.dart
@@ -7,9 +7,9 @@
import '../descriptor.dart' as d;
import '../test_pub.dart';
-Future<void> expectValidation(Matcher error, int exitCode) async {
+Future<void> expectValidation(Matcher output, int exitCode) async {
await runPub(
- error: error,
+ output: output,
args: ['publish', '--dry-run'],
environment: {
'FLUTTER_ROOT': fakeFlutterRoot.io.path,
diff --git a/test/validator/git_status_test.dart b/test/validator/git_status_test.dart
index f92653a..0ca1875 100644
--- a/test/validator/git_status_test.dart
+++ b/test/validator/git_status_test.dart
@@ -10,14 +10,14 @@
import '../test_pub.dart';
Future<void> expectValidation(
- Matcher error,
+ Matcher output,
int exitCode, {
List<String> extraArgs = const [],
Map<String, String> environment = const {},
String? workingDirectory,
}) async {
await runPub(
- error: error,
+ output: output,
args: ['publish', '--dry-run', ...extraArgs],
environment: environment,
workingDirectory: workingDirectory ?? d.path(appPath),
diff --git a/test/validator/gitignore_test.dart b/test/validator/gitignore_test.dart
index 58c431f..ea73c6d 100644
--- a/test/validator/gitignore_test.dart
+++ b/test/validator/gitignore_test.dart
@@ -12,13 +12,13 @@
import '../test_pub.dart';
Future<void> expectValidation(
- Matcher error,
+ Matcher output,
int exitCode, {
Map<String, String> environment = const {},
String? workingDirectory,
}) async {
await runPub(
- error: error,
+ output: output,
args: ['publish', '--dry-run'],
environment: environment,
workingDirectory: workingDirectory ?? d.path(appPath),
diff --git a/test/validator/utils.dart b/test/validator/utils.dart
index 3b3016c..f470134 100644
--- a/test/validator/utils.dart
+++ b/test/validator/utils.dart
@@ -25,14 +25,14 @@
}
Future<void> expectValidation({
- Object? error,
+ Object? message,
int exitCode = 0,
Map<String, String> environment = const {},
List<String>? extraArgs,
String? workingDirectory,
}) async {
await runPub(
- error: error ?? contains('Package has 0 warnings.'),
+ output: message ?? contains('Package has 0 warnings.'),
args: ['publish', '--dry-run', ...?extraArgs],
// workingDirectory: d.path(appPath),
exitCode: exitCode,
@@ -48,7 +48,7 @@
}) async {
final s = count == 1 ? '' : 's';
await expectValidation(
- error: allOf([
+ message: allOf([
contains(error),
contains('Package has $count warning$s'),
]),
@@ -64,7 +64,7 @@
}) async {
final s = count == 1 ? '' : 's';
await expectValidation(
- error: allOf([
+ message: allOf([
contains(hint),
contains('and $count hint$s'),
]),
@@ -77,7 +77,7 @@
Map<String, String> environment = const {},
}) async {
await expectValidation(
- error: allOf([
+ message: allOf([
contains(text),
contains('Package validation found the following error:'),
]),
diff --git a/test/validator/validations_output_test.dart b/test/validator/validations_output_test.dart
new file mode 100644
index 0000000..352c8eb
--- /dev/null
+++ b/test/validator/validations_output_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../descriptor.dart';
+import '../golden_file.dart';
+import '../test_pub.dart';
+
+Future<void> main() async {
+ testWithGolden('Layout of publication warnings', (ctx) async {
+ final server = await servePackages();
+ server.serve('foo', '1.0.0');
+ server.serve('bar', '1.0.0');
+
+ await dir(appPath, [
+ pubspec({
+ 'name': 'myapp',
+ 'dev_dependencies': {'foo': '1.0.0'},
+ 'dependencies': {'bar': null},
+ 'dependency_overrides': {'bar': '1.0.0'},
+ }),
+ dir('bin', [
+ file('main.dart', '''
+import 'package:foo/foo.dart';
+'''),
+ ]),
+ ]).create();
+ await ctx.run(
+ ['publish', '--dry-run'],
+ environment: {
+ // Use more columns to avoid unintended line breaking.
+ '_PUB_TEST_TERMINAL_COLUMNS': '200',
+ },
+ );
+ });
+}