Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save barseghyanartur/789ea73843cd18f9ad410e36a19d25be to your computer and use it in GitHub Desktop.

Select an option

Save barseghyanartur/789ea73843cd18f9ad410e36a19d25be to your computer and use it in GitHub Desktop.
Keep Changelog vs Conventional Commits

Adding JIRA Ticket Numbers (for Observability) to the Changelog

Below are pragmatic, tooling-friendly approaches to ensure every changelog line carries a JIRA reference that links back to your tracker. All examples assume JIRA keys like OBS-123 (adjust the regex if your project key differs).


Minimal Manual Pattern (no tooling required)

  1. Commit convention (Conventional Commits + JIRA at end):
feat(api): add distributed tracing [OBS-123]

or:

feat(api): add distributed tracing

Refs: OBS-123
  1. Changelog entry (Keep a Changelog):
### Added
- Add distributed tracing ([OBS-123](https://jira.example.com/browse/OBS-123))

Pros: Zero extra tools.
Cons: Manual discipline; no auto-linking.


Auto-Linking with git-cliff (simple, fast, language-agnostic)

1) Add a cliff.toml at repo root:

[changelog]
header = "# Changelog"
body = """
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | first_line | trim }}{% if commit.footers %} ({{ commit.footers | join(sep=", ") }}){% endif %}{% if commit.jira %} ({{ commit.jira | join(sep=", ") }}){% endif %}
{% endfor %}
{% endfor %}
"""
footer = ""

[git]
conventional_commits = true

# Extract JIRA keys from subject, body, or footers
# Matches OBS-123, CORE-42, etc. Adjust to your project(s).
filter_unconventional = false

[commit_parsers]
# Map types to Keep a Changelog sections
"feat" = { group = "Added" }
"fix" = { group = "Fixed" }
"perf" = { group = "Changed" }
"refactor" = { group = "Changed" }
"docs" = { group = "Changed" }
"build" = { group = "Changed" }
"ci" = { group = "Changed" }
"chore" = { group = "Changed" }
"style" = { group = "Changed" }
"test" = { group = "Changed" }

[regex]
# Capture JIRA keys anywhere in the commit
jira = "(?i)\\b([A-Z][A-Z0-9]+-\\d+)\\b"

[remote.github]
# not used for JIRA; keep if you also want GH links

[templates]
# Render matched JIRA keys as full links
jira = "[{{ key }}](https://jira.example.com/browse/{{ key }})"

2) Generate changelog:

git cliff -o CHANGELOG.md

Expected output snippet:

### Added
- add distributed tracing ([OBS-123](https://jira.example.com/browse/OBS-123))

Notes:

  • jira regex pulls keys from subject/body/footers.
  • templates.jira controls link format.
  • Maps Conventional Commit feat → “Added”, fix → “Fixed”, etc., matching Keep a Changelog.

Auto-Linking with Commitizen + Conventional Changelog

1) Enforce commit format with JIRA in subject or footer.
Example subject:

feat(auth): allow login using email alias [OBS-789]

Or footer:

Refs: OBS-789

2) .cz.toml (or .czrc) to standardize commits:

[tool.commitizen]
name = "cz_conventional_commits"
version = "0.0.0"
tag_format = "v$version"
bump_message = "chore(release): $current_version → $new_version"
changelog_file = "CHANGELOG.md"
update_changelog_on_bump = true

[tool.commitizen.customize]
# Optional: guardrail hint, not strict enforcement
message_template = "{commit_type}{scope}: {subject} [JIRA-KEY]"

3) commitlint (optional) to require a JIRA key
If you use commitlint with Husky:

// commitlint.config.cjs
module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'footer-max-line-length': [2, 'always', 200],
    'references-empty': [0, 'never'],
    'subject-case': [0],
    // Require JIRA key either in subject [...] or footers:
    'subject-jira-key': [2, 'always']
  },
  plugins: [
    {
      rules: {
        'subject-jira-key': ({ subject, footer }) => {
          const re = /\b[A-Z][A-Z0-9]+-\d+\b/;
          const ok = re.test(subject || '') || re.test(footer || '');
          return [
            ok ? 0 : 2,
            ok ? 'ok' : 'Commit must contain a JIRA key like OBS-123'
          ];
        }
      }
    }
  ]
};

