Skip to content
Open
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
7 changes: 7 additions & 0 deletions buildkite/pipeline_generator/pipeline_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from step import read_steps_from_job_dir, group_steps
from buildkite_step import convert_group_step_to_buildkite_step
from global_config import init_global_config, get_global_config
from utils_lib.git_utils import check_precommit_passed


class PipelineGenerator:
Expand All @@ -20,6 +21,12 @@ def __init__(
def generate(self):
global_config = get_global_config()

# Fail if pre-commit check has not passed on the PR
if global_config["pull_request"] and global_config["pull_request"] != "false":
check_precommit_passed(
global_config["commit"], global_config["github_repo_name"]
)

# Skip if changes are doc-only (unless RUN_ALL is set)
if global_config["docs_only_disable"] == "0" and not global_config["run_all"]:
if is_docs_only_change(global_config["list_file_diff"]):
Expand Down
63 changes: 63 additions & 0 deletions buildkite/pipeline_generator/utils_lib/git_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import subprocess
import os
import time
from typing import List, Optional
import requests

Expand Down Expand Up @@ -53,6 +54,68 @@ def get_list_file_diff(branch: str, merge_base_commit: Optional[str]) -> List[st
raise RuntimeError("Failed to determine merge base commit for git diff.")


def check_precommit_passed(commit: str, repo_name: str) -> None:
"""Poll until the pre-commit GitHub Actions check run completes, then fail if not successful.

Raises RuntimeError if the check fails, times out, or is not found.
"""
max_wait = 600
wait_interval = 30
elapsed = 0
api_url = f"https://api.github.com/repos/{repo_name}/commits/{commit}/check-runs"

while True:
response = requests.get(api_url)
response.raise_for_status()
check_runs = response.json().get("check_runs", [])
precommit_run = next(
(run for run in check_runs if run["name"] == "pre-commit"), None
)

if precommit_run and precommit_run["status"] == "completed":
conclusion = precommit_run["conclusion"]
if conclusion == "success":
print(f"pre-commit check passed on commit {commit}.")
return
subprocess.run(
[
"buildkite-agent",
"annotate",
f":x: pre-commit check has not passed on this PR (conclusion: {conclusion}). "
"Please fix pre-commit issues before running CI.",
"--style",
"error",
],
check=False,
)
raise RuntimeError(
f"pre-commit check failed on commit {commit} (conclusion: {conclusion})."
)

if elapsed >= max_wait:
subprocess.run(
[
"buildkite-agent",
"annotate",
":warning: Timed out waiting for pre-commit check to complete.",
"--style",
"warning",
],
check=False,
)
raise RuntimeError(
f"Timed out after {max_wait}s waiting for pre-commit check on commit {commit}."
)

status = precommit_run["status"] if precommit_run else "not found"
print(
f"pre-commit check is not yet complete (status: {status}). "
f"Waiting {wait_interval}s... ({elapsed}/{max_wait}s)"
)
time.sleep(wait_interval)
elapsed += wait_interval


def get_pr_labels(pull_request: str, repo_name: str) -> List[str]:
if not pull_request or pull_request == "false":
return []
Expand Down