0
# Plugin System
1
2
Release It!'s plugin system provides an extensible architecture for implementing release functionality. Plugins participate in a well-defined lifecycle and can communicate through shared context.
3
4
## Capabilities
5
6
### Base Plugin Class
7
8
Foundation class for all Release It! plugins with lifecycle hooks and utilities.
9
10
```javascript { .api }
11
/**
12
* Base plugin class providing lifecycle hooks and utilities
13
* All Release It! plugins extend this class
14
*/
15
class Plugin {
16
/**
17
* Create plugin instance
18
* @param options - Plugin configuration options
19
*/
20
constructor(options: PluginOptions);
21
22
/**
23
* Check if plugin should be enabled
24
* @param options - Plugin configuration options
25
* @returns Boolean indicating if plugin is enabled
26
*/
27
static isEnabled(options: any): boolean | Promise<boolean>;
28
29
/**
30
* Disable plugin and return null
31
* @returns null to indicate plugin is disabled
32
*/
33
static disablePlugin(): null;
34
35
/** Initialize plugin - called once during startup */
36
init(): void | Promise<void>;
37
38
/** Get package/project name */
39
getName(): string | Promise<string>;
40
41
/** Get current/latest version */
42
getLatestVersion(): string | Promise<string>;
43
44
/** Get changelog content for the release */
45
getChangelog(latestVersion?: string): string | Promise<string>;
46
47
/**
48
* Get version increment suggestion
49
* @param incrementBase - Base increment information
50
* @returns Suggested increment (major/minor/patch/etc)
51
*/
52
getIncrement(incrementBase: IncrementBase): string | Promise<string>;
53
54
/**
55
* Get incremented version for CI mode
56
* @param incrementBase - Base increment information
57
* @returns New version string
58
*/
59
getIncrementedVersionCI(incrementBase: IncrementBase): string | Promise<string>;
60
61
/**
62
* Get incremented version with user interaction
63
* @param incrementBase - Base increment information
64
* @returns New version string
65
*/
66
getIncrementedVersion(incrementBase: IncrementBase): string | Promise<string>;
67
68
/** Hook called before version bump */
69
beforeBump(): void | Promise<void>;
70
71
/**
72
* Hook called to perform version bump
73
* @param version - New version to bump to
74
* @returns True if bump was performed, false to skip
75
*/
76
bump(version: string): boolean | Promise<boolean>;
77
78
/** Hook called before release operations */
79
beforeRelease(): void | Promise<void>;
80
81
/**
82
* Hook called to perform release operations
83
* @returns True if release was performed, false to skip
84
*/
85
release(): boolean | Promise<boolean>;
86
87
/** Hook called after release operations */
88
afterRelease(): void | Promise<void>;
89
90
/**
91
* Get plugin context with optional path
92
* @param path - Optional dot-notation path to nested value
93
* @returns Context value or entire context
94
*/
95
getContext(path?: string): any;
96
97
/**
98
* Set plugin context by merging with existing
99
* @param context - Context to merge
100
*/
101
setContext(context: any): void;
102
103
/**
104
* Execute shell command with context interpolation
105
* @param command - Command to execute
106
* @param options - Execution options
107
* @returns Promise resolving to command output
108
*/
109
exec(command: string, options?: ExecOptions): Promise<string>;
110
111
/**
112
* Register interactive prompts for this plugin
113
* @param prompts - Prompt definitions
114
*/
115
registerPrompts(prompts: any): void;
116
117
/**
118
* Show interactive prompt
119
* @param options - Prompt options
120
* @returns Promise resolving to user input
121
*/
122
showPrompt(options: PromptOptions): Promise<any>;
123
124
/**
125
* Execute step with spinner or prompt based on mode
126
* @param options - Step execution options
127
* @returns Promise resolving to step result
128
*/
129
step(options: StepOptions): Promise<any>;
130
131
/**
132
* Get initial plugin options from configuration
133
* @param options - Full configuration options
134
* @param namespace - Plugin namespace
135
* @returns Plugin-specific options
136
*/
137
getInitialOptions(options: any, namespace: string): any;
138
}
139
140
interface PluginOptions {
141
/** Plugin namespace for configuration */
142
namespace: string;
143
/** Plugin-specific options */
144
options?: any;
145
/** Dependency injection container */
146
container?: DependencyContainer;
147
}
148
149
interface IncrementBase {
150
/** Current latest version */
151
latestVersion: string;
152
/** Requested increment type */
153
increment: string;
154
/** Whether this is a pre-release */
155
isPreRelease: boolean;
156
/** Pre-release identifier */
157
preReleaseId?: string;
158
/** Pre-release base version */
159
preReleaseBase?: string;
160
}
161
162
interface ExecOptions {
163
/** Additional execution options */
164
options?: any;
165
/** Context for template interpolation */
166
context?: any;
167
}
168
169
interface StepOptions {
170
/** Whether step is enabled */
171
enabled?: boolean;
172
/** Task function to execute */
173
task?: () => Promise<any>;
174
/** Step label for display */
175
label?: string;
176
/** Prompt type for interactive mode */
177
prompt?: string;
178
/** Context for template interpolation */
179
context?: any;
180
/** Whether this is an external command */
181
external?: boolean;
182
}
183
184
interface PromptOptions {
185
/** Prompt type */
186
type?: string;
187
/** Prompt name/key */
188
name?: string;
189
/** Prompt message */
190
message?: string;
191
/** Available choices for select prompts */
192
choices?: any[];
193
/** Default value */
194
default?: any;
195
/** Plugin namespace */
196
namespace?: string;
197
/** Value transformer function */
198
transformer?: (value: any) => any;
199
}
200
201
interface DependencyContainer {
202
/** Configuration instance */
203
config?: any;
204
/** Logger instance */
205
log?: any;
206
/** Shell executor instance */
207
shell?: any;
208
/** Spinner instance */
209
spinner?: any;
210
/** Prompt handler instance */
211
prompt?: any;
212
}
213
```
214
215
### Plugin Factory
216
217
Factory function for loading and instantiating plugins.
218
219
```javascript { .api }
220
/**
221
* Get plugin instances for the current configuration
222
* @param config - Configuration instance
223
* @param container - Dependency injection container
224
* @returns Tuple of [internal plugins, external plugins]
225
*/
226
function getPlugins(
227
config: Config,
228
container: DependencyContainer
229
): Promise<[Plugin[], Plugin[]]>;
230
```
231
232
### Built-in Plugins
233
234
Release It! includes several built-in plugins:
235
236
#### Version Plugin
237
Manages version updates in files (package.json, etc.)
238
239
#### Git Plugin
240
Handles Git operations (commit, tag, push)
241
242
#### npm Plugin
243
Manages npm publishing and registry operations
244
245
#### GitHub Plugin
246
Creates GitHub releases and uploads assets
247
248
#### GitLab Plugin
249
Creates GitLab releases
250
251
### Custom Plugin Development
252
253
```javascript { .api }
254
/**
255
* Example custom plugin implementation
256
* Custom plugins extend the base Plugin class
257
*/
258
class CustomPlugin extends Plugin {
259
constructor(options) {
260
super(options);
261
this.namespace = 'custom';
262
}
263
264
static isEnabled(options) {
265
return options !== false;
266
}
267
268
async init() {
269
// Plugin initialization logic
270
this.log.info('Custom plugin initialized');
271
}
272
273
async beforeRelease() {
274
// Custom pre-release logic
275
await this.exec('custom-pre-release-command');
276
}
277
278
async release() {
279
// Custom release logic
280
const result = await this.step({
281
enabled: this.options.deploy,
282
task: () => this.deploy(),
283
label: 'Custom deployment',
284
prompt: 'deploy'
285
});
286
287
return result;
288
}
289
290
async deploy() {
291
// Custom deployment logic
292
const version = this.config.getContext('version');
293
await this.exec(`deploy --version ${version}`);
294
}
295
}
296
297
export default CustomPlugin;
298
```
299
300
**Usage Examples:**
301
302
```javascript
303
// Using built-in plugins through configuration
304
const result = await runTasks({
305
git: {
306
commit: true,
307
tag: true,
308
push: true
309
},
310
npm: {
311
publish: true
312
},
313
github: {
314
release: true,
315
assets: ['dist/*.zip']
316
}
317
});
318
319
// Loading custom plugins
320
const result = await runTasks({
321
plugins: {
322
'./custom-plugin.js': {
323
deploy: true,
324
environment: 'production'
325
}
326
}
327
});
328
```
329
330
### Plugin Configuration
331
332
Each plugin accepts configuration through the main configuration object:
333
334
```json
335
{
336
"git": {
337
"commit": true,
338
"commitMessage": "Release ${version}",
339
"tag": true,
340
"push": true
341
},
342
"npm": {
343
"publish": true,
344
"tag": "latest"
345
},
346
"github": {
347
"release": true,
348
"releaseName": "Release ${version}",
349
"assets": ["dist/*.zip", "docs/*.pdf"]
350
},
351
"plugins": {
352
"@release-it/conventional-changelog": {
353
"preset": "angular"
354
},
355
"./plugins/custom-notifier.js": {
356
"webhook": "https://hooks.slack.com/..."
357
}
358
}
359
}
360
```
361
362
### Plugin Lifecycle
363
364
The plugin lifecycle ensures coordinated execution:
365
366
1. **Plugin Discovery**: Load internal and external plugins
367
2. **Initialization**: Call `init()` on all plugins
368
3. **Version Resolution**: Get current version and determine increment
369
4. **Pre-Bump Phase**: Call `beforeBump()` hooks
370
5. **Bump Phase**: Call `bump(version)` hooks
371
6. **Pre-Release Phase**: Call `beforeRelease()` hooks
372
7. **Release Phase**: Call `release()` hooks
373
8. **Post-Release Phase**: Call `afterRelease()` hooks
374
375
### Context Sharing
376
377
Plugins communicate through shared context:
378
379
```javascript
380
// Plugin A sets context
381
this.setContext({ buildId: '12345' });
382
383
// Plugin B reads context
384
const buildId = this.getContext('buildId');
385
386
// Global context access
387
const version = this.config.getContext('version');
388
```