Warn on `pub publish` if `dart analyze` has messages (#3568)
diff --git a/lib/src/log.dart b/lib/src/log.dart index f845aa6..61c6768 100644 --- a/lib/src/log.dart +++ b/lib/src/log.dart
@@ -8,7 +8,6 @@ import 'dart:io'; import 'package:args/command_runner.dart'; -import 'package:meta/meta.dart'; import 'package:path/path.dart' as p; import 'package:source_span/source_span.dart'; import 'package:stack_trace/stack_trace.dart'; @@ -341,7 +340,6 @@ /// replacing it with '[...]' if it is too long. /// /// [limit] must be more than 5. -@visibleForTesting String limitLength(String input, int limit) { const snip = '[...]'; assert(limit > snip.length);
diff --git a/lib/src/validator.dart b/lib/src/validator.dart index ef04bc4..82de012 100644 --- a/lib/src/validator.dart +++ b/lib/src/validator.dart
@@ -11,6 +11,7 @@ import 'entrypoint.dart'; import 'log.dart' as log; import 'sdk.dart'; +import 'validator/analyze.dart'; import 'validator/changelog.dart'; import 'validator/compiled_dartdoc.dart'; import 'validator/dependency.dart'; @@ -130,6 +131,7 @@ required List<String> warnings, required List<String> errors}) async { var validators = [ + AnalyzeValidator(), GitignoreValidator(), PubspecValidator(), LicenseValidator(),
diff --git a/lib/src/validator/analyze.dart b/lib/src/validator/analyze.dart new file mode 100644 index 0000000..b9af306 --- /dev/null +++ b/lib/src/validator/analyze.dart
@@ -0,0 +1,30 @@ +// Copyright (c) 2022, 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 'dart:async'; +import 'dart:io'; + +import 'package:path/path.dart' as p; + +import '../io.dart'; + +import '../log.dart'; +import '../validator.dart'; + +/// Runs `dart analyze` and gives a warning if it returns non-zero. +class AnalyzeValidator extends Validator { + @override + Future<void> validate() async { + final result = await runProcess(Platform.resolvedExecutable, [ + 'analyze', + '--fatal-infos', + if (!p.equals(entrypoint.root.dir, p.current)) entrypoint.root.dir, + ]); + if (result.exitCode != 0) { + final limitedOutput = limitLength(result.stdout.join('\n'), 1000); + warnings + .add('`dart analyze` found the following issue(s):\n$limitedOutput'); + } + } +}
diff --git a/test/validator/analyze_test.dart b/test/validator/analyze_test.dart new file mode 100644 index 0000000..0717b3c --- /dev/null +++ b/test/validator/analyze_test.dart
@@ -0,0 +1,102 @@ +// Copyright (c) 2022, 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 'package:pub/src/exit_codes.dart'; +import 'package:test/test.dart'; + +import '../descriptor.dart' as d; +import '../test_pub.dart'; + +Future<void> expectValidation( + error, + int exitCode, { + List<String> extraArgs = const [], + Map<String, String> environment = const {}, + String? workingDirectory, +}) async { + await runPub( + error: error, + args: ['publish', '--dry-run', ...extraArgs], + environment: {'_PUB_TEST_SDK_VERSION': '1.12.0', ...environment}, + workingDirectory: workingDirectory ?? d.path(appPath), + exitCode: exitCode, + ); +} + +void main() { + test('should consider a package valid if it contains no warnings or errors', + () async { + await d.dir(appPath, [ + d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'), + d.file('LICENSE', 'Eh, do what you want.'), + d.file('README.md', "This package isn't real."), + d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'), + d.dir('lib', [d.file('test_pkg.dart', 'int i = 1;')]) + ]).create(); + + await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'}); + + await expectValidation(contains('Package has 0 warnings.'), 0); + }); + + test('should warn if package contains errors, and works with --directory', + () async { + await d.dir(appPath, [ + d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'), + d.file('LICENSE', 'Eh, do what you want.'), + d.file('README.md', "This package isn't real."), + d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'), + d.dir('lib', [ + d.file('test_pkg.dart', ''' +void main() { +// Missing } +''') + ]) + ]).create(); + + await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'}); + + await expectValidation( + allOf([ + contains('`dart analyze` found the following issue(s):'), + contains('Analyzing myapp...'), + contains('error -'), + contains("Expected to find '}'."), + contains('Package has 1 warning.') + ]), + DATA, + extraArgs: ['--directory', appPath], + workingDirectory: d.sandbox, + ); + }); + + test('should warn if package contains infos', () async { + await d.dir(appPath, [ + d.libPubspec('test_pkg', '1.0.0', sdk: '>=1.8.0 <=2.0.0'), + d.file('LICENSE', 'Eh, do what you want.'), + d.file('README.md', "This package isn't real."), + d.file('CHANGELOG.md', '# 1.0.0\nFirst version\n'), + d.dir('lib', [ + d.file('test_pkg.dart', ''' +void main() { + final a = 10; // Unused. +} +''') + ]), + ]).create(); + + await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.12.0'}); + + await expectValidation( + allOf([ + contains('`dart analyze` found the following issue(s):'), + contains('Analyzing myapp...'), + contains('info -'), + contains("The value of the local variable 'a' isn't used"), + contains('Package has 1 warning.') + ]), + DATA, + ); + }); +}
diff --git a/test/validator/dependency_test.dart b/test/validator/dependency_test.dart index 69fc4a8..b3adc34 100644 --- a/test/validator/dependency_test.dart +++ b/test/validator/dependency_test.dart
@@ -39,10 +39,10 @@ } Future<void> expectValidationWarning(error, - {Map<String, String> environment = const {}}) async { + {int count = 1, Map<String, String> environment = const {}}) async { if (error is String) error = contains(error); await expectValidation( - error: allOf([error, contains('Package has 1 warning.')]), + error: allOf([error, contains('Package has $count warning')]), exitCode: DATA, environment: environment, ); @@ -106,7 +106,9 @@ await expectValidationWarning( allOf([ contains(' foo: any'), + contains("Publishable packages can't have 'git' dependencies"), ]), + count: 2, environment: {'_PUB_TEST_SDK_VERSION': '2.0.0'}); });