39

Ho un'applicazione web in cui distribuiamo in produzione ogni volta che una funzione è pronta, a volte può essere un paio di volte al giorno, a volte può essere un paio di settimane tra una release e l'altra.Qual è il modo Maven per le versioni di progetto automatiche quando si effettua la consegna continua?

Attualmente, non incrementiamo i numeri di versione per il nostro progetto e tutto è rimasto nella versione 0.0.1-SNAPSHOT per oltre un anno. Mi chiedo quale sia il modo Maven per eseguire la consegna continua per le app Web. Sembra eccessivo dare il numero di versione su ogni commit e non sbattere mai il numero di versione come stiamo facendo ora, sembra anche sbagliato.

Qual è la migliore prassi consigliata per questo tipo di utilizzo di Maven?

Il problema è in realtà un duplice uno:

  • Avanzando numero di versione del progetto in singolo file pom.xml (e ci possono essere molti).
  • Aggiornamento del numero di versione in tutti i componenti dipendenti per utilizzare i più recenti uno dell'altro.

risposta

32

vi consiglio il seguente presentazione che discute le realtà pratiche del doi ng erogazione continua con Maven:

L'asporto chiave è ogni generazione è un potenziale di rilascio, in modo da utilizzare il plugin Maven rilascio e non utilizzare le istantanee.

+0

Sto contrassegnando questo come la risposta corretta perché il video di You Tube è stato eccellente nel rispondere a questa domanda esattamente.Tuttavia, ho dovuto fare una pausa e riavvolgere alcune volte per ottenere dei punti più sottili. ho inserito un riassunto del processo raccomandato nel video nella mia risposta. – ams

+1

Il video è abbastanza buono e ti aiuterà a caricare. @ 23m35s nel video, direi che Maven dovrebbe fare la maggior parte delle verifiche di sanità mentale a breve termine, come test unitari, controlli di copertura, test di integrazione, ecc ... tuttavia la consegna continua non si ferma qui. Per le più grandi organizzazioni di tipo SOA, la suddivisione della pipeline in fasi discrete è una pratica molto buona, ad esempio test funzionali con endpoint simulati, test delle prestazioni, test di integrazione, test UAT, verifica della conformità, analisi del codice statico, revisione della sicurezza, ecc. – user924272

+0

Ottimo video. La mia unica preoccupazione è che cosa fanno le persone riguardo a tutti i "release candidate" nel repository di rilascio, che non vengono mai rilasciati ufficialmente? Abbiamo un programma di pulizia impostato per i nostri SNAPSHOT, tuttavia gli artefatti di rilascio sono conservati per sempre. Lo vedo usando un sacco di spazio su disco, sul lato delle cose del repository Maven. – Patrick

8

Ci sono alcuni grandi discussioni e proposte come affrontare il numero di versione Maven ed erogazione continua (CD) (li aggiungerò dopo la mia parte della risposta).

Quindi prima la mia opinione sulle versioni di SNAPSHOT. In Maven, SNAPSHOT mostra che questo è attualmente in fase di sviluppo per la versione specifica prima del suffisso SNAPSHOT. Per questo motivo, strumenti come Nexus o il plugin di rilascio di Maven hanno un trattamento speciale per SNAPSHOTS. Per Nexus sono archiviati in un repository separato e sono autorizzati ad aggiornare più artefatti con la stessa versione di rilascio SNAPSHOT. Quindi uno SNAPSHOT può cambiare senza che tu lo sappia (perché non aumenti mai alcun numero nel tuo pom). Per questo motivo non consiglio di usare le dipendenze di SNAPSHOT in un progetto, specialmente in un mondo di CD, dato che la compilazione non è più affidabile.

SNAPSHOT come versione del progetto sarebbe un problema quando il progetto viene utilizzato da altri, a causa dei motivi sopra riportati.

