From 964cb26130141847fd99ea961e8af3e976add0a7 Mon Sep 17 00:00:00 2001 From: Xi Xu Date: Mon, 17 Aug 2026 10:48:25 +0800 Subject: [PATCH] fix(ci): remove unusable PR automation --- .github/workflows/dependabot-auto-merge.yml | 201 -------------------- 1 file changed, 201 deletions(-) delete mode 100644 .github/workflows/dependabot-auto-merge.yml diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml deleted file mode 100644 index 239abad..0000000 --- a/.github/workflows/dependabot-auto-merge.yml +++ /dev/null @@ -1,201 +0,0 @@ -name: Dependabot Auto Merge - -on: - workflow_run: - workflows: - - "CodeQL" - - "Markdown" - - "Markdown Fix" - types: - - completed - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }} - cancel-in-progress: false - -permissions: - contents: write - pull-requests: write - checks: read - statuses: read - -jobs: - merge: - name: Auto-merge Dependabot PRs - if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - name: Merge Dependabot PRs when checks pass - uses: actions/github-script@v9 - with: - script: | - const owner = context.repo.owner; - const repo = context.repo.repo; - - const successfulCheckConclusions = new Set(["success", "skipped", "neutral"]); - const successfulStatusStates = new Set(["success"]); - const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); - - const latestBy = (items, keyOf, timeOf) => { - const latest = new Map(); - for (const item of items) { - const key = keyOf(item); - const itemTime = new Date(timeOf(item) || 0).getTime(); - const existing = latest.get(key); - const existingTime = existing ? new Date(timeOf(existing) || 0).getTime() : -1; - if (!existing || itemTime >= existingTime) { - latest.set(key, item); - } - } - return [...latest.values()]; - }; - - const findCandidatePulls = async () => { - const pulls = await github.paginate(github.rest.pulls.list, { - owner, - repo, - state: "open", - per_page: 100, - }); - - return pulls.filter((pr) => pr.user?.login === "dependabot[bot]"); - }; - - const getMergeablePullRequest = async (pull_number) => { - for (let attempt = 1; attempt <= 6; attempt += 1) { - const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number }); - if (pr.mergeable !== null) { - return pr; - } - core.info("PR #" + pull_number + " mergeability is still being computed; retry " + attempt + "/6."); - await wait(5000); - } - - const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number }); - return pr; - }; - - const getSignalState = async (sha) => { - const checkRuns = await github.paginate(github.rest.checks.listForRef, { - owner, - repo, - ref: sha, - per_page: 100, - }); - - const statuses = await github.paginate(github.rest.repos.listCommitStatusesForRef, { - owner, - repo, - ref: sha, - per_page: 100, - }); - - const latestChecks = latestBy( - checkRuns.filter((run) => run.name !== "Dependabot Auto Merge"), - (run) => (run.app?.slug || "unknown") + ":" + run.name, - (run) => run.completed_at || run.started_at || run.created_at, - ); - const latestStatuses = latestBy(statuses, (status) => status.context, (status) => status.updated_at || status.created_at); - - const pendingChecks = latestChecks.filter((run) => run.status !== "completed"); - const failedChecks = latestChecks.filter( - (run) => run.status === "completed" && !successfulCheckConclusions.has(String(run.conclusion || "").toLowerCase()), - ); - const failedStatuses = latestStatuses.filter((status) => !successfulStatusStates.has(String(status.state || "").toLowerCase())); - - return { - totalSignals: latestChecks.length + latestStatuses.length, - pendingChecks, - failedChecks, - failedStatuses, - }; - }; - - const { data: repository } = await github.rest.repos.get({ owner, repo }); - const mergeMethods = []; - if (repository.allow_merge_commit) mergeMethods.push("merge"); - if (repository.allow_squash_merge) mergeMethods.push("squash"); - if (repository.allow_rebase_merge) mergeMethods.push("rebase"); - - if (mergeMethods.length === 0) { - core.info("This repository has no enabled pull request merge methods."); - return; - } - - const pulls = await findCandidatePulls(); - if (pulls.length === 0) { - core.info("No open Dependabot PRs to evaluate."); - return; - } - - for (const candidate of pulls) { - const pull_number = candidate.number; - const pr = await getMergeablePullRequest(pull_number); - - if (pr.user?.login !== "dependabot[bot]") { - core.info("PR #" + pull_number + " is no longer a Dependabot PR."); - continue; - } - - if (pr.state !== "open" || pr.draft) { - core.info("PR #" + pull_number + " is not an open, ready PR."); - continue; - } - - if (pr.mergeable !== true) { - core.info("PR #" + pull_number + " is not currently mergeable."); - continue; - } - - const signalState = await getSignalState(pr.head.sha); - if (signalState.totalSignals === 0) { - core.info("PR #" + pull_number + " has no checks or statuses yet; skipping."); - continue; - } - - if (signalState.pendingChecks.length > 0) { - core.info("PR #" + pull_number + " still has pending checks: " + signalState.pendingChecks.map((run) => run.name).join(", ") + "."); - continue; - } - - if (signalState.failedChecks.length > 0 || signalState.failedStatuses.length > 0) { - const failedChecks = signalState.failedChecks.map((run) => run.name + "=" + run.conclusion).join(", "); - const failedStatuses = signalState.failedStatuses.map((status) => status.context + "=" + status.state).join(", "); - core.info("PR #" + pull_number + " is not green. Checks: " + (failedChecks || "none") + ". Statuses: " + (failedStatuses || "none") + "."); - continue; - } - - let merged = false; - let lastError = null; - for (const merge_method of mergeMethods) { - try { - await github.rest.pulls.merge({ owner, repo, pull_number, merge_method }); - core.info("Merged Dependabot PR #" + pull_number + " with " + merge_method + "."); - merged = true; - break; - } catch (error) { - lastError = error; - if (error.status === 403 || error.status === 405 || error.status === 409) { - core.info("Cannot merge PR #" + pull_number + " with " + merge_method + ": " + error.message); - continue; - } - throw error; - } - } - - if (!merged) { - core.info("PR #" + pull_number + " could not be merged: " + (lastError?.message || "unknown error") + "."); - continue; - } - - if (pr.head.repo?.full_name === owner + "/" + repo) { - try { - await github.rest.git.deleteRef({ owner, repo, ref: "heads/" + pr.head.ref }); - core.info("Deleted branch " + pr.head.ref + "."); - } catch (error) { - core.info("Could not delete branch " + pr.head.ref + ": " + error.message); - } - } - }