linux/doc/Push-to-Deploy.md

3.0 KiB

Introduction

This document describes how to setup a Git hook to enable the update of a repository when a new commit is received.

This effectively is an implementation of a Push-to-Deploy update/continuous integration strategy.

For the described approach to work, the Git server and the deployment target must be running on the same machine. However, the files do not need to be accessible by both Git and the application server. That is why a safe indirection over root is necessary.

The deployment tree is a working directory of the Git repository. This has the advantage that no files accidentally get overwritten by Git. For example, for projects using PHP, this might be important. Although the increased amount of storage space is a tradeoff, it can be optimized by reducing the history depth of the repository from time to time. A brief hint hereof can be found at the end of this document.

The main work of the implementation is done by a universal script. Actually, it could be used in any situation where a safe update of a repository is needed.

Files

The following files are used to describe the implementation:

  • /path/to/main.git The main bare repository receiving the updates.
  • /path/to/deploy-target The deployment target directory. It is a working directory of a git repository.
  • /path/to/safe-update The safe update script which is listed below.

Universal Safe Update

Copy the file git-safe-update.sh and make it executable.

It can be used to update any repository. It takes two arguments:

  1. Path of a non-bare Git repository
  2. Intended owner of the files

The chown line at the end of the script is the reason why the script needs to be run as root. The chapter below describes how to configure sudo to enable root access.

Note that the user always knows what is going on in case of a failure.

Git Hook

Install the following script as the post-receive hook. In this case to /path/to/main.git/hooks/post-receive.

It executes safe-update only when the master branch is updated.

#!/bin/sh

read oldid newid ref
if [ "$ref" = "refs/heads/master" ]; then
	sudo /path/to/safe-update /path/to/deploy-target www-data.www-data
fi

Deployment Target Git Configuration

Because the Git repository lies on the same machine, and is owned by a different user, it is safer to use a file: URL as the remote. The master branch is assumed to be a deployable version. Hence, use the following command to add the remote:

cd /path/to/deploy-target
git init
git remote add -t master origin file:///path/to/main.git
git fetch --depth=1
git checkout master

Sudo Configuration

Paste the following line to /etc/sudoers.d/safe-update or append it to /etc/sudoers:

git ALL=(root) NOPASSWD: /path/to/safe-update

This enables user git to run safe-update as root without password. So be careful..!

Miscellaneous

To "forget" old git history, I had success with the following commands:

rm -r .git/objects
mkdir .git/objects
git fetch --depth=1