2008年2月15日金曜日

commit時に自動的にrpm packageを生成する。

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
post-commitにフックするのだが、実行権限問題とrpm-buildをインスト&実行できるサーバに制限があることから、xmlrpcでリクエストを受け付けるサーバを書くことにした。で、ちょっと汎用的に書いたら任意のスクリプトを実行できるようになってしまった。makeでもキック可能。当然だけどセキュリティ上の問題を引き起こすので、これで立てたサーバを外部に公開しないように。urlのお尻に";rm"をつけてみるとか・・・。

スクリプトを実行する部分。

import string
import os
import popen2
import shutil
import tempfile


class FlyingCircus:
commands = ['$monty -V']

def __init__(self):
self.monty = 'python'

def expand_keyword(self, str, kw):
kw.update(self.__dict__)
t = string.Template(str)
return t.substitute(kw)

def apply(self, f, kw):
return [f(self.expand_keyword(cmd, kw)) for cmd in self.commands]

def get_result(self, s):
return s

def run(self, **kw):
def identity(cmd):
return cmd
def execute(cmd):
child = popen2.Popen3(cmd, capturestderr=True)
r = child.wait()
if os.WTERMSIG(r) or not os.WIFEXITED(r) or os.WEXITSTATUS(r):
raise child.childerr.read()
else:
return child.fromchild.read()
if "dry_run" in kw and kw['dry_run']:
f = identity
else:
f = execute
return self.get_result(''.join(self.apply(f, kw)))

class ScriptRunner(FlyingCircus):
def __init__(self):
self._cwd= os.getcwd()
self.working_dir = tempfile.mkdtemp()
os.chdir(self.working_dir)

def __del__(self):
os.chdir(self._cwd)
shutil.rmtree(self.working_dir)


rpmを作るサーバ。

import os
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from daemon import Daemon
from ScriptRunner import ScriptRunner

class RPMPackager(ScriptRunner):
commands = ['svn checkout $src $working_dir',
'python $working_dir/setup.py bdist_rpm',]
def get_result(self, x):
fname = ''
dir = 'dist'
d = os.path.join(self.working_dir, dir)
for f in os.listdir(d):
if f.endswith('noarch.rpm'):
fname = os.path.join(self.working_dir, dir, f)
f = file(fname, 'r+b')
try:
return f.read(-1) #ugh!
finally:
f.close()

def on_commit(url):
p = RPMPackager()
return xmlrpclib.Binary(p.run(src=url))

class PackageDaemon(Daemon):
default_conf = '/home/nori/Desktop/work/autopackaging/my.conf'
section = 'Package'
def run(self):
server = SimpleXMLRPCServer(('localhost', 9000))
server.register_function(on_commit)
server.serve_forever()

3 件のコメント:

nori さんのコメント...

post-commitのhooにわたってくるargが二つあるのだが、1つはrepoのpathで、もうひとつはrevだ。

てかさ~~svnlookで指定するrepoはfile://でないとだめで、http://は認められない。ぐは。

このままだとhookの側でpathを確定してurlを作ってserverに渡さないとお手上げになってしまう。

妥協してハードコードもありだがw。

nori さんのコメント...

きれいに解決しようとしたらbuildbotと同じように中継サーバをおくしかないね。repositoryをおいてあるマシン上に中継サーバをおいて、だれにbuildさせるかをマップするテーブルを作る。

テストがめんどくさいなぁ。

依存するsetup.pyを割り出さないとなぁ。

は~~どこ~~どしよう。はっはっは。じゃなかたらbuildbotを採用。

nori さんのコメント...

buildbotの日本語ドキュメント

buildbot自体はpythonの本体でも使われているっぽいし、buildbot自身も使っているようだ。

Tracを見る限り日に数件ticketがissueされているようだ。