在 GitHub 中搜索已绕过分支保护的 PR

问题描述 投票:0回答:1

我们的一些 GitHub 用户可以选择“无需等待满足要求即可合并”。然而,这是不鼓励的,并且是为了紧急情况而存在的。我希望能够检测、搜索或检查 PR,看看是否选中了此复选框。

更具体地说,我想找到所有已“强制合并”的已关闭 PR,而无需等待项目内满足要求。

谢谢你

git github pull-request
1个回答
0
投票

此脚本检查合并 PR 的状态并查找强制合并。 现在它会检查合并提交和 PR 源分支上的最后一次提交。 它还检查状态检查检查运行。您可以更新脚本以删除不需要的检查。

import os
import logging
from github import Github

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger()

# Read GitHub token, organization, and repository name from env varibles
token = os.getenv("GITHUB_TOKEN")
owner = os.getenv("GITHUB_OWNER")
repo_name = os.getenv("GITHUB_REPO")

logger.info("GitHub token and repository details retrieved from environment variables.")

# Authenticate
g = Github(token)

def find_force_merged_prs(owner, repo_name):
    logger.info(f"Searching for force merged PRs in repository: {owner}/{repo_name}")
    repo = g.get_repo(f"{owner}/{repo_name}")
    closed_prs = repo.get_pulls(state="closed")
    force_merged_prs = []

    for pr in closed_prs:
        logger.info(f"Checking PR #{pr.number}: {pr.title}")

        if pr.merged_at:
            logger.info(f"PR #{pr.number} is merged. Checking commit statuses and check runs.")

            # Check both the merge commit and the last commit on the PR branch
            merge_commit_sha = pr.merge_commit_sha
            head_commit_sha = pr.head.sha

            # Function to check commit statuses and check runs for a given commit SHA
            def check_commit_status_and_runs(commit_sha):
                commit = repo.get_commit(commit_sha)

                # Check Commit Statuses
                combined_status = commit.get_combined_status()
                statuses = combined_status.statuses
                has_failed_statuses = any(
                    status.state in ["failure", "pending"] for status in statuses
                )

                # Log statuses
                if statuses:
                    logger.info(f"Found {len(statuses)} statuses for commit {commit_sha}")
                    for status in statuses:
                        logger.info(f"Status Context: {status.context}, State: {status.state}")
                else:
                    logger.info(f"No statuses found for commit {commit_sha}.")

                # Check Check Runs (GitHub Actions or other Checks API integrations)
                check_runs = commit.get_check_runs()
                has_failed_runs = any(
                    run.conclusion in ["failure", "cancelled", "timed_out"] or run.status == "in_progress"
                    for run in check_runs
                )

                # Log check runs
                if check_runs.totalCount > 0:
                    logger.info(f"Found {check_runs.totalCount} check runs for commit {commit_sha}")
                    for run in check_runs:
                        logger.info(f"Check Run: {run.name}, Status: {run.status}, Conclusion: {run.conclusion}")
                else:
                    logger.info(f"No check runs found for commit {commit_sha}.")

                # true if either statuses or check runs have failed or are pending
                return has_failed_statuses or has_failed_runs

            # Check the merge commit first, then fall back to the PR's head commit
            has_failed_or_pending_checks = check_commit_status_and_runs(merge_commit_sha)
            if not has_failed_or_pending_checks:
                logger.info(f"Falling back to checking last commit on PR branch for PR #{pr.number}.")
                has_failed_or_pending_checks = check_commit_status_and_runs(head_commit_sha)

            # Record the PR if there are failed or pending statuses or check runs
            if has_failed_or_pending_checks:
                logger.warning(f"PR #{pr.number} was force merged without all checks passing.")
                force_merged_prs.append(pr)
            else:
                logger.info(f"PR #{pr.number} passed all required checks before merging.")
        else:
            logger.info(f"PR #{pr.number} was closed but not merged.")

    logger.info("Completed search for force merged PRs.")
    return force_merged_prs

force_merged_prs = find_force_merged_prs(owner, repo_name)
logger.info("Force Merged PRs:")
for pr in force_merged_prs:
    logger.info(f"- PR #{pr.number}: {pr.title} (merged at {pr.merged_at})")
© www.soinside.com 2019 - 2024. All rights reserved.