web-dev-qa-db-ja.com

CIによる開発を回避するにはどうすればよいですか?

私は非常に大規模な研究主導のオープンソースプロジェクトに取り組んでおり、他の多くの定期的な貢献者と協力しています。現在、プロジェクトは非常に大きいため、コンソーシアム(2人の正社員と少数のメンバーで構成される)がプロジェクトの維持、継続的インテグレーション(CI)などを担当しています。しかし貢献。

プロジェクトは、「コア」フレームワーク、約500万行程度のコード、コンソーシアムが管理する一連の「プラグイン」、およびいくつかの外部プラグインで構成されています。 tさえ承知しています。

現在、CIはコアとメンテナンスプラグインをビルドしています。

私たちが直面する大きな問題の1つは、ほとんどのコントリビューター(特に時折発生するコントリビューター)が、保守されているプラ​​グインの90%をビルドしていないため、コア(これらの日はかなり定期的に行われます)のリファクタリングの変更を提案するとき、彼らは、GitHubでプルリクエストを行う前に、コードがマシンでコンパイルされることを確認しました。

コードは機能し、満足し、CIの構築が完了して問題が発生します。コンソーシアムが管理するプラグインでコンパイルが失敗し、コントリビューターが自分のマシンで構築しなかった。

そのプラグインは、たとえば [〜#〜] cuda [〜#〜] などのサードパーティのライブラリに依存している可能性があり、ユーザーは望んでいない、方法がわからない、または単にできるハードウェア上の理由から、壊れたプラグインをコンパイルしてください。

それで-PRはマージされないマージの縁にあるままです PRs -またはコントリビューターは壊れたプラグインのソースで名前が変更された変数をつかみ、コードを変更してプッシュします彼/彼女のブランチは、CIがコンパイルを完了するのを待ち、通常より多くのエラーを取得し、CIが満足するまでプロセスを繰り返します-または、コンソーシアムの2つのすでにオーバーブッキングされたパーマネントの1つが手を差し伸べ、PRを修正しようとします機械。

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

45
lagarkane

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

  • 期待値を設定:CIが追加の問題を頻繁に検出すること、およびこれらの問題が修正される前に修正する必要があることを説明する寄稿ドキュメントを用意します。マージ。おそらく、小さめのローカルな変更のほうがうまく機能する可能性が高いため、大きな変更を複数のPRに分割する方が賢明な場合があります。

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

  • CIを自分で使用する方法を説明します:不満の一部は、このフィードバックがPRの送信後にのみ送信されることです。寄稿者が自分のリポジトリ用にCIを設定した場合、彼らはより早いフィードバックを受け取り、他の人々へのCI通知を少なくします。

  • すべてのPRをいずれかの方法で解決します。壊れているためにマージできない場合、および問題の修正に向けた進展がない場合は、それを閉じます。これらの放棄されたオープンPRはすべてを散らかすだけであり、フィードバックは問題を無視するよりも優れています。これは非常にうまく表現でき、問題が修正されたらマージしても問題ないことは明らかです。 (参照: The Art of Closingby Jessie Frazelleメンテナーのためのベストプラクティス:ノーと言うことを学ぶ

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

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

68
amon

持続可能なプラグインモデルを構築するには、コアフレームワークがプラグインが信頼できる安定したインターフェースを公開する必要があります。重要なルールは、新しいインターフェースを徐々に導入することはできても、すでに公開されているインターフェースを変更することはできないということです。このルールに従えば、コアフレームワークのimplementationをリファクタリングでき、コンソーシアムが管理するプラグインであろうと外部のプラグインであろうと、プラグインを誤って壊す心配はありません。

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

34
casablanca

正直なところ、これをより適切に処理できるとは思いません-変更の結果、プロジェクトの維持されている部分が壊れる場合CIは失敗するはずです。

プロジェクトにcontributing.mdまたは、新しくて不定期の寄稿者が寄稿を準備するのを助けるために何か似ていますか?明確なリストはありますか?どのプラグインがコアの一部であり、互換性を維持する必要があるか?

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

8
mhr

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

だから、ここがオープンソースプロジェクトのルーズスタイルが崩れる場所だと思います。中心的に組織されているほとんどのプロジェクトは、特にAPIの境界を越える場合、コアのリファクタリングに注意を払っています。彼らがAPI境界をリファクタリングする場合、それは通常「ビッグバン」であり、すべての変更が一度にスケジュールされ、APIメジャーバージョンに増分されますおよび古いAPIが維持されます。

「すべてのAPIの変更は事前に計画する必要があります」というルールを提案します。APIに下位互換性のない変更を行うPRが発生した場合、メンテナと連絡を取っていない人から事前にアプローチに同意することで、単に閉じられ、送信者はルールを指し示します。

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

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

8
pjc50

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

テクノロジーに関係なく、コントリビューターがブランチにプッシュしたときに自動ビルドを提供すると、変更を行う際に注意すべき点についてのフィードバックがはるかに速くなり、事後の修正が不要なPRにつながります。

設計上の問題は修正するのに適していますが、この問題とは無関係です。

2
Nathan Adams

コードは機能し、満足し、CIの構築が完了して問題が発生します。コンソーシアムが管理するプラグインでコンパイルが失敗し、コントリビューターが自分のマシンで構築しなかった。

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

あなたの解決策は簡単です:貢献への障壁を下げる

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

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

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

次に:

  • 彼らは維持されたプラグインを構築/テストしないことの言い訳はありません:彼らは利用可能なすべてを持っています。
  • CI駆動のPRで長いフィードバックを待つ必要はありません。インクリメンタルコンパイルと、(推測ではなく)デバッグする機能があります。

一般に、ビルドサーバーは複数のコントリビューター間で共有できますが、特別なハードウェア周辺機器が含まれる場合、コントリビューターがこれらの周辺機器を自分で使用する必要がある場合があります。


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

2
Matthieu M.

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

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

どちらの問題も簡単に解決できるはずですが、コアチームにはそれを実行する能力がない可能性があると述べています。 1つのオプションは、コミュニティにこの問題への対処の助けを求めることです。

1
jcayzac

これを潜在的な解決策として挙げた人は他にいないようです。

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

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

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

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

1
Kain0_0

次のような状況の理解に問題があります。CIが作成するブランチは1つだけですか?

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

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

次に、機能ブランチでの成功したCIビルドを要求して、そのブランチのプル要求が受け入れられるようにします。

0
Kyralessa