Technology Experience

Contenuti gestiti da Igor Damiani
posts - 949, comments - 2741, trackbacks - 15120

My Links

News

  • Questo blog si propone di raccogliere riflessioni, teoriche e pratiche, su tutto quello che riguarda il world-computing che mi sta attorno: programmazione in .NET, software attuale e futuro, notizie provenienti dal web, tecnologia in generale, open-source.

    L'idea è quella di lasciare una sorta di patrimonio personale, una raccolta di idee che un giorno potrebbe farmi sorridere, al pensiero di dov'ero e cosa stavo facendo.

    10/05/2005,
    Milano

Archives

Post Categories

Generale

Usare MSBuild per zippare & uploadare i sorgenti

Negli ultimi giorni ho studiato MSBuild per automatizzare la pubblicazione su un server Web (che supporta PHP & MySQL, alla faccia di ASP.NET ) di un file ZIP contenente i sorgenti di Fatturazione. Ne ho sempre parlato in modo un po' vago, per cui in questo post voglio descrivere nel modo più specifico quello che ho fatto.

Introduzione
In linea di massima, lo script parte da questi concetti:

  1. ho i sorgenti  da qualche parte, che devo prelevare
  2. copio i sorgenti trasferendoli da qualche altra parte
  3. zippo i sorgenti copiati al punto (2)
  4. faccio l'upload del file zippato su un server FTP

Perchè ho messo in corsivo e in blu le locazioni dei sorgenti? E' presto detto. I sorgenti al punto (1) possono stare - per adesso - in due tipi di posti diversi: o una directory sul mio hard-disk (D:\Documenti\Visual Studio 2005\Projects\Fatturazione) oppure mantenuti da un source control (come il Vault SourceGear). Per adesso, partiamo dal presupposto di avere la nostra soluzione in una directory, che è il caso più semplice che capita a tutti noi, poi vedremo come modificare in modo semplice lo script per fare diversamente.

Quindi, dicevamo, dobbiamo copiare tutti i files dalla directory di origine alla directory di destinazione, dobbiamo zippare i sorgenti ed infine dobbiamo uploadare i files zippati. Contate i grassetti nella frase precedente e scoprirete quanti task deve eseguire il nostro script per MSBuild: solo 3? In realtà, ce n'è uno in più, ovvero quello iniziale che si occupa di cancellare gli eventuali residui di una precedente esecuzione dello script (cancellazione della directory di destinazione ed il file ZIP vecchio.).
Detto questo, passiamo alla pratica.

Struttura dello script per MSBuild
Uno script di MSBuild non è nient'altro che un file XML creato in modo opportuno, rispettando un certo schema e così via. Vediamo la struttura di base.

<Project DefaultTargets="All" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    
...
    ...
    ...
    
    
<Target Name="All">
        <CallTarget 
Targets="DeleteLastDownload" />
        <CallTarget 
Targets="CopyFiles" />
        <CallTarget 
Targets="CreateZip" />
    <
/Target>
<
/Project

Il tag Project comincia lo script. La proprietà DefaultTargets indica il task che viene eseguito per primo: il task si chiama All, che esegue poi uno alla volta gli altri task che compongono lo script, ovvero: DeleteLastDownload, CopyFiles e CreateZip. In questo momento, non abbiamo ancora considerato l'upload via FTP, ne parleremo più avanti. I punti di sospensione indicano un blocco XML contenente uno alla volta il codice relativo a ciascun task.
Esaminiamoli nel dettaglio adesso uno alla volta.

Il task DeleteLastDownload
Questo task fa semplicemente due cose: cancella la directory di destinazione (se esiste) e il file ZIP (se esiste). Questo task ha senso solo se abbiamo eseguito lo script già una volta e quindi abbiamo i residui di una precedente esecuzione, appunto. Se la directory o il file non esistono, le corrispondenti operazioni vengono skippate senza danni. Il codice è:

<Target Name="DeleteLastDownload">
    <RemoveDir 
