sürekli entegrasyon ile büyüyen, çeşitli bir kod tabanının korunması


10

Sürekli bir entegrasyon kurulumunun felsefesi ve tasarımı konusunda yardıma ihtiyacım var.

Mevcut CI kurulumumuz buildbot kullanıyor. Tasarım yapmaya başladığımda, tüm yapıyı bir kerede, bir gecede çalıştırmak için uyarlanmış ısmarlama bir CI kurucusunu miras aldım (kesinlikle, kesinlikle değil, bir yıl önce tasarımına katıldım). Bir süre sonra bunun yetersiz olduğuna karar verdik ve nihayetinde buildbot'u seçerek farklı CI çerçevelerini keşfetmeye başladık. Buildbot'a geçişteki hedeflerimden biri (tüm whiz-bang ekstralarının tadını çıkarmanın yanı sıra), ısmarlama gece üreticimizin bazı yetersizliklerinin üstesinden gelmekti.

Bir an için beni mizah et, ve miras aldığımı açıklamama izin ver. Şirketim için kod tabanı, her biri bir düzine iç kütüphaneden birine (ve 3. parti kütüphanelerine de) bağımlı olan neredeyse 150 benzersiz c ++ Windows uygulamasıdır. Bu kütüphanelerin bazıları birbirine bağımlıdır ve (birbirleriyle hiçbir ilgileri olmasa da) bu kütüphanenin aynı derlemesi ile oluşturulması gereken bağımlı uygulamalara sahiptir. Bu uygulamaların ve kitaplıkların yarısı "eski" ve taşınabilir değil olarak kabul edilir ve IBM derleyicisinin birkaç farklı yapılandırmasıyla (benzersiz alt sınıfları yazdığım Compile) ve diğer yarısı da görsel stüdyo ile inşa edilmelidir .ShellCommands, çünkü VSS desteği yoktur).

Orijinal gece yapımcımız her şeyin kaynağını indirdi ve belirli bir sırayla bir şeyler yaptı. Yalnızca tek bir uygulama oluşturmanın, bir düzeltme seçmenin veya bir şeyleri gruplamanın bir yolu yoktu. Bir dizi uygulama oluşturmak için sanal makineler piyasaya sürecekti. Çok sağlam değildi, dağıtılamadı. Çok genişleyemezdi. Buildbot'taki tüm bu sınırlamaların üstesinden gelmek istedim.

