CI主導の開発をどのように回避しますか...?


45

私は非常に大規模な研究主導型のオープンソースプロジェクトに取り組んでおり、他の多くの定期的な貢献者もいます。プロジェクトは現在非常に大きいため、コンソーシアム(2人の常勤従業員と少数のメンバーで構成される)がプロジェクトの維持、継続的統合(CI)などを担当しています。外部の統合のための時間がありません。しかし貢献。

このプロジェクトは、「コア」フレームワーク、約50万行程度のコード行、コンソーシアムが管理する「プラグイン」の束、およびいくつかの外部プラグインで構成されています。気づいてさえいません。

現在、私たちのCIはコアとメンテナンスされたプラグインを構築しています。

私たちが直面している大きな問題の1つは、ほとんどの貢献者(および特に臨時の貢献者)がメンテナンスされたプラグインの90%を構築していないことです。 GitHubでプルリクエストを行う前に、コードがマシンでコンパイルされることを確認しました。

コードは機能し、満足し、CIはビルドを終了し、問題が始まります。コンソーシアムが管理しているプラ​​グインでコンパイルが失敗しました。コントリビューターは自分のマシンではビルドしませんでした。

そのプラグインは、たとえばCUDAなどのサードパーティライブラリに依存している可能性があり、ユーザーは壊れたプラグインをコンパイルしたくない、ハードウェア上の理由でコンパイルできない、または単にできない。

そのため、PRはマージされないPRの辺りにとどまるか、寄稿者が壊れたプラグインのソースで名前を変更した変数を把握し、コードを変更し、ブランチをプッシュし、 CIがコンパイルを終了し、通常はエラーが増え、CIが満足するまでプロセスを繰り返します-または、コンソーシアムで既にオーバーブッキングされている2人のパーマネントのうちの1人が手を差し伸べ、マシンのPRを修正しようとします。

これらのオプションはいずれも実行可能ではありませんが、どのように異なる方法を実行するのかわかりません。プロジェクトの同様の状況に直面したことがありますか?もしそうなら、この問題をどのように処理しましたか?ここに表示されていない解決策はありますか?


84
プラグインAPIをシステムに提供する際の最も重要なルールは、プラグインAPIが安定しているか、少なくとも下位互換性があることです。プラグインAPIを意図的に変更せずにコアを変更しても、プラグインのコンパイルが中断されることはありません(コンパイルではなく、偶発的に機能を中断する可能性があります)。コア内の変数名の単純な変更がプラグインのコンパイルの破損につながる場合、プラグインとコアの分離は完全に壊れているように見えます。
Doc Brown


1
@KevinKrumwiede:彼らはすでにこれを知っていると確信しています;-)あなたが非互換性を経験した場合、私は彼らが意図的にAPIを変更したと確信しています。
Doc Brown

3
それは本当に誤解を招くので、私は質問を言い換えます。以下のような何か、彼らは私たちの現在のCIを破るとき、どのように私はのPRを管理することができますか?あなたの状況をより良く捉えます。
bracco23

2
ビルド/テストプロセスはどれほど困難/複雑ですか?単一のコマンドを実行するか、単一のボタンをクリックするだけの問題です。その時点で、ユーザーがPRを送信する前にすべてのテストを自分で実行することを期待することが合理的になります。
アレクサンダー

回答:


68

