kopia lustrzana https://github.com/badgen/badgen.net
badge(gitlab): adding some badges for GitLab (#422)
* wip: added some badges * - some final touches * small fix * - corrected wrong error message * fixes after code reviewpull/424/head
rodzic
123c8889bf
commit
f07fad5e80
|
@ -0,0 +1,265 @@
|
|||
import millify from 'millify'
|
||||
import distanceToNow from 'date-fns/formatDistanceToNow'
|
||||
import { createBadgenHandler, PathArgs } from '../libs/create-badgen-handler'
|
||||
import { queryGitlab, restGitlab } from '../libs/gitlab'
|
||||
import { version } from '../libs/utils'
|
||||
|
||||
const removeNoSignFromHexColor = (hexColor: string) => hexColor.replace('#', '')
|
||||
|
||||
export default createBadgenHandler({
|
||||
title: 'Gitlab',
|
||||
examples: {
|
||||
'/gitlab/stars/fdroid/fdroidclient': 'stars',
|
||||
'/gitlab/forks/inkscape/inkscape': 'forks',
|
||||
'/gitlab/issues/gitlab-org/gitlab-runner': 'issues',
|
||||
'/gitlab/open-issues/gitlab-org/gitlab-runner': 'issues',
|
||||
'/gitlab/closed-issues/gitlab-org/gitlab-runner': 'issues',
|
||||
'/gitlab/label-issues/NickBusey/HomelabOS/Bug': 'issues by label',
|
||||
'/gitlab/label-issues/NickBusey/HomelabOS/Enhancement/opened': 'open issues by label',
|
||||
'/gitlab/label-issues/NickBusey/HomelabOS/Help%20wanted/closed': 'closed issues by label',
|
||||
'/gitlab/mrs/edouardklein/falsisign': 'MRs',
|
||||
'/gitlab/open-mrs/edouardklein/falsisign': 'open MRs',
|
||||
'/gitlab/closed-mrs/edouardklein/falsisign': 'closed MRs',
|
||||
'/gitlab/merged-mrs/edouardklein/falsisign': 'merged MRs',
|
||||
'/gitlab/branches/gitlab-org%2fgitter/webapp': 'branches',
|
||||
'/gitlab/releases/AuroraOSS/AuroraStore': 'release',
|
||||
'/gitlab/release/veloren/veloren': 'latest release',
|
||||
'/gitlab/tags/commento/commento': 'tags',
|
||||
'/gitlab/contributors/graphviz/graphviz': 'contributors',
|
||||
'/gitlab/license/gitlab-org/omnibus-gitlab': 'license',
|
||||
'/gitlab/commits/cryptsetup/cryptsetup': 'commits count',
|
||||
'/gitlab/commits/cryptsetup/cryptsetup/coverity_scan': 'commits count (branch ref)',
|
||||
'/gitlab/commits/cryptsetup/cryptsetup/v2.2.2': 'commits count (tag ref)',
|
||||
'/gitlab/last-commit/gitlab-org/gitlab-development-kit': 'last commit',
|
||||
'/gitlab/last-commit/gitlab-org/gitlab-development-kit/updating-chromedriver-install-v2': 'last commit (branch ref)',
|
||||
'/gitlab/last-commit/gitlab-org/gitlab-development-kit/v0.2.5': 'last commit (tag ref)',
|
||||
},
|
||||
handlers: {
|
||||
'/gitlab/:topic<stars|forks|issues|open-issues|closed-issues>/:owner/:repo': queryHandler,
|
||||
'/gitlab/:topic<mrs|open-mrs|closed-mrs|merged-mrs|branches|releases|release|tags|license|contributors>/:owner/:repo': restHandler,
|
||||
'/gitlab/:topic<label-issues>/:owner/:repo/:label/:state?<open|closed>': queryHandler,
|
||||
'/gitlab/:topic<commits|last-commit>/:owner/:repo/:ref?': restHandler,
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
async function restHandler({ topic, owner, repo, ...restArgs }: PathArgs) {
|
||||
const result = await makeRestCall({ topic, owner, repo, ...restArgs })
|
||||
|
||||
switch (topic) {
|
||||
case 'mrs':
|
||||
return {
|
||||
subject: 'MRs',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'closed-mrs':
|
||||
return {
|
||||
subject: 'closed MRs',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'open-mrs':
|
||||
return {
|
||||
subject: 'open MRs',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'merged-mrs':
|
||||
return {
|
||||
subject: 'merged MRs',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'commits':
|
||||
return {
|
||||
subject: 'commits',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'last-commit':
|
||||
const lastDate = result.length && new Date(result[0].committed_date)
|
||||
const fromNow = lastDate && distanceToNow(lastDate, { addSuffix: true })
|
||||
return {
|
||||
subject: 'last commit',
|
||||
status: fromNow || 'none',
|
||||
color: 'green'
|
||||
}
|
||||
case 'branches':
|
||||
return {
|
||||
subject: 'branches',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'releases':
|
||||
return {
|
||||
subject: 'releases',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'release':
|
||||
const [latest] = result
|
||||
if (!latest) {
|
||||
return {
|
||||
subject: 'release',
|
||||
status: 'none',
|
||||
color: 'yellow'
|
||||
}
|
||||
}
|
||||
return {
|
||||
subject: 'release',
|
||||
status: version(latest.name || latest.tag_name),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'tags':
|
||||
return {
|
||||
subject: 'tags',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'contributors':
|
||||
return {
|
||||
subject: 'contributors',
|
||||
status: millify(parseInt(result.headers['x-total'])),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'license':
|
||||
return {
|
||||
subject: 'license',
|
||||
status: result.license?.name || "no license",
|
||||
color: result.license ? 'blue' : 'grey'
|
||||
}
|
||||
default:
|
||||
return {
|
||||
subject: 'gitlab',
|
||||
status: 'unknown topic',
|
||||
color: 'grey'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function queryHandler({ topic, owner, repo, ...restArgs }: PathArgs) {
|
||||
const result = await makeQueryCall({ topic, owner, repo, ...restArgs })
|
||||
|
||||
if (!result) {
|
||||
return {
|
||||
subject: 'gitlab',
|
||||
status: 'not found',
|
||||
color: 'grey'
|
||||
}
|
||||
}
|
||||
|
||||
switch (topic) {
|
||||
case 'stars':
|
||||
return {
|
||||
subject: topic,
|
||||
status: millify(result.starCount),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'forks':
|
||||
return {
|
||||
subject: topic,
|
||||
status: millify(result.forksCount),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'issues':
|
||||
return {
|
||||
subject: topic,
|
||||
status: millify(result.issues.count),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'open-issues':
|
||||
return {
|
||||
subject: 'open issues',
|
||||
status: millify(result.openIssuesCount),
|
||||
color: result.openIssuesCount === 0 ? 'green' : 'orange'
|
||||
}
|
||||
case 'closed-issues':
|
||||
return {
|
||||
subject: 'closed issues',
|
||||
status: millify(result.issues.count),
|
||||
color: 'blue'
|
||||
}
|
||||
case 'label-issues':
|
||||
return {
|
||||
subject: `${restArgs.label}`,
|
||||
status: result.label ? millify(result.issues.count) : '0',
|
||||
color: result.label ? removeNoSignFromHexColor(result.label.color) : 'gray'
|
||||
}
|
||||
default:
|
||||
return {
|
||||
subject: 'gitlab',
|
||||
status: 'unknown topic',
|
||||
color: 'grey'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const makeQueryCall = async ({ topic, owner, repo, ...restArgs }) => {
|
||||
const repoQueryBodies = {
|
||||
'stars': 'starCount',
|
||||
'forks': 'forksCount',
|
||||
'open-issues': 'openIssuesCount',
|
||||
'closed-issues': 'issues(state:closed){ count }',
|
||||
'issues': 'issues{ count }',
|
||||
}
|
||||
|
||||
let queryBody
|
||||
switch (topic) {
|
||||
case 'label-issues':
|
||||
const { label, state } = restArgs
|
||||
const stateFilter = state ? `state:${state.toLowerCase()}` : ''
|
||||
queryBody = `
|
||||
issues(labelName:"${label}", ${stateFilter}) { count }
|
||||
label(title: "${label}"){ color }
|
||||
`
|
||||
break
|
||||
default:
|
||||
queryBody = repoQueryBodies[topic]
|
||||
}
|
||||
|
||||
const query = `
|
||||
query {
|
||||
project(fullPath:"${owner}/${repo}") {
|
||||
${queryBody}
|
||||
}
|
||||
}
|
||||
`
|
||||
return queryGitlab(query).then(res => res.data!.project)
|
||||
}
|
||||
|
||||
const makeRestCall = async ({ topic, owner, repo, ...restArgs }) => {
|
||||
const restPaths = {
|
||||
'mrs': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/merge_requests`,
|
||||
'open-mrs': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/merge_requests?state=opened`,
|
||||
'closed-mrs': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/merge_requests?state=closed`,
|
||||
'merged-mrs': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/merge_requests?state=merged`,
|
||||
'commits': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/commits?${restArgs.ref ? "ref_name=" + restArgs.ref : ''}`,
|
||||
'last-commit': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/commits?${restArgs.ref ? "ref_name=" + restArgs.ref : ''}`,
|
||||
'branches': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/branches`,
|
||||
'tags': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/tags`,
|
||||
'contributors': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/repository/contributors`,
|
||||
'releases': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/releases`,
|
||||
'release': `/projects/${encodeURIComponent(`${owner}/${repo}`)}/releases`,
|
||||
'license': `/projects/${encodeURIComponent(`${owner}/${repo}`)}?license=true`,
|
||||
}
|
||||
|
||||
let restPath = restPaths[topic]
|
||||
|
||||
return restGitlab(restPath, fullResponsePaths.includes(topic))
|
||||
}
|
||||
|
||||
const fullResponsePaths =
|
||||
[
|
||||
'mrs',
|
||||
'open-mrs',
|
||||
'closed-mrs',
|
||||
'merged-mrs',
|
||||
'commits',
|
||||
'branches',
|
||||
'releases',
|
||||
'tags',
|
||||
'contributors'
|
||||
]
|
||||
|
|
@ -7,6 +7,7 @@ const rel = (...args) => path.resolve(__dirname, ...args)
|
|||
export const liveBadgeList = [
|
||||
// source control
|
||||
'github',
|
||||
'gitlab',
|
||||
// release registries
|
||||
'npm',
|
||||
'david',
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import got from './got'
|
||||
import { BadgenError } from './create-badgen-handler'
|
||||
|
||||
const rand = <T>(arr: T[]): T => arr[Math.floor(Math.random() * arr.length)]
|
||||
|
||||
|
||||
// request gitlab api v4 (graphql)
|
||||
export function queryGitlab<T = any>(query) {
|
||||
const headers = {
|
||||
authorization: `Bearer ${pickGitlabToken()}`,
|
||||
}
|
||||
const json = { query }
|
||||
const endpoint =
|
||||
process.env.GITLAB_API_GRAPHQL || 'https://gitlab.com/api/graphql'
|
||||
return got.post(endpoint, { json, headers }).json<T>()
|
||||
}
|
||||
|
||||
export function restGitlab<T = any>(path: string, fullResponse = false) {
|
||||
const headers = {
|
||||
authorization: `Bearer ${pickGitlabToken()}`,
|
||||
}
|
||||
const prefixUrl = process.env.GITLAB_API || 'https://gitlab.com/api/v4'
|
||||
return fullResponse ? got.get(path, { prefixUrl, headers }) : got.get(path, { prefixUrl, headers }).json<T>()
|
||||
}
|
||||
|
||||
function pickGitlabToken() {
|
||||
const { GITLAB_TOKENS } = process.env
|
||||
if (!GITLAB_TOKENS) {
|
||||
throw new BadgenError({ status: 'token required' })
|
||||
}
|
||||
const tokens = GITLAB_TOKENS.split(',').map(segment => segment.trim())
|
||||
return rand(tokens)
|
||||
}
|
3
now.json
3
now.json
|
@ -13,6 +13,7 @@
|
|||
"env": {
|
||||
"GH_TOKENS": "@badgen-gh-tokens",
|
||||
"SENTRY_DSN": "@badgen-sentry-dsn",
|
||||
"TRACKING_GA": "@badgen-tracking-ga"
|
||||
"TRACKING_GA": "@badgen-tracking-ga",
|
||||
"GITLAB_TOKENS": "@badgen-gl-tokens"
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue