Pythonの「きれいな」継続的統合


116

これは少し無駄な質問ですが、BuildBotの出力は特に見た目が良くありません。

たとえば、と比較して

..その他、BuildBotはかなり古く見えます。

私は現在ハドソンで遊んでいますが、非常にJava中心です(このガイドを使用すると、BuildBotよりもセットアップが簡単で、より多くの情報が生成されます)。

基本的に:Pythonを対象とした継続的な統合システムはありますか?


更新:今回から、JenkinsプロジェクトがパッケージのコミュニティバージョンとしてHudsonに置き換わりました。元の作者もこのプロジェクトに移動しました。Jenkinsは、Ubuntu / Debian、RedHat / Fedora / CentOSなどの標準パッケージになりました。次の更新はまだ本質的に正しいです。Jenkinsでこれを行うための開始点は異なります。

更新:いくつかの代替案を試した後、私はハドソンに固執すると思います。整合性は素晴らしくシンプルでしたが、かなり制限されていました。Buildbotは、私が使用していたような1台のマシンですべてを実行するよりも、多数のビルドスレーブを使用する方が適していると思います。

Pythonプロジェクト用にHudsonを設定するのは非常に簡単でした。

  • Hudsonをhttp://hudson-ci.org/からダウンロードします。
  • で実行する java -jar hudson.war
  • のデフォルトアドレスでWebインターフェイスを開きます http://localhost:8080
  • ハドソン、プラグインの管理に移動し、「更新」などをクリックします
  • Gitプラグインをインストールします(gitHudsonのグローバル設定でパスを設定する必要がありました)。
  • 新しいプロジェクトを作成し、リポジトリ、SCMポーリング間隔などを入力します
  • まだインストールされnosetestsていeasy_installない場合は、
  • ビルドステップで、 nosetests --with-xunit --verbose
  • 「JUnitテスト結果レポートの公開」をチェックし、「テストレポートXML」を **/nosetests.xml

それだけで十分です。メール通知を設定でき、プラグインは一見の価値があります。私が現在Pythonプロジェクトで使用しているいくつか:

  • コード行をカウントするSLOCCountプラグイン(そしてそれをグラフ化します!)- sloccountを個別にインストールする必要があります
  • PyLint出力を解析するための違反(警告しきい値を設定し、各ビルドでの違反の数をグラフ化できます)
  • Coberturaは、coverage.py出力を解析できます。Nosetestは、テストの実行中にカバレッジを収集できますnosetests --with-coverage(これにより出力がに書き込まれます**/coverage.xml)。

すばらしい質問です。今、同様のことを調べています。1つのルートに行く場合、他の人と経験を共有できますか?
アンドレ

3
これを書いたときにそれが利用可能であったかどうかはわかりません。HudsonのChuck Norrisプラグインを使用して、コンテンツの制御をさらに強化してください!
ヨハネスシャラ09

8
2011/2012の更新:Hudsonを検討している人は、Hudsonプロジェクトのオープンソースの継続であるJenkinsを使用する必要があります(Hudsonは現在、Oracleによって制御されています
mindthief 2012

回答:


41

NoseXunit出力プラグインをチェックしてみてください。このコマンドでユニットテストとカバレッジチェックを実行することができます。

nosetests --with-xunit --enable-cover

これは、Jenkinsルートを使用する場合、またはJUnitテストレポートをサポートする別のCIサーバーを使用する場合に役立ちます。

同様に、ジェンキンスの違反プラグインを使用して、pylintの出力をキャプチャできます


4
Noseにxunitプラグインがデフォルトで含まれるようになりましたnosetests --with-xunit
dbr

3
では、どのようにしてPylintから監査を実行するのでしょうか。私はときnosetests --with-xunit --enable-audit私が得るnosetests: error: no such option: --enable-audit
アダム・パーキン

2
近代的な答えは、NoseXUnitのものは現在、組み込みと不幸--downcasedときから名前が変更され--with-nosexunit--with-xunit
2013

10

うまくいくかわからない:BittenはTracを書いている人によって作られ、Tracと統合されています。Apache Gumpは、Apacheで使用されるCIツールです。Pythonで書かれています。


9

TeamCityをCIサーバーとして使用し、ノーズをテストランナーとして使用して、大きな成功を収めてきました。 nosetestsのTeamcityプラグインは、合格/不合格のカウントを提供し、失敗したテストの読み取り可能な表示を提供します(メールで送信できます)。スタックの実行中に、テストの失敗の詳細を確認することもできます。

もちろん、複数のマシンでの実行などをサポートしていて、ビルドボットよりもセットアップと保守がはるかに簡単です。



6

Atlassian's Bambooもチェックする価値があります。Atlassianスイート全体(JIRA、Confluence、FishEyeなど)はかなり甘いです。


6

このスレッドはかなり古いと思いますが、ハドソンでの私の見解は次のとおりです。

私はpipを使用してリポジトリを設定することを決めました(動作するのは面倒ですが、見栄えの良いeggbasketです)。hudsonはテストを成功させて自動アップロードします。これは、次のようなhudson config executeスクリプトで使用するためのラフで準備ができたスクリプトです:/var/lib/hudson/venv/main/bin/hudson_script.py -w $ WORKSPACE -p my.package -v $ BUILD_NUMBER ** / coverage.xml、pylint.txt、および構成ビットのnosetests.xml:

#!/var/lib/hudson/venv/main/bin/python
import os
import re
import subprocess
import logging
import optparse

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(levelname)s %(message)s')

#venvDir = "/var/lib/hudson/venv/main/bin/"

UPLOAD_REPO = "http://ldndev01:3442"

def call_command(command, cwd, ignore_error_code=False):
    try:
        logging.info("Running: %s" % command)
        status = subprocess.call(command, cwd=cwd, shell=True)
        if not ignore_error_code and status != 0:
            raise Exception("Last command failed")

        return status

    except:
        logging.exception("Could not run command %s" % command)
        raise

def main():
    usage = "usage: %prog [options]"
    parser = optparse.OptionParser(usage)
    parser.add_option("-w", "--workspace", dest="workspace",
                      help="workspace folder for the job")
    parser.add_option("-p", "--package", dest="package",
                      help="the package name i.e., back_office.reconciler")
    parser.add_option("-v", "--build_number", dest="build_number",
                      help="the build number, which will get put at the end of the package version")
    options, args = parser.parse_args()

    if not options.workspace or not options.package:
        raise Exception("Need both args, do --help for info")

    venvDir = options.package + "_venv/"

    #find out if venv is there
    if not os.path.exists(venvDir):
        #make it
        call_command("virtualenv %s --no-site-packages" % venvDir,
                     options.workspace)

    #install the venv/make sure its there plus install the local package
    call_command("%sbin/pip install -e ./ --extra-index %s" % (venvDir, UPLOAD_REPO),
                 options.workspace)

    #make sure pylint, nose and coverage are installed
    call_command("%sbin/pip install nose pylint coverage epydoc" % venvDir,
                 options.workspace)

    #make sure we have an __init__.py
    #this shouldn't be needed if the packages are set up correctly
    #modules = options.package.split(".")
    #if len(modules) > 1: 
    #    call_command("touch '%s/__init__.py'" % modules[0], 
    #                 options.workspace)
    #do the nosetests
    test_status = call_command("%sbin/nosetests %s --with-xunit --with-coverage --cover-package %s --cover-erase" % (venvDir,
                                                                                     options.package.replace(".", "/"),
                                                                                     options.package),
                 options.workspace, True)
    #produce coverage report -i for ignore weird missing file errors
    call_command("%sbin/coverage xml -i" % venvDir,
                 options.workspace)
    #move it so that the code coverage plugin can find it
    call_command("mv coverage.xml %s" % (options.package.replace(".", "/")),
                 options.workspace)
    #run pylint
    call_command("%sbin/pylint --rcfile ~/pylint.rc -f parseable %s > pylint.txt" % (venvDir, 
                                                                                     options.package),
                 options.workspace, True)

    #remove old dists so we only have the newest at the end
    call_command("rm -rfv %s" % (options.workspace + "/dist"),
                 options.workspace)

    #if the build passes upload the result to the egg_basket
    if test_status == 0:
        logging.info("Success - uploading egg")
        upload_bit = "upload -r %s/upload" % UPLOAD_REPO
    else:
        logging.info("Failure - not uploading egg")
        upload_bit = ""

    #create egg
    call_command("%sbin/python setup.py egg_info --tag-build=.0.%s --tag-svn-revision --tag-date sdist %s" % (venvDir,
                                                                                                              options.build_number,
                                                                                                              upload_bit),
                 options.workspace)

    call_command("%sbin/epydoc --html --graph all %s" % (venvDir, options.package),
                 options.workspace)

    logging.info("Complete")

if __name__ == "__main__":
    main()

ものをデプロイすることになると、次のようなことができます:

pip -E /location/of/my/venv/ install my_package==X.Y.Z --extra-index http://my_repo

そして人々はそれを使ってものを開発することができます:

pip -E /location/of/my/venv/ install -e ./ --extra-index http://my_repo

この要素は、setup.pyと依存関係がすべて設定されたパッケージごとのリポジトリ構造を持っていることを前提としているので、トランクをチェックアウトしてこの要素を実行できます。

これが誰かを助けることを願っています。

- - - 更新 - - - - -

私はハドソンと本当によく合うepydocを追加しました。htmlフォルダーを使用して、構成にjavadocを追加するだけです

最近、pipは-Eフラグを適切にサポートしていないため、個別にvenvを作成する必要があります。


この回答は非常に便利で、Python CIの内部に関して多くの詳細があります。これは、Jenkinsなどから無料で入手できないものです。ありがとう!
maksimov





1

Continuumbinstarは、githubからビルドをトリガーできるようになり、linux、osx、windows(32/64)用にコンパイルできるようになりました。きちんとしたことは、配布と継続的な統合を密接に結合できることです。それは、tを超えて、Iの統合に点在しています。サイト、ワークフロー、ツールは非常に洗練されており、AFAIK condaは、C / C ++ / Fotranライブラリをラップして配布する必要がある複雑なPythonモジュールを配布するための最も堅牢でPython的な方法です。


0

かなり噛んで使用しております。それはきれいで、Tracとうまく統合されますが、非標準のワークフローがある場合にカスタマイズするのはお尻の面倒です。また、より一般的なツール用のプラグインほど多くありません。現在、ハドソンを代替品として評価しています。


0

rultor.comを確認してください。この記事では説明して、それはすべてのビルドのためにドッカーを使用しています。そのおかげで、Pythonを含め、Dockerイメージ内で好きなように構成できます。


0

少しの免責事項、私は実際に、git pushでコードを自動的にテストおよびデプロイし、git notesを介して課題チケットを管理する方法を必要とするクライアント向けに、このようなソリューションを構築する必要がありました。これは、AIMSプロジェクトでの私の仕事にもつながります。

一つは、可能性だけで簡単にセットアップビルドユーザーを持っているとを介して自分のビルドを管理する裸のノードシステムmake(1)expect(1)crontab(1)/ systemd.unit(5)、とincrontab(1)。さらに進んで、gridfs / nfsファイルストアを使用した分散ビルドにansibleとceleryを使用することもできます。

けれども、Graybeard UNIXの人またはPrincipleレベルのエンジニア/アーキテクト以外の誰かが実際にここまで行くとは思わないでしょう。ビルドサーバーは、スクリプト化されたタスクを自動化された方法で任意に実行する方法に過ぎないため、素晴らしいアイデアと潜在的な学習体験を生み出します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.