2009-12-14 19 views
9

La mia azienda ha difficoltà a trovare il modo migliore per gestire le nostre build, versioni e diramazioni ... La nostra configurazione di base è che abbiamo 4 applicazioni che gestiamo 2 applicazioni WPF e 2 ASP. Le applicazioni NET, tutte e 4 di queste applicazioni condividono le librerie comuni, quindi attualmente sono tutte in una cartella/trunk/{app1, app2, app3, app4}.Gestione dipendenze .NET e tagging/ramificazione

Questo rende molto difficile ramificare/taggare una singola applicazione perché si stanno ramificando tutti e 4 contemporaneamente, quindi vorremmo separarlo in qualcosa come {app1, app2, app3, app4}/{trunk , tag, rami} ma poi ci imbattiamo nel problema di dove mettere le librerie condivise?

Non possiamo mettere le librerie condivise come estensioni SVN perché quando si dirama/tag il ramo fa ancora riferimento alle librerie condivise del tronco invece di averle anch'esse diramate.

Qualche consiglio? Idee?

Attualmente stiamo utilizzando svn e cruisecontrol.net.

MODIFICA: Le librerie condivise stanno cambiando spesso sin da ora, motivo per cui non possiamo utilizzarle come estensioni svn per il trunk, perché potremmo cambiarle nel ramo. Quindi non possiamo usarli come riferimenti binari.

È anche molto difficile da testare e eseguire il debug quando le librerie sono costruite in modo statico invece di includere l'origine.

risposta

6

Suppongo che tutto dipenda dalla stabilità delle librerie condivise. La mia preferenza sarebbe che le librerie condivise fossero trattate come il loro progetto, costruito in CruiseControl come gli altri. Quindi le quattro applicazioni principali avrebbero riferimenti binari alle librerie condivise.

Il vantaggio principale con questo approccio è la stabilità delle applicazioni ora che le librerie condivise sono statiche. Una modifica alle librerie non avrebbe influito sulle applicazioni fino a quando non aggiornassero esplicitamente i binari alla versione più recente. Branching porta con sé i riferimenti binari. Non avrai la situazione in cui un cambiamento apparentemente innocuo rompe le altre tre applicazioni.

+0

Le librerie condivise stanno cambiando spesso sin da ora, motivo per cui non possiamo usarle come estensioni esterne per trunk, perché potremmo cambiarle nel ramo. Quindi non possiamo usarli come riferimenti binari. – sontek

+0

Se si aggiungono alle librerie condivise, inserire il nuovo codice nell'applicazione nel ramo, quindi spostarlo nelle librerie condivise solo quando necessario da una delle altre app. Esegui lo sviluppo dell'applicazione fino alla sua completa verifica, quindi esporla alle altre app solo quando necessario. Probabilmente non dovrebbe _change_ le librerie condivise diverse dalle correzioni di errori - la funzionalità/l'interfaccia di classi/metodi esistenti dovrebbe generalmente rimanere la stessa. Principio aperto/chiuso - aggiungere funzionalità, non modificare esistente. –

+0

Queste librerie condivise sono il fulcro delle nostre applicazioni, se viene trovato un errore o una nuova funzionalità, deve essere modificata. Ad esempio, una di queste librerie condivise è costituita da alcuni controlli utente di asp.net utilizzati in entrambe le applicazioni, pertanto di recente ho rielaborato i controlli della carta di credito/pagamento per aggiungere funzionalità del piano di pagamento (i piani di pagamento sono una nuova esigenza aziendale). Ovviamente non volevo modificare i controlli di pagamento nel bagagliaio perché ciò avrebbe interferito con il lavoro di tutti gli altri. Quindi avevo bisogno di diramarmi finché non ho funzionato e poi unirli di nuovo nel bagagliaio. – sontek

1

Sono d'accordo con @Brian Frantz. Non c'è motivo di non considerare le librerie condivise come il proprio progetto che viene costruito quotidianamente e i progetti prendono dipendenza binaria dalle build giornaliere.

Ma anche se si desidera tenerli come dipendenza di origine e crearli con l'app, perché gli esterni di SVN non dovrebbero funzionare per te? Quando si dirama un'app specifica, non è necessario suddividere la libreria condivisa, a meno che non si abbia bisogno di una copia separata di tale ramo. Ma questo significa che non è più una libreria condivisa, giusto?

