Skip to content

Commit 656d87a

Browse files
ogajduseclaude
andcommitted
fixes #199 - Add support for exempting i18n/translation commits from Redmine validation
Add exempt_patterns configuration to allow specific commit message patterns to bypass Redmine validation requirements while maintaining validation for regular commits. Features: - Global default patterns applied to all repositories (for common i18n patterns) - Repository-specific override capability for special cases - Regex pattern matching for flexible commit message formats - Backward compatible - no breaking changes to existing configuration Global patterns added for common translation workflows: - "^i18n - " (e.g., "i18n - Update Japanese translations") - "^Localization - " (e.g., "Localization - Fix German strings") - "^Update translations" (e.g., "Update translations for 3.5 release") - "^Automatic locale update" (e.g., "Automatic locale update from Crowdin") 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent c0ca014 commit 656d87a

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

prprocessor/__main__.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ class Commit:
6666

6767
@property
6868
def subject(self):
69-
return self.message.splitlines()[0]
69+
lines = self.message.splitlines()
70+
return lines[0] if lines else ""
7071

7172

7273
@dataclass
@@ -76,16 +77,31 @@ class Config:
7677
refs: set = field(default_factory=set)
7778
version_prefix: Optional[str] = None
7879
apply_labels: bool = True
80+
exempt_patterns: list = field(default_factory=list)
7981

8082

8183
# This should be handled cleaner
8284
with open(resource_filename(__name__, 'config/repos.yaml')) as config_fp:
83-
CONFIG = {
84-
repo: Config(project=config.get('redmine'), required=config.get('redmine_required', False),
85-
refs=set(config.get('refs', [])),
86-
version_prefix=config.get('redmine_version_prefix'))
87-
for repo, config in yaml.safe_load(config_fp).items()
88-
}
85+
config_data = yaml.safe_load(config_fp)
86+
87+
# Extract global patterns as default
88+
global_patterns = config_data.get('global_config', {}).get('exempt_patterns', [])
89+
90+
CONFIG = {}
91+
for repo, config in config_data.items():
92+
if repo == 'global_config':
93+
continue
94+
95+
# Use repository-specific patterns if defined, otherwise use global
96+
repo_patterns = config.get('exempt_patterns', global_patterns)
97+
98+
CONFIG[repo] = Config(
99+
project=config.get('redmine'),
100+
required=config.get('redmine_required', False),
101+
refs=set(config.get('refs', [])),
102+
version_prefix=config.get('redmine_version_prefix'),
103+
exempt_patterns=repo_patterns
104+
)
89105

90106
with open(resource_filename(__name__, 'config/users.yaml')) as users_fp:
91107
USERS = yaml.safe_load(users_fp)
@@ -94,6 +110,15 @@ class Config:
94110
logger = logging.getLogger('prprocessor') # pylint: disable=invalid-name
95111

96112

113+
def is_commit_exempt(commit: Commit, exempt_patterns: list) -> bool:
114+
"""Check if commit subject matches any exemption pattern."""
115+
import re
116+
for pattern in exempt_patterns:
117+
if re.search(pattern, commit.subject, re.IGNORECASE):
118+
return True
119+
return False
120+
121+
97122
def get_config(repository: str) -> Config:
98123
try:
99124
return CONFIG[repository]
@@ -214,7 +239,8 @@ async def get_issues_from_pr(pull_request: Mapping) -> tuple[IssueValidation, Co
214239
issue_ids.update(commit.fixes)
215240
issue_ids.update(commit.refs)
216241
if config.required and not commit.fixes and not commit.refs:
217-
invalid_commits.append(commit)
242+
if not is_commit_exempt(commit, config.exempt_patterns):
243+
invalid_commits.append(commit)
218244

219245
return verify_issues(config, issue_ids), invalid_commits
220246

prprocessor/config/repos.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@
44
# redmine_required: enforce commit message format to include Redmine ticket number (default: false)
55
# refs: optional list of Redmine projects that commits here can "refs" (default: [])
66
# branches: list of primary development branches, else uses repo default
7+
# exempt_patterns: optional list of regex patterns for commits that should bypass
8+
# Redmine validation (useful for i18n, automated updates, etc.)
79
---
10+
11+
# Global default patterns applied to ALL repositories (unless overridden)
12+
global_config:
13+
exempt_patterns:
14+
- "^i18n - "
15+
- "^Localization - "
16+
- "^Update translations"
17+
- "^Automatic locale update"
818
ekohl/gh-test-env:
919
redmine: pr-processor-test
1020
redmine_required: true

0 commit comments

Comments
 (0)