Làm thế nào để chúng ta tránh được sự phát triển dựa trên CI?


45

Tôi đang làm việc trong một dự án nguồn mở do nghiên cứu rất lớn, với một loạt những người đóng góp thường xuyên khác. Bởi vì dự án bây giờ khá lớn, một tập đoàn (gồm hai nhân viên toàn thời gian và một vài thành viên) chịu trách nhiệm duy trì dự án, tích hợp liên tục (CI), v.v. Họ chỉ không có thời gian để tích hợp bên ngoài đóng góp mặc dù.

Dự án này bao gồm một khung "cốt lõi", gồm khoảng một nửa triệu dòng mã, một loạt các "plugin" được duy trì bởi tập đoàn và một số plugin bên ngoài, hầu hết chúng tôi đều phát sinh ' thậm chí nhận thức được.

Hiện tại, CI của chúng tôi xây dựng lõi và các plugin được duy trì.

Một trong những vấn đề lớn mà chúng tôi gặp phải là hầu hết những người đóng góp (và đặc biệt là những người thỉnh thoảng) không xây dựng 90% các plugin được duy trì, vì vậy khi họ đề xuất tái cấu trúc các thay đổi trong lõi (ngày nay xảy ra khá thường xuyên), họ đã kiểm tra xem mã biên dịch trên máy của họ trước khi đưa ra yêu cầu kéo trên GitHub.

Mã hoạt động, họ rất vui, và sau đó CI hoàn thành việc xây dựng và các vấn đề bắt đầu: quá trình biên dịch thất bại trong một plugin được duy trì bởi tập đoàn, mà người đóng góp không xây dựng trên máy của anh ấy / cô ấy.

Plugin đó có thể có sự phụ thuộc vào các thư viện của bên thứ ba, chẳng hạn như CUDA và người dùng không muốn, không biết cách hoặc đơn giản là không thể vì lý do phần cứng, biên dịch plugin bị hỏng đó.

Vì vậy, sau đó - PR vẫn giữ nguyên thông tin quảng cáo trong tình trạng không bao giờ được hợp nhất PR - Hoặc người đóng góp greps biến đổi tên trong nguồn của plugin bị hỏng, thay đổi mã, đẩy vào chi nhánh của mình, chờ đợi CI hoàn thành quá trình biên dịch, thường gặp nhiều lỗi hơn và nhắc lại quy trình cho đến khi CI hài lòng - Hoặc một trong hai nhân vật đã đặt trước quá nhiều trong tập đoàn đưa ra một bàn tay và cố gắng sửa PR trên máy của họ.

Không có lựa chọn nào trong số đó là khả thi, nhưng chúng tôi không biết làm thế nào để làm điều đó khác đi. Bạn đã bao giờ phải đối mặt với một tình huống tương tự của các dự án của bạn? Và nếu vậy, làm thế nào bạn xử lý vấn đề này? Có một giải pháp tôi không thấy ở đây?


84
Nguyên tắc hàng đầu trong việc cung cấp API plugin cho hệ thống là nó được giữ ổn định hoặc ít nhất là tương thích ngược. Thay đổi lõi mà không cố ý thay đổi API Plugin sẽ không bao giờ phá vỡ quá trình biên dịch của bất kỳ plugin nào (có thể xảy ra do nó phá vỡ chức năng một cách tình cờ, nhưng không phải là quá trình biên dịch). Nếu một thay đổi đơn giản của một tên biến bên trong lõi có thể dẫn đến việc biên dịch plugin bị hỏng , thì sự tách biệt giữa các plugin và lõi dường như bị phá vỡ hoàn toàn.
Doc Brown


1
@KevinKrumwiede: Tôi chắc chắn họ đã biết điều này rồi ;-) Nếu bạn gặp phải sự không tương thích, tôi chắc chắn rằng họ đã thay đổi API có chủ ý.
Doc Brown

3
Tôi sẽ viết lại câu hỏi, vì nó thực sự sai lệch. Một cái gì đó như Làm thế nào tôi có thể quản lý PR khi họ phá vỡ CI hiện tại của chúng tôi? nắm bắt tốt hơn tình hình của bạn tôi nghĩ.
bracco23

2
Quá trình xây dựng / kiểm tra của bạn khó khăn / phức tạp như thế nào? Nó chỉ là vấn đề chạy một lệnh hoặc nhấp vào một nút duy nhất. Tại thời điểm đó, sẽ trở nên hợp lý khi mong đợi người dùng tự chạy tất cả các thử nghiệm trước khi gửi PR.
Alexander

Câu trả lời:


68

Phát triển theo định hướng CI là tốt! Điều này tốt hơn rất nhiều so với việc không chạy thử nghiệm và bao gồm cả mã bị hỏng! Tuy nhiên, có một vài điều giúp mọi người tham gia dễ dàng hơn:

  • Đặt kỳ vọng: Có tài liệu đóng góp giải thích rằng CI thường tìm thấy các vấn đề bổ sung và những vấn đề này sẽ phải được khắc phục trước khi hợp nhất. Có lẽ giải thích rằng những thay đổi nhỏ, cục bộ có nhiều khả năng hoạt động tốt - vì vậy việc chia một thay đổi lớn thành nhiều PR có thể hợp lý.

  • Khuyến khích thử nghiệm cục bộ: Giúp dễ dàng thiết lập môi trường thử nghiệm cho hệ thống của bạn. Một kịch bản xác minh rằng tất cả các phụ thuộc đã được cài đặt? Một container Docker đã sẵn sàng để đi? Một hình ảnh máy ảo? Người chạy thử của bạn có các cơ chế cho phép các bài kiểm tra quan trọng hơn được ưu tiên không?

  • Giải thích cách sử dụng CI cho bản thân: Một phần của sự thất vọng là phản hồi này chỉ xuất hiện sau khi gửi PR. Nếu những người đóng góp thiết lập CI cho kho lưu trữ của riêng họ, họ sẽ nhận được phản hồi sớm hơn - và tạo ra ít thông báo CI hơn cho người khác.

  • Giải quyết tất cả các PR, bằng một trong hai cách: Nếu một cái gì đó không thể được hợp nhất vì nó bị hỏng và nếu không có tiến triển nào trong việc khắc phục sự cố, chỉ cần đóng nó. Những PR mở bị bỏ rơi này chỉ làm lộn xộn mọi thứ, và bất kỳ phản hồi nào tốt hơn là bỏ qua vấn đề. Có thể diễn đạt điều này rất độc đáo, và làm rõ rằng tất nhiên bạn sẽ vui lòng hợp nhất khi các vấn đề được khắc phục. (xem thêm: Nghệ thuật kết thúc của Jessie Frazelle , Thực tiễn tốt nhất cho người duy trì: Học cách nói không )

    Cũng xem xét làm cho những PR bị bỏ rơi này có thể được khám phá để người khác có thể nhận chúng. Điều này thậm chí có thể là một nhiệm vụ tốt cho những người đóng góp mới, nếu các vấn đề còn lại mang tính máy móc hơn và không cần làm quen sâu sắc với hệ thống.

Đối với viễn cảnh dài hạn, những thay đổi đó dường như phá vỡ chức năng không liên quan nên thường có thể có nghĩa là thiết kế hiện tại của bạn có một chút vấn đề. Ví dụ, các giao diện plugin có đóng gói đúng cách các phần bên trong lõi của bạn không? C ++ giúp dễ dàng vô tình rò rỉ chi tiết triển khai, nhưng cũng có thể tạo ra sự trừu tượng mạnh mẽ rất khó sử dụng. Bạn không thể thay đổi điều này qua đêm, nhưng bạn có thể hướng dẫn sự phát triển lâu dài của phần mềm theo hướng kiến ​​trúc ít mong manh hơn.


13
"Những PR mở bị bỏ rơi này chỉ làm xáo trộn mọi thứ" Tôi ước gì nhiều người bảo trì có thái độ này
GammaGames

34

Xây dựng một mô hình plugin bền vững đòi hỏi khung công tác cốt lõi của bạn phải có giao diện ổn định mà các plugin có thể dựa vào. Nguyên tắc vàng là bạn có thể giới thiệu các giao diện mới theo thời gian nhưng bạn không bao giờ có thể sửa đổi giao diện đã được xuất bản. Nếu bạn tuân theo quy tắc này, bạn có thể cấu trúc lại việc thực hiện khung cốt lõi mà bạn muốn mà không sợ vô tình phá vỡ các plugin, cho dù đó là một tập đoàn được duy trì hay một bên ngoài.

