鸿 记5d13.cn

a programer log.

Home work linux

python写git钩子脚本实现多个版本的自动发布 - git备忘录

python写git钩子脚本实现多个版本的自动发布 - git备忘录

By 鸿记

本文记录了孙铭鸿在实际的游戏开发中,通过git 分支或标签自动发不多个版本的实现过程及相关脚本。

干货备忘录

本文的适应环境及声明
  • 发布文件夹所在的服务器上有git版本库
  • 否则,只有钩子脚本可供参考
  • 我不是git专家,我对git的使用观念是够用就好,本文是满足我需求的实践总结,大家随意交流,如有转载是我的荣幸!。

本文模拟一个场景:我们需要在服务器 SERVER 上将 /home/git/repositories/sg/xxx.git 提交自动发布/更新到/home/game/下同名的文件夹下,例如的 branchA 分支自动发布/更新到 /home/game/branchAbranchB 分支自动发布/更新到 /home/game/branchB

*/home/game下没有相应的分支文件夹的就不自动发布。

*git 服务器的帐号git

1、建立发布文件夹

这一步超重要,这是经过几天折腾“升华”出的最佳流程,如果读者想尽快投入使用,照着做是做就可以了。

$su -l root #输入root密码切换到root
$su -l git #再切换到git帐号,详见备注1
$umask 002 #可参见备注2
$cd /home/game
$git clone /home/git/repositories/sg/xxx.git -b branchA branchA
$git clone /home/git/repositories/sg/xxx.git -b branchB branchB

*备注: 1. 适用于给git服务器程序专门的帐号的情况(推荐这样部署git服务器),此时git帐号是没有密码不能直接切换的,所以可以先进root再切换到git。 2. umask 002 是设置git帐号下操作建立的文件的默认权限为775,这样别的帐号就对发布文件夹有足够的权限

2、git钩子脚本

$cd /home/git/repositories/sg/sgserver.git/hooks
$vim post-receive #写入如下代码,保存
$chmod +x post-receive

#!/usr/bin/python
#coding:utf-8
#hoos/post-receive

import sys,traceback import os,time import subprocess from datetime import datetime

def git(args): '''取得执行git命令的输出字符''' args = ['git'] + args git = subprocess.Popen(args, stdout = subprocess.PIPE) details = git.stdout.read() details = details.strip() return details

def get_repo_name(): '''读取当前提交的版本库的名称''' if git(['rev-parse','--is-bare-repository']) == 'true': name = os.path.basename(os.getcwd()) if name.endswith('.git'): name = name[:-4] return name else: return os.path.basename(os.path.dirname(os.getcwd()))

REPO_NAME = get_repo_name()

if name == 'main': #读取git调用钩子时的参数 for line in sys.stdin.xreadlines(): old, new, ref = line.strip().split(' ')

<span class="c">#取得分支名</span>
<span class="n">branchname</span> <span class="o">=</span> <span class="n">ref</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'refs/heads/'</span><span class="p">,</span><span class="s">''</span><span class="p">)</span>

<span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">allen's hooks receive </span><span class="si">%</span><span class="s">s,</span><span class="si">%</span><span class="s">s</span><span class="se">\n</span><span class="s">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">REPO_NAME</span><span class="p">,</span><span class="n">branchname</span><span class="p">))</span>

