ビルドに失敗したコミットを自動的に元に戻す


44

私の同僚は、ビルドに失敗したコミットを元に戻すためにCIサーバーを作成することを考えていると言ったので、(少なくともビルドを渡す場合のようHEADmaster)常に安定しています。

これはベストプラクティスmasterですか、それとも開発者が修正するまで壊れたままにしておくよりも問題がある可能性がありますか?

私の考えでは、コミットを元に戻すと、コミットと修正を読み直すタスクがより複雑になります(開発者は元に戻して修正をコミットする必要がありますが、これも混乱しますgit log)。修正。master安定していることにはいくつかの利点がありますが、失敗したコミットを元に戻すことは私を納得させません。

編集:それがmaster他の開発ブランチであるかどうかは関係ありませんが、質問は同じままです:ビルドに失敗したコミットをCIシステムが元に戻す必要がありますか?

別の(長い)編集:わかりgitました、奇妙な方法で使用しています。ブランチにコミットすると他の開発者とその変更から隔離され、ブランチを再統合して競合の可能性に対処する必要があるため、ブランチの概念は実際のCIに反すると信じています。全員がmasterこの競合にコミットすると、最小限に抑えられ、すべてのコミットがすべてのテストに合格します。

もちろん、これにより、安定性のみをプッシュする(またはビルドを中断する)ことを強制し、後方互換性を壊さないように、または新しい機能を導入するときに機能を切り替えないように、より慎重にプログラムします。

CIをこのように、またはそのように行う場合、トレードオフがありますが、それは質問の範囲外です(これに関する関連する質問を参照)。ご希望であれば、質問を言い換えることができます。開発者の小さなチームが機能ブランチで協力しています。1人の開発者がそのブランチのビルドを中断する何かをコミットした場合、CIシステムはコミットを元に戻すべきですか?


38
失敗したビルドはmaster、最初から到達することはありません。それが開発と機能のブランチの使用目的です。これらの変更は統合ブランチのようなもので行われ、そこで複数の開発者のすべての新機能が連携して動作するかどうかをテストできます。または、少なくともそれが1つの可能なワークフローです。
トールステンミュラー

1
@thorstenmüllerは、すべての開発者が使用する開発ブランチにあることをよく想像してください。CIシステムは、ビルドに失敗したコミットを元に戻す必要がありますか?
カルロスキャンデロス

7
奇妙な方法でgitを使用しているようです。一般に、人々は自分のブランチで自分のリポジトリに取り組み、個人ビルドのCIが変更が問題ないことを確認したら、メインにプッシュするだけです。
ウィルバート

4
>「この競合は最小限に抑えられます」。マージ時に競合は少なくなりますが、マージの問題はより多く発生します。解決策は、ブランチではなく、プロセスの一部としてマスターからブランチに継続的にマージすることです。
-deworde

2
...失敗したビルドが最初からマスターに受け入れられないようにしましょう。
user253751

回答:


56

次の理由でこれを行うことに反対します。

  • あなたに代わってコード変更する自動化ツールをセットアップするときはいつでも、それが間違ったり、その変更をやめる必要がある状況が発生するリスクがあります(たとえば、Google Mockの最新バージョン)バグがあったため、コードが失敗するわけではありません)、再設定に時間を浪費する必要があります。さらに、コードのバグではなく、ビルドシステムのバグが原因でビルドが失敗するというわずかなリスクが常にあります。私にとって、CIとは、自分のコードが正しいという自信を得ることです。これは単に、私が心配する潜在的な問題の別の原因になります。

  • 「ビルド」を破るバグの種類は、修正に非常に短い時間しかかからない愚かな間違いであるべきです(コメントで指摘したように、これはあなたに当てはまります)。より微妙で複雑なバグが定期的にマスターに反映される場合、正しい解決策は「速く修正する」ことではなく、機能ブランチをマージする前に確認するときは注意が必要です。

  • バグが適切に修正されている間にmasterをビルド不能のままにしておくと、だれも傷つけません。CEOが個人的にマスターをチェックアウトし、任意の時点でクライアントに直接コードを公開するわけではありません(少なくとも、できればあなたの関与がなければ)。あなたがバグを修正することができます前に、何かを解放する必要があることを非常に低い場合には、その後、あなたは簡単に公開する前に手動で復帰する意思決定を行うことができます。


1
また、成功したビルドのみが、展開可能な「ビルドドロップ」の作成をトリガーする必要があります。ビルドが失敗した場合、デプロイ可能なビルドのドロップはないはずです。そのため、誰かが悪いコードをクライアントに公開するリスクはありません。
マークフリードマン

1
間違いなく、私が思うにこれよりも優れた、使用頻度の高い別のオプションがあります(Twitterで使用しています)。失敗したビルドをマスターに配置しないでください。ばかげた間違いも簡単に修正できます。以下の私の完全な回答をご覧ください。
ディーンヒラー

26

最初に条件に同意しましょう。

私は個人的に、Continuous BuildおよびContinuous Integrationという用語を使用して、2つの異なるシナリオを区別しています。

  • 連続ビルド:リポジトリが最後のビルド以降に変更されたかどうかを定期的にチェックし、変更された場合はビルド/テストするツール。
  • 継続的インテグレーション:プルリクエストを受け取り、表示するに最新のヘッドに対して検証するツール。

後者の継続的インテグレーションは、それが保護するリポジトリが常にグリーンであることを意味します1:厳密に優れています。

あなたの質問は、Continuous Buildでのみ意味があるので、これがあなたの設定であると仮定して答えます。

1:環境上の原因もビルドを台無しにする可能性があります。たとえば、ハードコーディングされた年(2015)のテストが2016年1月に失敗し始め、ディスクがいっぱいになる可能性があります...そしてもちろん不安定なペストがありますテスト。ここではそれらの問題を謙虚に無視します。それ以外の場合は、どこにも到達しません。


継続的なビルドのセットアップがある場合、ビルドを壊した可能性のあるコミットの反転を実際に自動化できますが、微妙な点がいくつかあります。

  • 実際にコミットを削除することはできません。他の同僚は既にコミットをチェックアウトしている可能性があり、次にコミットしようとしたときにプッシュバックします。代わりに、リバースはリバース diff をコミットする必要があります。ああ、同僚は仕事を元に戻すことを嫌います。それは彼らが再びそれを押し戻す方法を見つけなければならないので、それが正しいとき、彼らが仕事を元に戻すために...
  • 実際には最後のコミット(マージ)だけを除去することはできませんが、特定のポイントまでのすべてのコミットを除去する必要があります。たとえば、最後の既知の良好なコミット(システムをブートストラップするときは注意してください)。
  • 外部の原因(環境問題)について考え、すべてを0日目に戻すセットアップを避ける必要があります。ありがたいことに、最後の既知の良いコミットに戻すと、この問題が回避されます。
  • 最後の既知の正常なビルドがビルドされなくなる可能性がある(環境の問題)と考える必要があります。その場合、それ以降のコミットはすべて取り消される可能性があります。理想的には、障害が発生した場合、元に戻す前に、最後に確認された正常なビルドをチェックアウトし、再テストします。合格した場合は元に戻し、それ以外の場合はアラートを発します。

このシステムでは、不安定なテストや同僚がしばしばがらくたをコミットする場合、多くの良いコミットが取り消されることに注意してください。あなたの同僚はあなたを嫌います。


私の恐怖物語が壊れたリポジトリを許可する問題を明らかにし、PRがリポジトリに直接プッシュされるのではなく、ワークキューにマージするためにキューに入れられ、一度に1つを統合する適切な継続的統合パイプラインを実装することを願っていますまたはロールアップにより):

  • リポジトリの先頭をローカルで取得する
  • プルリクエストを適用する
  • ビルドとテスト
  • 成功した場合はリポジトリにプッシュし、そうでなければ失敗としてマークする
  • 次のリクエストに移動する

両方を試してみると、これは厳密に優れています。


2
これは確かに正しい答えです-適切な解決策は、悪い変更がマスターブランチに到達するのを防ぐことです。
ダニエル・プライデン

ここでの問題は、質問者が「他の開発者と彼らの変更からあなたを隔離する」という述べられた費用が利益を上回ると信じていることだと思います。記載されているコストは、2人が長く分岐するほど重要な合併の危険性が増大することです。IMOでは、壊れたコードから隔離されることの利点は明らかです。質問者は、壊れたコードを簡単masterにプルできる「楽観的」戦略をとり、テストが失敗したらこの状況を修正したいと考えています。他のすべての人は、あなたが助言するように「悲観的な」戦略を取り、引き渡すコードのみを利用可能にします。
スティーブジェソップ

(「プル可能」とは、「プル」を意味します。masterこれは理想的には開発者が自由に実行できることですが、それを実現するmasterには、テストが合格する前に到着するコミットを遅らせる必要があります。チェリーピック未テストまたはテストして失敗したコードも問題なく、その意味でコードは「利用可能」であり、私が言及しているものではありません)
スティーブジェソップ

適切な解決策は、悪い変更がどのブランチにも届かないようにすることです。失敗したコミットは決して公開されるべきではありません。
マイルルーティング

5

これはベストプラクティスですか?それとも、開発者が修正するまでマスターを破損したままにするよりも問題があるかもしれませんか?

問題があります。「マスターHEADが壊れています。トップの変更を元に戻します」と決める人は、CIシステムが同じことをするのとはまったく異なります。

いくつかの欠点があります。

  • 自動化された反転プロセスのエラーは、リポジトリを台無しにします。

  • これは、単一のチェンジセット(最上部)がビルドを台無しにすることを想定しています(これは非現実的です)

  • メンテナーは、単に調査してコミットするよりも、問題を修正するために多くの作業を行う必要があります(逆の履歴を調べる必要もあります)

ブランチにコミットすると他の開発者とその変更から隔離され、ブランチを再統合して競合の可能性に対処する必要があるため、ブランチの概念は実際のCIに反すると信じています。

この信念(分岐対CI)は間違っています。ユニットテスト済みの変更セットのみをコミットする1つの安定したブランチを維持することを検討してください。残り(機能ブランチおよびローカルブランチ)は、各開発者の責任であり、CIポリシーの一部ではありません。

