181 lines
5.4 KiB
Python
181 lines
5.4 KiB
Python
#!/usr/bin/python3
|
|
"""
|
|
gen_release_notes.py
|
|
|
|
Retrieve release notes from the wiki, and generate
|
|
release notes adoc file for each release notes category in
|
|
modules/release-notes/pages/$category_name.adoc.
|
|
|
|
The generated category document is based on the matching
|
|
template $category_name.adoc.j2 in the templates directory.
|
|
If this template does not exists, it will use
|
|
default_category.adoc.j2 instead.
|
|
|
|
Requires:
|
|
python3-requests
|
|
python3-jinja2
|
|
|
|
dnf install -y python3-requests python3-jinja2
|
|
or
|
|
pip install -r requirements.txt
|
|
"""
|
|
|
|
import requests
|
|
import sys
|
|
import re
|
|
import jinja2
|
|
import logging
|
|
import urllib.parse
|
|
import os
|
|
import argparse
|
|
|
|
api_url = "https://fedoraproject.org/w/api.php"
|
|
|
|
|
|
def list_changes(release):
|
|
"""
|
|
Retrieve list of changes from ChangeAcceptedFxx wiki category
|
|
returns a list of wiki pages:
|
|
[{
|
|
"pageid": 12345,
|
|
"ns": 0,
|
|
"title": "Changes/MyAwesomeChange"
|
|
},...]
|
|
"""
|
|
params = {
|
|
"action": "query",
|
|
"list": "categorymembers",
|
|
"cmtitle": f"Category:ChangeAcceptedF{release}",
|
|
"cmlimit": 100,
|
|
"format": "json",
|
|
}
|
|
s = requests.Session()
|
|
req = s.get(url=api_url, params=params)
|
|
if req.status_code != 200:
|
|
logging.error(req.status_code)
|
|
return []
|
|
|
|
data = req.json()
|
|
return data["query"]["categorymembers"]
|
|
|
|
|
|
def get_change_info(pageid):
|
|
"""
|
|
Get change release notes and categories from the wiki page
|
|
returns a dict:
|
|
{
|
|
"title": MyAwesomeChange,
|
|
"categories": ["SystemWideChange", "SomeOtherCategory"],
|
|
"url": f"https://fedoraproject.org/wiki/Changes/MyAwesomeChange",
|
|
"release_notes": "You are awesome!",
|
|
}
|
|
"""
|
|
info = {}
|
|
s = requests.Session()
|
|
params = {
|
|
"action": "parse",
|
|
"pageid": pageid,
|
|
"prop": "categories|sections",
|
|
"format": "json",
|
|
}
|
|
req = s.get(url=api_url, params=params)
|
|
page_data = req.json()
|
|
rn_sid = None
|
|
info = {
|
|
"title": page["title"].replace("Changes/", ""),
|
|
"categories": [],
|
|
"url": f"https://fedoraproject.org/wiki/{urllib.parse.quote(page['title'])}",
|
|
"release_notes": "",
|
|
}
|
|
|
|
# Get categories
|
|
for category in page_data["parse"]["categories"]:
|
|
if category["*"].startswith("ChangeAccepted"):
|
|
continue
|
|
info["categories"].append(category["*"])
|
|
|
|
# Find release notes section
|
|
for section in page_data["parse"]["sections"]:
|
|
if section["line"] == "Release Notes":
|
|
rn_sid = section["index"]
|
|
break
|
|
if rn_sid:
|
|
# Fetch release notes text
|
|
params = {
|
|
"action": "parse",
|
|
"pageid": page["pageid"],
|
|
"section": rn_sid,
|
|
"prop": "wikitext",
|
|
"format": "json",
|
|
}
|
|
req = s.get(url=api_url, params=params)
|
|
section_data = req.json()
|
|
# Remove html comments and empty lines
|
|
info["release_notes"] = "\n".join(
|
|
re.sub(
|
|
"<!--.*?-->",
|
|
"",
|
|
section_data["parse"]["wikitext"]["*"],
|
|
flags=re.MULTILINE | re.DOTALL,
|
|
).splitlines()[1::]
|
|
).strip()
|
|
|
|
if not info["release_notes"]:
|
|
# If no release notes, fallback to summary
|
|
params = {
|
|
"action": "parse",
|
|
"pageid": page["pageid"],
|
|
"section": 2, # I expect the summary to be always the first section (after the title) of the page
|
|
"prop": "wikitext",
|
|
"format": "json",
|
|
}
|
|
req = s.get(url=api_url, params=params)
|
|
section_data = req.json()
|
|
# Remove html comments and empty lines
|
|
info["release_notes"] = "\n".join(
|
|
re.sub(
|
|
"<!--.*?-->",
|
|
"",
|
|
section_data["parse"]["wikitext"]["*"],
|
|
flags=re.MULTILINE | re.DOTALL,
|
|
).splitlines()[1::]
|
|
).strip()
|
|
|
|
return info
|
|
|
|
|
|
if __name__ == "__main__":
|
|
logging.basicConfig(level=logging.INFO)
|
|
abs_path = os.path.dirname(os.path.abspath(sys.argv[0]))
|
|
rn_per_cats = {}
|
|
parser = argparse.ArgumentParser(
|
|
description="Generate release notes from the ChangeAccepted wiki category"
|
|
)
|
|
parser.add_argument("release", help="Fedora Linux version")
|
|
args = parser.parse_args()
|
|
env = jinja2.Environment(loader=jinja2.FileSystemLoader(f"{abs_path}/templates"))
|
|
default_tpl = env.get_template("default_category.adoc.j2")
|
|
|
|
logging.info(f"Fetching changes for Fedora {args.release}...")
|
|
for page in list_changes(args.release):
|
|
change = get_change_info(page["pageid"])
|
|
logging.info(f"Processed change {change['title']}...")
|
|
for cat in change["categories"]:
|
|
if cat not in rn_per_cats:
|
|
rn_per_cats[cat] = []
|
|
rn_per_cats[cat].append(change)
|
|
|
|
for cat_name, changes in rn_per_cats.items():
|
|
logging.info(f"Generating {cat_name}.adoc...")
|
|
if os.path.exists(f"{abs_path}/templates/{cat_name}.adoc.j2"):
|
|
tpl = env.get_template(f"{cat_name}.adoc.j2")
|
|
else:
|
|
tpl = default_tpl
|
|
output_from_parsed_template = tpl.render(cat_name=cat_name, changes=changes)
|
|
|
|
with open(
|
|
f"{abs_path}/../modules/release-notes/pages/{cat_name}.adoc", "w"
|
|
) as fh:
|
|
fh.write(output_from_parsed_template)
|
|
|
|
logging.info("Completed.")
|