継続的な統合により、成長する多様なコードベースを維持する


10

継続的インテグレーションセットアップの哲学と設計について、いくつかの助けが必要です。

現在のCIセットアップではbuildbotを使用しています。それを設計し始めたとき、私は(厳密には、一年前にその設計に関わっていたため)、ビルド全体を一度に一晩実行するように調整されたオーダーメイドのCIビルダーを継承しました。しばらくして、これは不十分であると判断し、さまざまなCIフレームワークの調査を開始し、最終的にビルドボットを選択しました。buildbotへの移行における私の目標の1つ(ウィズバンのエキストラをすべて楽しむ以外に)は、オーダーメイドのナイトリービルダーの不備のいくつかを克服することでした。

私をちょっとユーモアして、私が受け継いだものを説明させてください。私の会社のコードベースは約150のユニークなc ++ Windowsアプリケーションで、それぞれが1ダース以上の内部ライブラリ(および多くのサードパーティライブラリ)に依存しています。これらのライブラリーの一部は相互依存しており、依存関係のあるアプリケーションがあり(それらは相互に何の関係もありませんが)、そのライブラリーの同じビルドでビルドする必要があります。これらのアプリケーションとライブラリの半分は「レガシー」で移植不可能と見なされており、IBMコンパイラーのいくつかの異なる構成で構築する必要があります(私はの固有のサブクラスを作成しましたCompile)。残りの半分はVisual Studioで構築します。ShellCommands、VSSのサポートがないため)。

オリジナルの夜間ビルダーは、すべてのソースを単純に削除し、特定の順序でビルドしました。単一のアプリケーションだけをビルドしたり、リビジョンを選択したり、グループ化したりする方法はありませんでした。仮想マシンを起動して、多数のアプリケーションを構築します。あまり堅牢ではなく、配布できませんでした。それはひどく拡張可能ではありませんでした。私はビルドボットのこれらの制限をすべて克服できるようにしたかったのです。

私がこれを最初に行った方法は、構築したい各アプリケーション(すべて150アプリケーション)のエントリを作成し、さまざまなアプリケーションをグループとして構築できるトリガースケジューラを作成し、全体的なナイトリービルドスケジューラの下にそれらのグループを含めることでした。これらは専用スレーブで実行でき(仮想マシンシカネリーは不要)、必要に応じて新しいスレーブを追加することもできます。これで、予定外のフルビルドを実行したい場合は、ワンクリックで実行できますが、必要に応じてアプリケーションを1つだけビルドすることもできます。

ただし、このアプローチには4つの弱点があります。1つは、ソースツリーの複雑な依存関係のWebです。設定のメンテナンスを簡略化するために、すべてのビルダーは大きな辞書から生成されます。依存関係は、それほど堅牢ではない方法で取得およびビルドされます(つまり、ビルドターゲットディクショナリ内の特定のものをキーオフします)。2つ目は、各ビルドに15から21のビルドステップがあり、Webインターフェイスで閲覧および確認するのが難しいことです。約150の列があるため、ロードに永久に時間がかかります(30秒から数分と考えてください)。3つ目は、ビルドターゲットの自動検出機能がなくなったことです(ただし、同僚の1人が私にこのことを気にかけているのと同じように、そもそも何が私たちにもたらされたのかわかりません)。最後に、

現在、新しい開発に移行し、g ++とsubversionを使用し始めています(古いリポジトリは移植しないでください。新しいものに限って)。また、より多くの単体テスト( "more"は誤った結果をもたらす可能性があります...それは他のものに似ています)、および統合テスト(pythonを使用)を開始しています。これらを私の既存の構成にどのように組み込むかを理解するのに苦労しています。

それで、私はここで哲学的にどこが間違っているのですか?どのようにすれば、自分の構成を実際に保守可能にするために(buildbotを使用して-これは私が取り組むライセンスを持っている唯一のパズルのピースです)先に進むことができますか?デザインの弱点に対処するにはどうすればよいですか?大規模な(おそらく過度に)複雑なコードベースのCI戦略に関して、実際に機能するものは何ですか?

編集:

私は自分の問題を説明したと思ったが、明らかに十分に明確ではなかった。私はない CIのプラットフォームを変更するための提案を探しています。それは起こらないでしょう、そしてそれが受け入れられないことを示唆する答え。私が知りたいのは、他の人々がCIを使用して複雑なコードベースをどのように管理するかです。私は十二乗の異なる製品を持っています、そして依存関係が風に散らばっていて、それらはすべて異なります。これは私がどのように対処するか知りたいものです。


私もその答えを知りたいです。私たちの環境はあなたの環境ほど複雑ではありませんが、依存関係の依存関係があります(セットアッププロジェクトの場合、4層の依存関係があります)。各プロジェクトをCIプロジェクトにする必要があるかどうか、またはVisual Studio .slnファイルを使用してそれを処理する必要があるかどうかわからないので、各プロジェクトの依存関係ツリーを再作成する必要はありません(および将来のプロジェクト)。
モスワルド2011

