-
Notifications
You must be signed in to change notification settings - Fork 263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pluggable hosting #108
Closed
Closed
Pluggable hosting #108
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
7e4d56b
first attempt at externalized hosting implementations
51d08ab
fixed paths + host being optional
albanm 0887b22
Merge branch 'master' of https://github.com/mapbox/node-pre-gyp
albanm 6fce0ed
try to prevent sending [object Object] string to node-gyp
albanm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,58 +1,25 @@ | ||
var hosting = require('./util/hosting'); | ||
|
||
module.exports = exports = publish | ||
module.exports = exports = publish; | ||
|
||
exports.usage = 'Publishes pre-built binary (requires aws-sdk)' | ||
exports.usage = 'Publishes pre-built binary (requires aws-sdk)'; | ||
|
||
var fs = require('fs') | ||
, path = require('path') | ||
, log = require('npmlog') | ||
, versioning = require('./util/versioning.js') | ||
, s3_setup = require('./util/s3_setup.js') | ||
, mkdirp = require('mkdirp') | ||
, existsAsync = fs.exists || path.exists | ||
, url = require('url') | ||
, config = require('rc')("node_pre_gyp",{acl:"public-read"}); | ||
|
||
function publish(gyp, argv, callback) { | ||
var AWS = require("aws-sdk"); | ||
var package_json = JSON.parse(fs.readFileSync('./package.json')); | ||
var opts = versioning.evaluate(package_json, gyp.opts); | ||
var tarball = opts.staged_tarball; | ||
existsAsync(tarball,function(found) { | ||
if (!found) { | ||
return callback(new Error("Cannot publish because " + tarball + " missing: run `node-pre-gyp package` first")) | ||
return callback(new Error("Cannot publish because " + tarball + " missing: run `node-pre-gyp package` first")); | ||
} | ||
s3_setup.detect(opts.hosted_path,config); | ||
var key_name = url.resolve(config.prefix,opts.package_name) | ||
AWS.config.update(config); | ||
var s3 = new AWS.S3(); | ||
var s3_opts = { Bucket: config.bucket, | ||
Key: key_name | ||
}; | ||
s3.headObject(s3_opts, function(err, meta){ | ||
if (err && err.code == 'NotFound') { | ||
// we are safe to publish because | ||
// the object does not already exist | ||
var s3 = new AWS.S3(); | ||
var s3_obj_opts = { ACL: config.acl, | ||
Body: fs.createReadStream(tarball), | ||
Bucket: config.bucket, | ||
Key: key_name | ||
}; | ||
s3.putObject(s3_obj_opts, function(err, resp){ | ||
if(err) return callback(err); | ||
console.log('['+package_json.name+'] Success: published to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key); | ||
return callback(); | ||
}); | ||
} else if(err) { | ||
return callback(err); | ||
} else { | ||
log.error('publish','Cannot publish over existing version'); | ||
log.error('publish',"Update the 'version' field in package.json and try again"); | ||
log.error('publish','If the previous version was published in error see:'); | ||
log.error('publish','\t node-pre-gyp unpublish'); | ||
return callback(new Error('Failed publishing to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key)); | ||
} | ||
}); | ||
hosting(opts).publish(opts, config, callback); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,18 @@ | ||
var hosting = require('./util/hosting'); | ||
|
||
module.exports = exports = unpublish | ||
module.exports = exports = unpublish; | ||
|
||
exports.usage = 'Unpublishes pre-built binary (requires aws-sdk)' | ||
exports.usage = 'Unpublishes pre-built binary (requires aws-sdk)'; | ||
|
||
var fs = require('fs') | ||
, path = require('path') | ||
, log = require('npmlog') | ||
, versioning = require('./util/versioning.js') | ||
, s3_setup = require('./util/s3_setup.js') | ||
, url = require('url') | ||
, config = require('rc')("node_pre_gyp",{acl:"public-read"}); | ||
|
||
function unpublish(gyp, argv, callback) { | ||
var AWS = require("aws-sdk"); | ||
var package_json = JSON.parse(fs.readFileSync('./package.json')); | ||
var opts = versioning.evaluate(package_json, gyp.opts); | ||
s3_setup.detect(opts.hosted_path,config); | ||
AWS.config.update(config); | ||
var key_name = url.resolve(config.prefix,opts.package_name) | ||
var s3 = new AWS.S3(); | ||
var s3_opts = { Bucket: config.bucket, | ||
Key: key_name | ||
}; | ||
s3.headObject(s3_opts, function(err, meta) { | ||
if (err && err.code == 'NotFound') { | ||
console.log('['+package_json.name+'] Not found: https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key); | ||
return callback(); | ||
} else if(err) { | ||
return callback(err); | ||
} else { | ||
log.info(JSON.stringify(meta)); | ||
s3.deleteObject(s3_opts, function(err, resp) { | ||
if (err) return callback(err); | ||
log.info(JSON.stringify(resp)); | ||
console.log('['+package_json.name+'] Success: removed https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key); | ||
return callback(); | ||
}) | ||
} | ||
}); | ||
|
||
hosting(opts).unpublish(opts, config, callback); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var request = require('request'); | ||
var log = require('npmlog'); | ||
var url = require('url'); | ||
var s3_setup = require('../util/s3_setup.js'); | ||
|
||
/** | ||
* Upload a tarball packaged by node-pre-gyp to AWS S3 | ||
* | ||
* @param {Object} opts - A options object as return by node-pre-gyp's versioning.evaluate() | ||
* @param {Object} config - A config object as built by node-pre-gyp using the rc configuration module | ||
* @param {Function} callback - No particular return, just err or no err | ||
*/ | ||
exports.publish = function(opts, config, callback) { | ||
var AWS = require("aws-sdk"); | ||
s3_setup.detect(opts.hosted_path, config); | ||
var key_name = url.resolve(config.prefix, opts.package_name); | ||
AWS.config.update(config); | ||
var s3 = new AWS.S3(); | ||
var s3_opts = { | ||
Bucket: config.bucket, | ||
Key: key_name | ||
}; | ||
s3.headObject(s3_opts, function(err, meta) { | ||
if (err && err.code == 'NotFound') { | ||
// we are safe to publish because | ||
// the object does not already exist | ||
var s3 = new AWS.S3(); | ||
var s3_obj_opts = { | ||
ACL: config.acl, | ||
Body: fs.createReadStream(tarball), | ||
Bucket: config.bucket, | ||
Key: key_name | ||
}; | ||
s3.putObject(s3_obj_opts, function(err, resp) { | ||
if (err) return callback(err); | ||
console.log('[' + package_json.name + '] Success: published to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key); | ||
return callback(); | ||
}); | ||
} else if (err) { | ||
return callback(err); | ||
} else { | ||
log.error('publish', 'Cannot publish over existing version'); | ||
log.error('publish', "Update the 'version' field in package.json and try again"); | ||
log.error('publish', 'If the previous version was published in error see:'); | ||
log.error('publish', '\t node-pre-gyp unpublish'); | ||
return callback(new Error('Failed publishing to https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key)); | ||
} | ||
}); | ||
}; | ||
|
||
/** | ||
* Remove a tarball packaged by node-pre-gyp that was previously uploaded as an asset to a AWS S3 | ||
* | ||
* @param {Object} opts - An options object as return by node-pre-gyp's versioning.evaluate() | ||
* @param {Object} config - A config object as built by node-pre-gyp using the rc configuration module | ||
* @param {Function} callback - No particular return, just err or no err | ||
*/ | ||
exports.unpublish = function(opts, config, callback) { | ||
var AWS = require("aws-sdk"); | ||
s3_setup.detect(opts.hosted_path, config); | ||
AWS.config.update(config); | ||
var key_name = url.resolve(config.prefix, opts.package_name); | ||
var s3 = new AWS.S3(); | ||
var s3_opts = { | ||
Bucket: config.bucket, | ||
Key: key_name | ||
}; | ||
s3.headObject(s3_opts, function(err, meta) { | ||
if (err && err.code == 'NotFound') { | ||
console.log('[' + package_json.name + '] Not found: https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key); | ||
return callback(); | ||
} else if (err) { | ||
return callback(err); | ||
} else { | ||
log.info(JSON.stringify(meta)); | ||
s3.deleteObject(s3_opts, function(err, resp) { | ||
if (err) return callback(err); | ||
log.info(JSON.stringify(resp)); | ||
console.log('[' + package_json.name + '] Success: removed https://' + s3_opts.Bucket + '.s3.amazonaws.com/' + s3_opts.Key); | ||
return callback(); | ||
}); | ||
} | ||
}); | ||
}; | ||
|
||
/** | ||
* Download a tarball packaged by node-pre-gyp that was previously uploaded to AWS S3 | ||
* | ||
* @param {Object} opts - An options object as return by node-pre-gyp's versioning.evaluate() | ||
* @param {Function} callback - called with a request object (https://github.com/mikeal/request) that will be used as a stream by node-pre-gyp | ||
*/ | ||
exports.download = function(opts, callback) { | ||
var uri = opts.hosted_tarball; | ||
log.http('GET', uri); | ||
|
||
var req = null; | ||
var requestOpts = { | ||
uri: uri, | ||
headers: { | ||
'User-Agent': 'node-pre-gyp (node ' + process.version + ')' | ||
} | ||
}; | ||
|
||
var proxyUrl = opts.proxy || process.env.http_proxy || process.env.HTTP_PROXY || process.env.npm_config_proxy; | ||
if (proxyUrl) { | ||
if (/^https?:\/\//i.test(proxyUrl)) { | ||
log.verbose('download', 'using proxy url: "%s"', proxyUrl); | ||
requestOpts.proxy = proxyUrl; | ||
} else { | ||
log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl); | ||
} | ||
} | ||
try { | ||
req = request(requestOpts); | ||
} catch (e) { | ||
return callback(e); | ||
} | ||
if (req) { | ||
req.on('response', function(res) { | ||
log.http(res.statusCode, uri); | ||
}); | ||
} | ||
return callback(null, req); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// Fetch the right hosting implementation for given options | ||
// first look for an implementation embedded into the project then in an outside module | ||
module.exports = function(opts) { | ||
var hosting; | ||
try { | ||
hosting = require('./hosting-' + opts.hosting.provider); | ||
} catch (e) { | ||
hosting = require('node-pre-gyp-hosting-' + opts.hosting.provider); | ||
} | ||
return hosting; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why fallback to null here (and below)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because host is no longer a required option and add_trailing_slash fails if called on null or undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, makes sense. Can you share what an alternative
hosting
might look like so I can ponder whether thehost
related params might be moved around so things are more generic? I worry about havingnull
params making this brittle.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see here for an example: https://github.com/albanm/node-addon-example/blob/master/package.json
I didn't move host around in order not to break compatibility, but following the logic of this PR it should probably be in a 'hosting' object in the 'binary' options. And the add_trailing_slash or other processing should be done in the specific hosting implementation.