From 3d13e7cfaa29506db2ed6431dedba82e0f2757f8 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 7 Aug 2025 21:40:29 -0500 Subject: [PATCH 1/3] feat: support github discussions Signed-off-by: Sebastian Beltran --- package-lock.json | 92 ++++++++++++++++++++++++++++++++++++++++++----- package.json | 1 + run.js | 66 ++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index c56427b..b612045 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": "^9.0.1", "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,81 @@ } }, "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": "9.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz", + "integrity": "sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==", "license": "MIT", "dependencies": { - "@octokit/request": "^8.4.1", - "@octokit/types": "^13.0.0", - "universal-user-agent": "^6.0.0" + "@octokit/request": "^10.0.2", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">= 18" + "node": ">= 20" } }, + "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", + "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "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": "10.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", + "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.0", + "@octokit/request-error": "^7.0.0", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", + "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "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/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", @@ -2210,7 +2287,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", - "dev": true, "funding": [ { "type": "github", diff --git a/package.json b/package.json index 3562b9c..25f3191 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": "^9.0.1", "ejs": "^3.1.10", "safe-parse-list": "^0.1.1" }, diff --git a/run.js b/run.js index 5c57fa7..6085822 100644 --- a/run.js +++ b/run.js @@ -1,6 +1,7 @@ 'use strict' const core = require('@actions/core') const { getOctokit, context } = require('@actions/github') +const { graphql } = require('@octokit/graphql') const list = require('safe-parse-list') const ejs = require('ejs') const meetings = require('./lib/meetings') @@ -97,6 +98,71 @@ const pkg = require('./package.json') } const agendaIssues = await agenda.fetchAgendaItems(client, repos, agendaLabel) + + 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}`) + agendaIssues.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 ${agendaIssues.length} total issues for agenda`) const opts = { ...repo, From 16b5a799061178cbf3a4c55108971614bd302ba2 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 21 Aug 2025 22:03:19 -0500 Subject: [PATCH 2/3] chore: separate discussions logic Signed-off-by: Sebastian Beltran --- action.yml | 4 +++ lib/agenda.js | 80 +++++++++++++++++++++++++++++++++++++++++++++-- package-lock.json | 59 +++++++++++++++++++++------------- package.json | 2 +- run.js | 76 ++++++-------------------------------------- 5 files changed, 131 insertions(+), 90 deletions(-) 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 b612045..16f66bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@actions/github": "^6.0.1", "@hackmd/api": "^2.5.0", "@js-temporal/polyfill": "^0.5.1", - "@octokit/graphql": "^9.0.1", + "@octokit/graphql": "^8.2.2", "ejs": "^3.1.10", "safe-parse-list": "^0.1.1" }, @@ -398,30 +398,30 @@ } }, "node_modules/@octokit/graphql": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz", - "integrity": "sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==", + "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": "^10.0.2", + "@octokit/request": "^9.2.3", "@octokit/types": "^14.0.0", "universal-user-agent": "^7.0.0" }, "engines": { - "node": ">= 20" + "node": ">= 18" } }, "node_modules/@octokit/graphql/node_modules/@octokit/endpoint": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", - "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", + "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": ">= 20" + "node": ">= 18" } }, "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { @@ -431,31 +431,31 @@ "license": "MIT" }, "node_modules/@octokit/graphql/node_modules/@octokit/request": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", - "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", + "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": "^11.0.0", - "@octokit/request-error": "^7.0.0", + "@octokit/endpoint": "^10.1.4", + "@octokit/request-error": "^6.1.8", "@octokit/types": "^14.0.0", - "fast-content-type-parse": "^3.0.0", + "fast-content-type-parse": "^2.0.0", "universal-user-agent": "^7.0.2" }, "engines": { - "node": ">= 20" + "node": ">= 18" } }, "node_modules/@octokit/graphql/node_modules/@octokit/request-error": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", - "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", + "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": ">= 20" + "node": ">= 18" } }, "node_modules/@octokit/graphql/node_modules/@octokit/types": { @@ -467,6 +467,22 @@ "@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", @@ -2287,6 +2303,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "dev": true, "funding": [ { "type": "github", diff --git a/package.json b/package.json index 25f3191..e5c3bc5 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@actions/github": "^6.0.1", "@hackmd/api": "^2.5.0", "@js-temporal/polyfill": "^0.5.1", - "@octokit/graphql": "^9.0.1", + "@octokit/graphql": "^8.2.2", "ejs": "^3.1.10", "safe-parse-list": "^0.1.1" }, diff --git a/run.js b/run.js index 6085822..d3665da 100644 --- a/run.js +++ b/run.js @@ -1,7 +1,6 @@ 'use strict' const core = require('@actions/core') const { getOctokit, context } = require('@actions/github') -const { graphql } = require('@octokit/graphql') const list = require('safe-parse-list') const ejs = require('ejs') const meetings = require('./lib/meetings') @@ -32,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') @@ -97,72 +98,15 @@ const pkg = require('./package.json') } } - const agendaIssues = await agenda.fetchAgendaItems(client, repos, agendaLabel) - - 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}`) - agendaIssues.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) + 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 ${agendaIssues.length} total issues for agenda`) + console.log(`Found ${agendaItems.length} total items for agenda`) const opts = { ...repo, @@ -172,7 +116,7 @@ const pkg = require('./package.json') createWithin, agendaLabel, meetingLink, - agendaIssues, + agendaIssues: agendaItems, issueTitle: titleTemplate } From 253ccb1f190dddee693b3a6db5120131388cabb7 Mon Sep 17 00:00:00 2001 From: Sebastian Beltran Date: Thu, 21 Aug 2025 22:07:33 -0500 Subject: [PATCH 3/3] fix: downgrade @octokit/graphql to version 7.0.2 for compatibility Signed-off-by: Sebastian Beltran --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e5c3bc5..b6f90b1 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@actions/github": "^6.0.1", "@hackmd/api": "^2.5.0", "@js-temporal/polyfill": "^0.5.1", - "@octokit/graphql": "^8.2.2", + "@octokit/graphql": "^7.0.2", "ejs": "^3.1.10", "safe-parse-list": "^0.1.1" },