GitHub-userscripts
GitHub-userscripts copied to clipboard
Add support for sorting GitHub checks
When having hundreds of tests, it is difficult to switch to the failing ones.
Example:
My solution proposal: Sort the list of check outputs by "priority": failing, running, queued, cancelled. Therein by name. This is done with this PR (accepting that currently the status is more or less randomly sorted).
After applying this PR:
I also increase the "minor" version, because a new functionality is added with this PR.
Alternatively, a filter showing the failing tests only would be helpful, too.
Fixes https://github.com/sindresorhus/refined-github/issues/3791
After a merge, https://github.com/Mottie/GitHub-userscripts/wiki/GitHub-sort-content neesd to be updated.
I'd like to have sort by status and stort by title as at the file listing. However, I do not know (yet) how to do it.
When sorting for status, the second criteria should be the check title. When sorting for the check title, the second sort criteria should be the status
Hi @koppor!
I was thinking it might be better to add a filter to filter out unwanted checks.
My idea is to changing the "212 cancelled, 140 queued, 21 failing, 52 in progress, and 7 successful checks" into a sentence with 5 links. Click the link to filter out the check in the list below. What do you think? The only thing I don't know is what octicon
is being used for "queued" and "in progress", and if there are more than 5 states.
Try out this userscript... it filters the checks for you:
// ==UserScript==
// @name GitHub Filter PR checks
// @version 0.1.0
// @description A userscript that filters PR checks
// @license MIT
// @author Rob Garrison
// @namespace https://github.com/Mottie
// @include https://github.com/*
// @run-at document-idle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_addStyle
// @require https://greasyfork.org/scripts/28721-mutations/code/mutations.js?version=878498
// @require https://greasyfork.org/scripts/398877-utils-js/code/utilsjs.js?version=877686
// @icon https://github.githubassets.com/pinned-octocat.svg
// ==/UserScript==
/* global $ $$ on off debounce */
(() => {
"use strict";
GM_addStyle(`
.status-meta .is-visible {}
.status-meta .is-hidden { text-decoration: line-through; }
`);
const defaultTypes = {
cancelled: {
icon: "octicon-stop",
isHidden: false
},
errored: {
icon: "octicon-x",
text: "error",
isHidden: false
},
expected: {
icon: "octicon-dot-fill",
text: "expected",
isHidden: false,
},
failing: {
icon: "octicon-x",
text: "failing",
isHidden: false
},
// Found in https://github.com/ruby/ruby/pull/3845
neutral: {
icon: "octicon-square-fill",
isHidden: false
},
pending: {
icon: "octicon-dot-fill",
text: "pending",
isHidden: false,
},
progress: {
icon: "octicon-dot-fill",
text: "in progress",
isHidden: false
},
queued: {
icon: "octicon-dot-fill",
text: "queued",
isHidden: false
},
successful: {
icon: "octicon-check",
isHidden: false
}
};
const types = Object.assign({}, defaultTypes, GM_getValue("ghfc", {}));
const metaRegexp = /(?:,|\s*and)\s*/;
const typeKeys = Object.keys(types);
const setVisibility = block => {
$$(".merge-status-item", block).forEach(row => {
const svgClass = $(".merge-status-icon .octicon", row)?.getAttribute("class") || "---";
const rowType = typeKeys.find(key => {
const type = types[key];
const matchingIcon = svgClass.includes(types[key].icon);
// only a few icons are unique
if (matchingIcon && type.text) {
return (row.textContent || "").toLowerCase().includes(type.text);
}
return matchingIcon;
});
const isHidden = types[rowType]?.isHidden;
if (rowType && row.classList.contains("d-none") !== isHidden) {
row.classList.toggle("d-none", isHidden);
}
});
};
const toggleVisibility = event => {
const target = event.target;
if (target.classList.contains("ghfc")) {
event.preventDefault();
event.stopPropagation();
const type = target.dataset.type;
const isHidden = !types[type].isHidden;
types[type].isHidden = isHidden;
target.className = `ghfc ${isHidden ? "is-hidden" : "is-visible"}`;
GM_setValue("ghfc", types);
setVisibility();
}
};
const createLinks = block => {
const meta = $(".status-meta", block);
if (!$("a", meta)) {
const links = meta.textContent.trim().split(metaRegexp).filter(t => t);
// Don't add clickable links if only 1 type is visible
if (links.length > 1) {
const last = links.length - 2;
// ## cancelled, ## queed, ## failing, ## in progress, ## neutral, and ##
// successful checks
meta.innerHTML = links.reduce((html, text, index) => {
const separator = index === last ? " and " : index > last ? "" : ", ";
const isType = typeKeys.find(type => text.includes(type));
if (isType) {
const isHidden = types[isType].isHidden;
html.push(`
<a
href="#"
data-type="${isType}"
aria-label="${isHidden ? "hidden" : "visible"}"
class="ghfc ${isHidden ? "is-hidden" : "is-visible"}"
>${text}</a>${separator}`);
}
return html;
}, []).join("");
}
}
};
// At least 3 branch-action-item blocks: reviewers, checks & merge state
const getChecksBlock = () => $$(".branch-action-item").find(block =>
$(".statuses-toggle-opened", block)?.textContent?.includes("checks")
);
function init() {
if (
location.pathname.includes("/pull") &&
$(".mergeability-details .status-meta")
) {
const block = getChecksBlock();
if (block) {
createLinks(block);
off(block, "click", toggleVisibility);
on(block, "click", toggleVisibility);
setVisibility(block);
}
}
}
on(document, "ghmo:updatable ghmo:container", debounce(init));
init();
})();
This one (adapted on Mottie's above) focuses on a certain selection at a time: https://gist.github.com/turadg/a6871cafba99d6b3fc281f407cd64e55