Từ những gì bạn mô tả, có vẻ như bạn không có giao diện được xác định rõ và điều đó gây khó khăn cho việc thay đổi có làm hỏng plugin hay không. Làm việc theo hướng xác định giao diện này và làm cho nó rõ ràng trong cơ sở mã của bạn, để những người đóng góp sẽ biết những gì họ không nên sửa đổi.


20
CI nên có các bài kiểm tra tự động. Nếu bạn muốn đảm bảo các plugin có cùng giao diện, mọi plugin nên đóng góp các bài kiểm tra thể hiện giao diện mà chúng cần. Đến với nó theo cách này và khi giao diện thay đổi, nó sẽ, bạn sẽ biết plugin nào bạn đang phá vỡ. Đưa cho tôi các bài kiểm tra này để chạy cục bộ và tôi sẽ biết những gì tôi vi phạm trước khi tôi thực hiện PR.
candied_orange

1
@lagarkane xác định rõ là một vấn đề chính sách hơn là kỹ thuật. Có những phần mềm giống như của bạn, chỉ cần từ bỏ hành vi trước đó trong một bản nâng cấp. Perl5 không tương thích với Perl6, Python2.7 không tương thích hoàn toàn với Python3.4, v.v ... Sau đó, có những phần mềm dù có bất cứ điều gì xảy ra vẫn hỗ trợ mã cũ. Bạn vẫn có thể chạy gần như tất cả mã javascript được viết cho Netscape Navigator 4 trong các trình duyệt hiện đại. Ngôn ngữ lập trình Tcl là cách tương thích backwords trở lại phiên bản gốc, v.v ...
slebetman

3
@lagarkane: Thành lập tập đoàn là một bước đi đúng hướng và nếu các thành viên cốt lõi tập trung năng lượng của họ vào việc khắc phục các giao diện này, thì bạn có thể khai thác sức mạnh của các tiến sĩ và thực tập sinh trong tương lai để giữ cho dự án của bạn phát triển mạnh mẽ trong khi giảm thiểu vỡ. :)
casifer

4
@Fattie: Điều đó hiệu quả với Apple vì họ xây dựng các sản phẩm thành công cho người tiêu dùng và các nhà phát triển buộc phải chơi cùng nếu họ muốn trở thành một phần của nó. Không chắc là các nhà phát triển đó thực sự thích phá vỡ các thay đổi và chắc chắn đó không phải là một mô hình tốt cho một dự án nguồn mở.
casablanca

1
@casTHER cả dòng MacOS và WindowsOS đều rất thành công. (Có thể cho rằng, hai sản phẩm lớn nhất về đồng đô la trong sự tồn tại của con người.) Trong nhiều thập kỷ, chúng có những cách tiếp cận hoàn toàn trái ngược. Rõ ràng cả hai đều thành công!
Fattie

8

Thành thật mà nói, tôi không nghĩ bạn có thể xử lý việc này theo cách tốt hơn - nếu thay đổi dẫn đến phá vỡ các phần được bảo trì trong dự án của bạn thì CI sẽ thất bại.

Dự án của bạn có một contributing.mdhoặc một cái gì đó tương tự để giúp những người đóng góp mới và thỉnh thoảng chuẩn bị đóng góp của họ? Bạn có một danh sách rõ ràng, plugin nào là một phần cốt lõi và cần phải tương thích?

Nếu khó xây dựng mọi thứ trên máy do phụ thuộc, v.v. bạn có thể nghĩ đến việc tạo hình ảnh docker sẵn sàng sử dụng làm môi trường xây dựng cho những người đóng góp của bạn sử dụng.


1
Cảm ơn vi đa trả lơi! Có, chúng tôi có các hướng dẫn đóng góp có sẵn công khai, nhưng nó không liệt kê các plugin như bạn đề xuất, đó sẽ là một ý tưởng tốt. Làm cho hình ảnh docker nghe có vẻ như là một cải tiến tuyệt vời cho quá trình đóng góp hiện tại! Cảm ơn về đầu vào
lagarkane

8

Vì vậy, khi họ đề xuất tái cấu trúc các thay đổi trong lõi (ngày nay xảy ra khá thường xuyên), họ đã kiểm tra xem mã có biên dịch trên máy của họ trước khi đưa ra yêu cầu kéo trên github không.

