Spaces:
Sleeping
Sleeping
| """Open a GitHub PR against the website repo for an approved submission. | |
| The site owner still reviews and merges the PR by hand — this only removes | |
| the manual data-entry step of splicing a new object into the right | |
| src/data/*.js array. | |
| """ | |
| import base64 | |
| import os | |
| import requests | |
| import formatters | |
| from about import GITHUB_API, GITHUB_REPO | |
| def _headers() -> dict: | |
| token = os.environ["GITHUB_TOKEN"] | |
| return { | |
| "Authorization": f"Bearer {token}", | |
| "Accept": "application/vnd.github+json", | |
| "X-GitHub-Api-Version": "2022-11-28", | |
| } | |
| def _default_branch() -> str: | |
| resp = requests.get(f"{GITHUB_API}/repos/{GITHUB_REPO}", headers=_headers()) | |
| resp.raise_for_status() | |
| return resp.json()["default_branch"] | |
| def _get_file(path: str, ref: str) -> tuple[str, str]: | |
| """Return (content, sha) of a file at ref.""" | |
| resp = requests.get( | |
| f"{GITHUB_API}/repos/{GITHUB_REPO}/contents/{path}", | |
| headers=_headers(), | |
| params={"ref": ref}, | |
| ) | |
| resp.raise_for_status() | |
| data = resp.json() | |
| content = base64.b64decode(data["content"]).decode("utf-8") | |
| return content, data["sha"] | |
| def _create_branch(branch: str, from_sha: str) -> None: | |
| resp = requests.post( | |
| f"{GITHUB_API}/repos/{GITHUB_REPO}/git/refs", | |
| headers=_headers(), | |
| json={"ref": f"refs/heads/{branch}", "sha": from_sha}, | |
| ) | |
| resp.raise_for_status() | |
| def _branch_sha(branch: str) -> str: | |
| resp = requests.get( | |
| f"{GITHUB_API}/repos/{GITHUB_REPO}/git/ref/heads/{branch}", headers=_headers() | |
| ) | |
| resp.raise_for_status() | |
| return resp.json()["object"]["sha"] | |
| def _update_file(path: str, branch: str, new_content: str, sha: str, message: str) -> None: | |
| resp = requests.put( | |
| f"{GITHUB_API}/repos/{GITHUB_REPO}/contents/{path}", | |
| headers=_headers(), | |
| json={ | |
| "message": message, | |
| "content": base64.b64encode(new_content.encode("utf-8")).decode("ascii"), | |
| "sha": sha, | |
| "branch": branch, | |
| }, | |
| ) | |
| resp.raise_for_status() | |
| def _open_pr(branch: str, base: str, title: str, body: str) -> str: | |
| resp = requests.post( | |
| f"{GITHUB_API}/repos/{GITHUB_REPO}/pulls", | |
| headers=_headers(), | |
| json={"title": title, "head": branch, "base": base, "body": body}, | |
| ) | |
| resp.raise_for_status() | |
| return resp.json()["html_url"] | |
| def open_pr_for_submission(submission: dict, fields: dict) -> str: | |
| """Splice the approved entry into the right data file and open a PR. | |
| `submission` is the row from submissions.py; `fields` are the | |
| reviewer-filled values matching formatters.TARGETS[type_]'s schema. | |
| """ | |
| type_ = submission["type"] | |
| file_path = formatters.target_file(type_) | |
| entry_block = formatters.render_entry(type_, fields) | |
| org_id = fields.get("orgId") | |
| base = _default_branch() | |
| base_sha = _branch_sha(base) | |
| slug = fields.get("id", submission["id"][:8]) | |
| branch = f"add/{type_}-{slug}" | |
| _create_branch(branch, base_sha) | |
| content, sha = _get_file(file_path, branch) | |
| new_content = formatters.insert_entry(content, type_, entry_block, org_id) | |
| _update_file( | |
| file_path, branch, new_content, sha, | |
| message=f"Add {type_}: {fields.get('name') or fields.get('title') or slug}", | |
| ) | |
| title = f"Add {type_}: {fields.get('name') or fields.get('title') or slug}" | |
| body = ( | |
| f"Auto-generated from a huggingscience.co submission via the review Space.\n\n" | |
| f"- **Submission id:** `{submission['id']}`\n" | |
| f"- **Submitted at:** {submission['submitted_at']}\n" | |
| f"- **Source:** {submission['source']}\n\n" | |
| f"**Original description:**\n{submission['description']}\n" | |
| ) | |
| return _open_pr(branch, base, title, body) | |