diff --git a/action.yml b/action.yml index f442caf..bed78ec 100644 --- a/action.yml +++ b/action.yml @@ -48,6 +48,10 @@ inputs: orgs: description: 'An optional list of org in the format: ,' required: false + discussions: + description: 'Disable/Active discussions fetching' + default: 'true' + required: false outputs: issueNumber: description: 'If an issue was created, this will be its number' diff --git a/lib/agenda.js b/lib/agenda.js index 2bbb9ba..f027a03 100644 --- a/lib/agenda.js +++ b/lib/agenda.js @@ -1,5 +1,7 @@ 'use strict' +const { graphql } = require('@octokit/graphql') + /** * get agenda issues and PRs from repositories * @param {Object} client - GitHub client @@ -38,7 +40,7 @@ async function fetchAgendaItems (client, repos, agendaLabel) { labels: agendaLabel, per_page: 100 })).filter(pr => pr.labels.find(label => label.name === agendaLabel) && - !(agendaIssues.find((i) => i.url === pr.url))) // workaround for flaky GH API/SDK behavior where sometimes the issue endpoint loads PRs + !(agendaIssues.find((i) => i.url === pr.url))) // workaround for flaky GH API/SDK behavior where sometimes the issue endpoint loads PRs console.log(`Fetching PRs for ${r.owner}/${r.repo}: Found ${_agendaPrs.length}`) @@ -52,6 +54,80 @@ async function fetchAgendaItems (client, repos, agendaLabel) { return agendaIssues } +async function fetchDiscussionsItems (repos, agendaLabel, token) { + const agendaDiscussions = [] + for (const r of repos) { + let hasNextPage = true + let endCursor = null + do { + const query = ` + query($owner: String!, $name: String!, $after: String) { + repository(owner: $owner, name: $name) { + discussions(first: 100, after: $after) { + pageInfo { + endCursor + hasNextPage + } + edges { + cursor + node { + id + title + url + labels(first: 10) { + nodes { + color + name + } + } + } + } + } + } + } + ` + const variables = { + owner: r.owner, + name: r.repo, + after: endCursor + } + + const _agendaDiscussions = await graphql(query, { + ...variables, + headers: { + authorization: `token ${token}` + } + }) + + const discussions = _agendaDiscussions?.repository?.discussions + + if (discussions) { + const { edges, pageInfo } = discussions + for (const edge of edges) { + const labels = edge.node?.labels.nodes + if (Array.isArray(labels) && labels.some(label => label.name === agendaLabel)) { + console.log(`Adding Discussion: ${edge.node.url}`) + agendaDiscussions.push({ + id: edge.node.id, + html_url: edge.node.url, + title: edge.node.title + }) + } + } + hasNextPage = pageInfo.hasNextPage + endCursor = pageInfo.endCursor + } else { + hasNextPage = false + } + } while (hasNextPage) + } + + console.log(`Found ${agendaDiscussions.length} total discussions for agenda`) + + return agendaDiscussions +} + module.exports = { - fetchAgendaItems + fetchAgendaItems, + fetchDiscussionsItems } diff --git a/package-lock.json b/package-lock.json index c56427b..16f66bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@actions/github": "^6.0.1", "@hackmd/api": "^2.5.0", "@js-temporal/polyfill": "^0.5.1", + "@octokit/graphql": "^8.2.2", "ejs": "^3.1.10", "safe-parse-list": "^0.1.1" }, @@ -369,6 +370,20 @@ "node": ">= 18" } }, + "node_modules/@octokit/core/node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/@octokit/endpoint": { "version": "9.0.6", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", @@ -383,19 +398,97 @@ } }, "node_modules/@octokit/graphql": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", - "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz", + "integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==", "license": "MIT", "dependencies": { - "@octokit/request": "^8.4.1", - "@octokit/types": "^13.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/request": "^9.2.3", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz", + "integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", + "license": "MIT" + }, + "node_modules/@octokit/graphql/node_modules/@octokit/request": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz", + "integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^2.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0" }, "engines": { "node": ">= 18" } }, + "node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^25.1.0" + } + }, + "node_modules/@octokit/graphql/node_modules/fast-content-type-parse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", + "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/@octokit/graphql/node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" + }, "node_modules/@octokit/openapi-types": { "version": "24.2.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", diff --git a/package.json b/package.json index 3562b9c..b6f90b1 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@actions/github": "^6.0.1", "@hackmd/api": "^2.5.0", "@js-temporal/polyfill": "^0.5.1", + "@octokit/graphql": "^7.0.2", "ejs": "^3.1.10", "safe-parse-list": "^0.1.1" }, diff --git a/run.js b/run.js index 5c57fa7..d3665da 100644 --- a/run.js +++ b/run.js @@ -31,6 +31,8 @@ const pkg = require('./package.json') const issueTitle = core.getInput('issueTitle') const issueTemplate = core.getInput('issueTemplate') + const discussions = core.getBooleanInput('discussions') + // variables we use for notes const createNotes = core.getInput('createNotes') const notesUserTemplate = core.getInput('notesTemplate') @@ -96,7 +98,15 @@ const pkg = require('./package.json') } } - const agendaIssues = await agenda.fetchAgendaItems(client, repos, agendaLabel) + const agendaItems = [] + agendaItems.push(...await agenda.fetchAgendaItems(client, repos, agendaLabel)) + + if (discussions) { + const agendaDiscussions = await agenda.fetchDiscussionsItems(repos, agendaLabel, token) + agendaItems.push(...agendaDiscussions) + } + + console.log(`Found ${agendaItems.length} total items for agenda`) const opts = { ...repo, @@ -106,7 +116,7 @@ const pkg = require('./package.json') createWithin, agendaLabel, meetingLink, - agendaIssues, + agendaIssues: agendaItems, issueTitle: titleTemplate }