HowTo keep Redmine in sync with Github without dedicated plugin (Apache CGI + Github Webhook) » History » Version 9

Version 8 (crypto gopher, 2018-10-31 16:13) → Version 9/10 (crypto gopher, 2018-10-31 16:13)

h1. HowTo keep Redmine in sync with Github without dedicated plugin (Apache CGI + Github Webhook)

This is a solution in case you don't want to install additional plugins just to keep repository synchronised. It requires you to have Apache webserver with access to repository you are trying to sync. Apache has to support running CGI scripts.

h2. Clone Github repository

Clone repository and make sure it is accessible by webserver:
<pre>
mkdir /var/lib/redmine/repo
chown apache /var/lib/redmine/repo
su -u apache git -C /var/lib/redmine/repo clone https://github.com/username/repo_name.git
</pre>

h2. Enable WS for repository management in Redmine

Go to @https://your.redmine.com/settings?tab=repositories@ and:
* select: _Enable WS for repository management_
* generate a repository management WS API key and save it for next step

h2. Prepare CGI script

Any script you run on your server will do. Below is an example of Bash script that pulls git repository and notifies Redmine to fetch changesets (substitute @<repository-api-key>@ with your own):

<pre>
#!/bin/sh
# Requires: jq

REPO_PATH='/var/lib/redmine/repo'

# Empty stdin, Apache issue https://bz.apache.org/bugzilla/show_bug.cgi?id=44782
REPO_NAME=$(cat <&0 | jq '.repository.name' | tr -cd 'A-Za-z0-9_-')
if [ -z "${REPO_NAME}" ] || [ ! -d "${REPO_PATH}/${REPO_NAME}" ]; then
echo "Status: 400 Bad Request"
echo "Content-Type: text/plain; charset=utf-8"
echo
echo "project: unrecognized"
exit 0
fi

/usr/bin/git -C "${REPO_PATH}/${REPO_NAME}" pull -n -q
result1=$?

PROJECT_NAME=$(echo "${REPO_NAME}" | tr '_' '-')
/usr/bin/curl --max-time 60 -s "https://your.redmine.com/sys/fetch_changesets?id=${PROJECT_NAME}&key=<repository-api-key>" >/dev/null
result2=$?

if [[ $result1 && $result2 ]]; then
echo "Status: 200 OK"
else
echo "Status: 500 Internal Server Error"
fi

echo "Content-Type: text/plain; charset=utf-8"
echo
echo "project: ${PROJECT_NAME}"

if [[ $result1 ]]; then
echo "git pull: ok"
else
echo "git pull: failed"
fi

if [[ $result2 ]]; then
echo "fetch changesets: ok"
else
echo "fetch changesets: failed"
fi
</pre>

Let's say you save this script under: _/var/www/cgi-bin/update-repo.cgi_

You can test if script executes properly:
<pre>
echo <copy-input-from-github-webhook-request> | sudo -u apache /var/www/cgi-bin/update-repo.cgi
</pre>



h2. Configure Apache to run script whenever particular URL is requested

Inside @VirtualHost@ of your choice just add:
<pre>
...
# Github webhook for repository pull/update
ScriptAlias /update-repo.cgi /var/www/cgi-bin/update-repo.cgi /var/www/localhost/cgi-bin/update-repo.cgi
<Directory /var/www/cgi-bin/> /var/www/localhost/cgi-bin/&gt;
Options ExecCGI
AllowOverride None
Require all granted
</Directory>
...
</pre>

In case you use the same @VirtualHost@ to proxy requests to your Redmine @rails server@, you should exclude your special URL from being proxied with:
<pre>
ProxyPass /update-repo.cgi !
</pre>



h2. Configure Github Webhook

Go to your Github repository page, choose _Settings -> Webhooks -> Add webhook_. Then set:
* Payload URL: @https://your.virtualhost.com/update-repo.cgi@
* Which events would you like to trigger this webhook?: Just the push event.
* Active: yes

Update webhook and you're done.