diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1f16355 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.9', '3.10', '3.11', '3.12'] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest mock six + pip install -e . + - name: Run tests + run: pytest tests/ -v + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install flake8 + run: pip install flake8 + - name: Run flake8 + run: flake8 giticket diff --git a/giticket/giticket.py b/giticket/giticket.py index 076154e..0b82437 100644 --- a/giticket/giticket.py +++ b/giticket/giticket.py @@ -14,7 +14,12 @@ regex_match_mode = 'regex_match' conventionalcommit_regex = r'^(?Pbuild|chore|ci|docs|feat|fix|perf|refactor|style|test)(\((?P.+)\))?: (?P.+)' -def update_commit_message(filename, regex, mode, format_string, conventionalcommits=False): + +def capitalize_first(text): + return text[:1].upper() + text[1:] if text else text + + +def update_commit_message(filename, regex, mode, format_string, conventionalcommits=False, capitalize=False): with io.open(filename, 'r+') as fd: contents = fd.readlines() commit_msg = contents[0].rstrip('\r\n') @@ -40,6 +45,8 @@ def update_commit_message(filename, regex, mode, format_string, conventionalcomm else: scope = ', '.join(tickets) subject = match.group('subject') + if capitalize: + subject = capitalize_first(subject) format_string = '{type}({scope}): {subject}' new_commit_msg = format_string.format( type=type, scope=scope, subject=subject @@ -49,6 +56,8 @@ def update_commit_message(filename, regex, mode, format_string, conventionalcomm ticket=tickets[0], tickets=', '.join(tickets), commit_msg=commit_msg ) + if capitalize: + new_commit_msg = capitalize_first(new_commit_msg) contents[0] = six.text_type(new_commit_msg + "\n") fd.seek(0) @@ -78,6 +87,7 @@ def main(argv=None): parser = argparse.ArgumentParser() parser.add_argument('filenames', nargs='+') parser.add_argument('--conventionalcommits', action='store_true') + parser.add_argument('--capitalize', action='store_true') parser.add_argument('--regex') parser.add_argument('--format', nargs='?') parser.add_argument('--mode', nargs='?', const=underscore_split_mode, @@ -89,7 +99,7 @@ def main(argv=None): return 1 regex = args.regex or r'[A-Z]+-\d+' # noqa format_string = args.format or '{ticket} {commit_msg}' # noqa - update_commit_message(args.filenames[0], regex, args.mode, format_string, args.conventionalcommits) + update_commit_message(args.filenames[0], regex, args.mode, format_string, args.conventionalcommits, args.capitalize) if __name__ == '__main__': diff --git a/requirements_dev.txt b/requirements_dev.txt index e982e59..6c2cec6 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -3,12 +3,12 @@ bumpversion==0.5.3 wheel==0.32.1 watchdog==0.9.0 flake8==3.5.0 -tox==3.5.2 coverage==4.5.1 Sphinx==1.8.1 twine==1.12.1 six mock +pre-commit -pytest==3.8.2 -pytest-runner==4.2 +pytest +pytest-runner diff --git a/tests/test_giticket.py b/tests/test_giticket.py index 31ff0ab..dc8dc87 100644 --- a/tests/test_giticket.py +++ b/tests/test_giticket.py @@ -124,6 +124,7 @@ def test_ci_message_with_nl_regex_match_mode(mock_branch_name, msg, tmpdir): 'regex_match', '{commit_msg} - {ticket}') assert path.read().split('\n')[0] == "{first_line} - {ticket}".format(first_line=first_line, ticket="JIRA-239") + # create a unit test to verify that if the --conventionalcommits flag is set, # the commit message is updated according to the conventional commit format @mock.patch(TESTING_MODULE + '.get_branch_name') @@ -135,6 +136,50 @@ def test_update_commit_message_conventionalcommits(mock_branch_name, tmpdir): 'regex_match', '{commit_msg}', conventionalcommits=True) assert path.read() == "feat(JIRA-5678): add new feature\n" + +@mock.patch(TESTING_MODULE + '.get_branch_name') +def test_update_commit_message_capitalize(mock_branch_name, tmpdir): + mock_branch_name.return_value = "jira-1234_new_feature" + path = tmpdir.join('file.txt') + path.write("Test commit message") + update_commit_message(six.text_type(path), r'[a-zA-Z]+-\d+', + 'regex_match', '{ticket}: {commit_msg}', + capitalize=True) + assert path.read() == "Jira-1234: Test commit message\n" + + +@mock.patch(TESTING_MODULE + '.get_branch_name') +def test_update_commit_message_capitalize_already_uppercase(mock_branch_name, tmpdir): + mock_branch_name.return_value = "JIRA-1234_new_feature" + path = tmpdir.join('file.txt') + path.write("Test commit message") + update_commit_message(six.text_type(path), r'[A-Z]+-\d+', + 'regex_match', '{ticket}: {commit_msg}', + capitalize=True) + assert path.read() == "JIRA-1234: Test commit message\n" + + +@mock.patch(TESTING_MODULE + '.get_branch_name') +def test_update_commit_message_capitalize_conventionalcommits(mock_branch_name, tmpdir): + mock_branch_name.return_value = "JIRA-5678_new_feature" + path = tmpdir.join('file.txt') + path.write("feat: add new feature") + update_commit_message(six.text_type(path), r'[A-Z]+-\d+', + 'regex_match', '{commit_msg}', + conventionalcommits=True, capitalize=True) + assert path.read() == "feat(JIRA-5678): Add new feature\n" + + +@mock.patch(TESTING_MODULE + '.get_branch_name') +def test_update_commit_message_capitalize_disabled_by_default(mock_branch_name, tmpdir): + mock_branch_name.return_value = "JIRA-1234_new_feature" + path = tmpdir.join('file.txt') + path.write("test commit message") + update_commit_message(six.text_type(path), r'[A-Z]+-\d+', + 'regex_match', '{ticket}: {commit_msg}') + assert path.read() == "JIRA-1234: test commit message\n" + + @pytest.mark.parametrize('msg', ( """A descriptive header @@ -189,9 +234,11 @@ def test_main(mock_update_commit_message, mock_argparse): mock_args.format = None mock_args.mode = 'underscore_split' mock_args.conventionalcommits = True + mock_args.capitalize = False mock_argparse.ArgumentParser.return_value.parse_args.return_value = mock_args main() mock_update_commit_message.assert_called_once_with('foo.txt', r'[A-Z]+-\d+', 'underscore_split', '{ticket} {commit_msg}', - True) + True, + False)