node-core-utils
Advanced tools
+7
| Copyright 2017 node-core-utils contributors | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
+2
-0
@@ -26,2 +26,4 @@ #!/usr/bin/env node | ||
| data.logIntro(); | ||
| const metadata = new MetadataGenerator(data).getMetadata(); | ||
@@ -28,0 +30,0 @@ const [SCISSOR_LEFT, SCISSOR_RIGHT] = MetadataGenerator.SCISSORS; |
+36
-33
@@ -5,6 +5,7 @@ 'use strict'; | ||
| const fs = require('fs'); | ||
| const { ClientRequest } = require('http'); | ||
| const os = require('os'); | ||
| const path = require('path'); | ||
| const util = require('util'); | ||
| const readline = require('readline'); | ||
| const ghauth = util.promisify(require('ghauth')); | ||
| const readFile = util.promisify(fs.readFile); | ||
@@ -20,3 +21,3 @@ const writeFile = util.promisify(fs.writeFile); | ||
| async function auth() { | ||
| async function auth(getCredentials = ghauth) { | ||
| let username, token; | ||
@@ -27,4 +28,6 @@ // Try reading from ~/.ncurc | ||
| } catch (e) { | ||
| process.stdout.write('Reading configuration for node-core-utils failed:\n' + | ||
| e.message + '\n'); | ||
| process.stdout.write('If this is your first time running this command, ' + | ||
| 'follow the instructions to create an access token. ' + | ||
| 'If you prefer to create it yourself on Github, ' + | ||
| 'see https://github.com/joyeecheung/node-core-utils/blob/master/README.md.\n'); | ||
| } | ||
@@ -38,33 +41,25 @@ | ||
| // Ask the user for input and write to ~/.ncurc, then try again | ||
| process.stdout.write('Please enter your Github user information:\n' + | ||
| '[Github tokens can be created as described in ' + | ||
| 'https://help.github.com/articles/' + | ||
| 'creating-a-personal-access-token-for-the-command-line/]\n'); | ||
| username = await prompt('Github user name'); | ||
| token = await prompt('Github token'); | ||
| check(username, token); | ||
| const json = JSON.stringify({ username, token }, null, ' '); | ||
| // Ask the user for input, create a token via github v3 API | ||
| // then write to ~/.ncurc and try auth() again | ||
| let credentials; | ||
| try { | ||
| credentials = await getCredentials({ | ||
| noSave: true, | ||
| scopes: ['user:email'], | ||
| note: 'node-core-utils CLI tools' | ||
| }); | ||
| } catch (e) { | ||
| process.stderr.write(`Could not get token: ${e.message}\n`); | ||
| process.exit(1); | ||
| } | ||
| const json = JSON.stringify({ | ||
| username: credentials.user, | ||
| token: credentials.token | ||
| }, null, ' '); | ||
| await writeFile(authFile, json, { mode: | ||
| 0o600 /* owner read/write */ | ||
| }); | ||
| return auth(); | ||
| } | ||
| async function prompt(question) { | ||
| return new Promise((resolve, reject) => { | ||
| process.stdout.write(`${question}: `); | ||
| const rl = readline.createInterface({ | ||
| input: process.stdin | ||
| }); | ||
| rl.on('line', (line) => { | ||
| rl.close(); | ||
| process.stdin.removeListener('error', reject); | ||
| process.stdin.removeListener('end', reject); | ||
| resolve(line.trim()); | ||
| }); | ||
| process.stdin.on('error', reject); | ||
| process.stdin.on('end', reject); | ||
| }); | ||
| return auth(getCredentials); | ||
| } | ||
@@ -74,9 +69,17 @@ | ||
| let cachedValue; | ||
| return function() { | ||
| return function(...args) { | ||
| if (cachedValue !== undefined) { | ||
| return cachedValue; | ||
| } | ||
| cachedValue = fn(); | ||
| cachedValue = fn(...args); | ||
| return cachedValue; | ||
| }; | ||
| } | ||
| // This is an ugly hack to get around a bug in hyperquest & ghauth | ||
| // which are not currently maintained | ||
| const originalSetTimeout = ClientRequest.prototype.setTimeout; | ||
| ClientRequest.prototype.setTimeout = function(msecs, ...args) { | ||
| msecs = Math.min(msecs, Math.pow(2, 31) - 1); | ||
| return originalSetTimeout.call(this, msecs, ...args); | ||
| }; |
+9
-8
| 'use strict'; | ||
| const FIXES_RE = /Fixes:\s*(\S+)/mg; | ||
| const FIX_RE = /Fixes:\s*(\S+)/; | ||
| const REFS_RE = /Refs?:\s*(\S+)/mg; | ||
| const REF_RE = /Refs?:\s*(\S+)/; | ||
| const FIXES_RE = /(Close[ds]?|Fix(e[ds])?|Resolve[sd]?)\s*:\s*(\S+)/mgi; | ||
| const FIX_RE = /(Close[ds]?|Fix(e[ds])?|Resolve[sd]?)\s*:\s*(\S+)/i; | ||
| const REFS_RE = /Refs?\s*:\s*(\S+)/mgi; | ||
| const REF_RE = /Refs?\s*:\s*(\S+)/i; | ||
| const { JSDOM } = require('jsdom'); | ||
@@ -13,3 +13,4 @@ | ||
| class LinkParser { | ||
| constructor(repo, html) { | ||
| constructor(owner, repo, html) { | ||
| this.owner = owner; | ||
| this.repo = repo; | ||
@@ -20,3 +21,3 @@ this.OP = JSDOM.fragment(html); | ||
| getFixesUrlsFromArray(arr) { | ||
| const repo = this.repo; | ||
| const { owner, repo } = this; | ||
| const result = []; | ||
@@ -26,4 +27,4 @@ for (const item of arr) { | ||
| if (!m) continue; | ||
| const fix = m[1]; | ||
| const url = fix.replace(/^#/, `${repo}#`).replace('#', '/issues/'); | ||
| const fix = m[3]; | ||
| const url = fix.replace(/^#/, `${owner}/${repo}#`).replace('#', '/issues/'); | ||
| result.push(`https://github.com/${url}`); | ||
@@ -30,0 +31,0 @@ } |
+2
-0
@@ -27,2 +27,3 @@ 'use strict'; | ||
| const prettyOptions = { | ||
| crlf: EOL === '\r\n', | ||
| forceColor: true, | ||
@@ -56,2 +57,3 @@ formatter(obj) { | ||
| const logger = pino({ | ||
| crlf: EOL === '\r\n', | ||
| name: 'node-core-utils', | ||
@@ -58,0 +60,0 @@ safe: true, |
@@ -13,3 +13,4 @@ 'use strict'; | ||
| constructor(data) { | ||
| const { repo, pr, reviewers } = data; | ||
| const { owner, repo, pr, reviewers } = data; | ||
| this.owner = owner; | ||
| this.repo = repo; | ||
@@ -27,6 +28,7 @@ this.pr = pr; | ||
| pr: { url: prUrl, bodyHTML: op }, | ||
| owner, | ||
| repo | ||
| } = this; | ||
| const parser = new LinkParser(repo, op); | ||
| const parser = new LinkParser(owner, repo, op); | ||
| const fixes = parser.getFixes(); | ||
@@ -33,0 +35,0 @@ const refs = parser.getRefs(); |
+24
-5
@@ -45,8 +45,10 @@ 'use strict'; | ||
| checkAll() { | ||
| this.checkReviews(); | ||
| this.checkPRWait(new Date()); | ||
| this.checkCI(); | ||
| const status = [ | ||
| this.checkReviews(), | ||
| this.checkPRWait(new Date()), | ||
| this.checkCI() | ||
| ]; | ||
| if (this.authorIsNew()) { | ||
| this.checkAuthor(); | ||
| status.push(this.checkAuthor()); | ||
| } | ||
@@ -56,2 +58,4 @@ // TODO: maybe invalidate review after new commits? | ||
| // does not support reading files changed | ||
| return status.every((i) => i); | ||
| } | ||
@@ -75,2 +79,3 @@ | ||
| } = this; | ||
| let status = true; | ||
@@ -80,2 +85,3 @@ if (rejected.length === 0) { | ||
| } else { | ||
| status = false; | ||
| let hint = this.getTSCHint(rejected); | ||
@@ -88,2 +94,3 @@ logger.warn(`Rejections: ${rejected.length}${hint}`); | ||
| if (approved.length === 0) { | ||
| status = false; | ||
| logger.warn(`Approvals: 0`); | ||
@@ -104,2 +111,3 @@ } else { | ||
| if (tscApproval < 2) { | ||
| status = false; | ||
| logger.warn('semver-major requires at least two TSC approvals'); | ||
@@ -109,2 +117,4 @@ } | ||
| } | ||
| return status; | ||
| } | ||
@@ -144,3 +154,6 @@ | ||
| logger.warn(`${wait.timeLeft} hours left to land`); | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
@@ -158,5 +171,8 @@ | ||
| const ciMap = new CIParser(thread).parse(); | ||
| let status = true; | ||
| if (!ciMap.size) { | ||
| logger.warn('No CI runs detected'); | ||
| return false; | ||
| } else if (!ciMap.get(FULL)) { | ||
| status = false; | ||
| logger.warn('No full CI runs detected'); | ||
@@ -169,2 +185,4 @@ } | ||
| } | ||
| return status; | ||
| } | ||
@@ -182,3 +200,3 @@ | ||
| if (!oddCommits.length) { | ||
| return; | ||
| return true; | ||
| } | ||
@@ -194,2 +212,3 @@ | ||
| } | ||
| return false; | ||
| } | ||
@@ -196,0 +215,0 @@ |
+22
-0
@@ -98,4 +98,26 @@ 'use strict'; | ||
| } | ||
| logIntro() { | ||
| const { | ||
| commits, | ||
| logger, | ||
| owner, | ||
| prid, | ||
| pr: { | ||
| author: { login: author }, | ||
| baseRefName, | ||
| headRefName, | ||
| labels, | ||
| title | ||
| } | ||
| } = this; | ||
| logger.info(`${title} #${prid}`); | ||
| logger.info(`${author} wants to merge ${commits.length} ` + | ||
| `commit${commits.length === 1 ? '' : 's'} into ` + | ||
| `${owner}:${baseRefName} from ${author}:${headRefName}`); | ||
| logger.info(`Labels: ${labels.nodes.map(label => label.name).join(' ')}`); | ||
| } | ||
| }; | ||
| module.exports = PRData; |
+7
-6
| { | ||
| "name": "node-core-utils", | ||
| "version": "1.4.0", | ||
| "version": "1.5.0", | ||
| "description": "Utilities for Node.js core collaborators", | ||
@@ -11,6 +11,6 @@ "main": "./bin/metadata.js", | ||
| "test": "npm run test-unit && npm run lint", | ||
| "test-unit": "mocha --require intelli-espower-loader test/unit/*.test.js", | ||
| "test-all": "mocha --require intelli-espower-loader test/**/*.test.js", | ||
| "coverage": "nyc npm test", | ||
| "coverage-all": "nyc npm run test-all", | ||
| "test-unit": "mocha --require intelli-espower-loader test/unit/*.test.js --exit", | ||
| "test-all": "mocha --require intelli-espower-loader test/**/*.test.js --exit", | ||
| "coverage": "nyc --reporter=html --reporter=text --reporter=text-summary npm test", | ||
| "coverage-all": "nyc --reporter=lcov --reporter=text --reporter=text-summary npm run test-all", | ||
| "lint": "eslint .", | ||
@@ -32,4 +32,5 @@ "report-coverage": "nyc report --reporter=lcov > coverage.lcov && codecov" | ||
| "chalk": "^2.2.0", | ||
| "ghauth": "^3.2.1", | ||
| "jsdom": "^11.3.0", | ||
| "pino": "^4.8.0", | ||
| "pino": "^4.9.0", | ||
| "request": "^2.83.0", | ||
@@ -36,0 +37,0 @@ "request-promise-native": "^1.0.5", |
+4
-1
@@ -16,5 +16,8 @@ query PR($prid: Int!, $owner: String!, $repo: String!) { | ||
| } | ||
| } | ||
| }, | ||
| title, | ||
| baseRefName, | ||
| headRefName | ||
| } | ||
| } | ||
| } |
+24
-11
| # Node.js Core Utilities | ||
| [](https://npmjs.org/package/node-core-utils) | ||
| [](https://travis-ci.org/joyeecheung/node-core-utils) | ||
| [](https://codecov.io/gh/joyeecheung/node-core-utils) | ||
| [](https://snyk.io/test/github/joyeecheung/node-core-utils) | ||
| [](https://travis-ci.org/joyeecheung/node-core-utils) | ||
| [](https://codecov.io/gh/joyeecheung/node-core-utils) | ||
| [](https://snyk.io/test/github/joyeecheung/node-core-utils) | ||
| CLI tools for Node.js Core collaborators | ||
| CLI tools for Node.js Core collaborators. | ||
| ## Usage | ||
| First, [follow these instructions](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) | ||
| to create a personal access token. | ||
| ``` | ||
| npm install -g node-core-utils | ||
| ``` | ||
| After running any of the tools for the first-time, you will be asked to provide a | ||
| GitHub username and password in order to create a personal access token. | ||
| If you prefer not to provide your login credentials, [follow these instructions](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/) | ||
| to create the token. | ||
| Note: We need to read the email of the PR author in order to check if it matches | ||
| the email of the commit author. This requires checking the box `user:email` when | ||
| the email of the commit author. This requires checking the box `user:email` when | ||
| you create the personal access token (you can edit the permission later as well). | ||
@@ -27,6 +34,4 @@ | ||
| If you install via npm, that's it. | ||
| If you would prefer to build from the source, install and link: | ||
| If you are using it from source, install and link: | ||
| ``` | ||
@@ -78,3 +83,3 @@ git clone git@github.com:joyeecheung/node-core-utils.git | ||
| ### TODO | ||
| ### Features | ||
@@ -91,1 +96,9 @@ - [x] Generate `PR-URL` | ||
| - [ ] Check number of files changed (request pre-backport) | ||
| ### Contributing | ||
| See [CONTRIBUTING.md](./CONTRIBUTING.md). | ||
| ### License | ||
| MIT. See [LICENSE](./LICENSE). |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
39836
8.04%24
4.35%1075
4.17%102
14.61%7
16.67%1
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
Updated