ローカルマシンで構築できないと、CIサーバーのミッションがビジネスにとって重要になります。あなたはこれを再考したいと思うかもしれません。
するThorbjörnRavnアンデルセン

回答:


3

私はあなたが説明するほど悪い状況に直面していませんが、私は何十ものコンポーネントを含むCI構成を維持しており、その間にいくつかの「単純な」依存関係があります。私のアプローチがあなたに進むべきいくつかのヒントを与えることを願っています。この問題は、CIサーバーの選択だけに関係するのではなく、全体的なビルドプロセスとプロジェクト構造にも関係しています。

問題を2つの部分に分けます。建物とCIです。

建物

「ビルド」とは、手元のソースコードを最終的なアーティファクトに変更するプロセスを意味します。私たちの会社は主に開発にJavaを使用しており、使用したビルドツールはMavenです。プロジェクトの性質上、おそらくそれを使用することはできませんが、Mavenには注目に値するいくつかの価値ある概念があります。

1)Mavenの世界では、各アーティファクト(ライブラリ、実際のプログラムなど)を明確に分離して分離する必要があります。アーティファクト間の依存関係は明確でなければなりません。厄介な依存関係、特にビルドアーティファクト間の循環依存関係は、ビルドプロセスを混乱させます。

たとえば、その前にいくつかのJavaプロジェクトを見ましたが、ビルドプロセス全体の後にいくつかのJAR(Javaではlib / dllと見なすこともできます)がビルドされていますが、実際には相互依存しています。同様に、A.jarはB.jar内のものを使用しており、その逆も同様です。このような「モジュール化」はまったく意味がありません。A.jarとB.jarは常に一緒にデプロイして使用する必要があります。つまり、後でそれらを別のプロジェクトに分離したい場合(たとえば、他のプロジェクトで再利用するため)、uはそれを実行できなくなります。つまり、最初にビルドするプロジェクトAまたはBを決定できません。

はい、それはあなたのソフトウェアの設計に仕入れる必要がありますが、複雑な構築ツール/モデルを乱雑なプロジェクトで機能させるために時間を費やすのではなく、設計を再編成して時間を費やすのではなく、シンプルな建物モデル。

2)依存関係は宣言的である必要があります。以前に見たビルドプロセスはたくさんありますが、ビルドプロセスには、プロジェクトでローカルに必要なすべてのライブラリが含まれています。一部のライブラリが実際にビルドする必要のある他のアーティファクトである場合、ビルドプロセスが非常に面倒になります。

3)依存関係を取得するための、またはコンパイルされたアーティファクトをデプロイするためのアーティファクトの「集中」ストレージ。オフィス全体で「集中化」する必要はありません(もしそうならそれは素晴らしいでしょう)、ローカルディレクトリだけで既に十分です。

2と3についてさらに詳しく説明します。例を挙げると、3つの独立したプロジェクトを含むプロジェクトに遭遇しました。各プロジェクトはソースに基づいて構築され、さらにlibsはソースディレクトリのlib /ディレクトリの下に構築されます。プロジェクトAはいくつかのライブラリをビルドします。これらはプロジェクトBとCによって使用されます。いくつかの欠点があります。ビルド手順は複雑で自動化が困難です。別のプロジェクトで再利用される不要な重複JARでソース管理が肥大化している

Mavenの世界では、プロジェクトBとCはプロジェクトソースにA.jar(および他のサードパーティライブラリなどの他の依存関係)を実際には含んでいません。宣言的です。たとえば、プロジェクトBのビルド構成では、A.lib v1.0、xyz.lib v2.1などが必要であることを宣言するだけで、ビルドスクリプトは/A/1.0/Aからlibを検索します。 jarおよび/xyz/2.1/xyz.lib

Maven以外の世界では、このアーティファクトディレクトリは、合意されたディレクトリ構造を持つ1つまたは2つのディレクトリである必要があります。すべてのサードパーティライブラリを共有場所に配置して、開発者に同期またはローカルマシンへのコピーを許可することができます。私が何年も前に行ったC ++プロジェクトでは、libとヘッダーを$ {artifact_dir} / lib_name / verに設定し、artifact_idを環境変数として宣言しています。

プロジェクトAがビルドされると、その成果物のコピーがそのArtifact_dirに含まれるため、プロジェクトBをビルドすると、Bは手動でコピーすることなく、Aの結果を自動的に取得できます。

4)変更できないリリース。A.lib 1.0をリリースしたら、それだけです。1か月後にA.lib 1.0のコンテンツが変更されることはありません。そのような場合、それはA.lib 1.1であるべきです。変化するコードベースのアーティファクトは、Mavenではスナップショットと呼ぶ特別な「バージョン」を考慮する必要があります。

