Red 3.5.5 - Changelog (#6249)

Co-authored-by: Michael Oliveira <34169552+Flame442@users.noreply.github.com>
This commit is contained in:
Jakub Kuczys 2023-09-14 21:50:17 +02:00 committed by GitHub
parent 4d4cb14725
commit 56377b0596
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 135 additions and 54 deletions

View File

@ -1,5 +1,38 @@
.. Red changelogs .. Red changelogs
Redbot 3.5.5 (2023-08-14)
=========================
| Thanks to all these amazing people that contributed to this release:
| :ghuser:`Flame442`, :ghuser:`Jackenmen`, :ghuser:`karlsbjorn`, :ghuser:`Kreusada`, :ghuser:`ltzmax`, :ghuser:`palmtree5`
End-user changelog
------------------
Changes
*******
- **Core - Dependencies** - Red's dependencies have been bumped (:issue:`6248`)
- **Cogs - Downloader** - Cogs in the ``[p]cog list`` command are now listed alphabetically (:issue:`6214`, :issue:`6215`)
Fixes
*****
- **Core - Bot Commands** - Fixed handling of an edge case in the ``[p]diagnoseissues`` command that involved commands without a cog (:issue:`6237`)
- **Core - Bot Commands** - Fixed the formatting of nested result lists in the ``[p]diagnoseissues`` command (:issue:`6238`)
- **Cogs - Mod** - Fixed the formatting of the help description for the ``[p]ban``, ``[p]kick``, and ``[p]tempban`` commands (:issue:`6245`)
- |cool| **Cogs - Streams** - Updated the implementation of Twitch streams to no longer use the "Get Users Follows" endpoint that was deprecated in February 2023 (:issue:`6246`, :issue:`6247`)
Documentation changes
---------------------
Changes
*******
- Updated Python version in ``pyenv`` instructions (:issue:`6241`)
----
Redbot 3.5.4 (2023-08-12) Redbot 3.5.4 (2023-08-12)
========================= =========================

View File

@ -12,9 +12,10 @@ import re
import shlex import shlex
import subprocess import subprocess
import time import time
import urllib.parse
import webbrowser import webbrowser
from collections import defaultdict from collections import defaultdict
from typing import Dict, List, Optional from typing import Dict, List, Optional, Tuple
import click import click
import requests import requests
@ -29,7 +30,7 @@ class ReleaseType(enum.Enum):
MAINTENANCE = 3 MAINTENANCE = 3
HOTFIX = 4 HOTFIX = 4
def __str__(self) -> None: def __str__(self) -> str:
return f"{self.name.lower()} release" return f"{self.name.lower()} release"
@classmethod @classmethod
@ -105,9 +106,7 @@ query getAllTagCommits {
nodes { nodes {
name name
target { target {
... on Commit { commitResourcePath
oid
}
} }
} }
} }
@ -144,6 +143,27 @@ query getCommitHistory($refQualifiedName: String!, $after: String) {
} }
} }
""" """
GET_LAST_ISSUE_NUMBER_QUERY = """
query getLastIssueNumber {
repository(owner: "Cog-Creators", name: "Red-DiscordBot") {
discussions(orderBy: {field: CREATED_AT, direction: DESC}, first: 1) {
nodes {
number
}
}
issues(orderBy: {field: CREATED_AT, direction: DESC}, first: 1) {
nodes {
number
}
}
pullRequests(orderBy: {field: CREATED_AT, direction: DESC}, first: 1) {
nodes {
number
}
}
}
}
"""
GH_URL = "https://github.com/Cog-Creators/Red-DiscordBot" GH_URL = "https://github.com/Cog-Creators/Red-DiscordBot"
LINKIFY_ISSUE_REFS_RE = re.compile(r"#(\d+)") LINKIFY_ISSUE_REFS_RE = re.compile(r"#(\d+)")
@ -228,11 +248,11 @@ def get_git_config_value(key: str) -> str:
return "" return ""
def set_git_config_value(key: str, value: str) -> str: def set_git_config_value(key: str, value: str) -> None:
subprocess.check_call(("git", "config", "--local", f"red-release-helper.{key}", value)) subprocess.check_call(("git", "config", "--local", f"red-release-helper.{key}", value))
def wipe_git_config_values() -> str: def wipe_git_config_values() -> None:
try: try:
subprocess.check_output( subprocess.check_output(
("git", "config", "--local", "--remove-section", "red-release-helper") ("git", "config", "--local", "--remove-section", "red-release-helper")
@ -304,7 +324,7 @@ def set_release_stage(stage: ReleaseStage) -> None:
@click.group(invoke_without_command=True) @click.group(invoke_without_command=True)
@click.option("--continue", "abort", flag_value=False, default=None) @click.option("--continue", "abort", flag_value=False, default=None)
@click.option("--abort", "abort", flag_value=True, default=None) @click.option("--abort", "abort", flag_value=True, default=None)
def cli(*, abort: bool = None): def cli(*, abort: Optional[bool] = None):
"""Red's release helper, guiding you through the whole process!""" """Red's release helper, guiding you through the whole process!"""
stage = get_release_stage() stage = get_release_stage()
if abort is True: if abort is True:
@ -516,40 +536,46 @@ def create_changelog(release_type: ReleaseType, version: str) -> None:
else: else:
changelog_branch = f"V3/changelogs/{version}" changelog_branch = f"V3/changelogs/{version}"
subprocess.check_call(("git", "fetch", GH_URL)) subprocess.check_call(("git", "fetch", GH_URL))
try: try:
subprocess.check_call(("git", "checkout", "-b", changelog_branch, "FETCH_HEAD")) subprocess.check_call(("git", "checkout", "-b", changelog_branch, "FETCH_HEAD"))
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
rich.print() rich.print()
if click.confirm( if click.confirm(
f"It seems that {changelog_branch} branch already exists, do you want to use it?" f"It seems that {changelog_branch} branch already exists, do you want to use it?"
): ):
subprocess.check_call(("git", "checkout", changelog_branch)) subprocess.check_call(("git", "checkout", changelog_branch))
elif not click.confirm("Do you want to use a different branch?"): elif not click.confirm("Do you want to use a different branch?"):
raise click.ClickException("Can't continue without a changelog branch...") raise click.ClickException("Can't continue without a changelog branch...")
elif click.confirm("Do you want to create a new branch?"): elif click.confirm("Do you want to create a new branch?"):
while True: while True:
changelog_branch = click.prompt("Input the name of the new branch") changelog_branch = click.prompt("Input the name of the new branch")
try: try:
subprocess.check_call( subprocess.check_call(
("git", "checkout", "-b", changelog_branch, "FETCH_HEAD") ("git", "checkout", "-b", changelog_branch, "FETCH_HEAD")
) )
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
continue continue
else: else:
break break
else: else:
while True: while True:
changelog_branch = click.prompt("Input the name of the branch to check out") changelog_branch = click.prompt("Input the name of the branch to check out")
try: try:
subprocess.check_call(("git", "checkout", changelog_branch)) subprocess.check_call(("git", "checkout", changelog_branch))
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
continue continue
else: else:
break break
set_changelog_branch(changelog_branch) set_changelog_branch(changelog_branch)
set_release_stage(ReleaseStage.CHANGELOG_BRANCH_EXISTS) set_release_stage(ReleaseStage.CHANGELOG_BRANCH_EXISTS)
title = f"Red {version} - Changelog"
commands = [
("git", "add", "."),
("git", "commit", "-m", title),
("git", "push", "-u", GH_URL, f"{changelog_branch}:{changelog_branch}"),
]
if get_release_stage() < ReleaseStage.CHANGELOG_COMMITTED: if get_release_stage() < ReleaseStage.CHANGELOG_COMMITTED:
rich.print( rich.print(
"\n:pencil: At this point, you should have an up-to-date milestone" "\n:pencil: At this point, you should have an up-to-date milestone"
@ -578,11 +604,6 @@ def create_changelog(release_type: ReleaseType, version: str) -> None:
if option == "4": if option == "4":
break break
commands = [
("git", "add", "."),
("git", "commit", "-m", f"Red {version} - Changelog"),
("git", "push", "-u", GH_URL, f"{changelog_branch}:{changelog_branch}"),
]
print( print(
"Do you want to commit everything from repo's working tree and push it?" "Do you want to commit everything from repo's working tree and push it?"
" The following commands will run:" " The following commands will run:"
@ -596,10 +617,37 @@ def create_changelog(release_type: ReleaseType, version: str) -> None:
else: else:
print("Okay, please open a changelog PR manually then.") print("Okay, please open a changelog PR manually then.")
if get_release_stage() is ReleaseStage.CHANGELOG_COMMITTED: if get_release_stage() is ReleaseStage.CHANGELOG_COMMITTED:
token = get_github_token()
resp = requests.post(
"https://api.github.com/graphql",
json={"query": GET_LAST_ISSUE_NUMBER_QUERY},
headers={"Authorization": f"Bearer {token}"},
)
next_issue_number = (
max(
next(iter(data["nodes"]), {"number": 0})["number"]
for data in resp.json()["data"]["repository"].values()
)
+ 1
)
docs_preview_url = (
f"https://red-discordbot--{next_issue_number}.org.readthedocs.build"
f"/en/{next_issue_number}/changelog.html"
)
subprocess.check_call(commands[2]) subprocess.check_call(commands[2])
query = {
"expand": "1",
"milestone": version,
"labels": "Type: Feature,Changelog Entry: Skipped",
"title": title,
"body": (
"### Description of the changes\n\n"
f"The PR for Red {version} changelog.\n\n"
f"Docs preview: {docs_preview_url}"
),
}
pr_url = ( pr_url = (
f"{GH_URL}/compare/V3/develop...{changelog_branch}" f"{GH_URL}/compare/V3/develop...{changelog_branch}?{urllib.parse.urlencode(query)}"
f"?expand=1&milestone={version}&labels=Type:+Feature"
) )
print(f"Create new PR: {pr_url}") print(f"Create new PR: {pr_url}")
webbrowser.open_new_tab(pr_url) webbrowser.open_new_tab(pr_url)
@ -782,11 +830,11 @@ STEPS = (
@cli.command(name="unreleased") @cli.command(name="unreleased")
@click.argument("version") @click.argument("version")
@click.argument("base_branch") @click.argument("base_branch")
def cli_unreleased(version: str, base_branch: str) -> int: def cli_unreleased(version: str, base_branch: str) -> None:
show_unreleased_commits(version, base_branch) show_unreleased_commits(version, base_branch)
def show_unreleased_commits(version: str, base_branch: str) -> int: def show_unreleased_commits(version: str, base_branch: str) -> None:
token = get_github_token() token = get_github_token()
resp = requests.post( resp = requests.post(
@ -796,7 +844,8 @@ def show_unreleased_commits(version: str, base_branch: str) -> int:
) )
json = resp.json() json = resp.json()
tag_commits = { tag_commits = {
node["target"]["oid"]: node["name"] for node in json["data"]["repository"]["refs"]["nodes"] node["target"]["commitResourcePath"].rsplit("/", 1)[-1]: node["name"]
for node in json["data"]["repository"]["refs"]["nodes"]
} }
after = None after = None
@ -868,7 +917,7 @@ def cli_milestone(version: str) -> None:
def view_milestone_issues(version: str) -> None: def view_milestone_issues(version: str) -> None:
issue_views = [] issue_views: List[str] = []
for issue_type in ("pr", "issue"): for issue_type in ("pr", "issue"):
for number in subprocess.check_output( for number in subprocess.check_output(
( (
@ -916,8 +965,8 @@ def get_contributors(version: str, *, show_not_merged: bool = False) -> None:
def _get_contributors(version: str, *, show_not_merged: bool = False) -> List[str]: def _get_contributors(version: str, *, show_not_merged: bool = False) -> List[str]:
after = None after = None
has_next_page = True has_next_page = True
authors = {} authors: Dict[str, List[Tuple[int, str]]] = {}
reviewers = {} reviewers: Dict[str, List[Tuple[int, str]]] = {}
token = get_github_token() token = get_github_token()
states = ["MERGED"] states = ["MERGED"]
if show_not_merged: if show_not_merged:
@ -940,7 +989,6 @@ def _get_contributors(version: str, *, show_not_merged: bool = False) -> List[st
milestone_data = json["data"]["repository"]["milestones"]["nodes"][0] milestone_data = json["data"]["repository"]["milestones"]["nodes"][0]
except IndexError: except IndexError:
raise click.ClickException("Given milestone couldn't have been found.") raise click.ClickException("Given milestone couldn't have been found.")
milestone_title = milestone_data["title"]
pull_requests = milestone_data["pullRequests"] pull_requests = milestone_data["pullRequests"]
nodes = pull_requests["nodes"] nodes = pull_requests["nodes"]
for pr_node in nodes: for pr_node in nodes: