diff options
Diffstat (limited to 'tools/gitolite.html')
-rw-r--r-- | tools/gitolite.html | 503 |
1 files changed, 356 insertions, 147 deletions
diff --git a/tools/gitolite.html b/tools/gitolite.html index 58d6d96..94abda0 100644 --- a/tools/gitolite.html +++ b/tools/gitolite.html @@ -23,7 +23,7 @@ <pre> # mkdir -p /srv/gitolite - # useradd -U -d /srv/gitolite gitolite + # useradd -r -s /bin/bash -m -d /srv/gitolite gitolite # chown gitolite:gitolite /srv/gitolite </pre> @@ -38,10 +38,20 @@ <p>Copy public key that will be used for authenticating gitolite administrator, read <a href="openssh.html#ssh">ssh</a> how to - create one.</p> + create one, key don't need to have password. + If the server is on remote a remote + machine you can use scp to copy the public key;</p> <pre> - $ sudo install -o gitolite -g gitolite /home/bob/.ssh/gitolite.pub /srv/gitolite/gitolite.pub + $ scp /home/bob/.ssh/gitolite.pub admin@core.privat-network.net:/home/admin/ + bob@core.privat-network.net's password: + gitolite.pub 100% 390 0.4KB/s 00:00 + </pre> + + <p>Then on remote machine;</p> + + <pre> + # cp /home/admin/gitolite.pub /srv/gitolite.pub </pre> <pre> @@ -62,7 +72,7 @@ </pre> <pre> - $ ssh -v -i ~/.ssh/gitulite_rsa gitolite@localhost -p 2222 + $ ssh -v -i ~/.ssh/gitolite gitolite@localhost -p 2222 </pre> <h2 id="admin">3. Gitolite Administration</h2> @@ -72,7 +82,7 @@ Start by cloning gitolite-adimin;</p> <pre> - $ git clone gitolite:gitolite-admin + $ git clone git-admin:gitolite-admin </pre> <h3>3.1. Recover Admin Account</h3> @@ -127,38 +137,55 @@ edit conf/gitolite.conf;</p> <pre> - @dev = alice david - @interns = clair - @dev = bob - @teamleads = mike + @guests = gitweb + @interns = bob alice + @dev = fred mary joe + @teamleads = mary @staff = @interns @dev @teamleads - @proj-repos = sysdoc storm atom + repo @secret + - = @guests + option deny-rules = 1 repo @floss - R = @all + RW+ = @dev @staff + R = @all + + repo @project + RW+ = @teamleads + - master = @dev + - refs/tags/v[0-9] = @dev + RW+ develop/ = @dev + RW+ feature/ = @dev + RW+ hot-fix/ = @dev + RW = @dev + R = @interns - repo @proto - RW+ = @staff + repo gitolite-admin + RW+ = gitolite - repo @proj-repos - RW+ = @teamleads - - master = @dev - - refs/tags/v[0-9] = @dev - RW+ develop/ = @dev - RW+ feature/ = @dev - RW+ hot-fix/ = @dev - RW = @dev - R = @managers + repo c9-doc c9-ports c9-pmwiki + config gitweb.owner = "c9 team" + config gitweb.category = "c9" - repo atom sysdoc - option hook.post-receive = deployweb + repo c9-doc + config gitweb.description = "c9 documentation" + option hook.post-receive = deploy-web-doc - repo testing - RW+ = @staff + repo c9-ports + config gitweb.description = "c9 ports" - repo gitolite-admin - RW+ = mike + repo c9-pmwiki + config gitweb.description = "c9 wiki" + option hook.post-receive = deploy-web-doc + + repo c9-assistant + config gitweb.owner = "c9 team" + config gitweb.category = "c9" + config gitweb.description = "c9 open assistant" + + @secret = gitolite-admin + @project = c9-doc c9-ports c9-pmwiki c9-assistant </pre> <p>Commit and push;</p> @@ -174,13 +201,13 @@ <pre> # cd /srv/gitolite/repositories/ - # mv void.git sysdoc.git + # mv void.git c9-doc.git </pre> <p>On workstation edit conf/gitolite.conf;</p> <pre> - repo sysdoc + repo c9-doc RW+ = bob </pre> @@ -191,12 +218,44 @@ $ git push </pre> + <h4>3.3.3 Delete Repository</h4> + + <pre> + # cd /srv/gitolite/repositories/ + # rm -rf c9-doc.git + </pre> + + <p>On workstation edit conf/gitolite.conf and remove c9-doc.</p> + <h2 id="hooks">4. Gitolite Hooks</h2> + <p>This document creates three scripts, one is run when gitolite receives + push to a project with hook active, second script is run under root + user to allow operations where gitolite user have no rights, third one + is project specific.</p> + + <p>This example try to have a separate creation of a package and its deployment, + in case deploy script is not on the same machine other method can be used to send + the package.</p> + + <p>A normal package will have a files.tar with all or new files to extract, + if necessary a deleted file with the list of files to be removed and a + project file with data about the package like new hash commit, or witch + script to call to deploy.</p> + + <p>Package is created under gitolite + <a href="conf/srv/gitolite/hook.sh">/srv/gitolite/deploy/hook.sh</a> + script and + <a href="conf/srv/gitolite/deploy.sh">/srv/gitolite/deploy/deploy.sh</a>, + deploy in this example is called called by cron.</p> + + <h3 id="gtl-activate">4.1. Activate Hooks</h3> + <p>Example from <a href="http://gitolite.com/gitolite/cookbook.html#v3.6-variation-repo-specific-hooks">Cookbook</a> how to apply hooks only to certain repos. Uncomment or add - this line on /srv/gitolite/.gitolite.rc, within the %RC block;</p> + this line on <a href="conf/srv/gitolite/.gitolite.rc">/srv/gitolite/.gitolite.rc</a>, + within the %RC block;</p> <pre> LOCAL_CODE => "$rc{GL_ADMIN_BASE}/local", @@ -206,194 +265,244 @@ or add it to the ENABLE list if it doesn't exist.</p> <pre> - GIT_CONFIG_KEYS => '.*', - </pre> - - <pre> # allow repo-specific hooks to be added 'repo-specific-hooks', </pre> - <p>Put your hooks into your gitolite-admin clone, as follows:</p> + <p>Create directory on gitolite-admin clone;</p> <pre> $ cd ~/gitolite-admin $ mkdir -p local/hooks/repo-specific </pre> - <p>Create the same directory on remote as gitolite;</p> + <p>Now add your hooks to that directory, but instead of using the + git "standard" names (pre-receive, post-receive, post-update), + you use descriptive names (e.g. "deploy", "RSS-post", etc).</p> + + <p>On remote run;</p> <pre> # su - gitolite - $ mkdir local/hooks/repo-specific + $ mkdir .gitolite/local/hooks/repo-specific + $ gitolite setup </pre> - <p>Now add your hooks to that directory, but instead of using the - git "standard" names (pre-receive, post-receive, post-update), - you use descriptive names (e.g. "deploy", "RSS-post", etc).</p> + <h3 id="gtl-deploy">4.2. Deploy and Hook script</h3> - <h3 id="gtl-deploy">4.1. Deploy Hook</h3> + <p>Create deploy directory on remote, /srv/gitolite/deploy + was chosen to have less impact on the package system;</p> - <p>This manual create two users; one gitolite that handle git - central server and system www for web servers. To avoid permission - problems this example use gitolite hooks and cron. By using cron - we have permission to use chown, this way files end up with right - www user ownership and permissions.</p> + <pre> + $ sudo -u gitolite mkdir /srv/gitolite/deploy + </pre> + + <p>Script + <a href="conf/srv/gitolite/hook.sh">/srv/gitolite/deploy/hook.sh</a> + receives call create_package "project-name" "git-dir" + "valid oldrev/invalid" "newrev" "script/to/call.sh" from gitolite hook + and creates a package.</p> - <p>This hook allows to select wich branch is deployed and if exists, - calls a script inside project folder with user www. This allows to - do post deploy (checkout) tasks such as composer update.</p> + <pre> + $ sudo -u gitolite cp conf/srv/gitolite/hook.sh /srv/gitolite/deploy/ + </pre> - <p>Create <a href="../conf/srv/gitoliteolite/deployweb">deployweb</a> - in gitolite-admin/local/hooks/repo-specific;</p> + <p>Script + <a href="conf/srv/gitolite/deploy.sh">/srv/gitolite/deploy/deploy.sh</a> + loops for each package, extracts, order commit hashes to create final + snapshot of files and call script to handle deploy.</p> <pre> - $ vim ~/gitolite-admin/local/hooks/repo-specific/deployweb + $ sudo -u gitolite cp conf/srv/gitolite/deploy.sh /srv/gitolite/deploy/ </pre> + <h3 id="gtl-setup">4.3. Setup project hook</h3> + + <p>Project hooks create a package by calling hook.sh script and + deploy a package being called by deploy.sh. Deploy script is a + simple example that handle multiple web projects.</p> + + <h4>4.3.1. Hook Script</h4> + + <p>Create + <a href="conf/srv/gitolite/deploy-web-doc">gitolite-admin/local/hooks/repo-specific/deploy-web-doc</a>;</p> + <pre> #!/bin/bash - ###################################################################### # # Put this file in your gitolite-admin; - # ~/gitolite-admin/local/hooks/repo-specific/deployweb + # ~/gitolite-admin/local/hooks/repo-specific/deploy-web-doc # - while read oldrev newrev refname - do - BRANCH=$(git rev-parse --symbolic --abbrev-ref $refname) - echo "Commit was for branch $BRANCH" + # set host to empty to create package for each push + # or set remote host to create package based on last deployed push + # host="https://doc.localhost" + host="" + # set name of witch branch should be deployed + branch_to_deploy="deploy_branch" - if [[ "$BRANCH" == "master" ]];then + ###################################################################### - # Get project name from current directory (without .git) - PROJECT=$(basename "$PWD") - PROJECT=${PROJECT%.git} - echo "Project $PROJECT added to deploy list." - echo $PWD > /srv/gitolite/deploy/$PROJECT - fi + url="$host/.last_deploy" + source /srv/gitolite/deploy/hook.sh + read oldrev newrev refname + push_branch=$(git rev-parse --symbolic --abbrev-ref $refname) - done - </pre> + #SCRIPT_VARS=$(set) + #echo "project: $PROJECT" + #echo "local dir: $PWD" > /srv/gitolite/deploy/${GL_REPO} + #echo "${SCRIPT_VARS}" >> /srv/gitolite/deploy/${GL_REPO} - <p>Create deploy directory on remote;</p> + if [[ $push_branch = $branch_to_deploy ]]; then - <pre> - # su - gitolite - $ mkdir deploy + # if host empty we make local tracking + if [[ $host = "" ]]; then + if [[ $(is_initial ${GL_REPO}) = "true" ]]; then + oldrev="initial" + fi + else + if [[ ! $(valid_url $url) = "true" ]]; then + echo "Deploy: set $url on remote to start creating packages" + exit 1 + fi + oldrev=$(get_remote_rev $url) + fi + create_package ${GL_REPO} ${PWD} ${oldrev} ${newrev} "deploy-web.sh" + fi </pre> - <p>Add scripts to the repos you want them to be active in - your conf file. For example:</p> + <p>Activate this hook, the idea is to start with this one as a template working + and then implement the final one. Edit gitolite admin configuration file and + activate:</p> <pre> - repo atom @baz - option hook.post-receive = deployweb + repo c9-doc + config gitweb.description = "c9 documentation" + option hook.post-receive = deploy-web-doc </pre> <p>Add, commit, and push the admin repo;</p> <pre> - $ git add -u && git commit -m "deploy hook" + $ git add local/hooks/repo-specific/hook-deployweb + $ git add -u && git commit -m "added deploy c9 hook" </pre> - <p>On remote run;</p> + <p>Now we can test if our script is functioning by creating a branch on c9-doc + making a random change and push;<p> <pre> - # su - gitolite - $ gitolite setup + $ cd c9-doc + $ git checkout -b deploy_branch </pre> - <p>Create deploy script that cron will call - every minute, this script will check inside - /srv/gitolite/deploy folder for projects that have - been updated.</p> + <h4>4.3.2. Deploy Script</h4> - <p>Create <a href="../conf/srv/gitolite/deploy.sh">deploy.sh</a> in - /usr/share/gitolite;</p> + <p>Create + <a href="conf/srv/gitolite/deploy-web.sh">/srv/gitolite/deploy/scripts/deploy-web.sh</a>;</p> <pre> - $ vim /usr/share/gitolite/deploy.sh - </pre> + #!/bin/bash - <pre> - #!/bin/sh + pkg_path=$1 - ###################################################################### - # - # Put this file in; - # /usr/share/gitolite/deploy.sh - # - DIR_WWW=/srv/www/ - DEPLOY_BRANCH=master - TARGET_USER=www + www_root="/srv/www" + www_user="nginx" + www_group="www" - for DP_FILE in /srv/gitolite/deploy/* - do + pkg_file="${pkg_path}/project" + pkg_rm="${pkg_path}/deleted" + pkg_files="${pkg_path}/files" - if [ ! -f "$DP_FILE" ]; then - # Nothing to do ;) - #echo "Deploy: invalid DP_FILE" - exit 1; + if [ ! -f ${pkg_file} ]; then + echo "Deploy web: invalid pkg_file ${pkg_file}" + exit 1 fi - # Get project name - PROJECT=$(basename "$DP_FILE") - echo "Deploy: PROJECT=${PROJECT}" + pkg_name=$(head -1 ${pkg_file}) + pkg_new=$(head -3 ${pkg_file} | tail -1) + pkg_new7=$(echo ${pkg_new} | cut -c1-7) + + pkg_www="${www_root}/${pkg_name}" + pkg_back="${pkg_www}/backup_deploy" + pkg_last="${pkg_www}/.last_deploy" - # Get git repository path and verify if exists - DIR_GIT=$(head -n 1 $DP_FILE) - if [ ! -d "$DIR_GIT" ]; then - echo "Deploy: invalid DIR_GIT: ${DIR_GIT}" - exit 2; + if [ ! -d ${pkg_www} ]; then + echo "Deploy web: invalid pkg_www ${pkg_www}" + exit 1 fi - echo "Deploy: DIR_GIT=${DIR_GIT}" - - # Get directory to deploy and verify if exists - GIT_WORK_TREE=${DIR_WWW}${PROJECT}/ - if [ ! -d "$GIT_WORK_TREE" ]; then - echo "Deploy: invalid GIT_WORK_TREE: ${GIT_WORK_TREE}" - echo "Deploy: creating directory: $GIT_WORK_TREE}" - mkdir -p $GIT_WORK_TREE + + # first backup all data + if [[ ! $(ls ${pkg_www} | grep -v "backup_deploy") = "" ]]; then + if [ ! -d ${pkg_back} ]; then + sudo -u ${www_user} mkdir -p ${pkg_back} + fi + backup_file="${pkg_back}/${pkg_name}-$(date '+%Y-%j-%H-%M-%S').tar.gz" + echo "Deploy web: making backup ${backup_file}" + sudo -u ${www_user} tar --exclude ${pkg_back} --xattrs -zcpf ${backup_file} ${pkg_www} fi - echo "Deploy: GIT_WORK_TREE={$GIT_WORK_TREE}" - # Deploy (checkout) - echo "Deploy: starting git checkout" + # remove files and directories that have been deleted + if [ -f ${pkg_rm} ]; then - git --git-dir=$DIR_GIT \ - --work-tree=$GIT_WORK_TREE \ - checkout -f $DEPLOY_BRANCH + echo "Deploy web: files to delete:" + # first we delete files + while read deleted_file; do + deleted_file="${pkg_www}/${deleted_file}" + if [ -f ${deleted_file} ]; then + echo "file rm ${deleted_file}" + rm ${deleted_file} + fi + done <${pkg_rm} + + # delete directories + while read deleted_file; do + deleted_file="${pkg_www}/${deleted_file}" + if [ -d ${deleted_file} ]; then + echo "file rm ${deleted_file}" + rm ${deleted_file} + fi + done <${pkg_rm} + fi - # Fix ownership and permissions - echo "Deploy: fixing permissions" + # copy new files to destination + if [ -d ${pkg_files} ]; then + echo "Deploy web: cp from ${pkg_files} to ${pkg_www}" + sudo -u ${www_user} cp -r ${pkg_files}/* ${pkg_www} + fi - echo "Deploy: setting owner: chown -R ${TARGET_USER}" - chown -R ${TARGET_USER}:${TARGET_USER} $GIT_WORK_TREE + echo ${pkg_new} > ${pkg_last} + echo "Deploy: scripts/deployweb.sh ${pkg_name} ${pkg_new7} deployed." - echo "Deploy: setting directory permissions: chmod 755" - find $GIT_WORK_TREE -type d -print0 | xargs -0 chmod 755 + #remove temporary package + rm -r ${pkg_path} + </pre> - echo "Deploy: setting file permissions: chmod 644" - find $GIT_WORK_TREE -type f -print0 | xargs -0 chmod 644 + <h4>4.3.3. Debuging hooks</h4> - # Call project script - if [ -f "${GIT_WORK_TREE}/deploy.sh" ]; then - echo "Deploy: calling ${GIT_WORK_TREE}deploy.sh" - cd ${GIT_WORK_TREE} - sudo -u ${TARGET_USER} sh ${GIT_WORK_TREE}deploy.sh - fi + <p>Comment gitolite admin repo script "if" and uncomment debug sections, this allow to + source the file with environment of hook.</p> - # Done with project - echo "Deploy: removing deploy file="$DP_FILE - rm $DP_FILE + <p>Later you can delete this branch locally and remote and start fresh. To test + if hook is called each time you push run;</p> - exit 0; - done + + <pre> + $ echo $(( ( RANDOM % 10 ) +1 )) >> index.html && git add -u && git commit -m "test deploy" && git push git </pre> + <p>See if a file was created in /srv/gitolite/deploy with name of project and + with environmental variables of gitolite script.</p> + + <p>From now on you can test changes directly on + /srv/gitolite/.gitolite/local/hooks/repo-specific/hook-deployweb + and repeat above command to see the results or create a separate script with + all variables generated by above script set so you don't have to push at all.</p> + + <h4 id="gtl-deploy">4.4. Deploy with Cron</h4> + <p>Add cron job to call deploy script every minute;</p> <pre> @@ -406,9 +515,9 @@ # # this way it will log - # * * * * * /usr/share/gitolite/deploy.sh + # * * * * * /usr/share/gitolite/deployweb # without log - * * * * * /usr/share/gitolite/deploy.sh > /dev/null 2>&1 + * * * * * /usr/share/gitolite/deployweb > /dev/null 2>&1 @hourly ID=sys.hourly /usr/sbin/runjobs /etc/cron/hourly @daily ID=sys.daily /usr/sbin/runjobs /etc/cron/daily @@ -418,6 +527,106 @@ # End of file </pre> + <h2 id="gitweb">5. Gitweb</h2> + + <pre> + $ prt-get depinst p5-cgi p5-cgi-session libcgi \ + fcgiwrap spawn-fcgi highlight + </pre> + + <h3>5.1. Configure gitweb</h3> + + <p>Edit /etc/gitweb.conf</p> + + <pre> + our $git_temp = "/srv/www/gitweb_tmp"; + + our $projects_list = "/srv/gitolite/projects.list"; + # The directories where your projects are. Must not end with a slash. + our $projectroot = "/srv/gitolite/repositories"; + + # Base URLs for links displayed in the web interface. + our @git_base_url_list = qw(git://core.privat-network.com http://git@core.private-network.com); + + our $projects_list_group_categories = 1; + </pre> + + <h3>5.2. Configure nginx</h3> + + <p>Edit /etc/rc.d/fcgiwrap to run as nginx user member of gitolite + and www group;</p> + + <pre> + USER=nginx + GROUP=nginx + </pre> + + <pre> + # usermod -G www,gitolite nginx + </pre> + + <p>Create link from gitweb to web server folder;</p> + + <pre> + # ln -s /usr/share/gitweb /srv/www + </pre> + + <p>Add this to default or main + <a href="nginx.html#virtual-host">nginx virtual host</a>;</p> + + <pre> + location /gitweb/gitweb.cgi { + alias /srv/www/gitweb; + include fastcgi_params; + gzip off; + fastcgi_param SCRIPT_FILENAME /srv/www/gitweb/gitweb.cgi; + fastcgi_param GITWEB_CONFIG /etc/gitweb.conf; + fastcgi_pass unix:/var/run/fcgiwrap.sock; + } + + location /gitweb { + alias /srv/www/gitweb; + index gitweb.cgi; + } + </pre> + + <h3>5.3. Configure gitolite</h3> + + <p>Edit + <a href="conf/srv/gitolite/.gitolite.rc">/srv/gitolite/.gitolite.rc</a>, + change UMASK and GIT_CONFIG_KEYS to;</p> + + <pre> + # default umask gives you perms of '0700'; see the rc file docs for + # how/why you might change this + UMASK => 027, + + # look for "git-config" in the documentation + GIT_CONFIG_KEYS => '.*', + </pre> + + <p>Fix permissions;</p> + + <pre> + $ sudo chown -R gitolite:gitolite /srv/gitolite + $ sudo chmod g+rx /srv/gitolite/projects.list + $ sudo chmod -R 755 /srv/gitolite/repositories/ + </pre> + + <p>Edit gitolite-admin/conf/gitolite.conf;</p> + + <pre> + repo c9-doc + config gitweb.owner = c9 team + config gitweb.description = c9 documentation + config gitweb.category = c9 + + repo c9-ports + config gitweb.owner = c9 team + config gitweb.description = c9 ports + config gitweb.category = c9 + </pre> + <a href="index.html">Tools Index</a> <p>This is part of the c9-doc Manual. Copyright (C) 2016 |