Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

heroku-like workflow on personal server

I'm trying to set up a server with pure-git workflow similar to heroku. I don't need help setting up git, but for informative purposes, I'm using gitolite. I'd like to (somehow) write custom hooks in the operating system (Ubuntu) of this system so that, when it receives a push on a particular branch, it performs all the operators heroku does (starting Rack, Mongrel, Apache (for static serving pages in my case), etc.

Can someone point me towards a resource to do this or at least get started? A google search didn't really seem to help...

like image 254
sethvargo Avatar asked Jan 25 '11 18:01

sethvargo


5 Answers

It sounds like you want to execute arbitrary functionality at a certain point in your Git workflow. Git hooks are the way to go.

If you look in any Git repo (inside the .git folder), you'll see a hooks folder. Inside it there are a number of example hook files with different names. Based on your explanation above, you want to edit the post-receive hook file, since that will be called immediately after a new ref has been updated in your remote repo (resulting from a push from a local one). For more info, read the official documentation on hooks or read this perhaps more approachable explanation.

You can put any shell commands you want in a hook file. Change the filename from post-receive.sample to simply post-receive, add the commands you need to start Rack, Mongrel, Apache, etc., then make the file executable with a quick chmod +x post-receive and you're all set.

like image 133
semperos Avatar answered Oct 12 '22 23:10

semperos


Have you looked at Capistrano? From wiki:

Capistrano is a utility and framework for executing commands in parallel on multiple remote machines, via SSH. It uses a simple Domain Specific Language borrowed in part from the tool rake. Rake is similar to make in the C world and allows you to define tasks, which may be applied to machines in certain roles. It also supports tunneling connections via some gateway machine to allow operations to be performed behind VPNs and firewalls.

Capistrano was originally designed to simplify and automate deployment of web applications to distributed environments, and originally came bundled with a set of tasks designed for deploying Rails applications. The deployment tasks are now (as of Capistrano 2.0) opt-in and require clients to explicitly put "load ‘deploy’" in their recipes.

It's not based on any sort of commit or post hooks, although I'm sure if you really needed that, then you would be able to find some example recipes to do something like that.

Update: Maybe git-deploy (based on Capistrano) is what you want:

A tool to install useful git hooks on your remote repository to enable push-based, Heroku-like deployment on your host.

like image 44
bhamby Avatar answered Oct 12 '22 23:10

bhamby


I just uncovered https://github.com/mislav/git-deploy, which is EXACTLY what I wanted. I'm going to leave the other answer as "correct" (since it was the best at the time), but I'm using git-deploy now :)

like image 28
sethvargo Avatar answered Oct 12 '22 23:10

sethvargo


I have a similar setup where the master branch is automatically deployed as staging using capistrano on git push. Production is manually deployed from the production branch.

The setup require that you use set :deploy_via, :remote_cache in deploy.rb to have a local cache copy on the server. This is to be able to run capistrano with the latest configuration if is has been changed since last deploy.

post-receive hook script:

#!/bin/bash
while read oldrev newrev ref
do
        if [ "$ref" = "refs/heads/master" ] ; then
                echo "Master branch pushed, deploying to staging"
                # seams to be set to "." for hooks, unset to make things more normal
                unset GIT_DIR
                # deploy path, where "current", "releases", "shared" etc are
                DEPLOYDIR="/home/user/deploy/staging"
                # default path for :deploy_via :remote_cache is shared/cached-copy
                cd "$DEPLOYDIR/shared/cached-copy"
                # update cache to pushed revision, will be done by capistrano too
                git fetch origin && git fetch --tags origin && git reset --hard "$newrev"
                # load rvm
                source ~/.rvm/scripts/rvm
                rvm use 1.9.2
                # make sure correct gems are installed
                # this will also create a .bundle directory
                bundle install --gemfile Gemfile --path "$DEPLOYDIR/shared/bundle" --deployment --without development test
                # run capistrano
                # if you use deploy:migrations instead of deploy you should probably add
                # after "deploy:migrations", "deploy:cleanup"
                # to your deploy.rb
                bundle exec cap staging deploy:migrations
        fi
done

A simpler setup without :remote_cache is also possible but it will run capistrano with the previous (currently deployed) configuration and seams to be a bit more fragile.

post-receive hook script:

#!/bin/bash
while read oldrev newrev ref
do
        if [ "$ref" = "refs/heads/master" ] ; then
                echo "Master branch pushed, deploying to staging"
                # seams to be set to "." for hooks, unset to make things more normal
                unset GIT_DIR
                source ~/.rvm/scripts/rvm
                rvm use 1.9.2
                cd /home/user/deploy/staging/current && bundle exec cap staging deploy:migrations  
        fi
done
like image 30
Mattias Wadman Avatar answered Oct 13 '22 00:10

Mattias Wadman


I recommend checking out GitHub:progrium/dokku, it's based on Docker technology and really easy to setup and use.

If you're also looking for cloud provider, I recommend DigitalOcean since they support Dokku out of the box! Checkout their community documentation for more information.

Your workflow will be very much similar to Heroku: (Full Tutorial)

  1. Setup Dokku Server (Your personal Heroku) and your public key
  2. Configure your domain to point *.DOMAIN.com to Dokku Server
  3. Add Git Remote to your repo: git remote add myheroku [email protected]:your-app
  4. Push code to Dokku server: git push myheroku master
  5. Checkout http://your-app.DOMAIN.com

Also if you want to have different sub-domain or full-domain assign to your app, you can install Dokku Domain Plugin and simply do specify domain to your-app: dokku domains:set your-app NEWDOMAIN.com

It's worth mentioning new project called Flynn GitHub: flynn/flynn which comes with more features than Dokku. Read history behind Flynn and Dokku here...

like image 21
Qorbani Avatar answered Oct 13 '22 00:10

Qorbani