A Zig library and CLI tool for generating beautiful changelogs from conventional commits.
- π Automatic changelog generation from conventional commits
- π¨ Beautiful formatting with emojis and proper grouping
- π Conventional commits parsing and analysis
- π Git repository integration with commit and compare URLs
- β‘ Fast and lightweight - written in Zig
- π¦ Both library and CLI - use programmatically or from command line
- π§ Highly configurable with sensible defaults
git clone https://github.com/yourusername/zig-changelog.git
cd zig-changelog
zig buildThe binary will be available at zig-out/bin/changelog.
# Add to your shell profile (.bashrc, .zshrc, etc.)
export PATH="$PATH:/path/to/zig-changelog/zig-out/bin"Generate a changelog and display in console:
changelogGenerate a changelog and save to CHANGELOG.md:
changelog -o CHANGELOG.mdGenerate changelog from specific commit range:
changelog --from v1.0.0 --to HEAD -o CHANGELOG.mdAdd to your build.zig.zon:
.dependencies = .{
.changelog = .{
.url = "https://github.com/yourusername/zig-changelog/archive/main.tar.gz",
.hash = "...",
},
},Use in your code:
const std = @import("std");
const changelog = @import("changelog");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const config = changelog.Config{
.from_ref = "v1.0.0",
.to_ref = "HEAD",
.verbose = true,
};
var result = try changelog.generateChangelog(allocator, ".", &config);
defer result.deinit(allocator);
std.debug.print("{s}\n", .{result.content});
}Options:
-h, --help Show help message
-v, --version Show version information
--verbose Enable verbose logging
--from <ref> Start commit reference (default: latest git tag)
--to <ref> End commit reference (default: HEAD)
--dir <dir> Path to git repository (default: current directory)
-o, --output <file> Output file (default: stdout)
--hide-author-email Hide author email addresses
--no-dates Don't include dates in changelog
# Generate and display changelog
changelog
# Write to file
changelog -o CHANGELOG.md
# Generate from specific tag
changelog --from v1.0.0 -o CHANGELOG.md
# Generate with verbose output
changelog --verbose -o CHANGELOG.mdIn your release script:
#!/bin/bash
# Generate changelog
changelog --from $(git describe --tags --abbrev=0) -o CHANGELOG.md
# Review the changelog
cat CHANGELOG.md
# Commit and tag
git add CHANGELOG.md
git commit -m "chore: update changelog"
git tag -a v1.2.3 -m "Release v1.2.3"
git push && git push --tagszig-changelog parses conventional commits and groups them by type:
feat: add new authentication system
fix: resolve memory leak in parser
docs: update API documentation
style: fix code formatting
refactor: simplify user service
perf: optimize database queries
test: add integration tests
build: update dependencies
ci: improve GitHub Actions workflow
chore: update development tools
Breaking changes are detected and highlighted:
feat!: remove deprecated API endpoints
feat: add new feature
BREAKING CHANGE: The old API has been removed
The generated changelog follows this format:
## [v1.2.3] - 2024-01-15
[v1.2.3]: https://github.com/user/repo/compare/v1.2.2...v1.2.3
### π Features
- **auth**: add OAuth integration ([abc123d](https://github.com/user/repo/commit/abc123d))
- **api**: implement rate limiting ([def456a](https://github.com/user/repo/commit/def456a))
### π Bug Fixes
- **parser**: fix memory leak in token processing ([ghi789b](https://github.com/user/repo/commit/ghi789b))
### π Documentation
- update API documentation ([jkl012c](https://github.com/user/repo/commit/jkl012c))Configuration options for changelog generation:
pub const Config = struct {
from_ref: ?[]const u8 = null, // Start commit reference
to_ref: []const u8 = "HEAD", // End commit reference
output_file: ?[]const u8 = null, // Output file path
verbose: bool = false, // Enable verbose logging
hide_author_email: bool = false, // Hide author emails
exclude_authors: []const []const u8 = &[_][]const u8{}, // Authors to exclude
include_dates: bool = true, // Include dates in output
group_breaking_changes: bool = true, // Group breaking changes
repo_url: ?[]const u8 = null, // Repository URL for links
};Parsed commit information:
pub const Commit = struct {
hash: []const u8,
short_hash: []const u8,
author_name: []const u8,
author_email: []const u8,
date: []const u8,
message: []const u8,
commit_type: CommitType,
scope: ?[]const u8,
description: []const u8,
breaking: bool,
body: ?[]const u8,
};Enum of conventional commit types:
pub const CommitType = enum {
feat,
fix,
docs,
style,
refactor,
perf,
test,
build,
ci,
chore,
revert,
unknown,
};pub fn generateChangelog(
allocator: std.mem.Allocator,
dir: []const u8,
config: *const Config,
) !ChangelogResultGenerate a changelog from git commits.
pub fn isGitRepository(
allocator: std.mem.Allocator,
dir: []const u8,
) !boolCheck if a directory is a git repository.
pub fn getLatestTag(
allocator: std.mem.Allocator,
dir: []const u8,
) !?[]const u8Get the latest git tag in the repository.
zig buildzig build testzig build -Doptimize=ReleaseFastzig build installzig-changelog/
βββ build.zig # Build configuration
βββ src/
β βββ main.zig # CLI entry point
β βββ lib.zig # Library entry point
β βββ types.zig # Core types and structures
β βββ git.zig # Git operations
β βββ parser.zig # Commit parser
β βββ changelog.zig # Changelog generator
βββ README.md
zig build testThis tool is inspired by logsmith but implemented in Zig for:
- Performance: Native Zig performance without runtime overhead
- Portability: Single binary with no dependencies
- Memory Safety: Zig's compile-time memory safety guarantees
- Simplicity: Focused on core changelog generation features
MIT License - see LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.