Compare commits

...

2 commits

Author SHA1 Message Date
eeb290586b
Updated RH_jira_bz_linker
- Isolated function
- updated namespace
2021-07-08 17:36:07 +03:00
87261d33a0
github list pr script cleanup and ui changes.
- Isolated in a function
 - changed namespace
 - updated description
 - added PR number
 - list is more concise
 - removed open button. Clicing on an item will open PR in new tab
2021-07-08 17:33:23 +03:00
2 changed files with 125 additions and 109 deletions

View file

@ -1,67 +1,69 @@
// ==UserScript== // ==UserScript==
// @name RedHat jira BZ Linker // @name RedHat jira BZ Linker
// @version 0.0.1 // @version 0.0.1
// @namespace http://arantius.com/misc/greasemonkey/ // @namespace https://git.sagidayan.com/sagi/greasemonkey-scripts
// @author Sagi Dayan // @author Sagi Dayan
// @description Adds BZ links in (RedHat) Jira when needed // @description Adds BZ links in (RedHat) Jira when needed
// @match https://issues.redhat.com/* // @match https://issues.redhat.com/*
// ==/UserScript== // ==/UserScript==
// Constants (function () {
const LOG_TAG = '[BZ-LINKER]'; // Constants
const summaryRegExp = new RegExp(/\[([0-9]+)\]/); const LOG_TAG = '[BZ-LINKER]';
const summaryRegExp = new RegExp(/\[([0-9]+)\]/);
// Entry point - observe DOM changes - and search for unlinked jira tickets // Entry point - observe DOM changes - and search for unlinked jira tickets
var observer = new MutationObserver(update); var observer = new MutationObserver(update);
observer.observe(document.body, { childList: true, characterData: true, subtree: true }); observer.observe(document.body, { childList: true, characterData: true, subtree: true });
// adds a tag prefix to logs for easy filters // adds a tag prefix to logs for easy filters
function log(...args) { function log(...args) {
const msg = args.reduce((msg, data) => { const msg = args.reduce((msg, data) => {
return `${msg} ${data}`; return `${msg} ${data}`;
}, LOG_TAG); }, LOG_TAG);
console.log(msg); console.log(msg);
} }
// When DOM changes - check for new unlinked issues // When DOM changes - check for new unlinked issues
function update() { function update() {
const issues = filterAndInflate([...document.getElementsByClassName("issuerow")]); const issues = filterAndInflate([...document.getElementsByClassName("issuerow")]);
if (issues.length) log(`Found #${issues.length} new unlinked issues. Linking...`); if (issues.length) log(`Found #${issues.length} new unlinked issues. Linking...`);
issues.forEach(issue => { issues.forEach(issue => {
const issueId = issue.bzId; const issueId = issue.bzId;
if (issueId) { if (issueId) {
const link = document.createElement('a'); const link = document.createElement('a');
const p = document.createElement('p'); const p = document.createElement('p');
link.href = `https://bugzilla.redhat.com/show_bug.cgi?id=${issueId}`; link.href = `https://bugzilla.redhat.com/show_bug.cgi?id=${issueId}`;
link.classList = ['issue-link']; link.classList = ['issue-link'];
link.target = '_blank'; link.target = '_blank';
link.innerHTML = `🐞 Bugzilla Bug: ${issueId} 🐞`; link.innerHTML = `🐞 Bugzilla Bug: ${issueId} 🐞`;
p.style = 'margin-top:10px;'; p.style = 'margin-top:10px;';
p.append(link); p.append(link);
issue.summaryElm.append(p); issue.summaryElm.append(p);
}
issue.touched = true;
});
}
// Returns only rows (TR tags) that are not linked and are BZ bugs
function filterAndInflate(rows) {
return rows.filter(r => {
if (r.tagName === 'TR' && !r.touched) {
const summary = [...r.children].reduce((prev, child) => {
if (prev) return prev;
if (child.getAttribute('data-field-id') === 'summary'
|| child.className.indexOf('summary') != -1) {
r.summaryElm = child;
return child.innerHTML;
}
}, null)
if (!summary) return false;
const bzId = summary.match(summaryRegExp);
if (bzId) {
r.bzId = bzId[1];
return true;
} }
} issue.touched = true;
return false; });
}) }
} // Returns only rows (TR tags) that are not linked and are BZ bugs
function filterAndInflate(rows) {
return rows.filter(r => {
if (r.tagName === 'TR' && !r.touched) {
const summary = [...r.children].reduce((prev, child) => {
if (prev) return prev;
if (child.getAttribute('data-field-id') === 'summary'
|| child.className.indexOf('summary') != -1) {
r.summaryElm = child;
return child.innerHTML;
}
}, null)
if (!summary) return false;
const bzId = summary.match(summaryRegExp);
if (bzId) {
r.bzId = bzId[1];
return true;
}
}
return false;
})
}
})();

