Secara otomatis mengembalikan komit yang gagal membangun

44

Seorang kolega saya mengatakan kepada saya bahwa ia berpikir untuk membuat server CI kami untuk mengembalikan komit yang gagal dibangun, sehingga HEADin masterselalu stabil (seperti melewati setidaknya build).

Apakah ini praktik terbaik atau mungkin lebih bermasalah daripada hanya membiarkannya masterrusak sampai pengembang memperbaikinya?

Pemikiran saya adalah bahwa mengembalikan komit akan membuat tugas pembacaan komit dan perbaikan menjadi lebih kompleks (pengembang harus mengembalikan revert dan kemudian melakukan perbaikan, yang juga akan mengacaukan git log) dan kita harus meninggalkan komit dan kemudian komit memperbaiki. Meskipun saya melihat beberapa keuntungan dalam memiliki masterstabil, kembalinya komitmen yang gagal ini tidak meyakinkan saya.

edit: Tidak masalah apakah itu masteratau cabang pengembangan lainnya, tetapi pertanyaannya tetap sama: haruskah sistem CI mengembalikan komit yang gagal dibangun?

sunting (lenghty) lain: Ok, kami menggunakan gitcara yang aneh. Kami percaya bahwa konsep cabang bertentangan dengan CI nyata, karena berkomitmen untuk cabang mengisolasi Anda dari pengembang lain dan perubahannya, dan menambah waktu ketika Anda harus mengintegrasikan kembali cabang Anda dan menangani kemungkinan konflik. Jika semua orang berkomitmen untuk masterkonflik ini dikurangi seminimal mungkin dan setiap komit melewati semua tes.

Tentu saja, ini memaksa Anda untuk mendorong hanya stabil (atau Anda melanggar build) dan program lebih hati-hati untuk tidak merusak kompatibilitas atau melakukan fitur-toggling ketika memperkenalkan fitur baru.

Ada pengorbanan ketika melakukan CI ini atau itu, tetapi itu di luar ruang lingkup pertanyaan (lihat pertanyaan terkait untuk ini). Jika Anda suka, saya dapat menulis ulang pertanyaan: tim kecil pengembang bekerja sama dalam cabang fitur. Jika satu pengembang melakukan sesuatu yang merusak build untuk cabang itu, haruskah sistem CI mengembalikan komit atau tidak?

Carlos Campderrós
sumber
38
Gagal membangun seharusnya tidak pernah mencapai masterawal. Untuk itulah pengembangan & cabang fitur digunakan. Perubahan itu kemudian dalam sesuatu seperti cabang integrasi di mana Anda dapat menguji apakah semua fitur baru dari beberapa pengembang akan bekerja bersama dan hanya jika ini diuji dapat masuk ke master. Atau setidaknya itu satu alur kerja yang mungkin.
thorsten müller
1
@ thorstenmüller bayangkan kalau itu adalah cabang pengembangan yang digunakan semua pengembang. Haruskah sistem CI mengembalikan komitmen yang gagal dibangun?
Carlos Campderrós
7
Sepertinya Anda menggunakan git dengan cara yang aneh. Secara umum, orang harus mengerjakan repo mereka sendiri di cabang mereka sendiri, dan hanya mendorong ke CI utama setelah untuk membangun pribadi mereka diverifikasi bahwa perubahan itu OK.
Wilbert
4
> "konflik ini dikurangi seminimal"; Anda mendapatkan lebih sedikit konflik saat penggabungan, tetapi Anda mendapatkan lebih banyak masalah dengan penggabungan buruk. Solusinya adalah terus menggabungkan dari master ke cabang Anda sebagai bagian dari proses Anda, bukan untuk tidak cabang.
deworde
2
... Kenapa tidak membuatnya jadi build yang gagal tidak diterima menjadi master untuk memulai?
user253751

Jawaban:

56

