1 | # Plugin Developer Guide
|
2 |
|
3 | To create a plugin for `semantic-release`, you need to decide which parts of the release lifecycle are important to that plugin. For example, it is best to always have a `verify` step because you may be receiving inputs from a user and want to make sure they exist. A plugin can abide by any of the following lifecycles:
|
4 |
|
5 | - `verify`
|
6 | - `prepare`
|
7 | - `publish`
|
8 | - `success`
|
9 | - `fail`
|
10 |
|
11 | `semantic-release` will require the plugin via `node` and look through the required object for methods named like the lifecyles stated above. For example, if your plugin only had a `verify` and `success` step, the `main` file for your object would need to `export` an object with `verify` and `success` functions.
|
12 |
|
13 | In addition to the lifecycle methods, each lifecyle is passed two objects:
|
14 |
|
15 | 1. `pluginConfig` - an object containing the options that a user may pass in via their `release.config.js` file (or similar)
|
16 | 2. `context` - provided by `semantic-release` for access to things like `env` variables set on the running process.
|
17 |
|
18 | For each lifecycle you create, you will want to ensure it can accept `pluginConfig` and `context` as parameters.
|
19 |
|
20 | ## Creating a Plugin Project
|
21 |
|
22 | It is recommended that you generate a new project with `yarn init`. This will provide you with a basic node project to get started with. From there, create an `index.js` file, and make sure it is specified as the `main` in the `package.json`. We will use this file to orchestrate the lifecycle methods later on.
|
23 |
|
24 | Next, create a `src` or `lib` folder in the root of the project. This is where we will store our logic and code for how our lifecycle methods work. Finally, create a `test` folder so you can write tests related to your logic.
|
25 |
|
26 | We recommend you setup a linting system to ensure good javascript practices are enforced. ESLint is usually the system of choice, and the configuration can be whatever you or your team fancies.
|
27 |
|
28 | ## Exposing Lifecycle Methods
|
29 |
|
30 | In your `index.js` file, you can start by writing the following code
|
31 |
|
32 | ```javascript
|
33 | const verifyConditions = require('./src/verify');
|
34 |
|
35 | let verified;
|
36 |
|
37 | /**
|
38 | * Called by semantic-release during the verification step
|
39 | * @param {*} pluginConfig The semantic-release plugin config
|
40 | * @param {*} context The context provided by semantic-release
|
41 | */
|
42 | async function verify(pluginConfig, context) {
|
43 | await verifyConditions(pluginConfig, context);
|
44 | verified = true;
|
45 | }
|
46 |
|
47 | module.exports = { verify };
|
48 | ```
|
49 |
|
50 | Then, in your `src` folder, create a file called `verify.js` and add the following
|
51 |
|
52 | ```javascript
|
53 | const AggregateError = require('aggregate-error');
|
54 |
|
55 | /**
|
56 | * A method to verify that the user has given us a slack webhook url to post to
|
57 | */
|
58 | module.exports = async (pluginConfig, context) => {
|
59 | const { logger } = context;
|
60 | const errors = [];
|
61 |
|
62 | // Throw any errors we accumulated during the validation
|
63 | if (errors.length > 0) {
|
64 | throw new AggregateError(errors);
|
65 | }
|
66 | };
|
67 | ```
|
68 |
|
69 | As of right now, this code won't do anything. However, if you were to run this plugin via `semantic-release`, it would run when the `verify` step occurred.
|
70 |
|
71 | Following this structure, you can create different steps and checks to run through out the release process.
|
72 |
|
73 | ## Supporting Options
|
74 |
|
75 | Let's say we want to verify that an `option` is passed. An `option` is a configuration object that is specific to your plugin. For example, the user may set an `option` in their release config like:
|
76 |
|
77 | ```js
|
78 | {
|
79 | prepare: {
|
80 | path: "@semantic-release/my-special-plugin"
|
81 | message: "My cool release message"
|
82 | }
|
83 | }
|
84 | ```
|
85 |
|
86 | This `message` option will be passed to the `pluginConfig` object mentioned earlier. We can use the validation method we created to verify this option exists so we can perform logic based on that knowledge. In our `verify` file, we can add the following:
|
87 |
|
88 | ```js
|
89 | const { message } = pluginConfig;
|
90 |
|
91 | if (message.length) {
|
92 | //...
|
93 | }
|
94 | ```
|
95 |
|
96 | ## Supporting Environment Variables
|
97 |
|
98 | Similar to `options`, environment variables exist to allow users to pass tokens and set special URLs. These are set on the `context` object instead of the `pluginConfig` object. Let's say we wanted to check for `GITHUB_TOKEN` in the environment because we want to post to GitHub on the user's behalf. To do this, we can add the following to our `verify` command:
|
99 |
|
100 | ```js
|
101 | const { env } = context;
|
102 |
|
103 | if (env.GITHUB_TOKEN) {
|
104 | //...
|
105 | }
|
106 | ``` |
\ | No newline at end of file |