+0

Le librerie condivise stanno cambiando spesso sin da ora, motivo per cui non possiamo usarle come estensioni esterne per trunk, perché potremmo cambiarle nel ramo. Quindi non possiamo usarli come riferimenti binari. Il motivo per cui dovremmo dirlo è che potremmo apportare modifiche importanti che avrebbero effetto sulle librerie condivise, ma non vogliamo rompere gli altri progetti finché il cambiamento non viene corretto e testato nel ramo, e poi quando lo uniamo nel bagagliaio, sistemeremo le chiamate ad esso nelle altre app. – sontek

+0

Questa è una ricetta del disastro. Cosa succede quando si diramano due app e si diramano le librerie condivise per entrambi? L'unione delle modifiche alle librerie condivise può (e probabilmente sarà) un incubo logistico. (Sono stato lì, fatto così :-)) –

+0

Beh, ovviamente questa è una preoccupazione ma dobbiamo fare affidamento su una buona comunicazione tra i nostri sviluppatori, ci dovrebbero essere pochissime volte che devono lavorare sulle stesse esatte linee e se lo fanno le stesse linee e sono in conflitto, abbiamo gli strumenti diff per capire cosa è andato storto, è solo una parte dello sviluppo con una squadra :) Penso che sia molto meglio avere il codice ramificato così * tutto * che cambiano sia in quella diramazione e che non interessa altri sviluppatori, l'unica volta in cui ci spostiamo è quando stiamo per apportare modifiche di rottura :) – sontek

1

Ho provato a risolvere questo problema in diversi modi nel corso degli anni e posso dire onestamente che non esiste la soluzione migliore.

La mia squadra è attualmente in una fase di sviluppo enorme e tutti hanno fondamentalmente bisogno di lavorare con le ultime e più grandi librerie condivise in un dato momento. Stando così le cose, abbiamo una cartella sull'unità C: C, chiamata SharedLibs \ Latest, che viene automaticamente sincronizzata con l'ultima versione di sviluppo di ciascuna delle nostre librerie condivise. Ogni progetto che dovrebbe bere da Firehose ha riferimenti a file assoluti in questa cartella. Mentre le persone spingono fuori nuove versioni delle librerie condivise, i singoli progetti finiscono per raccoglierli in modo trasparente.

Oltre alla cartella più recente, abbiamo una cartella SharedLibs \ Releases che ha una gerarchia di cartelle denominate per ogni versione di ogni lib condivisa.Man mano che i progetti maturano e arrivano alla fase di rilascio del candidato, i riferimenti di lib condivisi sono puntati su queste cartelle stabili.

Il più grande svantaggio di questo è che questa struttura deve essere presente per qualsiasi progetto da costruire. Se qualcuno vuole costruire un'app tra 10 anni, avrà bisogno di questa struttura. È importante notare che queste cartelle devono esistere anche sul server build/CI.

In precedenza, ogni soluzione disponeva di una cartella lib sotto il controllo del codice sorgente contenente i file binari. Ogni proprietario del progetto è stato incaricato di propagare nuove DLL condivise. Dato che la maggior parte delle persone possedeva diversi progetti, le cose spesso cadevano attraverso le fessure dei progetti che erano ancora nella fase non stabile. Inoltre, TFS non sembrava tenere traccia delle modifiche ai file binari. Se TFS fosse migliore nel tracciare le DLL, probabilmente avremmo usato una soluzione/progetto di libs condivisa invece dell'approccio del file system che stiamo adottando ora.

+0

Dai un'occhiata a Apache NPanday + Maven Release + Nexus Repository Manager (sono un committer e un utente ci ha appena chiesto di rendere NPanday più visibile, perché è fantastico :-)) –

4

Puoi chiarire perché non ti piace ramificare tutte e quattro le applicazioni contemporaneamente?

Questo rende molto difficile ramo/tag di una singola applicazione, perché si sta ramificazione tutti e 4 allo stesso tempo

Io di solito mettere tutti i miei progetti direttamente sotto il tronco, come si sta facendo. Quindi quando creo un ramo di rilascio o un ramo di funzionalità, ignoro semplicemente gli altri progetti che vengono portati avanti. Ricorda, le copie sono economiche, quindi non occupano spazio sul tuo server.