Saya akan menentang melakukan ini karena alasan berikut:

  • Setiap kali Anda membuat alat otomatis untuk mengubah kode atas nama Anda , ada risiko bahwa itu akan salah, atau suatu situasi akan muncul ketika Anda membutuhkannya untuk berhenti melakukan perubahan itu (misalnya, versi terbaru Google Mock memiliki bug di dalamnya, jadi itu bukan kode Anda gagal) dan Anda harus membuang waktu untuk mengkonfigurasi ulang. Plus, selalu ada sedikit risiko bahwa build akan gagal karena bug dalam sistem build, daripada bug dalam kode Anda. Bagi saya, CI adalah tentang mendapatkan kepercayaan bahwa kode saya benar; ini hanya akan mengubahnya menjadi sumber masalah potensial bagi saya untuk dikhawatirkan.

  • Jenis-jenis bug yang merusak "build" haruslah merupakan kesalahan konyol yang hanya membutuhkan sedikit waktu untuk memperbaikinya (seperti yang Anda tunjukkan dalam komentar, ini berlaku untuk Anda). Jika bug yang lebih halus dan rumit secara teratur membuatnya menjadi master, maka solusi yang tepat adalah tidak "memperbaikinya lebih cepat", itu harus lebih berhati-hati ketika meninjau cabang fitur sebelum mereka bergabung.

  • Membiarkan master tidak dapat dibangun selama beberapa menit sementara bug diperbaiki dengan benar tidak melukai siapa pun. Ini tidak seperti CEO yang secara pribadi akan memeriksa master dan mempublikasikan kode langsung ke klien setiap saat secara acak (setidaknya, semoga bukan tanpa keterlibatan Anda). Dalam hal yang sangat tidak mungkin bahwa Anda perlu merilis sesuatu sebelum Anda dapat memperbaiki bug, maka Anda dapat dengan mudah membuat keputusan untuk mengembalikan secara manual sebelum menerbitkan.

Ixrec
sumber
1
Selain itu, hanya build yang berhasil yang dapat memicu penciptaan "build drop" yang dapat digunakan. Jika build gagal, seharusnya tidak ada drop build yang bisa digunakan, jadi tidak boleh ada risiko bahwa seseorang akan mempublikasikan kode buruk kepada klien.
Mark Freedman
1
pasti ada opsi lain yang digunakan dan lebih baik dari yang ini saya pikir dan dalam penggunaan berat (kami menggunakannya di twitter). jangan membuat build gagal pada master DAN kesalahan konyol masih mudah untuk diperbaiki. Lihat jawaban lengkap saya di bawah ini.
Dean Hiller
26

Mari kita menyetujui persyaratan terlebih dahulu.

Saya pribadi menggunakan istilah Continuous Build dan Continuous Integration untuk membedakan dua skenario yang berbeda:

  • Continuous Build: alat yang memeriksa secara berkala apakah repositori berubah sejak build terakhir, dan build / test jika berhasil.
  • Integrasi Berkelanjutan: alat yang mengambil Permintaan Tarik dan memvalidasinya terhadap kepala terbaru sebelum membuatnya terlihat.

Yang terakhir, Integrasi Berkelanjutan, berarti bahwa repositori yang dilindunginya selalu berwarna hijau 1 : benar-benar lebih baik.

Pertanyaan Anda hanya benar-benar masuk akal untuk Pembangunan Berkelanjutan, jadi saya akan menjawab dengan anggapan ini adalah pengaturan Anda.

1 : Penyebab lingkungan juga dapat mengacaukan bangunan, misalnya tes dengan tahun kode keras (2015) mungkin mulai gagal Januari 2016, disk bisa penuh, ... Dan tentu saja ada wabah tidak stabil tes. Saya dengan angkuh mengabaikan masalah-masalah itu di sini; kalau tidak kita tidak akan pernah sampai di mana pun.


