From 1c8dcbc8aab0560fd85dccdc6c044f2f00fe950c Mon Sep 17 00:00:00 2001 From: Simon Lecoq <22963968+lowlighter@users.noreply.github.com> Date: Mon, 25 Jan 2021 23:47:24 +0100 Subject: [PATCH] Add basic support for organizations (#80) --- source/app/metrics.mjs | 100 ++++++++++++++++----- source/app/web/instance.mjs | 2 +- source/plugins/activity/index.mjs | 4 +- source/plugins/gists/index.mjs | 6 +- source/plugins/habits/index.mjs | 4 +- source/plugins/isocalendar/index.mjs | 6 +- source/plugins/lines/index.mjs | 12 ++- source/plugins/people/index.mjs | 10 +-- source/plugins/projects/index.mjs | 6 +- source/plugins/stargazers/index.mjs | 8 +- source/plugins/stars/index.mjs | 6 +- source/plugins/topics/index.mjs | 6 +- source/queries/common.organization.graphql | 29 ++++++ source/queries/people.repository.graphql | 2 +- source/queries/people.sponsors.graphql | 2 +- source/queries/projects.graphql | 2 +- source/queries/projects.repository.graphql | 2 +- source/queries/repositories.graphql | 2 +- source/queries/repository.graphql | 2 +- source/templates/common.mjs | 4 +- source/templates/repository/template.mjs | 22 +++-- 21 files changed, 178 insertions(+), 59 deletions(-) create mode 100644 source/queries/common.organization.graphql diff --git a/source/app/metrics.mjs b/source/app/metrics.mjs index 042daed6..26e9bcd1 100644 --- a/source/app/metrics.mjs +++ b/source/app/metrics.mjs @@ -45,30 +45,11 @@ } //Query data from GitHub API - console.debug(`metrics/compute/${login} > graphql query`) - const forks = q["repositories.forks"] || false - Object.assign(data, await graphql(queries.common({login, "calendar.from":new Date(Date.now()-14*24*60*60*1000).toISOString(), "calendar.to":(new Date()).toISOString(), forks:forks ? "" : ", isFork: false"}))) - //Query repositories from GitHub API - { - //Iterate through repositories - let cursor = null - let pushed = 0 - do { - console.debug(`metrics/compute/${login} > retrieving repositories after ${cursor}`) - const {user:{repositories:{edges, nodes}}} = await graphql(queries.repositories({login, after:cursor ? `after: "${cursor}"` : "", repositories:Math.min(repositories, 100), forks:forks ? "" : ", isFork: false"})) - cursor = edges?.[edges?.length-1]?.cursor - data.user.repositories.nodes.push(...nodes) - pushed = nodes.length - } while ((pushed)&&(cursor)&&(data.user.repositories.nodes.length < repositories)) - //Limit repositories - console.debug(`metrics/compute/${login} > keeping only ${repositories} repositories`) - data.user.repositories.nodes.splice(repositories) - console.debug(`metrics/compute/${login} > loaded ${data.user.repositories.nodes.length} repositories`) - } + await common({login, q, data, queries, repositories, graphql}) //Compute metrics console.debug(`metrics/compute/${login} > compute`) const computer = Templates[template].default || Templates[template] - await computer({login, q, dflags}, {conf, data, rest, graphql, plugins, queries}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, run, fs, os, paths, util, format, bytes, shuffle, htmlescape, urlexpand, __module}}) + await computer({login, q, dflags}, {conf, data, rest, graphql, plugins, queries, account:data.account}, {s, pending, imports:{plugins:Plugins, url, imgb64, axios, puppeteer, run, fs, os, paths, util, format, bytes, shuffle, htmlescape, urlexpand, __module}}) const promised = await Promise.all(pending) //Check plugins errors @@ -123,6 +104,83 @@ } } +/** Common query */ + async function common({login, q, data, queries, repositories, graphql}) { + //Iterate through account types + for (const account of ["user", "organization"]) { + try { + //Query data from GitHub API + console.debug(`metrics/compute/${login}/common > account ${account}`) + const forks = q["repositories.forks"] || false + const queried = await graphql(queries[{user:"common", organization:"common.organization"}[account]]({login, "calendar.from":new Date(Date.now()-14*24*60*60*1000).toISOString(), "calendar.to":(new Date()).toISOString(), forks:forks ? "" : ", isFork: false"})) + Object.assign(data, {user:queried[account]}) + common.post?.[account]({login, data}) + //Query repositories from GitHub API + { + //Iterate through repositories + let cursor = null + let pushed = 0 + do { + console.debug(`metrics/compute/${login}/common > retrieving repositories after ${cursor}`) + const {[account]:{repositories:{edges, nodes}}} = await graphql(queries.repositories({login, account, after:cursor ? `after: "${cursor}"` : "", repositories:Math.min(repositories, 100), forks:forks ? "" : ", isFork: false"})) + cursor = edges?.[edges?.length-1]?.cursor + data.user.repositories.nodes.push(...nodes) + pushed = nodes.length + } while ((pushed)&&(cursor)&&(data.user.repositories.nodes.length < repositories)) + //Limit repositories + console.debug(`metrics/compute/${login}/common > keeping only ${repositories} repositories`) + data.user.repositories.nodes.splice(repositories) + console.debug(`metrics/compute/${login}/common > loaded ${data.user.repositories.nodes.length} repositories`) + } + //Success + console.debug(`metrics/compute/${login}/common > graphql query > account ${account} > success`) + return + } catch (error) { + console.debug(`metrics/compute/${login}/common > account ${account} > failed : ${error}`) + console.debug(`metrics/compute/${login}/common > checking next account`) + } + } + //Not found + console.debug(`metrics/compute/${login}/common > no more account type`) + throw new Error("user not found") + } + +/** Common query post-processing */ + common.post = { + //User + user({login, data}) { + console.debug(`metrics/compute/${login}/common > applying common post`) + data.account = "user" + Object.assign(data.user, { + isVerified:false, + }) + }, + //Organization + organization({login, data}) { + console.debug(`metrics/compute/${login}/common > applying common post`) + data.account = "organization", + Object.assign(data.user, { + isHireable:false, + starredRepositories:{totalCount:0}, + watching:{totalCount:0}, + contributionsCollection:{ + totalRepositoriesWithContributedCommits:0, + totalCommitContributions:0, + restrictedContributionsCount:0, + totalIssueContributions:0, + totalPullRequestContributions:0, + totalPullRequestReviewContributions:0, + }, + calendar:{contributionCalendar:{weeks:[]}}, + repositoriesContributedTo:{totalCount:0}, + followers:{totalCount:0}, + following:{totalCount:0}, + issueComments:{totalCount:0}, + organizations:{totalCount:0}, + }) + } + } + /** Returns module __dirname */ function __module(module) { return paths.join(paths.dirname(url.fileURLToPath(module))) diff --git a/source/app/web/instance.mjs b/source/app/web/instance.mjs index 554d6769..f7e1a0df 100644 --- a/source/app/web/instance.mjs +++ b/source/app/web/instance.mjs @@ -167,7 +167,7 @@ catch (error) { //Not found user if ((error instanceof Error)&&(/^user not found$/.test(error.message))) { - console.debug(`metrics/app/${login} > 404 (user not found)`) + console.debug(`metrics/app/${login} > 404 (user/organization not found)`) return res.sendStatus(404) } //Invalid template diff --git a/source/plugins/activity/index.mjs b/source/plugins/activity/index.mjs index 4801e158..691dd8c6 100644 --- a/source/plugins/activity/index.mjs +++ b/source/plugins/activity/index.mjs @@ -1,5 +1,5 @@ //Setup - export default async function ({login, rest, imports, q}, {enabled = false} = {}) { + export default async function ({login, rest, q, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met @@ -21,7 +21,7 @@ console.debug(`metrics/compute/${login}/plugins > activity > ${events.length} events loaded`) //Extract activity events const activity = events - .filter(({actor}) => actor.login === login) + .filter(({actor}) => account === "organization" ? true : actor.login === login) .filter(({created_at}) => Number.isFinite(days) ? new Date(created_at) > new Date(Date.now()-days*24*60*60*1000) : true) .map(({type, payload, repo:{name:repo}}) => { //See https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/github-event-types diff --git a/source/plugins/gists/index.mjs b/source/plugins/gists/index.mjs index 10d1618b..233fb49a 100644 --- a/source/plugins/gists/index.mjs +++ b/source/plugins/gists/index.mjs @@ -1,10 +1,12 @@ //Setup - export default async function ({login, graphql, q, queries}, {enabled = false} = {}) { + export default async function ({login, graphql, q, queries, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled)||(!q.gists)) return null + if (account === "organization") + throw {error:{message:"Not available for organizations"}} //Query gists from GitHub API const gists = [] { @@ -39,6 +41,8 @@ } //Handle errors catch (error) { + if (error.error?.message) + throw error throw {error:{message:"An error occured", instance:error}} } } diff --git a/source/plugins/habits/index.mjs b/source/plugins/habits/index.mjs index cb9301c1..5b6f8530 100644 --- a/source/plugins/habits/index.mjs +++ b/source/plugins/habits/index.mjs @@ -1,5 +1,5 @@ //Setup - export default async function ({login, rest, imports, data, q}, {enabled = false, from:defaults = 100} = {}) { + export default async function ({login, rest, imports, data, q, account}, {enabled = false, from:defaults = 100} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met @@ -28,7 +28,7 @@ //Get user recent commits const commits = events .filter(({type}) => type === "PushEvent") - .filter(({actor}) => actor.login === login) + .filter(({actor}) => account === "organization" ? true : actor.login === login) .filter(({created_at}) => new Date(created_at) > new Date(Date.now()-days*24*60*60*1000)) console.debug(`metrics/compute/${login}/plugins > habits > filtered out ${commits.length} push events over last ${days} days`) //Retrieve edited files and filter edited lines (those starting with +/-) from patches diff --git a/source/plugins/isocalendar/index.mjs b/source/plugins/isocalendar/index.mjs index a596fb7f..35cf5403 100644 --- a/source/plugins/isocalendar/index.mjs +++ b/source/plugins/isocalendar/index.mjs @@ -1,10 +1,12 @@ //Setup - export default async function ({login, graphql, q, queries}, {enabled = false} = {}) { + export default async function ({login, graphql, q, queries, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled)||(!q.isocalendar)) return null + if (account === "organization") + throw {error:{message:"Not available for organizations"}} //Parameters override let {"isocalendar.duration":duration = "half-year"} = q //Duration in days @@ -83,6 +85,8 @@ } //Handle errors catch (error) { + if (error.error?.message) + throw error throw {error:{message:"An error occured", instance:error}} } } \ No newline at end of file diff --git a/source/plugins/lines/index.mjs b/source/plugins/lines/index.mjs index 26a56c08..15c448bc 100644 --- a/source/plugins/lines/index.mjs +++ b/source/plugins/lines/index.mjs @@ -1,10 +1,18 @@ //Setup - export default async function ({login, data, imports, rest, q}, {enabled = false} = {}) { + export default async function ({login, data, rest, q}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled)||(!q.lines)) return null + + //Context + let context = {mode:"user"} + if (q.repo) { + console.debug(`metrics/compute/${login}/plugins > people > switched to repository mode`) + context = {...context, mode:"repository"} + } + //Repositories const repositories = data.user.repositories.nodes.map(({name:repo, owner:{login:owner}}) => ({repo, owner})) ?? [] //Get contributors stats from repositories @@ -18,7 +26,7 @@ if (!Array.isArray(repository)) return //Extract author - const [contributor] = repository.filter(({author}) => author.login === login) + const [contributor] = repository.filter(({author}) => context.mode === "repository" ? true : author.login === login) //Compute editions if (contributor) contributor.weeks.forEach(({a, d}) => (lines.added += a, lines.deleted += d)) diff --git a/source/plugins/people/index.mjs b/source/plugins/people/index.mjs index 646be9d3..0b955654 100644 --- a/source/plugins/people/index.mjs +++ b/source/plugins/people/index.mjs @@ -1,5 +1,5 @@ //Setup - export default async function ({login, data, graphql, rest, q, queries, imports}, {enabled = false} = {}) { + export default async function ({login, data, graphql, rest, q, queries, imports, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met @@ -9,7 +9,7 @@ //Context let context = { mode:"user", - types:["followers", "following", "sponsorshipsAsMaintainer", "sponsorshipsAsSponsor", "thanks"], + types:account === "organization" ? ["sponsorshipsAsMaintainer", "sponsorshipsAsSponsor", "thanks"] : ["followers", "following", "sponsorshipsAsMaintainer", "sponsorshipsAsSponsor", "thanks"], default:"followers, following", alias:{followed:"following", sponsors:"sponsorshipsAsMaintainer", sponsored:"sponsorshipsAsSponsor", sponsoring:"sponsorshipsAsSponsor"}, sponsorships:{sponsorshipsAsMaintainer:"sponsorEntity", sponsorshipsAsSponsor:"sponsorable"} @@ -17,7 +17,7 @@ if (q.repo) { console.debug(`metrics/compute/${login}/plugins > people > switched to repository mode`) const {owner, repo} = data.user.repositories.nodes.map(({name:repo, owner:{login:owner}}) => ({repo, owner})).shift() - context = {...context, mode:"repo", types:["contributors", "stargazers", "watchers", "sponsorshipsAsMaintainer", "thanks"], default:"stargazers, watchers", owner, repo} + context = {...context, mode:"repository", types:["contributors", "stargazers", "watchers", "sponsorshipsAsMaintainer", "thanks"], default:"stargazers, watchers", owner, repo} } //Parameters override @@ -52,8 +52,8 @@ do { console.debug(`metrics/compute/${login}/plugins > people > retrieving ${type} after ${cursor}`) const {[type]:{edges}} = ( - type in context.sponsorships ? (await graphql(queries["people.sponsors"]({login:context.owner ?? login, type, size, after:cursor ? `after: "${cursor}"` : "", target:context.sponsorships[type]}))).user : - context.mode === "repo" ? (await graphql(queries["people.repository"]({login:context.owner, repository:context.repo, type, size, after:cursor ? `after: "${cursor}"` : ""}))).user.repository : + type in context.sponsorships ? (await graphql(queries["people.sponsors"]({login:context.owner ?? login, type, size, after:cursor ? `after: "${cursor}"` : "", target:context.sponsorships[type], account})))[account] : + context.mode === "repository" ? (await graphql(queries["people.repository"]({login:context.owner, repository:context.repo, type, size, after:cursor ? `after: "${cursor}"` : "", account})))[account].repository : (await graphql(queries.people({login, type, size, after:cursor ? `after: "${cursor}"` : ""}))).user ) cursor = edges?.[edges?.length-1]?.cursor diff --git a/source/plugins/projects/index.mjs b/source/plugins/projects/index.mjs index 0ac50cd3..f735c27d 100644 --- a/source/plugins/projects/index.mjs +++ b/source/plugins/projects/index.mjs @@ -1,5 +1,5 @@ //Setup - export default async function ({login, graphql, q, queries}, {enabled = false} = {}) { + export default async function ({login, graphql, q, queries, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met @@ -13,13 +13,13 @@ limit = Math.max(repositories.length, Math.min(100, Number(limit))) //Retrieve user owned projects from graphql api console.debug(`metrics/compute/${login}/plugins > projects > querying api`) - const {user:{projects}} = await graphql(queries.projects({login, limit})) + const {[account]:{projects}} = await graphql(queries.projects({login, limit, account})) //Retrieve repositories projects from graphql api for (const identifier of repositories) { //Querying repository project console.debug(`metrics/compute/${login}/plugins > projects > querying api for ${identifier}`) const {user, repository, id} = identifier.match(/(?[-\w]+)[/](?[-\w]+)[/]projects[/](?\d+)/)?.groups - const {user:{repository:{project}}} = await graphql(queries["projects.repository"]({user, repository, id})) + const {[account]:{repository:{project}}} = await graphql(queries["projects.repository"]({user, repository, id, account})) //Adding it to projects list console.debug(`metrics/compute/${login}/plugins > projects > registering ${identifier}`) project.name = `${project.name} (${user}/${repository})` diff --git a/source/plugins/stargazers/index.mjs b/source/plugins/stargazers/index.mjs index c6c09466..65e39b03 100644 --- a/source/plugins/stargazers/index.mjs +++ b/source/plugins/stargazers/index.mjs @@ -1,5 +1,5 @@ //Setup - export default async function ({login, graphql, data, q, queries, imports}, {enabled = false} = {}) { + export default async function ({login, graphql, data, q, queries}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met @@ -7,16 +7,16 @@ return null //Retrieve stargazers from graphql api console.debug(`metrics/compute/${login}/plugins > stargazers > querying api`) - const repositories = data.user.repositories.nodes.map(({name}) => name).slice(0, 2) + const repositories = data.user.repositories.nodes.map(({name:repository, owner:{login:owner}}) => ({repository, owner})) ?? [] const dates = [] - for (const repository of repositories) { + for (const {repository, owner} of repositories) { //Iterate through stargazers console.debug(`metrics/compute/${login}/plugins > stargazers > retrieving stargazers of ${repository}`) let cursor = null let pushed = 0 do { console.debug(`metrics/compute/${login}/plugins > stargazers > retrieving stargazers of ${repository} after ${cursor}`) - const {repository:{stargazers:{edges}}} = await graphql(queries.stargazers({login, repository, after:cursor ? `after: "${cursor}"` : ""})) + const {repository:{stargazers:{edges}}} = await graphql(queries.stargazers({login:owner, repository, after:cursor ? `after: "${cursor}"` : ""})) cursor = edges?.[edges?.length-1]?.cursor dates.push(...edges.map(({starredAt}) => new Date(starredAt))) pushed = edges.length diff --git a/source/plugins/stars/index.mjs b/source/plugins/stars/index.mjs index 8a8e4f99..fa4c1d3e 100644 --- a/source/plugins/stars/index.mjs +++ b/source/plugins/stars/index.mjs @@ -1,10 +1,12 @@ //Setup - export default async function ({login, graphql, q, queries, imports}, {enabled = false} = {}) { + export default async function ({login, graphql, q, queries, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled)||(!q.stars)) return null + if (account === "organization") + throw {error:{message:"Not available for organizations"}} //Parameters override let {"stars.limit":limit = 4} = q //Limit @@ -28,6 +30,8 @@ } //Handle errors catch (error) { + if (error.error?.message) + throw error throw {error:{message:"An error occured", instance:error}} } } diff --git a/source/plugins/topics/index.mjs b/source/plugins/topics/index.mjs index b18e8ec0..f3b6ceaa 100644 --- a/source/plugins/topics/index.mjs +++ b/source/plugins/topics/index.mjs @@ -1,10 +1,12 @@ //Setup - export default async function ({login, imports, q}, {enabled = false} = {}) { + export default async function ({login, imports, q, account}, {enabled = false} = {}) { //Plugin execution try { //Check if plugin is enabled and requirements are met if ((!enabled)||(!q.topics)) return null + if (account === "organization") + throw {error:{message:"Not available for organizations"}} //Parameters override let {"topics.sort":sort = "stars", "topics.mode":mode = "starred", "topics.limit":limit} = q //Shuffle @@ -85,6 +87,8 @@ } //Handle errors catch (error) { + if (error.error?.message) + throw error throw {error:{message:"An error occured", instance:error}} } } \ No newline at end of file diff --git a/source/queries/common.organization.graphql b/source/queries/common.organization.graphql new file mode 100644 index 00000000..4166f7aa --- /dev/null +++ b/source/queries/common.organization.graphql @@ -0,0 +1,29 @@ +query MetricsOrganization { + organization(login: "$login") { + databaseId + name + login + createdAt + avatarUrl + websiteUrl + isVerified + twitterUsername + repositories(last: 0) { + totalCount + totalDiskUsage + nodes { + name + } + } + packages { + totalCount + } + sponsorshipsAsSponsor { + totalCount + } + sponsorshipsAsMaintainer { + totalCount + } + + } +} diff --git a/source/queries/people.repository.graphql b/source/queries/people.repository.graphql index b6b6e949..f7b92c17 100644 --- a/source/queries/people.repository.graphql +++ b/source/queries/people.repository.graphql @@ -1,5 +1,5 @@ query PeopleRepository { - user(login: "$login") { + $account(login: "$login") { repository(name: "$repository") { $type($after first: 100) { edges { diff --git a/source/queries/people.sponsors.graphql b/source/queries/people.sponsors.graphql index 5b12565c..62388687 100644 --- a/source/queries/people.sponsors.graphql +++ b/source/queries/people.sponsors.graphql @@ -1,5 +1,5 @@ query PeopleSponsors { - user(login: "$login") { + $account(login: "$login") { login $type($after first: 100) { edges { diff --git a/source/queries/projects.graphql b/source/queries/projects.graphql index 01b5af8a..cad09502 100644 --- a/source/queries/projects.graphql +++ b/source/queries/projects.graphql @@ -1,5 +1,5 @@ query Projects { - user(login: "$login") { + $account(login: "$login") { projects(last: $limit, states: OPEN, orderBy: {field: UPDATED_AT, direction: DESC}) { totalCount nodes { diff --git a/source/queries/projects.repository.graphql b/source/queries/projects.repository.graphql index 5c4a5b78..21bc9eef 100644 --- a/source/queries/projects.repository.graphql +++ b/source/queries/projects.repository.graphql @@ -1,5 +1,5 @@ query RepositoryProject { - user(login: "$user") { + $account(login: "$user") { repository(name: "$repository") { project(number: $id) { name diff --git a/source/queries/repositories.graphql b/source/queries/repositories.graphql index c22469b1..de5ed976 100644 --- a/source/queries/repositories.graphql +++ b/source/queries/repositories.graphql @@ -1,5 +1,5 @@ query Repositories { - user(login: "$login") { + $account(login: "$login") { repositories($after first: $repositories $forks, orderBy: {field: UPDATED_AT, direction: DESC}) { edges { cursor diff --git a/source/queries/repository.graphql b/source/queries/repository.graphql index ad919e94..c49a750b 100644 --- a/source/queries/repository.graphql +++ b/source/queries/repository.graphql @@ -1,5 +1,5 @@ query Repository { - user(login: "$login") { + $account(login: "$login") { repository(name: "$repo") { name owner { diff --git a/source/templates/common.mjs b/source/templates/common.mjs index 07156c43..ac213974 100644 --- a/source/templates/common.mjs +++ b/source/templates/common.mjs @@ -1,5 +1,5 @@ /** Template common processor */ - export default async function ({login, q, dflags}, {conf, data, rest, graphql, plugins, queries}, {s, pending, imports}) { + export default async function ({login, q, dflags}, {conf, data, rest, graphql, plugins, queries, account}, {s, pending, imports}) { //Init const computed = data.computed = {commits:0, sponsorships:0, licenses:{favorite:"", used:{}}, token:{}, repositories:{watchers:0, stargazers:0, issues_open:0, issues_closed:0, pr_open:0, pr_merged:0, forks:0, forked:0, releases:0}} @@ -32,7 +32,7 @@ pending.push((async () => { try { console.debug(`metrics/compute/${login}/plugins > ${name} > started`) - data.plugins[name] = await imports.plugins[name]({login, q, imports, data, computed, rest, graphql, queries}, plugins[name]) + data.plugins[name] = await imports.plugins[name]({login, q, imports, data, computed, rest, graphql, queries, account}, plugins[name]) console.debug(`metrics/compute/${login}/plugins > ${name} > completed`) } catch (error) { diff --git a/source/templates/repository/template.mjs b/source/templates/repository/template.mjs index c70d7c60..e23fd3a2 100644 --- a/source/templates/repository/template.mjs +++ b/source/templates/repository/template.mjs @@ -2,7 +2,7 @@ import common from "./../common.mjs" /** Template processor */ - export default async function ({login, q}, {conf, data, rest, graphql, plugins, queries}, {s, pending, imports}) { + export default async function ({login, q}, {conf, data, rest, graphql, plugins, queries, account}, {s, pending, imports}) { //Check arguments const {repo} = q if (!repo) { @@ -10,10 +10,11 @@ data.errors.push({error:{message:`You must pass a "repo" argument to use this template`}}) return await common(...arguments) } + console.debug(`metrics/compute/${login}/${repo} > switching to mode ${account}`) //Retrieving single repository console.debug(`metrics/compute/${login}/${repo} > retrieving single repository ${repo}`) - const {user:{repository}} = await graphql(queries.repository({login, repo})) + const {[account]:{repository}} = await graphql(queries.repository({login, repo, account})) data.user.repositories.nodes = [repository] data.repo = repository @@ -26,12 +27,19 @@ const commits = [] for (let page = 0; page < 100; page++) { console.debug(`metrics/compute/${login}/${repo} > loading page ${page}`) - const {data} = await rest.repos.listCommits({owner:login, repo, per_page:100, page}) - if (!data.length) { - console.debug(`metrics/compute/${login}/${repo} > no more page to load`) - break + try { + const {data} = await rest.repos.listCommits({owner:login, repo, per_page:100, page}) + if (!data.length) { + console.debug(`metrics/compute/${login}/${repo} > no more page to load`) + break + } + commits.push(...data) + } + catch (error) { + if (/Git Repository is empty/.test(error)) + break + throw error } - commits.push(...data) } console.debug(`metrics/compute/${login}/${repo} > ${commits.length} commits loaded`)