Bagaimana kita menghindari pengembangan yang digerakkan oleh CI ...?

45

Saya sedang mengerjakan proyek open-source yang dipimpin oleh penelitian yang sangat besar, dengan sekelompok kontributor reguler lainnya. Karena proyek ini sekarang cukup besar, sebuah konsorsium (terdiri dari dua karyawan penuh waktu dan beberapa anggota) bertugas menjaga proyek, integrasi berkelanjutan (CI), dll. Mereka hanya tidak punya waktu untuk integrasi eksternal kontribusi sekalipun.

Proyek ini terdiri dari kerangka kerja "inti", dari sekitar setengah juta baris kode, sekelompok "plugin" yang dikelola oleh konsorsium, dan beberapa plugin eksternal, yang sebagian besar kami miliki bahkan tidak sadar.

Saat ini, CI kami membangun inti, dan plugin yang dikelola.

Salah satu masalah besar yang kita hadapi adalah sebagian besar kontributor (dan terutama kontributor sekali-sekali) tidak membangun 90% dari plugin yang dikelola, jadi ketika mereka mengusulkan perubahan refactor di inti (yang hari ini terjadi secara cukup teratur), mereka memeriksa kode yang dikompilasi pada mesin mereka sebelum membuat permintaan tarik pada GitHub.

Kode berfungsi, mereka senang, dan kemudian CI selesai membangun dan masalah mulai: kompilasi gagal dalam plugin yang dikelola konsorsium, bahwa kontributor tidak membangun di mesinnya.

Plugin itu mungkin memiliki ketergantungan pada pustaka pihak ketiga, seperti CUDA misalnya, dan pengguna tidak mau, tidak tahu bagaimana caranya, atau tidak bisa karena alasan perangkat keras, kompilasi plugin yang rusak itu.

Jadi - baik PR tetap aeternam iklan di limbo tidak pernah-to-be-digabung PR - Atau kontributor greps variabel yang diganti nama di sumber plugin rusak, perubahan kode, dorongan pada nya / cabang nya, menunggu CI untuk menyelesaikan kompilasi, biasanya mendapat lebih banyak kesalahan, dan mengulangi prosesnya sampai CI senang - Atau salah satu dari dua permanen yang sudah terlalu padat dalam konsorsium memberikan bantuan dan mencoba memperbaiki PR pada mesin mereka.

Tidak satu pun dari opsi-opsi itu yang layak, tetapi kami hanya tidak tahu bagaimana melakukannya secara berbeda. Pernahkah Anda dihadapkan pada situasi yang serupa dengan proyek Anda? Dan jika demikian, bagaimana Anda menangani masalah ini? Apakah ada solusi yang tidak saya lihat di sini?

lagarkane
sumber
84
Aturan paling atas dalam menyediakan API plugin untuk suatu sistem adalah tetap stabil atau paling tidak kompatibel. Perubahan ke inti tanpa sengaja mengubah API Plugin tidak akan pernah menghentikan kompilasi plugin apa pun (mungkin terjadi bahwa itu merusak fungsionalitas secara tidak sengaja, tetapi bukan kompilasi). Jika perubahan sederhana nama variabel di dalam inti dapat menyebabkan kompilasi plugin yang rusak , pemisahan antara plugin dan inti tampaknya benar-benar rusak.
Doc Brown
Martin Fowler's "Public versus Published Interfaces" mungkin merupakan bacaan yang bermanfaat.
Schwern
1
@KevinKrumwiede: Saya yakin mereka sudah tahu ini ;-) Jika Anda mengalami ketidakcocokan, saya cukup yakin mereka mengubah API dengan sengaja.
Doc Brown
3
Saya akan mengulangi pertanyaannya, karena itu benar-benar menyesatkan. Sesuatu seperti Bagaimana saya bisa mengelola PR ketika mereka melanggar CI kita saat ini? Tangkap situasi Anda dengan lebih baik.
bracco23
2
Seberapa sulit / rumit proses pembuatan / pengujian Anda? Seharusnya hanya masalah menjalankan satu perintah, atau mengklik satu tombol. Pada saat itu, menjadi masuk akal untuk mengharapkan pengguna menjalankan semua tes untuk diri mereka sendiri sebelum mengirimkan PR.
Alexander

