If you are using GitHub as your project’s source code repository, whether open source or private, it’s a good idea to set up an automated deployment mechanism so that whenever someone from your team pushes to the repository, your web app gets built/updated automatically to the latest changes.
There are several continuous integration systems, like Travis, Jenkins, etc., which you can implement for a nice automated build system. However, if your project doesn’t have a very complex build, then you can implement this automated deployment, too, with a simple custom mechanism.
Today, I am discussing a very easy and efficient way to achieve that goal, which won’t require that much complexity to set up those systems on your server. This should be affordable if you are just starting out or developing small/medium-sized apps.
I am already assuming your VPS/dedicated Linux server is set up with git installation.
The 6 Steps To Achieve Our Goal:
- Setup Your Server With a Publicly Accessible Deployment URL
- Have A Build System Set Up On Server
- Create A Web-hook On GitHub
- Web Script/build script settings
- Separating Production/Development Branch
- Run Test/Debug Issues
Let’s discuss the steps in detail:
1. Setup Your Server With a Publicly Accessible Deployment URL:
The first requirement is to have a public URL(either IP or domain-based) of the server where you need to deploy the application. So, if it is some private(password protected), you should consider making it public or at least provide public access to a single webhook script file that will be responsible for performing other necessary operations.
2. Have A Build System Set Up On Server:
You also need to have a simple automated build system on the server for operations like pull/checkout expected revision, update dependency, update file permissions, etc. For a simple build system, you can have a look at my suggestion on easily build system implementation using makefile. On the other hand, if you have proper shell permission on the server scripting language(say PHP), then you can add the commands there, too.
3. Create A Web-hook On Github:
On your project’s settings page, go to the ‘Webhooks/Services’ section and enter the URL of the deployment script you want to have called upon every successful push/merge operation, as in the below screenshot:
The ‘secret’ field is an option; let’s ignore it for our easy setup process.
4. Web Script/build script settings:
You will have to add the deploy script and change file paths to the .gitignore file so that those files aren’t considered part of the git repository at all. Alternatively, you can have it set up in an independent location(not under any git repo) and check/parse the payload data to detect which repository to update. This is helpful if you have multiple applications set up on the same server.
These files also should have proper execution permission by the web server user(usually ‘www-data’). If you have a make file for executing all other build operations, then the web script(here, in my case, a php script) can have a simple instruction as below:
echo shell_exec("make >application/logs/deploy.log 2>&1 </dev/null &");
Code language: PHP (php)
Only the ‘make’ command would work, too. However, we usually want to have our build output written to our log file so that we can analyze if it fails in any way. Also, we are instructing the script to run in the background so that on the GitHub side, we don’t face a timeout error.
5. Separating Production/Development Branch:
It’s necessary to map the build server to the proper git branch if you have multiple branches deployed(one for dev, one for life, etc.). So, if the push is done to a separate branch(say ‘dev’), then the master should be deployed on the dev server. After all testing is done, it should be deployed to the production server when it merges with the master branch. Now, to differentiate between branches, you should use the payload data, which might be something like below:
{
"ref": "refs/heads/master",
"after": "480fa5cfd86d3245db9f71d852aaf2753ded8cd8",
"before": "6290e00b02b70f016f3a6f7e6f4f129ac4062f94",
"created": false,
"deleted": false,
"forced": false,
"compare": "https://github.com/ranacseruet/codeigniterplus/compare/6290e00b02b7...480fa5cfd86d",
"commits": [
{
"id": "6369e6f2ba75d2dcd5f9b221f42e2ccb642c5799",
"distinct": true,
"message": "* add cdn url support.\n* use cdn url on scripts/css loading.\n* favicon",
"timestamp": "2014-08-30T23:06:11-04:00",
"url": "https://github.com/ranacseruet/codeigniterplus/commit/6369e6f2ba75d2dcd5f9b221f42e2ccb642c5799",
"author": {
"name": "Md Ali Ahsan Rana",
"email": "rana_cse_ruet@yahoo.com",
"username": "ranacseruet"
},
...........
}
Code language: JavaScript (javascript)
As you can see, the ‘ref’ key has the value “refs/heads/master”, which indicates the branch it was updated to. So you can use this field for branch detection and others as necessary.
6. Test/Debug Issues:
Now, we can move on to test this process by pushing a simple minor change. If the GitHub side workflow is acceptable, you should see an ok/success status on that GitHub webhook page as below:
Now, you can check the log file path on the server to see how the command execution is going. If it didn’t go well, you can use the ‘redeliver’ button on GitHub to send the same payload again.
Final Words:
You can use some additional measurements for the public repository, like Travis, to verify that your app builds fine without any issues. You might also want to check the requesting host to prevent unauthenticated triggering of the deployment script.
I hope this simple tutorial on the GitHub push-to-deploy mechanism will help you automate your server setup. If you have any specific questions or issues with any step, let me know by commenting.
Leave a Reply