CI駆動の開発は問題ありません!これは、テストを実行せず、壊れたコードを含めるよりもはるかに優れています!ただし、関係者全員にこれを容易にするいくつかのことがあります。

  • 期待を設定する: CIが追加の問題を見つけることが多いこと、およびマージの前にこれらを修正する必要があることを説明する貢献ドキュメントを用意します。おそらく、小さなローカルな変更がうまく機能する可能性が高いことを説明してください。そのため、大きな変更を複数のPRに分割することは賢明です。

  • ローカルテストを奨励する:システムのテスト環境を簡単にセットアップできます。すべての依存関係がインストールされたことを確認するスクリプトですか?準備ができているDockerコンテナーですか?仮想マシンのイメージ?テストランナーには、より重要なテストに優先順位を付けることができるメカニズムがありますか?

  • CIを自分で使用する方法を説明します。フラストレーションの一部は、このフィードバックがPRを送信した後にのみ発生することです。寄稿者が自分のリポジトリ用にCIを設定すると、より早いフィードバックが得られ、他の人に対するCI通知が少な​​くなります。

  • いずれにせよ、すべてのPRを解決します。 何かが壊れているためにマージできない場合、および問題の修正に向けて進展がない場合は、それを閉じます。これらの放棄されたオープンなPRはすべてを混乱させるだけであり、フィードバックは問題を無視するよりも優れています。これを非常にうまく表現することは可能であり、もちろん、問題が修正されたらマージしても問題ないことを明確にすることができます。(参照:Jessie Frazelleよる「クロージングの芸術」、メンテナーのためのベストプラクティス:ノーと言うことの学習

    また、これらの放棄されたPRを発見可能にして、他の誰かがそれらをピックアップできるようにすることも検討してください。残りの問題がより機械的なものであり、システムに精通している必要がない場合、これは新しい貢献者にとっても良いタスクです。

長期的な観点から見ると、この変更は無関係な機能を破壊することが多いため、現在の設計に少し問題がある可能性があります。たとえば、プラグインインターフェイスはコアの内部を適切にカプセル化しますか?C ++を使用すると、実装の詳細を誤って漏らしやすくなりますが、誤用が非常に難しい強力な抽象化を作成することもできます。これを一晩で変更することはできませんが、脆弱性の少ないアーキテクチャに向けたソフトウェアの長期的な進化を導くことができます。


13
私はより多くのメンテナは、このような態度😔よかった「これらの放棄されたオープンのPRだけですべてを散らかす」
GammaGames

34

持続可能なプラグインモデルを構築するには、コアフレームワークが、プラグインが依存できる安定したインターフェイスを公開する必要があります。黄金律は、時間の経過とともに新しいインターフェースを導入できるが、すでに公開されているインターフェースを変更することはできないということです。このルールに従うと、コンソーシアムが管理するものであれ外部のものであれ、誤ってプラグインを壊すことを恐れることなく、コアフレームワークの実装をリファクタリングできます。

あなたが説明したことから、あなたは明確に定義されたインターフェースを持っていないように聞こえます、そしてそれは変更がプラグインを壊すかどうかを見分けるのを難しくします。このインターフェイスを定義し、コードベースで明示的にすることで、寄稿者が修正すべきでないものを理解できるようにします。


20
CIには自動テストが必要です。プラグインのインターフェースが同じであることを確認したい場合、すべてのプラグインは必要なインターフェースを表すテストを提供する必要があります。このようにして、インターフェースが変更されると、どのプラグインが壊れているかがわかります。ローカルで実行するこれらのテストを提供してください。PRを発行する前に、何が壊れているのかがわかります。
candied_orange

1
@lagarkaneの明確な定義は、技術的というよりも政策上の問題です。あなたのものと同じように、アップグレードで以前の動作を単に放棄するソフトウェアがあります。Perl5はPerl6と互換性がなく、Python2.7はPython3.4などと完全に互換性がありません。その後、古いコードを引き続きサポートするソフトウェアがあります。Netscape Navigator 4用に記述されたほぼすべてのJavaScriptコードを最新のブラウザーで実行できます。Tclプログラミング言語は、元のバージョンなどに戻るようにバックワード互換です...
slebetman

3
@lagarkane:コンソーシアムの形成は正しい方向への一歩であり、コアメンバーがこれらのインターフェイスの作成に力を注いでいる場合、将来の博士号とインターンの力を活用して、破損を最小限に抑えながらプロジェクトを強力に進めることができます。:)
casablanca