Jika Anda memiliki pengaturan Continuous Build, Anda memang dapat mengotomatiskan pembalikan komit yang mungkin telah merusak build, namun ada beberapa seluk-beluk.

  • Anda tidak dapat benar-benar menghapus komit: rekan kerja lain mungkin sudah memeriksanya dan akan mendorong mereka kembali pada saat mereka mencoba untuk berkomitmen. Sebaliknya, pembalikan harus melakukan pembalikan terbalik . Oh, dan rekan kerja akan membenci Anda karena mengembalikan pekerjaan mereka ketika itu benar karena mereka harus menemukan cara untuk mendorongnya kembali ...
  • Anda tidak bisa benar-benar hanya menghapus komit terakhir (ini merupakan penggabungan), tetapi harus menghapus semua komit ... hingga titik tertentu. Sebagai contoh, komit bagus terakhir yang diketahui (waspadalah saat boot-strapping sistem).
  • Anda perlu memikirkan tentang penyebab eksternal (masalah lingkungan), dan menghindari pengaturan yang mengembalikan segalanya ke hari ke 0. Untungnya, kembali ke komitmen baik terakhir yang diketahui menghindari masalah ini.
  • Anda perlu berpikir bahwa bangunan baik terakhir yang diketahui mungkin tidak lagi dibangun (masalah lingkungan), dalam hal ini kemungkinan semua komitmen lebih lanjut akan dibatalkan. Idealnya, jika terjadi kegagalan, dan sebelum kembali, Anda harus memeriksa bangunan bagus yang terakhir diketahui, dan mengujinya kembali. Jika lewat, kembalikan, jika tidak, naikkan lansiran.

Perhatikan bahwa dengan sistem ini, jika ada tes yang tidak stabil atau rekan kerja yang sering melakukan omong kosong, banyak komitmen yang baik akan dibatalkan. Rekan kerja Anda kemudian akan membenci Anda.


Mudah-mudahan kisah horor saya telah mengungkap masalah-masalah yang memungkinkan repositori rusak dan Anda sekarang akan menerapkan pipa Continuous Integration yang tepat di mana PR tidak pernah langsung didorong ke repositori tetapi malah antri untuk bergabung dalam antrian kerja, dan terintegrasi satu per satu ( atau dengan roll-up):

  • ambil kepala repositori secara lokal
  • terapkan permintaan tarik
  • membangun dan menguji
  • jika berhasil, dorong ke repositori, jika tidak tandai gagal
  • pindah ke permintaan berikutnya

Setelah mencoba keduanya, ini benar-benar lebih baik.

Matthieu M.
sumber
2
Ini memang jawaban yang tepat - solusi yang tepat adalah untuk mencegah perubahan buruk dari tidak pernah mencapai cabang utama, tidak membiarkan mereka mendarat dan kemudian harus berurusan dengan mengembalikannya.
Daniel Pryden
Saya pikir masalahnya di sini adalah bahwa penanya percaya bahwa biaya yang dinyatakan untuk "mengisolasi Anda dari pengembang lain dan perubahannya" lebih besar daripada manfaatnya. Biaya yang dinyatakan adalah meningkatnya bahaya merger non-sepele semakin lama dua orang berbeda. IMO manfaat terisolasi dari kode yang rusak jelas. Penanya ingin mengambil strategi "optimis", di mana kode yang rusak tersedia sebentar masteruntuk ditarik, dan kemudian memperbaiki situasi ini setelah tes gagal. Semua orang mengambil strategi "pesimistis" seperti yang Anda sarankan, dan hanya membuat kode yang lewat tersedia untuk ditarik.
Steve Jessop
(di mana dengan "tersedia untuk menarik", maksud saya "menarik dari master", yang idealnya adalah sesuatu yang pengembang dapat lakukan sendiri, tetapi untuk mencapai itu Anda harus menunda melakukan kedatangan mastersebelum mereka diuji dan lulus. Jika seorang pengembang ingin cherry-pick kode yang belum diuji atau diuji-dan-gagal itu baik-baik saja, dan kode itu "tersedia" dalam pengertian itu, hanya saja bukan itu yang saya maksudkan)
Steve Jessop
Solusi yang tepat adalah untuk mencegah perubahan buruk dari tidak pernah mencapai cabang APAPUN. Komitmen yang gagal seharusnya tidak pernah dipublikasikan.
Miles Rout
5

