Theo tôi, đây là công cụ quan trọng bậc nhất trong những nhóm thực hành Agile với quy mô vừa tới lớn. CI (Continuous Integration – tích hợp liên tục) là một quy trình / công cụ giúp nhóm phát triển ngay lập tức nhận diện được những ảnh hưởng của một commit (một đoạn code hay một chức năng được thêm vào) với toàn bộ hệ thống nhằm phản ứng tức thì để đảm bảo toàn hệ thống hoạt động như mong đợi.
Khác với mô hình phát triển phần mềm truyền thống khi việc những module được thiết kế rất tỉ mỉ, phát triển độc lập và được thực hiện việc tích hợp vào giai đoạn cuối của việc phát triển nhằm phục vụ việc kiểm thử tích hợp và kiểm thử hệ thống; Agile coi trọng việc phát triển những chức năng liên tục theo kiểu “bồi đắp”. Cá biệt, trong Scrum, một vài phần tăng trưởng phải được chuyển giao sau mỗi Sprint – là những chức năng phải vận hành được bởi người dùng. Do đó, việc kiểm thử tích hợp và kiểm thử hệ thống diễn ra thường xuyên hơn (tối thiểu là trong mỗi Sprint), khiến việc thực hiện công việc tích hợp thủ công không khả thi. Ý tưởng về một công cụ thực hiện việc tích hợp vì thế đã xuất hiện.
Tuy vậy, chúng ta có thể hiểu CI là một quy trình, yêu cầu những thay đổi trên hệ thống phải được nhanh chóng nhận biết sự ảnh hưởng của chúng thông qua việc tích hợp sớm với hệ thống đang có, và thực hiện việc kiểm thử tích hợp và kiểm thử hệ thống. Lúc này CI liên quan mật thiết đến khái niệm “daily build”: toàn bộ mã nguồn của hệ thống phải được build hàng ngày nhằm nhận biết những lỗi tiềm năng và khắc phục sớm.
Tại sao phải là “daily build”? Hãy nhớ rằng, bất cứ thành viên nào trong nhóm phát triển đều có thể là một nhà thiết kế phần mềm, và một công việc của họ có thể ảnh hưởng rất nhiều tới hệ thống. Ví dụ, nhóm phát triển chạy nước rút với Sprint 2 tuần (10 ngày làm việc), với 2 lập trình viên cùng thực hiện việc thay đổi database nhằm hoàn thành 2 user story song song và mất 5 ngày thực hiện, việc tích hợp vào ngày thứ 6 với hàng tá xung đột về ràng buộc trong database có thể là một cơn ác mộng. Daily build chính là giải pháp để phát hiện xung đột xảy ra ngay từ ngày thứ 2 để nhóm phát triển có cách giải quyết thích hợp.
Nói chung, daily build giống như Daily Scrum về mặt mặt mã nguồn hệ thống. Trong Daily Scrum, nhóm thực hiện việc tích hợp, đồng bộ công việc với nhau cho các task hay user story. Trong daily build, nhóm thực hiện việc tích hợp, đồng bộ công việc với nhau cho mã nguồn và những thành phần liên quan như database, service… Xét cho cùng, kết quả của những task hay user story trên cũng là mã nguồn và những thành phần liên quan; bởi vậy, việc thực hiện Daily Scrum mà không có daily build giống như chúng ta đang đồng bộ những vấn đề “trên trời” mà không giải quyết những xung đột cụ thể.
Với nhiều nhóm thực hành Agile, daily build thậm chí là không đủ, nhóm cần tới commit build – thực hiện việc tích hợp, kiểm thử cho mỗi commit vào source code repository.
Một hệ thống CI thông thường thực hiện những tác vụ sau:
- Phát hiện thay đổi trong source code repository (xuất hiện commit mới)
- Phân tích chất lượng source code
- Thực hiện build
- Chạy toàn bộ unit test
- Chạy toàn bộ integration test
- Sinh ra những tạo tác có thể triển khai được, gọi là deployable artifact
- Có thể, deploy những artifact này và thực hiện những kiểm thử khác nếu cần
Nếu một trong những bước trên không thành công:
- Tuỳ thuộc vào mức độ nghiêm trọng, việc tích hợp có thể dừng lại hoặc đi tiếp
- Kết quả tích hợp được thông báo tới nhóm phát triển qua email, hệ thống chat. Thông qua sour code repository, CI có thể nhận biết cá nhân đã thực hiện việc commit gây ra lỗi trong việc tích hợp.
- Nhóm phát triển hoặc cá nhân thực hiện commit thực hiện sửa lỗi và commit
- CI phát hiện thay đổi trong source code repository và thực hiện lại những bước trên
Trong những tác vụ trên, tác vụ 1, 3, 6 thực sự rất dễ thực hiện và được hỗ trợ bởi hầu hết những công cụ CI hiện có trên thị trường. Những tác vụ 2, 4, 5 không đơn giản chỉ là sự hỗ trợ của công cụ, tư tưởng và cách thực hiện phía sau quan trọng hơn rất nhiều; chúng ta sẽ bàn về những vấn đề này ở những bài viết sau. Tác vụ 7 lại liên quan tới một hệ thống CD (Continuous Deployment – triển khai liên tục) với tư tưởng giống với CI nhưng dưới góc độ “triển khai” và lại phụ thuộc vào tần suất release của sản phẩm và độ phức tạp của môi trường nên không hẳn là một công cụ tiên quyết trong việc thực hành Agile.
Tuy vậy, nhiều nhóm thực hành Agile vẫn lựa chọn việc triển khai CI và CD đồng thời bởi một trong những best practice của CI là đảm bảo môi trường đồng nhất (hoặc gần giống nhất) giữa môi trường kiểm thử (tích hợp) và môi trường production.
Chúng ta dễ dàng nhận thấy ưu điểm của commit build so với daily build vì cô lập được thay đổi theo từng commit khiến việc xử lý xung đột đơn giản hơn. Tuy vậy, thời gian để CI thực hiện toàn bộ 7 tác vụ trên có thể rất nhiều với một số môi trường của dự án khiến việc này không khả thi; nên nhiều nhóm thực hành Agile vẫn lựa chọn daily build. Tôi là một người theo trường phái commit build và luôn cố gắng duy trì CI theo cách này. Với những dự án phức tạp, tôi thường sử dụng nhiều build agent để thực hiện việc tích hợp song song với những commit cùng thời điểm. Một giải pháp khác là, lược bỏ những tác vụ không cần thiết (ví dụ tác vụ 7) để vẫn thực hiện việc tích hợp với từng commit và thực hiện một “long build” vào cuối ngày.
Hiện nay có rất nhiều công cụ CI cho phép nhóm thực hành Agile lựa chọn với những tác vụ cơ bản như trên, phổ biến nhất có lẽ là Jenkins – hệ thống mã nguồn mở với rất nhiều plugin phù hợp với nhiều điều kiện hệ thống khác nhau. Tôi cũng là một kẻ hâm mộ Jenkins nhưng lại thường sử dụng những công cụ khác khi có thể, chỉ bởi giao diện của Jenkins thì quá tệ và cũng vì có nhiều người sử dụng quá.