Vì vậy, tôi nghĩ rằng đây là nơi mà phong cách lỏng lẻo của các dự án nguồn mở có thể rơi xuống; hầu hết các dự án được tổ chức tập trung đều cảnh giác với việc tái cấu trúc cốt lõi, đặc biệt là khi nó vượt qua ranh giới API. Nếu họ tái cấu trúc một ranh giới API, thì đó thường là một "vụ nổ lớn" trong đó tất cả các thay đổi được lên lịch cùng một lúc với sự gia tăng của phiên bản chính của API API cũ được duy trì.

Tôi sẽ đề xuất một quy tắc "tất cả các thay đổi API phải được lên kế hoạch trước": nếu PR xuất hiện làm thay đổi ngược không tương thích với API, từ một người không tiếp xúc với các nhà bảo trì để đồng ý trước cách tiếp cận của họ, thì đó là chỉ đơn giản là đóng cửa và người nộp chỉ vào quy tắc.

Bạn cũng sẽ cần phiên bản rõ ràng của API plugin. Điều này cho phép bạn phát triển v2 trong khi tất cả các plugin v1 tiếp tục xây dựng và hoạt động.

Tôi cũng sẽ hỏi thêm một chút tại sao rất nhiều tái cấu trúc cốt lõi và thay đổi API đang được thực hiện. Họ có thực sự cần thiết hay chỉ là mọi người áp đặt sở thích cá nhân của họ vào dự án?


2

Âm thanh như quy trình CI cần phải chặt chẽ hơn, toàn diện hơn và dễ thấy hơn đối với những người đóng góp trước khi họ đưa ra PR. Ví dụ, BitBucket có một tính năng đường ống cho phép điều này, trong đó bạn cung cấp cho nó một tệp xác định trong mã quy trình xây dựng CI và nếu thất bại, nhánh sẽ bị ngăn không được hợp nhất.

Bất kể công nghệ nào, việc cung cấp các bản dựng tự động khi người đóng góp chuyển đến chi nhánh sẽ cung cấp cho họ thông tin phản hồi nhanh hơn nhiều về những vấn đề cần chú ý khi thực hiện thay đổi và sẽ dẫn đến PR không cần sửa chữa sau thực tế.

Các vấn đề thiết kế sẽ là tốt để khắc phục, nhưng là trực giao cho vấn đề này.


2

Mã hoạt động, họ rất vui, và sau đó CI hoàn thành việc xây dựng và các vấn đề bắt đầu: quá trình biên dịch thất bại trong một plugin được duy trì bởi tập đoàn, mà người đóng góp không xây dựng trên máy của anh ấy / cô ấy.

Plugin đó có thể có sự phụ thuộc vào các thư viện của bên thứ ba, chẳng hạn như CUDA và người dùng không muốn, không biết cách hoặc đơn giản là không thể vì lý do phần cứng, biên dịch plugin bị hỏng đó.

Giải pháp của bạn rất đơn giản: hạ thấp rào cản đóng góp .

Cách đơn giản nhất để (1) tăng tốc chu trình kiểm tra biên dịch-biên dịch và (2) sự khác biệt về môi trường trơn tru là cung cấp các máy chủ xây dựng :

  • Chọn các máy mạnh mẽ: 24, 48 hoặc 96 lõi, RAM / lõi 2GB, SSD, để tăng tốc độ biên dịch.
  • Đảm bảo họ có phần cứng phù hợp: FPGA, Card đồ họa, bất cứ thứ gì cần thiết.
  • Tạo một hình ảnh Docker với tất cả các thư viện phần mềm cần thiết được cài đặt sẵn.

Và sau đó mở những máy chủ xây dựng cho những người đóng góp. Họ có thể đăng nhập từ xa trong hình ảnh Docker mới và kiểm tra biên dịch từ xa trên máy này.

Sau đó:

  • Họ không có lý do gì để không xây dựng / kiểm tra các plugin được duy trì: họ có sẵn mọi thứ.
  • Họ không phải chờ phản hồi dài với các PR do CI điều khiển: họ có khả năng biên dịch gia tăng và khả năng gỡ lỗi (thay vì đoán).

