semantic-release plugin to analyze commits with conventional-changelog
npx @tessl/cli install tessl/npm-semantic-release--commit-analyzer@13.0.0A semantic-release plugin that analyzes commits with conventional-changelog to determine the type of release (major, minor, patch, or no release) that should be created. It parses commits according to conventional commit formats and matches them against configurable release rules to provide automated semantic versioning decisions.
npm install @semantic-release/commit-analyzer -Dimport { analyzeCommits } from "@semantic-release/commit-analyzer";For CommonJS (not supported - this is an ES module only):
// Not supported - ES module only
const { analyzeCommits } = require("@semantic-release/commit-analyzer");This plugin is designed to work within the semantic-release ecosystem. It's typically configured in the semantic-release configuration file:
{
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"releaseRules": [
{ "type": "docs", "scope": "README", "release": "patch" },
{ "type": "refactor", "release": "patch" },
{ "type": "style", "release": "patch" }
],
"parserOpts": {
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES"]
}
}
],
"@semantic-release/release-notes-generator"
]
}Analyzes commits using conventional-changelog to determine the appropriate release type.
/**
* Determine the type of release to create based on a list of commits.
*
* @param {Object} pluginConfig - The plugin configuration
* @param {String} pluginConfig.preset - conventional-changelog preset ('angular', 'atom', 'codemirror', 'ember', 'eslint', 'express', 'jquery', 'jscs', 'jshint', 'conventionalcommits')
* @param {String} pluginConfig.config - Requireable npm package with a custom conventional-changelog preset
* @param {String|Array} pluginConfig.releaseRules - A String to load an external module or an Array of rules
* @param {Object} pluginConfig.parserOpts - Additional conventional-changelog-parser options that will overwrite ones loaded by preset or config
* @param {Object} pluginConfig.presetConfig - Additional configuration passed to the conventional-changelog preset
* @param {Object} context - The semantic-release context
* @param {Array<Object>} context.commits - The commits to analyze
* @param {String} context.cwd - The current working directory
* @param {Object} context.logger - Logger instance
* @returns {Promise<String|null>} The type of release to create or null if no release
*/
async function analyzeCommits(pluginConfig, context);Usage Example:
import { analyzeCommits } from "@semantic-release/commit-analyzer";
const pluginConfig = {
preset: "angular",
releaseRules: [
{ type: "docs", scope: "README", release: "patch" },
{ type: "refactor", release: "patch" }
]
};
const context = {
commits: [
{
hash: "abc123",
message: "feat: add new feature",
author: { name: "John Doe", email: "john@example.com" }
},
{
hash: "def456",
message: "fix: resolve bug",
author: { name: "Jane Smith", email: "jane@example.com" }
}
],
cwd: process.cwd(),
logger: console
};
const releaseType = await analyzeCommits(pluginConfig, context);
// Returns: "minor" (due to "feat:" commit)interface PluginConfig {
/** conventional-changelog preset name */
preset?: "angular" | "atom" | "codemirror" | "ember" | "eslint" | "express" | "jquery" | "jscs" | "jshint" | "conventionalcommits";
/** npm package name of a custom conventional-changelog preset */
config?: string;
/** External module path or array of release rules */
releaseRules?: string | ReleaseRule[];
/** Additional conventional-commits-parser options */
parserOpts?: ParserOptions;
/** Additional configuration passed to the conventional-changelog preset */
presetConfig?: object;
}
interface ReleaseRule {
/** Commit type (e.g., "feat", "fix") */
type?: string;
/** Commit scope */
scope?: string;
/** Whether commit has breaking changes */
breaking?: boolean;
/** Whether commit is a revert */
revert?: boolean;
/** Emoji in commit (for Atom preset) */
emoji?: string;
/** Tag in commit (for Ember/ESLint presets) */
tag?: string;
/** Component in commit (for Express preset) */
component?: string;
/** Release type to trigger */
release: "major" | "premajor" | "minor" | "preminor" | "patch" | "prepatch" | "prerelease" | false | null;
}
interface ParserOptions {
/** Keywords that indicate breaking changes */
noteKeywords?: string[];
/** Additional parser configuration */
[key: string]: any;
}interface Context {
/** Array of commit objects to analyze */
commits: Commit[];
/** Current working directory */
cwd: string;
/** Logger instance */
logger: Logger;
}
interface Commit {
/** Commit hash */
hash: string;
/** Commit message */
message: string;
/** Commit author information */
author: {
name: string;
email: string;
};
/** Additional commit properties */
[key: string]: any;
}
interface Logger {
log(message: string, ...args: any[]): void;
}The plugin returns one of the following release types based on semantic versioning:
type ReleaseType =
| "major" // Breaking changes
| "premajor" // Pre-release major
| "minor" // New features
| "preminor" // Pre-release minor
| "patch" // Bug fixes
| "prepatch" // Pre-release patch
| "prerelease" // Pre-release
| null; // No release neededThe plugin includes built-in release rules for common commit conventions:
major releasepatch releasefeat: → minor releasefix: → patch releaseperf: → patch releaseBUGFIX, FEATURE, SECURITY)Breaking, Fix, Update, New)The plugin validates configuration and throws descriptive errors for:
releaseRules format (must be array)release property in rulesCommon errors:
// Invalid releaseRules configuration
throw new TypeError('Error in commit-analyzer configuration: "releaseRules" must be an array of rules');
// Missing release property
throw new Error('Error in commit-analyzer configuration: rules must be an object with a "release" property');
// Invalid release type
throw new Error('Error in commit-analyzer configuration: "invalid" is not a valid release type. Valid values are: ["major","premajor","minor","preminor","patch","prepatch","prerelease"]');{
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"releaseRules": [
{ "type": "docs", "scope": "README", "release": "patch" },
{ "type": "refactor", "scope": "core-*", "release": "minor" },
{ "type": "refactor", "release": "patch" },
{ "scope": "no-release", "release": false },
{ "breaking": true, "release": "major" }
]
}
]
]
}{
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"parserOpts": {
"noteKeywords": ["BREAKING CHANGE", "BREAKING CHANGES", "BREAKING"],
"headerPattern": "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
}
}
]
]
}For presets that require configuration, such as conventionalcommits, the presetConfig option must be set:
{
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "conventionalcommits",
"presetConfig": {
"types": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "docs", "section": "Documentation", "hidden": true }
]
}
}
]
]
}{
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"releaseRules": "./config/release-rules.js"
}
]
]
}Where ./config/release-rules.js exports:
export default [
{ type: "feat", release: "minor" },
{ type: "fix", release: "patch" },
{ type: "docs", release: "patch" },
{ scope: "no-release", release: false }
];