API TFS 2010: la queue est créée de manière synchrone et permet d’obtenir l’état de chaque construction en queue: «Exécuter sur l’agent (en attente de l’agent de génération)»

Est-il possible de mettre les constructions en queue de manière synchrone?

J’ai essayé quelque chose comme ça:

CodeActivité:

[BuildActivity(HostEnvironmentOption.Agent)] public sealed class QueueNewBuild : CodeActivity { // The Team Project that the build definition belongs to. [RequiredArgument] public InArgument BuildDetail { get; set; } // The build definition to queue [RequiredArgument] public InArgument 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.ToSsortingng(); var server = new TfsTeamProjectCollection(new Uri(configurationServerUri)); server.EnsureAuthenticated(); var buildServer = server.GetService(); 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 }; } } 

BuildResult:

 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, ssortingng 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; } } } } 

J’essaie donc d’attendre que la génération soit terminée ou annulée, mais cela ne fonctionne pas, car l’agent de génération de la sous-génération attend tout le temps.

J’ai un processus de construction principal (exécuté sur l’agent 1) qui appelle 13 processus de construction secondaire (tous exécutés sur l’agent 2). Et je souhaite attendre chaque processus de génération de sous-projets pour pouvoir annuler le processus de génération principal lorsqu’un processus de génération de sous-serveurs échoue.

Des idées?

METTRE À JOUR:

Le service ‘XXX – Agent1’ présentait une exception: Message d’exception: l’opération ne s’est pas terminée dans le délai imparti de 00:00:30. Le temps alloué à cette opération peut être une partie d’un délai d’attente plus long. (tapez FaultException`1)

Exception Stack Trace: at Microsoft.TeamFoundation.Build.Machine.BuildAgentService.TerminateWorkflow (TerminatingException ex)

Le stream de travail:

entrez la description de l'image ici

    Comme tout ce que vous avez est un agent de génération supplémentaire, je pense que cela ne vous amène pas beaucoup à employer un module aussi complexe.

    Je mettrais en œuvre deux activités distinctes:
    Une activité prenant en entrée un BuildDetail et une BuildDefinition tant que sortie une fois qu’une nouvelle construction a été mise en queue.
    Je voudrais appeler cette activité dans une boucle dans le XAML. Cela mettrait en queue toutes les versions dans l’agent de construction n ° 2.

    La deuxième activité vérifie le statut de l’agent de génération n ° 2 et attend que l’agent redevienne inactif.
    Une fois que cela se produit, je vérifie chaque définition de génération supposée s’être exécutée avec succès dans l’agent n ° 2 avec un résultat similaire à celui-ci:
    if(buildDefinition.LastGoodBuildUri != buildDefinition.LastBuildUri)

    Ce qui peut sembler être un inconvénient avec cette approche, est le fait que la construction n’échouera pas / ne s’arrêtera pas à la toute première rupture de construction “enfant”.
    À mon avis, c’est un avantage: si plusieurs échouent, vous le saurez immédiatement.

    J’ai créé un modèle spécial pour lancer les constructions dans l’ordre. Le modèle de base:

    Obtenir la construction, QueueBuild, MonitorBuild

    Obtenir la construction est l’activité qui figure dans le modèle par défaut. C’est la première activité de mon modèle et appelée une seule fois au début.

    QueueBuild est l’activité obtenue de TFSExtensions chez codeplex. Je crée une variable contenant un object IQueueBuild, qui est le résultat de l’activité QueueBuild pour chaque génération que je souhaite lancer. J’ai mis le résultat à cette variable. J’ai appelé le mien CurrentQueueBuild. Une fois que chaque activité QueueBuild a démarré une génération, cette variable est mise à jour dans la queue de génération actuelle par l’activité.

    MonitorBuild est une séquence que j’ai créée qui effectue la majeure partie de la «synchronisation»:

    La première est une activité qui vérifie si CurrentQueueBuild est null (CurrentQueueBuild Is Nothing). Si c’est le cas, je lève une exception car je ne peux pas l’avoir.

    La deuxième est une activité While (appelée ‘While building’). Sa condition est ‘CurrentQueueBuild.Status = BuildStatus.InProgress’. Dans le corps du While j’ai une autre séquence qui contient une activité InvokeMethod (TargetObject = CurrentQueueBuild, MethodName = Refresh et j’ai ajouté le paramètre In de type QueryOptions défini sur QueryOptions.All). Je suis la méthode InvokeMethod avec une activité de délai définie pour attendre 5 secondes.

    Enfin, j’écris un message de construction pour consigner l’état. Ceci est évidemment facultatif.

    Donc, pour conclure, j’ai lancé cinq versions et pour chacune d’entre elles, j’ai une activité QueueBuild suivie d’une activité Monitor Build assemblée comme décrit ci-dessus.

    J’espère que ça aide quelqu’un.