How to deploy Gitlab project branch to directory

我的梦境 提交于 2019-12-11 18:00:16

问题


I have a Gitlab server (Ubuntu 14.04) where I am trying use it as both a host for my repositories as well as a testing server for my PHP projects. Ideally, I would like to have Gitlab/Git export the "release" branch to /var/www/git/<project-name> when that branch is updated.

My Question: How can I export a specific branch in Gitlab, to a specific directory on the localhost, when the branch is updated?

I am aware that there are webhooks available in Gitlab, but it seems unnecessary and wasteful to have the server POST to itself for a local operation.


回答1:


I suppose you are running the community edition of gitlab.

Then, only the server administrator can configure hook scripts by copying the required scripts into the affected repositories.

gitlab itself is using the $GIT_DIR/hooks directory for its own scripts already. Fortunately they forward control to any hook script in the gitlab specific $GIT_DIR/custom_hooks directory. See also this question about how to run multiple hooks with the same type on gitlab.

The script itself could look like this:

#!/bin/bash
#
# Hook script to export current state of repo to a release area
#
# Always hardcode release area - if configured in the repo this might incur data loss
# or security issues

echo "Git hook: $0 running"

. $(dirname $0)/functions

git=git
release_root=/gitlab/release
# The above release directory must be accessible from the gitlab server
# and any client machines that want to access the exports. Please configure.


if [ $(git rev-parse --is-bare-repository) = true ]; then
    group_name=$(basename $(dirname "$PWD"))
    repo_name=$(basename "$PWD")
else
    cd $(git rev-parse --show-toplevel)
    group_name=$(basename $(readlink -nf "$PWD"/../..))
    repo_name=$(basename $(readlink -nf "$PWD"/..))
fi



function do_release {
    ref=$1
    branch=$2

    # Decide on name for release
    release_date=$(git show -s --format=format:%ci $ref -- | cut -d' ' -f1-2 | tr -d -- -: | tr ' ' -)
    if [[ !  "$release_date" =~ [0-9]{8}-[0-9]{6} ]]; then
        echo "Could not determine release date for ref '$ref': '$release_date'"
        exit 1
    fi

    dest_root="$release_root/$group_name/$repo_name"
    dated_dir="dated/$release_date"
    export_dir="$dest_root/$dated_dir"
    # Protect against multiple releases in the same second
    if [[ -e "$export_dir" ]]; then
        export_dir="$export_dir-02"
        dated_dir="$dated_dir-02"
        while [[ -e "$export_dir" ]]; do
            export_dir=$(echo $export_dir | perl -pe 'chomp; print ++$_')
            dated_dir=$(echo $dated_dir | perl -pe 'chomp; print ++$_')
        done
    fi
    # Create release area
    if ! mkdir -pv "$export_dir"; then
        echo 'Failed to create export directory: ' "$export_dir"
        exit 1
    fi
    # Release
    if ! git archive $branch | tar -x -C "$export_dir"; then
        echo 'Failed to export!'
        exit 1
    fi
    chmod a-w -R "$export_dir"      # Not even me should change this dir after release
    echo "Exported $branch to $export_dir"

    ( cd "$dest_root" && rm -f latest && ln -s "$dated_dir" latest )
    echo "Adjusted $dest_root/latest pointer"
}


process_ref() {
    oldrev=$(git rev-parse $1)
    newrev=$(git rev-parse $2)
    refname="$3"

    set_change_type
    set_rev_types
    set_describe_tags

    echo "  Ref: $refname","$rev_type"

    case "$refname","$rev_type" in
        refs/heads/*,commit)
            # branch
            refname_type="branch"
            function="branch"
            short_refname=${refname##refs/heads/}
            if [[ $short_refname == release ]]; then
                echo "    Push accepted. Releasing export for $group_name/$repo_name $short_refname"
                do_release "$refname" "$short_refname"
            else
                echo "    Push accepted. No releases done for $group_name/$repo_name $short_refname"
            fi
        ;;
        refs/tags/*,tag)
          # annotated tag
          refname_type="annotated tag"
          function="atag"
          short_refname=${refname##refs/tags/}
        ;;
    esac
}

while read REF; do process_ref $REF; done

exit 0

The script was started based on this post-receive.send_email script which is already quoted on SO multiple times.

Configure a release area in the variable hardcoded in the script, or e.g. add a mechanism to read a config file in the repo. Maybe you want to give users control over this area. Depends on your security circumstances.

The release area must be accessible by the git@gitlab user, and of course by any client expecting the export.

The branch to export is hardcoded in the script.

The release area will be populated like this:

$release_root/$group_name/$repo_name/dated/$release_date

Plus a symbolic link latest pointing to the latest $release_date. The idea is that this is extensible to later be able to also export tags. If you expect to export different branches, a $branch should be included as a path component, too.

Access control of the gitlab server is not passed down to the directory structure. Currently I do this manually, and that is why I do not auto-populate all new repositories with this hook. I'd rather configure manually, and then adjust unix group permissions (and/or ACLs) on the $release_root/$groupname paths accordingly. This needs to be done only once per group and works because no one else is allowed to create new groups on my gitlab instance. This is very different from the default.

Anything else we can do for you? ;-)



来源:https://stackoverflow.com/questions/31794367/how-to-deploy-gitlab-project-branch-to-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!