Files
palladum-lightning/.github/scripts/sync-rpc-cmds.py
ShahanaFarooqui 611e262099 script: Update sync RPC documentation script to check if the page was renderable for Readme
- ReadMe API v2 now requires category.uri instead of category.id.

- ReadMe v2 page responses include a renderable field indicating whether the document is MDX-compatible and can be rendered successfully. The script now checks this field and prints detailed compilation errors if rendering fails.
2025-12-18 10:27:15 +10:30

154 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
from urllib.parse import quote
from time import sleep
import requests
import re
from enum import Enum
# readme url
URL = "https://api.readme.com/v2/branches/stable"
CATEGORY_SLUG = "JSON-RPC API Reference"
class Action(Enum):
ADD = 'add'
UPDATE = 'update'
DELETE = 'delete'
def getListOfRPCDocs(headers):
response = requests.get(f"{URL}/categories/reference/{quote(CATEGORY_SLUG)}/pages", headers=headers)
if response.status_code == 200:
return response.json().get('data', [])
else:
return []
def check_renderable(response, action, title):
try:
data = response.json()
except Exception:
print("Non-JSON response:")
print(response.text)
return False
renderable = data.get("renderable")
if renderable is None:
# Some endpoints dont include renderable (e.g. DELETE)
return True
if not renderable.get("status", False):
print(f"\n❌ RENDER FAILED for {action.value.upper()} '{title}'")
print("Error :", renderable.get("error"))
print("Message:", renderable.get("message"))
return False
return True
def publishDoc(action, title, body, order, headers):
payload = {
"title": title,
"type": "basic",
"content": {
"body": body,
},
"category": {
"uri": f"/branches/1/categories/reference/{CATEGORY_SLUG}"
},
"hidden": False,
"order": order,
}
if action == Action.ADD:
payload["slug"] = title
response = requests.post(URL + "/reference", json=payload, headers=headers)
if response.status_code != 201:
print("❌ HTTP ERROR:", response.status_code)
print(response.text)
return
if not check_renderable(response, action, title):
raise RuntimeError(f"Renderable check failed for {title}")
print("✅ Created", title)
elif action == Action.UPDATE:
response = requests.patch(f"{URL}/reference/{title}", json=payload, headers=headers)
if response.status_code != 200:
print("❌ HTTP ERROR:", response.status_code)
print(response.text)
return
if not check_renderable(response, action, title):
raise RuntimeError(f"Renderable check failed for {title}")
print("✅ Updated", title)
elif action == Action.DELETE:
response = requests.delete(f"{URL}/reference/{title}", headers=headers)
if response.status_code != 204:
print("❌ DELETE FAILED:", title)
print(response.text)
else:
print("🗑️ Deleted", title)
else:
print("Invalid action")
def extract_rpc_commands(rst_content):
manpages_block = re.search(
r"\.\. block_start manpages(.*?)" r"\.\. block_end manpages",
rst_content,
re.DOTALL,
)
if manpages_block:
commands = re.findall(
r"\b([a-zA-Z0-9_-]+)" r"\s+<([^>]+)>\n", manpages_block.group(1)
)
return commands
return []
def main():
# define headers for requests
headers = {
"accept": "application/json",
"content-type": "application/json",
"Authorization": "Bearer " + os.environ.get("README_API_KEY"),
}
# path to the rst file from where we fetch all the RPC commands
path_to_rst = "doc/index.rst"
with open(path_to_rst, "r") as file:
rst_content = file.read()
commands_from_local = extract_rpc_commands(rst_content)
commands_from_readme = getListOfRPCDocs(headers)
# Compare local and server commands list to get the list of command to add or delete
commands_local_title = set(command[0] for command in commands_from_local)
commands_readme_title = set(command['title'] for command in commands_from_readme)
commands_to_delete = commands_readme_title - commands_local_title
commands_to_add = commands_local_title - commands_readme_title
for name in commands_to_delete:
publishDoc(Action.DELETE, name, "", 0, headers)
sleep(3)
if commands_from_local:
order = 0
for name, file in commands_from_local:
with open("doc/" + file) as f:
body = f.read()
publishDoc(Action.ADD if name in commands_to_add else Action.UPDATE, name, body, order, headers)
order = order + 1
sleep(3)
else:
print("No commands found in the Manpages block.")
if __name__ == "__main__":
main()