Skip to content

Commit

Permalink
Initial ver (#1)
Browse files Browse the repository at this point in the history
* init files

* untested implementation

* untested skip merge commits

* rename to prepend_jira_issue

add entry point

* add a test on issue extract

add dependencies

* add GH workflow for pytest

* tweak readme
  • Loading branch information
falkben authored Sep 16, 2022
1 parent a37c83c commit 8ac0862
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 1 deletion.
23 changes: 23 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: CI

on:
push:
workflow_dispatch:

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.10"
cache: "pip"

- name: install
run: |
pip install . -r requirements.txt
- name: pytest
run: pytest
7 changes: 7 additions & 0 deletions .pre-commit-hooks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- id: prepend-jira-issue
name: Prepend Jira Issue
entry: prepend_jira_issue
language: python
description: This hook prepends a Jira issue to a commit message
always_run: true
stages: [commit-msg]
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
# pre-commit-prepend-jira-ticket
# pre-commit prepend jira issue

A [pre-commit](https://pre-commit.com/) hook to prepend a Jira issue to a commit message, extracted from the branch name.

## Usage

todo

## License

[MIT](LICENSE)

## Inspiration

1. <https://github.com/radix-ai/auto-smart-commit>
2. <https://agussarwono.com/article/add-ticket-to-your-commit/>
3. <https://github.com/erskaggs/jira-pre-commit>

## Developer Notes

todo
81 changes: 81 additions & 0 deletions prepend_jira_issue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from __future__ import annotations

import argparse
import re
import subprocess
from typing import Sequence


def run_command(command: str) -> str:
"""Run a command and return its output
If the command fails, return an empty string"""

try:
stdout: str = subprocess.check_output(command.split()).decode("utf-8").strip()
except Exception:
stdout = ""
return stdout


def get_branch_name() -> str:
# git rev-parse --abbrev-ref HEAD
# returns HEAD if in detached state
# git symbolic-ref --short HEAD
# returns fatal: ref HEAD is not a symbolic ref if in detached state
return run_command("git symbolic-ref --short HEAD")


def extract_jira_issue(content: str) -> str | None:
project_key, issue_number = r"[A-Z]{2,}", r"[0-9]+"
match = re.search(f"{project_key}-{issue_number}", content)
if match:
return match.group(0)
return None


def get_commit_msg(commit_msg_filepath: str) -> str:
with open(commit_msg_filepath) as f:
msg = f.read()
return msg


def write_commit_msg(commit_msg_filepath: str, commit_msg: str) -> None:
with open(commit_msg_filepath, "w") as f:
f.write(commit_msg)


def main(argv: Sequence[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument("commit_msg_filepath", type=str)

args = parser.parse_args(argv)

git_branch_name = get_branch_name()
branch_jira_issue = extract_jira_issue(git_branch_name)

# if no jira issue in branch name, exit
if branch_jira_issue is None:
return 0

commit_msg = get_commit_msg(args.commit_msg_filepath)

# ignore merge requests
if re.match("^Merge commit '", commit_msg):
return 0

# check if commit message already has a jira issue in it's name
commit_msg_jira_issue = extract_jira_issue(commit_msg)
# if jira issue already in commit message, skip
if commit_msg_jira_issue:
return 0

# prepend the jira issue to the commit message if it's missing
new_commit_msg = f"{branch_jira_issue}: {commit_msg}"
write_commit_msg(args.commit_msg_filepath, new_commit_msg)

return 0


if __name__ == "__main__":
raise SystemExit(main())
1 change: 1 addition & 0 deletions requirements.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest
22 changes: 22 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#
# This file is autogenerated by pip-compile with python 3.10
# To update, run:
#
# pip-compile
#
attrs==22.1.0
# via pytest
iniconfig==1.1.1
# via pytest
packaging==21.3
# via pytest
pluggy==1.0.0
# via pytest
py==1.11.0
# via pytest
pyparsing==3.0.9
# via packaging
pytest==7.1.3
# via -r requirements.in
tomli==2.0.1
# via pytest
12 changes: 12 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from setuptools import setup

setup(
name="prepend_jira_issue",
version="0.0.1",
py_modules=["prepend_jira_issue"],
entry_points={
"console_scripts": [
"prepend_jira_issue = prepend_jira_issue:main",
],
},
)
24 changes: 24 additions & 0 deletions test_prepend_jira_ticket.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import pytest

import prepend_jira_issue


@pytest.mark.parametrize(
("content", "expected"),
(
("ABC-1111", "ABC-1111"),
("A-1111", None),
("ABC-1", "ABC-1"),
("abc 1111", None),
("two little bears, sitting in chairs", None),
("and a bowl of much 123-ABC", None),
("and a little old lady CDE-123", "CDE-123"),
("CDE-123: and a little old lady ", "CDE-123"),
("ZYX-123-321-ABC", "ZYX-123"),
("ZYX-123-ABC-321", "ZYX-123"),
("ZYX-ABC-321-123", "ABC-321"),
),
)
def test_extract_jira_issue(content, expected):
output = prepend_jira_issue.extract_jira_issue(content)
assert output == expected

0 comments on commit 8ac0862

Please sign in to comment.