<span class="c"># 该分支的发布目录不存在就退出</span>
<span class="n">pullpath</span> <span class="o">=</span> <span class="s">"/opt/</span><span class="si">%</span><span class="s">s"</span> <span class="o">%</span> <span class="p">(</span><span class="n">branchname</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">pullpath</span><span class="p">):</span>
    <span class="c">#os.system('mkdir '+ pullpath) </span>
    <span class="nb">exit</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>   

<span class="n">nowtime</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">'</span><span class="si">%</span><span class="s">Y-</span><span class="si">%</span><span class="s">m-</span><span class="si">%</span><span class="s">d </span><span class="si">%</span><span class="s">H:</span><span class="si">%</span><span class="s">M:</span><span class="si">%</span><span class="s">s'</span><span class="p">)</span>
<span class="n">f</span><span class="o">=</span><span class="nb">file</span><span class="p">(</span><span class="s">r'/var/log/tmp/git-post-receive-</span><span class="si">%</span><span class="s">s.log'</span> <span class="o">%</span> <span class="n">REPO_NAME</span><span class="p">,</span><span class="s">'aw'</span><span class="p">)</span>
<span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'</span><span class="si">%</span><span class="s">s----</span><span class="si">%</span><span class="s">s-----</span><span class="se">\n</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">ref</span><span class="p">,</span><span class="n">nowtime</span><span class="p">))</span>
<span class="k">try</span><span class="p">:</span>
    <span class="n">cmd</span> <span class="o">=</span> <span class="s">'cd '</span><span class="o">+</span> <span class="n">pullpath</span> <span class="o">+</span><span class="s">'; env -i git log -1 --pretty=format:"</span><span class="si">%</span><span class="s">s"'</span>
    <span class="n">logcomment</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'logcomment:</span><span class="si">%</span><span class="s">s</span><span class="se">\n</span><span class="s">'</span> <span class="o">%</span> <span class="n">logcomment</span><span class="p">)</span>
    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'</span><span class="si">%</span><span class="s">s  </span><span class="si">%</span><span class="s">s</span><span class="se">\n</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">old</span> <span class="p">,</span> <span class="n">new</span> <span class="p">))</span>
    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'receive </span><span class="si">%</span><span class="s">s,</span><span class="si">%</span><span class="s">s</span><span class="se">\n</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">REPO_NAME</span><span class="p">,</span><span class="n">branchname</span><span class="p">))</span>

    <span class="c">#用umask 设置git pull执行新建的文件的权限 </span>
    <span class="n">cmd</span> <span class="o">=</span> <span class="s">'umask 002; cd </span><span class="si">%</span><span class="s">s/;env -i git pull'</span> <span class="o">%</span> <span class="p">(</span><span class="n">pullpath</span><span class="p">)</span>
    <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">'cmd:</span><span class="si">%</span><span class="s">s</span><span class="se">\n</span><span class="s">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">cmd</span><span class="p">))</span>
    <span class="n">os</span><span class="o">.</span><span class="n">system</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
    <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

    <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="s">',pull complete!</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
    <span class="n">msg</span> <span class="o">=</span> <span class="n">traceback</span><span class="o">.</span><span class="n">sys_exc</span><span class="p">()</span>
    <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">msg</span><span class="p">)</span>
    <span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
惨痛教训
  1. 在实现的过程中,可能是作者的环境权限很宽松的原因,在权限上走了些弯路,特别是git钩子pull的文件都是数组为git:git,导致其他用户没有权限读取、执行发布文件
  2. 建立发布文件夹的方式也是遇到了多次挫折,网上的多篇文档都没有强调这个,看了很多个文档,经过n次尝试,最后用了本地路径协议避免了权限问题(git clone /home/git/repositories/sg/xxx.git -b branchA branchA)。
  3. 在脚本里执行pull的那句command 也是我的”心血“:os.system('cd '+ pullpath +'; env -i git log -1 --pretty=format:"%s"'),刚开始没有加上env -i时,总是提示当前路径没有.git版本库。而我的python项目里经常不env -i也正常。我现在还不清楚原因,希望朋友们可以在回复里告诉我。

后记

  1. IT行业分工越来越细了,我从事开发十余年了(人生能有几个十年?),但现在越来越觉得自己所知甚少,很多时候都在是找个XXX岗位的专才还是自己学习学将就将就。之前一直用svn,最近换成git管理开发。享受git便利的同时,也必须接受新的挑战和折磨,~_~!
  2. 这两天对的git自动发布总算有了些经历,也终于写了这篇短文,希望可以帮助到同行。
  3. 从适应vim开始,开始我就一直在努力地在开发工作中少用鼠标,现在用上git,我离鼠标又远了一点点,~_~

孙铭鸿logo
by 鸿记

声明:本站文章除注明转载外,均为本站原创或者翻译。
本文采用 署名-非商业性使用-相同方式共享(BY-NC-SA) 协议进行授权。
转载请注明转自: 【鸿记】python写git钩子脚本实现多个版本的自动发布 - git备忘录

Fork me on GitHub