diff --git a/package-lock.json b/package-lock.json index 4517d33..0d6e670 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ "@liquid-labs/condition-eval": "^1.0.0-alpha.17", "@liquid-labs/federated-json": "^1.0.0-alpha.33", "@liquid-labs/git-toolkit": "^1.0.0-alpha.14", - "@liquid-labs/github-toolkit": "^1.0.0-alpha.16", + "@liquid-labs/github-toolkit": "^1.0.0-alpha.17", "@liquid-labs/http-smart-response": "^1.0.0-alpha.3", "@liquid-labs/liq-handlers-lib": "^1.0.0-alpha.13", "@liquid-labs/liq-projects-lib": "^1.0.0-alpha.12", @@ -2883,12 +2883,13 @@ } }, "node_modules/@liquid-labs/github-toolkit": { - "version": "1.0.0-alpha.16", - "resolved": "https://registry.npmjs.org/@liquid-labs/github-toolkit/-/github-toolkit-1.0.0-alpha.16.tgz", - "integrity": "sha512-DKre9wEI6sDE7Bzgf+UYUAlAK2I0E4iB2dC46TvmljlY0AOI9oI6fQZYJjcANeBa6xYG65SBGGTR0Jwvj2BZ1Q==", + "version": "1.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/@liquid-labs/github-toolkit/-/github-toolkit-1.0.0-alpha.17.tgz", + "integrity": "sha512-3JXRxIqCNCwYK06qANv57vFUnDBkbSglKtiS46EEB/FNmaYnzcGf79ClanoO9hu5FQiubF7bBVpECiPREv/AQQ==", "dependencies": { "@liquid-labs/git-toolkit": "^1.0.0-alpha.15", "@liquid-labs/octocache": "^1.0.0-alpha.3", + "@liquid-labs/semver-plus": "^1.0.0-alpha.10", "@liquid-labs/shell-toolkit": "^1.0.0-alpha.7", "http-errors": "^2.0.0" }, @@ -3037,6 +3038,48 @@ "resolved": "https://registry.npmjs.org/@liquid-labs/regex-repo/-/regex-repo-1.0.0-alpha.6.tgz", "integrity": "sha512-wxq/Gi+lGHT9lkUURiskQ42WIKpKn01H5sjPdsQkvdusuY3INY8Yi6fliIOcJNsxLI7pAKY1NqPaG019wJZ5XQ==" }, + "node_modules/@liquid-labs/semver-plus": { + "version": "1.0.0-alpha.10", + "resolved": "https://registry.npmjs.org/@liquid-labs/semver-plus/-/semver-plus-1.0.0-alpha.10.tgz", + "integrity": "sha512-4ybyePP39CAHyhFLJ1Js2s8/Mp+oBmo/i/RowrErA94uYUurFDl8q7xEOxCEPzF7IJECZMh2NcnLwZjw2r+ssA==", + "dependencies": { + "http-errors": "^2.0.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@liquid-labs/semver-plus/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@liquid-labs/semver-plus/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@liquid-labs/semver-plus/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/@liquid-labs/shell-toolkit": { "version": "1.0.0-alpha.7", "resolved": "https://registry.npmjs.org/@liquid-labs/shell-toolkit/-/shell-toolkit-1.0.0-alpha.7.tgz", diff --git a/package.json b/package.json index e9ef1e5..b1f5e56 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@liquid-labs/condition-eval": "^1.0.0-alpha.17", "@liquid-labs/federated-json": "^1.0.0-alpha.33", "@liquid-labs/git-toolkit": "^1.0.0-alpha.14", - "@liquid-labs/github-toolkit": "^1.0.0-alpha.16", + "@liquid-labs/github-toolkit": "^1.0.0-alpha.17", "@liquid-labs/http-smart-response": "^1.0.0-alpha.3", "@liquid-labs/liq-handlers-lib": "^1.0.0-alpha.13", "@liquid-labs/liq-projects-lib": "^1.0.0-alpha.12", diff --git a/src/handlers/work/_lib/answer-set-to-md.mjs b/src/handlers/work/_lib/answer-set-to-md.mjs index 3a83aab..49ff425 100644 --- a/src/handlers/work/_lib/answer-set-to-md.mjs +++ b/src/handlers/work/_lib/answer-set-to-md.mjs @@ -1,4 +1,4 @@ -import { getGitHubOrgBasenameAndVersion } from '@liquid-labs/github-toolkit' +import { getGitHubOrgAndProjectBasename } from '@liquid-labs/github-toolkit' const answerSetToMd = async({ app, @@ -61,7 +61,7 @@ const answerSetToMd = async({ md += '\n\nRelated projects: ' md += (await Promise.all(otherProjects.map(async({ name: otherProjFQN }) => { const { packageJSON: otherPkgJSON } = await app.ext._liqProjects.playgroundMonitor.getProjectData(otherProjFQN) - const { org: otherGitHubOrg } = getGitHubOrgBasenameAndVersion({ pkgJSON : otherPkgJSON }) + const { org: otherGitHubOrg } = getGitHubOrgAndProjectBasename({ pkgJSON : otherPkgJSON }) const [, otherProject] = otherProjFQN.split('/') const projectURL = await app.ext.integrations.callHook({ diff --git a/src/handlers/work/_lib/determine-work-status.mjs b/src/handlers/work/_lib/determine-work-status.mjs index f19a7be..14f6525 100644 --- a/src/handlers/work/_lib/determine-work-status.mjs +++ b/src/handlers/work/_lib/determine-work-status.mjs @@ -4,7 +4,7 @@ import { determineOriginAndMain, hasBranch } from '@liquid-labs/git-toolkit' -import { getGitHubOrgBasenameAndVersion } from '@liquid-labs/github-toolkit' +import { getGitHubOrgAndProjectBasename } from '@liquid-labs/github-toolkit' import { tryExec } from '@liquid-labs/shell-toolkit' import { WORKSPACE } from './constants' @@ -138,7 +138,7 @@ const generateProjectsReport = async({ projectStatus.pullRequests = [] reporter.push(`Retrieving pull requests associated with head '${workKey}'...`) const { packageJSON } = await app.ext._liqProjects.playgroundMonitor.getProjectData(projectFQN) - const { org: ghOrg, projectBasename } = getGitHubOrgBasenameAndVersion({ packageJSON }) + const { org: ghOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) let reportPRs = await octocache.paginate(`GET /repos/${ghOrg}/${projectBasename}/pulls`, { head : workKey, state : 'all' }) // As of 2023-03-08, the 'head' argument requires (for cross-repo merges) the name of the individual that diff --git a/src/handlers/work/_lib/save-lib.mjs b/src/handlers/work/_lib/save-lib.mjs index 009de71..633f686 100644 --- a/src/handlers/work/_lib/save-lib.mjs +++ b/src/handlers/work/_lib/save-lib.mjs @@ -184,7 +184,7 @@ const saveFiles = async({ app, backupOnly, description, files, noBackup, reporte if (impProj === undefined) { const currDir = req.get('X-CWD') npmName = (await getPackageJSON({ pkgDir : currDir })).name; - ({ projectPath } = app.ext._liqProjects.playgroundMonitor.getProjectData(npmName)) + ({ projectPath } = await app.ext._liqProjects.playgroundMonitor.getProjectData(npmName)) } return [npmName, f, projectPath] diff --git a/src/handlers/work/_lib/submit-lib.mjs b/src/handlers/work/_lib/submit-lib.mjs index 34dd34f..a0dc70f 100644 --- a/src/handlers/work/_lib/submit-lib.mjs +++ b/src/handlers/work/_lib/submit-lib.mjs @@ -4,7 +4,7 @@ import * as fsPath from 'node:path' import createError from 'http-errors' import { determineOriginAndMain, verifyBranchInSync, verifyClean } from '@liquid-labs/git-toolkit' -import { getGitHubOrgBasenameAndVersion } from '@liquid-labs/github-toolkit' +import { getGitHubOrgAndProjectBasename } from '@liquid-labs/github-toolkit' import { httpSmartResponse } from '@liquid-labs/http-smart-response' import { cleanupQAFiles, runQA, saveQAFiles } from '@liquid-labs/liq-qa-lib' import { tryExec } from '@liquid-labs/shell-toolkit' @@ -159,7 +159,7 @@ const doSubmit = async({ all, app, cache, projects, reporter, req, res, workKey const prURLs = [] for (const { name: projectFQN, private: isPrivate } of projects) { const { packageJSON, projectPath } = await app.ext._liqProjects.playgroundMonitor.getProjectData(projectFQN) - const { org: gitHubOrg, projectBasename } = getGitHubOrgBasenameAndVersion({ packageJSON }) + const { org: gitHubOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) const qaFiles = await saveQAFiles({ projectPath, reporter }) @@ -186,8 +186,6 @@ const doSubmit = async({ all, app, cache, projects, reporter, req, res, workKey const remote = setRemote({ isPrivate, projectPath }) tryExec(`cd '${projectPath}' && git push ${remote} ${workKey}`) - console.log('packageJSON:', packageJSON) // DEBUG - prURLs.push(...await app.ext.integrations.callHook({ providerFor : 'pull request', providerArgs : { pkgJSON : packageJSON }, diff --git a/src/handlers/work/_lib/work-db.mjs b/src/handlers/work/_lib/work-db.mjs index 814eaae..4f1163e 100644 --- a/src/handlers/work/_lib/work-db.mjs +++ b/src/handlers/work/_lib/work-db.mjs @@ -9,7 +9,7 @@ import { workBranchName, verifyIsOnBranch } from '@liquid-labs/git-toolkit' -import { determineGitHubLogin, getGitHubOrgBasenameAndVersion } from '@liquid-labs/github-toolkit' +import { determineGitHubLogin, getGitHubOrgAndProjectBasename } from '@liquid-labs/github-toolkit' import { crossLinkDevProjects } from '@liquid-labs/liq-projects-lib' import { Octocache } from '@liquid-labs/octocache' import { PLUGABLE_PLAYGROUND } from '@liquid-labs/plugable-defaults' @@ -70,7 +70,7 @@ const WorkDB = class WorkDB { const octocache = new Octocache({ authToken : this.#authToken }) for (const project of projects) { const { packageJSON } = await app.ext._liqProjects.playgroundMonitor.getProjectData(project) - const { org: ghOrg, projectBasename } = getGitHubOrgBasenameAndVersion({ packageJSON }) + const { org: ghOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) const projectData = await octocache.request(`GET /repos/${ghOrg}/${projectBasename}`) workData.projects.push({ name : project, @@ -143,7 +143,7 @@ const WorkDB = class WorkDB { reporter.push(`Processing work branch for ${project}...`) const { packageJSON, projectPath } = await app.ext._liqProjects.playgroundMonitor.getProjectData(project) - const { org: ghOrg, projectBasename } = getGitHubOrgBasenameAndVersion({ packageJSON }) + const { org: ghOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) let repoData const ghProject = ghOrg + '/' + projectBasename diff --git a/src/handlers/work/issues/_lib/add-lib.mjs b/src/handlers/work/issues/_lib/add-lib.mjs index 3466308..982209d 100644 --- a/src/handlers/work/issues/_lib/add-lib.mjs +++ b/src/handlers/work/issues/_lib/add-lib.mjs @@ -1,4 +1,4 @@ -import { claimIssues, getGitHubOrgBasenameAndVersion, verifyIssuesAvailable } from '@liquid-labs/github-toolkit' +import { claimIssues, getGitHubOrgAndProjectBasename, verifyIssuesAvailable } from '@liquid-labs/github-toolkit' import { httpSmartResponse } from '@liquid-labs/http-smart-response' import { Octocache } from '@liquid-labs/octocache' @@ -20,7 +20,7 @@ const doAddIssues = async({ app, cache, reporter, req, res, workKey }) => { const primaryProject = workData.projects[0].name const { packageJSON } = await app.ext._liqProjects.playgroundMonitor.getProjectData(primaryProject) - const { org: ghOrg, projectBasename } = getGitHubOrgBasenameAndVersion({ packageJSON }) + const { org: ghOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) issues = issues.map((i) => i.match(/^\d+$/) ? ghOrg + '/' + projectBasename + '/' + i : i) await verifyIssuesAvailable({ authToken, issues, noAutoAssign, notClosed : true, reporter }) diff --git a/src/handlers/work/start.mjs b/src/handlers/work/start.mjs index e882a26..2fdbeeb 100644 --- a/src/handlers/work/start.mjs +++ b/src/handlers/work/start.mjs @@ -2,6 +2,7 @@ import createError from 'http-errors' import { claimIssues, + createIssue, determineGitHubLogin, getGitHubOrgAndProjectBasename, verifyIssuesAvailable @@ -22,6 +23,27 @@ const help = { const method = 'post' const path = ['work', 'start'] const parameters = [ + { + name : 'issueBug', + isBoolean : true, + description : "Labels the created issue as a 'bug' rather than the default 'enhancement'. Only valid when 'createIssues' is set." + }, + { + name : 'issueDeliverables', + description : "A list of newline or a double semi-colon (';;') seperated deliverables items. Only valid when 'createIssue' is set." + }, + { + name : 'issueNotes', + description : "Notes to include in the issue body. Only valid when 'createIssue' is set." + }, + { + name : 'issueOverview', + description : "The overview text to use when creating an issue. Only valid if 'createIssue' is set." + }, + { + name : 'issueTitle', + description : "Creates an issue with the given title. Requires 'issueOverview' and 'issueDeliverables' also be set." + }, { name : 'projects', isMultivalue : true, @@ -36,7 +58,30 @@ Object.freeze(parameters) const func = ({ app, cache, reporter }) => async(req, res) => { reporter = reporter.isolate() - let { assignee, comment, issues, noAutoAssign = false, projects } = req.vars + const { + assignee, + comment, + issueBug, + issueDeliverables, + issueNotes, + issueOverview, + issueTitle, + noAutoAssign = false + } = req.vars + let { issues = [], projects } = req.vars + + if (issues.length === 0 && issueTitle === undefined) { + throw createError.BadRequest("Must provides 'issues' or create an issue with 'issueTitle', etc.") + } + + if (issueTitle !== undefined && (issueDeliverables === undefined || issueOverview === undefined)) { + throw createError.BadRequest("Parameters 'issueOverview' and 'issueDeliverables' must be provided when 'issueTitle' is set.") + } + else if (issueTitle === undefined + && (issueBug !== undefined || issueDeliverables !== undefined || issueOverview !== undefined || issueNotes !== undefined)) { + throw createError.BadRequest("Parameters 'issueBug', 'issueOverview', 'issueDeliverables', and 'issueNotes' are only valid when 'issueTitle' is set.") + } + // First, let's process projects. If nothing specified, assume the current, implied project. if (projects === undefined) { const currPkgJSON = await getPackageJSON({ pkgDir : req.get('X-CWD') }) @@ -50,19 +95,54 @@ const func = ({ app, cache, reporter }) => async(req, res) => { } } + // technically, we dont't always need this, but we usually do; this is the data for the 'primary' project + const { packageJSON } = await app.ext._liqProjects.playgroundMonitor.getProjectData(projects[0]) + const { org: ghOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) + + const credDB = app.ext.credentialsDB + const authToken = await credDB.getToken('GITHUB_API') + + if (issueTitle !== undefined) { + const labels = [] + if (issueBug === true) { + labels.push('bug') + } + else { + labels.push('enhancement') + } + + const deliverables = issueDeliverables.split(/(?:\n|;;)/) + const deliverablesText = '- [ ] ' + deliverables.join('\n- [ ] ') + + let issueBody = `## Overview +${issueOverview} + +## Deliverables + +${deliverablesText}` + + if (issueNotes !== undefined) { + issueBody += ` + +## Notes + +${issueNotes}` + } // if (notes) + + const projectFQN = ghOrg + '/' + projectBasename + + const { number } = await createIssue({ authToken, projectFQN, title : issueTitle, body : issueBody, labels, reporter }) + issues.unshift(number + '') + }// if (createIssue) + // Normalize issues as '//' issues = await Promise.all(issues.map(async(i) => { if (i.match(/^\d+$/)) { - const { packageJSON } = await app.ext._liqProjects.playgroundMonitor.getProjectData(projects[0]) - const { org: ghOrg, projectBasename } = getGitHubOrgAndProjectBasename({ packageJSON }) return ghOrg + '/' + projectBasename + '/' + i } return i })) - const credDB = app.ext.credentialsDB - const authToken = await credDB.getToken('GITHUB_API') - const githubLogin = (await determineGitHubLogin({ authToken })).login // TODO: this should be an integration hook point await verifyIssuesAvailable({ authToken, availableFor : githubLogin, issues, noAutoAssign, reporter })