node-pre-gyp-github
Advanced tools
Comparing version 1.4.3 to 1.4.4
#!/usr/bin/env node | ||
var module = require('../index.js'); | ||
var program = require('commander'); | ||
const NodePreGypGithub = require('../index.js'); | ||
const program = require('commander'); | ||
program | ||
.command('publish [options]') | ||
.description('publishes the contents of .\\build\\stage\\{version} to the current version\'s GitHub release') | ||
.option("-r, --release", "publish immediately, do not create draft") | ||
.option("-s, --silent", "turns verbose messages off") | ||
.action(function(cmd, options){ | ||
var opts = {}, | ||
x = new module(); | ||
opts.draft = options.release ? false : true; | ||
opts.verbose = options.silent ? false : true; | ||
x.publish(opts); | ||
}); | ||
.command('publish') | ||
.description('publishes the contents of .\\build\\stage\\{version} to the current version\'s GitHub release') | ||
.option("-r, --release", "publish immediately, do not create draft") | ||
.option("-s, --silent", "turns verbose messages off") | ||
.action(async function(cmd, options){ | ||
const opts = { | ||
draft: options.release ? false : true, | ||
verbose: options.silent ? false : true | ||
}; | ||
try { | ||
const nodePreGypGithub = new NodePreGypGithub(); | ||
await nodePreGypGithub.publish(opts); | ||
} catch (err) { | ||
console.error(`An error occurred whilst publishing:`, err); | ||
process.exit(1); | ||
} | ||
}); | ||
program | ||
.command('help','',{isDefault: true, noHelp: true}) | ||
.action(function() { | ||
console.log(); | ||
console.log('Usage: node-pre-gyp-github publish'); | ||
console.log(); | ||
console.log('publishes the contents of .\\build\\stage\\{version} to the current version\'s GitHub release'); | ||
}); | ||
program.parse(process.argv); | ||
if (!program.args.length) { | ||
program.help(); | ||
} | ||
program.parseAsync(process.argv); |
295
index.js
"use strict"; | ||
var path = require("path"); | ||
var fs = require('fs'); | ||
var mime = require("mime-types"); | ||
var cwd = process.cwd(); | ||
const path = require('path'); | ||
const fs = require('fs'); | ||
const cwd = process.cwd(); | ||
var verbose; | ||
var consoleLog = function(x){ | ||
return (verbose) ? console.log(x) : false; | ||
}; | ||
const {Octokit} = require('@octokit/rest'); | ||
function NodePreGypGithub() {} | ||
NodePreGypGithub.prototype.octokit = require("@octokit/rest"); | ||
NodePreGypGithub.prototype.stage_dir = path.join(cwd,"build","stage"); | ||
NodePreGypGithub.prototype.init = function() { | ||
var ownerRepo, hostPrefix; | ||
this.package_json = JSON.parse(fs.readFileSync(path.join(cwd,'package.json'))); | ||
if(!this.package_json.repository || !this.package_json.repository.url){ | ||
throw new Error('Missing repository.url in package.json'); | ||
} | ||
else { | ||
ownerRepo = this.package_json.repository.url.match(/https?:\/\/([^\/]+)\/(.*)(?=\.git)/i); | ||
if(ownerRepo) { | ||
this.host = 'api.' + ownerRepo[1]; | ||
ownerRepo = ownerRepo[2].split('/'); | ||
this.owner = ownerRepo[0]; | ||
this.repo = ownerRepo[1]; | ||
} | ||
else throw new Error('A correctly formatted GitHub repository.url was not found within package.json'); | ||
} | ||
hostPrefix = 'https://' + this.host + '/' + this.owner + '/' + this.repo + '/releases/download/'; | ||
if(!this.package_json.binary || 'object' !== typeof this.package_json.binary || 'string' !== typeof this.package_json.binary.host){ | ||
throw new Error('Missing binary.host in package.json'); | ||
} | ||
else if (this.package_json.binary.host.replace('https://','https://api.').substr(0, hostPrefix.length) !== hostPrefix){ | ||
throw new Error('binary.host in package.json should begin with: "' + hostPrefix + '"'); | ||
} | ||
let verbose; | ||
this.octokit = NodePreGypGithub.prototype.octokit({ | ||
baseUrl: 'https://' + this.host, | ||
headers: { | ||
"user-agent": (this.package_json.name) ? this.package_json.name : "node-pre-gyp-github" | ||
function consoleLog(x) { | ||
return (verbose) ? console.log(x) : false; | ||
} | ||
module.exports = class NodePreGypGithub { | ||
constructor() { | ||
this.stage_dir = path.join(cwd, 'build', 'stage'); | ||
} | ||
}); | ||
}; | ||
NodePreGypGithub.prototype.authenticate_settings = function(){ | ||
var token = process.env.NODE_PRE_GYP_GITHUB_TOKEN; | ||
if(!token) throw new Error('NODE_PRE_GYP_GITHUB_TOKEN environment variable not found'); | ||
return { | ||
"type": "oauth", | ||
"token": token | ||
}; | ||
}; | ||
init() { | ||
const token = process.env.NODE_PRE_GYP_GITHUB_TOKEN; | ||
if (!token) { | ||
throw new Error('NODE_PRE_GYP_GITHUB_TOKEN environment variable not found'); | ||
} | ||
NodePreGypGithub.prototype.createRelease = function(args, callback) { | ||
var options = { | ||
'host': this.host, | ||
'owner': this.owner, | ||
'repo': this.repo, | ||
'tag_name': this.package_json.version, | ||
'target_commitish': 'master', | ||
'name': 'v' + this.package_json.version, | ||
'body': this.package_json.name + ' ' + this.package_json.version, | ||
'draft': true, | ||
'prerelease': false | ||
}; | ||
Object.keys(args).forEach(function(key) { | ||
if(args.hasOwnProperty(key) && options.hasOwnProperty(key)) { | ||
options[key] = args[key]; | ||
} | ||
}); | ||
this.octokit.authenticate(this.authenticate_settings()); | ||
this.octokit.repos.createRelease(options, callback); | ||
}; | ||
this.package_json = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf-8')); | ||
NodePreGypGithub.prototype.uploadAsset = function(cfg){ | ||
this.octokit.authenticate(this.authenticate_settings()); | ||
this.octokit.repos.uploadAsset({ | ||
url: this.release.upload_url, | ||
owner: this.owner, | ||
id: this.release.id, | ||
repo: this.repo, | ||
name: cfg.fileName, | ||
file: fs.createReadStream(cfg.filePath), | ||
contentType: mime.contentType(cfg.fileName) || 'application/octet-stream', | ||
contentLength: fs.statSync(cfg.filePath).size | ||
}, function(err){ | ||
if(err) throw err; | ||
consoleLog('Staged file ' + cfg.fileName + ' saved to ' + this.owner + '/' + this.repo + ' release ' + this.release.tag_name + ' successfully.'); | ||
}.bind(this)); | ||
}; | ||
if (!this.package_json.repository || !this.package_json.repository.url) { | ||
throw new Error('Missing repository.url in package.json'); | ||
} else { | ||
const ownerRepo = this.package_json.repository.url.match(/https?:\/\/([^\/]+)\/(.*)(?=\.git)/i); | ||
if (!ownerRepo) { | ||
throw new Error('A correctly formatted GitHub repository.url was not found within package.json'); | ||
} | ||
NodePreGypGithub.prototype.uploadAssets = function(){ | ||
var asset; | ||
consoleLog("Stage directory path: " + path.join(this.stage_dir)); | ||
fs.readdir(path.join(this.stage_dir), function(err, files){ | ||
if(err) throw err; | ||
if(!files.length) throw new Error('No files found within the stage directory: ' + this.stage_dir); | ||
files.forEach(function(file){ | ||
if(this.release && this.release.assets) { | ||
asset = this.release.assets.filter(function(element, index, array){ | ||
return element.name === file; | ||
}); | ||
if(asset.length) { | ||
throw new Error("Staged file " + file + " found but it already exists in release " + this.release.tag_name + ". If you would like to replace it, you must first manually delete it within GitHub."); | ||
} | ||
} | ||
consoleLog("Staged file " + file + " found. Proceeding to upload it."); | ||
this.uploadAsset({ | ||
fileName: file, | ||
filePath: path.join(this.stage_dir, file) | ||
}); | ||
}.bind(this)); | ||
}.bind(this)); | ||
}; | ||
this.host = 'api.' + ownerRepo[1]; | ||
const [owner, repo] = ownerRepo[2].split('/'); | ||
this.owner = owner; | ||
this.repo = repo; | ||
} | ||
NodePreGypGithub.prototype.publish = function(options) { | ||
options = (typeof options === 'undefined') ? {} : options; | ||
verbose = (typeof options.verbose === 'undefined' || options.verbose) ? true : false; | ||
this.init(); | ||
this.octokit.authenticate(this.authenticate_settings()); | ||
this.octokit.repos.getReleases({ | ||
'owner': this.owner, | ||
'repo': this.repo | ||
}, function(err, data){ | ||
var release; | ||
if(err) throw err; | ||
// when remote_path is set expect files to be in stage_dir / remote_path after substitution | ||
if (this.package_json.binary.remote_path) { | ||
options.tag_name = this.package_json.binary.remote_path.replace(/\{version\}/g, this.package_json.version); | ||
this.stage_dir = path.join(this.stage_dir, options.tag_name); | ||
} else { | ||
// This is here for backwards compatibility for before binary.remote_path support was added in version 1.2.0. | ||
options.tag_name = this.package_json.version; | ||
} | ||
release = data.data.filter(function(element, index, array){ | ||
return element.tag_name === options.tag_name; | ||
}); | ||
if(release.length === 0) { | ||
this.createRelease(options, function(err, release) { | ||
if(err) throw err; | ||
this.release = release.data; | ||
if (this.release.draft) { | ||
consoleLog('Release ' + this.release.tag_name + " not found, so a draft release was created. YOU MUST MANUALLY PUBLISH THIS DRAFT WITHIN GITHUB FOR IT TO BE ACCESSIBLE."); | ||
} | ||
else { | ||
consoleLog('Release ' + release.tag_name + " not found, so a new release was created and published."); | ||
} | ||
this.uploadAssets(this.release.upload_url); | ||
}.bind(this)); | ||
} | ||
else { | ||
this.release = release[0]; | ||
this.uploadAssets(); | ||
} | ||
}.bind(this)); | ||
const hostPrefix = 'https://' + this.host + '/' + this.owner + '/' + this.repo + '/releases/download/'; | ||
if(!this.package_json.binary || 'object' !== typeof this.package_json.binary || 'string' !== typeof this.package_json.binary.host){ | ||
throw new Error('Missing binary.host in package.json'); | ||
} | ||
else if (this.package_json.binary.host.replace('https://','https://api.').substr(0, hostPrefix.length) !== hostPrefix){ | ||
throw new Error('binary.host in package.json should begin with: "' + hostPrefix + '"'); | ||
} | ||
this.octokit = this.createOctokitInstance(token); | ||
} | ||
createOctokitInstance(token) { | ||
return new Octokit({ | ||
baseUrl: 'https://' + this.host, | ||
auth: token, | ||
headers: { | ||
"user-agent": (this.package_json.name) ? this.package_json.name : "node-pre-gyp-github" | ||
} | ||
}); | ||
} | ||
async createRelease(args) { | ||
const options = { | ||
host: this.host, | ||
owner: this.owner, | ||
repo: this.repo, | ||
tag_name: this.package_json.version, | ||
target_commitish: 'master', | ||
name: 'v' + this.package_json.version, | ||
body: this.package_json.name + ' ' + this.package_json.version, | ||
draft: true, | ||
prerelease: false | ||
}; | ||
Object.keys(args).forEach(function(key) { | ||
if(args.hasOwnProperty(key) && options.hasOwnProperty(key)) { | ||
options[key] = args[key]; | ||
} | ||
}); | ||
const release = await this.octokit.rest.repos.createRelease(options); | ||
return release; | ||
} | ||
async uploadAssets() { | ||
consoleLog("Stage directory path: " + path.join(this.stage_dir)); | ||
const files = fs.readdirSync(path.join(this.stage_dir)); | ||
if(!files.length) throw new Error('No files found within the stage directory: ' + this.stage_dir); | ||
for (const file of files) { | ||
if (this.release && this.release.assets) { | ||
const asset = this.release.assets.filter(element => element.name === file); | ||
if (asset.length) { | ||
throw new Error("Staged file " + file + " found but it already exists in release " + this.release.tag_name + ". If you would like to replace it, you must first manually delete it within GitHub."); | ||
} | ||
} | ||
consoleLog(`Staged file ${file} found - proceeding to upload`); | ||
const filePath = path.join(this.stage_dir, file); | ||
const fileContents = fs.readFileSync(filePath); | ||
await this.octokit.rest.repos.uploadReleaseAsset({ | ||
owner: this.owner, | ||
repo: this.repo, | ||
release_id: this.release.id, | ||
name: file, | ||
data: fileContents | ||
}); | ||
consoleLog('Staged file ' + file + ' saved to ' + this.owner + '/' + this.repo + ' release ' + this.release.tag_name + ' successfully.'); | ||
} | ||
} | ||
async publish(options = {}) { | ||
verbose = (typeof options.verbose === 'undefined' || options.verbose) ? true : false; | ||
await this.init(); | ||
const {data} = await this.octokit.rest.repos.listReleases({ | ||
owner: this.owner, | ||
repo: this.repo | ||
}); | ||
// when remote_path is set expect files to be in stage_dir / remote_path after substitution | ||
if (this.package_json.binary.remote_path) { | ||
options.tag_name = this.package_json.binary.remote_path.replace(/\{version\}/g, this.package_json.version); | ||
this.stage_dir = path.join(this.stage_dir, options.tag_name); | ||
} else { | ||
// This is here for backwards compatibility for before binary.remote_path support was added in version 1.2.0. | ||
options.tag_name = this.package_json.version; | ||
} | ||
const release = data.filter(element => element.tag_name === options.tag_name); | ||
if (release.length === 0) { | ||
const release = await this.createRelease(options); | ||
this.release = release.data; | ||
if (this.release.draft) { | ||
consoleLog(`Release ${this.release.tag_name} not found, so a draft release was created. YOU MUST MANUALLY PUBLISH THIS DRAFT WITHIN GITHUB FOR IT TO BE ACCESSIBLE.`); | ||
} else { | ||
consoleLog(`Release ${this.release.tag_name} not found, so a new release was created and published.`); | ||
} | ||
} else { | ||
this.release = release[0]; | ||
} | ||
await this.uploadAssets(); | ||
} | ||
}; | ||
module.exports = NodePreGypGithub; |
{ | ||
"name": "node-pre-gyp-github", | ||
"version": "1.4.3", | ||
"version": "1.4.4", | ||
"description": "A node-pre-gyp module which provides the ability to publish to GitHub releases.", | ||
@@ -9,3 +9,4 @@ "bin": "./bin/node-pre-gyp-github.js", | ||
"test": "nyc --reporter=html --reporter=text mocha", | ||
"coverage": "nyc report --reporter=text-lcov | coveralls" | ||
"coverage": "nyc report --reporter=text-lcov | coveralls", | ||
"ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn publish && git push --follow-tags; fi" | ||
}, | ||
@@ -16,2 +17,6 @@ "repository": { | ||
}, | ||
"files": [ | ||
"bin", | ||
"index.js" | ||
], | ||
"keywords": [ | ||
@@ -30,12 +35,12 @@ "node-pre-gyp", | ||
"dependencies": { | ||
"@octokit/rest": "^15.9.5", | ||
"commander": "^2.17.0", | ||
"mime-types": "^2.1.19" | ||
"@octokit/rest": "18.12.0", | ||
"commander": "7.2.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"coveralls": "^3.0.2", | ||
"mocha": "^5.2.0", | ||
"nyc": "^12.0.2", | ||
"sinon": "^6.1.4" | ||
"chai": "4.3.6", | ||
"chai-as-promised": "7.1.1", | ||
"coveralls": "3.0.2", | ||
"mocha": "7.2.0", | ||
"nyc": "15.1.0", | ||
"sinon": "13.0.1" | ||
}, | ||
@@ -42,0 +47,0 @@ "author": "Bill Christo", |
# node-pre-gyp-github | ||
##### A node-pre-gyp module which provides the ability to publish to GitHub releases. | ||
@@ -8,5 +9,7 @@ | ||
## Usage | ||
Instead of ```node-pre-gyp publish``` use **```node-pre-gyp-github publish```** | ||
## Options for publish command | ||
* --silent : Turns verbose messages off. | ||
@@ -18,10 +21,15 @@ * --release : Publish the GitHub Release immediately instead of creating a Draft. | ||
## Install | ||
```javascript | ||
```bash | ||
npm install -g node-pre-gyp-github | ||
# or | ||
yarn global add node-pre-gyp-github | ||
``` | ||
## Configuration | ||
This module is intended to be used with node-pre-gyp. Therefore, be sure to configure and install node-pre-gyp first. After having done that, within **```package.json```** update the ```binary``` properties ```host``` and ```remote_path``` so it matches the following format: | ||
``` | ||
```json | ||
"host": "https://github.com/[owner]/[repo]/releases/download/", | ||
@@ -38,8 +46,8 @@ "remote_path": "{version}" | ||
1. go to Settings | ||
2. click Personal access tokens | ||
3. click Generate new token | ||
4. Select "public_repo" and "repo_deployment" | ||
1. go to `Settings` -> `Developer settings` | ||
2. click [`Personal access tokens`](https://github.com/settings/tokens) | ||
3. click `Generate new token` | ||
4. Select `public_repo` and `repo_deployment` | ||
5. Generate Token | ||
6. copy the key that's generated and set NODE_PRE_GYP_GITHUB_TOKEN environment variable to it. Within your command prompt: | ||
6. copy the key that's generated and set `NODE_PRE_GYP_GITHUB_TOKEN` environment variable to it. Within your command prompt: | ||
@@ -51,2 +59,3 @@ ``` | ||
## Example (Publish to GitHub as a Draft Release) | ||
1. node-pre-gyp configure | ||
@@ -58,2 +67,3 @@ 2. node-pre-gyp build | ||
## Example (Publish to GitHub as a Release) | ||
1. node-pre-gyp configure | ||
@@ -60,0 +70,0 @@ 2. node-pre-gyp build |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
2
68
2
11691
6
5
145
2
+ Added@octokit/auth-token@2.5.0(transitive)
+ Added@octokit/core@3.6.0(transitive)
+ Added@octokit/endpoint@6.0.12(transitive)
+ Added@octokit/graphql@4.8.0(transitive)
+ Added@octokit/openapi-types@12.11.0(transitive)
+ Added@octokit/plugin-paginate-rest@2.21.3(transitive)
+ Added@octokit/plugin-request-log@1.0.4(transitive)
+ Added@octokit/plugin-rest-endpoint-methods@5.16.2(transitive)
+ Added@octokit/request@5.6.3(transitive)
+ Added@octokit/request-error@2.1.0(transitive)
+ Added@octokit/rest@18.12.0(transitive)
+ Added@octokit/types@6.41.0(transitive)
+ Addedbefore-after-hook@2.2.3(transitive)
+ Addedcommander@7.2.0(transitive)
+ Addeddeprecation@2.3.1(transitive)
+ Addedis-plain-object@5.0.0(transitive)
+ Addeduniversal-user-agent@6.0.1(transitive)
- Removedmime-types@^2.1.19
- Removed@octokit/rest@15.18.3(transitive)
- Removedagent-base@4.3.0(transitive)
- Removedbefore-after-hook@1.4.0(transitive)
- Removedbtoa-lite@1.0.0(transitive)
- Removedcommander@2.20.3(transitive)
- Removedcross-spawn@6.0.5(transitive)
- Removeddebug@3.1.03.2.7(transitive)
- Removedend-of-stream@1.4.4(transitive)
- Removedes6-promise@4.2.8(transitive)
- Removedes6-promisify@5.0.0(transitive)
- Removedexeca@1.0.0(transitive)
- Removedget-stream@4.1.0(transitive)
- Removedhttp-proxy-agent@2.1.0(transitive)
- Removedhttps-proxy-agent@2.2.4(transitive)
- Removedis-stream@1.1.0(transitive)
- Removedisexe@2.0.0(transitive)
- Removedlodash@4.17.21(transitive)
- Removedmacos-release@2.5.1(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedms@2.0.02.1.3(transitive)
- Removednice-try@1.0.5(transitive)
- Removednpm-run-path@2.0.2(transitive)
- Removedos-name@3.1.0(transitive)
- Removedp-finally@1.0.0(transitive)
- Removedpath-key@2.0.1(transitive)
- Removedpump@3.0.2(transitive)
- Removedsemver@5.7.2(transitive)
- Removedshebang-command@1.2.0(transitive)
- Removedshebang-regex@1.0.0(transitive)
- Removedsignal-exit@3.0.7(transitive)
- Removedstrip-eof@1.0.0(transitive)
- Removeduniversal-user-agent@2.1.0(transitive)
- Removedurl-template@2.0.8(transitive)
- Removedwhich@1.3.1(transitive)
- Removedwindows-release@3.3.3(transitive)
Updated@octokit/rest@18.12.0
Updatedcommander@7.2.0