--- /dev/null
+import logging
+import sys
+from pathlib import Path
+from typing import Optional
+
+import httpx
+from github import Github
+from github.PullRequest import PullRequest
+from pydantic import BaseModel, BaseSettings, SecretStr, ValidationError
+
+github_api = "https://api.github.com"
+
+
+class Settings(BaseSettings):
+ github_repository: str
+ github_event_path: Path
+ github_event_name: Optional[str] = None
+ input_token: SecretStr
+ input_deploy_url: str
+
+
+class PartialGithubEventHeadCommit(BaseModel):
+ id: str
+
+
+class PartialGithubEventWorkflowRun(BaseModel):
+ head_commit: PartialGithubEventHeadCommit
+
+
+class PartialGithubEvent(BaseModel):
+ workflow_run: PartialGithubEventWorkflowRun
+
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.INFO)
+ settings = Settings()
+ logging.info(f"Using config: {settings.json()}")
+ g = Github(settings.input_token.get_secret_value())
+ repo = g.get_repo(settings.github_repository)
+ try:
+ event = PartialGithubEvent.parse_file(settings.github_event_path)
+ except ValidationError as e:
+ logging.error(f"Error parsing event file: {e.errors()}")
+ sys.exit(0)
+ use_pr: Optional[PullRequest] = None
+ for pr in repo.get_pulls():
+ if pr.head.sha == event.workflow_run.head_commit.id:
+ use_pr = pr
+ break
+ if not use_pr:
+ logging.error(
+ f"No PR found for hash: {event.workflow_run.head_commit.id}"
+ )
+ sys.exit(0)
+ github_headers = {
+ "Authorization": f"token {settings.input_token.get_secret_value()}"
+ }
+ url = f"{github_api}/repos/{settings.github_repository}/issues/{use_pr.number}/comments"
+ logging.info(f"Using comments URL: {url}")
+ response = httpx.post(
+ url,
+ headers=github_headers,
+ json={
+ "body": f"📝 Docs preview for commit {use_pr.head.sha} at: {settings.input_deploy_url}"
+ },
+ )
+ if not (200 <= response.status_code <= 300):
+ logging.error(f"Error posting comment: {response.text}")
+ sys.exit(1)
+ logging.info("Finished")
--- /dev/null
+import logging
+from datetime import datetime
+from pathlib import Path
+from typing import List, Optional
+
+import httpx
+from github import Github
+from github.NamedUser import NamedUser
+from pydantic import BaseModel, BaseSettings, SecretStr
+
+github_api = "https://api.github.com"
+netlify_api = "https://api.netlify.com"
+main_branch = "main"
+
+
+class Settings(BaseSettings):
+ input_token: SecretStr
+ github_repository: str
+ github_event_path: Path
+ github_event_name: Optional[str] = None
+
+
+class Artifact(BaseModel):
+ id: int
+ node_id: str
+ name: str
+ size_in_bytes: int
+ url: str
+ archive_download_url: str
+ expired: bool
+ created_at: datetime
+ updated_at: datetime
+
+
+class ArtifactResponse(BaseModel):
+ total_count: int
+ artifacts: List[Artifact]
+
+
+def get_message(commit: str) -> str:
+ return f"Docs preview for commit {commit} at"
+
+
+if __name__ == "__main__":
+ logging.basicConfig(level=logging.INFO)
+ settings = Settings()
+ logging.info(f"Using config: {settings.json()}")
+ g = Github(settings.input_token.get_secret_value())
+ repo = g.get_repo(settings.github_repository)
+ owner: NamedUser = repo.owner
+ headers = {"Authorization": f"token {settings.input_token.get_secret_value()}"}
+ prs = list(repo.get_pulls(state="open"))
+ response = httpx.get(
+ f"{github_api}/repos/{settings.github_repository}/actions/artifacts",
+ headers=headers,
+ )
+ data = response.json()
+ artifacts_response = ArtifactResponse.parse_obj(data)
+ for pr in prs:
+ logging.info("-----")
+ logging.info(f"Processing PR #{pr.number}: {pr.title}")
+ pr_comments = list(pr.get_issue_comments())
+ pr_commits = list(pr.get_commits())
+ last_commit = pr_commits[0]
+ for pr_commit in pr_commits:
+ if pr_commit.commit.author.date > last_commit.commit.author.date:
+ last_commit = pr_commit
+ commit = last_commit.commit.sha
+ logging.info(f"Last commit: {commit}")
+ message = get_message(commit)
+ notified = False
+ for pr_comment in pr_comments:
+ if message in pr_comment.body:
+ notified = True
+ logging.info(f"Docs preview was notified: {notified}")
+ if not notified:
+ artifact_name = f"docs-zip-{commit}"
+ use_artifact: Optional[Artifact] = None
+ for artifact in artifacts_response.artifacts:
+ if artifact.name == artifact_name:
+ use_artifact = artifact
+ break
+ if not use_artifact:
+ logging.info("Artifact not available")
+ else:
+ logging.info(f"Existing artifact: {use_artifact.name}")
+ response = httpx.post(
+ f"{github_api}/repos/{settings.github_repository}/actions/workflows/preview-docs.yml/dispatches",
+ headers=headers,
+ json={
+ "ref": main_branch,
+ "inputs": {
+ "pr": f"{pr.number}",
+ "name": artifact_name,
+ "commit": commit,
+ },
+ },
+ )
+ logging.info(
+ f"Trigger sent, response status: {response.status_code} - content: {response.content}"
+ )
+ logging.info("Finished")