Skip to content

Commit

Permalink
add config and remote plugins support
Browse files Browse the repository at this point in the history
  • Loading branch information
sylc committed Jun 1, 2022
1 parent df018c5 commit 40702cd
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 62 deletions.
10 changes: 8 additions & 2 deletions .release-me.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@
"release": true
},
"regex": {
"patterns": ["/(?<=@)(.*)(?=\/)/gm", "(?<=release-me\/)(.*)(?=\/cli)"]
"patterns": [
"/(?<=@)(.*)(?=\/)/gm",
"(?<=release-me\/)(.*)(?=\/cli)"
]
},
"versionFile": {}
"versionFile": {},
"testRemote": {
"path": "./plugins/testRemote/mod.ts"
}
}
62 changes: 49 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,64 @@ example: release-me major

## Plugins

Release-me supports plugins. The current ones are
Release-me supports local and remote plugins. By default, plugins are **NOT**
enabled. To enable them, create a `.release-me.json` file that has a key
matching the plugin. Example of configuration.

```json
// .release-me.json
{
"changelog": {},
"github": {
"release": true
},
"regex": {
"patterns": [
"/(?<=@)(.*)(?=\/)/gm",
"(?<=release-me\/)(.*)(?=\/cli)"
]
},
"versionFile": {},
"myRemotePlugin": {
"path": "./plugins/testRemote/mod.ts"
}
}
```

### Baked-in plugins

- [github](./plugin/github/mod.ts): Create a draft release on Github
- [changelog](./plugin/changelog/mod.ts): Create a changelog
- github: Create a draft release on Github
- regex: Apply a regex on the Readme to update the version number following `@` to the new one
- versionFile: Create a `version.json` file with the new version number
- [regex](./plugin/regex/mod.ts): Apply a regex on the Readme the regex can be
configure in the config file. For to update the version number following `@`
to the new one
- [versionFile](./plugin/versionFile/mod.ts): Create a `version.json` file with
the new version number

They are currently all enabled, but this will change soon...
### Remote plugins

To develop new plugins, refer to [./plugins.ts](/plugins.ts) api
Plugins can also be defined externally. In that case they must have a "path"
property in their config. The path can be either a local path or http(s) path.

A plugin must contain a default export with the signature defined at
[./plugins.ts](/plugins.ts)

## Secrets

Release-me uses dotenv to load environment variables
Release-me uses dotenv to load environment variables. For example for
interactiong with Github, set a `.env` file with the below

### Contribution

Pull request, issues and feedback are very welcome. Code style is formatted with
deno fmt.
```
GITHUB_TOKEN=<my secret token>
```

## Credits