Bunu ilk yapma şeklim, inşa etmek istediğimiz her bir uygulama için giriş oluşturmak (bunların 150'si kadar), daha sonra gruplar halinde çeşitli uygulamalar oluşturabilecek tetiklenmiş zamanlayıcılar oluşturmak ve daha sonra bu grupları genel bir gece oluşturma zamanlayıcısı altında toplamaktı. Bunlar özel köleler üzerinde çalışabilir (artık sanal makine chicanery yok) ve istersem yeni köleler ekleyebilirim. Şimdi, zamanlamanın dışında tam bir derleme yapmak istiyorsak, bu tek bir tıklamadır, ancak istediğimiz takdirde sadece bir uygulama da oluşturabiliriz.

Ancak bu yaklaşımın dört zayıf yönü vardır. Birincisi, kaynak ağacımızın karmaşık bağımlılık ağıdır. Yapılandırma bakımını basitleştirmek için tüm inşaatçılar büyük bir sözlükten üretilir. Bağımlılıklar, son derece sağlam olmayan bir şekilde alınır ve oluşturulur (yani, hedef hedef sözlüğümdeki bazı şeyleri kapatmak). İkincisi, her derlemede göz atmak ve web arayüzünde bakmak zor olan 15 ila 21 derleme adımı vardır ve yaklaşık 150 sütun olduğundan, yüklenmesi sonsuza kadar sürer (30 saniyeden birkaç dakikaya kadar düşünün). Üçüncüsü, artık hedef oluşturma hedefleri hakkında otomatik bir keşifimiz yok (iş arkadaşlarımdan biri bana bu konuda ne kadar fazla dokunsa da, ilk etapta bize neyin sahip olduğunu görmüyorum). En sonunda,

Şimdi, yeni gelişime geçerek, g ++ ve subversion kullanmaya başlıyoruz (eski veri havuzunu taşımıyor, sadece yeni şeyler için). Ayrıca, (bir daha gibi ... "daha" yanlış bir resim verebilir daha birim test yapmak başlıyor herhangi ) ve entegrasyonu (piton kullanarak) test. Bunları mevcut yapılandırmamın içine nasıl yerleştireceğimizi anlamakta zorlanıyorum.

Peki, burada felsefi açıdan nerede yanlış yaptım? En iyi nasıl ilerleyebilirim (buildbot ile - üzerinde çalışmam için lisansa sahip olduğum bulmacanın tek parçası), bu yüzden yapılandırmam gerçekten korunabilir mi? Tasarımımın bazı zayıf yönlerini nasıl giderebilirim? Büyük (muhtemelen aşırı) karmaşık kod tabanları için CI stratejileri açısından gerçekten işe yarayan nedir?

DÜZENLE:

Sorunumu açıkladığımı sanıyordum, ama açıkçası yeterince açık değildim. Ben am değil CI platformları değiştirme öneri aranıyor. O olduğu değil ne olacak ve öne süren cevaplar kabul almazsınız. Ne istiyorum bilmek Başkalarının CI kullanarak karmaşık codebases yönetmek nasıl. Bir düzine kare farklı ürünüm var ve rüzgara dağılmış bağımlılıklarım var ve hepsi farklı. Bununla nasıl başa çıkacağımı bilmek istiyorum.


Ben de bunun cevabını bilmek istiyorum. Ortamımız sizinki kadar karmaşık değil, ancak bağımlılık bağımlılık bağımlılıklarımız var (kurulum projesi durumunda, dört kat derinlikte bağımlılıklar var). Her projenin bir CI projesi olup olmadığını bilmiyor muyum, yoksa Visual Studio .sln dosyasını benim için bakmak için kullanmalıyım, böylece her proje için bağımlılık ağacını yeniden oluşturmam gerekmiyor (ve gelecekteki proje).
moswald

Yerel makinenizi oluşturamamanız, CI sunucu görevinizi işletmeniz için kritik hale getirir . Bunu yeniden düşünmek isteyebilirsiniz.
Thorbjørn Ravn Andersen

Yanıtlar:


3

Açıkladığınız kadar kötü bir durumla karşılaşmamış olmama rağmen, aralarında bazı 'basit' bağımlılıklar bulunan onlarca bileşenden oluşan bir CI yapılandırması sürdürüyorum. Umarım yaklaşımım size ilerlemeniz için bazı ipuçları verebilir. Sorun kesinlikle sadece CI sunucusu seçimi ile değil, aynı zamanda genel inşa süreci ve proje yapısı ile de ilgilidir.

Sorunu 2 kısma ayıracağım: Yapı ve CI.

bina

"Bina" için, kaynak kodu eldeki nihai yapıya değiştirme süreci anlamına gelir. Şirketimiz ağırlıklı olarak Java'yı geliştirmede kullanıyor ve kullandığımız derleme aracı Maven. Muhtemelen projenizin doğası gereği kullanamayacaksınız, ancak Maven'de dikkat çekmeye değer bazı değerli kavramlar var:

1) Maven dünyasında, her bir eserin (bir lib, gerçek program vb.) Açıkça izole edilmesi ve ayrıştırılması gerekir. Artefakt arasındaki bağımlılıklar açık olmalıdır. Şunu vurgulamam gerekir ki, dağınık bağımlılık, özellikle yapı eserleriniz arasındaki dairesel bağımlılıklar yapı sürecini dağınık hale getirecektir.

Örneğin, bundan önce bazı java projeleri gördüm, ancak tüm oluşturma işleminden sonra birkaç JAR (Java'da lib / dll olarak düşünebilirsiniz) inşa edilmiş olsa da, aslında birbirine bağımlıdırlar. A.jar, B.jar'daki şeyleri kullanıyor ve tam tersi. Bu tür bir 'modülerleşme' tamamen anlamsızdır. A.jar ve B.jar daima birlikte dağıtılmalı ve kullanılmalıdır. Bunun anlamı, daha sonra onları farklı projelere ayırmak istiyorsanız (örneğin diğer projelerde yeniden kullanım için), bunu yapamayacağınız, çünkü ilk önce hangi projeyi, A veya B'yi inşa edeceğinizi belirleyemezsiniz.

Evet, yazılımınızın tasarımında yiyecek ve içecek sağlamak gerekiyor, ancak her zaman, karmaşık bir inşaat aleti / modeli çalışması yapmak için zaman harcamak yerine, dağınık bir projede tasarım yapmak için zaman harcamak yerine, basit bina modeli.

2) Bağımlılıklar açıklayıcı olmalıdır. Daha önce gördüğüm, projede yerel olarak ihtiyaç duyduğu tüm kütüphaneleri içeren birçok inşa süreci var. Eğer bazı kütükler aslında inşa etmeniz gereken diğer eserler ise, inşa sürecini son derece zahmetli hale getirecektir.

