İçeriğe geç

CI Pipeline — Geri Bildirim Neden Bu Kadar Geç Geliyor?

Orta 9 dk Sık karşılaşılır

Önce şunu oku: Docker Katman Cache ve İmaj Boyutu

30 saniyede özet

Yavaş bir pipeline çoğu zaman aynı işi her koşuda baştan yapar ve birbirini beklemesi gerekmeyen aşamaları sıraya dizer. Cache tekrarı keser, paralel aşamalar bekleyişi kısaltır, hızlı testler kötü haberi erkene çeker.

Çamaşır gününü düşün. Yıkamak, kurutmak, ütülemek ve katlamak tek tek yapılırsa bütün gün sürer. Üstelik dolaptaki temiz gömlekleri de yeniden yıkıyorsan gün hiç bitmez.

  1. Bayt: Ödeme servisine tek satırlık bir düzeltme yaptım. Pipeline başladı!

  2. Sen: Yirmi dakika sonra kırmızı geldi. Hata ilk birim testindeymiş.

  3. Bayt: O test birkaç saniyede koşuyor. Neden yirmi dakika bekledik?

  4. Bayt: Testten önce bir sürü iş yapılıyor olmalı. Pipeline'ın içine bakalım.

Süre nereye gidiyor?

Bir CI pipelineHer commit'te kodu derleyip testleri otomatik koşan aşamalar dizisi. Asıl işi, değişikliğin sağlam olup olmadığını geliştiriciye hızlıca söylemektir.Sözlükte gör →’ı her commit’te kodu çeker, bağımlılıkları kurar, derler, testleri koşar ve bir imaj üretir. Sırayla koşan aşamaların süreleri toplanır.

Bu sürenin büyük bir kısmı çoğu zaman tekrarlanan iştir. Bağımlılıklar bir önceki koşudan beri değişmemiştir, ama her seferinde baştan indirilir.

Kafam karıştı, daha basit anlat

Sırayla koşan aşamaların süresi toplanır. Bir kısmı her seferinde aynı işi yapar.

Hızlı kontrolBaşlangıç

Bir CI pipeline'ı her commit'te ne yapar?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Sırayla koşan aşamalardan oluşan bir pipeline'ın toplam süresi nedir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Tekrarı kes, bekleyişi kısalt

Birim testleri, entegrasyon testleri ve Docker imajı derlemeden sonra yan yana koşarsa, bu üç aşamanın toplam süresini ne belirler? Cevabı göster

En uzun olanı. Yan yana koşan aşamalar birbirini beklemez. Üçü 3, 8 ve 4 dakika sürüyorsa, hepsi 8 dakikada biter.

Tekrarlananı kes, bağımsızı yan yana koştur.
Adım adım oku
  1. Her şey sırayla: bütün gün sürer.
  2. Temiz olanı yeniden yıkama: cache.
  3. Birbirini beklemeyen makineler yan yana.
  4. Tekrarlananı kes, bağımsızı paralel koştur.

Cache, bir önceki koşunun sonucunu bir cache anahtarıBir cache kaydının neye bağlı olduğunu söyleyen anahtar; genellikle bağımlılık dosyasının özeti. Dosya değişince anahtar da değişir ve eski cache kullanılmaz.Sözlükte gör → ile saklar. Anahtar genellikle bağımlılık dosyasının özetidir; dosya değişmediyse bağımlılıklar indirilmez, cache’ten gelir.

Paralellik ise bekleyişi kısaltır. Birim testleri ile imaj derlemesi birbirinin sonucuna ihtiyaç duymaz; yan yana koşarlar ve toplam süre en uzun aşama kadar olur.

Kafam karıştı, daha basit anlat

Cache tekrarlanan işi keser. Paralel aşamalarda süreyi en uzun aşama belirler.

Hızlı kontrolOrta

Birim testleri 3, entegrasyon testleri 8, imaj 4 dakika sürüyor ve üçü yan yana koşuyor. Bu bölüm ne kadar sürer?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Bağımlılık cache'inin anahtarı neden pom.xml ya da lock dosyasının özetinden üretilir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kendin gör

Commit’ten yeşil ışığa

Tohum 586559
  1. Kodu çek0–0,5 dk, bitti
  2. Bağımlılıklar0,5–6,5 dk, bitti
  3. Derle6,5–8,5 dk, bitti
  4. Birim testleri8,5–11,5 dk, bitti
  5. Entegrasyon testleri11,5–19,5 dk, bitti
  6. Docker imajı19,5–23,5 dk, bitti
  7. Staging’e deploy23,5–24,5 dk, bitti

Geçen süre: 0 dk

Hız
Adım 0

Şu an ne oldu?

Pipeline: cache yok · sıralı

Geliştirici commit’i gönderdi. Sonucu ne zaman öğrenecek?

Görevler0/3

  • Yeşil ışığı 24 dakikadan uzun bekleaçık

    İpucu

    Varsayılan ayarlar yeter.

  • Yeşil ışığı 12 dakikada alaçık

    İpucu

    İki iyileştirme birlikte.

  • Kırık testi 6 dakikada öğrenaçık

    İpucu

    Testlere varmadan önceki bekleme kısalmalı.

Olay günlüğü (0)

Henüz olay yok. Oynat veya adımla.

  1. Varsayılanla oynat. Cache yok, her şey sırayla: yeşil ışık 24,5 dakika sonra geldi.
  2. Cache’i aç. Bağımlılıklar ve imaj katmanları cache’ten geldi: 16 dakika.
  3. Cache’i kapat, paralel aç. Testler ve imaj yan yana koştu: 17,5 dakika.
  4. İkisini birlikte aç. 12 dakika; süreyi artık en uzun aşama, entegrasyon testleri belirliyor.
  5. Cache’i kapat, paraleli kapat ve “Bir birim testi kırık”ı aç. Kırmızı haber 11,5 dakika sonra geldi. Cache’i açınca 6 dakikaya indi.
