I’d like to share my workflow, as it has proven efficient for me. I’m running two ‘servers’ locally (!). Hang on, I said it was efficient, even though it surely doesn’t sound like it. The workflow should gain teams of any sizes, in my opinion.
I am developing an app it in rails and it also exposes some RESTful web services, with_feed :through => :third_party. The third parties aren’t necessarily third parties, as we develop these too, but they are external apps collecting and sending data to my app. Part 2 will cover the creation of dummy clients that send randomish data to the core app.
OK, I will share the script and procedure I did to have a running server locally alongside developing my app. I wanted to have the server running locally, being able to receive request to the web server, testing the app manually, fast. To distinguish this local server (say localhost:3001) from your development server (sat localhost:3000), I decided to name it experimental, for simplicity. This is my workflow cycle
- developing, creating migrations and so on, running mongrel at localhost:3000
- git commit -am “I commit small changes, often!”
- back_to step 2 if more_should_be_done
- relaunch experimental server at localhost:3001, continuously receiving WS requests.
git pull and git push is performed frequently as well, but not as frequent as the above.
So, why would you I want that last step?
- It’s a great way of proving your migration scripts work. That server is supposed to be running all the time, containing more data, and old data.
- proving that your code works (which you of course also have extensive unit and integration tests for)
- prove that the clients still submit data through the web services as expected. (more of this in Part 2)
- better break experimental than staging?
What? isn’t this just the same as Cap and a staging server?
Well, not exactly, but yes, very similar. Experimental is something in between of staging(pretty stable) and the development server(unstable). If stableish was a word, then that’s what it is;) Differences better explained:
- The staging server is shared, experimental is not.
- The round trip is shorter. ‘git commit’ is sufficient. For staging I bet you have agreements to perform ‘git push’ to share code before deploying to the server (or ‘cap uses git pull’)
- Local development server is too unstable to have other apps sending data to it every hour. So you wouldn’t normally do that, you’d set it up for staging.
- Breaking staging messes up for more people than yourself. Also, you checked the code in with git push, probably.
- With the local experimental server you may mess around as you see fit, without becoming an impediment in your team.
To do this locally, you can’t use Capistrano (if you can, please educate me), so I created my own super-simple script to automate it. Say I have this file structure :
dev/myrailsapp/ (with .git, app/, etc.) dev/temp/myrailsapptest/ (.git, app/, etc.)
where myrailsapptest is a duplicate of myrailsapp, except of the standard configuration files, like database.yml and such. These must be ignored by git, in .gitignore, or they will be overwritten.
#script deploy_to_local rm -rf ~/dev/temp/myrailsapptest/.git cp -rf .git ~/dev/temp/myrailsapptest/ pushd ~/dev/temp/myrailsapptest/ echo "git checkout ." git checkout . echo "rake db:migrate" rake db:migrate echo "Note: remember that the server must have been started with 'mongrel_rails start -d --port 3001' (daemon mode)" mongrel_rails restart echo "Restarting backgroundrb workers" script/backgroundrb restart -e development popd
Pretty simple, right? You can’t do this with svn, though, as it infects every directory you’ve got. Git stores everything in .git/ and a ‘git checkout .’ will automatically replace, add or delete everything as long as they’re not listed in .gitignore.
I’m using backgroundrb for scheduled tasks, if you’re not, remove backgroundrb restart from the script.
Notice that ‘git commit’ must be done first. This is why I consider the experimental server more stable than the development server. You may argue that it could be done without performing git commit first, but I guess nobody will. To me, committing is a small, important task that should be done often.
Backtracking a little, the first thing you have to do, a one-time effort, is
- copy your whole rails app project directory to ../temp/railsapptest so that you also get the ignored files.
- Or, copy the .git and fix the ignored files manually. Whatever suits you.
Note (as in the script): to be able to perform a mongrel restart, you have to start it in daemon mode.
mongrel_rails start -d --port 3001
I’m saying this, because it’s poorly explained and I struggled for hours with it stating “PID file log/mongrel.pid does not exist.” when trying restart after a standard server start (script/server).
Last note. Exposing the local experimental app over the internet.
You don’t need any other server than your own mac/linux/win to show off your app to other people through the internet. Why deploy to staging before showing off your changes?
I did this at home, logged into my router, set up port forwarding of port 3001 to my computer (I’ve set up my router to recognize my mac and always give it the same local ip address)
Then, given the IP address of the router is abc.def.ghi.jkl I would call or email whomever and say, check out the app at abc.def.ghi.jkl:3000 and tell me what you think! This guy would see exactly the same as I would on localhost:3001, which is cool. I’m sorry if you’re a corporate guy with routines, rules or other a bureaucrazy environments, hehe. Well, of course you can’t go port forwarding to thousands of people, this one is just a snack for those of us wanting to show of stuff we make at home in our spare time;)
Hope somebody find this useful! In the next post I will talk about the dummy client apps I wrote to feed my app, using RESTful web services. Maybe something about the backgroundrb jobs I’m using, if I feel like it. Should I?