Permalink
Browse files

Merged in versions

  • Loading branch information...
2 parents b19e6ad + 3bd191f commit e5f41d0c39f3de5a8319d7e59faec264a0b50590 @ericallam committed Jan 11, 2012
View
@@ -29,27 +29,45 @@ Example usage:
The buildpack will detect your app as Node.js if it has the file `package.json` in the root. It will use NPM to install your dependencies, and vendors a version of the Node.js runtime into your slug. The `node_modules` directory will be cached between builds to allow for faster NPM install time.
+Node.js and npm versions
+------------------------
+
+You can specify the versions of Node.js and npm your application requires using `package.json`
+
+ {
+ "name": "myapp",
+ "engines": {
+ "node": ">=0.4.7 <0.7.0",
+ "npm": ">=1.0.0"
+ }
+ }
+
+To list the available versions of Node.js and npm, see these manifests:
+
+http://heroku-buildpack-nodejs.s3.amazonaws.com/manifest.nodejs
+http://heroku-buildpack-nodejs.s3.amazonaws.com/manifest.npm
+
Hacking
-------
To use this buildpack, fork it on Github. Push up changes to your fork, then create a test app with `--buildpack <your-github-url>` and push to it.
To change the vendored binaries for Node.js, NPM, and SCons, use the helper scripts in the `support/` subdirectory. You'll need an S3-enabled AWS account and a bucket to store your binaries in.
-For example, you can change the vendored version of Node.js to v0.5.8.
+For example, you can change the default version of Node.js to v0.6.7.
First you'll need to build a Heroku-compatible version of Node.js:
$ export AWS_ID=xxx AWS_SECRET=yyy S3_BUCKET=zzz
$ s3 create $S3_BUCKET
- $ support/package_node 0.5.8
+ $ support/package_nodejs 0.6.7
Open `bin/compile` in your editor, and change the following lines:
- NODE_VERSION="0.5.8"
-
+ DEFAULT_NODE_VERSION="0.6.7"
S3_BUCKET=zzz
+:w
Commit and push the changes to your buildpack to your Github fork, then push your sample app to Heroku to test. You should see:
- -----> Vendoring node 0.5.8
+ -----> Vendoring node 0.6.7
View
@@ -4,7 +4,12 @@
# fail fast
set -e
-mktmpdir() {
+function error() {
+ echo " ! $*"
+ exit 1
+}
+
+function mktmpdir() {
dir=$(mktemp -t node-$1-XXXX)
rm -rf $dir
mkdir -p $dir
@@ -19,14 +24,22 @@ function indent() {
esac
}
-# clean up leaking environment
-unset GIT_DIR
+function manifest_versions() {
+ curl "http://${S3_BUCKET}.s3.amazonaws.com/manifest.${1}" -s -o - | tr -s '\n' ' '
+}
+
+function resolve_versions() {
+ args=""
+ for version in $1; do args="${args} -v \"${version}\""; done
+ for version in $2; do args="${args} -r \"${version}\""; done
+ eval vendor/node-semver/bin/semver ${args} | tail -r | head -n1
+}
# config
-NODE_VERSION="0.6.7"
-NPM_VERSION="1.1.0-beta-10"
+DEFAULT_NODE_VERSION="0.6.7"
+DEFAULT_NPM_VERSION="1.0.106"
SCONS_VERSION="1.2.0"
-S3_BUCKET="node-build"
+S3_BUCKET="heroku-buildpack-nodejs"
# parse and derive params
BUILD_DIR=$1
@@ -35,6 +48,49 @@ LP_DIR=`cd $(dirname $0); cd ..; pwd`
CACHE_STORE_DIR=$CACHE_DIR"/node_modules/$NPM_VERSION"
CACHE_TARGET_DIR=$BUILD_DIR"/node_modules"
+# determine available versions
+NODEJS_VERSIONS=$(manifest_versions "nodejs")
+NPM_VERSIONS=$(manifest_versions "npm")
+
+# determine requested versions
+engines=$(cat $BUILD_DIR/package.json | $LP_DIR/vendor/json/json engines 2>&1)
+
+if [ $? == 0 ] && [ "$engines" != "" ]; then
+ REQUESTED_NODE_VERSION=$(cat $BUILD_DIR/package.json | $LP_DIR/vendor/json/json engines.node)
+ REQUESTED_NPM_VERSION=$(cat $BUILD_DIR/package.json | $LP_DIR/vendor/json/json engines.npm 2>&1)
+else
+ REQUESTED_NODE_VERSION=""
+ REQUESTED_NPM_VERSION=""
+fi
+
+# resolve node version
+if [ "${REQUESTED_NODE_VERSION}" == "" ]; then
+ NODE_VERSION=${DEFAULT_NODE_VERSION}
+else
+ RESOLVED_NODE=$(resolve_versions "${NODEJS_VERSIONS}" "${REQUESTED_NODE_VERSION}")
+
+ if [ "${RESOLVED_NODE}" == "" ]; then
+ error "Requested Node.js version: ${REQUESTED_NODE_VERSION} does not match available versions: ${NODEJS_VERSIONS}"
+ else
+ NODE_VERSION=${RESOLVED_NODE}
+ fi
+fi
+echo "-----> Using Node.js version: ${NODE_VERSION}"
+
+# resolve npm version
+if [ "${REQUESTED_NPM_VERSION}" == "" ]; then
+ NPM_VERSION=${DEFAULT_NPM_VERSION}
+else
+ RESOLVED_NPM=$(resolve_versions "${NPM_VERSIONS}" "${REQUESTED_NPM_VERSION}")
+
+ if [ "${RESOLVED_NPM}" == "" ]; then
+ error "Requested Node.js version: ${REQUESTED_NPM_VERSION} does not match available versions: ${NPMJS_VERSIONS}"
+ else
+ NPM_VERSION=${RESOLVED_NPM}
+ fi
+fi
+echo "-----> Using npm version: ${NPM_VERSION}"
+
# s3 packages
NODE_PACKAGE="http://${S3_BUCKET}.s3.amazonaws.com/nodejs-${NODE_VERSION}.tgz"
NPM_PACKAGE="http://${S3_BUCKET}.s3.amazonaws.com/npm-${NPM_VERSION}.tgz"
@@ -53,7 +109,7 @@ mkdir -p $VENDORED_SCONS && curl $SCONS_PACKAGE -s -o - | tar xzf - -C $VENDORED
# vendor node into the slug
PATH="$BUILD_DIR/bin:$PATH"
-echo "-----> Vendoring node $NODE_VERSION"
+echo "-----> Vendoring node into slug"
mkdir -p "$BUILD_DIR/bin"
cp "$VENDORED_NODE/bin/node" "$BUILD_DIR/bin/node"
@@ -70,13 +126,12 @@ if [ -d $CACHE_STORE_DIR ]; then
fi
# install dependencies with npm
-echo "-----> Installing dependencies with npm $NPM_VERSION"
+echo "-----> Installing dependencies with npm"
cd $BUILD_DIR
HOME="$BUILD_DIR" $VENDORED_NODE/bin/node $VENDORED_NPM/cli.js prune 2>&1 | indent
HOME="$BUILD_DIR" $VENDORED_NODE/bin/node $VENDORED_NPM/cli.js install 2>&1 | indent
if [ "${PIPESTATUS[*]}" != "0 0" ]; then
- echo " ! Failed to install dependencies with npm"
- exit 1
+ error "Failed to install dependencies with npm"
else
echo " Dependencies installed"
fi
View
@@ -117,14 +117,17 @@ s3_curl() {
# $2 = remote bucket.
# $3 = remote name
# $4 = local name.
+ # $5 = mime type
local bucket remote date sig md5 arg inout headers
# header handling is kinda fugly, but it works.
bucket="${2:+/${2}}/" # slashify the bucket
remote="$(urlenc "${3}")" # if you don't, strange things may happen.
stdopts="--connect-timeout 10 --fail --silent"
+ mime="${5}"
[[ $CURL_S3_DEBUG == true ]] && stdopts="${stdopts} --show-error --fail"
case "${1}" in
GET) arg="-o" inout="${4:--}" # stdout if no $4
+ headers[${#headers[@]}]="x-amz-acl: public-read"
;;
PUT) [[ ${2} ]] || die "PUT can has bucket?"
if [[ ! ${3} ]]; then
@@ -135,6 +138,9 @@ s3_curl() {
arg="-T" inout="${4}"
headers[${#headers[@]}]="x-amz-acl: public-read"
headers[${#headers[@]}]="Expect: 100-continue"
+ if [ "$mime" != "" ]; then
+ headers[${#headers[@]}]="Content-Type: $mime"
+ fi
else
die "Cannot write non-existing file ${4}"
fi
@@ -145,7 +151,7 @@ s3_curl() {
*) die "Unknown verb ${1}. It probably would not have worked anyways." ;;
esac
date="$(TZ=UTC date '+%a, %e %b %Y %H:%M:%S %z')"
- sig=$(s3_signature_string ${1} "${date}" "${bucket}" "${remote}" "${md5}" "" "x-amz-acl:public-read")
+ sig=$(s3_signature_string ${1} "${date}" "${bucket}" "${remote}" "${md5}" "${mime}" "x-amz-acl:public-read")
headers[${#headers[@]}]="Authorization: AWS ${AWS_ID}:${sig}"
headers[${#headers[@]}]="Date: ${date}"
@@ -159,7 +165,8 @@ s3_put() {
# $1 = remote bucket to put it into
# $2 = remote name to put
# $3 = file to put. This must be present if $2 is.
- s3_curl PUT "${1}" "${2}" "${3:-${2}}"
+ # $4 = mime type
+ s3_curl PUT "${1}" "${2}" "${3:-${2}}" "${4}"
return $?
}
View
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+set -e
+
+manifest_type="$1"
+
+if [ "$manifest_type" == "" ]; then
+ echo "usage: $0 <nodejs|npm>"
+ exit 1
+fi
+
+if [ "$AWS_ID" == "" ]; then
+ echo "must set AWS_ID"
+ exit 1
+fi
+
+if [ "$AWS_SECRET" == "" ]; then
+ echo "must set AWS_SECRET"
+ exit 1
+fi
+
+if [ "$S3_BUCKET" == "" ]; then
+ echo "must set S3_BUCKET"
+ exit 1
+fi
+
+basedir="$( cd -P "$( dirname "$0" )" && pwd )"
+
+# make a temp directory
+tempdir="$( mktemp -t node_XXXX )"
+rm -rf $tempdir
+mkdir -p $tempdir
+pushd $tempdir
+
+# generate manifest
+$basedir/aws/s3 ls $S3_BUCKET \
+ | grep "^${manifest_type}" \
+ | sed -e "s/${manifest_type}-\([0-9.]*\)\\.tgz/\\1/" \
+ | sort -r \
+ > manifest.${manifest_type}
+
+# upload manifest to s3
+$basedir/aws/s3 put $S3_BUCKET \
+ manifest.${manifest_type} "" "text/plain"
@@ -33,7 +33,7 @@ mkdir -p $tempdir
pushd $tempdir
# download and extract node
-curl http://nodejs.org/dist/node-v${node_version}.tar.gz -o node.tgz
+curl http://nodejs.org/dist/v${node_version}/node-v${node_version}.tar.gz -o node.tgz
tar xzvf node.tgz
# go into node dir
@@ -56,3 +56,6 @@ tar czvf $tempdir/scons-${scons_version}.tgz *
# upload scons to s3
$basedir/aws/s3 put $S3_BUCKET \
scons-${scons_version}.tgz $tempdir/scons-${scons_version}.tgz
+
+# generate manifest
+$basedir/manifest nodejs
View
@@ -48,3 +48,6 @@ tar czvf $tempdir/npm-${npm_version}.tgz *
# upload npm to s3
$basedir/aws/s3 put $S3_BUCKET \
npm-${npm_version}.tgz $tempdir/npm-${npm_version}.tgz
+
+# generate manifest
+$basedir/manifest npm
View
@@ -0,0 +1,2 @@
+json: https://github.com/trentm/json
+node-semver: http://github.com/isaacs/node-semver
Oops, something went wrong.

0 comments on commit e5f41d0

Please sign in to comment.