Skip to content

stellarwp/changelogger

Repository files navigation

@stellarwp/changelogger

A TypeScript-based changelog management tool that works both as a GitHub Action and CLI tool. This is inspired by the Jetpack Changelogger but implemented in TypeScript and designed to work seamlessly with GitHub Actions.

Features

  • Manage changelog entries through individual change files
  • Interactive CLI for adding changelog entries
  • GitHub Action support for CI/CD integration
  • Configurable through package.json
  • Supports semantic versioning
  • Validates change files format and content
  • Automatically generates well-formatted changelog entries
  • Multiple writing strategies (Keep a Changelog, StellarWP formats)
  • Multiple versioning strategies (SemVer, StellarWP)

Installation

npm install @stellarwp/changelogger

Usage

As a CLI Tool

# Add a new changelog entry
npm run changelog add

# Validate all change files
npm run changelog validate

# Write changes to CHANGELOG.md
npm run changelog write

CLI Commands Reference

add Command

Adds a new changelog entry to the project. Can be used in interactive or non-interactive mode.

# Interactive mode - prompts for all required information
npm run changelog add

# Non-interactive mode - provide all options directly
npm run changelog add -- --significance minor --type feature --entry "Added new feature X"

# Non-interactive mode with auto-generated filename
npm run changelog add -- --significance minor --type feature --entry "Added new feature X" --auto-filename

Options:

  • --significance: The significance of the change (patch, minor, major)
  • --type: The type of change (e.g., feature, fix, enhancement)
  • --entry: The changelog entry text
  • --filename: The desired filename for the changelog entry (optional)
  • --auto-filename: Automatically generate the filename based on branch name or timestamp (optional)

The command will:

  • Create a new YAML file in the configured changes directory
  • Generate a filename based on the branch name or timestamp
  • Handle duplicate filenames by appending a timestamp
  • Validate all inputs before creating the file

When using --auto-filename:

  • The filename will be automatically generated from the current git branch name (if available)
  • If no branch name is available, a timestamp-based filename will be used
  • The filename prompt will be skipped

validate Command

Validates all changelog entries in the changes directory.

npm run changelog validate

This command performs the following checks:

  • Validates YAML format of all change files
  • Ensures required fields are present
  • Verifies significance values (patch, minor, or major)
  • Validates type values against configuration
  • Ensures non-patch changes have an entry description

write Command

Writes changelog entries to the configured files.

# Automatic versioning
npm run changelog write

# Manual versioning
npm run changelog write -- --overwrite-version 1.2.3

# Dry run - show what would be written without making changes
npm run changelog write -- --dry-run

# Specify a custom date (supports PHP strtotime format)
npm run changelog write -- --date "2024-03-20"
npm run changelog write -- --date "yesterday"
npm run changelog write -- --date "last monday"

Options:

  • --overwrite-version: Optional version number to use instead of auto-determining
  • --dry-run: If true, only show what would be written without making changes
  • --date: Custom date to use for the changelog entry (supports PHP strtotime format)

The command will:

  • Read all YAML change files from the changes directory
  • Determine the next version number based on change significance (if not specified)
  • Write the changes to each configured file using its specific writing strategy
  • Clean up processed change files

When using --dry-run:

  • Shows what would be written to each configured file
  • Displays the formatted changelog entries
  • No changes are actually made to any files

When using --overwrite-version:

  • Uses the specified version instead of auto-determining
  • If the version exists in the changelog, new changes are appended to that version
  • If the version doesn't exist, a new version entry is created

When using --date:

  • Uses the specified date for the changelog entry
  • Supports PHP strtotime format for flexible date specification
  • Examples:
    • --date "2024-03-20" - Specific date
    • --date "yesterday" - Relative date
    • --date "last monday" - Relative date
    • --date "next friday" - Relative date
  • If not specified, uses the current date

The command supports multiple output files with different writing strategies:

  • Keep a Changelog format
  • StellarWP changelog format
  • StellarWP readme format
  • Custom writing strategies

Each file is processed according to its configured strategy and the changes are written in the appropriate format.

As a Module

import {
  addCommand,
  validateCommand,
  writeCommand,
  writingStrategies,
  versioningStrategies,
  loadConfig,
  loadWritingStrategy,
  loadVersioningStrategy,
  WritingStrategy,
  VersioningStrategy,
} from "@stellarwp/changelogger";

// Use built-in writing strategies
const keepachangelog = writingStrategies.keepachangelog;
const stellarwpChangelog = writingStrategies.stellarwpChangelog;
const stellarwpReadme = writingStrategies.stellarwpReadme;

// Use built-in versioning strategies
const semver = versioningStrategies.semverStrategy;
const stellarwp = versioningStrategies.stellarStrategy;

// Load custom strategies
const customWritingStrategy = await loadWritingStrategy("./path/to/custom-writing.ts");
const customVersioningStrategy = await loadVersioningStrategy("./path/to/custom-versioning.ts");

As a GitHub Action

name: Verify changelog Entry.

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: stellarwp/changelogger@main
        with:
          command: validate

Configuration

Configure the changelogger through your package.json:

{
  "changelogger": {
    "changelogFile": "CHANGELOG.md",
    "changesDir": "changelog",
    "linkTemplate": "https://github.com/owner/repo/compare/${old}...${new}",
    "ordering": ["type", "content"],
    "types": {
      "added": "Added",
      "changed": "Changed",
      "deprecated": "Deprecated",
      "removed": "Removed",
      "fixed": "Fixed",
      "security": "Security"
    },
    "versioning": "semver",
    "files": [
      {
        "path": "CHANGELOG.md",
        "strategy": "keepachangelog"
      },
      {
        "path": "readme.txt",
        "strategy": "stellarwp-readme"
      }
    ]
  }
}

