5

ビルドを同期的にキューに入れることは可能ですか?

私はこのようなことを試しました:

コードアクティビティ:

[BuildActivity(HostEnvironmentOption.Agent)]
public sealed class QueueNewBuild : CodeActivity<BuildResult>
{
    // The Team Project that the build definition belongs to.
    [RequiredArgument]
    public InArgument<IBuildDetail> BuildDetail { get; set; }

    // The build definition to queue
    [RequiredArgument]
    public InArgument<String> BuildDefinition { get; set; }

    protected override BuildResult Execute(CodeActivityContext context)
    {
        // Obtain the runtime value of the input arguments
        var buildDefinitionName = context.GetValue(BuildDefinition);
        var buildDetail = context.GetValue(BuildDetail);

        // Obtain the Team Project for the current build definition.
        var tfsProject = buildDetail.BuildDefinition.TeamProject;

        var configurationServerUri = buildDetail.BuildServer.TeamProjectCollection.Uri.ToString();

        var server = new TfsTeamProjectCollection(new Uri(configurationServerUri));
        server.EnsureAuthenticated();
        var buildServer = server.GetService<IBuildServer>();
        var buildDefinition = buildServer.GetBuildDefinition(tfsProject, buildDefinitionName);

        var queuedBuild = buildServer.QueueBuild(buildDefinition);

        var buildStatusWatcher = new BuildStatusWatcher(queuedBuild.Id);
        buildStatusWatcher.Connect(buildServer, tfsProject);

        do
        {
        } while (buildStatusWatcher.Status != QueueStatus.Completed && buildStatusWatcher.Status != QueueStatus.Canceled);

        buildStatusWatcher.Disconnect();

        return new BuildResult
        {
            WasSuccessfully = buildStatusWatcher.Build.CompilationStatus == BuildPhaseStatus.Succeeded, 
            BuildDetail = buildStatusWatcher.Build
        };
    }
}

ビルド結果:

public class BuildResult
{
    public bool WasSuccessfully { get; set; }
    public IBuildDetail BuildDetail { get; set; }
}

BuildStatusWatcher:

public class BuildStatusWatcher
{
    private IQueuedBuildsView _queuedBuildsView;
    private readonly int _queueBuildId;
    private QueueStatus _status;
    private IBuildDetail _build;

    public BuildStatusWatcher(int queueBuildId)
    {
        _queueBuildId = queueBuildId;
    }

    public IBuildDetail Build
    {
        get { return _build; }
    }

    public QueueStatus Status
    {
        get { return _status; }
    }

    public void Connect(IBuildServer buildServer, string tfsProject)
    {
        _queuedBuildsView = buildServer.CreateQueuedBuildsView(tfsProject);
        _queuedBuildsView.StatusChanged += QueuedBuildsViewStatusChanged;
        _queuedBuildsView.Connect(10000, null);
    }

    public void Disconnect()
    {
        _queuedBuildsView.Disconnect();
    }

    private void QueuedBuildsViewStatusChanged(object sender, StatusChangedEventArgs e)
    {
        if (e.Changed)
        {
            var queuedBuild = _queuedBuildsView.QueuedBuilds.FirstOrDefault(x => x.Id == _queueBuildId);
            if (queuedBuild != null)
            {
                _status = queuedBuild.Status;
                _build = queuedBuild.Build;
            }
        }
    }
}

そのため、ビルドが完了するかキャンセルされるまで待機しようとしていますが、サブビルドのビルド エージェントがずっと待機しているため、これは機能しません。

13 のサブ ビルド プロセス (すべてエージェント 2 で実行) を呼び出す 1 つのマスター ビルド プロセス (エージェント 1 で実行) があります。また、サブビルドプロセスが失敗したときにマスタービルドプロセスを中止できるように、各サブビルドプロセスを待ちたいと思います。

何か案は?

アップデート:

サービス 'XXX - Agent1' に例外がありました: 例外メッセージ: 割り当てられたタイムアウト 00:00:30 内に操作が完了しませんでした。この操作に割り当てられた時間は、より長いタイムアウトの一部であった可能性があります。(タイプ FaultException`1)

例外スタック トレース: Microsoft.TeamFoundation.Build.Machine.BuildAgentService.TerminateWorkflow (TerminatingException ex) で

ワークフロー:

ここに画像の説明を入力

4

2 に答える 2

1

ビルド エージェントを 1 つ追加するだけなので、このような複雑なモジュールを使用してもあまり意味がないと思います。

2 つの別個のアクティビティを実装します
。1 つのアクティビティは入力として a を受け取りBuildDetailBuildDefinition新しいビルドがキューに入れられると終了します。
XAML のループ内でこのアクティビティを呼び出します。これにより、ビルド エージェント #2 のすべてのビルドがキューに入れられます。

2 番目のアクティビティは、ビルド エージェント #2 のステータスを確認し、エージェントが再びアイドル状態になるのを待ちます。
そうしたら、エージェント #2 で正常に実行されたはずの各ビルド定義を次のようにチェックします
if(buildDefinition.LastGoodBuildUri != buildDefinition.LastBuildUri)

。最初の破壊的な「子」ビルド。
私の意見では、それは実際には利点です。1 つ以上が失敗した場合は、すぐにわかります。

于 2012-02-16T12:18:58.880 に答える
1

ビルドを順番に開始するための特別なテンプレートを作成しました。基本的なテンプレート:

ビルド、QueueBuild、M​​onitorBuild を取得する

Get the Buildは、既定のテンプレートにあるアクティビティです。これは私のテンプレートの最初のアクティビティであり、最初に 1 回だけ呼び出されます。

QueueBuildは、codeplex で TFSExtensions から取得したアクティビティです。開始する各ビルドの QueueBuild アクティビティの結果である IQueueBuild オブジェクトを保持する変数を作成します。Result をこの変数に設定します。私は CurrentQueueBuild と呼びました。すべての QueueBuild アクティビティがビルドを開始した後、この変数はアクティビティによって現在のビルド キューに更新されます。

MonitorBuildは、「同期」のほとんどを行う、私が作成したシーケンスです。

1 つ目は、CurrentQueueBuild が null (CurrentQueueBuild Is Nothing) かどうかを確認するアクティビティです。もしそうなら、私はそれを持つことができないので例外をスローします。

2 つ目は、While アクティビティ (「While building」と呼ばれます) です。その条件は「CurrentQueueBuild.Status = BuildStatus.InProgress」です。While の本体には、InvokeMethod アクティビティを含む別のシーケンスがあります (TargetObject = CurrentQueueBuild、M​​ethodName = Refresh で、QueryOptions 型の In パラメータを QueryOptions.All に設定して追加しました)。遅延アクティビティを 5 秒待機するように設定して、InvokeMethod に従います。

最後に、ステータスをログに記録するビルド メッセージを記述します。これは明らかにオプションです。

まとめると、開始する 5 つのビルドがあり、それぞれに対してQueueBuildアクティビティがあり、その後に上記のようにまとめられたMonitor Buildアクティビティがあります。

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

于 2012-06-26T16:25:48.437 に答える