TFS 2010: Como produzir um changelog (ou seja, lista de itens de trabalho) entre duas versões do aplicativo usando labels?

Eu estou procurando uma maneira de produzir automaticamente um changelog (na verdade, uma lista de itens de trabalho) entre duas versões do meu aplicativo. Eu tenho duas versões do meu aplicativo, v1 e v2, cada uma é identificada por um label no TFS 2010 (LABEL1 e LABEL2) que eu criei manualmente antes de criar as configurações do meu aplicativo. Eu tenho um sistema de ramificação, o que significa que eu tenho um tronco onde a maioria dos bugs são corrigidos, e uma ramificação onde os patches são aplicados principalmente usando mesclagens do tronco (mas também há algumas correções no branch que não dizem respeito ao tronco) . As duas versões da minha aplicação (v1 e v2) são versões da ramificação.

Gostaria que o TFS 2010 pudesse retornar a lista de bugs corrigidos (ou seja, a lista de itens de trabalho com type = Bug fechados e verificados) entre esses dois labels.

Tentei fazer isso usando a interface do usuário da Web do TFS 2010 ou usando o Visual Studio, mas não encontrei nenhuma maneira.

Então eu tentei pedir tf.exe para um histórico usando a seguinte linha de comando:

tf history /server:http://server_url/collection_name "$/project_path" /version:LLABEL1~LLABEL2 /recursive /noprompt /format:brief 

onde LABEL1 é o label que foi associado ao código-fonte da v1 do aplicativo e LABEL2 o label que foi associado ao código-fonte da versão 2 do aplicativo. Na verdade, ele falha de duas maneiras: – a linha de comando retorna apenas uma lista de conjuntos de mudanças, não uma lista de itens de trabalho fechados associados – a lista de conjuntos de mudanças contém apenas os conjuntos de alterações que eu apliquei na própria ramificação, não os conjuntos de alterações que também apliquei e o tronco e, em seguida, mesclado ao ramo. Definir ou não o parâmetro “/ slotmode” não altera nada.

Lá eu tentei escrever um pedaço de código C # para recuperar a lista de itens de trabalho (não a lista de changesets):

 var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://server_url/collection_name")); VersionControlServer controlServer = tfs.GetService(); VersionControlServer vcs = tfs.GetService(); VersionSpec sFrom = VersionSpec.ParseSingleSpec("LLABEL1", null); VersionSpec sTo = VersionSpec.ParseSingleSpec("LLABEL2", null); var changesets = vcs.QueryHistory( "$/project_path", sTo, 0, RecursionType.Full, null, sFrom, sTo, int.MaxValue, true, false); // Slotmode to false Dictionary dico = new Dictionary(); foreach (Changeset set in changesets) { foreach (WorkItem zz in set.WorkItems) { if (!dico.ContainsKey(zz.Id)) { dico.Add(zz.Id, zz); } } } foreach (KeyValuePair pair in dico.OrderBy(z => z.Key)) { Console.WriteLine(string.Format("ID: {0}, Title: {1}", pair.Key, pair.Value.Title)); } 

Isso realmente funciona, eu recebo a lista de itens de trabalho entre meus dois labels que é realmente o que eu queria. Mas apenas os itens de trabalho associados a conjuntos de alterações que foram confirmados na própria ramificação são levados em conta: os itens de trabalho do tipo “Bug” que foram resolvidos no tronco e depois mesclados à ramificação não aparecem. Slotmode não muda nada.

Então eu finalmente tentei replace VersionSpecs que foram definidos por um label com VersionSpecs que são definidos por changesets:

 VersionSpec sFrom = VersionSpec.ParseSingleSpec("C5083", null); VersionSpec sTo = VersionSpec.ParseSingleSpec("C5276", null); 

E meu código finalmente funciona.

Então, minha pergunta é: como eu poderia obter o mesmo resultado com labels, quais são os objects do TFS que eu uso para identificar uma versão? Se não for possível, como devo identificar uma versão no TFS 2010? THX.

Btw eu encontrei algumas perguntas no stackoverflow, mas nenhum deles me deu respostas com labels. Por exemplo: exemplo da pergunta

Acho que o http://tfschangelog.codeplex.com/ pode ajudá-lo aqui.

O aplicativo TFS ChangeLog permite que os usuários gerem automaticamente notas de versão do TFS. Os usuários precisarão fornecer informações sobre o intervalo de projeto, ramificação e conjunto de alterações e, em seguida, o aplicativo TFS ChangeLog extrairá informações de cada conjunto de alterações em um determinado intervalo e todos os itens de trabalho associados a esses conjuntos de alterações. isto é, ele passará de iniciar changeset até finalizar changeset e irá extrair dados sobre cada changeset junto com workitems associados em um arquivo XML.

Os usuários podem então usar sua própria lógica de transformação, incluindo filtro, sorting, estilo, formatação de saída, etc., para gerar o Relatório de Notas de Lançamento.

Outra coisa que gostaria de adicionar aqui será relacionada a labels no TFS. Os labels são basicamente atribuídos / associados a conjuntos de alterações. Atualmente, o aplicativo TFS ChangeLog não suporta Rótulos para definir o ponto inicial e final, mas suporta o conjunto de alterações que pode ser usado como solução alternativa.