変更不可のリリースは、より倫理的な問題です。しかし、それが解決したことは明らかです:uが同じlibを使用する多くのプロジェクトを持っている場合、uは使用しているそのlibのバージョンを知っており、異なるプロジェクトで使用されている同じバージョンのlibが実際に同じであることが確実になります。プロジェクトXとYの両方がlib Aを使用しているのに、ビルド結果が異なるのはなぜですか?(そして、XとYによって使用されるlib Aは、libのコンテンツまたはファイルサイズを調べた後、実際には異なることがわかります)。


これらはすべて、プロジェクトを個別にビルドできることを保証します。たとえば、最初にプロジェクトAをビルドし、A.libをプロジェクトBにコピーしてから、プロジェクトBをビルドするなどの手作業は不要です。

このような演習を行った後、たとえばプロジェクトAをビルドすると、一元化されたアーティファクトストレージから依存関係を取得しようとします。いくつかの依存関係(会社の他のプロジェクト、たとえばプロジェクトB)が見つからない場合、必要なのは、プロジェクトBのソースを取得してビルドし(成功すると中央ストレージにデプロイされます)、そしてその後、プロジェクトAを再度ビルドします。


CI

簡単なビルドシステムと明確な依存関係により、CIははるかに簡単になります。CIサーバーが次の要件を満たしていると思います。

1)ソース管理を監視し、ソースに変更がある場合はチェックアウト+ビルドのみ

2)プロジェクト間の依存関係を設定できる

プロジェクトの明確な依存関係により、実際のプロジェクトに従ってCIでプロジェクトをセットアップし、プロジェクトの依存関係に従ってCIプロジェクトの依存関係をセットアップするだけです。CIサーバーは、プロジェクトをビルドする前に依存プロジェクトをビルドするように設定する必要があります(もちろん、プロジェクトソースが実際に変更されている場合にのみビルドが行われます)。

すべてがうまくいけば、巨大で複雑でありながら管理可能なCI(さらに重要なことに、管理可能なプロジェクト構造)が必要です。


私はこの答えがどこに行くのが好きですが、「建物」セクションでより詳細に入ることができますか?つまり、いくつかの例を挙げ、いくつかの概念をより完全に、詳細に説明します。
ネイト

うーん...どの部分が好きですか?記事を編集して、各部分の詳細を示します。どの部分を詳しく説明する必要があると感じられるかを教えてもらえれば、さらに良いでしょう。ちなみに、Javaも使用している場合は、maven.apache.orgをご覧ください。Mavenは採用するのが最も簡単なことではないかもしれませんが、それはあなたがあなたのものをきれいで組織化することを余儀なくさせます。
エイドリアンシャム

1

私にとって同じような状況でうまくいったこと:

  • ビルドの一部を専用のビルドアプリにシャントすることによるアプリレベルの抽象化(この場合、これらはメインビルドから呼び出されるPHPスクリプトです)。これにより、数十行のビルドステップを1つのビルドステップに減らすことができます。
  • メインビルドスクリプトから起動されるサブビルドスクリプトを作成することによるビルドレベルの抽象化。それがビルドボットに関連しているかどうかはわかりません(その製品の経験はありません)。

ビルド自体をソフトウェア開発プロジェクトとして扱うことをお勧めします。これは、ビルドコードベースをモジュール化し、それに対するいくつかの自動テストを作成する必要があることを意味します(たとえば、既知のリビジョン番号をビルドし、正しい結果が生成されるかどうかを確認します)。


0

JenkinsをCIサーバーと見なします。ここで機能を確認できます。

https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins

どうして?インストールは簡単で、すばらしいインターフェースがあり、設定や拡張が簡単で、ほとんどすべての準備ができたプラグインがたくさんあります。

https://wiki.jenkins-ci.org/display/JENKINS/Plugins

試してみる :)


2
私の質問のタイトルは読んだようですが、本文は読んでいません...私は製品の提案を探していません。商品を選びました。複雑なCIセットアップを整理する方法を探しています。
ネイト

ネイト、私はあなたの投稿をすべて読んで、あなたが間違った製品を選んだと思います、それが私がジェンキンスを提案した理由です。私はJenkinsを使用して、C ++製品のさまざまな種類のテスト(複数の言語で記述されたテストを含む)を複数のマシンでのクラスター化を使用して実行しています。管理と構成は非常に簡単です。本当に、試してみてください:)
Patrizio Rullo

あまりにも、このブログの記事を見てください:vperic.blogspot.com/2011/05/...
PATRIZIO Rullo

0

今では、Go by ThoughtWorksを使用する前に、CruiseControl.Netを使用していました。世界の半分の場所に2つのチームがあり、タイムゾーンに大きな差があることを考えると、これは役に立ちました。

私たちは複数のプロジェクトを管理しており、ほとんどのタスクは地球の両側にいる2人の開発者間の重複を含んでいるため、すべてのファイルが他の誰かのビルドを壊してはならないことに注意する必要があります。

また、GoとAgile Processがハードであることにより、管理が容易になり、インストール後の頭痛が軽減されました。テストはGoとも統合されています。

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