Generic CLI tool to automate versioning and package publishing-related tasks.
—
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.
Foundation class for all Release It! plugins with lifecycle hooks and utilities.
/**
* Base plugin class providing lifecycle hooks and utilities
* All Release It! plugins extend this class
*/
class Plugin {
/**
* Create plugin instance
* @param options - Plugin configuration options
*/
constructor(options: PluginOptions);
/**
* Check if plugin should be enabled
* @param options - Plugin configuration options
* @returns Boolean indicating if plugin is enabled
*/
static isEnabled(options: any): boolean | Promise<boolean>;
/**
* Disable plugin and return null
* @returns null to indicate plugin is disabled
*/
static disablePlugin(): null;
/** Initialize plugin - called once during startup */
init(): void | Promise<void>;
/** Get package/project name */
getName(): string | Promise<string>;
/** Get current/latest version */
getLatestVersion(): string | Promise<string>;
/** Get changelog content for the release */
getChangelog(latestVersion?: string): string | Promise<string>;
/**
* Get version increment suggestion
* @param incrementBase - Base increment information
* @returns Suggested increment (major/minor/patch/etc)
*/
getIncrement(incrementBase: IncrementBase): string | Promise<string>;
/**
* Get incremented version for CI mode
* @param incrementBase - Base increment information
* @returns New version string
*/
getIncrementedVersionCI(incrementBase: IncrementBase): string | Promise<string>;
/**
* Get incremented version with user interaction
* @param incrementBase - Base increment information
* @returns New version string
*/
getIncrementedVersion(incrementBase: IncrementBase): string | Promise<string>;
/** Hook called before version bump */
beforeBump(): void | Promise<void>;
/**
* Hook called to perform version bump
* @param version - New version to bump to
* @returns True if bump was performed, false to skip
*/
bump(version: string): boolean | Promise<boolean>;
/** Hook called before release operations */
beforeRelease(): void | Promise<void>;
/**
* Hook called to perform release operations
* @returns True if release was performed, false to skip
*/
release(): boolean | Promise<boolean>;
/** Hook called after release operations */
afterRelease(): void | Promise<void>;
/**
* Get plugin context with optional path
* @param path - Optional dot-notation path to nested value
* @returns Context value or entire context
*/
getContext(path?: string): any;
/**
* Set plugin context by merging with existing
* @param context - Context to merge
*/
setContext(context: any): void;
/**
* Execute shell command with context interpolation
* @param command - Command to execute
* @param options - Execution options
* @returns Promise resolving to command output
*/
exec(command: string, options?: ExecOptions): Promise<string>;
/**
* Register interactive prompts for this plugin
* @param prompts - Prompt definitions
*/
registerPrompts(prompts: any): void;
/**
* Show interactive prompt
* @param options - Prompt options
* @returns Promise resolving to user input
*/
showPrompt(options: PromptOptions): Promise<any>;
/**
* Execute step with spinner or prompt based on mode
* @param options - Step execution options
* @returns Promise resolving to step result
*/
step(options: StepOptions): Promise<any>;
/**
* Get initial plugin options from configuration
* @param options - Full configuration options
* @param namespace - Plugin namespace
* @returns Plugin-specific options
*/
getInitialOptions(options: any, namespace: string): any;
}
interface PluginOptions {
/** Plugin namespace for configuration */
namespace: string;
/** Plugin-specific options */
options?: any;
/** Dependency injection container */
container?: DependencyContainer;
}
interface IncrementBase {
/** Current latest version */
latestVersion: string;
/** Requested increment type */
increment: string;
/** Whether this is a pre-release */
isPreRelease: boolean;
/** Pre-release identifier */
preReleaseId?: string;
/** Pre-release base version */
preReleaseBase?: string;
}
interface ExecOptions {
/** Additional execution options */
options?: any;
/** Context for template interpolation */
context?: any;
}
interface StepOptions {
/** Whether step is enabled */
enabled?: boolean;
/** Task function to execute */
task?: () => Promise<any>;
/** Step label for display */
label?: string;
/** Prompt type for interactive mode */
prompt?: string;
/** Context for template interpolation */
context?: any;
/** Whether this is an external command */
external?: boolean;
}
interface PromptOptions {
/** Prompt type */
type?: string;
/** Prompt name/key */
name?: string;
/** Prompt message */
message?: string;
/** Available choices for select prompts */
choices?: any[];
/** Default value */
default?: any;
/** Plugin namespace */
namespace?: string;
/** Value transformer function */
transformer?: (value: any) => any;
}
interface DependencyContainer {
/** Configuration instance */
config?: any;
/** Logger instance */
log?: any;
/** Shell executor instance */
shell?: any;
/** Spinner instance */
spinner?: any;
/** Prompt handler instance */
prompt?: any;
}Factory function for loading and instantiating plugins.
/**
* Get plugin instances for the current configuration
* @param config - Configuration instance
* @param container - Dependency injection container
* @returns Tuple of [internal plugins, external plugins]
*/
function getPlugins(
config: Config,
container: DependencyContainer
): Promise<[Plugin[], Plugin[]]>;Release It! includes several built-in plugins:
Manages version updates in files (package.json, etc.)
Handles Git operations (commit, tag, push)
Manages npm publishing and registry operations
Creates GitHub releases and uploads assets
Creates GitLab releases
/**
* Example custom plugin implementation
* Custom plugins extend the base Plugin class
*/
class CustomPlugin extends Plugin {
constructor(options) {
super(options);
this.namespace = 'custom';
}
static isEnabled(options) {
return options !== false;
}
async init() {
// Plugin initialization logic
this.log.info('Custom plugin initialized');
}
async beforeRelease() {
// Custom pre-release logic
await this.exec('custom-pre-release-command');
}
async release() {
// Custom release logic
const result = await this.step({
enabled: this.options.deploy,
task: () => this.deploy(),
label: 'Custom deployment',
prompt: 'deploy'
});
return result;
}
async deploy() {
// Custom deployment logic
const version = this.config.getContext('version');
await this.exec(`deploy --version ${version}`);
}
}
export default CustomPlugin;Usage Examples:
// Using built-in plugins through configuration
const result = await runTasks({
git: {
commit: true,
tag: true,
push: true
},
npm: {
publish: true
},
github: {
release: true,
assets: ['dist/*.zip']
}
});
// Loading custom plugins
const result = await runTasks({
plugins: {
'./custom-plugin.js': {
deploy: true,
environment: 'production'
}
}
});Each plugin accepts configuration through the main configuration object:
{
"git": {
"commit": true,
"commitMessage": "Release ${version}",
"tag": true,
"push": true
},
"npm": {
"publish": true,
"tag": "latest"
},
"github": {
"release": true,
"releaseName": "Release ${version}",
"assets": ["dist/*.zip", "docs/*.pdf"]
},
"plugins": {
"@release-it/conventional-changelog": {
"preset": "angular"
},
"./plugins/custom-notifier.js": {
"webhook": "https://hooks.slack.com/..."
}
}
}The plugin lifecycle ensures coordinated execution:
init() on all pluginsbeforeBump() hooksbump(version) hooksbeforeRelease() hooksrelease() hooksafterRelease() hooksPlugins communicate through shared context:
// Plugin A sets context
this.setContext({ buildId: '12345' });
// Plugin B reads context
const buildId = this.getContext('buildId');
// Global context access
const version = this.config.getContext('version');Install with Tessl CLI
npx tessl i tessl/npm-release-it