git server-side hooks – maintenance

Hi folks.

Server-side hooks that I wrote previously has one huge shortcoming – Maintenance

How do I modify server-side hooks at the moment?

I edit the hook on a client-side, then commit and push.
After that I connect to a git server via Remote Desktop, and manually update hooks in the corresponding folder.

This is lame. This is a manual process, which causes its own complexity.

Ideally server-side hook should just reuse the hooks being pushed.

But usually git server repo is bare so it will require some special kind of checkout. Which I’ve just blogged šŸ™‚

The following code assumes that hooks are located under Tools/GitHooks folder in git repo

git-server-repo\hooks\pre-receive

#!/bin/sh
#
while read oldRef newRef refName
do
    psCommand=".\\hooks\\HookProxy.ps1 -HookName pre-receive -Arguments \"-OldRef\", \"$oldRef\", \"-NewRef\", \"$newRef\", \"-RefName\", \"$refName\""
    c:/windows/system32/WindowsPowerShell/v1.0/PowerShell.exe -Sta -ExecutionPolicy RemoteSigned -NoProfile -Command "$psCommand"

    exitCode=$?

    if [ $exitCode != 0 ]
    then
        exit $exitCode
    fi
done

git-server-repo\hooks\HookProxy.ps1

#requires -version 2.0

[CmdletBinding()]
param
(
    [string] $HookName,
    [object[]] $Arguments
)

$script:ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest
function PSScriptRoot { $MyInvocation.ScriptName | Split-Path }

Trap { throw $_ }

function Main
{
    $tempDir = [Guid]::NewGuid()
    New-Item -Path $tempDir -ItemType Directory | Out-Null

    try
    {
        Git-CheckoutFile -Branch master -RelativeFilePath Tools\GitHooks -DestinationFolder $tempDir

        Invoke-Expression "$tempDir\GitHooks\$HookName.ps1 $Arguments"
    }
    finally
    {
        Remove-Item -Path $tempDir -Recurse -Force
    }

}

function Git-CheckoutFile
{
    param
    (
        [string] $Branch,
        [string] $RelativeFilePath,
        [string] $DestinationFolder
    )

    if ($RelativeFilePath -eq ".")
    {
        $RelativeFilePath = "*"
    }

    $RelativeFilePath = $RelativeFilePath -replace "\\", "/"

    $tempDir = [Guid]::NewGuid()
    New-Item -Path $tempDir -ItemType Directory | Out-Null

    git archive $Branch $RelativeFilePath --output "$tempDir\__temp.tar"
    tar -xf "$tempDir/__temp.tar" -C $tempDir
    Remove-Item "$tempDir/__temp.tar"

    if (-not (Test-Path $DestinationFolder))
    {
        New-Item -Path $DestinationFolder -ItemType Directory | Out-Null
    }

    Copy-Item -Path "$tempDir/$RelativeFilePath" -Destination $DestinationFolder -Recurse

    Remove-Item -Path $tempDir -Recurse -Force
}

Main

Absolutely the same approach could be used for other server-side hooks such as post-receive

And this works as expected

The idea is very simple. We write a proxy (HookProxy.ps1) which will extract corresponding hook from a repo and execute it.
So HookProxy.ps1 is the only piece of code should be deployed once to the server, and later on all hooks modifications are made via source control (master branch).

P.S. I’ve just realized that this can be useful for client-side hooks as well. It will get rid of the need to keep hooks updated in all possible branches.

Advertisements

About mnaoumov

Senior .NET Developer in Readify
This entry was posted in Uncategorized and tagged , , . Bookmark the permalink.

2 Responses to git server-side hooks – maintenance

  1. Pingback: git checkout on bare repo | mnaoumov.NET

  2. Pingback: git hook proxy | mnaoumov.NET

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s