La mia implementazione di (quasi) Continuous Integration

di Alessio Leoncini, in ASP.NET,

Durante lo sviluppo di una applicazione web un po' più estesa del solito ho sentito fin da subito l'esigenza di organizzare una procedura di deploy per ridurre gli interventi manuali sul codice pronto per il rilascio.

Il progetto pilota è distribuito a due clienti, entrambi hanno a disposizione tre applicazioni : sviluppo, test e produzione ; è presente anche un sito demo per la guida e per i commerciali: in totale 7 distribuzioni che differiscono per web.config ed altri piccoli particolari interni, grafici e non.

La prima soluzione è stata adottare Web Deployment Project e creare i corrispondenti 7 progetti di deploy, questo tool è molto comodo per compilare automaticamente il sito in un unico assembly ed eseguire altre operazioni, quindi agendo direttamente sul file del progetto ho inserito i codici per effettuare le variazioni di cui avevo bisogno. Semplice ed efficace, una bella comodità rispetto a modificare a mano le stringhe di connessione o inserire a mano i file di licenza.

Dopo le compilazioni dovevo pubblicare a mano i sette progetti : 7 connessioni FTP, cancellare tutti i file eccetto App_offline.htm , prendere i nuovi file e fare upload. Niente di che, sono operazioni che facciamo tutti i giorni eccetto il fatto che una operazione manuale e ripetitiva, anche se semplice, fa sprecare tempo e può portare a qualche mero errore di distrazione dovuto proprio alla semplicità ed alla ripetitività dell'operazione stessa. Poi non è bello farsi chiamare dal cliente per una banalità.

Allora ho pensato che potevo prendere spunto dai principi di Continuous Integration del quale avevo letto qualcosa anche dal nostro .db (solo dopo mi sono accorto che anche Ricciolo ne aveva parlato :D ) : un suo consiglio mi ha indirizzato a http://msbuildtasks.tigris.org/ , un progetto open source per ampliare le funzionalità di MSBuild (http://msdn2.microsoft.com/it-it/library/wea2sca5(VS.80).aspx) il tool di Microsoft che si occupa della preparazione dei progetti e dei sorgenti per la compilazione.

Tra le funzionalità di Msbuildtasks la più adatta al mio scopo è FtpUpload, pensando che alla fine della compilazione potevo prendere i file del progetto e fare automaticamente upload attraverso il protocollo FTP sui server del cliente in modo da automatizzare il processo, tuttavia l'implementazione di FtpUpload fa upload solo dei singoli file della root del sito, non considerando cartelle, sotto cartelle e relativi file.

Avendo a disposizione i sorgenti ho pensato che potevo estendere questo comportamento per poter fare un upload completo, e così ho fatto.

Il codice di Msbuildtasks è ben scritto, è commentato ed è molto facile da capire, io ho aggiunto la parte di cancellazione delle directory e dei file remoti, una versione asincrona di Upload ed un log su file di testo delle attività.

Ho fatto una (semplice) versione asincrona perché pubblicare 7 progetti da 20 MB ciascuno mi bloccava l'uso dell'istanza di visual studio oggetto di building, ok ne potevo aprire un'altra ma mi sembrava più carino così :D .

Non mi addentro nella spiegazione del codice perché è molto semplice, l'unica cosa che mi ha impegnato di più è stato riuscire a capire la presenza di un file o una cartella remota per attuare la giusta operazione. Alla fine ho usato le regular expression con questo pattern:

@"^(?<month>\d{1,2})-(?<day>\d{1,2})-(?<year>\d{1,2})\s+(?<hour>\d{1,2}):(?<minutes>\d{1,2})(?<ampm>am|pm)\s+((?<dir>[<]dir[>])|(?<size>\d+))\s+(?<name>.*)$"

In questo modo, in presenza di una directory eseguo un FtpWebRequest.Method di tipo WebRequestMethods.Ftp.RemoveDirectory , altrimenti FtpWebRequest.Method di tipo WebRequestMethods.Ftp.DeleteFile.

Non ho seguito tutti i dettami del progetto originale, il codice l'ho scritto velocemente per risolvere in breve il mio scenario, lo voglio condividere perché magari a qualcuno può far comodo così com'è oppure può dare spunto a qualcuno (meno pigro di me) per scrivere una completa estensione a Msbuildtasks.

Per usare Msbuildtasks scaricate ed istallate il filehttp://msbuildtasks.tigris.org/files/documents/3383/28296/MSBuild.Community.Tasks.msi , scaricate la mia soluzione a questo indirizzohttps://blogs.aspitalia.com/img/novecento/MSBuildTasks_CompleteUpload.zip , compilate il progetto, e copiate la nuova MSBuild.Community.Tasks.dll sovrascrivendo l'originale che trovate nella cartella di istallazione di Msbuildtasks (C:\Program Files\MSBuild\MSBuildCommunityTasks\ ).

Nel file di progetto del vostro Web Deployment Project aggiungete il riferimento a Msbuildtasks:

<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>

E all'interno del Target Name="AfterBuild? inserite:

<FtpUpload Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "
LocalFile="C:\Users\Alessio\Documents\WebSite\WebSite_deploy\Release\"
RemoteUri="ftp://192.168.1.1/website1/"
Username="UserFTP"
Password="PasswordUserFTP"
ContinueOnError="false">
</FtpUpload>

Con questo codice il Task FtpUpload viene eseguito in fase di compilazione in versione Release, recupera tutti i file e cartelle all'interno della directory specificata in LocalFile , pubblica con FTP all'indirizzo specificato nell'attributo RemoteUri autenticandosi al server FTP con le credenziali specificate negli attributi Username e Password. Di default usa il metodo PassiveMode, ma è possibile modificare il comportamento con lo specifico attributo.

Riguardo al file da usare come log, dovete predisporre un file esito.txt in c:\ .. l'ho detto che ho scritto la soluzione velocemente! :D

Un saluto.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Nella stessa categoria
I più letti del mese