4
@Fattie:消費者向け製品の開発に成功し、開発者はその一部になりたいのであれば、一緒に遊ぶことを余儀なくされるため、Appleにとってはうまくいきます。これらの開発者が実際に重大な変更を好む可能性は低いと思われ、オープンソースプロジェクトの良いモデルではありません。
カサブランカ

1
@casablancaは、MacOSとWindowsOSの両方の系統が大成功を収めています。(ほぼ間違いなく、人間の存在下でのドル換算で最も優れた2つの製品。)数十年にわたって、彼らはまったく反対のアプローチをとっていました。どうやら両方とも成功したようです!
ファッティ

8

正直に言うと、これをもっと良い方法で処理できるとは思わない-変更がプロジェクトの維持された部分を壊すことになった場合、CIは失敗するはずだ。

あなたのプロジェクトには、contributing.md新規および時々寄稿者が寄稿を準備するのに役立つようなものがありますか?どのプラグインがコアの一部であり、互換性を維持する必要があるか、明確なリストはありますか?

依存関係などのためにすべてをマシン上で構築するのが難しい場合は、貢献者が使用するビルド環境としてすぐに使用できるドッカーイメージを作成することを検討できます。


1
返信いただきありがとうございます!はい、貢献ガイドラインは公開されていますが、提案されているようにプラグインはリストされていません。これはすでに良いアイデアです。Dockerイメージを作成することは、現在の貢献プロセスをすでに大きく改善しているように聞こえます!入力をありがとう
lagarkane

8

そのため、コアでのリファクタリングの変更を提案するとき(最近は非常に定期的に行われます)、githubでプルリクエストを行う前に、コードがマシンでコンパイルされることを確認しました。

だから私は、オープンソースプロジェクトのルーズスタイルが崩壊する可能性がある場所だと思います。ほとんどの中央組織のプロジェクトは、特にAPIの境界を越える場合、コアリファクタリングに慎重です。彼らはリファクタリングAPIの境界をすれば、それは通常、すべての変更がAPIメジャーバージョンへの増分で一度に予定されている、「ビッグバン」だ古いAPIが維持されています。

「すべてのAPIの変更は事前に計画する必要があります」というルールを提案します:メンテナーと連絡を取っていない人からAPIに後方互換性のない変更を行ってPRが来たら、そのアプローチに事前に同意します。単に閉じられ、提出者がルールを指しただけです。

プラグインAPIの明示的なバージョン管理も必要になります。これにより、すべてのv1プラグインが引き続きビルドおよび動作しながら、v2を開発できます。

また、なぜ多くのコアリファクタリングとAPIの変更が行われているの、もう少し質問します。彼らは本当に必要なのか、それとも人々がプロジェクトに自分の好みを課しているのか?


2

CIプロセスのように聞こえるのは、PRを上げる前に、貢献者がより​​きめ細かく、より包括的で、目に見えるようにする必要があります。例として、BitBucketには、これを可能にするパイプライン機能があります。この機能では、CIビルドプロセスをコードで定義するファイルを提供し、失敗した場合、ブランチはマージされません。

技術に関係なく、貢献者がブランチにプッシュするときに自動ビルドを提供すると、変更を行う際に注意すべきことについてより迅速にフィードバックが得られ、事後の修正が不要なPRにつながります。

設計上の問題は修正するのが良いでしょうが、この問題とは直交しています。


2

コードは機能し、満足し、CIはビルドを終了し、問題が始まります。コンソーシアムが管理しているプラ​​グインでコンパイルが失敗しました。コントリビューターは自分のマシンではビルドしませんでした。

そのプラグインは、たとえばCUDAなどのサードパーティライブラリに依存している可能性があり、ユーザーは壊れたプラグインをコンパイルしたくない、ハードウェア上の理由でコンパイルできない、または単にできない。

あなたの解決策は簡単です。貢献への障壁を下げてください

