Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clean up writing plugin docs #1220

Merged
merged 1 commit into from
May 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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