La mischia e uno sviluppo stabile creano una contraddizione?


11

Faccio parte di un gruppo di sviluppo con 5 team, per un totale di circa 40 sviluppatori. Stiamo seguendo la metodologia Scrum, con sprint di 3 settimane. Abbiamo una configurazione di integrazione continua (Jenkins), con una pipeline di compilazione che richiede diverse ore (a causa di numerosi test automatizzati). Fondamentalmente, il processo di sviluppo funziona bene.

Tuttavia, osserviamo che dopo alcuni giorni in un nuovo sprint, la nostra build diventa spesso instabile e rimane instabile fino alla fine dello "sprint commit". L'effetto negativo di questo è che le fasi di costruzione molto lontane dalla pipeline, in particolare UI- / Webtest, non vengono eseguite per diversi giorni (perché attivate solo su una build "verde"). Di conseguenza, i bug appena introdotti vengono spesso rilevati solo molto tardi nello sprint.

  • Ogni commit viene verificato rispetto a una serie di test di base. Una volta verificato, la modifica viene trasferita al master dopo una revisione del codice (Gerrit)
  • I test unitari di base vengono eseguiti ogni 30 minuti, durata inferiore a 10 minuti
  • I test di integrazione vengono eseguiti ogni 2 ore, durata 1 ora
  • I test UI / Web vengono eseguiti con successo test di integrazione, durata diverse ore

A seconda di chi è responsabile della stabilità della build durante lo sprint (tale responsabilità viene trasferita per ogni sprint), potrebbero esserci "stop commit" intermedi e ad hoc per riportare la build alla stabilità.

Quindi, vogliamo:

  1. I nostri team di sviluppo sviluppano e commettono modifiche durante uno sprint senza ostacoli
  2. Il nostro processo di compilazione da abbandonare se una fase di compilazione fallisce, poiché i risultati di compilazione successivi hanno poco significato
  3. Il nostro processo di creazione per fornire agli sviluppatori un feedback di qualità in modo tempestivo

Dato (2), i punti (1) e (3) sembrano contraddirsi. Qualcuno ha una buona pratica su come affrontare questo?

( Attualmente stiamo allentando il punto (2) e stiamo permettendo la continuazione della costruzione anche su passaggi di costruzione falliti. Non ho ancora alcun feedback su come ciò influisca sulla nostra qualità )

Grazie Simone