3) Bağımlılık elde etmek ya da derlendikten sonra yapay nesneleri dağıtmak için yapay nesneler için "merkezi" depolama. Tüm ofis için "merkezileştirilmesi" gerekmiyor (varsa harika olacak), sadece yerel bir dizin zaten iyi olacak.

2 ve 3 üzerinde daha fazla ayrıntı. Sadece bir örnek vermek gerekirse, 3 bağımsız proje içeren bir projeyle karşılaştım. Her proje, kaynak tabanının yanı sıra, kaynak dizindeki lib / dizininin altındaki kütüphaneleri temel alır. Proje A, proje B ve C tarafından kullanılan birkaç kütüphaneyi inşa edecek. kaynak kontrolü farklı projede tekrar kullanılan gereksiz kopya JAR'lar ile şişiyor

Maven'in dünyasında, B ve C projesi, proje kaynağında gerçekten A.jar (ve diğer üçüncü taraf lib gibi diğer bağımlılıklar) içermiyor. Deklaratiftir. Örneğin, B projesinin derleme yapılandırmasında, yalnızca gerekli olduğunu beyan eder: A.lib v1.0, xyz.lib v2.1 vb. Ve derleme betiği lib'yi /A/1.0/A'dan arayacaktır. kavanoz ve /xyz/2.1/xyz.lib

Maven olmayan dünya için, bu yapay dizin yalnızca kabul edilen dizin yapısına sahip bir veya iki dizin olmalıdır. Tüm 3. taraf kütüphanelerini bir paylaşım konumuna koyabilir ve geliştiricilerin yerel makinelerini senkronize etmesine veya kopyalamasına izin verebilirsiniz. Yıllar önce yaptığım C ++ projelerimde, yaptığım şey lib ve üstbilgiyi $ {artifact_dir} / lib_name / ver olarak ayarlamak ve artifact_id ile ortam değişkeni olarak ayarlamak.

A projesi oluşturulduğunda, bu artifact_dir'deki sonucunun bir kopyasına sahip olacak, böylece B projesini oluşturduğumuzda B, A'nın sonucunu manuel kopyalama olmadan otomatik olarak alabilir.

4) Değişmez salım. A.lib 1.0'ı bıraktığınızda, işte bu, A.lib 1.0'ın 1 ay sonra içerik değişikliğini beklemeyeceksiniz, sadece bazı hata düzeltmeleri var. Bu durumda A.lib 1.1 olmalıdır. Değişen bir kod tabanının yapısı, Maven'de buna anlık görüntü adını verdiğimiz özel bir "sürümü" dikkate almalıdır.

Değişmez salım daha etik bir konudur. Ama çözdüğü şey açık: Aynı lib'i kullanan çok sayıda projeniz olduğunda, bu lib'in hangi sürümünü kullandığınızı biliyorsunuz ve farklı projelerde kullanılan aynı lib sürümünün gerçekten aynı olduğundan emin olacaksınız. . Sanırım birçoğumuz şu problemden geçiyor: X ve Y projesi neden lib A'yı kullanıyor ancak inşa sonucu farklı? (ve X ve Y tarafından kullanılan lib A'nın aslında lib'in içeriğine veya dosya boyutuna baktıktan sonra farklı olduğu ortaya çıkar).


Tüm bunlar, projelerinizin, önce A projesini inşa etmek, A.lib'i B projesine kopyalamak ve sonra B projesini oluşturmak gibi çok manuel hile yapmadan bağımsız olarak inşa edebilmesini sağlar ...

Bunun gibi bir alıştırmadan geçtikten sonra, örneğin A projesini oluşturduğunuzda, bağımlılıkları merkezi artefakt deposundan almaya çalışacaktır. Bazı bağımlılıklar (şirketinizin diğer projeleri, örneğin proje B) bulunamazsa, yapmanız gereken şey, B projesinin kaynağını almak, inşa etmek (başarı üzerine merkezi depolamaya dağıtılacak) ve sonra A projesini tekrar oluşturun.


CI

Kolay bir inşa sistemi ile, açık bağımlılıklar ile CI çok daha kolay olacaktır. CI sunucunuzun aşağıdaki gereksinimi karşılamasını bekleyeceğim:

1) Kaynak kontrolünü izleyin, sadece kaynakta değişiklikler olduğunda ödeme + derleme yapın

2) Projeler arasındaki bağımlılıkları kurabilir

