diff --git a/.github/ISSUE_TEMPLATE/meeting.md b/.github/ISSUE_TEMPLATE/meeting.md index 518c317..7122465 100644 --- a/.github/ISSUE_TEMPLATE/meeting.md +++ b/.github/ISSUE_TEMPLATE/meeting.md @@ -31,7 +31,7 @@ Extracted from **<%= agendaLabel %>** labelled issues and pull requests from **< ## Links -* Minutes: +* Minutes: <%= meetingNotes || '' %> ### Joining the meeting diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8cb9b5f..2b9d550 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -50,5 +50,6 @@ jobs: createWithin: P2D labels: meeting, test agendaLabel: meeting-agenda-test + createNotes: true - name: clean up issue run: node ./test/_close-issue.js ${{ secrets.GITHUB_TOKEN }} ${{ steps.maker.outputs.issueNumber }} diff --git a/action.yml b/action.yml index 26c2497..be3e9ea 100644 --- a/action.yml +++ b/action.yml @@ -31,6 +31,14 @@ inputs: description: 'A name of an issue template (found in .github/ISSUE_TEMPLATES)' default: 'meeting.md' required: true + createNotes: + description: 'Create meeting notes on HackMD' + default: 'false' + required: false + notesUserTemplate: + description: 'A name of an issue template (found in .github/meet)' + default: 'notes.md' + required: false outputs: issueNumber: description: 'If an issue was created, this will be its number' diff --git a/lib/default-notes-template.js b/lib/default-notes-template.js new file mode 100644 index 0000000..6d79327 --- /dev/null +++ b/lib/default-notes-template.js @@ -0,0 +1,29 @@ +'use strict' + +module.exports = ({ agendaIssues, agendaLabel, owner, repo, issue }) => { + return ` +# ${issue.title} + +## Links + + * **Recording**: + * **GitHub Issue**: https://github.com/${owner}/${repo}/issues/${issue.number} + +## Present + + * + +## Announcements + +## Agenda + +*Extracted from **${agendaLabel}** labelled issues and pull requests from the **${owner} org** prior to the meeting. + +${agendaIssues.map((i) => { + return `* ${i.title} [#${i.number}](${i.html_url})` +}).join('\n')} + +## Q&A, Other + +` +} diff --git a/lib/default-template.js b/lib/default-template.js index 2ece1ed..9ff078e 100644 --- a/lib/default-template.js +++ b/lib/default-template.js @@ -1,6 +1,6 @@ 'use strict' -module.exports = ({ date, agendaIssues, agendaLabel, owner, repo }) => { +module.exports = ({ date, agendaIssues, agendaLabel, meetingNotes, owner, repo }) => { return ` ## Date/Time @@ -35,7 +35,7 @@ ${agendaIssues.map((i) => { ## Links -* Minutes: +* Minutes: ${meetingNotes || ''} ### Joining the meeting diff --git a/lib/issues.js b/lib/issues.js index 843dd8b..a44526f 100644 --- a/lib/issues.js +++ b/lib/issues.js @@ -12,6 +12,17 @@ module.exports.create = async function (client, issue) { return resp } +module.exports.update = async function (client, issue) { + const resp = await client.issues.update({ + owner: issue.owner, + repo: issue.repo, + issue_number: issue.issue_number, + body: issue.body + }) + + return resp +} + module.exports.getMeetingIssues = async function (client, opts) { const resp = await client.issues.listForRepo({ owner: opts.owner, diff --git a/lib/meetings.js b/lib/meetings.js index 71c7e41..ec3d537 100644 --- a/lib/meetings.js +++ b/lib/meetings.js @@ -11,10 +11,37 @@ module.exports.createNextMeeting = async function (client, opts) { return issues.create(client, meetingToCreate) } +module.exports.setMeetingIssueBody = async function (client, opts) { + const issue = await getNextIssue(client, opts) + issue.body = typeof opts.template === 'function' ? opts.template(issue) : opts.template + return issues.update(client, issue) +} + +async function getNextIssue (client, opts) { + const now = opts.now || DateTime.utc() + const date = getNextScheduledMeeting(opts.schedules, now) + const title = typeof opts.issueTitle === 'function' ? opts.issueTitle({ date }) : opts.issueTitle + + const issue = { + owner: opts.owner, + repo: opts.repo, + title, + date, + agendaLabel: opts.agendaLabel, + agendaIssues: opts.agendaIssues, + labels: opts.labels, + meetingNotes: opts.meetingNotes || '', + issue_number: (opts.issue || {}).number || null, + body: '' + } + return issue +} + const shouldCreateNextMeetingIssue = module.exports.shouldCreateNextMeetingIssue = async function (client, opts = {}) { const now = opts.now || DateTime.utc() const createWithin = Duration.fromISO(opts.createWithin) - const next = getNextScheduledMeeting(opts.schedules, now) + const issue = getNextIssue(client, opts) + const { date: next, title: nextIssueTitle } = issue // Further out than the create within limit if (next > now.plus(createWithin)) { @@ -27,7 +54,6 @@ const shouldCreateNextMeetingIssue = module.exports.shouldCreateNextMeetingIssue label: opts.labels }) - const nextIssueTitle = typeof opts.issueTitle === 'function' ? opts.issueTitle({ date: next }) : opts.issueTitle const shouldCreate = !meetings.find((i) => { return i.title === nextIssueTitle }) @@ -36,25 +62,6 @@ const shouldCreateNextMeetingIssue = module.exports.shouldCreateNextMeetingIssue } // Load issues for agenda - const agendaLabel = opts.agendaLabel - const agendaResp = await client.issues.listForRepo({ - owner: opts.owner, - repo: opts.repo, - state: 'open', - labels: agendaLabel - }) - - const issue = { - owner: opts.owner, - repo: opts.repo, - title: nextIssueTitle, - date: next, - agendaLabel: agendaLabel, - agendaIssues: agendaResp.data, - labels: opts.labels, - body: null - } - issue.body = typeof opts.template === 'function' ? opts.template(issue) : opts.template return issue } diff --git a/lib/notes.js b/lib/notes.js new file mode 100644 index 0000000..8ab8c4a --- /dev/null +++ b/lib/notes.js @@ -0,0 +1,25 @@ +'use strict' + +const { default: HackMD } = require('@hackmd/api') +const defaultNotesTemplate = require('./default-notes-template') + +module.exports.create = function createNote (notesTemplate, opts) { + const note = typeof notesTemplate === 'function' ? notesTemplate(opts) : notesTemplate || defaultNotesTemplate(opts) + const hackmd = new HackMD() + + return hackmd.newNote(note) +} + +async function getNotesTemplate (client, opts) { + const resp = await client.repos.getContents({ + owner: opts.owner, + repo: opts.repo, + path: `.github/meet/${opts.notesTemplate}` + }) + if (resp.statusCode === 404) { + return false + } + return Buffer.from(resp.data.content, resp.data.encoding).toString() +} + +module.exports.getNotesTemplate = getNotesTemplate diff --git a/package-lock.json b/package-lock.json index 3fd7938..5bac6aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,20 @@ "js-tokens": "^4.0.0" } }, + "@hackmd/api": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@hackmd/api/-/api-1.1.1.tgz", + "integrity": "sha512-uihajFT/SgV8+zzq/Jk9ovtOWzOzai15wD+EKqnhIuZis+IvpFPLb04iG5duFojx/ZH8jipRrk5zKKoUkVy9oA==", + "requires": { + "cheerio": "^1.0.0-rc.3", + "fetch-cookie": "^0.8.0", + "fs-extra": "^9.0.0", + "node-fetch": "^2.6.0", + "tough-cookie": "^3.0.0", + "tough-cookie-filestore": "^0.0.1", + "tslib": "^1.11.1" + } + }, "@octokit/auth-token": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.0.tgz", @@ -307,6 +321,11 @@ "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "dev": true }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, "atob-lite": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", @@ -329,6 +348,11 @@ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -399,6 +423,19 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + } + }, "chokidar": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", @@ -515,6 +552,22 @@ } } }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -593,6 +646,37 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, "dotenv": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", @@ -618,6 +702,11 @@ "once": "^1.4.0" } }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -1067,6 +1156,14 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fetch-cookie": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/fetch-cookie/-/fetch-cookie-0.8.0.tgz", + "integrity": "sha512-3EzzY298LQL2Iau5VvmnbOXw1/gvAHD/Jm4wDCUn0RFrEijp+1RoJkeKmAyi2oXC32374p7cPBI+QmmD9hg+Xg==", + "requires": { + "tough-cookie": "^2.3.3 || ^3.0.1 || ^4.0.0" + } + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -1135,6 +1232,17 @@ "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, + "fs-extra": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz", + "integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -1215,8 +1323,7 @@ "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", - "dev": true + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" }, "growl": { "version": "1.10.5", @@ -1257,6 +1364,19 @@ "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1301,8 +1421,7 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "inquirer": { "version": "7.1.0", @@ -1415,6 +1534,11 @@ } } }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -1568,6 +1692,15 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" + } + }, "jsx-ast-utils": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", @@ -1613,8 +1746,7 @@ "lodash": { "version": "4.17.19", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" }, "lodash.get": { "version": "4.4.2", @@ -1801,6 +1933,14 @@ "path-key": "^2.0.0" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "requires": { + "boolbase": "~1.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1981,6 +2121,14 @@ "error-ex": "^1.2.0" } }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "requires": { + "@types/node": "*" + } + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -2160,6 +2308,11 @@ "react-is": "^16.8.1" } }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -2172,8 +2325,7 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "react-is": { "version": "16.13.1", @@ -2247,6 +2399,16 @@ } } }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "readdirp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", @@ -2332,6 +2494,11 @@ "tslib": "^1.9.0" } }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, "safe-parse-list": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/safe-parse-list/-/safe-parse-list-0.1.1.tgz", @@ -2503,6 +2670,14 @@ "es-abstract": "^1.17.5" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -2608,11 +2783,38 @@ "is-number": "^7.0.0" } }, + "tough-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", + "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "requires": { + "ip-regex": "^2.1.0", + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tough-cookie-filestore": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tough-cookie-filestore/-/tough-cookie-filestore-0.0.1.tgz", + "integrity": "sha1-C/IwjtKTpQugcz7X1iiWAUhVcLY=", + "requires": { + "tough-cookie": "~0.12.1" + }, + "dependencies": { + "tough-cookie": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.12.1.tgz", + "integrity": "sha1-giDH4hq9WxPZaAQlS9WoHr8sfWI=", + "requires": { + "punycode": ">=0.2.0" + } + } + } + }, "tslib": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", - "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", - "dev": true + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==" }, "tunnel": { "version": "0.0.6", @@ -2648,6 +2850,11 @@ "os-name": "^3.1.0" } }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -2657,6 +2864,11 @@ "punycode": "^2.1.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", diff --git a/package.json b/package.json index 8a2489c..9a26519 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dependencies": { "@actions/core": "^1.2.6", "@actions/github": "^2.1.1", + "@hackmd/api": "^1.1.1", "ejs": "^3.0.2", "luxon": "^1.23.0", "safe-parse-list": "^0.1.1" diff --git a/run.js b/run.js index 9db0bd7..0956d43 100644 --- a/run.js +++ b/run.js @@ -5,7 +5,9 @@ const list = require('safe-parse-list') const ejs = require('ejs') const meetings = require('./lib/meetings') const issues = require('./lib/issues') +const notes = require('./lib/notes') const defaultTemplate = require('./lib/default-template') +const defaultNotesTemplate = require('./lib/default-notes-template') ;(async function run () { try { @@ -23,6 +25,10 @@ const defaultTemplate = require('./lib/default-template') const issueTitle = core.getInput('issueTitle') const issueTemplate = core.getInput('issueTemplate') + // variables we use for notes + const createNotes = core.getInput('createNotes') + const notesUserTemplate = core.getInput('notesTemplate') + const repo = github.context.repo const client = new github.GitHub(token) @@ -48,21 +54,56 @@ const defaultTemplate = require('./lib/default-template') } } - const issue = await meetings.createNextMeeting(client, { + const agendaIssues = (await client.issues.listForRepo({ + owner: repo.owner, + repo: repo.repo, + state: 'open', + labels: agendaLabel + })).data || [] + const opts = { ...repo, schedules, - template, labels, createWithin, agendaLabel, + agendaIssues, issueTitle: titleTemplate - }) + } + + const issue = await meetings.createNextMeeting(client, { ...opts, template }) if (!issue) { return console.log('No issues to create') } - core.setOutput('issueNumber', issue.data.number.toString()) - console.log(`Issue created: (#${issue.data.number}) ${issue.data.title}`) + const issueNumber = issue.data.number + core.setOutput('issueNumber', issueNumber.toString()) + console.log(`Issue created: (#${issueNumber}) ${issue.data.title}`) + + opts.issue = issue.data + + if (createNotes === true || createNotes === 'true') { + let notesTemplate = defaultNotesTemplate + if (notesUserTemplate) { + try { + const tmpl = await notes.getNotesTemplate(client, { + ...repo, + notesUserTemplate + }) + notesTemplate = ejs.compile(tmpl) + } catch (e) { + console.error(`notesTemplate missing or invalid (${notesUserTemplate}): ${e.message}`) + } + } + opts.meetingNotes = await notes.create(notesTemplate, opts) + console.log(`Notes created: ${opts.meetingNotes}`) + } + + const updatedIssue = await meetings.setMeetingIssueBody(client, { ...opts, template }) + if (!updatedIssue) { + return console.log('No issues to update') + } else { + return console.log('Issue updated successfully') + } } catch (e) { console.error(e) core.setFailed(e.message)