diff --git a/source/app/metrics/utils.mjs b/source/app/metrics/utils.mjs index cb84873a..0ad27dbf 100644 --- a/source/app/metrics/utils.mjs +++ b/source/app/metrics/utils.mjs @@ -309,15 +309,25 @@ export function ghfilter(text, object) { console.debug(`metrics/svg/ghquery > checking ${text} against ${JSON.stringify(object)}`) const result = text.split(/(? x.trim()).filter(x => x).map(criteria => { const [key, filters] = criteria.split(":") - const value = object[/^NOT /.test(key) ? key.substring(3).trim() : key.trim()] + const value = object[/^NOT /.test(key) ? key.substring(3).trim() : /^-/.test(key) ? key.substring(1).trim() : key.trim()] console.debug(`metrics/svg/ghquery > checking ${criteria} against ${value}`) + if (value === undefined) { + console.debug(`metrics/svg/ghquery > value for ${criteria} is undefined, considering it truthy`) + return true + } return filters?.split(",").map(x => x.trim()).filter(x => x).map(filter => { if (!Number.isFinite(Number(value))) { if (/^NOT /.test(filter)) return value !== filter.substring(3).trim() + if (/^-/.test(key)) + return value !== filter return value === filter.trim() } switch (true) { + case /^true$/.test(filter): + return value === true + case /^false$/.test(filter): + return value === false case /^>\d+$/.test(filter): return value > Number(filter.substring(1)) case /^>=\d+$/.test(filter): diff --git a/source/plugins/notable/index.mjs b/source/plugins/notable/index.mjs index cc15a35d..d024ffcc 100644 --- a/source/plugins/notable/index.mjs +++ b/source/plugins/notable/index.mjs @@ -7,7 +7,8 @@ export default async function({login, q, imports, rest, graphql, data, account, return null //Load inputs - let {filter, repositories, from, indepth} = imports.metadata.plugins.notable.inputs({data, account, q}) + let {filter, skipped, repositories, from, indepth} = imports.metadata.plugins.notable.inputs({data, account, q}) + skipped.push(...data.shared["repositories.skipped"]) //Iterate through contributed repositories const commits = [] @@ -19,6 +20,7 @@ export default async function({login, q, imports, rest, graphql, data, account, const {user:{repositoriesContributedTo:{edges}}} = await graphql(queries.notable.contributions({login, after:cursor ? `after: "${cursor}"` : "", repositories:data.shared["repositories.batch"] || 100})) cursor = edges?.[edges?.length - 1]?.cursor edges + .filter(({node}) => !((skipped.includes(node.nameWithOwner.toLocaleLowerCase()))||(skipped.includes(node.nameWithOwner.split("/")[1].toLocaleLowerCase())))) .filter(({node}) => ({all:true, organization:node.isInOrganization, user:!node.isInOrganization}[from])) .filter(({node}) => imports.ghfilter(filter, {name:node.nameWithOwner, user:node.owner.login, stars:node.stargazers.totalCount, watchers:node.watchers.totalCount, forks:node.forks.totalCount})) .map(({node}) => commits.push({handle:node.nameWithOwner, stars:node.stargazers.totalCount, organization:node.isInOrganization, avatarUrl:node.owner.avatarUrl})) @@ -79,7 +81,7 @@ export default async function({login, q, imports, rest, graphql, data, account, if (aggregated.has(key)) { const aggregate = aggregated.get(key) aggregate.aggregated++ - if (extras) { + if (indepth) { const {history = 0, user:{commits = 0, percentage = 0, maintainer = false} = {}} = _extras aggregate.history = aggregate.history ?? 0 aggregate.history += history @@ -94,9 +96,11 @@ export default async function({login, q, imports, rest, graphql, data, account, } contributions = [...aggregated.values()] - if (extras) { + if (indepth) { //Normalize contribution percentage contributions.map(aggregate => aggregate.user ? aggregate.user.percentage /= aggregate.aggregated : null) + //Additional filtering (no user commits means that API wasn't able to answer back, considering it as matching by default) + contributions = contributions.filter(({handle, user}) => !user?.commits ? true : imports.ghfilter(filter, {handle, commits:contributions.history, "commits.user":user.commits, "commits.user%":user.percentage*100, maintainer:user.maintainer})) //Sort contribution by maintainer first and then by contribution percentage contributions = contributions.sort((a, b) => ((b.user?.percentage + b.user?.maintainer) || 0) - ((a.user?.percentage + a.user?.maintainer) || 0)) } diff --git a/source/plugins/notable/metadata.yml b/source/plugins/notable/metadata.yml index c6315055..de4b4ef2 100644 --- a/source/plugins/notable/metadata.yml +++ b/source/plugins/notable/metadata.yml @@ -22,9 +22,20 @@ inputs: Based on [GitHub search syntax](https://docs.github.com/en/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax). Supported fields are `stars`, `forks` and `watchers` + + If `plugin_notable_indepth` is enabled, `commits`, `commits.user`, `commits.user%` and `maintainer` fields are also supported. + Some repositories may not be able to reported advanced stats and in the case the default behaviour will be to bypass filtering type: string default: "" - example: stars:>500 forks:>100 + example: stars:>500 forks:>100 maintainer:true commits.user%:>5 + + plugin_notable_skipped: + description: Skipped repositories + type: array + format: comma-separated + default: "" + example: my-repo-1, my-repo-2, owner/repo-3, ... + inherits: repositories_skipped plugin_notable_from: description: |