機能ブランチでは、したい他の開発者から隔離すること。これにより、次のことが可能になります。

  • 探索的コーディングを実行する

  • コードベースで実験する

  • 部分的なコミット(非機能コードを効果的にコミット)を実行してバックアップポイントを設定し(失敗した場合)、より意味のある変更履歴を作成し(コミットメッセージを使用)、作業をバックアップして完全に別のものに切り替えます(で「git commit && git checkout」を記述するのにかかる時間)

  • 時間がかかる低優先度のタスクを実行します(たとえば、データレイヤーの80クラスすべてを変更するリファクタリングを実行する場合:1日2回変更し、それらすべてを変更してコードをコンパイルします(ただし、これを実行できます)単一のコミットができるまで、誰にも影響を与えません)。

1人の開発者がそのブランチのビルドを中断する何かをコミットした場合、CIシステムはコミットを元に戻すべきですか?

すべきではありません。CIブランチで安定したコードをコミットするのは、自動化されたシステムではなく、コミッターの責任です。


2

マスターブランチを常に良好な状態に保つために、Gerrit + Jenkins環境を使用することをお勧めします。新しいコードをGerritにプッシュすると、Jenkinsジョブがトリガーされ、そのパッチ、ビルド、テストなどが取得されます。あなたのパッチやJenkinsが他の開発者の仕事を正常に完了した場合、Gerritはそのコードをmasterブランチにマージします。

@ brian-vandenbergによって記述された同様の環境

ブランチを良好な状態に保つことに加えて、コードの品質とソフトウェアに関する知識の共有を改善するコードレビューステップを追加します。

[1] Jenkins https://jenkins-ci.org/

[2] Gerrit https://www.gerritcodereview.com/


1

CIは、レポジトリのコミット履歴を変更しないでください。

ここでの正しい解決策は、テストと検証が行われていない場合、コミットをmasterブランチに追加しないことです。

機能ブランチで作業し、それらでCIを自動的に実行します。ビルドが失敗した場合、それらをマスターにマージしないでください。

featureブランチで実行し、ビルド中にmaster / integration / whateverをローカルブランチにマージしてからテストを実行することにより、それらが懸念される場合にマージをテストする追加ビルドを作成できます。


1
これは質問には一切答えません。機能ブランチでビルドが失敗した場合、CIはコミットを元に戻す必要がありますか?
カルロスキャンデロス

機能ブランチでビルドは成功したが、マージに失敗た場合はどうなりますか?
マチューM.

なつみ マージはコミットですが、マージするCIステップはビルドを元に戻す必要がありますか?
カルロスキャンデロス

@CarlosCampderrós:個人的には、コミットを取り消そうとする設定はありません。あまりにも複雑です。
マチューM.

コメントに対処しました。
デニス

1

ビルドサーバーにJenkinsを使用し、コミットをプッシュするためにゲートキーパーモデルを使用します(Jenkinsとコミットトリガーの組み合わせ(ピアレビューアが仕事を完了したことを確認する)がゲートキーパーです。

コミットはカールを介して間接的にJenkinsにプッシュされ、そこでマスターリポジトリのクローンを作成し、マージするコミットをプルして、必要なすべてのビルドを実行します(Linux / solarisの場合)。すべてのビルドが完了すると、コミットがプッシュされます。

これにより、これまでに説明したすべてではないにしても、多くの問題が回避されます。

  • 歴史改変
  • あなたが破損を修正しなければならない開発者なら、履歴を正しく取得する
  • 不安定な(壊れたビルドの形で)導入されない

また、単体テストが正常に完了するなど、他の要件を直接実施することもできます。


re:downvote、あなたは私の答えについて好きではなかったことにコメントしてくれませんか?
ブライアンヴァンデンバーグ

0

あなたの最後のコミットがビルドを壊したという自動メールを何回受け取りましたか?何回間違っていますか?しかし、今は本当にそれがあなたなのか、それとも同じ時間に別のコミットをした人なのかを確認する必要があります。それとも環境的なものだったのかもしれません。

システムが確実に知らない場合、私は確かにそれを自動化したくありません。


0

質問には欠陥があります。私はこの声明を尊重します

「ブランチの概念は実際のCIに反すると信じています。ブランチにコミットすると、他の開発者とその変更から隔離されるからです」

あなたがすべきことはこれらの手順です

  • 必要に応じてマスターで作業します(それで問題ありません。全員から変更を引き出し続けます)
  • 変更をマスターにコミットする前に、submit_XXXXXXでブランチを作成します
  • 自動ビルドにすべてのsubmit_XXXブランチビルドを選択させる
  • オプション1:ブレークを構築、またはブレークをマージ...変更が拒否され、マスターに到達しない
  • オプション2:ビルドは動作し、ジェンキンスはマスターをプッシュして更新します

次に、誰もが実際にマスターにコミットするのを防ぐためにgit commitフックを設定します。うまく機能します。...壊れたビルドやマスターからのコミットの取り消しもありません。

後で、ディーン

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