Per essere precisi, ecco come avrei lay out dei sorgenti che hai descritto:

  • tronco
    • WPF1
    • WPF2
    • ASP.NET 1
    • ASP .NET 2
    • lib1
    • lib2
  • rami
    • WPF1 v 1,0
      • WPF1
      • WPF2
      • ASP.NET 1
      • ASP.NET 2
      • lib1
      • lib2
    • WPF1 v 1,1
      • WPF1
      • WPF2
      • ASP.NET 1
      • ASP.NET 2
      • lib1
      • lib2
    • piano di pagamento lib1
      • WPF1
      • WPF2
      • ASP.NET 1
      • ASP.NET 2
      • lib1
      • lib2
+0

La copia sul server è economica ma il checkout e copia sul computer degli sviluppatori non è economico, la maggior parte degli sviluppatori preferisce mantenere l'intero repo verificato nel caso in cui debbano lavorare su un ramo con qualcuno, lo avranno già abbattuto, ma questo inizia a prendere per sempre quando hai alcuni rami e tag in corso. Ma finora, questa sembra essere la soluzione migliore :) – sontek

+2

Nella vostra situazione, vorrei controllare il bagagliaio o una singola filiale, qualunque cosa stia lavorando. Quindi utilizzare l'interruttore per lavorare su un altro ramo. Potrei controllare due copie di lavoro, quindi posso lasciarne una sul mio ramo di lavoro principale e usare l'altra per spostarmi quando faccio piccoli lavori su altri rami. Qualcos'altro da considerare sono casse poco profonde: controlla l'intero repository dalla radice, ma non reclamare la cassa fino ai rami finché non ne hai bisogno. Trovo questo più fastidioso perché sbarazzarsi di un ramo dalla cassa è una seccatura. –

+2

Sono d'accordo che questo è l'approccio corretto. Gli sviluppatori che controllano l'intero repository è un comportamento che può cambiare: non c'è motivo di avere una soluzione sub-standard solo per soddisfare ciò che è effettivamente la pigrizia, IMHO. In aggiunta a ciò, mentre qualcuno sta lavorando sul ramo sperimentale WPF 1.1, non voglio aspettare di ricevere tutti questi aggiornamenti mentre sto solo provando a lavorare su un ramo specifico. – gregmac

4

Ci stanno avviando un progetto open source per cercare di affrontare questo problema. Se qualcuno è interessato a commentare su di esso o contribuire ad esso, è a:

http://refix.codeplex.com

+0

Vedere [la domanda sulle alternative Maven] (http://stackoverflow.com/q/652583/4794) per un elenco di strumenti .NET per gestire le dipendenze binarie. Tuttavia, penso che tu ottenga il massimo beneficio usando questi strumenti per gestire i binari di terze parti. Personalmente, preferisco creare librerie dal sorgente se il mio team le ha scritte. –

1

Apache NPanday + Apache Maven Release

... potrebbe risolvere i vostri problemi

Ti dà dependeny gestione (transitive risoluzione), supporto per il controllo delle versioni e tag/ramificazione automatici su sistemi di controllo versione 14+, incluso SVN.

Dammi un suggerimento, se dovessi elaborare di più.

Penso che non ci sia modo di evitare il controllo delle versioni e la distribuzione delle librerie condivise come artefatti separati, ma Maven ti aiuta molto a farlo!

e sempre si può fare trucchi per ottenere tutto aperto in un'unica soluzione :-)

Un flusso di lavoro di esempio:

  1. Dev 1 costruire un utilizzo a livello locale Maven
  2. Controlli nelle fonti
  3. Il build build genera A e distribuisce le cosiddette SNAPSHOT-Versions to Repository Manager (e.g. Nexus)
  4. Dev 2 2 carichi B, NPanday risolverà automaticamente l'A- librerie dal Gestore del repository (Nessuna necessità di ottenere l'origine e la compilazione)
  5. Dev 1 vuole rilasciare A: Maven Release crea un ramo o un tag con l'origine, finalizza la Versione (rimuovendo SNAPSHOT) e distribuisce le risorse in un Responsabile del deposito.
  6. Dev 2 può ora aggiornare B per utilizzare la versione finale di A (modificare la voce in xml o utilizzare VS-addin per farlo)
  7. Ora Dev 2 può rilasciare B, di nuovo con la creazione automatica di tag o ramo e distribuzione di artefatti costruiti.

Se si desidera fornire pacchetti zippati come output dalla build, Maven Assembly Plugin ti aiuterà a farlo.

0

È possibile utilizzare Apache/IVY in modalità standalone.

http://ant.apache.org/ivy/history/latest-milestone/standalone.html

ho bisogno di sottolineare "stand alone". Se cerchi google per gli esempi .... troverai molti (non autonomi).

Fondamentalmente, IVY funziona su questa premessa.

Si pubblicano binari (o qualsiasi tipo di file, ma dirò i binari da questo punto in poi) ..... come piccoli pacchetti binari.

Di seguito è il codice PSEUDO, non fare affidamento sulla mia memoria.

java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.4 (< < dove il XML si riferisce al numero N di file che costituiscono l'unico pacchetto.))

"pacchetto" significa semplicemente un gruppo di file. È possibile includere file .dll e .xml e .pdb in un pacchetto (cosa faccio con una build di assiemi DotNet). O qualsiasi altra cosa IVY è agnostico di tipo file. Se vuoi mettere WordDocs lassù, potresti farlo, ma sharepoint è meglio per i documenti.

Come si apportano correzioni di errori al codice, si incrementa la revisione.

java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.5

poi è possibile recuperare dal IVY ciò che si desidera.

java.exe ivy.jar -retrieve PackagesINeed.xml 

PackagesINeed.xml conterrà informazioni sui pacchetti desiderati.

qualcosa come "Voglio la versione '1.2+ del MyBinaryPackageOne" (definito in XML)

come costruire la vostra binari quadro ... si pubblica IVY. Quindi, mentre sviluppi e costruisci il tuo codice ... ti riprendi da Ivy.

In un NUTSHELL, IVY è un repository per FILE (non codice sorgente).

L'edera diventa quindi la fonte definitiva dei file binari.

Nessuno dei "Hey, Developer-Joe ha i binari di cui abbiamo bisogno" tipo di bull-pasticcio.

.......

Vantaggi: 1. non tenere i binari nel controllo del codice sorgente. (e quindi non BLOAT il controllo del codice sorgente). 2. Si dispone di UNA sorgente definitiva per i binari. 3. Tramite la configurazione xml, si indicano quali versioni sono necessarie per una libreria. (nell'esempio sopra, se la versione 2 (2.0.0.0) di MyBinaryPackageOne è pubblicata su IVY (assumiamo con interruzione delle modifiche da 1.2.xy) ... allora sei OK, perché hai definito nel tuo richiamo (file di configurazione xml) .. che vuoi solo "1.2+", quindi il tuo progetto ignorerà qualsiasi cosa 2 + ... a meno che tu non modifichi il pacchetto di configurazione

Avanzato: Se hai una macchina di compilazione (ad esempio CruiseControl.NET) .... è possibile scrivere la logica per pubblicare i binari (di nuova costruzione) su IVY dopo ogni generazione. (che è quello che faccio).

Io uso la revisione SVN come l'ultimo numero nel numero di build. Se la mia revisione SVN è stato "3333", quindi vorrei correre qualcosa di simile:

java.exe ivy.jar -publish MyBinaryPackageOne.xml --revision 1.2.3.3333

Così ogni volta che recuperare il pacchetto di revisione "1.2.3+" .... vado a prendere l'ultimo costruire. In questo caso, otterrei la versione 1.2.3.3333 del pacchetto.

È triste che IVY sia stato avviato nel 2005 (beh, questa è una buona notizia) ... ma quel NUGET non è uscito fino al 2010? (2011?) Microsoft aveva 5-6 anni di ritardo su questo, IMHO.

Non tornerei mai a mettere i binari nel controllo del codice sorgente.

IVY è molto buono. È ora dimostrato. Risolve il problema della gestione della DIPENDENZA.

Ci vuole un po 'di tempo per sentirsi a proprio agio? Sì.

Ma ne vale la pena alla fine.

I miei 2 centesimi.

.................

Ma l'idea # 2 è Imparare ad usare Nuget con un locale (come in..local per la vostra azienda) repository .

Questa è la stessa cosa di IVY.

Ma guardando NUGET, mi piace ancora l'IVY.