4) conventional-changelog
Most generators can be extended via writer options, but it’s simpler to:

  • Keep the key in the subject, and
  • Post-process output (a small script) to auto-link OBS-123https://jira.example.com/browse/OBS-123.

Example post-process (Node):

// scripts/link-jira.js
const fs = require('fs');
const path = 'CHANGELOG.md';
let s = fs.readFileSync(path, 'utf8');
s = s.replace(/\b([A-Z][A-Z0-9]+-\d+)\b/g, '[$1](https://jira.example.com/browse/$1)');
fs.writeFileSync(path, s);

Then:

conventional-changelog -p angular -i CHANGELOG.md -s
node scripts/link-jira.js

Python-Only Stack (no Node): towncrier with references

If you prefer curated entries:

  • Put JIRA in the news fragment filename or content, e.g. 123.feature containing:
    Add distributed tracing. (OBS-123)
  • towncrier build will assemble CHANGELOG.md.
  • After build, run a small Python script to auto-link JIRA keys:
    # scripts/link_jira.py
    import re, pathlib
    p = pathlib.Path("CHANGELOG.md")
    s = p.read_text()
    s = re.sub(r"\b([A-Z][A-Z0-9]+-\d+)\b",
               r"[\1](https://jira.example.com/browse/\1)", s)
    p.write_text(s)

Recommended Practice (Concise)

  1. Put the JIRA key in every commit (subject [...] or footer Refs:).
  2. Generate changelog with git-cliff and a short cliff.toml that:
    • Maps Conventional Commit types to Keep a Changelog sections,
    • Auto-detects JIRA keys via regex,
    • Renders them as links.
  3. Keep entries user-focused; the JIRA link is appended at the end of each bullet.

Resulting changelog excerpt:

## [Unreleased]

### Added
- Add distributed tracing ( [OBS-123](https://jira.example.com/browse/OBS-123) )

### Fixed
- Correct negative number handling in parser ( [OBS-456](https://jira.example.com/browse/OBS-456) )

This gives you reliable observability from changelog → JIRA with minimal friction and excellent team hygiene.

Keep a Changelog vs Conventional Commits

Does Keep a Changelog use Conventional Commits?

  • No, Keep a Changelog does not formally adopt Conventional Commits.
  • Keep a Changelog focuses on changelog structure for end users:
    Added, Changed, Deprecated, Removed, Fixed, Security.
  • Conventional Commits specifies commit message formatting (type(scope): description).
  • They are compatible but independent. You can map commit types to changelog sections.

Common Commit Prefixes

Suggested prefixes (Conventional Commits style) and their mapping to Keep a Changelog:

Prefix Purpose Maps to Changelog
feat: New feature Added
fix: Bug fix Fixed
chore: Maintenance, build, deps, tooling Changed / omit
docs: Documentation Added / Changed
refactor: Code restructuring without feature/bug Changed
perf: Performance improvements Changed
style: Formatting, linting Usually omit
test: Adding/modifying tests Usually omit
ci: CI/CD changes Usually omit
build: Build system / dependency changes Changed

Breaking changes:

  • Use ! after type, e.g. feat(ui)!: remove deprecated API
  • Or add footer: BREAKING CHANGE: description.

Branch Naming

Recommended branch naming patterns:

  • feature/<short-description> or feat/<short-description>
  • bugfix/<short-description> or fix/<short-description>
  • hotfix/<short-description>
  • chore/<short-description>
  • docs/<short-description>
  • refactor/<short-description>
  • release/vX.Y.Z

If you use issue/ticket numbers:
feature/ABC-123-short-description


Commit Message Template

<type>(<scope>): <short description>

[optional body]

[optional footer(s): BREAKING CHANGE: details, Closes #123]

Example:

feat(parser): add support for nested expressions
fix(parser): correct handling of negative numbers
refactor(api): clean up request validation
feat(ui)!: remove deprecated theming API

Example Changelog Mapping

## [Unreleased]

### Added
- Support for nested expressions in parser.
- Remove deprecated theming API (BREAKING CHANGE).

### Fixed
- Correct handling of negative numbers in parser.

### Changed
- Clean up request validation in API.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment