I have a Digital Ocean Droplet that has been hosting an old Python project for years now. I distinctly remember being able to git push to deploy that service, but I don’t remember how I set it up. Now I’m going back to figure that out. First, I have a look at my project on my old development machine, to maybe get a bit wiser:
~/projects/projectname $ git remote -v live ssh://email@example.com:/var/repo/project.git (fetch) live ssh://firstname.lastname@example.org:/var/repo/project.git (push) livegit email@example.com:/var/repo/site.git (fetch) livegit firstname.lastname@example.org:/var/repo/site.git (push) origin https://github.com/casperlehmann/project.git (fetch) origin https://github.com/casperlehmann/project.git (push)
There is an origin pointing to Github, fine. Apparently, I was also thinking to separate the web page from the api I was developing. That was never how I ended up doing things, I’m certain. But that’s that.
Anyway, we see that I was using a user named
git on the server. That means I was not deploying with my admin account. Good thing, that.
Now, lets have a look at the server itself.
The server process runs in a
tmux session. That session can be accessed with
tmux attach. We shut down the session with
Ctrl+C and see that the site itself is located in
/var/www/project. This is different from the repo location that we just found, and I’d like to know why.
To recap: The dev machine is pushing to a remote repo called
live. It lives on the VM under
/var/repo/project.git, meanwhile, the server process is hosted from the directory
/var/www/project. Again, why? And how?
/var/repo/project.git, we find the
hooks folder. This contains a number of files, one of them is called
post-receive. It’s the only file not named
$ cat /var/repo/project.git/hooks/post-receive #!/bin/sh git --work-tree=/var/www/project --git-dir=/var/repo/project.git checkout -f
This is a clever hack for keeping the
work tree and the
repo separate. Obviously, Git is called, but then the two locations are passed as named parameters, and finally the
checkout argument is forced. When this command is used in a git hook like this, it runs automatically every time anything is pushed to the repo. The checkout means that the code that is live on the site is going to get refreshed with the latest changes.
This operation translates to a re-deploy of the entire repo, thus updating the web service.
But why? Well, this was a long time ago, and I am sure I had not heard about continuous delivery at that point. This solution allows for direct and secure communication with the deployment server through ssh, and with no middle man. In other words, it’s a deploy script.
Looking back, this seems like a good value proposition, discounting the fact that there is no automated regression testing in sight. But had I known you could deploy a branch automatically with Jenkins, I would probably have done that. Also, I’m still not sure why the
work tree are separate.
That said, this is a fun exercise for learning about git hooks, and maybe exploring how to go about building an automation system of one’s own.