Skip to content

Commit

Permalink
Parse Trac component, priority, and keywords into GitHub labels.
Browse files Browse the repository at this point in the history
  • Loading branch information
danuker committed Oct 5, 2021
1 parent 28c1e59 commit b99d8fb
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.py.sample
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ USER_MAPPING = {
}

TRAC_TICKET_PREFIX = 'https://trac.chevah.com/ticket/'

# Component to GitHub repository mapping
REPOSITORY_MAPPING = {
'client': 'client',
'commons': 'commons',
}

FALLBACK_REPOSITORY = 'server'
86 changes: 86 additions & 0 deletions test/test_ticket_migrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import unittest

from ticket_migrate import get_repo, get_labels, labels_from_keywords


class TestRepositoryMapping(unittest.TestCase):
"""
Trac components map to the configured GitHub repositories.
These tests depend on `config.py` having the contents
from `config.py.sample`.
"""

def test_get_repo(self):
"""
Check that the issue is opened in the correct GitHub repository
based on the Trac component.
"""
self.assertEqual(get_repo('client'), 'client')
self.assertEqual(get_repo('commons'), 'commons')
self.assertEqual(get_repo('fallback'), 'server')


class TestLabelMapping(unittest.TestCase):
"""
Trac labels are parsed based on component, priority, and keywords_string.
These tests depend on `config.py` having the contents
from `config.py.sample`.
"""

def test_labels_from_keywords(self):
"""
Parse and clean the Trac keywords.
"""
# Split by space.
self.assertEqual(
{'easy', 'tech-debt'},
labels_from_keywords('easy tech-debt'))

# Remove commas.
self.assertEqual({'tech-debt'}, labels_from_keywords('tech-debt,'))
self.assertEqual(
{'tech-debt', 'feature'},
labels_from_keywords('tech-debt, feature'))

# Fix typos.
self.assertEqual(
{'tech-debt', 'easy'},
labels_from_keywords('tech-dept easy'))
self.assertEqual(
{'tech-debt'},
labels_from_keywords('tech-deb'))

# Discard unknown words to prevent tag explosion.
self.assertEqual(
set(),
labels_from_keywords('unknown-tag'))

# Deduplicate.
self.assertEqual(
{'tech-debt'},
labels_from_keywords('tech-deb, tech-debt tech-dept'))

def test_get_labels_none(self):
"""
The issues that do not map to the fallback repository
get no label based on the component.
"""
self.assertEqual(
{'priority-low', 'tech-debt'},
get_labels(
component='client', priority='Low', keywords='tech-dept'))
self.assertEqual(
{'priority-high'},
get_labels(
component='client', priority='High', keywords=''))

def test_get_labels_component_name(self):
self.assertEqual(
{'priority-low', 'fallback'},
get_labels('fallback', 'Low', ''))


if __name__ == '__main__':
unittest.main()
66 changes: 66 additions & 0 deletions ticket_migrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Migrate Trac tickets to GitHub.
from config import REPOSITORY_MAPPING, FALLBACK_REPOSITORY


def get_repo(component):
"""
Given the Trac component,
choose the GitHub repository to create the issue in.
"""
return REPOSITORY_MAPPING.get(component, FALLBACK_REPOSITORY)


def labels_from_component(component: str):
"""
Given the Trac component,
choose the labels to apply on the GitHub issue, if any.
"""
if component in REPOSITORY_MAPPING:
return []

return [component]


def labels_from_keywords(keywords: str):
"""
Given the Trac `keywords` string, clean it up and parse it into a list.
"""
keywords = keywords.replace(',', '')
keywords = keywords.split(' ')

allowed_keyword_labels = {
'design',
'easy',
'feature',
'happy-hacking',
'onboarding',
'password-management',
'perf-test',
'remote-management',
'salt',
'scp',
'security',
'tech-debt',
'twisted',
'ux',
}
typo_fixes = {'tech-dept': 'tech-debt', 'tech-deb': 'tech-debt'}

keywords = [typo_fixes.get(kw, kw) for kw in keywords]
discarded = [kw for kw in keywords if kw not in allowed_keyword_labels]

if discarded:
print("Warning: discarded keywords:", discarded)

return {kw for kw in keywords if kw in allowed_keyword_labels}


def get_labels(component: str, priority: str, keywords: str):
"""
Given the Trac component, priority, and keywords,
return the labels to apply on the GitHub issue.
"""
priority_label = 'priority-{}'.format(priority.lower())
keyword_labels = labels_from_keywords(keywords)
component_labels = labels_from_component(component)
return {priority_label}.union(keyword_labels).union(component_labels)

0 comments on commit b99d8fb

Please sign in to comment.