diff --git a/src/content/docs/docs/guides/writing-tasks.mdx b/src/content/docs/docs/guides/writing-tasks.mdx index 9487ffad..ea09419e 100644 --- a/src/content/docs/docs/guides/writing-tasks.mdx +++ b/src/content/docs/docs/guides/writing-tasks.mdx @@ -117,4 +117,42 @@ If you're developing a plugin, you must use `setAction()` with lazy-loaded modul To learn more about how task actions are loaded, see the [Task Actions' lifecycle](/docs/plugin-development/explanations/lifecycle#task-actions-lifecycle) documentation. +## Returning a result + +Task actions can optionally return a `Result` to signal success or failure to the CLI. When a task action returns a failed result, the CLI sets the process exit code to 1. This is useful when you want to indicate failure to scripts or CI pipelines without throwing an exception. + +To use this, import the `Result` type from `hardhat/types/utils` and the helper functions from `hardhat/utils/result`: + +```ts +// tasks/accounts.ts +import type { HardhatRuntimeEnvironment } from "hardhat/types/hre"; +import type { Result } from "hardhat/types/utils"; +import { successfulResult, errorResult } from "hardhat/utils/result"; + +interface AccountTaskArguments {} + +export default async function ( + _taskArguments: AccountTaskArguments, + hre: HardhatRuntimeEnvironment, +): Promise> { + const { provider } = await hre.network.connect(); + const accounts = await provider.request({ method: "eth_accounts" }); + + if (accounts.length === 0) { + return errorResult("No accounts found"); + } + + return successfulResult(accounts); +} +``` + +`Result` is a discriminated union: + +- `{ success: true; value: ValueT }` - a successful result, carrying a value +- `{ success: false; error: ErrorT }` - a failed result, carrying error information + +Use `successfulResult(value?)` and `errorResult(error?)` to create these objects. Both helpers can be called without a parameter, in which case they set `value` or `error` to `undefined`. + +If a task action doesn't return a `Result` (for example, it returns `undefined` or any other value), the CLI exit code is left unchanged. + {/* To learn more about tasks, please read [this guide](../advanced/create-task). */} diff --git a/src/content/docs/docs/plugin-development/explanations/lifecycle.mdx b/src/content/docs/docs/plugin-development/explanations/lifecycle.mdx index 2a770949..e7fcc4e7 100644 --- a/src/content/docs/docs/plugin-development/explanations/lifecycle.mdx +++ b/src/content/docs/docs/plugin-development/explanations/lifecycle.mdx @@ -259,6 +259,12 @@ Inline actions are loaded immediately when the configuration file is evaluated, Plugins cannot use `setInlineAction()`. Attempting to do so will result in an error. Plugins must always use `setAction()` with lazy-loaded modules. ::: +### Returning a result + +The task action, either the inline callback you pass to `setInlineAction()`, or the `default` export of the module loaded via `setAction()`, can optionally return a `Result` value. If the action returns a result with `success: false`, the CLI sets the process exit code to 1. + +To learn more, see the [Returning a result](/docs/guides/writing-tasks#returning-a-result) section of the Writing Hardhat tasks guide. + ## Configuration Variables' lifecycle There are two things that plugins can do with Configuration Variables: