11

アプリケーションの 2 つのリリース間で変更ログ (実際には作業項目のリスト) を自動的に生成する方法を探しています。アプリケーションには v1 と v2 の 2 つのバージョンがあり、それぞれは、アプリのセットアップをビルドする前に手動で作成した TFS 2010 のラベル (LABEL1 と LABEL2) によって識別されます。私は分岐システムを持っています。つまり、ほとんどのバグが修正されたトランクと、主にトランクからのマージを使用してパッチが適用されるブランチがあります (ただし、トランクに関係のないブランチのみの修正もあります)。 . アプリケーションの 2 つのバージョン (v1 と v2) は、ブランチのバージョンです。

TFS 2010 が、これら 2 つのラベルの間で修正されたバグのリスト (つまり、type = Bug で、クローズされ、検証された作業項目のリスト) を返すことができるようにしたいと考えています。

TFS 2010 の Web UI または Visual Studio を使用してこれを実現しようとしましたが、方法が見つかりませんでした。

次に、次のコマンド ラインを使用して tf.exe に履歴を要求しようとしました。

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

ここで、LABEL1 はアプリケーションの v1 のソース コードに関連付けられているラベルであり、LABEL2 はアプリケーションの v2 のソース コードに関連付けられているラベルです。実際には 2 つの方法で失敗します: - コマンド ラインは変更セットのリストのみを返し、関連する閉じた作業項目のリストは返しません - 変更セットのリストにはブランチ自体に適用した変更セットのみが含まれ、私が適用した変更セットも含まれませんそしてトランク、そしてブランチにマージされました。「/slotmode」パラメーターを設定してもしなくても、何も変わりません。

そこで、作業項目のリスト (変更セットのリストではない) を取得する C# コードを書き込もうとしました。

var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://server_url/collection_name"));

VersionControlServer controlServer = tfs.GetService<VersionControlServer>();
VersionControlServer vcs = tfs.GetService<VersionControlServer>();

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<int, WorkItem> dico = new Dictionary<int, WorkItem>();
foreach (Changeset set in changesets)
{
    foreach (WorkItem zz in set.WorkItems)
    {
        if (!dico.ContainsKey(zz.Id))
        {
            dico.Add(zz.Id, zz);
        }
    }
}

foreach (KeyValuePair<int, WorkItem> pair in dico.OrderBy(z => z.Key))
{
    Console.WriteLine(string.Format("ID: {0}, Title: {1}", pair.Key, pair.Value.Title));
}

これは実際に機能し、実際に私が望んでいた 2 つのラベル間の作業項目のリストを取得します。ただし、ブランチ自体でコミットされた変更セットに関連付けられた作業項目のみが考慮されます。トランクで解決されてからブランチにマージされたタイプ「バグ」の作業項目は表示されません。Slotmode は何も変更しません。

次に、ラベルによって定義された VersionSpecs を、変更セットによって定義された VersionSpecs に置き換えようとしました。

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

そして、私のコードは最終的に機能します。

私の質問は、バージョンを識別するために使用する TFS オブジェクトであるラベルを使用して、どうすれば同じ結果を得ることができるかということです。それが不可能な場合、TFS 2010 でバージョンを特定するにはどうすればよいですか? どうも。

ところで、stackoverflow に関するいくつかの質問を見つけましたが、どれもラベル付きの回答をくれませんでした。例: 質問の例

4

4 に答える 4

2

http://tfschangelog.codeplex.com/がおそらくここで役立つと思います。

TFS ChangeLog アプリケーションを使用すると、ユーザーは TFS からリリース ノートを自動的に生成できます。ユーザーは、プロジェクト、ブランチ、および変更セットの範囲に関する情報を提供する必要があります。その後、TFS ChangeLog アプリケーションは、指定された範囲内の各変更セットから情報を抽出し、そのような変更セットに関連付けられているすべての作業項目を抽出します。つまり、変更セットの開始から変更セットの終了まで移動し、各変更セットに関するデータを XML ファイル内の関連する作業項目と共に抽出します。

ユーザーは、フィルタ、並べ替え、スタイル設定、出力フォーマットなどを含む独自の変換ロジックを使用して、リリース ノート レポートを生成できます。

ここで追加したいもう 1 つのことは、TFS のラベルに関連するものです。ラベルは基本的に変更セットに割り当てられます/関連付けられます。現在、TFS ChangeLog アプリケーションは、開始点と終了点を定義するラベルをサポートしていませんが、回避策として使用できる変更セットをサポートしています。

これが役に立つことを願っています。

于 2012-05-21T22:47:06.610 に答える
1

一般に、SCM で特定の時点を定義する絶対的な方法は、明らかにチェックイン ID です。これを抽象化するためにラベルを使用することは、ここここで
説明されているように、TFS では最適ではありません。特に最新の CI 環境では、代わりにビルドを使用することをお勧めします。

特定のビルドに含まれていた最大変更セットを取得するには、次のようにする必要があります。

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<IChangesetSummary> associatedChangesets = InformationNodeConverters.GetAssociatedChangesets(build);

            int idMax = associatedChangesets[0].ChangesetId; 
        }
    }
}


上記の問題は、関心のあるビルドの BuildUri を取得することです。この情報を取得するには、次のようにすることができます。

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

次に、重要な Uri を取得します。

最終的にラベルの使用を主張する場合にも、これは優れたUri手段build[]ですLabelName

于 2011-12-08T13:03:07.313 に答える
1

私はあなたと同じ状況にありました。また、マージされたチェンジセットのワークアイテムも含めたいです。Doneである Work Items のみを含めます。また、同じ作業項目が複数の変更セットにリンクされている場合、最後の変更セットのみが報告されます。これを CI セットアップで使用します。ビルドごとに変更ログを作成します。その後List<ChangeInfo>、XML/HTML/TXT ファイルにエクスポートできます。これが私の解決策です:

namespace TFSChangelog
{
  public class TFSChangelogGenerator
  {
    private const string workItemDoneText = "Done";

    /// <summary>
    /// This class describes a change by:
    /// Changeset details
    /// and
    /// WorkItem details
    /// </summary>
    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<ChangeInfo> 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<VersionControlServer>();

      // 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<int, ChangeInfo>();

      // 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<Changeset>();
      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();
    }
  }
}
于 2011-12-18T10:30:27.177 に答える
0

この質問により、私が抱えていた同様の問題の解決に近づきました。

ラベル バージョンLabelVersionSpecの代わりにタイプを使用します。VersionSpec

交換:

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

と:

LabelVersionSpec sFrom = new LabelVersionSpec("LLABEL1");
LabelVersionSpec sTo = new LabelVersionSpec("LLABEL2");
于 2012-05-30T21:43:14.100 に答える