Apakah ini praktik terbaik atau mungkin lebih bermasalah daripada hanya membiarkan masternya rusak sampai pengembang memperbaikinya?

Itu bermasalah. Seseorang yang memutuskan "KEPALA master rusak; Saya akan mengembalikan perubahan teratas" sama sekali berbeda dari sistem CI melakukan hal yang sama.

Berikut ini beberapa kelemahannya:

  • Kesalahan dalam proses pembalikan otomatis akan mengacaukan repositori;

  • ini mengasumsikan satu set perubahan (paling atas) mengacaukan build (yang tidak realistis)

  • Pemelihara akan memiliki lebih banyak pekerjaan yang harus dilakukan untuk memperbaiki masalah, dari sekedar investigasi dan komitmen (mereka juga harus melihat sejarah terbalik)

Kami percaya bahwa konsep cabang bertentangan dengan CI nyata, karena berkomitmen untuk cabang mengisolasi Anda dari pengembang lain dan perubahannya, dan menambah waktu ketika Anda harus mengintegrasikan kembali cabang Anda dan menangani kemungkinan konflik.

Keyakinan ini (cabang vs CI) salah. Pertimbangkan untuk mempertahankan satu cabang stabil, di mana Anda hanya melakukan perubahan pada unit yang diuji . Selebihnya (cabang fitur dan cabang lokal) harus menjadi tanggung jawab setiap pengembang dan bukan bagian dari kebijakan CI Anda dengan cara apa pun.

