embark/site/source/docs/executing_scripts.md

116 lines
4.8 KiB
Markdown
Raw Permalink Normal View History

feat(plugins/scripts-runner): introduce exec command to run scripts This commit introduces a new feature that enables users to run (migration) scripts. Similar to deployment hooks, scripts are functions that may perform operations on newly deployed Smart Contracts. Therefore a script needs to export a function that has access to some dependencies: ``` // scripts/001-some-script.js module.exports = async ({contracts, web3, logger}) => { ... }; ``` Where `contracts` is a map of newly deployed Smart Contract instances, `web3` a blockchain connector instance and `logger` Embark's logger instance. Script functions can but don't have to be `async`. To execute such a script users use the newly introduced `exec` command: ``` $ embark exec development scripts/001-some-script.js ``` In the example above, `development` defines the environment in which Smart Contracts are being deployed to as well as where tracking data is stored. Alternativey, users can also provide a directory in which case Embark will try to execute every script living inside of it: ``` $ embark exec development scripts ``` Scripts can fail and therefore emit an error accordingly. When this happens, Embark will abort the script execution (in case multiple are scheduled to run) and informs the user about the original error: ``` .. 001_foo.js running.... Script '001_foo.js' failed to execute. Original error: Error: Some error ``` It's recommended for scripts to emit proper instances of `Error`. (Migration) scripts can be tracked as well but there are a couple of rules to be aware of: - Generally, tracking all scripts that have been executed by default is not a good thing because some scripts might be one-off operations. - OTOH, there might be scripts that should always be tracked by default - Therefore, we introduce a dedicated `migrations` directory in which scripts live that should be tracked by default - Any other scripts that does not live in the specified `migrations` directory will not be tracked **unless** - The new `--track` option was provided For more information see: https://notes.status.im/h8XwB7xkR7GKnfNh6OnPMQ
2020-02-04 10:47:12 +00:00
title: Executing Scripts
layout: docs
---
There are various features in Embark that help you making the deployment of your DApps and Smart Contracts as smooth as possible. Next to general [Smart Contract Configurations](contracts_configuration.html), [Deployment Hooks](contracts_configuration.html#Deployment-hooks) and [Cockpit](cockpit_introduction.html), there's the possibility to run (migration) scripts as well.
In this guide we'll explore why scripts are useful and how they can be run.
## Why scripts?
Given that Embark supports [afterDeploy](contracts_configuration.html#afterDeploy-hook) hooks that make it extremely easy to perform custom operations after all of your Smart Contracts have been deployed, you might wonder when and where scripts can be useful.
It's important to note that `afterDeploy` hooks are executed every time all Smart Contracts have been deployed. Often there are cases where running a (migration) script manually is what you really need.
Scripts let you do exactly that as they can be run at any time, regardless of what your app's current deployment status is.
## What's a script?
A script is really just a file with an exported function that has special dependencies injected into it. Here's what it could look like:
```
modules.exports = async ({ contracts, web3, logger}) => {
...
};
```
The injected parameters are:
- `contracts` - A map object containing all of your Smart Contracts as Embark Smart Contract instances.
- `web3` - A web3 instances to give you access to things like accounts.
- `logger` - Embark's custom logger.
Scripts can be located anywhere on your machine, but should most likely live inside your project's file tree in a dedicated folder.
## Running scripts
To run a script, use the CLI `exec` command and specify an environment as well as the script to be executed:
```
$ embark exec development scripts/001.js
```
The command above will execute the function in `scripts/001.js` and ensures that Smart Contracts are deployed in the `development` environment.
If you have multiple scripts that should run in order, it's also possible to specify the directory in which they live in:
```
$ embark exec development scripts
```
Embark will then find all script files inside the specified directory (in this case `scripts`) and then run them one by one. If any of the scripts fails by emitting an error, Embark will abort the execution. Scripts are executed in sequence, which means all following scripts won't be executed in case of an error.
## Error Handling
It's possible and recommended for scripts to emit proper errors in case they fail to do their job. There are several ways to emit an error depending on how you write your function. Scripts are executed asyncronously, so one way to emit an error is to reject a promise:
```
modules.exports = () => {
return new Promise((resolve, reject) => {
reject(new Error('Whoops, something went wrong'));
});
};
// or
modules.exports = () => {
return Promise.reject(new Error ('Whoops, something went wrong'));
};
```
If your script uses the `async/await` syntax, errors are emitted by default when using other `async` APIs that fail:
```
module.exports = async () => {
await someAPIThatFails(); // this will emit an error
};
```
If an error is emitted, Embark will do its best to give you information about the original error:
```
001.js running....
Script '001.js' failed to execute. Original error: Error: Whoops, something went wrong
```
## Tracking scripts
Just like Smart Contract deployments are tracked, (migration) scripts can be tracked as well. Since scripts can be one-off operations, Embark will not track whether they have been executed by default. Users are always able to run a script using the `exec` command as discussed in the previous sections.
To have Embark "remember" that a certain script was already run, you can use the `--track` option of the `exec` command, which will force tracking for this particular script:
```
$ embark exec development scripts/001.js --track
```
If we try to run the script again with the `--track` option, Embark will notice that the script has already been executed and tell us that it's "already done".
```
$ embark exec development scripts/001.js --track
.. 001.js already done
```
If however, we don't provide the `--track` flag, Embark will execute the script as usual.
For cases in which we **do** want to track a set of scripts, especially when the main use case are migration operations, we can put our scripts in a special "migrations" directory. All scripts inside that directory will be tracked by default.
The directory can be specified using the `migrations` property in your project's embark.json:
```
{
...
migrations: 'migrations'
}
```
If no such property is specified, Embark will default to "migrations". Running any script or set of scripts is then automatically tracked.