node-pre-gyp
Advanced tools
Comparing version 0.3.0 to 0.3.1
# node-pre-gyp changelog | ||
## 0.3.1 | ||
- Added `unpublish` command | ||
- Fixed module path construction in tests | ||
- Added ability to disable falling back to build behavior via `npm install --fallback-to-buil=false` which overrides setting in a depedencies package.json `install` target. | ||
## 0.3.0 | ||
@@ -4,0 +9,0 @@ |
@@ -120,2 +120,11 @@ | ||
var should_do_fallback_build = fallback_to_build === package_json.name || (fallback_to_build === true || fallback_to_build === 'true'); | ||
// but allow override from npm | ||
if (process.env.npm_config_argv) { | ||
var cooked = JSON.parse(process.env.npm_config_argv).cooked; | ||
var match = cooked.indexOf("--fallback-to-build"); | ||
if (match > -1 && cooked.length > match && cooked[match+1] == "false") { | ||
should_do_fallback_build = false; | ||
log.info('install','Build fallback disabled via npm flag: --fallback-to-build=false'); | ||
} | ||
} | ||
versioning.evaluate(package_json, gyp.opts, function(err,opts) { | ||
@@ -133,3 +142,3 @@ if (err) return callback(err); | ||
place_binary(from,to,opts,function(err) { | ||
if (err && fallback_to_build) { | ||
if (err && should_do_fallback_build) { | ||
log.info('build','source compile required'); | ||
@@ -152,3 +161,3 @@ return do_build(gyp,argv,callback); | ||
place_binary(from,to,opts,function(err) { | ||
if (err && fallback_to_build) { | ||
if (err && should_do_fallback_build) { | ||
log.error('Source compile required: ' + err.message); | ||
@@ -160,3 +169,3 @@ return do_build(gyp,argv,callback); | ||
test_binary.validate(opts,function(err) { | ||
if (err && fallback_to_build) { | ||
if (err && should_do_fallback_build) { | ||
console.error(err.message); | ||
@@ -163,0 +172,0 @@ log.error("Testing pre-built binary failed, attempting to re-download"); |
@@ -26,4 +26,5 @@ | ||
'package', | ||
'testpackage', | ||
'publish', | ||
'testpackage' | ||
'unpublish' | ||
] | ||
@@ -30,0 +31,0 @@ , aliases = { |
@@ -10,2 +10,3 @@ | ||
, versioning = require('./util/versioning.js') | ||
, s3_setup = require('./util/s3_setup.js') | ||
, mkdirp = require('mkdirp') | ||
@@ -27,17 +28,6 @@ , existsAsync = fs.exists || path.exists | ||
if(!config.accessKeyId || !config.secretAccessKey) { | ||
return callback(new Error("Unknown S3 `accessKeyId` and `secretAccessKey`")); | ||
return callback(new Error("Unknown S3 `accessKeyId` and `secretAccessKey`")); | ||
} else { | ||
var to = package_json.binary.remote_uri + '/' + opts.versioned; | ||
var url_paths = url.parse(to).hostname.split('.'); | ||
if (!config.bucket && url_paths && url_paths[0]) { | ||
config.bucket = url_paths[0]; | ||
} | ||
if (!config.region && url_paths && url_paths[1]) { | ||
var s3_domain = url_paths[1]; | ||
if (s3_domain.slice(0,3) == 's3-' && | ||
s3_domain.length >= 3) { | ||
// it appears the region is explicit in the url | ||
config.region = s3_domain.replace('s3-',''); | ||
} | ||
} | ||
s3_setup.detect(to,config); | ||
AWS.config.update(config); | ||
@@ -44,0 +34,0 @@ var s3 = new AWS.S3(); |
@@ -18,3 +18,6 @@ | ||
Object.keys(opts).forEach(function(key) { | ||
template = template.replace('{'+key+'}',opts[key]); | ||
var pattern = '{'+key+'}'; | ||
while (template.indexOf(pattern) > -1) { | ||
template = template.replace(pattern,opts[key]); | ||
} | ||
}); | ||
@@ -32,3 +35,3 @@ return template; | ||
function validate_config(package_json,callback) { | ||
var msg = package_json.name + ' package is not node-pre-gyp ready:\n'; | ||
var msg = package_json.name + ' package.json is not node-pre-gyp ready:\n'; | ||
if (!package_json.main) { | ||
@@ -35,0 +38,0 @@ return callback(new Error(msg+"package.json must declare 'main'")); |
{ | ||
"name": "node-pre-gyp", | ||
"description": "Node.js native addon binary install tool", | ||
"version": "0.3.0", | ||
"version": "0.3.1", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "native", |
125
README.md
@@ -14,18 +14,10 @@ # node-pre-gyp | ||
What node-pre-gyp does is stand between `npm` and `node-gyp`. | ||
What `node-pre-gyp` does is stand between `npm` and `node-gyp`. | ||
## Who uses node-pre-gyp? | ||
You: the developers of a C++ module. You use `node-pre-gyp` to package and and publish the binary `.node` right before you `npm publish` a new version. | ||
**Developers** of C++ modules can use `node-pre-gyp` to package and publish the binary `.node` before running `npm publish`. | ||
Your users: Once your package uses `node-pre-gyp` then users can `npm install` your module without a C++ compiler and `node-pre-gyp` handles the complexity behind the scenes. | ||
**Users** can then `npm install` your module from a binary and `node-pre-gyp` does the work to make this seamless. | ||
## Why use node-pre-gyp? | ||
Successful deployment of your module using `node-pre-gyp` will mean: | ||
- Users can be blissfully unaware that your module is written in C++ | ||
- During development you will run `node-pre-gyp build` instead of `npm install` | ||
- You will take on the responsibility for providing binaries to your users | ||
## Modules using `node-pre-gyp`: | ||
@@ -36,28 +28,39 @@ | ||
- [node-osmium](https://github.com/osmcode/node-osmium) | ||
- [node-osrm](https://github.com/DennisOSRM/node-OSRM) | ||
For more examples see also the [test apps](test/). | ||
For more examples see the [test apps](test/). | ||
## Usage | ||
**1) You add a `binary` property to your modules `package.json`** | ||
**1) Add a custom `install` script to `package.json`** | ||
```js | ||
"scripts": { | ||
"install": "node-pre-gyp install --fallback-to-build", | ||
} | ||
``` | ||
**2) Add a `binary` property to `package.json`** | ||
It must provide these properties: | ||
- `module_name`: The name of your native node module. | ||
- `module_path`: The location your native module is placed after a build (commonly `build/Release/`) | ||
- `module_path`: The location your native module is placed after a build. This should be an empty directory without other javascript files. | ||
- `remote_uri`: A url to the remote location where you've published tarball binaries | ||
- `template`: A string describing the tarball versioning scheme for your binaries | ||
And example from `node-osmium` looks like: | ||
And example from `node-sqlite3` looks like: | ||
```js | ||
"binary": { | ||
"module_name": "osmium", | ||
"module_path": "./lib", | ||
"remote_uri": "http://node-osmium.s3.amazonaws.com", | ||
"template": "{module_name}-v{major}.{minor}.{patch}-{node_abi}-{platform}-{arch}.tar.gz" | ||
"module_name": "node_sqlite3", | ||
"module_path": "./lib/binding/", | ||
"remote_uri": "http://node-sqlite3.s3.amazonaws.com", | ||
"template": "{configuration}/{module_name}-v{version}-{node_abi}-{platform}-{arch}.tar.gz" | ||
}, | ||
``` | ||
**2) Build and package your app** | ||
**3) Build and package your app** | ||
@@ -68,23 +71,28 @@ ```sh | ||
**3) Publish the tarball** | ||
**4) Publish the tarball** | ||
Post the resulting tarball (in the `build/stage/` directory) to your `remote-uri`. | ||
```sh | ||
node-pre-gyp publish | ||
``` | ||
- Learn how to [host on S3](#s3-hosting). | ||
- See [Travis Packaging](#travis-packaging) for recipes for automating publishing builds on OS X and Linux. | ||
Currently the `publish` command pushes your binary to S3. This requires: | ||
**4) Add a custom `install` script** | ||
- You have created a bucket already. | ||
- The `remote-uri` points to an S3 http or https endpoint. | ||
- You have configured node-pre-gyp to read your S3 credentials (see [S3 hosting](#s3-hosting) for details). | ||
```js | ||
"scripts": { | ||
"install": "node-pre-gyp install --fallback-to-build", | ||
} | ||
``` | ||
You can also host your binaries elsewhere. To do this requires: | ||
Then users installing your module will get your binary, if available, instead of the default behavior of `npm` calling `node-gyp rebuild` right away. The `--fallback-to-build` option is recommended: if no binary is available for a given users platform then a source compile (`node-pre-gyp rebuild`) will be attempted. | ||
- You manually publish the binary created by the `package` command. | ||
- The package is available as a tarball in the `build/stage/` directory. | ||
- You provide a remote location and point the `remote_uri` value to it. | ||
**5) You're done!** | ||
**5) Automating builds** | ||
Now you are done. Publish your package to the npm registry. Users will now be able to install your module from a binary. | ||
Now you need to publish builds for all the platforms and node versions you wish to support. This is best automated. See [Travis Automation](#travis-automation) for how to auto-publish builds on OS X and Linux. On windows consider using a script [like this](https://github.com/mapbox/node-sqlite3/blob/master/scripts/build.bat) to quickly create and publish binaries. | ||
**6) You're done!** | ||
Now publish your package to the npm registry. Users will now be able to install your module from a binary. | ||
What will happen is this: | ||
@@ -94,15 +102,17 @@ | ||
2. npm will run the `install` script which will call out to `node-pre-gyp` | ||
3. `node-pre-gyp` will fetch the binary `.node` module and place it in the right place | ||
3. `node-pre-gyp` will fetch the binary `.node` module and unpack in the right place | ||
4. Assuming that all worked, you are done | ||
If a failure occurred and `--fallback-to-build` was used then `node-gyp rebuild` will be called. | ||
If a failure occurred and `--fallback-to-build` was used then `node-gyp rebuild` will be called to try to source compile the module. | ||
## S3 Hosting | ||
The usage examples above and in the tests use Amazon S3 for hosting binaries. You can host wherever you choose but S3 is cheap, `node-pre-gyp publish` expects it, and S3 can be integrated well with [travis.ci](http://travis-ci.org) to automate builds for OS X and Ubuntu. Here is an approach to do this: | ||
You can host wherever you choose but S3 is cheap, `node-pre-gyp publish` expects it, and S3 can be integrated well with [travis.ci](http://travis-ci.org) to automate builds for OS X and Ubuntu. Here is an approach to do this: | ||
First, get setup locally and test the workflow: | ||
**1) Create an S3 bucket and have your key and secret key ready** | ||
**1) Create an S3 bucket** | ||
And have your key and secret key ready for writing to the bucket. | ||
**2) Install node-pre-gyp** | ||
@@ -122,3 +132,3 @@ | ||
`~/.node_pre_gyprc` looks like: | ||
A `~/.node_pre_gyprc` looks like: | ||
@@ -141,16 +151,14 @@ ```js | ||
Do this for every platform and node version you wish to support: | ||
node-pre-gyp package publish | ||
Note: if you hit the error `Hostname/IP doesn't match certificate's altnames` it likely means that you need to provide the `region` option in your config. | ||
Note: if you hit an error like `Hostname/IP doesn't match certificate's altnames` it may mean that you need to provide the `region` option in your config. | ||
## Travis Packaging | ||
## Travis Automation | ||
Travis can push to S3 after a successful build and supports both: | ||
- Ubuntu precise and OS X | ||
- multiple Node.js versions | ||
- Ubuntu Precise and OS X | ||
- Multiple Node.js versions | ||
This enables you to cheaply auto-build and auto-publish binaries for (likely) the majority of users. | ||
This enables you to cheaply auto-build and auto-publish binaries for (likely) the majority of your users. | ||
@@ -195,3 +203,3 @@ **1) Install the travis gem** | ||
You can replace: | ||
But you can replicate the lost behavior by replacing: | ||
@@ -223,11 +231,8 @@ ```yml | ||
if test "${TRAVIS_COMMIT#*[publish]}" != "$TRAVIS_COMMIT"; then | ||
node-pre-gyp publish | ||
fi | ||
COMMIT_MESSAGE=$(git show -s --format=%B $TRAVIS_COMMIT | tr -d '\n') | ||
if test "${COMMIT_MESSAGE#*[publish]}" != "$COMMIT_MESSAGE"; then node-pre-gyp publish; fi; | ||
Or you could automatically detect if the git branch is a tag: | ||
if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]] ; then | ||
node-pre-gyp publish | ||
fi | ||
if [[ $TRAVIS_BRANCH == `git describe --tags --always HEAD` ]] ; then node-pre-gyp publish; fi | ||
@@ -239,4 +244,10 @@ Remember this publishing is not the same as `npm publish`. We're just talking about the | ||
`node-pre-gyp` supports many of the same commands as `node-gyp` with some critical differences | ||
View all possible commands: | ||
node-pre-gyp --help | ||
#### Unpublish binaries | ||
node-pre-gyp unpublish | ||
#### Clean install and build artifacts | ||
@@ -250,8 +261,2 @@ | ||
#### Build the module from source instead of installing from pre-built binary: | ||
node-pre-gyp install --build-from-source | ||
This is basically the equivalent to calling `node-gyp rebuild` which is what `npm install` call if you don't override (like recommended above) the `scripts/install` target in `package.json`. | ||
### Options | ||
@@ -264,3 +269,3 @@ | ||
Both of these options can be passed as they are or can provide values. So, in addition to being able to pass `--build-from-source` you can also pass `--build-from-source=myapp` where `myapp` is the name of your module. | ||
Both of these options can be passed alone or they can provide values. So, in addition to being able to pass `--build-from-source` you can also pass `--build-from-source=myapp` where `myapp` is the name of your module. | ||
@@ -267,0 +272,0 @@ For example: `npm install --build-from-source=myapp`. This is useful if: |
@@ -5,6 +5,6 @@ var path = require('path'); | ||
var module_path = path.join( | ||
path.relative(__dirname,pkg.binary.module_path), | ||
path.join(__dirname,pkg.binary.module_path), | ||
pkg.binary.module_name + '.node'); | ||
var app = require('./'+module_path); | ||
var binding = require(module_path); | ||
assert.ok(app); | ||
assert.ok(binding); |
@@ -18,5 +18,5 @@ { | ||
"scripts": { | ||
"install":"node-pre-gyp install", | ||
"install":"node-pre-gyp install --fallback-to-build", | ||
"test":"node index.js" | ||
} | ||
} |
@@ -10,3 +10,3 @@ { | ||
"version": "0.1.0", | ||
"main": "./index.js", | ||
"main": "./lib/index.js", | ||
"binary": { | ||
@@ -19,5 +19,5 @@ "module_name": "app2", | ||
"scripts": { | ||
"install":"node-pre-gyp install", | ||
"test":"node index.js" | ||
"install":"node-pre-gyp install --fallback-to-build", | ||
"test":"node ./lib/index.js" | ||
} | ||
} |
@@ -5,7 +5,7 @@ var path = require('path'); | ||
var module_path = path.join( | ||
path.relative(__dirname,pkg.binary.module_path), | ||
path.join(__dirname,pkg.binary.module_path), | ||
pkg.binary.module_name + '.node'); | ||
var app = require('./'+module_path); | ||
var binding = require(module_path); | ||
assert.ok(app); | ||
assert.equal(app.hello(),"hello"); | ||
assert.ok(binding); | ||
assert.equal(binding.hello(),"hello"); |
@@ -18,5 +18,5 @@ { | ||
"scripts": { | ||
"install":"node-pre-gyp install", | ||
"install":"node-pre-gyp install --fallback-to-build", | ||
"test":"node index.js" | ||
} | ||
} |
@@ -5,7 +5,7 @@ var path = require('path'); | ||
var module_path = path.join( | ||
path.relative(__dirname,pkg.binary.module_path), | ||
path.join(__dirname,pkg.binary.module_path), | ||
pkg.binary.module_name + '.node'); | ||
var app = require('./'+module_path); | ||
var binding = require(module_path); | ||
assert.ok(app); | ||
assert.equal(app.hello(),"hello"); | ||
assert.ok(binding); | ||
assert.equal(binding.hello(),"hello"); |
@@ -18,5 +18,5 @@ { | ||
"scripts": { | ||
"install":"node-pre-gyp install", | ||
"install":"node-pre-gyp install --fallback-to-build", | ||
"test":"node index.js" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
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
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
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 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
Install scripts
Supply chain riskInstall scripts are run when the package is installed. The majority of malware in npm is hidden in install scripts.
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
57123
55
768
266
28
11