Generate, display, and optionally edit release notes. Args: version: Version being released. tag_name: Tag name for the release. no_edit: Skip the interactive edit prompt. cwd: Directory to run git commands in (defaults to current). gh_repo: GitHub repo (
(
version: str,
tag_name: str,
no_edit: bool,
cwd: Path | None = None,
gh_repo: str = "crewAIInc/crewAI",
openai_client: OpenAI | None = None,
bump_already_done: bool = True,
)
| 932 | |
| 933 | |
| 934 | def _generate_release_notes( |
| 935 | version: str, |
| 936 | tag_name: str, |
| 937 | no_edit: bool, |
| 938 | cwd: Path | None = None, |
| 939 | gh_repo: str = "crewAIInc/crewAI", |
| 940 | openai_client: OpenAI | None = None, |
| 941 | bump_already_done: bool = True, |
| 942 | ) -> tuple[str, OpenAI, bool]: |
| 943 | """Generate, display, and optionally edit release notes. |
| 944 | |
| 945 | Args: |
| 946 | version: Version being released. |
| 947 | tag_name: Tag name for the release. |
| 948 | no_edit: Skip the interactive edit prompt. |
| 949 | cwd: Directory to run git commands in (defaults to current). |
| 950 | gh_repo: GitHub repo (``owner/name``) for resolving contributors. |
| 951 | openai_client: Reuse an existing OpenAI client if provided. |
| 952 | bump_already_done: True when the ``feat: bump versions to <version>`` |
| 953 | commit for the current release is already in history (the real |
| 954 | release path). False in previews where no bump exists yet — the |
| 955 | most recent bump commit is the *previous* version and must be |
| 956 | used as the range start. |
| 957 | |
| 958 | Returns: |
| 959 | Tuple of (release_notes, openai_client, is_prerelease). |
| 960 | """ |
| 961 | release_notes = f"Release {version}" |
| 962 | commits = "" |
| 963 | |
| 964 | with console.status("[cyan]Generating release notes..."): |
| 965 | try: |
| 966 | prev_bump_output = run_command( |
| 967 | [ |
| 968 | "git", |
| 969 | "log", |
| 970 | "--grep=^feat: bump versions to", |
| 971 | "--format=%H %s", |
| 972 | ], |
| 973 | cwd=cwd, |
| 974 | ) |
| 975 | bump_entries = [ |
| 976 | line for line in prev_bump_output.strip().split("\n") if line.strip() |
| 977 | ] |
| 978 | |
| 979 | is_stable = not _is_prerelease(version) |
| 980 | prev_commit = None |
| 981 | scan_entries = bump_entries[1:] if bump_already_done else bump_entries |
| 982 | for entry in scan_entries: |
| 983 | bump_ver = entry.split("feat: bump versions to", 1)[-1].strip() |
| 984 | if is_stable and _is_prerelease(bump_ver): |
| 985 | continue |
| 986 | prev_commit = entry.split()[0] |
| 987 | break |
| 988 | |
| 989 | if prev_commit: |
| 990 | commit_range = f"{prev_commit}..HEAD" |
| 991 | commits = run_command( |
no test coverage detected