Jawaban:

68

Pengembangan yang digerakkan oleh CI baik-baik saja! Ini jauh lebih baik daripada tidak menjalankan tes dan termasuk kode yang rusak! Namun, ada beberapa hal untuk mempermudah ini pada semua orang yang terlibat:

  • Tetapkan harapan: Memiliki dokumentasi kontribusi yang menjelaskan bahwa CI sering menemukan masalah tambahan, dan bahwa ini harus diperbaiki sebelum penggabungan. Mungkin jelaskan bahwa perubahan lokal yang lebih kecil cenderung bekerja dengan baik - jadi memecah perubahan besar menjadi banyak PR bisa masuk akal.

  • Dorong pengujian lokal: Memudahkan mengatur lingkungan pengujian untuk sistem Anda. Sebuah skrip yang memverifikasi bahwa semua dependensi telah diinstal? Wadah Docker yang siap digunakan? Gambar mesin virtual? Apakah pelari ujian Anda memiliki mekanisme yang memungkinkan diprioritaskannya tes yang lebih penting?

  • Jelaskan bagaimana menggunakan CI untuk diri mereka sendiri: Bagian dari frustrasi adalah bahwa umpan balik ini hanya datang setelah mengirimkan PR. Jika kontributor mengatur CI untuk repositori mereka sendiri, mereka akan mendapatkan umpan balik lebih awal - dan menghasilkan lebih sedikit pemberitahuan CI untuk orang lain.

  • Selesaikan semua PR, jika : Jika sesuatu tidak dapat digabungkan karena rusak, dan jika tidak ada kemajuan untuk menyelesaikan masalah, tutup saja. PR terbuka yang terabaikan ini hanya mengacaukan segalanya, dan umpan balik apa pun lebih baik daripada hanya mengabaikan masalah. Dimungkinkan untuk mengutarakan ini dengan sangat baik, dan membuatnya jelas bahwa tentu saja Anda akan senang untuk bergabung ketika masalah diperbaiki. (lihat juga: Seni Penutup oleh Jessie Frazelle , Praktik Terbaik untuk Pemelihara: Belajar mengatakan tidak )

    Juga pertimbangkan untuk membuat PR yang ditinggalkan ini dapat ditemukan sehingga orang lain dapat mengambilnya. Ini bahkan mungkin merupakan tugas yang baik untuk kontributor baru, jika masalah yang tersisa lebih mekanis dan tidak perlu akrab dengan sistem.

Untuk perspektif jangka panjang, perubahan itu tampaknya merusak fungsionalitas yang tidak terkait sehingga seringkali dapat berarti bahwa desain Anda saat ini agak bermasalah. Misalnya, apakah antarmuka plugin dengan benar merangkum internal Anda? C ++ membuatnya mudah untuk secara tidak sengaja membocorkan detail implementasi, tetapi juga memungkinkan untuk membuat abstraksi yang kuat yang sangat sulit untuk disalahgunakan. Anda tidak dapat mengubahnya dalam semalam, tetapi Anda dapat menggembalakan evolusi jangka panjang dari perangkat lunak menuju arsitektur yang kurang rapuh.

amon
sumber
13
"Ini PR terbuka yang terabaikan hanya mengacaukan segalanya" Saya berharap lebih banyak pemelihara yang memiliki sikap ini 😔
GammaGames
34

Membangun model plugin yang berkelanjutan mengharuskan kerangka kerja inti Anda mengekspos antarmuka yang stabil yang dapat diandalkan oleh plugin. Aturan utamanya adalah Anda dapat memperkenalkan antarmuka baru dari waktu ke waktu tetapi Anda tidak pernah dapat memodifikasi antarmuka yang sudah diterbitkan. Jika Anda mengikuti aturan ini, Anda bisa menolak pelaksanaan kerangka kerja inti semua yang Anda inginkan tanpa takut melanggar plugin, baik itu yang dikelola oleh konsorsium atau eksternal.