Hızlı kontrolOrta

Cache'i açmak kırık bir birim testinin ne zaman öğrenildiğini nasıl etkiler?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Paralel koşuda birim testi kırmızı oldu; entegrasyon testleri hâlâ koşuyor. Ne yapılmalı?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Tuzaklar

Yanlış cache anahtarı. Anahtar bağımlılık dosyasını içermezse, yeni bir kütüphane eklediğinde eski cache kullanılır. Anahtarı lock ya da pom dosyasının özetinden üret.

Yavaş testleri öne koymak. Entegrasyon testleri birim testlerinden önce koşarsa, saniyelerde bulunabilecek bir hata dakikalar sonra görünür. Hızlı ve sık kırılan testler önce koşmalı.

Eski koşuları beklemek. Aynı dala art arda üç commit gelirse, ilk ikisinin pipeline’ı artık kimseyi ilgilendirmez. Bir dalda yeni koşu başlayınca eskisini iptal et.

Kafam karıştı, daha basit anlat

Cache anahtarını doğru kur, hızlı testleri öne al, eski koşuları iptal et.

Hızlı kontrolOrta

Aynı dala art arda üç commit geldi. İlk iki commit'in pipeline'ları için ne yapılmalı?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aşağıdaki örnek bir ödeme servisinin GitHub Actions pipeline’ından: Maven cache’i, paralel işler, imaj katmanları için cache ve aynı daldaki eski koşuların iptali.

Derinleş · Ödeme servisi pipeline'ı: cache, paralel işler, önce hızlı testler 3 dosya · ~110 satır · ilk okumada atlayabilirsin
Proje dosyaları

.github/workflows/ ci.yml Akış: derleme bir kez yapılıyor; birim testleri, entegrasyon testleri ve imaj onun ardından yan yana koşuyor.

.github/workflows/ci.yml
name: payments-ci
on:
push:
branches: [main]
pull_request:
concurrency: # a newer commit on the same branch cancels the older run
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven # keyed on the hash of pom.xml
- run: ./mvnw -B -q -DskipTests package
- uses: actions/upload-artifact@v4
with:
name: app
path: target/*.jar
unit-tests: # fast, fails often: gives the first answer
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: '21', cache: maven }
- run: ./mvnw -B test
integration-tests: # slow; runs beside the unit tests, not after them
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { distribution: temurin, java-version: '21', cache: maven }
- run: ./mvnw -B verify -DskipUnitTests
image:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with: { name: app, path: target }
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
push: false
cache-from: type=gha # layers from earlier runs
cache-to: type=gha,mode=max
deploy-staging:
needs: [unit-tests, integration-tests, image]
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- run: echo "deploy to staging"

pom.xml (test plugins) Cache: Maven bağımlılıkları pom.xml'in özetiyle, imaj katmanları Actions cache'iyle saklanıyor.

pom.xml (test plugins)
<properties>
<skipUnitTests>false</skipUnitTests>
</properties>
<build>
<plugins>
<!-- *Test.java: fast unit tests, run by `mvn test` -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${skipUnitTests}</skipTests>
</configuration>
</plugin>
<!-- *IT.java: integration tests with Testcontainers, run by `mvn verify` -->
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

src/test/java/com/bank/payments/ TransferFeeIT.java Eski koşular: aynı dalda yeni commit gelince önceki koşu iptal ediliyor.

src/test/java/com/bank/payments/TransferFeeIT.java
// The IT suffix sends this class to failsafe: it needs a real database and runs in its own job.
@SpringBootTest
@Testcontainers
class TransferFeeIT {
@Container
@ServiceConnection
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine");
@Autowired
TransferService transfers;
@Test
void chargesTheFeeOncePerTransfer() {
TransferReceipt receipt = transfers.send(new TransferRequest("TR01", "TR02", new BigDecimal("100.00")));
assertThat(receipt.fee()).isEqualByComparingTo("2.50");
}
}

Kendini sına

Şimşek turu1/4

Paralel koşan aşamaların toplam süresini en uzun olanı belirler.

Soru 1/3İleri

Cache anahtarı bağımlılık dosyasını içermiyor. Yeni bir kütüphane eklendi. Ne olur?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aklında kalacak üç şey

  1. 1 Pipeline'daki en büyük israf çoğu zaman tekrarlanan iştir: her koşuda aynı bağımlılıkları indirmek ve aynı imaj katmanlarını kurmak. Cache bunu bir önceki koşudan getirir.
  2. 2 Birbirinin sonucuna ihtiyaç duymayan aşamalar yan yana koşabilir. O zaman toplam süreyi bütün aşamaların toplamı değil, en uzun olanı belirler.
  3. 3 Bir pipeline'ın asıl işi geliştiriciye haber vermektir. Hızlı ve sık kırılan testler öne alınırsa kötü haber, uzun aşamalar başlamadan gelir.
Sonraki kapı Senin testlerinin hepsi yeşil ve kodunu hiç değiştirmedin. Peki havale ekranı neden bu sabah çöktü? Sözleşme Testleri — Karşı Servis Değişince Kim Kırılır? · 9 dk

4 kart sonraki derste seni bekliyor

0/4 kart bu dersten toplandı

Bu dersin üstüne kurulanlar

Bunlar bu dersi temel alıyor; hazır olduğunda devam edebilirsin.