View file

@ -1,74 +1,88 @@
// ==UserScript== // ==UserScript==
// @name GitHub - list own PRs in a repository // @name GitHub - list own PRs in a repository
// @description A brief description of your script // @description List Your own (open) PRs in a repo with CI state for easy navigation
// @namespace http://arantius.com/misc/greasemonkey/ // @namespace https://git.sagidayan.com/sagi/greasemonkey-scripts
// @author Sagi Dayan // @author Sagi Dayan
// @match https://github.com/* // @match https://github.com/*
// @version 1.0 // @version 1.0
// ==/UserScript== // ==/UserScript==
// Update These (function () {
const GITHUB_AUTH = ''; // https://github.com/settings/tokens // Update These
const GITHUB_USERNAME = ''; const GITHUB_AUTH = '';
// const GITHUB_USERNAME = '';
//
let currentRepo = '';
let currentRepo = ''; // fetch my prs
async function getPRs() {
const response = await fetch("https://api.github.com/graphql", {
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": `token ${GITHUB_AUTH}`
},
"body": "{\"query\":\"{\\n user(login: \\\"" + GITHUB_USERNAME + "\\\") {\\n pullRequests(first: 100, states: OPEN, baseRefName:\\\"master\\\") {\\n totalCount\\n nodes {\\n createdAt\\n number\\n title\\n mergeable\\n url\\n commits(last:1) {\\n nodes {\\n commit {\\n statusCheckRollup{\\n state\\n }\\n }\\n }\\n }\\n baseRefName\\n headRefName\\n repository{\\n nameWithOwner\\n }\\n }\\n pageInfo {\\n hasNextPage\\n endCursor\\n }\\n }\\n }\\n}\"}"
});
const payload = await response.json();
const prs = payload.data.user.pullRequests.nodes.filter(pr => {
return pr.repository.nameWithOwner === currentRepo;
});
// fetch my prs const main = document.getElementsByTagName('main')[0];
async function getPRs() { if (!main) return;
const response = await fetch("https://api.github.com/graphql", { prs.forEach(pr => {
"method": "POST", // Check if element Exists - if it does, remove and add updated one.
"headers": { const prItem = document.getElementById(generatePrItemId(pr.number));
"Content-Type": "application/json", if (prItem) {
"Authorization": `token ${GITHUB_AUTH}` console.log('Item Found', prItem.id);
}, main.removeChild(prItem);
"body": "{\"query\":\"{\\n user(login: \\\"" + GITHUB_USERNAME + "\\\") {\\n pullRequests(first: 100, states: OPEN, baseRefName:\\\"master\\\") {\\n totalCount\\n nodes {\\n createdAt\\n number\\n title\\n mergeable\\n url\\n commits(last:1) {\\n nodes {\\n commit {\\n statusCheckRollup{\\n state\\n }\\n }\\n }\\n }\\n baseRefName\\n headRefName\\n repository{\\n nameWithOwner\\n }\\n }\\n pageInfo {\\n hasNextPage\\n endCursor\\n }\\n }\\n }\\n}\"}" }
}); main.lastElementChild.insertBefore(createPrHTML(pr), main.lastElementChild.firstElementChild);
const payload = await response.json(); });
const prs = payload.data.user.pullRequests.nodes.filter(pr => {
return pr.repository.nameWithOwner === currentRepo;
});
const main = document.getElementsByTagName('main')[0];
if (!main) return;
prs.forEach(pr => {
main.lastElementChild.insertBefore(createPrHTML(pr), main.lastElementChild.firstElementChild);
});
}
setInterval(() => {
const urlSplit = document.URL.split('/');
if (urlSplit.length !== 5) { // Not A base repo URL
currentRepo = '';
return;
} }
const location = urlSplit.slice(-2).join('/')
if (location !== currentRepo) {
currentRepo = location;
getPRs();
}
}, 1000);
function createPrHTML(pr) { setInterval(() => {
const div = document.createElement('div'); const urlSplit = document.URL.split('/');
const prState = pr.commits.nodes[0].commit.statusCheckRollup?.state || ''; if (urlSplit.length !== 5) {
const prStateColor = prState === 'FAILURE' ? 'red' : (prState === 'SUCCESS' ? 'green' : 'yellow'); currentRepo = '';
return; // Not A base repo URL
}
div.className = "d-sm-flex Box mb-2 Box-body color-bg-secondary"; const location = urlSplit.slice(-2).join('/')
div.innerHTML = ` if (location !== currentRepo) {
currentRepo = location;
getPRs();
}
}, 1000);
function createPrHTML(pr) {
const div = document.createElement('div');
const prState = pr.commits.nodes[0].commit.statusCheckRollup?.state || '';
const prStateColor = prState === 'FAILURE' ? 'red' : (prState === 'SUCCESS' ? 'green' : 'yellow');
div.id = generatePrItemId(pr.number);
div.onclick = () => {
window.open(pr.url, '_blank');
}
div.className = "btn d-sm-flex Box mb-2 Box-body color-bg-secondary";
div.innerHTML = `
<div class="d-flex flex-auto"> <div class="d-flex flex-auto">
<div class="flex-shrink-0 mb-2 mr-2" > <div class="flex-shrink-0 mr-2" >
<span title="Status" data-view-component="true" class="State" style="color:${prStateColor}"> <span title="Status" data-view-component="true" class="State" style="color:${prStateColor}">
<svg height="16" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg> ${prState} <svg height="16" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" version="1.1" width="16" aria-hidden="true"><path style="color:${prStateColor}" fill-rule="evenodd" d="M7.177 3.073L9.573.677A.25.25 0 0110 .854v4.792a.25.25 0 01-.427.177L7.177 3.427a.25.25 0 010-.354zM3.75 2.5a.75.75 0 100 1.5.75.75 0 000-1.5zm-2.25.75a2.25 2.25 0 113 2.122v5.256a2.251 2.251 0 11-1.5 0V5.372A2.25 2.25 0 011.5 3.25zM11 2.5h-1V4h1a1 1 0 011 1v5.628a2.251 2.251 0 101.5 0V5A2.5 2.5 0 0011 2.5zm1 10.25a.75.75 0 111.5 0 .75.75 0 01-1.5 0zM3.75 12a.75.75 0 100 1.5.75.75 0 000-1.5z"></path></svg> #${pr.number} - ${prState}
</span> </span>
</div> </div>
<p style="padding-top:5px"> <p style="padding-top:5px" class="mb-0">
${pr.title} ${pr.title}
</p> </p>
<div class="flex-auto"></div>
<a class="btn ml-2 d-none d-md-block" href="${pr.url}">Open</a>
</div> </div>
`; `;
return div; return div;
} }
function generatePrItemId(prNumber) {
return `PR-${prNumber}`;
}
})();