Dari apa yang Anda jelaskan, sepertinya Anda tidak memiliki antarmuka yang terdefinisi dengan baik, dan itu membuatnya sulit untuk mengetahui apakah perubahan akan merusak plugin. Berusahalah mendefinisikan antarmuka ini dan membuatnya eksplisit dalam basis kode Anda, sehingga kontributor akan tahu apa yang tidak boleh mereka modifikasi.

casablanca
sumber
20
CI harus memiliki tes otomatis. Jika Anda ingin memastikan plugin memiliki antarmuka yang sama, setiap plugin harus menyumbangkan tes yang mengekspresikan antarmuka yang mereka butuhkan. Datanglah dengan cara ini dan ketika antarmuka berubah, yang mana akan, Anda akan tahu plugin mana yang Anda hancurkan. Berikan saya tes ini untuk dijalankan secara lokal dan saya akan tahu apa yang saya langgar sebelum saya mengeluarkan PR.
candied_orange
1
@lagarkane definisi yang baik lebih merupakan masalah kebijakan daripada teknis. Ada perangkat lunak di luar sana yang seperti milik Anda, cukup abaikan perilaku sebelumnya dalam peningkatan. Perl5 tidak kompatibel dengan Perl6, Python2.7 tidak sepenuhnya kompatibel dengan Python3.4 dll. Lalu ada perangkat lunak yang apa pun yang terjadi masih mendukung kode lama. Anda masih dapat menjalankan hampir semua kode javascript yang ditulis untuk Netscape Navigator 4 di peramban modern. Bahasa pemrograman Tcl adalah backword yang kompatibel dengan cara kembali ke versi asli dll ...
slebetman
3
@lagarkane: Membentuk konsorsium adalah langkah ke arah yang benar, dan jika anggota inti memfokuskan energi mereka untuk mengukir antarmuka ini, maka Anda dapat memanfaatkan kekuatan PhD dan magang masa depan untuk menjaga proyek Anda tetap kuat sambil meminimalkan kerusakan. :)
casablanca
4
@Fattie: Itu bekerja untuk Apple karena mereka membangun produk yang menghadap ke konsumen yang sukses dan pengembang dipaksa untuk bermain bersama jika mereka ingin menjadi bagian dari itu. Tidak mungkin bahwa para pengembang itu benar-benar suka melanggar perubahan, dan itu jelas bukan model yang baik untuk proyek open-source.
casablanca
1
@casablanca garis keturunan MacOS dan WindowsOS sangat sukses. (Boleh dibilang, dua produk terbesar dalam dolar semata-mata dalam keberadaan manusia.) Selama beberapa dekade mereka memiliki pendekatan yang benar-benar berlawanan. Rupanya keduanya berhasil!
Fattie
8

Sejujurnya, saya tidak berpikir Anda bisa menangani ini dengan cara yang lebih baik - jika perubahan mengakibatkan rusaknya bagian proyek Anda , CI seharusnya gagal.

Apakah proyek Anda memiliki contributing.mdatau sesuatu yang serupa untuk membantu kontributor baru dan sesekali mempersiapkan kontribusi mereka? Apakah Anda memiliki daftar yang jelas, plugin mana yang merupakan bagian dari inti dan perlu tetap kompatibel?

Jika sulit untuk membangun semuanya di atas mesin karena ketergantungan dll Anda dapat berpikir tentang membuat gambar buruh pelabuhan yang siap pakai sebagai lingkungan pembangun yang digunakan oleh kontributor Anda.

jam
sumber
1
Terima kasih balasannya! Ya, kami memang memiliki pedoman kontribusi yang tersedia untuk umum, tetapi tidak mencantumkan plugin seperti yang Anda sarankan, yang sudah merupakan ide bagus. Membuat gambar buruh pelabuhan terdengar seperti perbaikan besar untuk proses kontribusi saat ini! Terima kasih atas masukannya
lagarkane
8