Directories="$(DownloadDir)"/>
    <Delete 
Files="$(ZipFileName)"/>
<
/Target>

$(DownloadDir) e $(ZipFileName) sono due costanti: ne parleremo un'altra volta.

Il task CopyFiles
Questo task copia i sorgenti da una directory di origine ad un'altra di destinazione. Per farlo, sfrutta una copia ricorsiva: come tutti sappiamo, una soluzione .NET è articolata in molte directory, una innestata all'altra, ma noi con un semplice comando possiamo fare il tutto senza problemi. Il codice è questo:

<Target Name="CopyFiles">
    <Copy
        
SourceFiles="@(MySourceFiles)"
        
DestinationFiles="@(MySourceFiles->'$(DownloadDir)\%(RecursiveDir)%(Filename)%(Extension)')" />
<
/Target>

Non chiedetemi molti dettagli, perchè io stesso l'ho copiata & incollata dal sito MSDN.  Anche in questo caso, $(MySourceFiles) e $(DownloadDir) fanno riferimento a costanti.

Il task CreateZip
Questo task - che non fa parte del pacchetto standard di MSBuild - crea un file ZIP partendo da uno o più files. Il comando, su cui sono impazzito parecchio , è il seguente:

<ItemGroup>
    <ZipFiles 
Include="$(DownloadDir)\**\*.*" />
<
/ItemGroup>
<
Target Name="CreateZip">
    <Zip 
ZipFileName="$(ZipFileName)" WorkingDirectory="$(DownloadDir)" Files="@(ZipFiles)"/
<
/Target>

Attenzione: il gruppo di files da zippare è indicato dal tag ItemGroup. Se anche voi dovete fare una cosa del genere, assicuratevi di metterlo assolutamente prima del task CreateZip. Sto ancora indagando sulla questione, ma ho la netta sensazione che se nello script voi copiate dei files (come in questo caso) e quell'include viene "valutato" prima della copia, nello ZIP non vengono inclusi i files copiati durante l'esecuzione dello script. Io sono diventato matto, perchè continuavo a generare il file ZIP vuoto, oppure che non corrispondeva al 100% ai files effettivamente contenuti nella directory di destinazione.

E se devo usare Vault SourceGear?
Se i sorgenti sono mantenuti su un source control, possiamo recuperarli attraverso il client di Vault disponibile da linea di comando. In pratica, il task CopyFiles non ci servirebbe più, ma verrebbe sostituiti da un GetLatestVersion che concettualmente fa la stessa cosa (fornisce i sorgenti aggiornati), ma li preleva fisicamente da un repository raggiungibile via http. Il task è:

<Target Name="GetLastestVersion">
    <Exec 
Command=' $(SourceGearClientPath) GETWILDCARD -makewritable -destpath $(DownloadDir) $(SourceGearPath) * -user $(SourceGearUsername) -password $(SourceGearPassword) -host $(SourceGearHost) -REPOSITORY "Default Repository" ' />
<
/Target>

Il tag Exec non fa altro che eseguire il comando riportato nella proprietà Command del tag stesso. Utilizza tutta una serie di costanti $(qualcosa) per rendere più manutenibile lo script. Una cosa importante: il comando qui sopra non fa il check-out dei sorgenti, ma chiede una semplice copia dei files. Il check-out non avrebbe senso, dal momento che lo si fa solo che bisogna modificare un file, cosa che a noi non serve.

Conclusioni
C'è ancora qualcosa da vedere, ma non ho tempo: come definire le costanti e, soprattutto capire quello che non ho ancora capito, ovvero che differenza c'è tra i tag ItemGroup e PropertyGroup Stay tuned!

powered by IMHO 1.2

Print | posted on mercoledì 17 maggio 2006 17:48 | Filed Under [ Tecnologia ]

Feedback

Gravatar

# Se c'

06/06/2006 02:16 | Technology Experience
Comments have been closed on this topic.

Powered by:
Powered By Subtext Powered By ASP.NET