Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ Add this to your workflow file (e.g., `.github/workflows/changelog-check.yml`):
| `changelog-path` | `changelog/unreleased` | Path to changelog directory |
| `on-missing-entry` | `fail` | Action: `fail`, `warn`, or `generate` |
| `skip-files-regex` | (empty) | Skip changelog if all files match pattern |
| `skip-changelog-labels` | (empty) | Skip changelog if PR has any of these labels (comma-separated) |
| `missing-entry-message` | (see below) | Custom message when changelog entry is missing |
| `claude-token` | (empty) | Claude API key for generation |
| `claude-model` | `claude-3-5-sonnet-20241022` | Claude model to use |
| `claude-model` | `claude-opus-4-1-20250805` | Claude model to use |
| `changelog-language` | `English` | Language for generated entries |

### Validation Rules
Expand Down Expand Up @@ -79,6 +81,29 @@ Add this to your workflow file (e.g., `.github/workflows/changelog-check.yml`):
| `max-tokens-per-file` | `1000` | Max tokens per file |
| `claude-system-prompt` | (built-in) | Custom AI instructions |

### Managed Changelog Support

| Input | Default | Description |
|-------|---------|-------------|
| `managed-changelog-paths` | `CHANGELOG.md` | Managed changelog files to detect (comma-separated). Set to empty to disable. |
| `on-managed-entry` | `convert` | Action when managed file is edited: `fail` (no help), `warn` (comment), `remove` (suggest removal), `convert` (LLM conversion) |
| `on-managed-and-logchange` | `warn` | Action when both managed and logchange entries exist: `fail`, `warn`, or `ignore` |
| `managed-entry-message` | (see below) | Custom message when managed entry is detected |
| `managed-conflict-message` | (see below) | Custom message when both entry types exist |

### Validation Messages & Behavior

| Input | Default | Description |
|-------|---------|-------------|
| `validation-fail-message` | (see below) | Custom message when changelog entry fails validation |
| `validation-fail-workflow` | `true` | Whether to fail the workflow on validation errors |

### Testing & Debugging

| Input | Default | Description |
|-------|---------|-------------|
| `dry-run` | `false` | Generate suggestions without posting comments (for testing) |

## Examples

**Skip changelog for docs-only changes:**
Expand Down
34 changes: 17 additions & 17 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,30 @@ inputs:
required: false
default: ''

legacy-changelog-paths:
description: 'Comma-separated list of legacy changelog file paths to detect (e.g., CHANGELOG.md,HISTORY.txt). Defaults to CHANGELOG.md. Set to empty string to disable legacy changelog detection.'
managed-changelog-paths:
description: 'Comma-separated list of managed changelog file paths to detect (e.g., CHANGELOG.md,HISTORY.txt). Defaults to CHANGELOG.md. Set to empty string to disable managed changelog detection.'
required: false
default: 'CHANGELOG.md'

on-legacy-entry:
description: 'Action when legacy changelog entry is found. Always fails the action with different levels of help: "fail" (just fail), "warn" (fail + comment), "remove" (fail + removal suggestions), "convert" (fail + removal suggestions + LLM conversion to logchange)'
on-managed-entry:
description: 'Action when managed changelog file is edited. Always fails the action with different levels of help: "fail" (just fail), "warn" (fail + comment), "remove" (fail + removal suggestions), "convert" (fail + removal suggestions + LLM conversion to logchange)'
required: false
default: 'convert'

on-legacy-and-logchange:
description: 'Action when both legacy and logchange entries in same PR: "fail", "warn", or "ignore"'
description: 'Action when both managed and logchange entries in same PR: "fail", "warn", or "ignore"'
required: false
default: 'warn'

legacy-entry-message:
description: 'Custom message when legacy changelog entry is found'
managed-entry-message:
description: 'Custom message when managed changelog file is detected'
required: false
default: 'I detected a legacy changelog entry. Converting it to logchange format...'
default: 'I detected a managed changelog file. Converting it to logchange format...'

