Como obter todos os arquivos das changesets de um Work Item

Essa semana, um desenvolvedor me perguntou como ele poderia obter todos os arquivos .sql de um determinado work item. Ele precisava atualizar o banco de dados de produção e gostaria de saber quais scripts ele deveria executar.

Inicialmente, achei o pedido um pouco estranho, pois o Visual Studio faz isso automaticamente pra gente quando estamos utilizando um projeto do tipo Database Project, porém acabei descobrindo que o projeto estava fora do nosso padrão recomendado e além de não ter o Database Project, também estava sem a estratégia de branch, builds, etc.

O mais triste é que o desenvolver até tinha achado uma “solução”: Ele estava acessando a aba All Links do Work Item, clicando em cada changeset e anotando cada arquivo manualmente, parecido com as imagens abaixo. Confesso que até pensei em deixar o desenvolvedor sofrer um pouco mais, já que ele estava fora do padrão, porém quando vi a quantidade de changesets que havia no work item, mudei de ideia e resolvi ajudar o cidadão.

changeset
Imagem 1: Work Item com a listagem das changesets

changeset details
Imagem 2: Detalhes de uma changeset

A ajuda foi, basicamente, escrever o código C# abaixo que usa as APIs do TFS. Esse código conecta no servidor, obtém uma referência para o Work Item, entra em cada link do tipo changeset e imprime os nomes de arquivos lá existentes.

Para rodar o código abaixo, você precisará instalar o Visual Studio 2010 SDK e adicionar as seguintes referências em seu projeto:

  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.Common
  • Microsoft.TeamFoundation.VersionControl.Client
  • Microsoft.TeamFoundation.WorkItemTracking.Client

           
//Id do Work Item a ser consultado
const int workItemId = 63;           
           
//Endereço da coleção do Team Foundation Server
Uri collectionUri = new Uri("http://localhost:8080/tfs/DefaultCollection");

//Connecta no team foundation server
using (var tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(collectionUri))
{
    //Obtém referências para os repositórios de Work Item e de Código Fonte
    var workItemStore = tpc.GetService<WorkItemStore>();
    var versionControlServer = tpc.GetService<VersionControlServer>();

    //Obtém o Work Item armazenado no repositório
    WorkItem wi = workItemStore.GetWorkItem(workItemId);

    //Varre todos os links do Work Item 
    foreach (var link in wi.Links)
    {
        //Verifica se o link é um link externo pois queremos
        //os links do tipo changeset (externos)
        if (link is ExternalLink)
        {
            //Utiliza um utilitário para quebrar a URL do recurso
            //em diversos campos
            var artefactId = LinkingUtilities.DecodeUri(((ExternalLink)link).LinkedArtifactUri);

            //verifica se o link externo é do tipo Changeset
            if (artefactId.ArtifactType == "Changeset")
            {
                //captura o Id do Changeset
                int changesetId = int.Parse(artefactId.ToolSpecificId);

                //obtem o objeto changeset de acordo com o seu ID
                var changeset = versionControlServer.GetChangeset(changesetId);

                //Imprime no console todos os arquivos que foram
                //encontrados dentro da changeset
                Console.WriteLine("Arquivos da changeset: " + changesetId);
                changeset.Changes.ToList().ForEach(p => Console.WriteLine(p.Item.ServerItem));
            }

        }

    }
}

Como vocês podem ver o código não é nada complexo. Ele trabalha com vários recursos do TFS, além de acessar dois de seus principais repositórios: Work Items e Source Control, logo é um código que você pode facilmente adaptá-lo para outras necessidades.

Bom, é isso! Espero que seja útil para vocês também :-)

Abraços e até a próxima!

André Dias