jadi ketika mereka mengusulkan perubahan refactoring di inti (yang hari ini terjadi secara cukup teratur), mereka memeriksa bahwa kode dikompilasi pada mesin mereka sebelum membuat permintaan tarikan pada github.

Jadi saya pikir di sinilah gaya longgar proyek open source dapat jatuh; sebagian besar proyek yang dikelola secara terpusat mewaspadai refactoring inti, terutama ketika melintasi batas API. Jika mereka melakukan refactor terhadap batas API, biasanya merupakan "big bang" di mana semua perubahan dijadwalkan sekaligus dengan peningkatan ke versi utama API, dan API lama dipertahankan.

Saya akan mengusulkan aturan "semua perubahan API harus direncanakan terlebih dahulu": jika seorang PR masuk yang membuat perubahan yang tidak kompatibel ke belakang ke API, dari seseorang yang belum pernah berhubungan dengan pengelola untuk menyetujui pendekatan mereka sebelumnya, itu hanya akan ditutup dan pengirim menyerahkan pada aturan.

Anda juga akan membutuhkan versi eksplisit dari plugin API. Ini memungkinkan Anda untuk mengembangkan v2 sementara semua plugin v1 terus membangun dan bekerja.

Saya juga akan mempertanyakan lebih banyak mengapa begitu banyak inti refactoring dan perubahan API sedang dibuat. Apakah mereka benar-benar perlu atau hanya orang yang memaksakan selera pribadi mereka pada proyek?

pjc50
sumber
2

Kedengarannya seperti proses CI harus lebih ketat, lebih komprehensif dan lebih terlihat oleh kontributor sebelum mereka menaikkan PR. Sebagai contoh, BitBucket memiliki fitur jalur pipa yang memungkinkan ini, di mana Anda memberikannya file yang menentukan dalam kode proses pembangunan CI, dan jika gagal, cabang dicegah dari digabung.

Terlepas dari teknologinya, menyediakan pemuatan otomatis ketika kontributor mendorong ke cabang akan memberi mereka umpan balik yang lebih cepat dari apa yang harus diwaspadai yang harus diperhatikan ketika melakukan perubahan dan akan mengarah pada PR yang tidak perlu memperbaiki setelah fakta.

Masalah desain akan baik untuk diperbaiki, tetapi ortogonal untuk masalah ini.

Nathan Adams
sumber
2

Kode berfungsi, mereka senang, dan kemudian CI selesai membangun dan masalah mulai: kompilasi gagal dalam plugin yang dikelola konsorsium, bahwa kontributor tidak membangun di mesinnya.

Plugin itu mungkin memiliki dependensi pada pustaka pihak ketiga, seperti CUDA misalnya, dan pengguna tidak mau, tidak tahu bagaimana caranya, atau tidak bisa karena alasan perangkat keras, kompilasi plugin yang rusak itu.

Solusi Anda sederhana: turunkan penghalang kontribusi .

Cara paling sederhana untuk (1) mempercepat siklus edit-kompilasi-uji dan (2) perbedaan lingkungan yang halus adalah menyediakan server-server pembangun :

  • Ambil mesin gemuk: 24, 48 atau 96 core, 2GB RAM / core, SSD, untuk mempercepat kompilasi.
  • Pastikan mereka memiliki perangkat keras yang tepat: FPGA, Kartu Grafis, apa pun yang diperlukan.
  • Buat gambar Docker dengan semua pustaka perangkat lunak yang diperlukan yang sudah diinstal sebelumnya.

Dan kemudian buka server pembangun itu untuk kontributor. Mereka harus dapat login jarak jauh di gambar Docker baru, dan mengedit-kompilasi-uji jarak jauh pada mesin ini.