Projelere açık bir bağımlılıkla, gerçek projelerinize göre CI'deki projeleri ayarlamanız, projelerinizin bağımlılığına göre CI proje bağımlılığını ayarlamanız yeterlidir. CI sunucunuz herhangi bir proje oluşturmadan önce bağımlı projeler oluşturacak şekilde ayarlanmalıdır (ve tabii ki derleme yalnızca proje kaynağında gerçekten değişiklik olması durumunda gerçekleşir).

Her şey yolunda giderse, devasa, karmaşık ancak yine de yönetilebilir bir CI'niz (ve daha da önemlisi, yönetilebilir bir proje yapınız) olmalıdır


Bu cevabın nereye gittiğini seviyorum, ama 'bina' bölümünde daha fazla ayrıntıya girebilir misiniz? Yani, bazı örnekler verin, bazı kavramları daha ayrıntılı, ayrıntılı bir şekilde açıklayın.
Nate

hm ... hangi kısım gibi? Her bölüm hakkında daha ayrıntılı bilgi vermek için yayını düzenlemeye çalışıyorum. U bana hangi kısmı üzerinde detaylandırılması gerektiğini hissediyorum eğer daha iyi olacaktır. Bu arada, Java'yı da kullanıyorsanız, maven.apache.org adresine bir göz atın. Maven benimsemek en kolay şey olmayabilir, ancak eşyalarınızı temiz ve düzenli hale getirmeye zorlar.
Adrian Shum

1

Benim için benzer durumlarda ne işe yaradı:

  • Yapının bazı bölümlerini özel yapım uygulamalarına dönüştürerek uygulama düzeyinde soyutlama (bizim durumumuzda bunlar ana yapıdan çağrılan PHP komut dosyalarıdır). Bu, birkaç düzine oluşturma adımını bir oluşturma adımına indirgeyebilir.
  • Ana yapı komut dosyasından başlatılan alt yapı komut dosyaları oluşturarak yapı düzeyinde soyutlama. Buildbot ile alakalı olup olmadığı hakkında hiçbir fikrim yok (bu ürünle ilgili deneyim yok).

Yapının kendisine bir yazılım geliştirme projesi olarak davranmanızı öneririm. Bu, derleme kod tabanını modüle etmeniz ve bunun için bazı otomatik testler yazmanız gerektiği anlamına gelir (örneğin, bilinen bir revizyon numarası oluşturun ve doğru sonuçlar üretip üretmediğini kontrol edin).


0

Jenkins'i bir CI sunucusu olarak görüyorum, buradaki özelliklere bakabilirsiniz:

https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins

Neden? Kurulumu kolaydır, harika bir arayüze sahiptir, yapılandırılması ve genişletilmesi kolaydır ve hemen hemen her şey için çok sayıda hazır eklenti vardır:

https://wiki.jenkins-ci.org/display/JENKINS/Plugins

Bir şans ver :)


2
Sorumun başlığını okuduğunuzu hissediyorum, ancak cesedi okumadım ... Ürün önerisi aramıyorum. Ben var seçilen bir ürün. Karmaşık bir CI kurulumunun nasıl organize edileceğini arıyorum.
Nate

Nate, tüm yazılarını okudum ve sanırım yanlış ürünü seçtin, bu yüzden Jenkins'i önerdim. Jenkins, C ++ ürünlerinin çeşitli testlerinde (birden fazla dilde yazılmış testler bile) birden fazla makinede kümeleme ile işte kullanıyorum ve çok iyi çalışıyor. Yönetmek ve yapılandırmak çok kolay. Gerçekten, deneyin :)
Patrizio Rullo

Bu blog gönderisine de bakın: vperic.blogspot.com/2011/05/…
Patrizio Rullo

0

Biz artık kullanıma THOUGHTWORKS tarafından Git , biz kullandığını öncesinde CruiseControl.Net . Dünyanın yarısını birbirinden ayıran iki ekibimiz olduğu ve aramızda büyük bir zaman dilimi farkı olduğu göz önüne alındığında faydalı oldu.

Birden fazla projeyi yönetiyoruz ve görevlerin çoğu dünyanın her iki tarafındaki iki geliştirici arasındaki çakışmaları içeriyor, bu nedenle tüm dosyaların başkalarının yapısını bozmaması gerektiğini aklımızda tutmalıyız.

Ayrıca Go ve Agile Process diehard olarak yönetim daha kolaydır, kurduktan sonra bize daha az baş ağrısı verdi. Test Go ile de entegre edildi.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.