Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions .github/scripts/analyze_flaky_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,28 @@ def list_workflow_runs(
while len(runs) < num_runs:
endpoint = (
f"/repos/{repo}/actions/workflows/{workflow_name}/runs"
f"?branch={branch}&status=completed&per_page={per_page}&page={page}"
f"?branch={branch}&event=push&status=completed"
f"&per_page={per_page}&page={page}"
)
data = gh_api(endpoint)
if not data or "workflow_runs" not in data:
break
batch = data["workflow_runs"]
if not batch:
raw_batch = data["workflow_runs"]
if not raw_batch:
break
# The API filters above are the primary boundary. Keep this fail-closed
# check as defense in depth before downloading executable-repository
# artifacts such as JUnit XML.
batch = [
run
for run in raw_batch
if run.get("event") == "push"
and run.get("head_branch") == branch
and (run.get("head_repository") or {}).get("full_name") == repo
]
runs.extend(batch)
page += 1
if len(batch) < per_page:
if len(raw_batch) < per_page:
break

return runs[:num_runs]
Expand Down
23 changes: 22 additions & 1 deletion .github/tdbot/tdbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ def get_pr_info(repo: str, pr_number: int) -> dict:
"--repo",
repo,
"--json",
"headRefName,baseRefName,author,title,url,labels,mergeable,reviewDecision",
"headRefName,baseRefName,author,title,url,labels,mergeable,reviewDecision,"
"isCrossRepository",
)
return json.loads(result.stdout)

Expand Down Expand Up @@ -113,6 +114,20 @@ def is_ghstack_pr(head_branch: str) -> bool:
return bool(re.match(r"^gh/[^/]+/\d+/head$", head_branch))


def reject_cross_repository_write(ctx: CommandContext, command: str) -> bool:
"""Reject commands that would push through the base repository remote."""
if ctx.pr_info.get("isCrossRepository") is False:
return False
post_comment(
ctx.repo,
ctx.pr_number,
f"`{command}` cannot safely update a branch from a fork. "
"Please perform the update in the fork and push it from an account "
"that controls that repository.",
)
return True


def find_ghstack_stack_top(repo: str, head_branch: str) -> int:
"""Return the PR number at the top of the ghstack stack containing *head_branch*.

Expand Down Expand Up @@ -279,6 +294,9 @@ def cmd_rebase(ctx: CommandContext, args: argparse.Namespace) -> None:
)
return

if reject_cross_repository_write(ctx, "rebase"):
return

if is_ghstack_pr(head):
_rebase_ghstack(ctx, args)
else:
Expand Down Expand Up @@ -380,6 +398,9 @@ def cmd_lint(ctx: CommandContext, _args: argparse.Namespace) -> None:
)
return

if reject_cross_repository_write(ctx, "lint"):
return

post_comment(
ctx.repo,
ctx.pr_number,
Expand Down
12 changes: 10 additions & 2 deletions .github/workflows/pr-label.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,16 @@ jobs:
**Note:** Matching is case-insensitive. Common variations (singular/plural) are supported.
COMMENT_EOF
sed -i 's/^ *//' /tmp/pr_comment.md
sed -i "s/REASON_PLACEHOLDER/$reason/" /tmp/pr_comment.md
sed -i "s|TITLE_PLACEHOLDER|$current_title|" /tmp/pr_comment.md
COMMENT_REASON="$reason" COMMENT_TITLE="$current_title" python3 - <<'PY'
import os
from pathlib import Path

path = Path("/tmp/pr_comment.md")
comment = path.read_text()
comment = comment.replace("REASON_PLACEHOLDER", os.environ["COMMENT_REASON"])
comment = comment.replace("TITLE_PLACEHOLDER", os.environ["COMMENT_TITLE"])
path.write_text(comment)
PY
gh pr comment "$PR_NUMBER" --repo "$REPO" --body-file /tmp/pr_comment.md
}

Expand Down
Loading