feat: Added badge endpoint for Jenkins jobs (#418)

* feat: Added badge endpoint for Jenkins jobs

* fix: Removed unused variable

* Update api/jenkins.ts

Co-authored-by: Amio Jin <amio.cn@gmail.com>

Co-authored-by: Amio Jin <amio.cn@gmail.com>
pull/420/head
Deepak Bhardwaj 2020-08-13 16:50:16 +05:30 zatwierdzone przez GitHub
rodzic d5cbde60ce
commit defdbb9dcd
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
4 zmienionych plików z 125 dodań i 10 usunięć

108
api/jenkins.ts 100644
Wyświetl plik

@ -0,0 +1,108 @@
import got from "../libs/got";
import { createBadgenHandler, PathArgs } from "../libs/create-badgen-handler";
import humanizeDuration from "humanize-duration";
export default createBadgenHandler({
title: "Jenkins",
examples: {
"/jenkins/last-build/jenkins.mono-project.com/job/test-mono-mainline/":
"Last build status",
"/jenkins/fix-time/jenkins.mono-project.com/job/test-mono-mainline/":
"Time taken to fix a broken build",
"/jenkins/broken-build/jenkins.mono-project.com/job/test-mono-mainline/":
"# of broken builds",
},
handlers: {
"/jenkins/last-build/:hostname/:job*": lastJobStatusHandler,
"/jenkins/fix-time/:hostname/:job*": buildFixTimeHandler,
"/jenkins/broken-build/:hostname/:job*": brokenBuildsHandler,
},
});
const shortEnglishHumanizer = humanizeDuration.humanizer({
language: "shortEn",
units: ["d", "h"],
round: true,
languages: {
shortEn: {
y: () => "y",
mo: () => "mo",
w: () => "w",
d: () => "d",
h: () => "h",
m: () => "m",
s: () => "s",
ms: () => "ms",
},
},
});
const statusToColor = (status: string) => {
return status.toUpperCase() === "SUCCESS" ? "green" : "red";
};
const brokenBuildsToColor = (count: number) => {
return count < 10 ? "green" : count < 20 ? "orange" : "red";
};
const buildFixTimeToColor = (hours: number) => {
return hours < 2 ? "green" : hours < 6 ? "orange" : "red";
};
async function jenkinsLastBuild({ hostname, job }: PathArgs) {
const endpoint = `https://${hostname}/${job}/lastBuild/api/json?tree=result,timestamp,estimatedDuration`;
return await got(endpoint).json<any>();
}
async function jenkinsBuilds({ hostname, job }: PathArgs) {
const endpoint = `https://${hostname}/${job}/api/json?tree=builds[number,status,timestamp,id,result]`;
return await got(endpoint).json<any>();
}
async function lastJobStatusHandler({ hostname, job }: PathArgs) {
const response = await jenkinsLastBuild({ hostname, job });
return {
subject: "Last Build",
status: response.result,
color: statusToColor(response.result),
};
}
async function brokenBuildsHandler({ hostname, job }: PathArgs) {
const response = await jenkinsBuilds({ hostname, job });
const brokenBuilds = response.builds.filter(function (build) {
return build.result.toUpperCase() !== "SUCCESS";
});
return {
subject: "Broken Builds",
status: brokenBuilds.length,
color: brokenBuildsToColor(brokenBuilds.length),
};
}
async function buildFixTimeHandler({ hostname, job }: PathArgs) {
const response = await jenkinsBuilds({ hostname, job });
var lastSuccessTime = 0;
var lastFailTime = 0;
for (let index = 0; index < response.builds.length; index++) {
const element = response.builds[index];
if (element.result.toUpperCase() == "SUCCESS") {
lastSuccessTime = element.timestamp;
lastFailTime = lastSuccessTime;
} else {
lastFailTime = element.timestamp;
break;
}
}
if (lastSuccessTime == 0) lastSuccessTime = new Date().getTime();
if (lastFailTime == 0) lastFailTime = lastSuccessTime;
return {
subject: "Fix Time",
status: `${shortEnglishHumanizer((lastSuccessTime - lastFailTime) | 0)}`,
color: buildFixTimeToColor(
((lastSuccessTime - lastFailTime) / 3600000) | 0
),
};
}

Wyświetl plik

@ -58,6 +58,7 @@ export const liveBadgeList = [
'tidelift',
'runkit',
'https',
'jenkins',
]
export async function loadBadgeMeta () {

25
package-lock.json wygenerowano
Wyświetl plik

@ -4861,9 +4861,9 @@
"dev": true
},
"elliptic": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz",
"integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==",
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
"integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
"dev": true,
"requires": {
"bn.js": "^4.4.0",
@ -6114,6 +6114,11 @@
}
}
},
"humanize-duration": {
"version": "3.23.1",
"resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.23.1.tgz",
"integrity": "sha512-aoOEkomAETmVuQyBx4E7/LfPlC9s8pAA/USl7vFRQpDjepo3aiyvFfOhtXSDqPowdBVPFUZ7onG/KyuolX0qPg=="
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@ -7114,9 +7119,9 @@
}
},
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"minipass": {
@ -7203,12 +7208,12 @@
}
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "0.0.8"
"minimist": "^1.2.5"
}
},
"move-concurrently": {

Wyświetl plik

@ -32,6 +32,7 @@
"date-fns": "^2.15.0",
"got": "^10.7.0",
"haxe-rpc-client": "^1.0.0",
"humanize-duration": "^3.23.1",
"lodash.debounce": "^4.0.8",
"measurement-protocol": "^0.1.1",
"micro": "^9.3.4",