(1)編集-コンパイル-テストサイクルを高速化し、(2)環境の違いをスムーズにする最も簡単な方法は、ビルドサーバーを提供することです。

  • 24、48、または96コア、2GB RAM /コア、SSDの強力なマシンを選択して、コンパイルを高速化します。
  • 適切なハードウェア(FPGA、グラフィックカードなど)が必要であることを確認してください。
  • 必要なすべてのソフトウェアライブラリがプリインストールされたDockerイメージを作成します。

そして、それらのビルドサーバーを貢献者に公開します。新しいDockerイメージにリモートでログインし、このマシンでリモートで編集、コンパイル、テストできる必要があります。

次に:

  • メンテナンスされているプラ​​グインをビルド/テストしないことの言い訳はありません。利用可能なすべてのものがあります。
  • CI主導のPRで長いフィードバックを待つ必要はありません。インクリメンタルコンパイルとデバッグ(推測ではなく)が可能です。

一般に、ビルドサーバーは複数の貢献者間で共有できますが、特別なハードウェア周辺機器が関係する場合、貢献者がその周辺機器を単独で使用する必要がある場合があります。


出典:獣の価格と必要なさまざまなモデルを考えると、FPGAを使用してソフトウェアで作業している場合、すべての開発者のマシンにインストールされているFPGAの各モデルは見つかりません。


1

契約を変更せずにコアに貢献すると、依存ソフトウェアが破損する可能性がある場合は、次のいずれかを提案します。

  • インターフェイスの契約はあいまいな場合があります。関数と関数パラメーターに属性を追加すると、クライアントコードに追加の制約を公開して、契約を明確にするのに役立つ場合があります。または、契約に違反する変更を適用する場合は、セマンティックバージョニングを採用すると役立つ場合があります。
  • 単体テストは、可能な呼び出しシナリオを十分にカバーしていません。

どちらの問題も簡単に解決できるはずですが、コアチームにはそうする能力がない可能性があることに言及しています。1つの選択肢は、問題に対処する際にコミュニティに支援を求めることです。


1

これを潜在的な解決策として挙げた人は他にいません。

  • アクセスできるすべてのプラグインをリストします。
  • これらのプラグインが定義するすべてのテストを実行します
  • コアとすべてのプラグイン間のすべての要求/応答/相互作用を記録する
  • それらの記録を保存すると、これらは大まかな互換性テストになります。

コアを開発するとき、開発者にこれらの互換性テストを実行するように勧めてください。失敗した場合はチェックインしないでください。

これは100%の互換性を保証するものではありませんが、より多くの問題を早期にキャッチします。

副次的な利点は、これらの記録により、どのインターフェイスがアクティブに使用され、どの機能がアクティブに使用されているかを強調できることです。


0

状況が次のように理解できません。CIは1つのブランチのみを構築しますか?

CIで複数のブランチを構築できない理由はありますか?

この問題の最も簡単な解決策は、貢献者が自分の機能ブランチでCIビルドを実行できるようにすることです。

次に、そのブランチのプルリクエストが受け入れられるように、機能ブランチでのCIビルドの成功が必要です。


これは問題を要約しているようです。
ファッティ

1
質問には、「または貢献者がコードを変更し、ブランチをプッシュし、CIのコンパイルが完了するまで待機し、通常はより多くのエラーが発生し、CIが満足するまでプロセスを繰り返す」と書かれています。既にそうなっていますが、問題は、このような長い編集-デバッグサイクルで開発するのがやや苦しいことです。
npostavs

@npostavsありがとう、私はそれを読んだ最初か2つを見逃したと思います。それでも...私は問題ではないようです。多くの依存関係があり、それらを壊すことはできないので、貢献者はそれらすべてとの互換性を保つ必要があります。それが大きなソフトウェアの性質です。確かに、おそらくビルドを高速化するために作業を行うことができますが、そうでなければ、どのショートカットが存在する可能性がありますか?
キラレッサ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.