Deploy para FTP usando o TFS Build

Recentemente um cliente solicitou que sua aplicação WEB fosse publicada automaticamente em um FTP, no processo atual de Build a aplicação era publicada em seu ambiente interno usando o Default Build Template do TFS 2010.

Cenário

O ambiente possui um servidor de TFS onde estão todos os códigos fontes, e um servidor de Build onde é executado builds diários e um servidor externo onde temos um FTP para publicação do sistema

Solução

A solução proposta foi customizar o Build Process Template criando uma nova atividade para conectar ao FTP e enviar o resultado do build para seu servidor WEB

Criando um Atividade

A criação de uma atividade é uma tarefa trabalhosa porém sem grandes mistérios, como podemos ver nesse post Alterando a versão do Assembly Info com TFS Build

Primeiramente criamos as variáveis onde vamos passar os valores necessários para conectar ao servidor FTP e o caminho onde foi copiado o resultado do nosso build (DLLs, ASPX, CSS, etc..)

[sourcecode language=”csharp”]
protected override void Execute(CodeActivityContext context)
{
string _dirFTP = context.GetValue(this.DiretorioFTP);
string _server = context.GetValue(this.Server);
string _user = context.GetValue(this.User);
string _password = context.GetValue(this.Password);
string _out = context.GetValue(this.BinariesDirectory);

this.Delete(_dirFTP, _server, _user, _password, context);

this.Upload(_dirFTP, _out, _server, _user, _password, context);

}
[/sourcecode]

Agora vamos escrever um método responsável por deletar os arquivos existentes no FTP

[sourcecode language=”csharp”]
private void DeleteArquivos(string dir)
{
if (_ftp.IsConnected)
{
// muda de diretorio no FTP
_ftp.ChangeDir(dir);

//deleta os arquivos
ArrayList arquivos = _ftp.ListFilesName();
foreach (var item in arquivos)
{
_ftp.RemoveFile(item.ToString());
}

// loop through each subdirectory
ArrayList dirs = _ftp.ListDirectoriesName();

if (dirs.Count > 0)
{
foreach (var d in dirs)
{
// chama o mesmo método para mudar de diretorio e realizar o upload dos arquivos
DeleteArquivos(d.ToString());

//depois que caminhos por todos diretorios, retorna para o anterior
_ftp.ChangeDir("..");

// remove o diretório
_ftp.RemoveDir(d.ToString());
}
}
}
else
{
throw new Exception("FTP disconectado!");
}
}
[/sourcecode]

Agora vamos escrever um método recursivo que é responsável por realizar o Upload dos arquivos para o FTP. Perceba que sempre estou verificando as pastas da nossa solução e depois tenho que criar essa mesma pasta no FTP, por esse motivo foi usado um método recursivo para facilitar o desenvolvimento

[sourcecode language=”csharp”]
private void UploadArquivos(string dir, string changeDir)
{
if (_ftp.IsConnected)
{
// muda de diretorio no FTP
_ftp.ChangeDir(changeDir);

// recupera as informações do diretorio
DirectoryInfo directory = new DirectoryInfo(dir);

//Faz upload de todos os arquivos
foreach (FileInfo f in directory.GetFiles())
{
FazerUpload(f.FullName);
}

// recupera os subdirectorios
DirectoryInfo[] dirs = directory.GetDirectories();

if (dirs.Length > 0)
{
foreach (DirectoryInfo d in dirs)
{
// cria o diretorio no FTP
_ftp.MakeDir(d.Name);

// chama o mesmo método para mudar de diretorio e realizar o upload dos arquivos
UploadArquivos(d.FullName, d.Name);

//depois que caminhos por todos diretorios, retorna para o anterior
_ftp.ChangeDir("..");
}
}
}
else
{
throw new Exception("FTP disconectado!");
}
}
[/sourcecode]

Para realizar a conexão e a transferência de arquivos com o FTP foi usado a biblioteca FTP client library for C#

Customizando o Build Template

Depois de criado e compilado a atividade temos que adiciona-la em nosso Build Template, adicine essa atividade logo após da atividade MS Build conforme a imagem abaixo

Agora temos que criar os seguintes argumentos para passar como parâmetro para a nossa atividade

  • Servidor – Endereço do servidor FTP
  • Usuario – Nome do usuário para conectar ao FTP
  • Senha – Senha do usuário
  • DiretorioFTP – Diretório no FTP onde vai ser copiado os arquivos
  • PublishedWebSites – Diretório onde o TFS Build copia o resultado do  build

O próximo passo é configurar a nossa atividade passando esses argumentos como parâmetro, conforme a imagem abaixo

Executando

Agora vamos criar uma nova build definitios usando esse template customizado adicionando os valores para os argumentos conforme a imagem abaixo

Após executar o build teremos o seguinte resultado

Download do Projeto

Segue abaixo a atividade com o código completo para download

UploadFtp.zip

Deixe seu comentário, opinião, critica

Aquele abraço!

Sobre Leandro Prado

Leandro Silveira Prado é Premier Field Engineer na Microsoft especializado em Application Lifecycle Management.