diff --git a/docs/use.md b/docs/use.md index f871b7d..68b647f 100644 --- a/docs/use.md +++ b/docs/use.md @@ -41,8 +41,20 @@ github-activity jupyter/notebook -s 6.0.0 -u 6.0.1 -o sample_notebook_activity.m You can find the [resulting markdown here](sample_notebook_activity). -```{tip} -For repositories that use multiple branches, it may be necessary to filter PRs by a branch name. This can be done using the `--branch` parameter in the CLI. Other git references can be used as well in place of a branch name. +## Filter pull requests by branch + +Many repositories work with multiple active branches (e.g., `main`, `develop`, feature branches). When generating a changelog for a specific release, you typically only want to include pull requests that were merged into the release branch. + +Use the `--branch` (or `-b`) parameter to filter pull requests by their target branch: + +```bash +github-activity org/repo --since v1.0.0 --until v2.0.0 --branch main +``` + +This will **only include pull requests that targeted the `main` branch**, excluding any PRs merged to other branches like `develop` or feature branches. + +```{note} +You can use any git reference (tag, commit hash, etc.) in place of a branch name. ``` ## Choose a date or a tag to filter activity @@ -217,7 +229,7 @@ This is not as well-documented as the CLI, but should have most functionality av For generating markdown changelogs from Python, here's an example: -``` +```python from github_activity import generate_activity_md markdown = generate_activity_md( @@ -231,7 +243,7 @@ markdown = generate_activity_md( include_opened=True, strip_brackets=True, heading_level=1, - branch=None, + branch="main", # Filter PRs by target branch (optional, use None for all branches) ) # Print or save the markdown diff --git a/github_activity/cli.py b/github_activity/cli.py index 21ad281..67ace69 100644 --- a/github_activity/cli.py +++ b/github_activity/cli.py @@ -123,7 +123,9 @@ "--branch", "-b", default=None, - help=("""The branch or reference name to filter pull requests by"""), + help=( + """Filter pull requests by their target branch. Only PRs merged into this branch will be included. """ + ), ) parser.add_argument( "--all", @@ -223,31 +225,36 @@ def main(): ignored_contributors=args.ignore_contributor, ) - if args.all: - md = generate_all_activity_md(args.target, **common_kwargs) + # Wrap in a try/except so we don't have an ugly stack trace if there's an error + try: + if args.all: + md = generate_all_activity_md(args.target, **common_kwargs) - else: - md = generate_activity_md( - args.target, - since=args.since, - until=args.until, - heading_level=args.heading_level, - **common_kwargs, - ) + else: + md = generate_activity_md( + args.target, + since=args.since, + until=args.until, + heading_level=args.heading_level, + **common_kwargs, + ) - if not md: - return - - if args.output: - output = os.path.abspath(args.output) - output_dir = os.path.dirname(output) - if not os.path.exists(output_dir): - os.makedirs(output_dir) - with open(args.output, "w") as ff: - ff.write(md) - print(f"Finished writing markdown to: {args.output}", file=sys.stderr) - else: - print(md) + if not md: + return + + if args.output: + output = os.path.abspath(args.output) + output_dir = os.path.dirname(output) + if not os.path.exists(output_dir): + os.makedirs(output_dir) + with open(args.output, "w") as ff: + ff.write(md) + print(f"Finished writing markdown to: {args.output}", file=sys.stderr) + else: + print(md) + except ValueError as e: + print(f"Error: {e}", file=sys.stderr) + sys.exit(1) if __name__ == "__main__": diff --git a/github_activity/github_activity.py b/github_activity/github_activity.py index 9f07a58..4f93c2a 100644 --- a/github_activity/github_activity.py +++ b/github_activity/github_activity.py @@ -462,8 +462,27 @@ def generate_activity_md( data = get_activity( target, since=since, until=until, kind=kind, auth=auth, cache=False ) + + # Raise error if GitHub API returned no activity at all + # This happens when the repository has no issues/PRs in the date range if data.empty: - return + raise ValueError( + f"No activity found for {org}/{repo} between {since} and {until}." + ) + + # Filter the PRs by branch (or ref) if given + if branch is not None: + index_names = data[ + (data["kind"] == "pr") & (data["baseRefName"] != branch) + ].index + data.drop(index_names, inplace=True) + + # Raise error if branch filter removed all data + # This happens when PRs exist but none targeted the specified branch + if data.empty: + raise ValueError( + f"Found activity, but none for the --branch target specified for {org}/{repo} on branch '{branch}' between {since} and {until}.\n" + ) # Collect authors of comments on issues/prs that they didn't open for our attribution list comment_response_cutoff = 6 # Comments on a single issue @@ -581,15 +600,6 @@ def filter_ignored(userlist): ].index.tolist() all_contributors |= set(c for c in comment_contributors if isinstance(c, str)) - # Filter the PRs by branch (or ref) if given - if branch is not None: - index_names = data[ - (data["kind"] == "pr") & (data["baseRefName"] != branch) - ].index - data.drop(index_names, inplace=True) - if data.empty: - return - # Extract datetime strings from data attributes for pandas query since_dt_str = data.since_dt_str # noqa: F841 until_dt_str = data.until_dt_str # noqa: F841