Un altro problema di SNAPSHOT per me è che non è più tracciabile o riproducibile. Quando vedo una versione 0.0.1-SNAPSHOT in produzione ho bisogno di fare qualche ricerca per scoprire quando è stata costruita da quale revisione è stata costruita. Quando trovo una versione di questo software su un filesystem, ho bisogno di dare un'occhiata al pom.properties o al file MANIFEST per vedere se questa è una vecchia spazzatura o forse la versione più recente e più grande.

Per evitare la modifica manuale del numero di versione (soprattutto quando si costruiscono più build al giorno) lasciare che Build Server modifichi il numero. Così, per lo sviluppo vorrei andare con una versione

<major>.<minor>-SNAPSHOT 

ma quando la costruzione di una nuova versione della build dei server potrebbe sostituire l'ISTANTANEA con qualcosa di più unico e rintracciabile.

Per esempio uno di questo:

<major>.<minor>-b<buildNumber> 
<major>.<minor>-r<scmNumber> 

Così il numero maggiore e minore può essere utilizzato per questioni di marketing o per semplicemente mostrare che un nuovo grande traguardo viene raggiunto e può essere modificato manualmente, quando mai lo vuoi . E il numero build (numero dal server di Continuous Integration) o il numero scm (Revision of SUbversion o GIT) rendono ogni release univoca e tracciabile. Quando si utilizza la revisione buildNumber o Subversion, le versioni del progetto sono anche ordinabili (non con i numeri GIT). Con buildNumber o scmNumber è anche abbastanza facile vedere quali cambiamenti ci sono in questa versione.

Un altro esempio è il controllo delle versioni dei StackOverflow che utilizzano

<year>.<month>.<day>.<buildNumber> 

E qui i collegamenti mancanti:

+1

Il primo collegamento Versioning in una pipeline è rotto –

+0

Sembra essere rimosso. Non ho trovato un link sostitutivo o il contenuto di una cache web :(. – mszalbach

+0

Questa risposta riguarda più il formato del nome della versione e il suo significato. Ci sono già abbastanza specifiche formalizzate [chiamate "versioning semantico"] (http: // semver .org /) - basta aggiungere "SNAPSHOT" per indicare la versione "non ancora rilasciata" e il formato della versione è ** non ** davvero un problema in Maven e lì ** ci sono [alcune restrizioni] (http: // goo.gl/JW9PS7)**.Il problema è rendere questo processo _effortless_ e preferibilmente _automatic_ (almeno fino al rilascio con semantic = versione manuale come 'XYZ') .Aggiornamento delle sezioni di più file' pom.xml' interdipendenti * * è ** il problema – uvsmtid

29

Questo è il mio riassunto basato sul video collegato dalla risposta di Mark O'Connor.

  • La soluzione richiede un git come DVCS e un server CI come Jenkins.
  • Non utilizzare le build di snapshot nella pipeline di Continuous Delivery e non utilizzare il plug-in di rilascio di Maven.
  • Le versioni di istantanee come 1.0-SNAPSHOT vengono convertite in versioni reali come 1.0.buildNumber dove lo buildNumber è il numero di lavoro di Jenkins.
  • passi

algoritmo:

  1. Jenkins cloni il repo git con il codice sorgente, e dire che il codice sorgente è la versione 1.0-SNAPSHOT
  2. Jenkins crea un ramo git chiamato 1.0.JENKINS-JOB-NUMBER così la versione istantanea viene trasformato in una versione reale 1.0.124
  3. Jenkins invoca il plug-in di versioni di Maven per modificare il numero di versione nei file pom.xml da 1.0-SNAPSHOT a 1.0.JENKINS-JOB-NUMBER
  4. Jenkins invoca mvn install
  5. Se il mvn install è un successo, allora Jenkins commetterà il ramo 1.0.JENKINS-JOB-NUMBER e una vera e propria versione non snapshot viene creato con un tag corretto in git per riprodurre in seguito. Se lo mvn install fallisce, Jenkins cancellerà semplicemente il ramo appena creato e fallirà la costruzione.

Consiglio vivamente il video collegato dalla risposta di Mark.

+1

Come gestisci un progetto multi-modulo maven? Hai appena rilasciato l'intero progetto e tutti i bambini con la stessa versione? Se ho un progetto A in base a B e faccio un commit nel progetto B, i passaggi precedenti sono attivati ​​per B, che quindi attiva i passaggi precedenti per il progetto A, ma come fa A conoscere la versione di B? – dukethrash

+1

Si tratta di un progetto multi-modulo, quindi l'esperienza mi dice che avere una singola versione ha senso - è coerente con il plugin delle versioni. Se alcuni moduli non cambiano così spesso, possono anche essere componenti separati estratti da un repository artefatto - ad esempio, log4j, sl4fj ... – user924272

+3

Beh, nel mio caso non è nemmeno un modulo multiplo.Ho un progetto A che dipende dal progetto B. Il progetto B ha il suo lavoro Jenkins e potrebbe avere un commit che genera un artefatto rilasciato. Il Progetto A deve quindi fare riferimento a questo artefatto rilasciato nel pom. Stai suggerendo di aggiornare manualmente il Progetto A quando la costruzione del Progetto B ha esito positivo e l'artefatto è disponibile? Il Progetto B è un progetto di base e il Progetto A è un'app Web in modo che siano accoppiati ma abbiano un grande sovraccarico nell'aggiornamento della dipendenza del Progetto A dal Progetto B, specialmente quando si sviluppa in un IDE che visualizza le modifiche con le dipendenze di SNAPSHOT. – dukethrash

5

NON FARE QUESTO!

<Major>.<minor>-<build> 

ti morderà nel sedere perché Maven considera nulla dopo un trattino come lessicale. Ciò significa che la versione 1 sarà lessicalmente superiore a 10.

Questo è un problema come se si stesse chiedendo l'ultima versione di qualcosa in Maven, quindi il punto sopra vince.

La soluzione consiste nell'utilizzare una virgola decimale anziché un trattino che precede il numero di build.

FARE QUESTO!

<Major>.<minor>.<build> 

E 'bene avere versioni offline localmente, ma come parte di una generazione, è meglio usare

mvn versions:set -DnewVersion=${major}.${minor}.${build.number} 

Ci sono modi per ottenere la versione principale/minore dal pom, per esempio usando help: valuta e reindirizza a una variabile d'ambiente prima di richiamare le versioni: set. Questo è sporco, ma ho davvero scalfito la mia testa (e altri nel mio team) per renderlo più semplice, e (al momento) Maven non era abbastanza maturo per gestire questo. Credo che Maven 2.3.1 potrebbe avere qualcosa che aiuta in qualche modo, quindi questa informazione potrebbe non essere più pertinente.

Va bene per un gruppo di sviluppatori rilasciare sulla stessa versione major.minor - ma è sempre bene essere consapevoli del fatto che le modifiche minori non violano e le modifiche delle versioni principali hanno qualche modifica dell'API di rottura, o la deprecazione della funzionalità/comportamento.

Da una prospettiva di consegna continua ogni build è potenzialmente rilasciabile, pertanto ogni check-in deve creare una build.

+4

Imposto da http://mojo.codehaus.org/versions-maven-plugin/version-rules.html e secondo i miei test, questo non è corretto. Lo schema di gestione delle versioni di Maven predefinito è '. . - '(con la maggior parte di esso opzionale). Finché la parte dopo il trattino è numerica, non verrà confrontata lessicalmente. Ho provato questo con 'versioni mvn: use-latest-versions'and per es. '1.4-11' viene rilevato correttamente come nuovo di' 1.4-2'. –

+0

Quale versione di Maven hai testato con questo? Inoltre, hai provato a installare anche una versione 1.4.21, poi a giocare per scoprire come funziona la risoluzione della gamma di versioni di Maven? Sarebbe interessante conoscere le tue scoperte, poiché ho sicuramente questo problema con 2.2.1, e ho verificato ciò cercando nel codice sorgente di Maven. Inoltre, non penso che queste regole si applichino effettivamente a qualsiasi cosa eccetto il plugin delle versioni, e sto parlando della risoluzione delle dipendenze. – user924272

+0

Seguire https://docs.oracle.com/middleware/1212/core/MAVEN/maven_version.htm#MAVEN401 @philipp è corretto. È sicuro usare numeri incrementali in $ {major}. $ {Minor}. $ {Build.number} e $ {major}. $ {Minor}. $ {Build.number} - $ {patchNumber}, ma non $ {major}. $ {minor}. $ {build.number}. $ {patchNumber} – iMysak

1

Al mio lavoro per le applicazioni web che attualmente utilizzano questo schema di controllo delle versioni:

<jenkins build num>-<git-short-hash>

Esempio: 247-262e37b9.

Questo è bello perché ti dà una versione che è sempre unica e rintracciabile alla build di jenkins e alla revisione git che l'ha prodotta.

In Maven 3.2.1+ alla fine hanno ucciso gli avvisi per l'utilizzo di $ {property} come versione, in modo che sia davvero facile crearli. Basta cambiare tutti i tuoi poms per usare <version>${revision}</version> e creare con -Drevision=whatever. L'unico problema è che nei tuoi poms rilasciati la versione rimarrà allo ${revision} nel vero file pom che può causare tutti i tipi di problemi strani. Per risolvere questo ho scritto un semplice plugin Maven (https://github.com/jeffskj/cd-versions-maven-plugin) che sostituisce la variabile nel file.

+0

Il plugin sembra una soluzione per aggiornare le versioni dei file 'pom.xml'. Tuttavia, il prossimo problema è di aggiornare le versioni all'interno della sezione 'dependencies' di tutti i componenti dipendenti che partecipano al rilascio in modo che possano effettivamente utilizzare l'ultimo l'uno dell'altro. Ho ** [questo problema quando l'aggiornamento automatico è inaffidabile] (http://stackoverflow.com/q/31579730/441652) ** in build multi-modulo/reattore (che aggiorna componenti esterni e non solo interni). Quindi, la soluzione a breve termine per rimanere in 'SHAPSHOT's. ** Qualche commento su come hai risolto questo problema? ** – uvsmtid

+0

In pratica non dovresti usare le versioni di istantanee. Aggiorna le versioni delle dipendenze prima di costruire. –

+0

Mantieni tutti i moduli thr nella stessa versione. Nel modulo root la sezione dependencyManagement imposta i moduli su '$ {project.version}'. Quindi semplice 'versioni mvn: set -DnewVersion = whatever' farà il trucco e cambierà le versioni nell'ordine del reattore compresi i genitori ecc. –

6

A partire da Maven 3.2.1 erogazione continua versioni amichevoli sono supportate out of the box: https://issues.apache.org/jira/browse/MNG-5576 è possibile utilizzare 3 variabili predefinite nella versione:

${changelist} 
${revision} 
${sha1} 

Quindi quello che fondamentalmente fa è:

  1. Impostare la versione per esempio 1.0.0-${revision}. (È possibile utilizzare mvn versions:set per farlo in modo rapido e corretto nel progetto multi-modulo.)
  2. Mettere una proprietà <revision>SNAPSHOT</revision> per lo sviluppo locale.
  3. Nell'ambiente CI eseguire mvn clean install -Drevision=${BUILD_NUMBER} o qualcosa del genere o anche mvn clean verify -Drevision=${BUILD_NUMBER}.

È possibile utilizzare ad esempio https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin per generare numeri di build interessanti.

Una volta scoperto che la build è stabile (ad esempio, i test di accettazione dei passaggi) è possibile spingere la versione su Nexus o altro repository. Le build instabili vanno semplicemente nel cestino.

Problemi correlati