Di cabang fitur Anda ingin diisolasi dari pengembang lain. Ini memungkinkan Anda untuk:

  • melakukan pengkodean eksplorasi

  • bereksperimen dengan basis kode

  • melakukan sebagian komitmen (secara efektif melakukan kode yang tidak berfungsi) untuk mengatur poin cadangan (jika Anda mengacaukan), untuk membuat riwayat perubahan yang lebih bermakna (melalui pesan komit), dan untuk mencadangkan pekerjaan Anda dan beralih sepenuhnya ke hal lain (di waktu yang Anda perlukan untuk menulis "git commit && git checkout")

  • melakukan tugas dengan prioritas rendah yang membutuhkan waktu lama (mis. Anda ingin melakukan refactoring yang mengubah semua 80 kelas lapisan data: Anda mengubah dua per hari, sampai Anda mengubah semuanya sebagai kode yang dikompilasi (tetapi Anda dapat melakukan ini tanpa mempengaruhi siapa pun hingga Anda dapat membuat satu komit).

Jika satu pengembang melakukan sesuatu yang merusak build untuk cabang itu, haruskah sistem CI mengembalikan komit atau tidak?

Seharusnya tidak. Melakukan kode stabil pada cabang CI Anda adalah tanggung jawab dari pengangkat, bukan sistem otomatis.

utnapistim
sumber
2

Saya sarankan menggunakan lingkungan Gerrit + Jenkins untuk menjaga agar cabang master Anda selalu dalam kondisi yang baik. Orang mendorong kode baru mereka ke Gerrit yang memicu pekerjaan Jenkins untuk menarik tambalan itu, membangun, menguji, dan sebagainya. Jika pengembang lain menyukai tambalan Anda dan Jenkins menyelesaikan tugasnya dengan sukses, maka Gerrit akan menggabungkan potongan kode itu ke cabang master Anda.

Lingkungannya mirip dengan yang dijelaskan oleh @ brian-vandenberg

Selain menjaga agar cabang Anda tetap dalam kondisi yang baik, Anda juga menambahkan langkah peninjauan kode yang meningkatkan kualitas kode dan berbagi pengetahuan tentang perangkat lunak Anda.

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

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

Gustavo Coelho
sumber
1

CI tidak boleh mengubah riwayat commit dari repo.

Solusi yang benar di sini adalah tidak ada komitmen yang ditambahkan ke cabang master jika belum diuji dan diverifikasi.

Apakah Anda bekerja pada cabang fitur, memiliki CI berjalan secara otomatis pada mereka, dan jika membangun gagal, jangan gabungkan mereka menjadi master.

Anda bisa memiliki build tambahan yang menguji penggabungan jika itu menjadi masalah, dengan menjalankan pada cabang fitur, dan selama master penggabungan / integrasi / apa pun ke cabang lokal, kemudian menjalankan tes.

Daenyth
sumber
1
Ini tidak menjawab pertanyaan dengan cara apa pun. Jika build gagal di cabang fitur, haruskah CI mengembalikan komit?
Carlos Campderr
Bagaimana jika build berhasil di cabang fitur, tetapi gagal setelah penggabungan?
Matthieu M.
@ MatthieuM. merge adalah commit, haruskah langkah CI yang menggabungkan mengembalikan build?
Carlos Campderr
@ CarlosCampderrós: ​​Saya pribadi tidak akan pernah memiliki pengaturan yang mencoba mengembalikan komit; terlalu rumit.
Matthieu M.
Saya menyampaikan komentar.
Daenyth
1

Kami menggunakan Jenkins untuk server build kami dan menggunakan model gatekeeper untuk mendorong commit - di mana kombinasi Jenkins dan pemicu komit (yang memastikan peer reviewer telah melakukan pekerjaan mereka) adalah gatekeeper.

Komit didorong secara tidak langsung melalui ikal ke Jenkins, di mana klon master repo kemudian menarik komit untuk digabung dan melakukan semua build yang diperlukan (untuk Linux / solaris). Jika semua build selesai, komit akan didorong.

Ini menghindari banyak jika tidak semua masalah yang dibahas sejauh ini:

  • perubahan sejarah
  • mendapatkan riwayat yang benar jika Anda adalah dev yang harus memperbaiki kerusakannya
  • ketidakstabilan (dalam bentuk bangunan yang rusak) tidak pernah diperkenalkan

Itu juga memungkinkan kita untuk secara langsung menegakkan persyaratan lain seperti pengujian unit yang berhasil diselesaikan.

Brian Vandenberg
sumber
re: downvote, maukah Anda mengomentari apa yang tidak Anda sukai tentang jawaban saya?
Brian Vandenberg
0

Berapa kali Anda mendapatkan email otomatis yang mengatakan komit terakhir Anda merusak build? Berapa kali salah? Tetapi sekarang Anda harus memeriksa untuk melihat apakah itu benar-benar Anda, atau orang lain yang melakukan komitmen lain pada waktu yang bersamaan. Atau mungkin itu sesuatu yang ramah lingkungan.

Jika sistem tidak tahu pasti, maka saya pasti tidak ingin mengotomatiskannya.

Mohair
sumber
0

Pertanyaan yang diajukan cacat. Saya menghargai pernyataan ini

"Kami percaya bahwa konsep cabang bertentangan dengan CI nyata, karena berkomitmen untuk cabang mengisolasi Anda dari pengembang lain dan perubahannya"

Apa yang seharusnya Anda lakukan adalah langkah-langkah ini

  • matikan master jika Anda suka (itu baik-baik saja dan terus menarik perubahan dari semua orang) TETAPI JANGAN berkomitmen untuk menguasainya secara lokal
  • HANYA SEBELUM Anda akan mengkomit perubahan Anda untuk dikuasai, buat cabang dengan submit_XXXXXX
  • minta build otomatis Anda mengambil semua cabang subm_XXX build
  • Opsi 1: bangun istirahat, atau menggabungkan istirahat ... perubahan ditolak dan itu tidak pernah mendarat di master
  • Opsi 2: build works, jenkins mendorong master dan memperbaruinya

LALU, apa yang kita lakukan adalah meletakkan hook komit git dalam mencegah SEMUA ORANG dari benar-benar berkomitmen untuk menguasai. Ini bekerja dengan baik .... TIDAK ada bangunan yang rusak dan TIDAK juga mengembalikan komitmen dari master.

kemudian, Dean

Dean Hiller
sumber