Espero que isso seja útil.

Em geral, o método absoluto de definir pontos no tempo em qualquer SCM é claramente o checkin-id.
Usando labels para abstrair isso, é no TFS não o melhor como discutido aqui e aqui . Uma abordagem melhor é usar builds, especialmente em um ambiente de IC moderno.

Para recuperar o max changeset contido em uma determinada build você teria que fazer algo assim:

 using System; using System.Collections.Generic; using Microsoft.TeamFoundation.Build.Client; using Microsoft.TeamFoundation.Client; namespace GetChangesetsFromBuild { class Program { static void Main() { TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://TFSServer:8080/Name")); IBuildServer bs = (IBuildServer)tpc.GetService(typeof(IBuildServer)); IBuildDetail build = bs.GetAllBuildDetails(new Uri("vstfs:///...")); List associatedChangesets = InformationNodeConverters.GetAssociatedChangesets(build); int idMax = associatedChangesets[0].ChangesetId; } } } 

Uma dificuldade com o exposto acima é recuperar o BuildUri das compilações nas quais você está interessado. Para obter essas informações, você poderia fazer algo assim:

 IBuildDetail[] builds = bs.QueryBuilds("TeamPorjectName", "yourBuildDefinitionName") 

e então recupere os Uri que são importantes para você.

Este também é um bom veículo se você eventualmente insistir em usar labels: Além do Uri , cada build[] possui também um LabelName .

Eu estive na mesma situação que você. Eu também quero itens de trabalho de conjuntos de alterações mesclados incluídos. Eu só incluo itens de trabalho que são feitos . Além disso, se o mesmo Item de Trabalho estiver vinculado a vários conjuntos de alterações, apenas o último conjunto de alterações será relatado. Eu uso isso em uma configuração de CI; e crie um changelog para cada construção. A List pode então ser exportada para um arquivo XML / HTML / TXT. Aqui está a minha solução:

 namespace TFSChangelog { public class TFSChangelogGenerator { private const string workItemDoneText = "Done"; ///  /// This class describes a change by: /// Changeset details /// and /// WorkItem details ///  public class ChangeInfo { #region Changeset details public DateTime ChangesetCreationDate { get; set; } public int ChangesetId { get; set; } #endregion #region WorkItem details public string WorkItemTitle { get; set; } public int WorkItemId { get; set; } #endregion } public static List GetChangeinfo(string tfsServer, string serverPath, string from, string to) { // Connect to server var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(tfsServer)); tfs.Connect(ConnectOptions.None); var vcs = tfs.GetService(); // Create versionspec's VersionSpec versionFrom = null; if (!string.IsNullOrEmpty(from)) versionFrom = VersionSpec.ParseSingleSpec(from, null); VersionSpec versionTo = VersionSpec.Latest; if (!string.IsNullOrEmpty(to)) versionTo = VersionSpec.ParseSingleSpec(to, null); // Internally used dictionary var changes = new Dictionary(); // Find Changesets that are checked into the branch var directChangesets = vcs.QueryHistory( serverPath, VersionSpec.Latest, 0, RecursionType.Full, null, versionFrom, versionTo, Int32.MaxValue, true, false ).Cast(); foreach (var changeset in directChangesets) { foreach (var workItem in changeset.WorkItems.Where(workItem => workItem.State == workItemDoneText)) { if (changes.ContainsKey(workItem.Id)) { if (changeset.ChangesetId < changes[workItem.Id].ChangesetId) continue; } changes[workItem.Id] = new ChangeInfo { ChangesetId = changeset.ChangesetId, ChangesetCreationDate = changeset.CreationDate, WorkItemId = workItem.Id, WorkItemTitle = workItem.Title }; } } // Find Changesets that are merged into the branch var items = vcs.GetItems(serverPath, RecursionType.Full); foreach (var item in items.Items) { var changesetMergeDetails = vcs.QueryMergesWithDetails( null, null, 0, item.ServerItem, VersionSpec.Latest, 0, versionFrom, versionTo, RecursionType.Full ); foreach (var merge in changesetMergeDetails.Changesets) { foreach (var workItem in merge.WorkItems.Where(workItem => workItem.State == workItemDoneText)) { if (changes.ContainsKey(workItem.Id)) { if (merge.ChangesetId < changes[workItem.Id].ChangesetId) continue; } changes[workItem.Id] = new ChangeInfo { ChangesetId = merge.ChangesetId, ChangesetCreationDate = merge.CreationDate, WorkItemId = workItem.Id, WorkItemTitle = workItem.Title }; } } } // Return a list sorted by ChangesetId return (from entry in changes orderby entry.Value.ChangesetId descending select entry.Value).ToList(); } } } 

Essa questão me aproximou de resolver um problema similar que eu estava tendo.

Use o tipo LabelVersionSpec vez de VersionSpec para versões de label.

Substituir:

 VersionSpec sFrom = VersionSpec.ParseSingleSpec("LLABEL1", null); VersionSpec sTo = VersionSpec.ParseSingleSpec("LLABEL2", null); 

com:

 LabelVersionSpec sFrom = new LabelVersionSpec("LLABEL1"); LabelVersionSpec sTo = new LabelVersionSpec("LLABEL2"); 
Intereting Posts