Skip to content

Instantly share code, notes, and snippets.

@fcangialosi
Last active August 10, 2017 09:25
Show Gist options
  • Save fcangialosi/019c395d6185060cfe348f5b6a840a86 to your computer and use it in GitHub Desktop.
Save fcangialosi/019c395d6185060cfe348f5b6a840a86 to your computer and use it in GitHub Desktop.
DIY GitHub Build Server

DIY GitHub Build Server

This gist shows how to setup a simple build server with Apache.

GitHub sends a push request to the server each time the repository is updated.

Apache handles this request and runs a python script in response, which pulls from the repository and creates a new build.

This assumes the Apache user is called "www-data" with a home directory of /var/www/ and that project files live in /var/www/PROJECT

(Note: The order of these steps is mostly arbitrary)

Step 1: Setup Apache Config

Copy the contents of apache.config to /etc/apache2/sites-enabled/000-default.conf

Modify as necssary, at minimum replacing PROJECT and making sure all directories and files exist as expected

Run sudo service apache2 restart

Step 2: Create push handler script

Copy push script into /var/www/PROJECT

Modify as necessary

Step 3: Create ssh keypair for Apache

sudo mkdir /var/www/.ssh

ssh-keygen

(Location: /var/www/.ssh/)

sudo -R chown www-data:www-data /var/www/.ssh

sudo -R chmod 600 /var/www/.ssh/*

Then, add this ssh keypair to your GitHub Account

Step 4: Setup webhook

Create push webhook on GitHub (in project settings)

Point it to $IP/PROJECT/push

Step 5: Apache permissions

Give apache user permission to access all of the project files

sudo chown -R www-data:www-data /var/www/PROJECT

sudo chmod -R 777 /var/www/PROJECT

Note: If git pull says "the authenticity of host cannot be established" each time, this probably means the www-data user doesn't have access to /var/www/.ssh, which it needs to create the known_hosts file.

Step 6: Verify that script has correct permissions

sudo -u www-data /var/www/PROJECT/push

Versions

Apache/2.4.18 (Ubuntu)

# Replace PROJECT with name of repository
<VirtualHost *:80>
# Default directory for files
DocumentRoot /var/www/html
# Provide path for Script to handle push requests from GitHub
ScriptAlias /PROJECT/push /var/www/PROJECT/push
# Access to build files outside of DocumentRoot
Alias /PROJECT /var/www/PROJECT
<Directory /var/www/PROJECT>
Options Indexes FollowSymlinks Multiviews
Order allow,deny
# Public
Allow from all
# Ignore the push script in index listing for "/"
IndexIgnore push
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
#!/usr/bin/env python
import os, subprocess
import cgitb
cgitb.enable()
# Print header
# Add Connection:Keep-Alive and flush buffer for real-time
print "Content-Type: text/html;charset=utf-8\n"
# Run command, e.g.
p = subprocess.Popen("cd PROJECT && git pull && GOPATH=/home/ubuntu/go-work make", shell=True, stdout=subprocess.PIPE)
out = p.stdout.read()
# Pipe output to stdout (which gets sent as html)
for l in out.split("\n"):
print l
print "<br>"
# Copy build files to apache dir
os.system("cp .../PROJECT/* /var/www/PROJECT")
print "Done"
# Save output for easy checking of latest build status at $IP/PROJECT/status
with open('./status', 'w') as f:
f.write(out)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment