Dopo aver suddiviso il nostro codice in bit riutilizzabili, come testiamo e implementiamo?


9

Abbiamo iniziato con uno sviluppatore e un repository svn contenente tutto il nostro codice:

^/foo/trunk/module-a
^/foo/trunk/module-b
^/foo/trunk/module-b/submodule-b1
^/foo/trunk/website1

(al momento questo è stato un grande miglioramento). Dopo che ciò ha avuto la possibilità di crescere per un po ', abbiamo iniziato a riscontrare problemi con dipendenze circolari, test di ricerca lenti e difficoltà generali nel riutilizzo del codice (dal momento che, ad esempio, il set di funzionalità di website1 si era insinuato nel modulo-a altrimenti generico).

Volendo modulare la base di codice e aspettandoci di passare a git a breve (e avendo letto da qualche parte che a git non piacciono i mega-repository svn), siamo passati a una struttura molto più granulare:

^/module-a/trunk/
^/module-b/trunk/
^/module-b/trunk/sumbmodule-b1
^/earlier-sub-sub-sub-module-c/trunk
etc. (about 120 such modules)

Questo è stato concettualmente fantastico. Codice più modulare, suite di test molto più veloci, più facile da documentare, ecc. Abbiamo acquisito alcuni dei nostri componenti più generici e reso installabili tutti i moduli pip (usando pip install -e .per installarli in developmentvirtualenv).

Abbiamo creato un ^/srv/trunkrepository contenente la struttura di cartelle dell'ambiente di runtime, ad es. ^/srv/trunk/libper i moduli, /srv/trunk/srcper i resti di ^/foo/trunk, ^/srv/trunk/wwwper siti Web ecc.