Big Credits to [denosaurs](https://github.com/denosaurs). This project is a fork
of [release](https://github.com/denosaurs/release). However due to the lack of
development on the original package, I have done some update.
of [release](https://github.com/denosaurs/release). The current core features
have been implemented by it.

### Contribution

Pull request, issues and feedback are very welcome. Code style is formatted with
deno fmt.
33 changes: 18 additions & 15 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { fetchRepo, Repo } from "./src/repo.ts";
import { ezgit } from "./src/git.ts";

// Plugins
import { github } from "./plugins/github/mod.ts";
import { changelog } from "./plugins/changelog/mod.ts";
import { regex } from "./plugins/regex/mod.ts";
import { versionFile } from "./plugins/versionFile/mod.ts";
import github from "./plugins/github/mod.ts";
import changelog from "./plugins/changelog/mod.ts";
import regex from "./plugins/regex/mod.ts";
import versionFile from "./plugins/versionFile/mod.ts";

import version from "./version.json" assert { type: "json" };
import { ReleasePlugin } from "./plugin.ts";
Expand Down Expand Up @@ -55,9 +55,9 @@ await new Command()
default: ".release-me.json",
})
.action(async (opts, release_type, name) => {
await initLogger(opts.debug)
await initLogger(opts.debug);
log.debug(opts, release_type, name);

let suffix: string | undefined = undefined;
if (["prepatch", "preminor", "premajor"].includes(release_type)) {
suffix = (name as string | undefined) ?? "canary";
Expand All @@ -66,7 +66,10 @@ await new Command()
// Load config, if any
let config: ReleaseConfig<unknown> = { options: opts };
try {
config = { ...(JSON.parse(Deno.readTextFileSync(opts.config))), ...config} ;
config = {
...(JSON.parse(Deno.readTextFileSync(opts.config))),
...config,
};
} catch (err) {
if (err.code !== "ENOENT") {
log.error(`error parsing the config file at ${opts.config}`);
Expand All @@ -84,14 +87,14 @@ await new Command()
else if (key === "regex") plugins.push(regex);
else if (key === "versionFile") plugins.push(versionFile);
else {
const def = val as { path: string; };
if (!def.path) throw Error(`Invalid config entry ${val}`)
const remotePlugin = await import(def.path)
plugins.push(remotePlugin);
const def = val as { path: string };
if (!def.path) throw Error(`Invalid config entry ${val}`);
const remotePlugin = await import(def.path);
plugins.push(remotePlugin.default);
}
}
log.debug(`plugins loaded: ${plugins.map(p => p.name).join(', ')}`)

log.debug(`plugins loaded: ${plugins.map((p) => p.name).join(", ")}`);

// Plugins setup
for (const plugin of plugins) {
Expand Down Expand Up @@ -140,7 +143,7 @@ await new Command()
for (const plugin of plugins) {
if (!plugin.preCommit) continue;
try {
log.debug(`Executing preCommit ${plugin.name}`)
log.debug(`Executing preCommit ${plugin.name}`);
await plugin.preCommit(repo, release_type, from, to, config, log);
} catch (err) {
log.critical(err.message);
Expand Down Expand Up @@ -190,7 +193,7 @@ await new Command()
for (const plugin of plugins) {
if (!plugin.postCommit) continue;
try {
log.debug(`Executing postCommit ${plugin.name}`)
log.debug(`Executing postCommit ${plugin.name}`);
await plugin.postCommit(repo, release_type, from, to, config, log);
} catch (err) {
log.critical(err.message);
Expand Down
5 changes: 3 additions & 2 deletions config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ interface CliConfig {
options: {
dry?: boolean;
allowUncommitted?: boolean;
}
debug?: boolean;
};
}

export type ReleaseConfig<T> = T & CliConfig
export type ReleaseConfig<T> = T & CliConfig;
5 changes: 4 additions & 1 deletion deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ export { parse as ccparse } from "https://deno.land/x/[email protected]/mod.ts";

export * as semver from "https://deno.land/x/[email protected]/mod.ts";
export * as ini from "https://deno.land/x/[email protected]/mod.ts";
export { Command, EnumType } from "https://deno.land/x/[email protected]/command/mod.ts";
export {
Command,
EnumType,
} from "https://deno.land/x/[email protected]/command/mod.ts";
17 changes: 14 additions & 3 deletions plugin.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { log } from './deps.ts'
import { log } from "./deps.ts";
import type { ReleaseConfig } from "./config.ts";
import type { ReleaseType } from "./cli.ts";
import type { Repo } from "./src/repo.ts";
Expand All @@ -11,21 +11,32 @@ export type { Commit } from "./src/commits.ts";

export interface ReleasePlugin<T = unknown> {
name: string;
/**
* This run at the start of the cli
*/
setup?: (logs: typeof log) => Promise<void>;

/**
* This run before a commit is done
*/
preCommit?: (
repo: Repo,
releaseType: ReleaseType,
from: string,
to: string,
config: ReleaseConfig<T>,
logger: typeof log
logger: typeof log,
) => Promise<void>;

/**
* This run after a commit with all the changes is done
*/
postCommit?: (
repo: Repo,
releaseType: ReleaseType,
from: string,
to: string,
config: ReleaseConfig<T>,
logger: typeof log
logger: typeof log,
) => Promise<void>;
}
10 changes: 5 additions & 5 deletions plugins/changelog/mod.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { join } from "./deps.ts";

import type {
ReleasePlugin,
} from "../../plugin.ts";
import type { ReleasePlugin } from "../../plugin.ts";
import {
Document,
Filter,
Expand All @@ -12,15 +10,15 @@ import {
render,
} from "../../src/changelog.ts";

export const changelog = <ReleasePlugin> {
const plugin: ReleasePlugin = {
name: "Changelog",
async preCommit(
repo,
_releaseType,
_from,
to,
config,
log
log,
): Promise<void> {
const doc: Document = { sections: [], links: [] };
pushHeader(doc);
Expand Down Expand Up @@ -52,3 +50,5 @@ export const changelog = <ReleasePlugin> {
}
},
};

export default plugin;
8 changes: 4 additions & 4 deletions plugins/github/mod.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import {
ReleasePlugin,
} from "../../plugin.ts";
import { ReleasePlugin } from "../../plugin.ts";
import {
Document,
Filter,
Expand All @@ -14,7 +12,7 @@ import { ReleaseError } from "../../src/error.ts";

const GITHUB_TOKEN = "GITHUB_TOKEN";

export const github = <ReleasePlugin> {
const plugin: ReleasePlugin = {
name: "GitHub",
async setup(log): Promise<void> {
const token = Deno.env.get(GITHUB_TOKEN);
Expand Down Expand Up @@ -73,3 +71,5 @@ export const github = <ReleasePlugin> {
}
},
};

export default plugin;
16 changes: 8 additions & 8 deletions plugins/regex/mod.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import type {
ReleasePlugin,
} from "../../plugin.ts";
import type { ReleasePlugin } from "../../plugin.ts";
import { join } from "./deps.ts";

interface RegexConfig {
regex: {
patterns: string[]
}
patterns: string[];
};
}

export const regex: ReleasePlugin<RegexConfig> = {
const plugin: ReleasePlugin<RegexConfig> = {
name: "Regex",
async preCommit(
repo,
_releaseType,
_from,
to,
config,
log
log,
): Promise<void> {
const readmePath = "README.md";
let text = await Deno.readTextFile(readmePath);
// apply regex. This should come from a config loaded on setup step
// as a prototype, it is harcoded to update versions in urls
// as a prototype, it is harcoded to update versions in urls
for (const pattern of config.regex.patterns) {
text = text.replace(new RegExp(pattern), to);
}
Expand All @@ -33,3 +31,5 @@ export const regex: ReleasePlugin<RegexConfig> = {
}
},
};

export default plugin;
2 changes: 2 additions & 0 deletions plugins/testRemote/deps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { join } from "https://deno.land/[email protected]/path/mod.ts";
export { EOL } from "https://deno.land/[email protected]/fs/mod.ts";
34 changes: 34 additions & 0 deletions plugins/testRemote/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { ReleasePlugin } from "../../plugin.ts";
import { join } from "./deps.ts";

/**
* Export a version file with the new version number
*/
const plugin: ReleasePlugin = {
name: "TestRemote",
async preCommit(
repo,
_releaseType,
_from,
to,
config,
log,
): Promise<void> {
const versionFile = "versionTest.json";
const version = {
version: to,
};
if (!config.options.dry) {
await Deno.writeTextFile(
join(repo.path, versionFile),
JSON.stringify(version, null, 2) +
// to comply with deno fmt
"\n",
);
} else {
log.info(`dryRun: Would have created ${versionFile} file`);
}
},
};

export default plugin;
Loading

0 comments on commit 40702cd

Please sign in to comment.