Updated GitHub progress query & caching

This commit is contained in:
Jonathan Barrow 2023-07-19 23:31:52 -04:00
parent 441d754e77
commit f60db1b9b4
No known key found for this signature in database
GPG Key ID: E86E9FE9049C741F

View File

@ -1,106 +1,173 @@
const { GraphQLClient, gql } = require('graphql-request');
const Stripe = require('stripe');
const logger = require('./logger');
const config = require('../config.json');
const graphql = new GraphQLClient('https://api.github.com/graphql', {
const github = new GraphQLClient('https://api.github.com/graphql', {
headers: {
Authorization: `bearer ${config.github.graphql_token}`,
}
});
const stripe = new Stripe(config.stripe.secret_key);
const getProjectCards = gql`
fragment ItemContent on Node {
__typename
... on DraftIssue {
title
}
... on Issue {
title
}
}
fragment Itemfields on Node {
__typename
... on ProjectV2ItemFieldSingleSelectValue {
name,
field {
... on ProjectV2SingleSelectField {
name
}
}
}
}
query getProjectCards($orgName: String!) {
organization(login: $orgName) {
projectsV2(first: 100) {
nodes {
repositories(first: 1) {
nodes {
url
}
}
title
items(first: 100) {
nodes {
id
content {
...ItemContent
}
fieldValues(first: 20) {
nodes {
...Itemfields
}
}
}
}
}
}
}
}
const getProjectsV2GQL = gql`
query getProjectsV2($orgName: String!, $cursor: String!) {
organization(login: $orgName) {
projectsV2(first: 10, after: $cursor) {
nodes {
id
title
repositories(first: 1) {
nodes {
url
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
`;
let githubProjectsCache;
let stripeDonationCache;
const getProjectsV2FieldsGQL = gql`
query getProjectsV2Fields($id: ID!, $cursor: String!) {
node(id: $id) {
... on ProjectV2 {
items(first: 10, after: $cursor) {
nodes {
content {
... on DraftIssue {
title
}
... on Issue {
title
}
}
fieldValues(first: 20) {
nodes {
... on ProjectV2ItemFieldSingleSelectValue {
name
field {
... on ProjectV2SingleSelectField {
name
}
}
}
}
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
}
}
`;
async function getGithubProjectsCache() {
if (!githubProjectsCache) {
githubProjectsCache = await updateGithubProjectsCache();
let githubProjectsCache = {
update_time: 0,
sections: []
};
let githubCacheBeingFetched = false;
let stripeDonationCache = {
update_time: 0,
sections: []
};
async function getGitHubProjectsV2(after='') {
let projects = [];
const data = await github.request(getProjectsV2GQL, {
orgName: 'PretendoNetwork',
cursor: after
});
for (const node of data.organization.projectsV2.nodes) {
projects.push({
id: node.id,
title: node.title,
url: node.repositories.nodes[0]?.url,
});
}
if (githubProjectsCache.update_time < Date.now() - (1000 * 60 * 60)) {
githubProjectsCache = await updateGithubProjectsCache();
const { hasNextPage, endCursor } = data.organization.projectsV2.pageInfo;
if (hasNextPage) {
const nextPage = await getGitHubProjectsV2(endCursor);
projects = [...projects, ...nextPage];
}
return projects;
}
async function getGitHubProjectsV2Fields(id, after='') {
let fields = [];
const data = await github.request(getProjectsV2FieldsGQL, {
id: id,
cursor: after
});
for (const node of data.node.items.nodes) {
fields.push({
title: node.content.title,
column: node.fieldValues.nodes.find(fieldValue => fieldValue.field?.name === 'Status')?.name
});
}
const { hasNextPage, endCursor } = data.node.items.pageInfo;
if (hasNextPage) {
const nextPage = await getGitHubProjectsV2Fields(id, endCursor);
fields = [...fields, ...nextPage];
}
return fields;
}
async function getGithubProjectsCache() {
if (githubCacheBeingFetched) {
return githubProjectsCache;
}
try {
if (!githubCacheBeingFetched && githubProjectsCache.update_time < Date.now() - (1000 * 60 * 60)) {
githubCacheBeingFetched = true;
githubProjectsCache = await updateGithubProjectsCache();
}
} catch (error) {
logger.error(error);
} finally {
githubCacheBeingFetched = false;
}
return githubProjectsCache;
}
function getProgressField(fields) {
const found = fields.nodes.find(v => v.field?.name === 'Status');
return found?.name ?? undefined;
}
async function updateGithubProjectsCache() {
const projectsCacheData = {
update_time: Date.now(),
sections: []
};
const data = await graphql.request(getProjectCards, {
orgName: 'PretendoNetwork',
});
const projects = data.organization.projectsV2.nodes;
const projects = await getGitHubProjectsV2();
for (const project of projects) {
if (!project.repositories.nodes[0]) {
if (!project.url) {
continue;
}
const extractedData = {
title: project.title,
url: project.repositories.nodes[0]?.url,
url: project.url,
cards: {
done: [],
in_progress: [],
@ -108,18 +175,10 @@ async function updateGithubProjectsCache() {
}
};
for (const { content, fieldValues } of project.items.nodes) {
const progress = getProgressField(fieldValues);
const fields = await getGitHubProjectsV2Fields(project.id);
if (!['DraftIssue'].includes(content.__typename)) {
continue; // not a supported card, skip
}
if (!progress) {
continue; // entry does not have a status, skip
}
extractedData.cards[progress.toLowerCase().replace(' ', '_')]?.push(content.title);
for (const field of fields) {
extractedData.cards[field.column.toLowerCase().replace(' ', '_')]?.push(field.title);
}
projectsCacheData.sections.push(extractedData);