Kemudian:

  • Mereka tidak memiliki alasan untuk tidak membangun / menguji plugin yang dikelola: mereka memiliki semuanya tersedia.
  • Mereka tidak harus menunggu umpan balik yang panjang dengan PR berbasis CI: mereka memiliki kompilasi tambahan, dan kemampuan untuk debug (daripada menebak).

Secara umum, build server dapat dibagikan di beberapa kontributor, namun ketika perangkat keras khusus terlibat, kontributor harus menggunakan perangkat tersebut sendiri.


Sumber: mengerjakan perangkat lunak menggunakan FPGA, mengingat harga beast, dan beragam model yang kami butuhkan, Anda tidak menemukan setiap model FPGA diinstal pada mesin setiap pengembang.

Matthieu M.
sumber
1

Jika berkontribusi pada inti tanpa mengubah kontrak apa pun dapat merusak perangkat lunak dependen, ini menunjukkan bahwa:

  • Kontrak antarmuka Anda mungkin ambigu. Mungkin menambahkan atribut pada fungsi dan parameter fungsi Anda akan membantu dalam mengungkap kendala tambahan untuk kode klien untuk membuat kontrak lebih jelas. Atau jika Anda menerapkan perubahan yang melanggar kontrak, mungkin mengadopsi versi semantik dapat membantu.
  • Tes unit tidak cukup mencakup skenario panggilan yang mungkin.

Salah satu masalah seharusnya mudah dipecahkan, tetapi Anda menyebutkan tim inti mungkin tidak memiliki kapasitas untuk melakukannya. Salah satu opsi adalah meminta bantuan komunitas dalam menangani masalah ini.

jcayzac
sumber
1

Sepertinya tidak ada orang lain yang mengangkat ini sebagai solusi potensial.

  • daftar semua plugin yang dapat Anda akses.
  • jalankan semua tes yang ditentukan oleh plugin ini
  • catat semua permintaan / tanggapan / interaksi antara inti dan semua plugin
  • simpan rekaman itu, ini sekarang tes kompatibilitas kasar.

Saat mengembangkan inti, dorong pengembang untuk menjalankan tes kompatibilitas ini. Jika gagal, jangan check-in.

Ini tidak akan 100% memastikan kompatibilitas tetapi akan menangkap lebih banyak masalah dan lebih awal.

Manfaat kedua adalah bahwa rekaman ini dapat menyoroti antarmuka mana yang aktif digunakan, dan fitur apa yang sedang aktif digunakan.

Kain0_0
sumber
0

Saya mengalami kesulitan memahami situasinya: CI hanya membangun satu cabang?

Apakah ada alasan Anda tidak dapat membangun lebih dari satu cabang dengan CI?

Solusi paling sederhana untuk masalah ini adalah dengan memungkinkan kontributor untuk menjalankan pembangunan CI pada cabang fitur-nya .

Maka Anda hanya perlu membangun CI yang sukses di cabang fitur agar permintaan tarik cabang itu dapat diterima.

Kyralessa
sumber
Ini sepertinya meringkas masalah ini.
Fattie
1
Pertanyaannya mengatakan "Atau kontributor [...] mengubah kode, mendorong cabangnya, menunggu CI menyelesaikan kompilasi, biasanya mendapat lebih banyak kesalahan, dan mengulangi prosesnya sampai CI bahagia" - jadi saya pikir ini memang sudah demikian, tapi masalahnya agak menyakitkan untuk dikembangkan dengan siklus edit-debug yang begitu panjang.
npostavs
@npostavs Terima kasih, saya rasa itulah yang saya lewatkan pertama atau dua kali saya membacanya. Meski begitu ... kurasa aku tidak masalah. Ada banyak dependensi, mereka tidak dapat rusak, sehingga seorang kontributor perlu tetap kompatibel dengan semuanya. Itulah sifat dari perangkat lunak besar. Tentu saja pekerjaan dapat dilakukan untuk membuat pembangunan lebih cepat, mungkin, tetapi sebaliknya, jalan pintas apa yang mungkin ada?
Kyralessa