2015-08-25 15 views
15

Come aggiornare la versione dei moduli figlio? Ci sono molte domande StackOverflow come questa, ma non sono riuscito a trovarne una adatta a questo scenario esatto ... mi piacerebbe se si trattasse di un duplicato.Come aggiornare la versione dei moduli figlio in Maven?

Considerare il seguente progetto.

parent 
    --mod1 
    --mod2 

All'inizio di un ciclo di sviluppo Dev ho bisogno di aggiornare il genitore ei moduli alla stessa versione. Se la versione del genitore e dei moduli rimanesse la stessa per tutta la versione, vorrei semplicemente omettere il tag <version> dai moduli ed eseguire versions:set -DnewVersion=1.1.1 per avviare il ciclo di sviluppo. Ma a quanto pare i moduli non terminano tutti il ​​ciclo con la stessa versione. Come bug e correzioni si materializzano solo quei moduli con i bug e tali vengono aggiornati. Ad esempio genitore e mod2 potrebbero essere alla versione 1.1.1-RC1, ma mod1 potrebbe essere a 1.1.1-RC2.

Come tale, è necessario:
1) Includere un tag <version> nei moduli per tenere traccia di ogni versione dei moduli in modo indipendente.

2) Se mod2 richiede mod1 come dipendenza, è necessario verificare che mod2 faccia riferimento all'ultima versione di mod1.

Questo porta alle seguenti due domande.

1) All'inizio del ciclo, come è possibile impostare il padre e i moduli sulla stessa versione in un comando maven? Ho provato version:set -DnewVersion=1.1.1, ma questo aggiorna solo la versione del genitore attraverso tutti i POM ma non la versione del modulo. Ho anche provato -N versions:update-child-modules, ma penso di usarlo male perché non fa nulla, mostra solo saltato per tutti i moduli.

2) Questo è un po 'più difficile e corrisponde al punto 2 sopra. Come posso aggiornare sia la versione di mod1 che il riferimento di mod2 alla versione di mod1 in un solo passaggio? So come si fa in 2 fasi:

genitore pom:

<properties> 
    <!-- update this manually if mod1's version no longer matches parent --> 
    <mod1.version>${project.version}</mod1.version> 
</properties> 

mod2 pom:

<dependency> 
     <groupId>com.xxx</groupId> 
     <artifactId>mod1</artifactId> 
     <version>${mod1.version}</version> 
    </dependency> 

Quando mod1 urti fino a 1.1.1-RC2 aggiorno il POM genitore e mod1 POM per riflettere questo. Questi sono due passaggi. Ad ogni modo per trasformarlo in un unico passaggio?

Il mio esempio era piccolo ma nella vita reale ci sono molti moduli che rendono questo importante risparmio di tempo, in più sono curioso.

+0

Suggerirei di cambiare la procedura e di eseguire nuovi RC di tutti i moduli anche se solo alcuni di essi cambiano. Sincronizza il ciclo di rilascio e lascia che "release: prepare" gestisca l'aggiornamento della versione per te. – rec

+0

@rec Grazie per il consiglio. Questo era già sul tavolo come opzione. Qualche idea su come realizzare ciò che viene richiesto? –

+0

Ho visto un '$ {mod1.versione} 'variabile impostata nel padre pom, poi chiamata nel poms figlio' $ {mod1.version} 'e per le dipendenze, sebbene dagli avvertimenti di Maven 3, sono sicuro che ci sono molte buone ragioni per non farlo. – Rossiar

risposta

3

Domanda 1)

Il modo migliore per gestire il ciclo di vita delle applicazioni e uscite è quello di utilizzare il plugin di rilascio.

Come forse saprai, la filosofia di Maven è convenzione sulla configurazione. La convenzione di Maven consiste nell'usare le versioni di istantanee (quelle che terminano con -SNAPSHOT) durante lo sviluppo e l'assegnazione di una versione non istantanea solo per le versioni.

Supponiamo che stiate sviluppando la versione 1.1.1. Durante lo sviluppo, basta usare 1.1.1-SNAPSHOT. Maven si prenderà cura degli aggiornamenti dell'istantanea. Se si utilizza un repository di risorse, è possibile utilizzare -U per assicurarsi di avere sempre l'ultima versione delle istantanee.

