Skip to content

Commit

Permalink
feat(main): implement reference search (#58)
Browse files Browse the repository at this point in the history
* refactor(options): make users optional

* feat(main): add support for reference searching

* test(main): verify reference is passed correctly

* test(github): verify reference search

* docs(readme): add example reference

* docs(readme): add reference search
  • Loading branch information
kiran94 authored Jan 26, 2024
1 parent c706840 commit b5dc58a
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 18 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ prfiesta -u charliermarsh --after 2023-05-01 --use-reviewed-by
# Get all pull requests where the user was requested a review rather then being the author
prfiesta -u charliermarsh --after 2023-05-01 --use-review-requested

# Get all pull requests which contains a reference (e.g JIRA card reference) within the PR title or body
prfiesta --reference PA-12765

# Get help
prfiesta --help

Expand Down Expand Up @@ -128,6 +131,15 @@ When using the `--after` and `--before` date filters, by default `prfiesta` will

Learn more about date filters [here](https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-when-an-issue-or-pull-request-was-created-or-last-updated).

### Reference Search

You may come across a use case where you want to filter pull requests on a specific reference. For example, it may be a team practise to put a JIRA card reference within the pull request title or body.

For this you can use the `--reference` filter.

> [!NOTE]
> Results from reference search is entirely up to the GitHub Search API. On some ocassions, it may not provide inaccurate results.
## Analysis

`prfiesta` ships with built in plots to help analyze your pull request data. These serve as a starting point in your analysis. See more information on the build in plots and views [here](https://github.com/kiran94/prfiesta/blob/main/docs/analysis.md).
Expand Down
5 changes: 4 additions & 1 deletion prfiesta/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
@cloup.command()
@cloup.option_group(
"general options",
cloup.option("-u", "--users", required=True, multiple=True, help="The GitHub Users to search for. Can be multiple"),
cloup.option("-u", "--users", multiple=True, help="The GitHub Users to search for. Can be multiple"),
cloup.option("--reference", help="A external ticket reference to search for e.g. JIRA-1234"),
)
@cloup.option_group(
"date filter options",
Expand Down Expand Up @@ -69,6 +70,7 @@ def main(**kwargs) -> None:
use_involves: bool = kwargs.get("use_involves")
use_reviewed_by: bool = kwargs.get("use_reviewed_by")
use_review_requested: bool = kwargs.get("use_review_requested")
reference: str = kwargs.get("reference")

logger.info("[bold green]PR Fiesta 🦜🥳")

Expand All @@ -84,6 +86,7 @@ def main(**kwargs) -> None:
use_involves=use_involves,
use_reviewed_by=use_reviewed_by,
use_review_requested=use_review_requested,
reference=reference,
)

if not pr_frame.empty:
Expand Down
12 changes: 9 additions & 3 deletions prfiesta/collectors/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,16 @@ def __init__(self, **kwargs) -> None:

def collect(
self,
*users: Tuple[str],
*users: Optional[Tuple[str]],
after: Optional[datetime] = None,
before: Optional[datetime] = None,
use_updated: Optional[bool] = False,
use_involves: Optional[bool] = False,
use_reviewed_by: Optional[bool] = False,
use_review_requested: Optional[bool] = False,
reference: Optional[str] = None,
) -> pd.DataFrame:
query = self._construct_query(users, after, before, use_updated, use_involves, use_reviewed_by, use_review_requested)
query = self._construct_query(users, after, before, use_updated, use_involves, use_reviewed_by, use_review_requested, reference)

update_spinner(f"Searching {self._url} with[bold blue] {query}", self._spinner, logger)

Expand Down Expand Up @@ -84,13 +85,14 @@ def collect(

@staticmethod
def _construct_query(
users: List[str],
users: Optional[List[str]],
after: Optional[datetime] = None,
before: Optional[datetime] = None,
use_updated: Optional[bool] = False,
use_involves: Optional[bool] = False,
use_reviewed_by: Optional[bool] = False,
use_review_requested: Optional[bool] = False,
reference: Optional[str] = None,
) -> str:
"""
Constructs a GitHub Search Query
Expand All @@ -105,6 +107,7 @@ def _construct_query(
type:pr involves:user2
type:pr reviewed-by:user1
type:pr review-requested:user1
type:pr in:title,body "PA-12765"
All dates are inclusive.
See GitHub Docs for full options https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests
Expand Down Expand Up @@ -138,6 +141,9 @@ def _construct_query(
elif after:
query.append(f"{time_filter}:>={after.strftime('%Y-%m-%d')}")

if reference:
query.append(f'in:title,body "{reference}"')

return " ".join(query)

def _move_column_to_end(self, df: pd.DataFrame) -> pd.DataFrame:
Expand Down
7 changes: 7 additions & 0 deletions tests/collectors/test_github.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,13 @@
"type:pr review-requested:user1 review-requested:user2",
id="review_requested_user",
),
pytest.param(
(),
{"reference": "JIRA-1234"},
[_mock_issue1, _mock_issue2],
'type:pr in:title,body "JIRA-1234"',
id="reference",
),
],
)
@patch("prfiesta.collectors.github.Github")
Expand Down
109 changes: 95 additions & 14 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@
FAILURE_CODE = 2


def test_main_missing_users() -> None:
runner = CliRunner()
result = runner.invoke(main, [""])

assert "Missing option '-u' / '--users'" in result.output
assert result.exit_code == FAILURE_CODE


@pytest.mark.parametrize(
"arguments",
[
Expand All @@ -42,7 +34,18 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
[
pytest.param(
["--users", "test_user"],
[call("test_user", after=None, before=None, use_updated=False, use_involves=False, use_reviewed_by=False, use_review_requested=False)],
[
call(
"test_user",
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
)
],
pd.DataFrame(),
"csv",
None,
Expand All @@ -59,6 +62,7 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
),
],
pd.DataFrame(),
Expand All @@ -77,6 +81,7 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
),
],
pd.DataFrame(),
Expand All @@ -95,6 +100,7 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
),
],
pd.DataFrame(),
Expand All @@ -104,7 +110,18 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
),
pytest.param(
["--users", "test_user"],
[call("test_user", after=None, before=None, use_updated=False, use_involves=False, use_reviewed_by=False, use_review_requested=False)],
[
call(
"test_user",
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
)
],
pd.DataFrame(
data=[(1, 2, 3)],
columns=["col1", "col2", "col3"],
Expand All @@ -115,7 +132,18 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
),
pytest.param(
["--users", "test_user", "--output-type", "parquet"],
[call("test_user", after=None, before=None, use_updated=False, use_involves=False, use_reviewed_by=False, use_review_requested=False)],
[
call(
"test_user",
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
)
],
pd.DataFrame(
data=[(1, 2, 3)],
columns=["col1", "col2", "col3"],
Expand All @@ -135,6 +163,7 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
),
],
pd.DataFrame(),
Expand All @@ -153,6 +182,7 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
use_involves=True,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
),
],
pd.DataFrame(),
Expand All @@ -162,28 +192,79 @@ def test_main_author_filters_mutually_exclusive(arguments: List[str]) -> None:
),
pytest.param(
["--users", "test_user", "--use-reviewed-by"],
[call("test_user", after=None, before=None, use_updated=False, use_involves=False, use_reviewed_by=True, use_review_requested=False)],
[
call(
"test_user",
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=True,
use_review_requested=False,
reference=None,
)
],
pd.DataFrame(),
"csv",
None,
id="user_reviewed_by",
),
pytest.param(
["--users", "test_user", "--use-review-requested"],
[call("test_user", after=None, before=None, use_updated=False, use_involves=False, use_reviewed_by=False, use_review_requested=True)],
[
call(
"test_user",
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=False,
use_review_requested=True,
reference=None,
)
],
pd.DataFrame(),
"csv",
None,
id="user_review_requested",
),
pytest.param(
["--users", "test_user", "--output-type", "duckdb", "--output", "my.duckdb"],
[call("test_user", after=None, before=None, use_updated=False, use_involves=False, use_reviewed_by=False, use_review_requested=False)],
[
call(
"test_user",
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference=None,
)
],
pd.DataFrame(data={"a": [1, 2, 3]}),
"duckdb",
"my.duckdb",
id="with_duckdb",
),
pytest.param(
["--reference", "JIRA-1234"],
[
call(
after=None,
before=None,
use_updated=False,
use_involves=False,
use_reviewed_by=False,
use_review_requested=False,
reference="JIRA-1234",
)
],
pd.DataFrame(data={"a": [1, 2, 3]}),
"csv",
None,
id="with_reference",
),
],
)
@patch("prfiesta.__main__.Spinner")
Expand Down

0 comments on commit b5dc58a

Please sign in to comment.