diff --git a/automation/deploy-bin.ts b/automation/deploy-bin.ts index 4038eeb7..20e18407 100644 --- a/automation/deploy-bin.ts +++ b/automation/deploy-bin.ts @@ -16,7 +16,7 @@ */ import * as Bluebird from 'bluebird'; import * as _ from 'lodash'; -import * as publishRelease from 'publish-release'; +import * as semver from 'semver'; import { finalReleaseAssets, version } from './build-bin'; @@ -28,6 +28,7 @@ const { GITHUB_TOKEN } = process.env; */ export async function createGitHubRelease() { console.log(`Publishing release ${version} to GitHub`); + const publishRelease = await import('publish-release'); const ghRelease = await Bluebird.fromCallback( publishRelease.bind(null, { token: GITHUB_TOKEN || '', @@ -57,3 +58,201 @@ export async function release() { process.exit(1); } } + +let cachedOctokit: any; + +/** Return a cached Octokit instance, creating a new one as needed. */ +function getOctokit(): any { + if (cachedOctokit) { + return cachedOctokit; + } + const Octokit = require('@octokit/rest').plugin( + require('@octokit/plugin-throttling'), + ); + return (cachedOctokit = new Octokit({ + auth: GITHUB_TOKEN, + throttle: { + onRateLimit: (retryAfter: number, options: any) => { + console.warn( + `Request quota exhausted for request ${options.method} ${ + options.url + }`, + ); + // retries 3 times + if (options.request.retryCount < 3) { + console.log(`Retrying after ${retryAfter} seconds!`); + return true; + } + }, + onAbuseLimit: (_retryAfter: number, options: any) => { + // does not retry, only logs a warning + console.warn( + `Abuse detected for request ${options.method} ${options.url}`, + ); + }, + }, + })); +} + +/** + * Extract pagination information (current page, total pages, ordinal number) + * from the 'link' response header (example below), using the parse-link-header + * npm package: + * "link": "; rel=\"next\", + * ; rel=\"last\"" + * + * @param response Octokit response object (including response.headers.link) + * @param perPageDefault Default per_page pagination value if missing in URL + * @return Object where 'page' is the current page number (1-based), + * 'pages' is the total number of pages, and 'ordinal' is the ordinal number + * (3rd, 4th, 5th...) of the first item in the current page. + */ +function getPageNumbers( + response: any, + perPageDefault: number, +): { page: number; pages: number; ordinal: number } { + const res = { page: 1, pages: 1, ordinal: 1 }; + if (!response.headers.link) { + return res; + } + const parse = require('parse-link-header'); + const parsed = parse(response.headers.link); + let perPage = perPageDefault; + if (parsed.next) { + if (parsed.next.per_page) { + perPage = parseInt(parsed.next.per_page, 10); + } + res.page = parseInt(parsed.next.page, 10) - 1; + res.pages = parseInt(parsed.last.page, 10); + } else { + if (parsed.prev.per_page) { + perPage = parseInt(parsed.prev.per_page, 10); + } + res.page = res.pages = parseInt(parsed.prev.page, 10) + 1; + } + res.ordinal = (res.page - 1) * perPage + 1; + return res; +} + +/** + * Iterate over every GitHub release in the given owner/repo, check whether + * its tag_name matches against the affectedVersions semver spec, and if so + * replace its release description (body) with the given newDescription value. + * @param owner GitHub repo owner, e.g. 'balena-io' or 'pdcastro' + * @param repo GitHub repo, e.g. 'balena-cli' + * @param affectedVersions Semver spec, e.g. '2.6.1 - 7.10.9 || 8.0.0' + * @param newDescription New release description (body) + * @param editID Short string present in newDescription, e.g. '[AA101]', that + * can be searched to determine whether that release has already been updated. + */ +async function updateGitHubReleaseDescriptions( + owner: string, + repo: string, + affectedVersions: string, + newDescription: string, + editID: string, +) { + const perPage = 30; + const octokit = getOctokit(); + const options = await octokit.repos.listReleases.endpoint.merge({ + owner, + repo, + per_page: perPage, + }); + let errCount = 0; + for await (const response of octokit.paginate.iterator(options)) { + const { page: thisPage, pages: totalPages, ordinal } = getPageNumbers( + response, + perPage, + ); + let i = 0; + for (const cliRelease of response.data) { + const prefix = `[#${ordinal + i++} pg ${thisPage}/${totalPages}]`; + if (!cliRelease.id) { + console.error( + `${prefix} Error: missing release ID (errCount=${++errCount})`, + ); + continue; + } + const skipMsg = `${prefix} skipping release "${cliRelease.tag_name}" (${ + cliRelease.id + })`; + if (cliRelease.draft === true) { + console.info(`${skipMsg}: draft release`); + continue; + } else if (cliRelease.body && cliRelease.body.includes(editID)) { + console.info(`${skipMsg}: already updated`); + continue; + } else if (!semver.satisfies(cliRelease.tag_name, affectedVersions)) { + console.info(`${skipMsg}: outside version range`); + continue; + } else { + const updatedRelease = { + owner, + repo, + release_id: cliRelease.id, + body: newDescription, + }; + let oldBodyPreview = cliRelease.body; + if (oldBodyPreview) { + oldBodyPreview = oldBodyPreview.replace(/\s+/g, ' ').trim(); + if (oldBodyPreview.length > 12) { + oldBodyPreview = oldBodyPreview.substring(0, 9) + '...'; + } + } + console.info( + `${prefix} updating release "${cliRelease.tag_name}" (${ + cliRelease.id + }) old body="${oldBodyPreview}"`, + ); + try { + await octokit.repos.updateRelease(updatedRelease); + } catch (err) { + console.error( + `${skipMsg}: Error: ${err.message} (count=${++errCount})`, + ); + continue; + } + } + } + } +} + +/** + * Add a warning description to CLI releases affected by a mixpanel tracking + * security issue (#1359). This function can be executed "manually" with the + * following command line: + * + * npx ts-node --type-check -P automation/tsconfig.json automation/run.ts fix1359 + */ +export async function updateDescriptionOfReleasesAffectedByIssue1359() { + // Run only on Linux/Node10, instead of all platform/Node combinations. + // (It could have been any other platform, as long as it only runs once.) + if (process.platform !== 'linux' || semver.major(process.version) !== 10) { + return; + } + const owner = 'balena-io'; + const repo = 'balena-cli'; + const affectedVersions = + '2.6.1 - 7.10.9 || 8.0.0 - 8.1.0 || 9.0.0 - 9.15.6 || 10.0.0 - 10.17.5 || 11.0.0 - 11.7.2'; + const editID = '[AA100]'; + let newDescription = ` + Please note: the "login" command in this release is affected by a + security issue fixed in versions + [7.10.10](https://github.com/balena-io/balena-cli/releases/tag/v7.10.10), + [8.1.1](https://github.com/balena-io/balena-cli/releases/tag/v8.1.1), + [9.15.7](https://github.com/balena-io/balena-cli/releases/tag/v9.15.7), + [10.17.6](https://github.com/balena-io/balena-cli/releases/tag/v10.17.6), + [11.7.3](https://github.com/balena-io/balena-cli/releases/tag/v11.7.3) + and later. If you need to use this version, avoid passing your password, + keys or tokens as command-line arguments. ${editID}`; + // remove line breaks and collapse white space + newDescription = newDescription.replace(/\s+/g, ' ').trim(); + await updateGitHubReleaseDescriptions( + owner, + repo, + affectedVersions, + newDescription, + editID, + ); +} diff --git a/automation/run.ts b/automation/run.ts index e298b6e6..c31e557c 100644 --- a/automation/run.ts +++ b/automation/run.ts @@ -24,7 +24,16 @@ import { ROOT, runUnderMsys, } from './build-bin'; -import { release } from './deploy-bin'; +import { + release, + updateDescriptionOfReleasesAffectedByIssue1359, +} from './deploy-bin'; + +function exitWithError(error: Error | string): never { + console.error(`Error: ${error}`); + process.exit(1); + throw error; // to please the Typescript compiler +} /** * Trivial command-line parser. Check whether the command-line argument is one @@ -43,17 +52,17 @@ export async function run(args?: string[]) { console.log(`automation/run.ts process.argv=[${process.argv}]\n`); console.log(`automation/run.ts args=[${args}]`); if (_.isEmpty(args)) { - console.error('Error: missing args'); - process.exit(1); + return exitWithError('missing command-line arguments'); } const commands: { [cmd: string]: () => void } = { 'build:installer': buildOclifInstaller, 'build:standalone': buildStandaloneZip, + fix1359: updateDescriptionOfReleasesAffectedByIssue1359, release, }; for (const arg of args) { if (!commands.hasOwnProperty(arg)) { - throw new Error(`Error: unknown build target: ${arg}`); + return exitWithError(`command unknown: ${arg}`); } } @@ -98,8 +107,7 @@ export async function run(args?: string[]) { const cmdFunc = commands[arg]; await cmdFunc(); } catch (err) { - console.log(`Error running command "${arg}": ${err}`); - process.exit(1); + return exitWithError(`"${arg}": ${err}`); } } } diff --git a/automation/tsconfig.json b/automation/tsconfig.json index 83d916dc..919dd14a 100644 --- a/automation/tsconfig.json +++ b/automation/tsconfig.json @@ -4,7 +4,7 @@ "target": "es2017", "strict": true, "strictPropertyInitialization": false, - "noUnusedLocals": true, + "noUnusedLocals": false, "noUnusedParameters": true, "preserveConstEnums": true, "removeComments": true, diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index c82f0981..faf3e29d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -301,6 +301,113 @@ "resolved": "https://registry.npmjs.org/@oclif/screen/-/screen-1.0.4.tgz", "integrity": "sha512-60CHpq+eqnTxLZQ4PGHYNwUX572hgpMHGPtTWMjdTMsAvlm69lZV/4ly6O3sAYkomo4NggGcomrDpBe34rxUqw==" }, + "@octokit/endpoint": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.3.2.tgz", + "integrity": "sha512-gRjteEM9I6f4D8vtwU2iGUTn9RX/AJ0SVXiqBUEuYEWVGGAVjSXdT0oNmghH5lvQNWs8mwt6ZaultuG6yXivNw==", + "dev": true, + "requires": { + "deepmerge": "4.0.0", + "is-plain-object": "^3.0.0", + "universal-user-agent": "^3.0.0", + "url-template": "^2.0.8" + }, + "dependencies": { + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", + "dev": true, + "requires": { + "isobject": "^4.0.0" + } + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + } + } + }, + "@octokit/plugin-throttling": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-2.6.0.tgz", + "integrity": "sha512-E0xQrcD36sVEeBhut6j9nWX38vm/1LKMRSUqjvJ/mqGLXfHr4jYMsrR3I/nT2QC0eJL1/SKMt7zxOt7pZiFhDA==", + "dev": true, + "requires": { + "bottleneck": "^2.15.3" + } + }, + "@octokit/request": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.0.2.tgz", + "integrity": "sha512-z1BQr43g4kOL4ZrIVBMHwi68Yg9VbkRUyuAgqCp1rU3vbYa69+2gIld/+gHclw15bJWQnhqqyEb7h5a5EqgZ0A==", + "dev": true, + "requires": { + "@octokit/endpoint": "^5.1.0", + "@octokit/request-error": "^1.0.1", + "deprecation": "^2.0.0", + "is-plain-object": "^3.0.0", + "node-fetch": "^2.3.0", + "once": "^1.4.0", + "universal-user-agent": "^3.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", + "dev": true, + "requires": { + "isobject": "^4.0.0" + } + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + }, + "node-fetch": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", + "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "dev": true + } + } + }, + "@octokit/request-error": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.0.4.tgz", + "integrity": "sha512-L4JaJDXn8SGT+5G0uX79rZLv0MNJmfGa4vb4vy1NnpjSnWDLJRy6m90udGwvMmavwsStgbv2QNkPzzTCMmL+ig==", + "dev": true, + "requires": { + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "16.28.7", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.28.7.tgz", + "integrity": "sha512-cznFSLEhh22XD3XeqJw51OLSfyL2fcFKUO+v2Ep9MTAFfFLS1cK1Zwd1yEgQJmJoDnj4/vv3+fGGZweG+xsbIA==", + "dev": true, + "requires": { + "@octokit/request": "^5.0.0", + "@octokit/request-error": "^1.0.2", + "atob-lite": "^2.0.0", + "before-after-hook": "^2.0.0", + "btoa-lite": "^1.0.0", + "deprecation": "^2.0.0", + "lodash.get": "^4.4.2", + "lodash.set": "^4.3.2", + "lodash.uniq": "^4.5.0", + "octokit-pagination-methods": "^1.1.0", + "once": "^1.4.0", + "universal-user-agent": "^3.0.0", + "url-template": "^2.0.8" + } + }, "@resin.io/types-hidepath": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@resin.io/types-hidepath/-/types-hidepath-1.0.1.tgz", @@ -1178,6 +1285,12 @@ "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, + "atob-lite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", + "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", + "dev": true + }, "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", @@ -2077,6 +2190,12 @@ "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, + "before-after-hook": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", + "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==", + "dev": true + }, "big-integer": { "version": "1.6.44", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.44.tgz", @@ -2293,6 +2412,12 @@ "multicast-dns-service-types": "^1.1.0" } }, + "bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true + }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -2356,6 +2481,12 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "btoa-lite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", + "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", + "dev": true + }, "buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", @@ -3433,6 +3564,12 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "deepmerge": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.0.0.tgz", + "integrity": "sha512-YZ1rOP5+kHor4hMAH+HRQnBQHg+wvS1un1hAOuIcxcBy0hzcUf6Jg2a1w65kpoOUnurOfZbERwjI1TfZxNjcww==", + "dev": true + }, "default-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", @@ -3754,6 +3891,12 @@ "integrity": "sha512-b5dDNQYdy2vW9WXUD8+RQlfoxvqztLLhDE+T7Gd37I5E8My7nJkKu6FmhdDeRWJ8B+yjZKuwjCta8pgi8kgSqA==", "dev": true }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true + }, "deps-regex": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.1.4.tgz", @@ -7881,6 +8024,12 @@ "lodash._root": "^3.0.0" } }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -7906,6 +8055,12 @@ "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" }, + "lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", + "dev": true + }, "lodash.template": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.4.0.tgz", @@ -7923,6 +8078,12 @@ "lodash._reinterpolate": "~3.0.0" } }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -8008,6 +8169,12 @@ "integrity": "sha1-qsz7nv62fdbpRkm5HMErNtAtLPE=", "optional": true }, + "macos-release": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz", + "integrity": "sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA==", + "dev": true + }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -12761,6 +12928,12 @@ "yosay": "^2.0.2" } }, + "octokit-pagination-methods": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", + "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", + "dev": true + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -12886,6 +13059,16 @@ "lcid": "^1.0.0" } }, + "os-name": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", + "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", + "dev": true, + "requires": { + "macos-release": "^2.2.0", + "windows-release": "^3.1.0" + } + }, "os-shim": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", @@ -13027,6 +13210,15 @@ "json-parse-better-errors": "^1.0.1" } }, + "parse-link-header": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-1.0.1.tgz", + "integrity": "sha1-vt/g0hGK64S+deewJUGeyKYRQKc=", + "dev": true, + "requires": { + "xtend": "~4.0.1" + } + }, "parse-node-version": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", @@ -16985,6 +17177,15 @@ "moment": "^2.14.1" } }, + "universal-user-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-3.0.0.tgz", + "integrity": "sha512-T3siHThqoj5X0benA5H0qcDnrKGXzU8TKoX15x/tQHw1hQBvIEBHjxQ2klizYsqBOO/Q+WuxoQUihadeeqDnoA==", + "dev": true, + "requires": { + "os-name": "^3.0.0" + } + }, "universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", @@ -17190,6 +17391,12 @@ "prepend-http": "^1.0.1" } }, + "url-template": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-2.0.8.tgz", + "integrity": "sha1-/FZaPMy/93MMd19WQflVV5FDnyE=", + "dev": true + }, "url-to-options": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", @@ -17542,6 +17749,15 @@ } } }, + "windows-release": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.2.0.tgz", + "integrity": "sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA==", + "dev": true, + "requires": { + "execa": "^1.0.0" + } + }, "winusb-driver-generator": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/winusb-driver-generator/-/winusb-driver-generator-1.2.4.tgz", diff --git a/package.json b/package.json index e4555b43..522ef9d1 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,8 @@ "@oclif/config": "^1.12.12", "@oclif/dev-cli": "1.22.0", "@oclif/parser": "^3.7.3", + "@octokit/plugin-throttling": "^2.6.0", + "@octokit/rest": "^16.28.7", "@types/archiver": "2.1.2", "@types/bluebird": "3.5.21", "@types/chai": "^4.1.7", @@ -120,6 +122,7 @@ "gulp-shell": "^0.5.2", "mocha": "^6.2.0", "nock": "^10.0.6", + "parse-link-header": "~1.0.1", "pkg": "^4.4.0", "prettier": "1.17.0", "publish-release": "^1.6.0",