Skip to content

Commit acf8a6a

Browse files
committed
Address reviews
1 parent b164477 commit acf8a6a

File tree

11 files changed

+144
-189
lines changed

11 files changed

+144
-189
lines changed

news/0.2.0.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Modmail 0.2.0 (2021-11-23)
2+
3+
---
4+
5+
### Features
6+
- qwerty (#89)

news/next/.gitkeep

Whitespace-only changes.

news/next/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
All your changelogs for upcoming release!

scripts/news/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
ERROR_MSG_PREFIX = "Oh no! 💥 💔 💥"
2-
31
__version__ = "0.0.1"

scripts/news/__main__.py

Lines changed: 18 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,104 +1,18 @@
1-
import os
2-
import subprocess
31
from collections import defaultdict
42
from datetime import datetime, timezone
5-
from pathlib import Path
63
from typing import Optional
74

85
import click
9-
import requests
10-
11-
from . import ERROR_MSG_PREFIX, __version__
12-
from .utils import (
13-
NotRequiredIf,
14-
err,
15-
get_metadata_from_file,
16-
get_project_meta,
17-
glob_fragments,
18-
load_toml_config,
19-
nonceify,
20-
out,
21-
render_fragments,
22-
)
23-
24-
25-
PR_ENDPOINT = "https://api.github.com/repos/discord-modmail/modmail/pulls/{number}"
26-
BAD_RESPONSE = {
27-
404: "Pull request not located! Please enter a valid number!",
28-
403: "Rate limit has been hit! Please try again later!",
29-
}
30-
31-
TEMPLATE = """
32-
# Please write your news content. When finished, save the file.
33-
# In order to abort, exit without saving.
34-
# Lines starting with \"#\" are ignored.
35-
36-
""".lstrip()
37-
NO_NEWS_PATH_ERROR = (
38-
f"{ERROR_MSG_PREFIX} `news/next/` doesn't exist.\nYou are either in the wrong directory while"
39-
" running this command (should be in the project root) or the path doesn't exist, if it "
40-
"doesn't exist please create it and run this command again :) Happy change-logging!"
41-
)
426

43-
CONFIG = load_toml_config()
44-
SECTIONS = [_type for _type, _ in CONFIG.get("types").items()]
45-
46-
47-
def save_news_fragment(ctx: click.Context, gh_pr: int, nonce: str, news_entry: str, news_type: str) -> None:
48-
"""Save received changelog data to a news file."""
49-
date = datetime.now(timezone.utc).strftime("%Y-%m-%d")
50-
path = Path(Path.cwd(), f"news/next/{news_type}/{date}.pr-{gh_pr}.{nonce}.md")
51-
if not path.parents[1].exists():
52-
err(NO_NEWS_PATH_ERROR, fg="blue")
53-
ctx.exit(1)
54-
elif not path.parents[0].exists():
55-
make_news_type_dir = click.confirm(
56-
f"Should I make the new type DIR for the news type at {path.parents[0]}"
57-
)
58-
if make_news_type_dir:
59-
path.parents[0].mkdir(exist_ok=True)
60-
elif path.exists():
61-
# The file exists
62-
err(f"{ERROR_MSG_PREFIX} {Path(os.path.relpath(path, start=Path.cwd()))} already exists")
63-
ctx.exit(1)
64-
65-
text = str(news_entry)
66-
with open(path, "wt", encoding="utf-8") as file:
67-
file.write(text)
68-
69-
# Add news fragment to git stage
70-
subprocess.run(["git", "add", "--force", path]).check_returncode()
71-
72-
out(
73-
f"All done! ✨ 🍰 ✨ Created news fragment at {Path(os.path.relpath(path, start=Path.cwd()))}"
74-
"\nYou are now ready for commit!"
75-
)
76-
77-
78-
def validate_pull_request_number(
79-
ctx: click.Context, _param: click.Parameter, value: Optional[int]
80-
) -> Optional[int]:
81-
"""Check if the given pull request number exists on the github repository."""
82-
r = requests.get(PR_ENDPOINT.format(number=value))
83-
if r.status_code == 403:
84-
if r.headers.get("X-RateLimit-Remaining") == "0":
85-
err(f"{ERROR_MSG_PREFIX} Ratelimit reached, please retry in a few minutes.")
86-
ctx.exit()
87-
err(f"{ERROR_MSG_PREFIX} Cannot access pull request.")
88-
ctx.exit()
89-
elif r.status_code in (404, 410):
90-
err(f"{ERROR_MSG_PREFIX} PR not found.")
91-
ctx.exit()
92-
elif r.status_code != 200:
93-
err(f"{ERROR_MSG_PREFIX} Error while fetching issue, retry again after sometime.")
94-
ctx.exit()
95-
96-
return value
7+
from . import __version__
8+
from .constants import *
9+
from .utils import *
9710

9811

9912
@click.group(context_settings=dict(help_option_names=["-h", "--help"]), invoke_without_command=True)
10013
@click.version_option(version=__version__)
101-
def cli_main() -> None:
14+
@click.pass_context
15+
def cli_main(ctx: click.Context) -> None:
10216
"""
10317
Modmail News 📜🤖.
10418
@@ -107,7 +21,9 @@ def cli_main() -> None:
10721
contributors and maintainers to work with news files (changelogs) by automating
10822
the process of generating, compiling and validating them!
10923
"""
110-
...
24+
if not ctx.args and not ctx.resilient_parsing and not ctx.command:
25+
click.echo(ctx.get_help())
26+
ctx.exit()
11127

11228

11329
@cli_main.command("add")
@@ -131,24 +47,19 @@ def cli_main() -> None:
13147
prompt=True,
13248
)
13349
@click.option(
134-
"--pr-number",
50+
"--pr",
13551
type=int,
13652
prompt=True,
13753
callback=validate_pull_request_number,
13854
)
13955
@click.pass_context
140-
def cli_add_news(ctx: click.Context, message: str, editor: str, type: str, pr_number: int) -> None:
56+
def cli_add_news(ctx: click.Context, message: str, editor: str, type: str, pr: int) -> None:
14157
"""Add a news entry 📜 to the current discord-modmail repo for your awesome change!"""
14258
if not message:
14359
message_notes = []
14460
while True:
14561
content = click.edit(
146-
(
147-
"# Please write your news content. When finished, save the file.\n"
148-
"# In order to abort, exit without saving.\n"
149-
"# Lines starting with '#' are ignored.\n"
150-
"\n".join(message_notes)
151-
),
62+
"\n".join((TEMPLATE, *message_notes)),
15263
editor=editor,
15364
extension="md",
15465
)
@@ -167,7 +78,7 @@ def cli_add_news(ctx: click.Context, message: str, editor: str, type: str, pr_nu
16778

16879
break
16980

170-
save_news_fragment(ctx, pr_number, nonceify(message), message, type)
81+
save_news_fragment(ctx, pr, nonceify(message), message, type)
17182

17283

17384
@cli_main.command("build")
@@ -192,7 +103,7 @@ def cli_build_news(ctx: click.Context, edit: Optional[bool], keep: bool) -> None
192103
for filename in filenames:
193104
if not filename.endswith(".md"):
194105
continue
195-
_file_metadata[filename] = get_metadata_from_file(Path(filename))
106+
_file_metadata[filename] = get_metadata_from_news(Path(filename))
196107

197108
# Group metadata according to news_type
198109
for path, fragment in _file_metadata.items():
@@ -201,28 +112,16 @@ def cli_build_news(ctx: click.Context, edit: Optional[bool], keep: bool) -> None
201112
fragment["path"] = path
202113
file_metadata[news_type].append(fragment)
203114

204-
template = CONFIG["core"].get("template")
205-
if not template:
206-
template = Path(Path.cwd(), "scripts/news/template.md.jinja")
207-
else:
208-
template = Path(Path.cwd(), f"scripts/news/{template}")
209-
210-
if not template.exists():
211-
err(
212-
f"{ERROR_MSG_PREFIX} Template at {template.relative_to(Path.cwd())} not found :(. Make sure "
213-
f"your path is relative to `scripts/news`!"
214-
)
215-
216115
name, version = get_project_meta()
217116
version_news = render_fragments(
218-
section_names=CONFIG["types"],
219-
template=template,
117+
sections=SECTIONS,
118+
template=TEMPLATE_FILE_PATH,
220119
metadata=file_metadata,
221120
wrap=True,
222121
version_data=(name, version),
223122
date=date,
224123
)
225-
news_path = Path(Path.cwd(), f"news/{version}.md")
124+
news_path = Path(REPO_ROOT, f"news/{version}.md")
226125

227126
with open(news_path, mode="w") as file:
228127
file.write(version_news)
@@ -233,10 +132,9 @@ def cli_build_news(ctx: click.Context, edit: Optional[bool], keep: bool) -> None
233132
click.edit(filename=str(news_path))
234133

235134
if not keep:
236-
files = Path(Path.cwd(), "scripts/news/next")
237-
for news_fragment in files.glob("*.md"):
135+
for news_fragment in NEWS_NEXT.glob("*/*.md"):
238136
os.remove(news_fragment)
239-
out("🍰 Cleared existing `scripts/news/next` news fragments!")
137+
out("🍰 Cleared existing `news/next` news fragments!")
240138

241139

242140
if __name__ == "__main__":

scripts/news/check_news_workflow/__main__.py

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,16 @@
11
import pathlib
22
import re
33
import sys
4-
import traceback
54
from typing import Tuple
65

76
import requests
8-
import tomli
97

108

119
NEWS_NEXT_DIR = "news/next/"
1210
SKIP_NEWS_LABEL = "skip changelog"
1311
GH_API_URL = "https://api.github.com/"
1412
HEADERS = {"accept": "application/vnd.github.v3+json"}
15-
16-
17-
def load_toml_config() -> dict:
18-
"""Load the news TOML configuration file and exit if found to be invalid."""
19-
config_path = pathlib.Path(pathlib.Path.cwd(), "scripts/news/config.toml")
20-
21-
try:
22-
with open(config_path, mode="r") as file:
23-
toml_dict = tomli.loads(file.read())
24-
except tomli.TOMLDecodeError as e:
25-
message = "Invalid news configuration at {0}\n{1}".format(
26-
config_path,
27-
"".join(traceback.format_exception_only(type(e), e)),
28-
)
29-
print(message)
30-
sys.exit(1)
31-
else:
32-
return toml_dict
13+
REPO_ORG_NAME = "discord-modmail/modmail"
3314

3415

3516
FILENAME_RE = re.compile(
@@ -48,7 +29,7 @@ def is_news_dir(filename: str) -> bool:
4829

4930
def main(pr: int) -> Tuple[str, bool]:
5031
"""Main function to check for a changelog entry."""
51-
r = requests.get(f"{GH_API_URL}repos/discord-modmail/modmail/pulls/{pr}/files", headers=HEADERS)
32+
r = requests.get(f"{GH_API_URL}repos/{REPO_ORG_NAME}/pulls/{pr}/files", headers=HEADERS)
5233
files_changed = r.json()
5334
in_next_dir = file_found = False
5435

@@ -64,7 +45,7 @@ def main(pr: int) -> Tuple[str, bool]:
6445
status = (f"News entry found in {NEWS_NEXT_DIR}", True)
6546
break
6647
else:
67-
_r = requests.get(f"{GH_API_URL}repos/discord-modmail/modmail/pulls/{pr}", headers=HEADERS)
48+
_r = requests.get(f"{GH_API_URL}repos/{REPO_ORG_NAME}/pulls/{pr}", headers=HEADERS)
6849
pr_data = _r.json()
6950
labels = [label["name"] for label in pr_data["labels"]]
7051
if SKIP_NEWS_LABEL in labels:

scripts/news/config.toml

Lines changed: 0 additions & 9 deletions
This file was deleted.

scripts/news/constants.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import os
2+
from pathlib import Path
3+
4+
import modmail
5+
6+
7+
PR_ENDPOINT = "https://api.github.com/repos/discord-modmail/modmail/pulls/{number}"
8+
BAD_RESPONSE = {
9+
404: "Pull request not located! Please enter a valid number!",
10+
403: "Rate limit has been hit! Please try again later!",
11+
}
12+
13+
TEMPLATE_FILE_PATH = Path(Path(__file__).parent, "template.md.jinja")
14+
REPO_ROOT = Path(modmail.__file__).parent.parent
15+
NEWS_NEXT = Path(REPO_ROOT, "news/next")
16+
17+
ERROR_MSG_PREFIX = "Oh no! 💥 💔 💥"
18+
TEMPLATE = """
19+
# Please write your news content. When finished, save the file.
20+
# In order to abort, exit without saving.
21+
# Lines starting with "#" are ignored.
22+
23+
""".lstrip()
24+
NO_NEWS_PATH_ERROR = (
25+
f"{ERROR_MSG_PREFIX} {Path(os.path.relpath(NEWS_NEXT, start=Path.cwd()))} doesn't exist, please create it"
26+
f" and run this command again :) Happy change-logging!"
27+
)
28+
29+
SECTIONS = {
30+
"feature": "Features",
31+
"trivial": "Trivial/Internal Changes",
32+
"improvement": "Improvements",
33+
"bugfix": "Bug Fixes",
34+
"doc": "Improved Documentation",
35+
"deprecation": "Deprecations",
36+
"breaking": "Breaking Changes",
37+
"internal": "Internal",
38+
}

scripts/news/template.md.jinja

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
---
1010

1111
{% for section, fragments in metadata.items() %}
12-
### {{ section_names[section] }}
12+
### {{ sections[section] }}
1313
{% for fragment in fragments %}
1414
- {{ fragment["news_entry"].strip("\n") }} (#{{ fragment["gh_pr"].split("-")[1] }})
1515
{% endfor %}

0 commit comments

Comments
 (0)