andrewrk / naught

Zero downtime deployment for your Node.js server using builtin cluster API
MIT License
793 stars 69 forks source link

Provide new 'cwd' option during deploy #25

Open JoshuaGross opened 11 years ago

JoshuaGross commented 11 years ago

I don't really understand how to use Naught in a robust way for new deploys. My current deploy script has a git post-receive hook that brings the old server down and a new server up; if the new server fails, it will rollback and bring the old server back up. One thing I'd like to do with Naught is provide new CWDs in a deploy and then periodically check the health of the new deploy and switch back to the old CWD if necessary. What I'll do for now is symlink a directory and point Naught to that, but this seems strange.

andrewrk commented 11 years ago

Your request makes sense; however I think we may be limited by node's cluster API.

JoshuaGross commented 11 years ago

Ahh, I didn't realize that. Makes sense. Do you manage production deploys in a similar way to me / do you have any suggestions for how to do this elegantly?

andrewrk commented 11 years ago

We currently use rodent to do production deploys. It may not be generic enough for your use case, but here's what a deploy looks like:

So there are no backup folders with previous releases to roll back to. However, deploys are very fast, usually taking about 5 seconds. So if you want to roll back to a previous commit, you can deploy that previous commit and the previous commit will be live in 5 seconds.

JoshuaGross commented 11 years ago

I think I like that better than the current system, which takes much longer than 5s to deploy and doesn't really use the power of Git. Thanks - this is informative!

Joshua Gross Christian / SpanDeX, Inc. / BA of Computer Science, UW-Madison 2013 http://www.joshisgross.com / http://www.spandex.io

On 5 March 2013 14:07, Andrew Kelley notifications@github.com wrote:

We currently use rodent https://github.com/indabamusic/rodent to do production deploys. It may not be generic enough for your use case, but here's what a deploy looks like:

  • developer pushes the code to a remote branch (usually master)
  • developer executes the deploy command
  • on each production target
    • git fetch
    • git checkout origin/(deploy-branch)
    • npm install
    • ./node_modules/.bin/naught deploy

So there are no backup folders with previous releases to roll back to. However, deploys are very fast, usually taking about 5 seconds. So if you want to roll back to a previous commit, you can deploy that previous commit and the previous commit will be live in 5 seconds.

— Reply to this email directly or view it on GitHubhttps://github.com/indabamusic/naught/issues/25#issuecomment-14462133 .

iuriaranda commented 10 years ago

We perform deploys the capistrano / chef way, so the deploy process creates a /release/<version> directory and then creates a symlink from /current to the latest deployed version dir. So we face the problem of the cwd in the deploy command.

A quick workaround that I've seen here: http://clarkdave.net/2013/02/node-js-and-cluster-cwd-dirname-shenanigans/ would be to chdir inside the main script of the app using the __dirname variable:

if (__dirname !== process.cwd()) {
  process.chdir(__dirname);
}

Even this does not involve any change in naught, I think it would be cleaner if there was a way to change the cwd during a naught deploy.

andrewrk commented 10 years ago

Feel free to make a PR. This feature can easily lead to subtle problems - I think we want an automated test or 2 for this feature.

andrewrk commented 10 years ago

This is now implemented and released in 1.2.0 thanks to dmcaulay

danshulman commented 10 years ago

I have a node.js app (express) in folder1. I start the server using "naught start app.js". I now would like to deploy the updated version located in folder2. I run (from folder1) "naught deploy --cwd ../folder2".

I get the following result:

SpawnNew. booting: 1, online: 1, dying: 0, new_online: 0 NewOnline. booting: 0, online: 1, dying: 0, new_online: 1 ShutdownOld. booting: 0, online: 0, dying: 1, new_online: 1 OldExit. booting: 0, online: 0, dying: 0, new_online: 1 done

The server is still up, but folder1 is still deployed, instead of folder2. I would like to make the switch from folder1 to folder2 with zero downtime. Any suggestions?

andrewrk commented 10 years ago

cc @dmcaulay

dmcaulay commented 10 years ago

@andrewrk I'll take a look

dmcaulay commented 10 years ago

@zenshulman I've updated my fork with a possible fix. I've tested locally, but I want to make sure it works for you before opening a PR. Can you test with my fork? https://github.com/prix-fixe/naught

dmcaulay commented 10 years ago

@zenshulman I want to clarify that the cwd option does not change the script location. I'm using a symlink for that.

For example if you run naught deploy --cwd '/release/2' it doesn't change the script file location from '/release/1/server.js' to '/release/2/server.js'. It only changes the cwd directory for the master process. This is needed because the workers inherit the cwd from the master process.

I think we could update the script file, but that would take a little more work. What do you think @andrewrk? Should the cwd option change the script location on deploy?

danshulman commented 10 years ago

Oh, I thought cwd role is to change the script. Using symlink works, but what's cwd for?

andrewrk commented 10 years ago

if cwd exists, it seems like it should work for this use case, right?

danshulman commented 10 years ago

For what use case? Switching scripts from different folders?

andrewrk commented 10 years ago

Yes. This is your use case, correct?

danshulman commented 10 years ago

It is. But using cwd alone with no symlink doesn't change the script.

andrewrk commented 10 years ago

Sorry, to be clear, I am arguing in favor of your use case. I am saying that as is it is broken and we should support this use case.

danshulman commented 10 years ago

ah, ok great. Yes, I 'm totally in favor of that :)

dmcaulay commented 10 years ago

i just reviewed the docs and im not sure if that's possible. check it out. http://nodejs.org/api/cluster.html#cluster_cluster_setupmaster_settings

"Only the first call to .setupMaster() has any effect, subsequent calls are ignored"

also cluster.settings http://nodejs.org/api/cluster.html#cluster_cluster_settings

"It is effectively frozen after being set, because .setupMaster() can only be called once."

dmcaulay commented 10 years ago

@zenshulman you need to change cwd because it's used when you require files. If it is not updated then require will load the files from the old directory.

danshulman commented 10 years ago

cool, got it!

danshulman commented 10 years ago

Wait, so how come when I deploy after changing only the symlink ("naught deploy" only, no pwd option), I see changes from the new folder?

dmcaulay commented 10 years ago

Because cwd defaults to the cwd of the naught script.

andrewrk commented 10 years ago

I looked into it, and sadly I think @dmcaulay is right - we already call process.chdir with the new cwd when you deploy, but it doesn't work for the script.

See https://github.com/joyent/node/issues/3893 and https://github.com/joyent/node/issues/6264

danshulman commented 10 years ago

ah ok, so I'll use the symlink method then.

dmcaulay commented 10 years ago

@andrewrk we should probably update the readme so this is clearer. do you want me to take a stab at it and open a pr?

danshulman commented 10 years ago

sure, why not

andrewrk commented 10 years ago

@dmcaulay yes please. meanwhile I opened the above issue in joyent/node

freezy commented 10 years ago

Great! Started testing this out yesterday and didn't work, then I read through the GitHub issues here, saw it was fixed three hours before, pulled from repo and it started working. :)

I've described how to setup naught with an upstart service wrapper and Git push deployment here in case anyone is interested. All the rest is still WIP though.