您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically clicks the merge button on selected Dependabot PRs and "Done" button on the notification bar and shows status messages
当前为
// ==UserScript== // @name Auto Merge Dependabot PRs with Status and Selection // @namespace typpi.online // @version 1.6 // @description Automatically clicks the merge button on selected Dependabot PRs and "Done" button on the notification bar and shows status messages // @author Nick2bad4u // @match https://github.com/*/*/pulls // @grant none // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com // @license UnLicense // ==/UserScript== (function () { 'use strict'; let observer; let statusElement; let statusTimeout; function showStatus(message, isSuccess) { if (!statusElement) { statusElement = document.createElement('div'); statusElement.style.position = 'fixed'; statusElement.style.bottom = '10px'; statusElement.style.right = '10px'; statusElement.style.padding = '10px'; statusElement.style.color = 'white'; statusElement.style.zIndex = '1000'; document.body.appendChild(statusElement); } statusElement.textContent = message; statusElement.style.backgroundColor = isSuccess ? 'green' : 'red'; statusElement.style.display = 'block'; if (statusTimeout) { clearTimeout(statusTimeout); } statusTimeout = setTimeout(() => { statusElement.style.display = 'none'; }, 3000); } function checkAndMerge() { const selectedPRs = document.querySelectorAll('input[type="checkbox"].pr-checkbox:checked'); if (selectedPRs.length === 0) { showStatus('No PRs selected for merging', false); return; } selectedPRs.forEach((checkbox) => { const prElement = checkbox.closest('.js-issue-row'); const authorElement = prElement.querySelector('.opened-by a'); if (authorElement && /dependabot(\[bot\])?|Nick2bad4u/.test(authorElement.textContent.trim())) { setTimeout(() => { const mergeButton = prElement.querySelector( '.btn-group-merge .btn-primary, .merge-message .btn-primary, .merge-box-button .btn-primary, .merge-status-details .btn-primary', ); if (mergeButton && !mergeButton.disabled) { console.log('Merge button is enabled, clicking it'); mergeButton.click(); showStatus('Merge button clicked', true); } else { console.log('Merge button is disabled or not found'); showStatus('Merge button is disabled or not found', false); } }, 500); } else { console.log('PR is not created by dependabot'); showStatus('PR is not created by dependabot', false); } }); } function addUI() { const prList = document.querySelectorAll('.js-issue-row'); prList.forEach((pr) => { const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.classList.add('pr-checkbox'); pr.querySelector('.d-flex').prepend(checkbox); }); const mergeButton = document.createElement('button'); mergeButton.textContent = 'Merge Selected PRs'; mergeButton.style.position = 'fixed'; mergeButton.style.top = '10px'; mergeButton.style.right = '10px'; mergeButton.style.padding = '10px'; mergeButton.style.backgroundColor = 'blue'; mergeButton.style.color = 'white'; mergeButton.style.zIndex = '1000'; mergeButton.addEventListener('click', checkAndMerge); document.body.appendChild(mergeButton); } globalThis.addEventListener( 'load', function () { console.log('Page loaded'); const targetNode = document.querySelector('.js-navigation-container'); if (!targetNode) { console.log('Target node for observation not found'); showStatus('Target node for observation not found', false); return; } observer = new MutationObserver((mutationsList) => { for (const mutation of mutationsList) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { console.log('Relevant DOM mutation detected'); addUI(); break; } } }); observer.observe(targetNode, { childList: true, subtree: true, }); addUI(); }, false, ); })();