Repository: jerryjliu/gpt_index
File: llama-dev/llama_dev/release/changelog.py (Python)

Code before:
                    console.print(
                        f"Warning: Could not fetch details for PR #{pr_number}. {e}",
                        style="error",
                    )

        # Generate the markdown output
        changelog_text = f"<!--- generated changelog --->\n\n## [{date.today().strftime('%Y-%m-%d')}]"
        sorted_pkgs = sorted(package_prs.keys())
        for pkg in sorted_pkgs:
            changelog_text += f"\n\n### {pkg} [{package_versions[pkg]}]"
            prs = sorted(package_prs[pkg], key=lambda p: p["number"])
            for pr in prs:
                changelog_text += f"\n- {pr['title']} ([#{pr['number']}]({pr['url']}))"

        if dry_run:
            click.echo(changelog_text)
        else:
            with open(repo_root / "CHANGELOG.md", "r+") as f:
                content = f.read()
                f.seek(0)
                f.truncate()
                f.write(
                    content.replace("<!--- generated changelog --->", changelog_text)
                )

    except FileNotFoundError:
        click.ClickException(
            "Error: 'gh' command not found. "
            "Please ensure it's installed and in your PATH."
        )


Review comment (bug):
Since we're tolerant about `gh` failing, this is always swallowed by `_extract_pr_data()`, so let's get rid of it. If `gh` is totally missing from the user env, the error will be a generic `FileNotFound` but still visible in the standard output

Code after:
    """Update the content of the monorepo changelog file."""
    with open(repo_root / "CHANGELOG.md", "r+") as f:
        content = f.read()
        f.seek(0)
        f.truncate()
        f.write(content.replace(CHANGELOG_PLACEHOLDER, changelog_text))


@click.command(short_help="Generate the changelog from the previous release tag")
@click.option(
    "--dry-run",
    is_flag=True,
    help="Show the changelog text without altering the CHANGELOG.md file",
)
@click.pass_obj
def changelog(obj: dict, dry_run: bool) -> None:
    """
    Generate the changelog in markdown syntax.

    \b
    This command will:
        - get the list of GitHub PRs that happened since the last release tag
        - create a bullet list in Markdown syntax using the PR titles
        - group the changes per package, depending on the path that changed
    """  # noqa
    console = obj["console"]
    repo_root = obj["repo_root"]
    all_packages = find_all_packages(repo_root)
    latest_tag = _get_latest_tag()

    console.print(f"Generating changelog since tag '{latest_tag}'...")

    # Get commits since the last tag and extract PR numbers
    pr_numbers = _get_pr_numbers(latest_tag)
    if not pr_numbers:
        raise click.ClickException("No pull requests found since the last tag.")

    package_prs = {}
    package_versions = {}

    with click.progressbar(sorted(pr_numbers), label="Fetching PR details") as bar:
        for pr_number in bar:
            try:
                prs, versions = _extract_pr_data(repo_root, all_packages, pr_number)
                package_prs |= prs
                package_versions |= versions

            except Exception as e:
                console.print(
                    f"Warning: Could not fetch details for PR #{pr_number}. {e}",
                    style="error",