legacy-conflict-message:
description: 'Custom message when both legacy and logchange entries are present'
managed-conflict-message:
description: 'Custom message when both managed and logchange entries are present'
required: false
default: 'This PR contains both legacy and logchange changelog entries. Please use only logchange format.'
default: 'This PR contains both managed and logchange changelog entries. Please use only logchange format.'

external-issue-regex:
description: 'Regex pattern to detect external issue references (e.g., JIRA-123). Must have capture group for issue ID. Example: "JIRA-(\d+)"'
Expand Down Expand Up @@ -148,12 +148,12 @@ outputs:
description: 'Whether the changelog entry is valid'
changelog-generated:
description: 'Whether a changelog entry was generated'
legacy-entry-found:
description: 'Whether a legacy changelog entry was found'
legacy-converted:
description: 'Whether a legacy entry was converted to logchange format'
legacy-conflict:
description: 'Whether both legacy and logchange entries were found'
managed-entry-found:
description: 'Whether a managed changelog file was found'
managed-converted:
description: 'Whether a managed entry was converted to logchange format'
managed-conflict:
description: 'Whether both managed and logchange entries were found'
generation-error:
description: 'Error message if generation failed'

Expand Down
22 changes: 11 additions & 11 deletions action/src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,19 @@ def __init__(self):
self.optional_fields = self._parse_list_input("optional-fields", "")

# Legacy changelog configuration (enabled by default with CHANGELOG.md)
self.legacy_changelog_paths = self._parse_list_input(
self.managed_changelog_paths = self._parse_list_input(
"legacy-changelog-paths", "CHANGELOG.md"
)
self.on_legacy_entry = self._get_input("on-legacy-entry", "convert").lower()
self.on_legacy_and_logchange = self._get_input(
self.on_managed_entry = self._get_input("on-legacy-entry", "convert").lower()
self.on_managed_and_logchange = self._get_input(
"on-legacy-and-logchange", "warn"
).lower()
self.legacy_entry_message = self._get_input(
self.managed_entry_message = self._get_input(
"legacy-entry-message",
"I detected a legacy changelog entry. Converting it to logchange format...",
)
self.legacy_conflict_message = self._get_input(
"legacy-conflict-message",
self.managed_conflict_message = self._get_input(
"managed-conflict-message",
"This PR contains both legacy and logchange changelog entries. Please use only logchange format.",
)

Expand Down Expand Up @@ -173,16 +173,16 @@ def _validate_config(self) -> None:
)

# Validate on_legacy_entry mode
if self.on_legacy_entry not in ("convert", "warn", "fail", "remove"):
if self.on_managed_entry not in ("convert", "warn", "fail", "remove"):
raise ConfigurationError(
f"Invalid on-legacy-entry mode: {self.on_legacy_entry}. "
f"Invalid on-legacy-entry mode: {self.on_managed_entry}. "
"Must be one of: fail, warn, remove, convert"
)

# Validate on_legacy_and_logchange mode
if self.on_legacy_and_logchange not in ("fail", "warn", "ignore"):
if self.on_managed_and_logchange not in ("fail", "warn", "ignore"):
raise ConfigurationError(
f"Invalid on-legacy-and-logchange mode: {self.on_legacy_and_logchange}. "
f"Invalid on-legacy-and-logchange mode: {self.on_managed_and_logchange}. "
"Must be one of: fail, warn, ignore"
)

Expand Down Expand Up @@ -230,7 +230,7 @@ def get_summary(self) -> str:
f"Validation types: {', '.join(self.changelog_types)}",
f"Mandatory fields: {', '.join(self.mandatory_fields)}",
f"Forbidden fields: {', '.join(self.forbidden_fields) if self.forbidden_fields else '(none)'}",
f"Legacy support: {len(self.legacy_changelog_paths)} paths configured",
f"Legacy support: {len(self.managed_changelog_paths)} paths configured",
f"Dry-run mode: {'enabled' if self.dry_run else 'disabled'}",
"=" * 40,
]
Expand Down
Loading
Loading