From 2a0c5228acb0326244e251ce03f8d1b7de6453a0 Mon Sep 17 00:00:00 2001 From: chcosta Date: 2026年6月17日 09:34:51 -0700 Subject: [PATCH 1/4] Enable Helix queue stats logging for Arcade unit tests --- tests/UnitTests.proj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/UnitTests.proj b/tests/UnitTests.proj index 2c7fcde4efd..d96251e46e9 100644 --- a/tests/UnitTests.proj +++ b/tests/UnitTests.proj @@ -24,6 +24,8 @@ instead of the in-build Python reporter. The corresponding monitor job is configured in the Arcade pipeline YAML. --> true + + true From 6efdd09a54d9cd7014766d7af144e03e252ce9d0 Mon Sep 17 00:00:00 2001 From: chcosta Date: 2026年6月17日 12:24:02 -0700 Subject: [PATCH 2/4] Elevate JobSender log callback to High when queue stats enabled Default CI verbosity is Minimal, which filters out MessageImportance.Normal messages. When EnableShowHelixQueueStats is opted in, route SendAsync log output (including the queue-health summary) at High importance so it survives the default verbosity. --- src/Microsoft.DotNet.Helix/Sdk/SendHelixJob.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Helix/Sdk/SendHelixJob.cs b/src/Microsoft.DotNet.Helix/Sdk/SendHelixJob.cs index 2012872ad23..e36f745e307 100644 --- a/src/Microsoft.DotNet.Helix/Sdk/SendHelixJob.cs +++ b/src/Microsoft.DotNet.Helix/Sdk/SendHelixJob.cs @@ -267,8 +267,10 @@ protected override async Task ExecuteCore(CancellationToken cancellationToken) Log.LogMessage(MessageImportance.High, $"Sending Job to {TargetQueue}..."); cancellationToken.ThrowIfCancellationRequested(); - // LogMessageFromText will take any string formatted as a canonical error or warning and convert the type of log to this - ISentJob job = await def.SendAsync(msg => Log.LogMessageFromText(msg, MessageImportance.Normal), cancellationToken); + // LogMessageFromText will take any string formatted as a canonical error or warning and convert the type of log to this. + // When queue-stats logging is opted in, elevate to High importance so the summary survives the default 'Minimal' build verbosity. + MessageImportance sendAsyncImportance = EnableShowHelixQueueStats ? MessageImportance.High : MessageImportance.Normal; + ISentJob job = await def.SendAsync(msg => Log.LogMessageFromText(msg, sendAsyncImportance), cancellationToken); JobCorrelationId = job.CorrelationId; JobCancellationToken = job.HelixCancellationToken; cancellationToken.ThrowIfCancellationRequested(); From c368b793f1c63014d57b7e0d39dc37e35e5cb736 Mon Sep 17 00:00:00 2001 From: chcosta Date: 2026年6月22日 18:22:45 -0700 Subject: [PATCH 3/4] Add Azure DevOps organization/project context to Helix job creation Add WithAzureDevOpsOrganization() and WithAzureDevOpsProject() fluent builder methods to JobDefinition to allow callers (especially public pipelines) to specify which Azure DevOps organization/project is requesting queue stats. These parameters are passed through JobCreationRequest to Helix API. Fixes: Arcade PR for enabling queue stats support with org/project scoping --- .../generated-code/Models/JobCreationRequest.cs | 6 ++++++ .../JobSender/IJobDefinition.cs | 14 ++++++++++++++ .../JobSender/JobDefinition.cs | 16 ++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/src/Microsoft.DotNet.Helix/Client/CSharp/generated-code/Models/JobCreationRequest.cs b/src/Microsoft.DotNet.Helix/Client/CSharp/generated-code/Models/JobCreationRequest.cs index a547731f6b8..54a2da52d7a 100644 --- a/src/Microsoft.DotNet.Helix/Client/CSharp/generated-code/Models/JobCreationRequest.cs +++ b/src/Microsoft.DotNet.Helix/Client/CSharp/generated-code/Models/JobCreationRequest.cs @@ -55,6 +55,12 @@ public JobCreationRequest(string type, string listUri, string queueId) [JsonProperty("ResultContainerPrefix")] public string ResultContainerPrefix { get; set; } + [JsonProperty("AzureDevOpsOrganization")] + public string AzureDevOpsOrganization { get; set; } + + [JsonProperty("AzureDevOpsProject")] + public string AzureDevOpsProject { get; set; } + [JsonIgnore] public bool IsValid { diff --git a/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs b/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs index 3f80365bd7d..0bcd790ea6f 100644 --- a/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs +++ b/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs @@ -182,6 +182,20 @@ public interface IJobDefinition /// Fluent job builder. IJobDefinition WithQueueStats(); + /// + /// Sets the Azure DevOps organization for queue stats lookup. + /// When not specified, defaults to the observer's configured default organization. + /// + /// Fluent job builder. + IJobDefinition WithAzureDevOpsOrganization(string organization); + + /// + /// Sets the Azure DevOps project for queue stats lookup. + /// When not specified, defaults to the observer's configured default project. + /// + /// Fluent job builder. + IJobDefinition WithAzureDevOpsProject(string project); + /// /// Sends the fully specified job to execution. /// diff --git a/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs b/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs index b9ccd89ecdc..a8f466b05c8 100644 --- a/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs +++ b/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs @@ -48,6 +48,8 @@ public JobDefinition(IJob jobApi) public IDictionary CorrelationPayloads { get; } = new Dictionary(); public int? MaxRetryCount { get; private set; } public bool ShowQueueStats { get; private set; } + public string AzureDevOpsOrganization { get; private set; } + public string AzureDevOpsProject { get; private set; } public string StorageAccountConnectionString { get; private set; } public string TargetContainerName { get; set; } = DefaultContainerName; public string TargetResultsContainerName { get; set; } = DefaultContainerName; @@ -226,6 +228,8 @@ public async Task SendAsync(Action log, CancellationToken canc ResultContainerPrefix = ResultContainerPrefix, DockerTag = dockerTag, QueueAlias = queueAlias, + AzureDevOpsOrganization = AzureDevOpsOrganization, + AzureDevOpsProject = AzureDevOpsProject, }; if (string.IsNullOrEmpty(Source)) @@ -462,6 +466,18 @@ public IJobDefinition WithQueueStats() return this; } + public IJobDefinition WithAzureDevOpsOrganization(string organization) + { + AzureDevOpsOrganization = organization; + return this; + } + + public IJobDefinition WithAzureDevOpsProject(string project) + { + AzureDevOpsProject = project; + return this; + } + internal void AddWorkItem(WorkItemDefinition workItemDefinition) { _workItems.Add(workItemDefinition); From 24f9f816ead8e23bbb10d72158f0d96032e942bc Mon Sep 17 00:00:00 2001 From: chcosta Date: 2026年6月22日 18:25:12 -0700 Subject: [PATCH 4/4] Remove unnecessary Azure DevOps org/project context from Helix client Queue names are globally unique across all organizations and projects, so the Helix API does not need org/project context to return stats. These parameters only serve as optional audit context on the public Helix Observer endpoint for external callers to declare their scope. Reverts the org/project fluent builder methods since: 1. They are unused in the codebase 2. Queue stats are queried and returned by queue name globally 3. Org/project scoping is only relevant on the public HTTP endpoint --- .../JobSender/IJobDefinition.cs | 14 -------------- .../JobSender/JobDefinition.cs | 16 ---------------- 2 files changed, 30 deletions(-) diff --git a/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs b/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs index 0bcd790ea6f..3f80365bd7d 100644 --- a/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs +++ b/src/Microsoft.DotNet.Helix/JobSender/IJobDefinition.cs @@ -182,20 +182,6 @@ public interface IJobDefinition /// Fluent job builder. IJobDefinition WithQueueStats(); - /// - /// Sets the Azure DevOps organization for queue stats lookup. - /// When not specified, defaults to the observer's configured default organization. - /// - /// Fluent job builder. - IJobDefinition WithAzureDevOpsOrganization(string organization); - - /// - /// Sets the Azure DevOps project for queue stats lookup. - /// When not specified, defaults to the observer's configured default project. - /// - /// Fluent job builder. - IJobDefinition WithAzureDevOpsProject(string project); - /// /// Sends the fully specified job to execution. /// diff --git a/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs b/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs index a8f466b05c8..b9ccd89ecdc 100644 --- a/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs +++ b/src/Microsoft.DotNet.Helix/JobSender/JobDefinition.cs @@ -48,8 +48,6 @@ public JobDefinition(IJob jobApi) public IDictionary CorrelationPayloads { get; } = new Dictionary(); public int? MaxRetryCount { get; private set; } public bool ShowQueueStats { get; private set; } - public string AzureDevOpsOrganization { get; private set; } - public string AzureDevOpsProject { get; private set; } public string StorageAccountConnectionString { get; private set; } public string TargetContainerName { get; set; } = DefaultContainerName; public string TargetResultsContainerName { get; set; } = DefaultContainerName; @@ -228,8 +226,6 @@ public async Task SendAsync(Action log, CancellationToken canc ResultContainerPrefix = ResultContainerPrefix, DockerTag = dockerTag, QueueAlias = queueAlias, - AzureDevOpsOrganization = AzureDevOpsOrganization, - AzureDevOpsProject = AzureDevOpsProject, }; if (string.IsNullOrEmpty(Source)) @@ -466,18 +462,6 @@ public IJobDefinition WithQueueStats() return this; } - public IJobDefinition WithAzureDevOpsOrganization(string organization) - { - AzureDevOpsOrganization = organization; - return this; - } - - public IJobDefinition WithAzureDevOpsProject(string project) - { - AzureDevOpsProject = project; - return this; - } - internal void AddWorkItem(WorkItemDefinition workItemDefinition) { _workItems.Add(workItemDefinition);

AltStyle によって変換されたページ (->オリジナル) /