Permalink
Browse files

sc-deploy now runs an optional "dependencies" script when present. Th…

…is script is for installing server-side dependencies that can't just be rsynced over from development. The provided example script runs "npm install", if and only if there is a package.json file. This is a great way to do it for node apps. Now it is safe to deploy apps that contain compiled node extensions among their npm modules with stagecoach. Thanks to Howard Tyson for pointing out the need to address this. The example app now depends on express, just to demonstrate that the remote 'npm install' works.
  • Loading branch information...
1 parent 2264ffc commit 50653cf6a92ed7315daafd6d445e80a1fa9fddf7 @boutell boutell committed Aug 23, 2012
Showing with 97 additions and 12 deletions.
  1. +1 −0 .gitignore
  2. +12 −4 README.md
  3. +29 −3 bin/sc-deploy
  4. +23 −0 example/deployment/dependencies
  5. +3 −0 example/deployment/rsync_exclude.txt
  6. +19 −0 example/package.json
  7. +10 −5 example/server.js
View
@@ -1,5 +1,6 @@
sc-proxy/config.js
sc-proxy/node_modules
+example/node_modules
# These are YOUR apps, if you're trying to send me a pull request you don't want to send me these (:
apps
# This is YOUR settings file, not mine
View
@@ -1,8 +1,8 @@
# stagecoach: host multiple Node apps on your Linux servers
-Stagecoach is a framework for deploying node.js web applications and testing them on a staging server, then deploying them to production servers. It includes a complete mechanism for running many such node applications on a single staging or production server, restarting them gracefully on reboot, and accessing them at nice URLs without port numbers.
+Stagecoach is a framework for deploying node.js web applications and testing them on a staging server, then deploying them to production servers. It includes a complete mechanism for running many such node applications on a single staging or production server, restarting them gracefully on reboot, and accessing them at nice URLs without port numbers.
-Stagecoach also includes `sc-deploy`, a minimalist deployment tool based on rsync that understands multiple deployment targets and makes pretty much no assumptions about your project. It is suitable for pretty much any site or web app you wish to deploy, although the examples provided are node-oriented.
+Stagecoach also includes `sc-deploy`, a minimalist deployment tool based on rsync that understands multiple deployment targets and makes pretty much no assumptions about your project. It is suitable for pretty much any site or web app you wish to deploy, although the examples provided are node-oriented. Although `sc-deploy` relies on `rsync` it will also run an optional `dependencies` script to install dependencies that are server-specific and can't be transferred from your development environment. This is handy for installing npm modules with `npm install`.
We also threw in a nice installer script for node, forever and mongodb on Ubuntu which installs the recommended versions from Joyent and the MongoDB team.
@@ -34,7 +34,7 @@ Like other deployment tools, sc-deploy deploys to a new folder on the target ser
`sc-deploy` creates a symbolic link from `/opt/stagecoach/apps/example/current` to the latest deployment folder if everything happens successfully (assuming that your project is called `myproject` and you base your paths on those in `example`). If you're deploying traditional web languages like PHP, you'll want to make sure your web document root is configured accordingly.
-`sc-deploy` relies on bash scripts in a subdirectory of your project called `deployment` to carry out the work of starting (`start`), stopping (`stop`) and migrating (`migrate`) your project. If any of these exit with a nonzero status, the deployment process stops and the previous version of the site stays live. Currently any failed deployment folders are left on the server for your debugging convenience.
+`sc-deploy` relies on bash scripts in a subdirectory of your project called `deployment` to carry out the work of starting (`start`), installing dependencies for (`dependencies`), stopping (`stop`) and migrating (`migrate`) your project. If any of these scripts exit with a nonzero status, the deployment process stops and the previous version of the site stays live. Currently any failed deployment folders are left on the server for your debugging convenience.
Settings that apply to all deployment targets for this project, such as the project's name and (usually) the deployment directory, reside in `deployment/settings`. You'll want to edit the `PROJECT` setting, and possibly the `DIR` setting as well. The project name should be a reasonable Unix shortname; it's the folder name you'll be deploying to. If you use `sc-proxy` it is also the subdomain you'll use to access the staging site.
@@ -62,6 +62,14 @@ Tip: you should definitely set up a trusted ssh public key that allows you to ss
In the `example` folder you'll find an example of ndoe app deployment, with all the important bits already set up (be sure to look in `example/deployment`). The `start` script integrates with `sc-proxy` by registering a port number for the project to listen on via the data/port file, and the provided example node app consults that file as well at startup.
+## Installing dependencies on the server side
+
+Note that if your project has a `production/dependencies` script it will be run immediately after the rsync is complete and before the site is restarted. This is the right place to execute `npm install` if your application has dependencies on npm modules that involve compiled code that can't be transferred from your own computer.
+
+Did your eyes skip right over all that? Don't worry - if you are copying your app's `deployment` folder from the latest `example` app included with stagecoach, then `npm install` will happen for you automatically. Those of you already using stagecoach who want this feature can just copy `example/deployment/dependencies`.
+
+Thanks to Howard Tyson for pointing out the need to install dependencies on the server side.
+
## Production Hosting
You can do production hosting with `sc-proxy` as well.
@@ -82,7 +90,7 @@ If you add or modify a `hosts` file, there will be a delay of up to a minute. I'
## Warnings and Limitations
-`sc-deploy` expects that you will not have spaces in your target deployment folder name or your project name. If you like making things difficult for shell scripts, this is not the tool for you.
+`sc-deploy` expects that you will not have spaces in your target deployment folder name or your project name. If you like making things difficult for shell scripts, this is not the tool for you.
The provided sample `start` and `stop` scripts do not attempt to use `chroot` jails to prevent apps from seeing each other's files. If you need that, you might be happier with `haibu`.
View
@@ -29,7 +29,7 @@ VERSION=`date "+%Y-%m-%d-%H-%M-%S"`
# rsync to a new folder, then flip the symlink if everything runs without error.
#
# start is run after the symlink is changed so the current directory looks
-# more reasonable to other scripts.
+# more reasonable to other scripts.
DEPLOYTO="$DIR/deployments/$VERSION"
CURRENT="$DIR/current"
@@ -41,6 +41,32 @@ CURRENT="$DIR/current"
ssh -p $SSH_PORT $USER@$SERVER "mkdir -p $DIR/deployments" &&
rsync -e "ssh -p $SSH_PORT -l$USER" -C -a --delete $EXCLUDE . $USER@$SERVER:$DEPLOYTO &&
-ssh -p $SSH_PORT $USER@$SERVER "$ADJUST_PATH; cd $CURRENT; bash deployment/stop; cd $DEPLOYTO && bash deployment/migrate && rm -rf $CURRENT && ln -s $DEPLOYTO $CURRENT && cd $CURRENT && bash deployment/start" &&
-echo "Deployment successful."
+ssh -p $SSH_PORT $USER@$SERVER <<EOM
+ $ADJUST_PATH
+ # A good place to run "npm install"
+ echo "Looking for dependencies script at $DEPLOYTO/deployment/dependencies"
+ hostname
+ if [ -f $DEPLOYTO/deployment/dependencies ]; then
+ cd $DEPLOYTO
+ bash deployment/dependencies
+ if [ \$? -ne 0 ]; then
+ echo "Deployment failed during dependencies script!"
+ exit 1
+ fi
+ fi
+ cd $CURRENT
+ bash deployment/stop
+ cd $DEPLOYTO &&
+ bash deployment/migrate &&
+ rm -rf $CURRENT &&
+ ln -s $DEPLOYTO $CURRENT &&
+ cd $CURRENT &&
+ bash deployment/start
+EOM
+if [ $? -ne 0 ]; then
+ echo "Deployment failed!"
+ exit 1
+else
+ echo "Deployment successful."
+fi
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# Install any dependencies that can't just be rsynced over with
+# the deployment. Example: node apps have npm modules in a
+# node_modules folder. These may contain compiled C++ code that
+# won't work portably from one server to another.
+
+# This script runs after the rsync, but before the 'stop' script,
+# so your app is not down during the npm installation.
+
+# Make sure node_modules exists so npm doesn't go searching
+# up the filesystem tree
+mkdir -p node_modules
+
+# If there is no package.json file then we don't need npm install
+if [ -f './package.json' ]; then
+ # Install npm modules
+ npm install
+ if [ $? -ne 0 ]; then
+ echo "Error during npm install!"
+ exit 1
+ fi
+fi
@@ -5,3 +5,6 @@
data
.git
.gitignore
+# We don't deploy these anymore, instead we always 'npm install' to ensure
+# that any compiled C++ modules are built for the right architecture
+node_modules
View
@@ -0,0 +1,19 @@
+{
+ "author": "P'unk Avenue <tom@punkave.com> (http://punkave.com/)",
+ "name": "example",
+ "description": "Example node app run and deployed under stagecoach",
+ "version": "1.0.0",
+ "homepage": "http://github.com/punkave/stagecoach",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/punkave/stagecoach.git"
+ },
+ "dependencies": {
+ "express": "~3.0.0rc3"
+ },
+ "devDependencies": {},
+ "optionalDependencies": {},
+ "engines": {
+ "node": "*"
+ }
+}
View
@@ -2,7 +2,11 @@
// Note that since we rsync_exclude that folder you can have one in your
// git repository for testing in dev environments
-var http = require('http');
+// Use express just to demonstrate that we can install npm modules on the
+// remote server. You don't have to use Express
+
+var express = require('express');
+var app = express();
var fs = require('fs');
// Get the port number from data/port. Watch out for trailing whitespace
@@ -21,7 +25,8 @@ try
port = 3000;
}
-http.createServer(function (req, res) {
- res.writeHead(200, {'Content-Type': 'text/plain'});
- res.end("Hi there! I was deployed with stagecoach.\n");
-}).listen(port, '127.0.0.1');
+app.get('/', function(req, res) {
+ res.send("I was deployed with Stagecoach!");
+});
+
+app.listen(port);

0 comments on commit 50653cf

Please sign in to comment.