Skip to content

Commit

Permalink
clean up writing plugin docs
Browse files Browse the repository at this point in the history
  • Loading branch information
hipstersmoothie committed May 17, 2020
1 parent a5c5e6d commit 3a35a37
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 114 deletions.
4 changes: 2 additions & 2 deletions docs/pages/plugins/configuration-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Make sure to account for the [different ways you plugin can be included](./plugi

```ts
auto.hooks.validateConfig.tapPromise("test", (name, options) => {
if (name === this.name || name === `@auto-it/${this.name}`) {
if (name === this.name || name === `auto-plugin-${this.name}`) {
return; // your validation error. Can either be strings for { path, expectedType, value }
}
});
Expand Down Expand Up @@ -137,7 +137,7 @@ To do this `auto` exposes a helper function to validate you plugins with the `io
import { validatePluginConfiguration } from "@auto-it/core";

auto.hooks.validateConfig.tapPromise("test", (name, options) => {
if (name === this.name || name === `@auto-it/${this.name}`) {
if (name === this.name || name === `auto-plugin-${this.name}`) {
return validatePluginConfiguration(this.name, pluginOptions, options);
}
});
Expand Down
3 changes: 1 addition & 2 deletions docs/pages/plugins/hook-api-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ Some hooks are specific to a single command, such as the "Init" hooks, and other
This is the general flow when any `auto` command is ran:

- Call configuration hooks
- Run `before` release lifecycle hooks
- Get `git log` => Pass through `LogParse` hooks
- If necessary: Create a changelog and => Call `Changelog` hooks
- Run necessary remaining release lifecycle hooks
- Run release lifecycle hooks

## Plugin Ideas

Expand Down
99 changes: 69 additions & 30 deletions docs/pages/plugins/writing-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,113 @@ If you've ever written a `webpack` plugin it's a lot like that.

A plugin definition is:

- a class the has an `apply` function where a plugin hooks into various functions in auto (REQUIRED)
- a name for the plugin, should match the [name of the package](../plugins.md#plugin-declaration) (REQUIRED)
- a constructor where you can load plugin specific config
- a class the has an `apply` function where a plugin hooks into various functions in auto (REQUIRED)

```ts
import { Auto, IPlugin } from "auto";

export default class TestPlugin implements IPlugin {
name = "test";

private readonly config: any;

constructor(config: any) {
this.config = config;
}

apply(auto: Auto) {
// hook into auto
}
/** Tap into auto plugin points. */
apply(auto: Auto) {}
}
```

Or in JavaScript:

```js
module.exports = class TestPlugin {
constructor(config) {
this.config = config;
constructor() {
this.name = "test";
}

/**
* Setup the plugin
* Tap into auto plugin points.
* @param {import('@auto-it/core').default} auto
*/
apply(auto) {
// hook into auto
}
apply(auto) {}
};
```

## Constructor
## Hooks

In the constructor you have access to any plugin specific config provided in the `.autorc`.
It might be useful to write a more type-safe interface for your config.
Plugins work by hooking into various actions that `auto` has to do in order to facilitate a release or interact with your GitHub repo.

[Read more about using hooks](./hook-api-docs.md)

## Adding Options

Most plugins will find the need to some some options from the user.
The constructor of the plugin gets access to the options passed in the `.autorc`.

```ts
import { Auto, IPlugin } from "auto";
import { Auto, IPlugin } from "@auto-it/core";

interface ITestPluginConfig {
foo?: string;
bar?: boolean;
interface TestPluginOptions {
someOption?: boolean;
}

export default class TestPlugin implements IPlugin {
/** The name of the plugin */
name = "test";

private readonly config: ITestPluginConfig;
/** The options of the plugin */
readonly options: TestPluginOptions;

constructor(config: ITestPluginConfig) {
this.config = config;
/** Initialize the plugin with it's options */
constructor(options: TestPluginOptions) {
this.options = options;
}
}
```

## Hooks
### Validation

Plugins work by hooking into various actions that `auto` has to do in order to facilitate a release or interact with your GitHub repo.
To get validate of the options passed to plugins, `auto` uses [io-ts](https://github.com/gcanti/io-ts) and exports a utility function to validate the structured produced by `io-ts`.
It lets you defined your interfaces in JavaScript and easily convert them to TypeScript.
This means it's super simple to have type-safe code and runtime validation checking!

[Read more about using hooks](./hook-api-docs.md)
First install the following:

```sh
npm i --save io-ts fp-ts
# or
yarn add io-ts fp-ts
```

Then convert your options interface to the equivalent `io-ts` structure.

```ts
import * as t from "io-ts";

const pluginOptions = t.partial({
someOption: t.boolean,
});

export type TestPluginOptions = t.TypeOf<typeof pluginOptions>;
```

Then tap into the `validateConfig` hook and use the `validatePluginConfiguration` utility.

```ts
import { validatePluginConfiguration } from "@auto-it/core";

export default class MyPlugin implements IPlugin {
// ...
apply(auto: Auto) {
auto.hooks.validateConfig.tapPromise(this.name, async (name, options) => {
if (name === this.name || name === `auto-plugin-${this.name}`) {
return validatePluginConfiguration(this.name, pluginOptions, options);
}
});
}
}
```

And that's it!
Now `auto` will validate your plugins configuration before running.

## Example Plugin - NPM (simple)

Expand Down Expand Up @@ -138,3 +175,5 @@ export default class NPMPlugin {
}
}
```

[Read more about creating publishing plugins.](./writing-publishing-plugins.md)
83 changes: 3 additions & 80 deletions docs/pages/plugins/writing-publishing-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,83 +120,6 @@ Once you have the above hooks implemented you should be able to successfully use

The above plugins is pretty simple and there are a bunch of features you can add to your plugin through hooks or functions that `auto` exports.

## Adding Options

Most plugins will find the need to some some options from the user.
The constructor of the plugin gets access to the options passed in the `.autorc`.

```ts
import { Auto, IPlugin } from "@auto-it/core";

interface IGitTagPluginOptions {
someOption?: boolean;
}

export default class GitTagPlugin implements IPlugin {
/** The name of the plugin */
name = "my-git-tag";

/** The options of the plugin */
readonly options: IGitTagPluginOptions;

/** Initialize the plugin with it's options */
constructor(options: IGitTagPluginOptions) {
this.options = options;
}

/** Tap into auto plugin points. */
apply(auto: Auto) {
console.log(this.options.someOption);
}
}
```

### Validation

To get validate of the options passed to plugins, `auto` uses [io-ts](https://github.com/gcanti/io-ts) and exports a utility function to validate the structured produced by `io-ts`.
It lets you defined your interfaces in JavaScript and easily convert them to TypeScript.
This means it's super simple to have type-safe code and runtime validation checking!

First install the following:

```sh
npm i --save io-ts fp-ts
# or
yarn add io-ts fp-ts
```

Then convert your options interface to the equivalent `io-ts` structure.

```ts
import * as t from "io-ts";

const pluginOptions = t.partial({
someOption: t.boolean,
});

export type IGitTagPluginOptions = t.TypeOf<typeof pluginOptions>;
```

Then tap into the `validateConfig` hook and use the `validatePluginConfiguration` utility.

```ts
import { validatePluginConfiguration } from "@auto-it/core";

export default class GitTagPlugin implements IPlugin {
// ...
apply(auto: Auto) {
auto.hooks.validateConfig.tapPromise(this.name, async (name, options) => {
if (name === this.name || name === `@auto-it/${this.name}`) {
return validatePluginConfiguration(this.name, pluginOptions, options);
}
});
}
}
```

And that's it!
Now `auto` will validate your plugins configuration before running.

## Advanced Release Hooks

### `canary`
Expand Down Expand Up @@ -225,7 +148,7 @@ Like the `canary` hook your package management platform must support separate re

These hooks are not required for publishing plugins, but can really improve the developer experience of it.

### beforeRun
### `beforeRun`

Happens before anything is done.
This is a great place to check for platform specific secrets such as a npm token.
Expand All @@ -242,7 +165,7 @@ export default class GitTagPlugin implements IPlugin {
}
```

### getAuthor
### `getAuthor`

Get git author to commit with.
Typically from a package distribution description file.
Expand All @@ -257,7 +180,7 @@ auto.hooks.getAuthor.tapPromise("NPM", async () => {
});
```

### getRepository
### `getRepository`

Get owner and repository for the project to automate releases for.
Typically from a package distribution description file.
Expand Down

0 comments on commit 3a35a37

Please sign in to comment.