3
Direi che se si sta realizzando una build, several hoursquesto è il vero problema. significa che la soluzione combinata è troppo grande e troppo ampia. Dovresti cercare di strutturare la soluzione e quindi avere piccoli blocchi di codice come pacchetti (disponibili in un modo o nell'altro in tutte le principali lingue su tutte le piattaforme). Pertanto, qualsiasi modifica andrebbe solo nei componenti e verrà rilevata molto più velocemente. La build completa essenzialmente metterà insieme i componenti già combinati e sarà anche più veloce. Quindi potresti eseguire solo alcuni test per accertarti che i componenti giusti siano stati risolti.
zaitsman

Il tuo ambiente di costruzione è on-premise o basato su cloud?
Lauri Laanti,

@LauriLaanti, il nostro ambiente di costruzione è on-premise, 1 istanza Jenkins con 3 slave.
Simon,

Risposte:


7

Prima un paio di principi di base: - Le modifiche principali dovrebbero sempre avvenire su un ramo di funzionalità nel VCS - I rami di funzione devono superare tutti i test prima di fondersi nel trunk. Aggiunti - I commit devono sempre costruire - Una build interrotta richiede un'azione immediata da parte del committer e / o del resto della squadra. - Un test fallito dovrebbe interrompere i test rimanenti solo se è un test critico .

Se, come squadra, segui queste pratiche e le imposti, ad esempio: "nome e vergogna" quando la build viene interrotta, dovresti essere pronto a procedere poiché qualsiasi commit che potrebbe interromperla sarà su un ramo delle caratteristiche. Altri commit che interrompono la compilazione dovranno essere indirizzati immediatamente e quindi otterrai i risultati del test a valle.

Puoi anche aggiungere un test automatico dell'ultima build "riuscita", (non necessariamente quella che supera i test di integrazione), per i test UI / Web come test notturno che riporta la prima cosa al mattino.


3
Una buona pratica da aggiungere qui è che i rami delle caratteristiche dovrebbero superare tutti i test prima di essere uniti alla linea principale
Bart van Ingen Schenau,

@BartvanIngenSchenau - buon punto aggiunto!
Steve Barnes,

@SteveBarnes, grazie per l'input. Un commit in Gerrit è sempre su una filiale e si fonde solo in caso di successo (il mio primo punto elenco nel processo di compilazione). È dopo che inizia il problema. Con 30 sviluppatori che commettono modifiche più volte al giorno, dobbiamo unirci presto e quindi verificare. V'è un'azione immediata, dopo una build rotto, ma come il tempo che intercorre tra il commit e il feedback di compilazione è di 2 ore, ci saranno molti altri commit nel frattempo. Forse rompere la prossima build.
Simon,

@Simon il punto del "nome e vergogna" è di far smettere ai tuoi sviluppatori di commettere un codice non funzionante! Sulla maggior parte dei sistemi è possibile eseguire una build di test in breve tempo utilizzando strumenti come formica, marca, scons, ecc. Se il progetto è ben strutturato, la maggior parte delle lingue consente la ricostruzione parziale per verificare se le cose verranno costruite, (completo / pulito le build devono ancora essere eseguite ovviamente).
Steve Barnes,

8

Non ha nulla a che fare con Scrum. La tua build dovrebbe essere costantemente stabile, indipendentemente.

Nessuno dovrebbe fare il check-in a meno che non abbiano eseguito una build locale ed eseguito i test unitari a livello locale (ed entrambi hanno superato, ovviamente). Il processo di compilazione e test locale dovrebbe essere sensibile alle modifiche e può saltare i test per il codice che non è cambiato.

Chiunque introduce qualcosa che causa il fallimento della build o il fallimento di un test unitario deve essere pubblicamente vergognoso . Se la build viene interrotta, deve essere riparata immediatamente.


2
Da un lato, va sottolineato che la stabilità della costruzione è responsabilità di tutti. D'altro canto, sconsiglioi la vergogna pubblica, perché (1) i membri del team più esperti hanno una maggiore responsabilità nell'aiutare i membri junior a raggiungere la stabilità della costruzione (mediante revisione del codice, accoppiamento della programmazione o semplicemente lavorando a stretto contatto prima di un commit, oppure tramite sistemando una build rotta insieme), (2) la vergogna toglie sicurezza psicologica alla squadra .
rwong

1
Se le persone non vogliono essere vergognose, non dovrebbero interrompere la costruzione. Non è che sia uno standard irragionevolmente alto. Se hai sviluppatori che non riescono ad hackerarlo, lascia che abbiano il loro ramo in cui giocare fino a quando non riescono a capire come non rompere i Comuni critici della squadra. (Detto questo, qualsiasi vergogna dovrebbe essere di buon gusto).
John Wu,

Nel nostro processo, ogni commit è ramificato (in Gerrit) e deve superare una serie di test di base prima di unirsi al master. Questi test di base non possono essere eseguiti per un'ora, poiché desideriamo riesaminare e unire rapidamente il codice. È dopo l'unione in cui inizia il problema, vedi il mio commento a @SteveBarnes
Simon

6

Il tuo problema sembra essere che i test impiegano troppo tempo per essere eseguiti. Fortunatamente, la legge di Moore ci ha fornito una soluzione a questo problema. Oggi, le CPU dei server di fascia alta possono facilmente avere oltre 10 core (e oltre 10 HyperThread). Potrebbero esserci più di tali CPU in un singolo computer.

Se avessi dei test che impiegano così tanto tempo, risolverei il problema con più hardware. Vorrei acquistare un server di fascia alta e quindi parallelizzare i test in modo che i test sfruttino appieno tutti i core della CPU. Se i tuoi test sono oggi a thread singolo, sfruttando 10 core e 10 HyperThreds probabilmente i test verranno eseguiti 15 volte più velocemente. Ovviamente, ciò significa che usano anche 15 volte la memoria, quindi il computer deve avere abbastanza RAM.

Quindi, le diverse ore si trasformeranno in 10-30 minuti.

Non hai detto quanto tempo impiega la build, ma strumenti di build standard come make consentono di parallelizzare anche la build. Se si parallelizzano i test unitari e il tipico computer sviluppatore ha 4 core e 4 HyperThread, i test unitari di meno di 10 minuti si trasformeranno in meno di 2 minuti. Quindi, forse potresti applicare una politica secondo cui tutti dovrebbero eseguire i test unitari prima di impegnarsi?

Informazioni sull'errore di test che interrompe ulteriori test: non farlo sul server di compilazione! Desideri quante più informazioni possibili sull'errore e ulteriori test potrebbero rivelare qualcosa di importante. Naturalmente, se la build stessa non è riuscita, non è possibile eseguire unit test. Se lo sviluppatore esegue unit test sul proprio computer, è possibile che si desideri interrompere al primo errore.

Non vedo alcun collegamento tra Scrum e i tuoi problemi. I problemi potrebbero realmente verificarsi con qualsiasi processo di sviluppo.


Sono d'accordo, con una costruzione più veloce le cose sarebbero molto più facili. Il nostro TechTeam ha trascorso giorni a migliorare la velocità del nostro processo di creazione, altrimenti aspetteremmo giorni anziché ore. Per ora, quella durata del feedback è data a ca. 2 ore. Quindi sto cercando un approccio che lo prenda come un "dato". (Certo, stiamo continuamente cercando di accelerare la costruzione. Ma per il prossimo futuro, saranno 2 ore)
Simon

Alcuni test possono essere in conflitto con l'esecuzione parallela
deFreitas

È possibile lanciare più hardware su di esso se i test sono scritti in un modo in cui possono essere eseguiti indipendentemente l'uno dall'altro senza introdurre effetti collaterali. Quanto più si ottiene dall'hardware tanto più diventa difficile ... la maggior parte degli sviluppatori non lo fanno fai bene, quindi, mentre concordo con te, mi concentrerei prima di strutturare i test nel modo giusto.
c_maker,

2

Non è possibile avere più installazioni Jenkins e far controllare gli sviluppatori su un'istanza Jenkins separata?

Penso che la soluzione migliore qui sia fare in modo che il codice superi tutti i test prima che venga verificato nel ramo master e compilato / testato dall'istanza principale di Jenkins. Non lasciare che le persone eseguano il check-in del codice che interrompe la build.

Controllo il mio codice nel ramo di sviluppo, vedo se supera i test e creo una richiesta pull. Ma potresti ovviamente avere jenkins che estrae un ramo di funzionalità e lo verifica.


1

Il punto (2) sembra essere il punto più doloroso, quindi mi concentrerò su quello.

Potrebbe essere il momento di suddividere il progetto in più moduli.

https://en.wikipedia.org/wiki/Dependency_inversion_principle

A. I moduli di alto livello non dovrebbero dipendere da moduli di basso livello. Entrambi dovrebbero dipendere dalle astrazioni.

B. Le astrazioni non dovrebbero dipendere dai dettagli. I dettagli dovrebbero dipendere dalle astrazioni.

Se un modulo non riesce a compilare, la compilazione per altri moduli sarà in grado di continuare, purché quegli altri moduli possano dipendere da un'interfaccia e il codice che costituisce tale interfaccia è stato creato correttamente.

Questo ti darà un feedback su ciò che potrebbero verificarsi altri errori di build, in modo da avere il tempo di riparare più di un modulo rotto prima che avvenga la build successiva.

In generale, i principi SOLID sono concepiti per gestire le biblioteche e creare problemi. In altre parole, questo insieme di principi è concepito per risolvere il tipo esatto di problemi che stai affrontando.


Come nota a margine (vedere la risposta del juhist), non è possibile eseguire la build più veloce (in parallelo) se non si partiziona la build in moduli separati.


0

Penso che al tuo team manchi uno dei principi chiave della mischia: software funzionante e funzionante. Un PBI non dovrebbe essere contrassegnato come fatto fino a quando non avrà superato la Definizione di Fine stabilita dal team. La definizione di Fatto è diversa per ogni squadra, ma probabilmente includerebbe cose come:

  • Il codice ha test unitari
  • Test unit test come parte di una build automatizzata
  • Il codice è stato unito al principale (e i conflitti sono stati risolti)
  • eccetera.

Quindi, in sostanza, ciò che sta accadendo è che la tua squadra sta segnando cose fatte che in realtà non sono state fatte. Questo è un problema in sé.

Oltre a ciò, si riduce alla corretta gestione del controllo della versione. Se stai usando Git, allora tutto il lavoro viene svolto nel repository locale dello sviluppatore e non dovrebbero spingere nulla a distanza a meno che non sia "fatto" e potenzialmente rilasciabile. Il lavoro incompleto non dovrebbe mai essere inviato al repository principale. Se lo sviluppatore ha bisogno di lavorare su un ramo di funzionalità più longevo e vuole spingere in remoto per assicurarsi che non perda il proprio lavoro, allora dovrebbe lavorare su un fork e quindi uniresti quel fork in main quando la funzione è "completata" e potenzialmente rilasciabile, non prima.

Per TFVC, è leggermente più complicato perché tutto accade su "remoto". Ciò significa che gli sviluppatori dovrebbero quindi sempre lavorare fuori dai rami, a meno che non sia una soluzione rapida. Le stesse regole si applicano qui come con Git, tuttavia: il software incompleto non si impegna. Periodo. Nel controllo di versione gestito correttamente, "main" dovrebbe essere sempre rilasciabile. Se è stato effettuato un commit che ha "main", allora non lo stai facendo bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.