diff --git a/pkgs/hooks_runner/CHANGELOG.md b/pkgs/hooks_runner/CHANGELOG.md index 91288ea40e..c2bb00b637 100644 --- a/pkgs/hooks_runner/CHANGELOG.md +++ b/pkgs/hooks_runner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +- Ensure build fails if a build hook does not produce an output file. + ## 1.0.0 - Stable release. diff --git a/pkgs/hooks_runner/lib/src/build_runner/build_runner.dart b/pkgs/hooks_runner/lib/src/build_runner/build_runner.dart index 5efdcd4b5d..6fc4e89c46 100644 --- a/pkgs/hooks_runner/lib/src/build_runner/build_runner.dart +++ b/pkgs/hooks_runner/lib/src/build_runner/build_runner.dart @@ -961,7 +961,17 @@ ${e.message}'''); String packageName, ) async { final file = hookOutputFile; - final fileContents = await file.readAsString(); + final String fileContents; + try { + fileContents = await file.readAsString(); + } on FileSystemException catch (e) { + logger.severe(''' +Building assets for package:$packageName failed. +Error reading ${hookOutputFile.uri.toFilePath()}. + +${e.message}'''); + return const Failure(HooksRunnerFailure.hookRun); + } logger.info('output.json contents:\n$fileContents'); final Map hookOutputJson; try { diff --git a/pkgs/hooks_runner/lib/src/locking/locking.dart b/pkgs/hooks_runner/lib/src/locking/locking.dart index 7a1c26f737..46cdff9ccf 100644 --- a/pkgs/hooks_runner/lib/src/locking/locking.dart +++ b/pkgs/hooks_runner/lib/src/locking/locking.dart @@ -87,6 +87,7 @@ Future _runUnderFileLock( if (!await file.exists()) await file.create(recursive: true); final randomAccessFile = await file.open(mode: FileMode.write); var printed = false; + var errorFromCallback = false; final stopwatch = Stopwatch()..start(); while (timeout == null || stopwatch.elapsed < timeout) { try { @@ -96,11 +97,19 @@ Future _runUnderFileLock( 'Last acquired by ${Platform.resolvedExecutable} ' '(pid $pid) running ${Platform.script} on ${DateTime.now()}.', ); - return await callback(); + try { + return await callback(); + } on FileSystemException { + errorFromCallback = true; + rethrow; + } } finally { await randomAccessFile.unlock(); } } on FileSystemException { + if (errorFromCallback) { + rethrow; + } if (!printed) { logger?.finer( 'Waiting to be able to obtain lock of directory: ${file.path}.', diff --git a/pkgs/hooks_runner/pubspec.yaml b/pkgs/hooks_runner/pubspec.yaml index 67ee7cf68d..3594c37ee3 100644 --- a/pkgs/hooks_runner/pubspec.yaml +++ b/pkgs/hooks_runner/pubspec.yaml @@ -2,7 +2,7 @@ name: hooks_runner description: >- This package is the backend that invokes build hooks. -version: 1.0.0 +version: 1.0.1 repository: https://github.com/dart-lang/native/tree/main/pkgs/hooks_runner diff --git a/pkgs/hooks_runner/test/build_runner/no_build_output_test.dart b/pkgs/hooks_runner/test/build_runner/no_build_output_test.dart new file mode 100644 index 0000000000..4c8ebedd33 --- /dev/null +++ b/pkgs/hooks_runner/test/build_runner/no_build_output_test.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2025, 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:logging/logging.dart'; +import 'package:test/test.dart'; + +import '../helpers.dart'; +import 'helpers.dart'; + +const Timeout longTimeout = Timeout(Duration(minutes: 5)); + +void main() async { + test('no build output', timeout: longTimeout, () async { + await inTempDir((tempUri) async { + await copyTestProjects(targetUri: tempUri); + final packageUri = tempUri.resolve('no_build_output/'); + + await runPubGet(workingDirectory: packageUri, logger: logger); + + final logMessages = []; + final result = await build( + packageUri, + createCapturingLogger(logMessages, level: Level.SEVERE), + dartExecutable, + buildAssetTypes: [], + ); + expect(result.isFailure, isTrue); + final fullLog = logMessages.join('\n'); + expect(fullLog, contains('Error reading')); + expect(fullLog, contains('output.json')); + }); + }); +} diff --git a/pkgs/hooks_runner/test_data/manifest.yaml b/pkgs/hooks_runner/test_data/manifest.yaml index e77ac74b53..a9ba72bb4a 100644 --- a/pkgs/hooks_runner/test_data/manifest.yaml +++ b/pkgs/hooks_runner/test_data/manifest.yaml @@ -139,6 +139,8 @@ - native_subtract/src/native_subtract.h - no_asset_for_link/hook/link.dart - no_asset_for_link/pubspec.yaml +- no_build_output/hook/build.dart +- no_build_output/pubspec.yaml - no_hook/lib/no_hook.dart - no_hook/pubspec.yaml - package_reading_metadata/hook/build.dart diff --git a/pkgs/hooks_runner/test_data/no_build_output/hook/build.dart b/pkgs/hooks_runner/test_data/no_build_output/hook/build.dart new file mode 100644 index 0000000000..7b14a35d59 --- /dev/null +++ b/pkgs/hooks_runner/test_data/no_build_output/hook/build.dart @@ -0,0 +1,7 @@ +// Copyright (c) 2025, 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. + +void main(List arguments) { + // This hook does nothing, and doesn't write an output file. +} diff --git a/pkgs/hooks_runner/test_data/no_build_output/pubspec.yaml b/pkgs/hooks_runner/test_data/no_build_output/pubspec.yaml new file mode 100644 index 0000000000..d4e4ee83a0 --- /dev/null +++ b/pkgs/hooks_runner/test_data/no_build_output/pubspec.yaml @@ -0,0 +1,13 @@ +name: no_build_output +description: A package with a build hook that does not produce any output. +version: 0.1.0 + +publish_to: none + +resolution: workspace + +environment: + sdk: '>=3.9.0 <4.0.0' + +dependencies: + hooks: any