E infine (prendendo un'idea da perforce, con cui ho lavorato molto tempo fa [ https://www.perforce.com/perforce/r12.1/manuals/cmdref/client.html] ) abbiamo creato un "vcs- recuperare "file di testo che elenca tutti i repository rilevanti e dove devono essere estratti nell'ambiente di sviluppo e un comando corrispondente per farlo. Ad esempio una linea vcs-fetc:

svn srv/lib/module-a ^/module-a/trunk

causerebbe entrambi (la prima volta)

cd /srv/lib && svn co ^/module-a/trunk module-a

o (in seguito)

cd /srv/lib/module-a && svn up

e allo stesso modo per i repository github (sia i nostri pacchetti fornitori che quelli alterati / inalterati).

Abbiamo usato lo stesso processo di vcs-fetch per creare l'ambiente di produzione, ma stiamo rapidamente scoprendo che non abbiamo modo di sapere quale versione era utilizzata in prod dopo aver eseguito un vcs-fetch.

Con il mega-repository, potremmo solo notare il numero di revisione prima di aggiornare prod da trunk, e tornare indietro era un semplice passo indietro svn -r nnn up .. Con il codice sia in svn che in git (e un modulo in hg) - e ~ 120 repository, non è ovvio come farlo.

Ho letto http://12factor.net/ oggi e il primo fattore è "One codebase", quindi mi chiedo anche se sono fuori strada giusta qui?

Un'idea che ho avuto è stata quella di creare uno script di distribuzione in grado di creare ruote di "distribuzione" installabili tramite pip e "raggrupparle" in un requirements.txtfile. Una distribuzione implicherebbe quindi la creazione di un nuovo virtualenv, l'installazione pip del file requisito.txt che elenca le ruote di distribuzione e il cambio del virtualenv attivo. Il ritorno al precedente implicherebbe semplicemente il ripristino della virtualenv (ma a meno che non volessimo mantenere la virtualenv in giro per sempre, non ci permetterebbe di tornare indietro nel tempo - nella mia esperienza che non è mai stata necessaria).

A questo punto mi chiedo se sto camminando nella direzione sbagliata o se non ho camminato abbastanza lontano sulla strada giusta ..? (tutto quello che sto leggendo continua a parlare della "tua app", e non so come questo si traduca nella gestione di 14 siti Web al di fuori della stessa base di codice ...)


Posso supporre che i singoli componenti siano ora sviluppati da diversi team con cicli di sviluppo divergenti? In tal caso, la suddivisione del repository è inevitabile in entrambi i casi. Anche se con git, dovresti posizionare i tag di rilascio sincronizzati per le configurazioni principali e stabili. Dai un'occhiata allo strumento repository di Google. Tentare di abbinare le versioni di sviluppo con metadati integrati è praticamente inutile. Anche il collegamento dell'applicazione tramite pip è perfettamente legittimo.
Ext3h

Se includi stime KLOC (1000 righe di codice) e misure di byte del codice, possiamo facilmente avere un'idea della dimensione, ad esempio "2000 righe di codice. 50 kilobyte di codice sorgente". o "40 KLOC, 2 GB XML". . Sembra che ciò di cui hai bisogno per migrare su git e git abbia funzioni di importazione. Puoi iniziare leggendo il libro git .
Niklas,

1
@ Programmer400 il codebase è: .py 670 kloc, .js: 135kloc, .less: 25kloc, .html: 130kloc. Così grande, ma non enorme. Da quello che ho letto git non piace molto i repository di queste dimensioni, quindi immagino che dovremo dividere in repository più piccoli prima di passare a git ..?
thebjorn,

Risposte:


2

Sembra che manchi i rami (o piuttosto "tag" o "rilascio").

Invece di usare il tuo revnum SVN come riferimento per determinare quale versione stai installando, dovresti creare un ramo in quella revisione rilasciata. Quindi distribuire il nome di quel ramo.

Rende più facile ramificarsi anche se non ci sono modifiche, quindi ogni modulo mantiene lo stesso numero di rilascio, tuttavia ai pacchetti OSS potrebbe non piacere essere ramificato senza modifiche, quindi la cosa migliore è mantenere uno script di dipendenze - quindi versione 5 del tuo prodotto richiede il modulo OSS X v2 e così via.

Cambieresti il ​​tuo script per smettere di fare riferimento alle versioni e invece lavoreresti con i nomi dei rami (anche se possono essere qualsiasi cosa, è meglio decidere su una convenzione di denominazione fissa, ad esempio Release_1_2_3)

Un altro suggerimento è quello di mantenere un file con ogni modulo che descriva la versione corrente, è possibile generarli automaticamente se necessario e forse includere anche un log delle modifiche completo, ma significa che chiunque può vedere quale versione viene distribuita semplicemente guardando.


1

Penso che tu abbia già molte buone idee, ne ho utilizzate la maggior parte in vari progetti nel corso degli anni e la tua preoccupazione principale sembra essere l'incapacità di dire quale versione di tutti i moduli fosse inclusa in un determinato pacchetto se dividi li su.

Sono tutto per dividerli, ad un certo livello di granularità, specialmente se hai più team e vari cicli di rilascio, come menziona @ Ext3h.

Dal momento che non sono sicuro di quanto siano isolati i tuoi moduli o di quanto dettagliato desideri che il tuo controllo delle versioni sia, suggerirò alcune opzioni.


Usa i sottomoduli git. Con i sottomoduli, puoi memorizzare ciascun modulo in un repository git separato, simile alla tua configurazione svn, e anche a quello a cui stai pensando. Quindi collegare tali moduli al progetto radice che conterrà un riferimento al commit pertinente di ciascun sottomodulo, per ciascuno dei propri commit.

IMO questa è una configurazione teoricamente piacevole e ragionevolmente semplice. Gli svantaggi principali sono che il flusso di lavoro per i sottomoduli è un po 'imbarazzante, tuttavia sembra che tu abbia risolto queste cose bene con gli script prima, quindi potrebbe non essere un vero problema.

L'altro avvertimento è che i riferimenti al commit del sottomodulo saranno solo SHA1, non ci sono mai dettagli leggibili dall'uomo su quale ramo sei e potresti finire per dover controllare manualmente il ramo giusto quando vuoi fare un lavoro direttamente nel sottomodulo.

Tuttavia, non ho usato questo modello ampiamente, quindi non so quanto possa essere un problema per un grande progetto come il tuo.


Un'altra alternativa è quella di utilizzare una sorta di gestore delle dipendenze. Ciò richiede che ogni modulo o set di moduli possa essere aggiornato, impacchettato e pubblicato singolarmente e che si disponga di un sistema in grado di riunire i pacchetti nel modo desiderato quando desiderato.

Stai già suggerendo pip e ciò che sembra mancare nel tuo suggerimento è la memorizzazione dei requisiti risultanti. Txt insieme alla build o nel repository del progetto radice, in modo da poter ricreare virtualenv in un secondo momento anziché dover salvare su disco.

Esistono anche altri sistemi; Ho creato un progetto piuttosto grande usando una versione leggermente personalizzata di Apache Ivy sia come strumento per impacchettare e pubblicare ciascun modulo, sia per metterli insieme per il progetto finale. Ivy memorizza anche un manifest che elenca tutte le versioni di tutti i moduli a cui fai riferimento, se devi ricreare l'installazione in un secondo momento.

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.