Nói chung, các máy chủ xây dựng có thể được chia sẻ trên nhiều người đóng góp, tuy nhiên khi có các thiết bị ngoại vi phần cứng đặc biệt thì có thể cần một người đóng góp sử dụng thiết bị ngoại vi nói trên.


Nguồn: làm việc trên phần mềm bằng cách sử dụng các GPU, với giá của các quái thú và nhiều loại mô hình chúng tôi cần, bạn không tìm thấy từng mô hình của FPGA được cài đặt trên mỗi máy của nhà phát triển.


1

Nếu đóng góp vào cốt lõi mà không thay đổi bất kỳ hợp đồng nào có thể phá vỡ phần mềm phụ thuộc, điều đó cho thấy rằng:

  • Các hợp đồng của giao diện của bạn có thể mơ hồ. Có lẽ việc thêm các thuộc tính trên các hàm và tham số hàm của bạn sẽ giúp phơi bày các ràng buộc bổ sung cho mã máy khách để làm cho các hợp đồng rõ ràng hơn. Hoặc nếu bạn đang áp dụng các thay đổi vi phạm hợp đồng, có thể áp dụng phiên bản ngữ nghĩa có thể giúp ích.
  • Các bài kiểm tra đơn vị không bao gồm đủ các tình huống cuộc gọi có thể.

Vấn đề là dễ giải quyết, nhưng bạn đề cập đến nhóm nòng cốt có thể không có khả năng để làm điều đó. Một lựa chọn sẽ là yêu cầu cộng đồng giúp đỡ giải quyết vấn đề.


1

Không ai khác dường như đã nêu ra điều này như một giải pháp tiềm năng.

  • liệt kê tất cả các plugin mà bạn có thể truy cập.
  • chạy tất cả các bài kiểm tra mà các plugin này xác định
  • ghi lại tất cả yêu cầu / phản hồi / tương tác giữa lõi và tất cả các plugin
  • lưu trữ những bản ghi âm, đây là những thử nghiệm tương thích thô.

Khi phát triển lõi, khuyến khích các nhà phát triển chạy các thử nghiệm tương thích này. Nếu họ thất bại không kiểm tra.

Điều này sẽ không đảm bảo 100% khả năng tương thích nhưng nó sẽ nắm bắt được nhiều vấn đề hơn và sớm hơn.

Một lợi ích thứ hai là những bản ghi này có thể làm nổi bật những giao diện nào được sử dụng tích cực và những tính năng nào đang được sử dụng tích cực.


0

Tôi gặp khó khăn trong việc hiểu tình hình như hiện tại: CI chỉ xây dựng một chi nhánh?

Có lý do nào bạn không thể xây dựng nhiều hơn một chi nhánh với CI không?

Giải pháp đơn giản nhất cho vấn đề này là làm cho bất kỳ người đóng góp nào có thể chạy bản dựng CI trên nhánh tính năng của anh ấy / cô ấy .

Sau đó, bạn chỉ cần yêu cầu xây dựng CI thành công trên nhánh tính năng để yêu cầu kéo của nhánh đó được chấp nhận.


Điều này dường như tổng hợp vấn đề.
Fattie

1
Câu hỏi cho biết "Hoặc người đóng góp [...] thay đổi mã, đẩy chi nhánh của anh ấy / cô ấy, đợi CI hoàn thành biên dịch, thường nhận được nhiều lỗi hơn và nhắc lại quy trình cho đến khi CI hài lòng" - vì vậy tôi nghĩ rằng đã là trường hợp, nhưng vấn đề là nó hơi khó để phát triển với chu kỳ sửa lỗi dài như vậy.
npostavs

@npostavs Cảm ơn, tôi đoán đó là những gì tôi đã bỏ lỡ lần đầu tiên hoặc hai lần tôi đọc nó. Mặc dù vậy ... tôi đoán tôi không có vẻ gì là vấn đề. Có rất nhiều phụ thuộc, chúng không thể bị phá vỡ, vì vậy một người đóng góp cần phải tương thích với tất cả chúng. Đó là bản chất của phần mềm lớn. Chắc chắn công việc có thể được thực hiện để làm cho việc xây dựng nhanh hơn, có lẽ, nhưng nếu không, lối tắt nào có thể có?
Kyralessa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.