Quando la versione è pronta, il plugin di rilascio genera e distribuisce la versione 1.1.1 e aggiorna POM con la nuova versione di sviluppo, ad esempio 1.1.2-SNAPSHOT.

I progetti multimodule presentano due scenari: i moduli sono correlati ma indipendenti (come diverse applicazioni Web) oppure sono moduli di un'unica grande applicazione o libreria e condividono le versioni. Sembri interessato a quest'ultimo.

Il modo migliore in questo caso è di ereditare lo stesso modulo genitore (forse anche root), inclusa la sua versione. Si fa riferimento al gruppo genitore: artefatto: versione e non si specifica una versione per i bambini. In genere si eredita anche il gruppo, così il vostro pom bambino può guardare come:

<parent> 
    <groupId>com.mycompany.myproject</groupId> 
    <artifactId>myproject-parent</artifactId> 
    <version>1.1.1-SNAPSHOT</version> 
    <relativePath>../myproject-parent</relativePath> 
</parent> 
<artifactId>myproject-module1</artifactId> 

Ora è solo bisogno di prendersi cura dei bambini che punta alla versione corretta del genitore, con l'aiuto del plugin rilascio.

Per aiutarlo a conoscere i bambini, è consigliabile creare un pom per le radici includendo la sezione dei moduli come mostrato di seguito.

Domanda 2) In genere dichiaro le proprietà nel genitore con tutte le versioni di tutti gli artefatti a cui è possibile fare riferimento. Se diversi moduli condividono la versione, hai solo bisogno di una proprietà. Il genitore può apparire come:

<groupId>com.mycompany.myproject</groupId> 
<artifactId>myproject-parent</artifactId> 
<version>1.1.1-SNAPSHOT</version> 
<packaging>pom</packaging> 
<properties> 
    <myproject.version>1.1.1-SNAPSHOT</myproject.version> 
</properties> 

....... 

<modules> 
    <module>../myproject-module1</module> 
    ... 
</modules> 

I bambini possono fare riferimento ad altri moduli usando

<version>${myproject.version}</version> 

Si tratta di una cattiva pratica di dichiarare le dipendenze che utilizza l'ultimo. Diciamo di farlo per la versione 1.1.1. Ora stai lavorando con la versione 1.1.2-SNAPSHOT e probabilmente hai artefatti con questa versione installata nel repository locale.

Ora diciamo per qualche motivo che è necessario ricostruire la versione 1.1.1, ad esempio a causa di un bug nella produzione. La tua build utilizzerà la nuova versione. Se sei fortunato, questo romperà la build. Se sei sfortunato, potrebbe anche passare inosservato alla produzione.

Ultimo ma non meno importante, ad alcune persone piace usare i valori delle proprietà per dichiarare le versioni dei bambini. Questo è fortemente scoraggiato e verrà segnalato come un avvertimento da parte di Maven. Io personalmente non lo faccio mai. Le ragioni sono anche legate alla riproducibilità delle build e al fatto che Maven suppone che una build di rilascio non cambierà mai. Avere una versione del modulo esternamente modificabile non è davvero una buona idea.

EDIT:

caso in cui le versioni del modulo non sono allineati.

In realtà entrambi gli scenari possono essere combinati. Si possono avere, per esempio:

Parent

--- Component1

--- Component2

--- Componente3

------ Comp3Module1

------ Como3Module2

------ Comp3Module3

Dove le versioni padre e le tre componenti sono diverse ei tre moduli di component3 condividono la stessa versione di prima spiegata.

Domanda 1) In questo caso ogni modulo ha la sua versione specificata in modo indipendente. Come detto prima, è un cattivo consiglio usare una proprietà per specificare la versione del modulo, motivo per cui posso solo raccomandare di specificare letteralmente le versioni. Come già detto, per gestire il controllo delle versioni, il modo migliore è utilizzare il plugin di rilascio e integrarlo con il sistema di controllo della versione, come SVN. Altre risposte forniscono dettagli su come usarlo, quindi non lo elaborerò ulteriormente, se non richiesto.

Domanda 2) L'approccio consigliato è lo stesso spiegato per il caso di condivisione della stessa versione, solo che sono necessarie diverse proprietà. Il genitore può apparire come:

<properties> 
    <myproject.group>com.mycompany.myproject</myproject.group> 
    <component1.version>1.1.1-RC1</component1.version> 
    <component2.version>1.1.1-RC2</component2.version> 
    <component3.version>2.0.0</component3.version> 