Versioning Strategies

The changelogger supports multiple versioning strategies:

  1. semver (default): Standard semantic versioning (major.minor.patch)

    {
      "changelogger": {
        "versioning": "semver"
      }
    }
  2. stellarwp: StellarWP versioning with hotfix support (major.minor.patch[.hotfix])

    • Supports 3-part versions: 1.2.3
    • Supports 4-part versions with hotfix: 1.2.3.4
    • Hotfix number only appears when greater than 0
    • Version handling:
      • major: Increments major, resets others (1.2.3.4 → 2.0.0)
      • minor: Increments minor, resets patch/hotfix (1.2.3.4 → 1.3.0)
      • patch:
        • With hotfix: Increments hotfix (1.2.3.4 → 1.2.3.5)
        • Without hotfix: Increments patch (1.2.3 → 1.2.4)
    {
      "changelogger": {
        "versioning": "stellarwp"
      }
    }
  3. Custom Versioning: You can provide a path to a JavaScript file that implements the versioning strategy:

    {
      "changelogger": {
        "versioning": "./path/to/custom-versioning.js"
      }
    }

    The custom versioning file must export these functions:

    export function getNextVersion(currentVersion: string, significance: "major" | "minor" | "patch"): string;
    export function isValidVersion(version: string): boolean;
    export function compareVersions(v1: string, v2: string): number;

Writing Strategies

The changelogger supports multiple writing strategies that can be configured per file in your package.json:

{
  "changelogger": {
    "files": [
      {
        "path": "CHANGELOG.md",
        "strategy": "keepachangelog"
      },
      {
        "path": "readme.txt",
        "strategy": "stellarwp-readme"
      }
    ]
  }
}

Available built-in strategies:

  1. keepachangelog: Follows the Keep a Changelog format

    Example output:

    ## [1.2.3] - 2024-03-22
    
    ### Added
    
    - New feature description
    
    ### Fixed
    
    - Bug fix description
    
    [1.2.3]: https://github.com/owner/repo/compare/1.2.2...1.2.3
  2. stellarwp-changelog: A WordPress-style changelog format

    Example output:

    ### [1.2.3] 2024-03-22
    
    - Feature - Added new feature
    - Fix - Fixed a bug
  3. stellarwp-readme: Updates readme.txt in WordPress plugin format

    Example output:

    == Changelog ==
    
    = [1.2.3] 2024-03-22 =
    
    * Feature - Added new feature
    * Fix - Fixed a bug
    
  4. Custom Writing: You can provide a path to a JavaScript file that implements the writing strategy:

    {
      "changelogger": {
        "files": [
          {
            "path": "CHANGELOG.md",
            "strategy": "./path/to/custom-writing.js"
          }
        ]
      }
    }

    The custom writing file must implement the WritingStrategy interface:

    interface WritingStrategy {
      /**
       * Format the changes into a changelog entry
       */
      formatChanges(version: string, changes: Array<{ type: string; entry: string }>, previousVersion?: string): string;
    
      /**
       * Format the header for a new version
       */
      formatVersionHeader(version: string, date: string, previousVersion?: string): string;
    
      /**
       * Optional: Format version comparison links
       */
      formatVersionLink?(version: string, previousVersion: string, template?: string): string;
    }

    Example custom writing strategy:

    // custom-writing.ts
    import * as fs from "fs/promises";
    import * as path from "path";
    import { WritingStrategy } from "@stellarwp/changelogger";
    
    const customStrategy: WritingStrategy = {
      formatChanges(version, changes) {
        return changes.map(change => `- [${change.type.toUpperCase()}] ${change.entry}`).join("\n");
      },
    
      formatVersionHeader(version, date) {
        return `# Version ${version} (${date})`;
      },
    
      formatVersionLink(version, previousVersion, template) {
        if (!template) return "";
        return `Compare: ${template.replace("${old}", previousVersion).replace("${new}", version)}`;
      },
    };
    
    export default customStrategy;

    Example output:

    # Version 1.2.3 (2024-03-22)
    
    - [ADDED] New feature description
    - [FIXED] Bug fix description
      Compare: https://github.com/owner/repo/compare/1.2.2...1.2.3

Change File Handling

When adding new changelog entries:

  1. Default Filename: By default, uses the current git branch name (cleaned up) or a timestamp if no branch name is available.

  2. File Naming Rules:

    • Converts to lowercase
    • Replaces non-alphanumeric characters with hyphens
    • Removes leading/trailing hyphens
    • Collapses multiple hyphens into one Example: Feature/Add-NEW_thing!!!feature-add-new-thing.yaml
  3. Duplicate Handling: If a file with the same name exists:

    • Adds a timestamp to the filename
    • Example: If feature.yaml exists, creates feature-1234567890.yaml
  4. Interactive Prompts:

    • Significance: patch, minor, or major
    • Type: added, changed, deprecated, removed, fixed, or security
    • Entry: Description of the change
    • Filename: Optional custom filename
  5. Directory Structure:

    • Creates the changes directory if it doesn't exist
    • Stores all change files in the configured directory (default: changelog/)

Change File Format

Change files are YAML files containing:

significance: patch|minor|major
type: added|changed|deprecated|removed|fixed|security
entry: Description of the change

License

MIT

About

No description, website, or topics provided.

Resources

Code of conduct

Stars

Watchers

Forks

Packages

No packages published