<properties> 

quindi è possibile utilizzare la gestione delle dipendenze per centralizzare la gestione delle versioni nel genitore.

Per esempio, nel pom genitore,

<dependencyManagement> 
    <dependencies> 
     <dependency> 
     <groupId>${myproject.group}</groupId> 
     <artifactId>component1</artifactId> 
     <version>${component1.version}</version> 
     </dependency> 
     <dependency> 
     <groupId>${myproject.group}</groupId> 
     <artifactId>component2</artifactId> 
     <version>${component2.version}</version> 
     <type>war</type> 
     </dependency> 
     <dependency> 
     <groupId>${myproject.group}</groupId> 
     <artifactId>comp3module1</artifactId> 
     <version>${component3.version}</version> 
     <type>ejb</type> 
     </dependency> 
     <dependency> 
     <groupId>${myproject.group}</groupId> 
     <artifactId>comp3module1</artifactId> 
     <version>${component3.version}</version> 
     <type>ejb-client</type> 
     </dependency> 
     <dependency> 
     <groupId>${myproject.group}</groupId> 
     <artifactId>comp3module2</artifactId> 
     <version>${component3.version}</version> 
     <type>war</version> 
     </dependency> 
    </dependencies> 
</dependencyManagement> 

Ora, fare riferimento a qualsiasi modulo da qualsiasi altro modulo, è facile come:

<dependency> 
    <groupId>${myproject.group}</groupId> 
    <artifactId>component1</artifactId> 
</dependency> 
<dependency> 
    <groupId>${myproject.group}</groupId> 
    <artifactId>comp3module1</artifactId> 
    <type>ejb-client</type> 
</dependency> 

versioni sono gestite automaticamente dal genitore. Non è necessario mantenerli nelle dipendenze dei bambini, che diventano anche meno prolissi.

+0

Juan grazie per la risposta dettagliata. La domanda 1 si riferisce a ciascun modulo con la propria versione. Nella tua risposta tutti i moduli hanno la stessa versione. Si prega di notare che usiamo -SNAPSHOT ma alla fine di un ciclo di sviluppo quando entriamo in UAT usiamo le versioni non-SNAPSHOT. Lo stesso con la domanda 2, presuppone che ogni modulo avrà la stessa versione. La varianza delle versioni all'interno dei moduli figlio è alla base della domanda. –

+0

Ok, avevo capito che alla fine del ciclo hai riallineato tutte le versioni per avviare un nuovo ciclo con la stessa versione per tutti i moduli. Chiarirò le differenze in questo caso. – Juan

+0

Aggiunte informazioni sulle versioni indipendenti. Spero che sia d'aiuto. – Juan

1

1) Ho provato anche la versione: impostata in passato, ma non funzionava correttamente. Dovrebbe fare lo stesso processo del rilascio: prepararsi, ma in realtà no. Quindi quello che potresti provare è mvn release:prepare -DautoVersionSubmodules -DdryRun. Questo dovrebbe fare tutti gli aggiornamenti senza controllare nulla nel repository e senza fare alcun tag.

2) Credo che il progetto ClearTK abbia seguito una strategia simile a quella attuale: hanno mantenuto un progetto multi-modulo con ogni modulo con il proprio ciclo di rilascio. Per rimanere al top della situazione, hanno implementato un plug-in personalizzato per avvisarli delle incoerenze della versione delle dipendenze.

https://github.com/ClearTK/cleartk/tree/master/consistent-versions-plugin

Mentre un tale plugin non farebbe gli aggiornamenti che si domanda, dovrebbe almeno una notifica quando sono necessari aggiornamenti. Per risolvere davvero il tuo problema, potresti considerare di seguire la stessa strada di ClearTK e implementare il tuo plugin Maven (o fai quello che ClearTK alla fine ha fatto: passare a un ciclo di rilascio sincronizzato;))

1

Ok questo è quello che mi è venuto in mente. Questo è basato su questo articolo continuous-releasing-of-maven-artifacts.

Parent

POM:

<properties> 
    <!-- versions of modules --> 
    <main.version>1.0</main.version> 
    <revision>SNAPSHOT</revision> <!-- default revision --> 
    <Module1.revision>${revision}</Module1.revision> 
    <Module2.revision>${revision}</Module2.revision> 
    <Module3.revision>${revision}</Module3.revision> 
    <Module4.revision>${revision}</Module4.revision> 
    <Module5.revision>${revision}</Module5.revision> 
    <Module1.version>${main.version}-${Module1.revision}</Module1.version> 
    <Module2.version>${main.version}-${Module2.revision}</Module2.version> 
    <Module3.version>${main.version}-${Module3.revision}</Module3.version> 
    <Module4.version>${main.version}-${Module4.revision}</Module4.version> 
    <Module5.version>${main.version}-${Module5.revision}</Module5.version> 
</properties> 

Esempio POM bambino con l'Inter dipendenza progetto:

<groupId>com.xyz</groupId> 
    <artifactId>Module4</artifactId> 
    <packaging>jar</packaging> 
    <version>${Module4.version}</version> 

    <parent> 
     <groupId>com.xyz</groupId> 
     <artifactId>ParentProject</artifactId> 
     <version>1.0</version> 
    </parent> 

    <dependencies> 
     <dependency> 
      <groupId>com.xyz</groupId> 
      <artifactId>Module1</artifactId> 
      <version>${Module1.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>com.xyz</groupId> 
      <artifactId>Module2</artifactId> 
      <version>${Module2.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>com.xyz</groupId> 
      <artifactId>Module3</artifactId> 
      <version>${Module3.version}</version> 
      <type>jar</type> 
     </dependency> 
    <dependencies> 

1) All'inizio del ciclo Come è possibile impostare il genitore e moduli per la stessa versione in un comando di maven?

Non è più necessario. Il POM padre può rimanere nella stessa versione, cambiando solo se cambia il POM padre. In tal caso è possibile utilizzare mvn version:set -DnewVersion=1.1.1. Ma non è necessario per questo approccio.

Invece è possibile impostare dinamicamente la versione utilizzando la proprietà main.version. Per esempio. mvn clean deploy -Dmain.version=1.1.1 Inoltre, per forzare il passaggio dinamico del numero di versione, è possibile tralasciare la proprietà di default main.version che ho incluso nella mia POM padre sopra.

2) Come aggiornare sia la versione di mod1 che il riferimento di mod2 alla versione di mod1 in un unico passaggio?

Questo in pratica si riduce a come gestire le revisioni. Se non si imposta la proprietà revision nel comando mvn, tutti i moduli utilizzeranno lo SNAPSHOT come revisione. Se imposto la proprietà revision su RC1, tutti i moduli otterranno tale revisione. Inoltre, se imposto da revision a RC1 ma da Module4.revision a RC2, Module4 ottiene RC2 e tutti gli altri moduli ricevono RC1. Questo soddisfa la richiesta dei clienti di avere revisioni dinamiche per modulo.

ecco alcuni esempi:

  • mvn clean deploy -Dmain.version=1.1.1 Imposta tutti i moduli per la versione 1.1.1-SNAPSHOT.
  • mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 Imposta tutti i moduli sulla versione 1.1.1-RC1.
  • mvn clean deploy -Dmain.version=1.1.1 -Drevision=RC1 -DModule4.revision=RC2 Imposta tutti i moduli sulla versione 1.1.1-RC1 ad eccezione di Module4, che è impostato sulla versione 1.1.1-RC2.

C'è un avvertimento che deve essere menzionato. Se si incrementa la versione di un modulo dipendente, ad esempio Module1, in RC2, è necessario anche incrementare la versione di tutti i moduli che la utilizzano, ad esempio Module4 non deve essere incrementato anche su RC2 (o sulla prossima versione). Questo è qualcosa a cui il client è stato messo a conoscenza ed è anche il motivo per cui preferirei che tutti i moduli avessero la stessa versione. Ma mi piace davvero come è emersa la dinamica. Essenzialmente la versione è ora impostata tramite la riga di comando senza aggiornamenti ai file POM richiesti.

0

1) Come @rec Detto questo, il plugin di rilascio Maven farebbe il trucco

$ mvn release:prepare -DautoVersionSubmodules=true 
$ mvn release:perform 

2) È possibile definire la dipendenza da mod2 a Mod1 come:

<dependency> 
    <groupId>com.xxx</groupId> 
    <artifactId>mod1</artifactId> 
    <version>LATEST</version> 
</dependency> 

Maggiori informazioni: How do I tell Maven to use the latest version of a dependency?

Ho provato entrambe le soluzioni e funziona! Spero che ti aiuta :)