mirror of
https://github.com/actions/runner.git
synced 2025-12-12 15:13:30 +00:00
Compare commits
7 Commits
users/tihu
...
broker_bak
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04ece46c6a | ||
|
|
e75d502ab1 | ||
|
|
5686904fbe | ||
|
|
c278fb1736 | ||
|
|
332b8f9240 | ||
|
|
25f6cc100f | ||
|
|
6ec30ea522 |
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@@ -101,11 +101,11 @@ jobs:
|
|||||||
working-directory: src
|
working-directory: src
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
#- name: L0
|
- name: L0
|
||||||
# run: |
|
run: |
|
||||||
# ${{ matrix.devScript }} test
|
${{ matrix.devScript }} test
|
||||||
# working-directory: src
|
working-directory: src
|
||||||
# if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm'
|
||||||
|
|
||||||
# Create runner package tar.gz/zip
|
# Create runner package tar.gz/zip
|
||||||
- name: Package Release
|
- name: Package Release
|
||||||
|
|||||||
@@ -1,18 +1,8 @@
|
|||||||
## Features
|
## Features
|
||||||
- Continue-on-error is now possible for the composite action steps (#1763)
|
|
||||||
- Now it's possible to use context evaluation in the `shell` of composite action run steps (#1767)
|
|
||||||
|
|
||||||
## Bugs
|
## Bugs
|
||||||
- Fix a bug where job would be marked as 'cancelled' after self-hosted runner going offline (#1792)
|
- Fixed an issue where websockets failed to successfully close when posting log lines (#1790)
|
||||||
- Translate paths in `github` and `runner` contexts when running on a container (#1762)
|
|
||||||
- Warn about invalid flags when configuring or running the runner (#1781)
|
|
||||||
- Fix a bug where job hooks would use job level working directory (#1809)
|
|
||||||
|
|
||||||
## Misc
|
|
||||||
- Allow warnings about actions using Node v12 (#1735)
|
|
||||||
- Better exception handling when runner is configured with invalid Url or token (#1741)
|
|
||||||
- Set user agent for websocket requests (#1791)
|
|
||||||
- Gracefully handle websocket failures (#1789)
|
|
||||||
|
|
||||||
## Windows x64
|
## Windows x64
|
||||||
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows.
|
||||||
|
|||||||
@@ -47,6 +47,11 @@
|
|||||||
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
|
<DefineConstants>$(DefineConstants);DEBUG</DefineConstants>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- Set USE_BROKER vars -->
|
||||||
|
<PropertyGroup Condition="'$(USE_BROKER)' == 'true'">
|
||||||
|
<DefineConstants>$(DefineConstants);USE_BROKER</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Set Treat tarnings as errors -->
|
<!-- Set Treat tarnings as errors -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||||
|
|||||||
59
src/Runner.Common/BrokerServer.cs
Normal file
59
src/Runner.Common/BrokerServer.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
|
{
|
||||||
|
[ServiceLocator(Default = typeof(BrokerServer))]
|
||||||
|
public interface IBrokerServer : IRunnerService
|
||||||
|
{
|
||||||
|
Task ConnectAsync(Uri serverUrl, CancellationToken cancellationToken);
|
||||||
|
Task<string> GetMessageAsync(TaskAgentSession session, RunnerSettings settings, long? lastMessageId, CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class BrokerServer : RunnerService, IBrokerServer
|
||||||
|
{
|
||||||
|
private HttpClient _httpClient;
|
||||||
|
|
||||||
|
public async Task ConnectAsync(Uri serverUrl, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_httpClient = new HttpClient();
|
||||||
|
_httpClient.BaseAddress = serverUrl;
|
||||||
|
_httpClient.Timeout = TimeSpan.FromSeconds(100);
|
||||||
|
await _httpClient.GetAsync("health", cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetMessageAsync(TaskAgentSession session, RunnerSettings settings, long? lastMessageId, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var response = await _httpClient.GetAsync($"message?tenant=org:github&root_tenant=org:github&group_id={settings.PoolId}&group_name={settings.PoolName}&runner_id={settings.AgentId}&runner_name={settings.AgentName}&labels=self-hosted,linux", cancellationToken);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var content = default(string);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
content = await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = $"HTTP {(int)response.StatusCode} {Enum.GetName(typeof(HttpStatusCode), response.StatusCode)}";
|
||||||
|
if (!string.IsNullOrEmpty(content))
|
||||||
|
{
|
||||||
|
error = $"{error}: {content}";
|
||||||
|
}
|
||||||
|
throw new Exception(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -86,7 +86,7 @@ namespace GitHub.Runner.Common
|
|||||||
public static class CommandLine
|
public static class CommandLine
|
||||||
{
|
{
|
||||||
//if you are adding a new arg, please make sure you update the
|
//if you are adding a new arg, please make sure you update the
|
||||||
//validOptions dictionary as well present in the CommandSettings.cs
|
//validArgs array as well present in the CommandSettings.cs
|
||||||
public static class Args
|
public static class Args
|
||||||
{
|
{
|
||||||
public static readonly string Auth = "auth";
|
public static readonly string Auth = "auth";
|
||||||
@@ -121,7 +121,7 @@ namespace GitHub.Runner.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if you are adding a new flag, please make sure you update the
|
//if you are adding a new flag, please make sure you update the
|
||||||
//validOptions dictionary as well present in the CommandSettings.cs
|
//validFlags array as well present in the CommandSettings.cs
|
||||||
public static class Flags
|
public static class Flags
|
||||||
{
|
{
|
||||||
public static readonly string Check = "check";
|
public static readonly string Check = "check";
|
||||||
@@ -150,7 +150,6 @@ namespace GitHub.Runner.Common
|
|||||||
{
|
{
|
||||||
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
public static readonly string DiskSpaceWarning = "runner.diskspace.warning";
|
||||||
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
|
public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action";
|
||||||
public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry";
|
||||||
|
|||||||
120
src/Runner.Common/RunServer.cs
Normal file
120
src/Runner.Common/RunServer.cs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using GitHub.Services.Common;
|
||||||
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
|
namespace GitHub.Runner.Common
|
||||||
|
{
|
||||||
|
[ServiceLocator(Default = typeof(RunServer))]
|
||||||
|
public interface IRunServer : IRunnerService
|
||||||
|
{
|
||||||
|
Task ConnectAsync(Uri serverUrl, VssCredentials credentials);
|
||||||
|
|
||||||
|
Task<AgentJobRequestMessage> GetJobMessageAsync(Guid scopeId, Guid hostId, string planType, string planGroup, Guid planId, IList<InstanceRef> instanceRefsJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class RunServer : RunnerService, IRunServer
|
||||||
|
{
|
||||||
|
private bool _hasConnection;
|
||||||
|
private VssConnection _connection;
|
||||||
|
private TaskAgentHttpClient _taskAgentClient;
|
||||||
|
|
||||||
|
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
||||||
|
{
|
||||||
|
// System.Console.WriteLine("RunServer.ConnectAsync");
|
||||||
|
_connection = await EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
||||||
|
_taskAgentClient = _connection.GetClient<TaskAgentHttpClient>();
|
||||||
|
_hasConnection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
|
||||||
|
{
|
||||||
|
// System.Console.WriteLine("EstablishVssConnection");
|
||||||
|
Trace.Info($"EstablishVssConnection");
|
||||||
|
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
|
||||||
|
int attemptCount = 5;
|
||||||
|
while (attemptCount-- > 0)
|
||||||
|
{
|
||||||
|
var connection = VssUtil.CreateConnection(serverUrl, credentials, timeout: timeout);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await connection.ConnectAsync();
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (attemptCount > 0)
|
||||||
|
{
|
||||||
|
Trace.Info($"Catch exception during connect. {attemptCount} attempt left.");
|
||||||
|
Trace.Error(ex);
|
||||||
|
|
||||||
|
await HostContext.Delay(TimeSpan.FromMilliseconds(100), CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// should never reach here.
|
||||||
|
throw new InvalidOperationException(nameof(EstablishVssConnection));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckConnection()
|
||||||
|
{
|
||||||
|
if (!_hasConnection)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"SetConnection");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<AgentJobRequestMessage> GetJobMessageAsync(
|
||||||
|
Guid scopeId,
|
||||||
|
Guid hostId,
|
||||||
|
string planType,
|
||||||
|
string planGroup,
|
||||||
|
Guid planId,
|
||||||
|
IList<InstanceRef> instanceRefsJson)
|
||||||
|
{
|
||||||
|
// System.Console.WriteLine("RunServer.GetMessageAsync");
|
||||||
|
CheckConnection();
|
||||||
|
return _taskAgentClient.GetJobMessageAsync(scopeId, hostId, planType, planGroup, planId, StringUtil.ConvertToJson(instanceRefsJson, Newtonsoft.Json.Formatting.None));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: move to SDK?
|
||||||
|
[DataContract]
|
||||||
|
public sealed class MessageRef
|
||||||
|
{
|
||||||
|
[DataMember(Name = "url")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
[DataMember(Name = "token")]
|
||||||
|
public string Token { get; set; }
|
||||||
|
[DataMember(Name = "scopeId")]
|
||||||
|
public Guid ScopeId { get; set; }
|
||||||
|
[DataMember(Name = "hostId")]
|
||||||
|
public Guid HostId { get; set; }
|
||||||
|
[DataMember(Name = "planType")]
|
||||||
|
public string PlanType { get; set; }
|
||||||
|
[DataMember(Name = "planGroup")]
|
||||||
|
public string PlanGroup { get; set; }
|
||||||
|
[DataMember(Name = "planId")]
|
||||||
|
public Guid PlanId { get; set; }
|
||||||
|
[DataMember(Name = "instanceRefs")]
|
||||||
|
public InstanceRef[] InstanceRefs { get; set; }
|
||||||
|
[DataMember(Name = "labels")]
|
||||||
|
public string[] Labels { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataContract]
|
||||||
|
public sealed class InstanceRef
|
||||||
|
{
|
||||||
|
[DataMember(Name = "name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[DataMember(Name = "instanceType")]
|
||||||
|
public string InstanceType { get; set; }
|
||||||
|
[DataMember(Name = "attempt")]
|
||||||
|
public int Attempt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ namespace GitHub.Runner.Common
|
|||||||
// job request
|
// job request
|
||||||
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
|
||||||
Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId, CancellationToken cancellationToken);
|
Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId, CancellationToken cancellationToken);
|
||||||
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken);
|
Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, Guid targetHostId, CancellationToken cancellationToken);
|
||||||
|
|
||||||
// agent package
|
// agent package
|
||||||
Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken);
|
Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken);
|
||||||
@@ -68,11 +68,23 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
public async Task ConnectAsync(Uri serverUrl, VssCredentials credentials)
|
||||||
{
|
{
|
||||||
var createGenericConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
// System.Console.WriteLine("RunnerServer.ConnectAsync: Create message connection");
|
||||||
var createMessageConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
|
var createMessageConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
|
||||||
var createRequestConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
|
await Task.WhenAll(createMessageConnection);
|
||||||
|
|
||||||
await Task.WhenAll(createGenericConnection, createMessageConnection, createRequestConnection);
|
// System.Console.WriteLine("RunnerServer.ConnectAsync: Create generic connection");
|
||||||
|
var createGenericConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
||||||
|
await Task.WhenAll(createGenericConnection);
|
||||||
|
|
||||||
|
// System.Console.WriteLine("RunnerServer.ConnectAsync: Create request connection");
|
||||||
|
var createRequestConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
|
||||||
|
await Task.WhenAll(createRequestConnection);
|
||||||
|
|
||||||
|
// var createGenericConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(100));
|
||||||
|
// var createMessageConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
|
||||||
|
// var createRequestConnection = EstablishVssConnection(serverUrl, credentials, TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
// await Task.WhenAll(createGenericConnection, createMessageConnection, createRequestConnection);
|
||||||
|
|
||||||
_genericConnection = await createGenericConnection;
|
_genericConnection = await createGenericConnection;
|
||||||
_messageConnection = await createMessageConnection;
|
_messageConnection = await createMessageConnection;
|
||||||
@@ -182,6 +194,8 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
|
private async Task<VssConnection> EstablishVssConnection(Uri serverUrl, VssCredentials credentials, TimeSpan timeout)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("EstablishVssConnection");
|
||||||
|
Trace.Info($"EstablishVssConnection");
|
||||||
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
|
Trace.Info($"Establish connection with {timeout.TotalSeconds} seconds timeout.");
|
||||||
int attemptCount = 5;
|
int attemptCount = 5;
|
||||||
while (attemptCount-- > 0)
|
while (attemptCount-- > 0)
|
||||||
@@ -238,41 +252,48 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation)
|
public Task<List<TaskAgentPool>> GetAgentPoolsAsync(string agentPoolName = null, TaskAgentPoolType poolType = TaskAgentPoolType.Automation)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetAgentPoolsAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.GetAgentPoolsAsync(agentPoolName, poolType: poolType);
|
return _genericTaskAgentClient.GetAgentPoolsAsync(agentPoolName, poolType: poolType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent)
|
public Task<TaskAgent> AddAgentAsync(Int32 agentPoolId, TaskAgent agent)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.AddAgentAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.AddAgentAsync(agentPoolId, agent);
|
return _genericTaskAgentClient.AddAgentAsync(agentPoolId, agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null)
|
public Task<List<TaskAgent>> GetAgentsAsync(int agentPoolId, string agentName = null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetAgentsAsync 1");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
|
return _genericTaskAgentClient.GetAgentsAsync(agentPoolId, agentName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<TaskAgent>> GetAgentsAsync(string agentName)
|
public Task<List<TaskAgent>> GetAgentsAsync(string agentName)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetAgentsAsync 2");
|
||||||
return GetAgentsAsync(0, agentName); // search in all all agentPools
|
return GetAgentsAsync(0, agentName); // search in all all agentPools
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent)
|
public Task<TaskAgent> ReplaceAgentAsync(int agentPoolId, TaskAgent agent)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.ReplaceAgentAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
|
return _genericTaskAgentClient.ReplaceAgentAsync(agentPoolId, agent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(int agentPoolId, int agentId)
|
public Task DeleteAgentAsync(int agentPoolId, int agentId)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.DeleteAgentAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
return _genericTaskAgentClient.DeleteAgentAsync(agentPoolId, agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentAsync(int agentId)
|
public Task DeleteAgentAsync(int agentId)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.DeleteAgentAsync");
|
||||||
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
return DeleteAgentAsync(0, agentId); // agentPool is ignored server side
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,24 +303,28 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken)
|
public Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.CreateAgentSessionAsync");
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||||
return _messageTaskAgentClient.CreateAgentSessionAsync(poolId, session, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.CreateAgentSessionAsync(poolId, session, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken)
|
public Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.DeleteAgentMessageAsync");
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||||
return _messageTaskAgentClient.DeleteMessageAsync(poolId, messageId, sessionId, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.DeleteMessageAsync(poolId, messageId, sessionId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken)
|
public Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.DeleteAgentSessionAsync");
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||||
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken)
|
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetAgentMessageAsync");
|
||||||
CheckConnection(RunnerConnectionType.MessageQueue);
|
CheckConnection(RunnerConnectionType.MessageQueue);
|
||||||
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken);
|
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -310,18 +335,21 @@ namespace GitHub.Runner.Common
|
|||||||
|
|
||||||
public Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId = null, CancellationToken cancellationToken = default(CancellationToken))
|
public Task<TaskAgentJobRequest> RenewAgentRequestAsync(int poolId, long requestId, Guid lockToken, string orchestrationId = null, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.RenewAgentRequestAsync");
|
||||||
CheckConnection(RunnerConnectionType.JobRequest);
|
CheckConnection(RunnerConnectionType.JobRequest);
|
||||||
return _requestTaskAgentClient.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId: orchestrationId, cancellationToken: cancellationToken);
|
return _requestTaskAgentClient.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId: orchestrationId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, CancellationToken cancellationToken = default(CancellationToken))
|
public Task<TaskAgentJobRequest> FinishAgentRequestAsync(int poolId, long requestId, Guid lockToken, DateTime finishTime, TaskResult result, Guid targetHostId, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.FinishAgentRequestAsync");
|
||||||
CheckConnection(RunnerConnectionType.JobRequest);
|
CheckConnection(RunnerConnectionType.JobRequest);
|
||||||
return _requestTaskAgentClient.FinishAgentRequestAsync(poolId, requestId, lockToken, finishTime, result, cancellationToken: cancellationToken);
|
return _requestTaskAgentClient.FinishAgentRequestAsync(poolId, requestId, lockToken, finishTime, result, targetHostId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken = default(CancellationToken))
|
public Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetAgentRequestAsync");
|
||||||
CheckConnection(RunnerConnectionType.JobRequest);
|
CheckConnection(RunnerConnectionType.JobRequest);
|
||||||
return _requestTaskAgentClient.GetAgentRequestAsync(poolId, requestId, cancellationToken: cancellationToken);
|
return _requestTaskAgentClient.GetAgentRequestAsync(poolId, requestId, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -331,18 +359,21 @@ namespace GitHub.Runner.Common
|
|||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken)
|
public Task<List<PackageMetadata>> GetPackagesAsync(string packageType, string platform, int top, bool includeToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetPackagesAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, includeToken, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackagesAsync(packageType, platform, top, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken)
|
public Task<PackageMetadata> GetPackageAsync(string packageType, string platform, string version, bool includeToken, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.GetPackageAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
return _genericTaskAgentClient.GetPackageAsync(packageType, platform, version, includeToken, cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace)
|
public Task<TaskAgent> UpdateAgentUpdateStateAsync(int agentPoolId, int agentId, string currentState, string trace)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("RunnerServer.UpdateAgentUpdateStateAsync");
|
||||||
CheckConnection(RunnerConnectionType.Generic);
|
CheckConnection(RunnerConnectionType.Generic);
|
||||||
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
return _genericTaskAgentClient.UpdateAgentUpdateStateAsync(agentPoolId, agentId, currentState, trace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,57 +17,43 @@ namespace GitHub.Runner.Listener
|
|||||||
private readonly IPromptManager _promptManager;
|
private readonly IPromptManager _promptManager;
|
||||||
private readonly Tracing _trace;
|
private readonly Tracing _trace;
|
||||||
|
|
||||||
// Valid flags for all commands
|
private readonly string[] validCommands =
|
||||||
private readonly string[] genericOptions =
|
|
||||||
{
|
{
|
||||||
Constants.Runner.CommandLine.Flags.Help,
|
Constants.Runner.CommandLine.Commands.Configure,
|
||||||
Constants.Runner.CommandLine.Flags.Version,
|
Constants.Runner.CommandLine.Commands.Remove,
|
||||||
Constants.Runner.CommandLine.Flags.Commit,
|
Constants.Runner.CommandLine.Commands.Run,
|
||||||
Constants.Runner.CommandLine.Flags.Check
|
Constants.Runner.CommandLine.Commands.Warmup,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Valid flags and args for specific command - key: command, value: array of valid flags and args
|
private readonly string[] validFlags =
|
||||||
private readonly Dictionary<string, string[]> validOptions = new Dictionary<string, string[]>
|
|
||||||
{
|
|
||||||
// Valid configure flags and args
|
|
||||||
[Constants.Runner.CommandLine.Commands.Configure] =
|
|
||||||
new string[]
|
|
||||||
{
|
{
|
||||||
|
Constants.Runner.CommandLine.Flags.Check,
|
||||||
|
Constants.Runner.CommandLine.Flags.Commit,
|
||||||
Constants.Runner.CommandLine.Flags.DisableUpdate,
|
Constants.Runner.CommandLine.Flags.DisableUpdate,
|
||||||
Constants.Runner.CommandLine.Flags.Ephemeral,
|
Constants.Runner.CommandLine.Flags.Ephemeral,
|
||||||
|
Constants.Runner.CommandLine.Flags.Help,
|
||||||
|
Constants.Runner.CommandLine.Flags.Once,
|
||||||
Constants.Runner.CommandLine.Flags.Replace,
|
Constants.Runner.CommandLine.Flags.Replace,
|
||||||
Constants.Runner.CommandLine.Flags.RunAsService,
|
Constants.Runner.CommandLine.Flags.RunAsService,
|
||||||
Constants.Runner.CommandLine.Flags.Unattended,
|
Constants.Runner.CommandLine.Flags.Unattended,
|
||||||
|
Constants.Runner.CommandLine.Flags.Version
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly string[] validArgs =
|
||||||
|
{
|
||||||
Constants.Runner.CommandLine.Args.Auth,
|
Constants.Runner.CommandLine.Args.Auth,
|
||||||
Constants.Runner.CommandLine.Args.Labels,
|
Constants.Runner.CommandLine.Args.Labels,
|
||||||
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
|
||||||
Constants.Runner.CommandLine.Args.Name,
|
Constants.Runner.CommandLine.Args.Name,
|
||||||
Constants.Runner.CommandLine.Args.PAT,
|
Constants.Runner.CommandLine.Args.PAT,
|
||||||
Constants.Runner.CommandLine.Args.RunnerGroup,
|
Constants.Runner.CommandLine.Args.RunnerGroup,
|
||||||
|
Constants.Runner.CommandLine.Args.StartupType,
|
||||||
Constants.Runner.CommandLine.Args.Token,
|
Constants.Runner.CommandLine.Args.Token,
|
||||||
Constants.Runner.CommandLine.Args.Url,
|
Constants.Runner.CommandLine.Args.Url,
|
||||||
Constants.Runner.CommandLine.Args.UserName,
|
Constants.Runner.CommandLine.Args.UserName,
|
||||||
Constants.Runner.CommandLine.Args.WindowsLogonAccount,
|
Constants.Runner.CommandLine.Args.WindowsLogonAccount,
|
||||||
Constants.Runner.CommandLine.Args.WindowsLogonPassword,
|
Constants.Runner.CommandLine.Args.WindowsLogonPassword,
|
||||||
Constants.Runner.CommandLine.Args.Work
|
Constants.Runner.CommandLine.Args.Work
|
||||||
},
|
|
||||||
// Valid remove flags and args
|
|
||||||
[Constants.Runner.CommandLine.Commands.Remove] =
|
|
||||||
new string[]
|
|
||||||
{
|
|
||||||
Constants.Runner.CommandLine.Args.Token,
|
|
||||||
Constants.Runner.CommandLine.Args.PAT
|
|
||||||
},
|
|
||||||
// Valid run flags and args
|
|
||||||
[Constants.Runner.CommandLine.Commands.Run] =
|
|
||||||
new string[]
|
|
||||||
{
|
|
||||||
Constants.Runner.CommandLine.Flags.Once,
|
|
||||||
Constants.Runner.CommandLine.Args.StartupType
|
|
||||||
},
|
|
||||||
// valid warmup flags and args
|
|
||||||
[Constants.Runner.CommandLine.Commands.Warmup] =
|
|
||||||
new string[] { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Commands.
|
// Commands.
|
||||||
@@ -140,48 +126,17 @@ namespace GitHub.Runner.Listener
|
|||||||
List<string> unknowns = new List<string>();
|
List<string> unknowns = new List<string>();
|
||||||
|
|
||||||
// detect unknown commands
|
// detect unknown commands
|
||||||
unknowns.AddRange(_parser.Commands.Where(x => !validOptions.Keys.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
unknowns.AddRange(_parser.Commands.Where(x => !validCommands.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||||
|
|
||||||
if (unknowns.Count == 0)
|
// detect unknown flags
|
||||||
{
|
unknowns.AddRange(_parser.Flags.Where(x => !validFlags.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||||
// detect unknown flags and args for valid commands
|
|
||||||
foreach (var command in _parser.Commands)
|
// detect unknown args
|
||||||
{
|
unknowns.AddRange(_parser.Args.Keys.Where(x => !validArgs.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
||||||
if (validOptions.TryGetValue(command, out string[] options))
|
|
||||||
{
|
|
||||||
unknowns.AddRange(_parser.Flags.Where(x => !options.Contains(x, StringComparer.OrdinalIgnoreCase) && !genericOptions.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
|
||||||
unknowns.AddRange(_parser.Args.Keys.Where(x => !options.Contains(x, StringComparer.OrdinalIgnoreCase)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return unknowns;
|
return unknowns;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCommandName()
|
|
||||||
{
|
|
||||||
string command = string.Empty;
|
|
||||||
|
|
||||||
if (Configure)
|
|
||||||
{
|
|
||||||
command = Constants.Runner.CommandLine.Commands.Configure;
|
|
||||||
}
|
|
||||||
else if (Remove)
|
|
||||||
{
|
|
||||||
command = Constants.Runner.CommandLine.Commands.Remove;
|
|
||||||
}
|
|
||||||
else if (Run)
|
|
||||||
{
|
|
||||||
command = Constants.Runner.CommandLine.Commands.Run;
|
|
||||||
}
|
|
||||||
else if (Warmup)
|
|
||||||
{
|
|
||||||
command = Constants.Runner.CommandLine.Commands.Warmup;
|
|
||||||
}
|
|
||||||
|
|
||||||
return command;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Interactive flags.
|
// Interactive flags.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
return creds;
|
return creds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_BROKER
|
||||||
|
public VssCredentials LoadCredentials()
|
||||||
|
{
|
||||||
|
return new VssCredentials();
|
||||||
|
}
|
||||||
|
#else
|
||||||
public VssCredentials LoadCredentials()
|
public VssCredentials LoadCredentials()
|
||||||
{
|
{
|
||||||
IConfigurationStore store = HostContext.GetService<IConfigurationStore>();
|
IConfigurationStore store = HostContext.GetService<IConfigurationStore>();
|
||||||
@@ -69,6 +75,7 @@ namespace GitHub.Runner.Listener.Configuration
|
|||||||
|
|
||||||
return creds;
|
return creds;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataContract]
|
[DataContract]
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
bool Busy { get; }
|
bool Busy { get; }
|
||||||
TaskCompletionSource<bool> RunOnceJobCompleted { get; }
|
TaskCompletionSource<bool> RunOnceJobCompleted { get; }
|
||||||
void Run(Pipelines.AgentJobRequestMessage message, bool runOnce = false);
|
void Run(Guid targetHostId, Pipelines.AgentJobRequestMessage message, bool runOnce = false);
|
||||||
bool Cancel(JobCancelMessage message);
|
bool Cancel(JobCancelMessage message);
|
||||||
Task WaitAsync(CancellationToken token);
|
Task WaitAsync(CancellationToken token);
|
||||||
Task ShutdownAsync();
|
Task ShutdownAsync();
|
||||||
@@ -79,7 +79,7 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
public bool Busy { get; private set; }
|
public bool Busy { get; private set; }
|
||||||
|
|
||||||
public void Run(Pipelines.AgentJobRequestMessage jobRequestMessage, bool runOnce = false)
|
public void Run(Guid targetHostId, Pipelines.AgentJobRequestMessage jobRequestMessage, bool runOnce = false)
|
||||||
{
|
{
|
||||||
Trace.Info($"Job request {jobRequestMessage.RequestId} for plan {jobRequestMessage.Plan.PlanId} job {jobRequestMessage.JobId} received.");
|
Trace.Info($"Job request {jobRequestMessage.RequestId} for plan {jobRequestMessage.Plan.PlanId} job {jobRequestMessage.JobId} received.");
|
||||||
|
|
||||||
@@ -112,11 +112,11 @@ namespace GitHub.Runner.Listener
|
|||||||
if (runOnce)
|
if (runOnce)
|
||||||
{
|
{
|
||||||
Trace.Info("Start dispatcher for one time used runner.");
|
Trace.Info("Start dispatcher for one time used runner.");
|
||||||
newDispatch.WorkerDispatch = RunOnceAsync(jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
newDispatch.WorkerDispatch = RunOnceAsync(targetHostId, jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newDispatch.WorkerDispatch = RunAsync(jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
newDispatch.WorkerDispatch = RunAsync(targetHostId, jobRequestMessage, orchestrationId, currentDispatch, newDispatch.WorkerCancellationTokenSource.Token, newDispatch.WorkerCancelTimeoutKillTokenSource.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
_jobInfos.TryAdd(newDispatch.JobId, newDispatch);
|
_jobInfos.TryAdd(newDispatch.JobId, newDispatch);
|
||||||
@@ -317,11 +317,11 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunOnceAsync(Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
private async Task RunOnceAsync(Guid targetHostId, Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await RunAsync(message, orchestrationId, previousJobDispatch, jobRequestCancellationToken, workerCancelTimeoutKillToken);
|
await RunAsync(targetHostId, message, orchestrationId, previousJobDispatch, jobRequestCancellationToken, workerCancelTimeoutKillToken);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -330,7 +330,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RunAsync(Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
private async Task RunAsync(Guid targetHostId, Pipelines.AgentJobRequestMessage message, string orchestrationId, WorkerDispatcher previousJobDispatch, CancellationToken jobRequestCancellationToken, CancellationToken workerCancelTimeoutKillToken)
|
||||||
{
|
{
|
||||||
Busy = true;
|
Busy = true;
|
||||||
try
|
try
|
||||||
@@ -383,7 +383,7 @@ namespace GitHub.Runner.Listener
|
|||||||
await renewJobRequest;
|
await renewJobRequest;
|
||||||
|
|
||||||
// complete job request with result Cancelled
|
// complete job request with result Cancelled
|
||||||
await CompleteJobRequestAsync(_poolId, message, lockToken, TaskResult.Canceled);
|
await CompleteJobRequestAsync(targetHostId, _poolId, message, lockToken, TaskResult.Canceled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,7 +540,7 @@ namespace GitHub.Runner.Listener
|
|||||||
await renewJobRequest;
|
await renewJobRequest;
|
||||||
|
|
||||||
// complete job request
|
// complete job request
|
||||||
await CompleteJobRequestAsync(_poolId, message, lockToken, result, detailInfo);
|
await CompleteJobRequestAsync(targetHostId, _poolId, message, lockToken, result, detailInfo);
|
||||||
|
|
||||||
// print out unhandled exception happened in worker after we complete job request.
|
// print out unhandled exception happened in worker after we complete job request.
|
||||||
// when we run out of disk space, report back to server has higher priority.
|
// when we run out of disk space, report back to server has higher priority.
|
||||||
@@ -637,7 +637,7 @@ namespace GitHub.Runner.Listener
|
|||||||
await renewJobRequest;
|
await renewJobRequest;
|
||||||
|
|
||||||
// complete job request
|
// complete job request
|
||||||
await CompleteJobRequestAsync(_poolId, message, lockToken, resultOnAbandonOrCancel);
|
await CompleteJobRequestAsync(targetHostId, _poolId, message, lockToken, resultOnAbandonOrCancel);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -666,17 +666,25 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
|
// #if USE_BROKER
|
||||||
Trace.Info($"Successfully renew job request {requestId}, job is valid till {request.LockedUntil.Value}");
|
|
||||||
|
|
||||||
if (!firstJobRequestRenewed.Task.IsCompleted)
|
if (!firstJobRequestRenewed.Task.IsCompleted)
|
||||||
{
|
{
|
||||||
// fire first renew succeed event.
|
// fire first renew succeed event.
|
||||||
firstJobRequestRenewed.TrySetResult(0);
|
firstJobRequestRenewed.TrySetResult(0);
|
||||||
|
|
||||||
// Update settings if the runner name has been changed server-side
|
|
||||||
UpdateAgentNameIfNeeded(request.ReservedAgent?.Name);
|
|
||||||
}
|
}
|
||||||
|
// #else
|
||||||
|
// request = await runnerServer.RenewAgentRequestAsync(poolId, requestId, lockToken, orchestrationId, token);
|
||||||
|
// Trace.Info($"Successfully renew job request {requestId}, job is valid till {request?.LockedUntil.Value}");
|
||||||
|
|
||||||
|
// if (!firstJobRequestRenewed.Task.IsCompleted)
|
||||||
|
// {
|
||||||
|
// // fire first renew succeed event.
|
||||||
|
// firstJobRequestRenewed.TrySetResult(0);
|
||||||
|
|
||||||
|
// // Update settings if the runner name has been changed server-side
|
||||||
|
// UpdateAgentNameIfNeeded(request.ReservedAgent?.Name);
|
||||||
|
// }
|
||||||
|
// #endif
|
||||||
|
|
||||||
if (encounteringError > 0)
|
if (encounteringError > 0)
|
||||||
{
|
{
|
||||||
@@ -911,7 +919,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CompleteJobRequestAsync(int poolId, Pipelines.AgentJobRequestMessage message, Guid lockToken, TaskResult result, string detailInfo = null)
|
private async Task CompleteJobRequestAsync(Guid targetHostId, int poolId, Pipelines.AgentJobRequestMessage message, Guid lockToken, TaskResult result, string detailInfo = null)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
|
|
||||||
@@ -928,7 +936,7 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await runnerServer.FinishAgentRequestAsync(poolId, message.RequestId, lockToken, DateTime.UtcNow, result, CancellationToken.None);
|
await runnerServer.FinishAgentRequestAsync(poolId, message.RequestId, lockToken, DateTime.UtcNow, result, targetHostId, CancellationToken.None);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (TaskAgentJobNotFoundException)
|
catch (TaskAgentJobNotFoundException)
|
||||||
|
|||||||
@@ -2,7 +2,11 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -27,10 +31,13 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
public sealed class MessageListener : RunnerService, IMessageListener
|
public sealed class MessageListener : RunnerService, IMessageListener
|
||||||
{
|
{
|
||||||
|
#if !USE_BROKER
|
||||||
private long? _lastMessageId;
|
private long? _lastMessageId;
|
||||||
|
#endif
|
||||||
private RunnerSettings _settings;
|
private RunnerSettings _settings;
|
||||||
private ITerminal _term;
|
private ITerminal _term;
|
||||||
private IRunnerServer _runnerServer;
|
private IRunnerServer _runnerServer;
|
||||||
|
private IBrokerServer _brokerServer;
|
||||||
private TaskAgentSession _session;
|
private TaskAgentSession _session;
|
||||||
private TimeSpan _getNextMessageRetryInterval;
|
private TimeSpan _getNextMessageRetryInterval;
|
||||||
private bool _accessTokenRevoked = false;
|
private bool _accessTokenRevoked = false;
|
||||||
@@ -45,8 +52,44 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
_term = HostContext.GetService<ITerminal>();
|
_term = HostContext.GetService<ITerminal>();
|
||||||
_runnerServer = HostContext.GetService<IRunnerServer>();
|
_runnerServer = HostContext.GetService<IRunnerServer>();
|
||||||
|
_brokerServer = HostContext.GetService<IBrokerServer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_BROKER
|
||||||
|
public async Task<Boolean> CreateSessionAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
Trace.Entering();
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
var configManager = HostContext.GetService<IConfigurationManager>();
|
||||||
|
_settings = configManager.LoadSettings();
|
||||||
|
var serverUrl = _settings.ServerUrl;
|
||||||
|
Trace.Info(_settings);
|
||||||
|
|
||||||
|
// Connect
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
Trace.Info($"Attempt to create session.");
|
||||||
|
Trace.Info("Connecting to the Runner Server...");
|
||||||
|
_term.WriteLine($"Connecting to {new Uri(serverUrl)}");
|
||||||
|
await _brokerServer.ConnectAsync(new Uri(serverUrl), token);
|
||||||
|
_term.WriteLine();
|
||||||
|
_term.WriteSuccessMessage("Connected to GitHub");
|
||||||
|
_term.WriteLine();
|
||||||
|
|
||||||
|
// Session info
|
||||||
|
var agent = new TaskAgentReference
|
||||||
|
{
|
||||||
|
Id = _settings.AgentId,
|
||||||
|
Name = _settings.AgentName,
|
||||||
|
Version = BuildConstants.RunnerPackage.Version,
|
||||||
|
OSDescription = RuntimeInformation.OSDescription,
|
||||||
|
};
|
||||||
|
string sessionName = $"{Environment.MachineName ?? "RUNNER"}";
|
||||||
|
_session = new TaskAgentSession(sessionName, agent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
public async Task<Boolean> CreateSessionAsync(CancellationToken token)
|
public async Task<Boolean> CreateSessionAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
@@ -81,6 +124,7 @@ namespace GitHub.Runner.Listener
|
|||||||
Trace.Info($"Attempt to create session.");
|
Trace.Info($"Attempt to create session.");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Trace.Info("Connecting to the Runner Server...");
|
||||||
Trace.Info("Connecting to the Runner Server...");
|
Trace.Info("Connecting to the Runner Server...");
|
||||||
await _runnerServer.ConnectAsync(new Uri(serverUrl), creds);
|
await _runnerServer.ConnectAsync(new Uri(serverUrl), creds);
|
||||||
Trace.Info("VssConnection created");
|
Trace.Info("VssConnection created");
|
||||||
@@ -151,6 +195,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public async Task DeleteSessionAsync()
|
public async Task DeleteSessionAsync()
|
||||||
{
|
{
|
||||||
@@ -170,6 +215,167 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_BROKER
|
||||||
|
[DataContract]
|
||||||
|
public sealed class MessageRef
|
||||||
|
{
|
||||||
|
[DataMember(Name = "url")]
|
||||||
|
public string Url { get; set; }
|
||||||
|
[DataMember(Name = "token")]
|
||||||
|
public string Token { get; set; }
|
||||||
|
[DataMember(Name = "scopeId")]
|
||||||
|
public string ScopeId { get; set; }
|
||||||
|
[DataMember(Name = "planType")]
|
||||||
|
public string PlanType { get; set; }
|
||||||
|
[DataMember(Name = "planGroup")]
|
||||||
|
public string PlanGroup { get; set; }
|
||||||
|
[DataMember(Name = "instanceRefs")]
|
||||||
|
public InstanceRef[] InstanceRefs { get; set; }
|
||||||
|
[DataMember(Name = "labels")]
|
||||||
|
public string[] Labels { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataContract]
|
||||||
|
public sealed class InstanceRef
|
||||||
|
{
|
||||||
|
[DataMember(Name = "name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[DataMember(Name = "instanceType")]
|
||||||
|
public string InstanceType { get; set; }
|
||||||
|
[DataMember(Name = "attempt")]
|
||||||
|
public int Attempt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
|
||||||
|
{
|
||||||
|
Trace.Entering();
|
||||||
|
ArgUtil.NotNull(_session, nameof(_session));
|
||||||
|
ArgUtil.NotNull(_settings, nameof(_settings));
|
||||||
|
bool encounteringError = false;
|
||||||
|
int continuousError = 0;
|
||||||
|
string errorMessage = string.Empty;
|
||||||
|
Stopwatch heartbeat = new Stopwatch();
|
||||||
|
heartbeat.Restart();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
token.ThrowIfCancellationRequested();
|
||||||
|
string message = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
message = await _brokerServer.GetMessageAsync(_session, _settings, null/*_lastMessageId*/, token);
|
||||||
|
_term.WriteLine($"{DateTime.UtcNow:u}: {message}");
|
||||||
|
if (!string.IsNullOrEmpty(message))
|
||||||
|
{
|
||||||
|
var messageRef = StringUtil.ConvertFromJson<MessageRef>(message);
|
||||||
|
var client = new HttpClient();
|
||||||
|
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", messageRef.Token);
|
||||||
|
var response = await client.GetAsync(messageRef.Url, token);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var content = default(string);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
content = await response.Content.ReadAsStringAsync();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = $"HTTP {(int)response.StatusCode} {Enum.GetName(typeof(HttpStatusCode), response.StatusCode)}";
|
||||||
|
if (!string.IsNullOrEmpty(content))
|
||||||
|
{
|
||||||
|
error = $"{error}: {content}";
|
||||||
|
}
|
||||||
|
throw new Exception(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fullMessage = await response.Content.ReadAsStringAsync();
|
||||||
|
return StringUtil.ConvertFromJson<TaskAgentMessage>(fullMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encounteringError) //print the message once only if there was an error
|
||||||
|
{
|
||||||
|
_term.WriteLine($"{DateTime.UtcNow:u}: Runner reconnected.");
|
||||||
|
encounteringError = false;
|
||||||
|
continuousError = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
Trace.Info("Get next message has been cancelled.");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (TaskAgentAccessTokenExpiredException)
|
||||||
|
{
|
||||||
|
Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
|
||||||
|
_accessTokenRevoked = true;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Trace.Error("Catch exception during get next message.");
|
||||||
|
Trace.Error(ex);
|
||||||
|
|
||||||
|
// don't retry if SkipSessionRecover = true, DT service will delete agent session to stop agent from taking more jobs.
|
||||||
|
if (ex is TaskAgentSessionExpiredException && !_settings.SkipSessionRecover && await CreateSessionAsync(token))
|
||||||
|
{
|
||||||
|
Trace.Info($"{nameof(TaskAgentSessionExpiredException)} received, recovered by recreate session.");
|
||||||
|
}
|
||||||
|
else if (!IsGetNextMessageExceptionRetriable(ex))
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continuousError++;
|
||||||
|
//retry after a random backoff to avoid service throttling
|
||||||
|
//in case of there is a service error happened and all agents get kicked off of the long poll and all agent try to reconnect back at the same time.
|
||||||
|
if (continuousError <= 5)
|
||||||
|
{
|
||||||
|
// random backoff [15, 30]
|
||||||
|
_getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), _getNextMessageRetryInterval);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// more aggressive backoff [30, 60]
|
||||||
|
_getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(60), _getNextMessageRetryInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!encounteringError)
|
||||||
|
{
|
||||||
|
//print error only on the first consecutive error
|
||||||
|
_term.WriteError($"{DateTime.UtcNow:u}: Runner connect error: {ex.Message}. Retrying until reconnected.");
|
||||||
|
encounteringError = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// re-create VssConnection before next retry
|
||||||
|
await _runnerServer.RefreshConnectionAsync(RunnerConnectionType.MessageQueue, TimeSpan.FromSeconds(60));
|
||||||
|
|
||||||
|
Trace.Info("Sleeping for {0} seconds before retrying.", _getNextMessageRetryInterval.TotalSeconds);
|
||||||
|
await HostContext.Delay(_getNextMessageRetryInterval, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (message == null)
|
||||||
|
// {
|
||||||
|
// if (heartbeat.Elapsed > TimeSpan.FromMinutes(30))
|
||||||
|
// {
|
||||||
|
// Trace.Info($"No message retrieved from session '{_session.SessionId}' within last 30 minutes.");
|
||||||
|
// heartbeat.Restart();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// Trace.Verbose($"No message retrieved from session '{_session.SessionId}'.");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Trace.Info($"Message '{message.MessageId}' received from session '{_session.SessionId}'.");
|
||||||
|
// return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
|
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
|
||||||
{
|
{
|
||||||
Trace.Entering();
|
Trace.Entering();
|
||||||
@@ -281,6 +487,7 @@ namespace GitHub.Runner.Listener
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
public async Task DeleteMessageAsync(TaskAgentMessage message)
|
public async Task DeleteMessageAsync(TaskAgentMessage message)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,15 +95,7 @@ namespace GitHub.Runner.Listener
|
|||||||
var unknownCommandlines = command.Validate();
|
var unknownCommandlines = command.Validate();
|
||||||
if (unknownCommandlines.Count > 0)
|
if (unknownCommandlines.Count > 0)
|
||||||
{
|
{
|
||||||
string commandName = command.GetCommandName();
|
terminal.WriteError($"Unrecognized command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
|
||||||
if (string.IsNullOrEmpty(commandName))
|
|
||||||
{
|
|
||||||
terminal.WriteError($"This command does not recognize the command-line input arguments: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
terminal.WriteError($"Unrecognized command-line input arguments for command {commandName}: '{string.Join(", ", unknownCommandlines)}'. For usage refer to: .\\config.cmd --help or ./config.sh --help");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Defer to the Runner class to execute the command.
|
// Defer to the Runner class to execute the command.
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ using GitHub.Runner.Sdk;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using GitHub.Runner.Listener.Check;
|
using GitHub.Runner.Listener.Check;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
namespace GitHub.Runner.Listener
|
namespace GitHub.Runner.Listener
|
||||||
{
|
{
|
||||||
@@ -449,7 +453,37 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
Trace.Info($"Received job message of length {message.Body.Length} from service, with hash '{IOUtil.GetSha256Hash(message.Body)}'");
|
Trace.Info($"Received job message of length {message.Body.Length} from service, with hash '{IOUtil.GetSha256Hash(message.Body)}'");
|
||||||
var jobMessage = StringUtil.ConvertFromJson<Pipelines.AgentJobRequestMessage>(message.Body);
|
var jobMessage = StringUtil.ConvertFromJson<Pipelines.AgentJobRequestMessage>(message.Body);
|
||||||
jobDispatcher.Run(jobMessage, runOnce);
|
jobDispatcher.Run(Guid.Empty, jobMessage, runOnce);
|
||||||
|
if (runOnce)
|
||||||
|
{
|
||||||
|
Trace.Info("One time used runner received job message.");
|
||||||
|
runOnceJobReceived = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Broker flow
|
||||||
|
else if (string.Equals(message.MessageType, JobRequestMessageTypes.RunnerJobRequest, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (autoUpdateInProgress || runOnceJobReceived)
|
||||||
|
{
|
||||||
|
skipMessageDeletion = true;
|
||||||
|
Trace.Info($"Skip message deletion for job request message '{message.MessageId}'.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var messageRef = StringUtil.ConvertFromJson<MessageRef>(message.Body);
|
||||||
|
|
||||||
|
// Create connection
|
||||||
|
var credMgr = HostContext.GetService<ICredentialManager>();
|
||||||
|
var creds = credMgr.LoadCredentials();
|
||||||
|
|
||||||
|
// todo: add retries
|
||||||
|
var runServer = HostContext.CreateService<IRunServer>();
|
||||||
|
await runServer.ConnectAsync(new Uri(settings.ServerUrl), creds);
|
||||||
|
var jobMessage = await runServer.GetJobMessageAsync(messageRef.ScopeId, messageRef.HostId, messageRef.PlanType, messageRef.PlanGroup, messageRef.PlanId, messageRef.InstanceRefs);
|
||||||
|
|
||||||
|
// todo: Trace.Info($"Received job message of length {message.Body.Length} from service, with hash '{IOUtil.GetSha256Hash(message.Body)}'");
|
||||||
|
jobDispatcher.Run(messageRef.HostId, jobMessage, runOnce);
|
||||||
if (runOnce)
|
if (runOnce)
|
||||||
{
|
{
|
||||||
Trace.Info("One time used runner received job message.");
|
Trace.Info("One time used runner received job message.");
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ namespace GitHub.Runner.Sdk
|
|||||||
|
|
||||||
public static VssConnection CreateConnection(Uri serverUri, VssCredentials credentials, IEnumerable<DelegatingHandler> additionalDelegatingHandler = null, TimeSpan? timeout = null)
|
public static VssConnection CreateConnection(Uri serverUri, VssCredentials credentials, IEnumerable<DelegatingHandler> additionalDelegatingHandler = null, TimeSpan? timeout = null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssUtil.CreateConnection");
|
||||||
VssClientHttpRequestSettings settings = VssClientHttpRequestSettings.Default.Clone();
|
VssClientHttpRequestSettings settings = VssClientHttpRequestSettings.Default.Clone();
|
||||||
|
|
||||||
int maxRetryRequest;
|
int maxRetryRequest;
|
||||||
|
|||||||
@@ -817,6 +817,7 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
// Something else bad happened, let's go to our retry logic
|
// Something else bad happened, let's go to our retry logic
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
|
throw new Exception("Unexpected response code: " + response.StatusCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using GitHub.DistributedTask.ObjectTemplating;
|
using GitHub.DistributedTask.ObjectTemplating;
|
||||||
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||||
@@ -10,6 +9,7 @@ using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
|||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
|
using GitHub.Runner.Worker;
|
||||||
using GitHub.Runner.Worker.Handlers;
|
using GitHub.Runner.Worker.Handlers;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
|
|
||||||
@@ -171,16 +171,8 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// Load the inputs.
|
// Load the inputs.
|
||||||
ExecutionContext.Debug("Loading inputs");
|
ExecutionContext.Debug("Loading inputs");
|
||||||
Dictionary<string, string> inputs;
|
|
||||||
if (ExecutionContext.Global.Variables.GetBoolean(Constants.Runner.Features.UseContainerPathForTemplate) ?? false)
|
|
||||||
{
|
|
||||||
inputs = EvaluateStepInputs(stepHost);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
||||||
inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);
|
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);
|
||||||
}
|
|
||||||
|
|
||||||
var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
var userInputs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
foreach (KeyValuePair<string, string> input in inputs)
|
foreach (KeyValuePair<string, string> input in inputs)
|
||||||
@@ -307,15 +299,6 @@ namespace GitHub.Runner.Worker
|
|||||||
return didFullyEvaluate;
|
return didFullyEvaluate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<String, String> EvaluateStepInputs(IStepHost stepHost)
|
|
||||||
{
|
|
||||||
DictionaryContextData expressionValues = ExecutionContext.GetExpressionValues(stepHost);
|
|
||||||
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
|
||||||
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, expressionValues, ExecutionContext.ExpressionFunctions);
|
|
||||||
|
|
||||||
return inputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GenerateDisplayName(ActionStep action, DictionaryContextData contextData, IExecutionContext context, out bool didFullyEvaluate)
|
private string GenerateDisplayName(ActionStep action, DictionaryContextData contextData, IExecutionContext context, out bool didFullyEvaluate)
|
||||||
{
|
{
|
||||||
ArgUtil.NotNull(context, nameof(context));
|
ArgUtil.NotNull(context, nameof(context));
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Web;
|
||||||
using GitHub.DistributedTask.Expressions2;
|
using GitHub.DistributedTask.Expressions2;
|
||||||
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||||
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
@@ -15,7 +20,7 @@ using GitHub.Runner.Common;
|
|||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
using GitHub.Runner.Worker.Handlers;
|
using GitHub.Services.WebApi;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
|
using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating;
|
||||||
using Pipelines = GitHub.DistributedTask.Pipelines;
|
using Pipelines = GitHub.DistributedTask.Pipelines;
|
||||||
@@ -110,6 +115,7 @@ namespace GitHub.Runner.Worker
|
|||||||
void UpdateGlobalStepsContext();
|
void UpdateGlobalStepsContext();
|
||||||
|
|
||||||
void WriteWebhookPayload();
|
void WriteWebhookPayload();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
public sealed class ExecutionContext : RunnerService, IExecutionContext
|
||||||
@@ -1193,66 +1199,6 @@ namespace GitHub.Runner.Worker
|
|||||||
{
|
{
|
||||||
return new TemplateTraceWriter(context);
|
return new TemplateTraceWriter(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DictionaryContextData GetExpressionValues(this IExecutionContext context, IStepHost stepHost)
|
|
||||||
{
|
|
||||||
if (stepHost is ContainerStepHost)
|
|
||||||
{
|
|
||||||
|
|
||||||
var expressionValues = context.ExpressionValues.Clone() as DictionaryContextData;
|
|
||||||
context.UpdatePathsInExpressionValues("github", expressionValues, stepHost);
|
|
||||||
context.UpdatePathsInExpressionValues("runner", expressionValues, stepHost);
|
|
||||||
return expressionValues;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return context.ExpressionValues.Clone() as DictionaryContextData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void UpdatePathsInExpressionValues(this IExecutionContext context, string contextName, DictionaryContextData expressionValues, IStepHost stepHost)
|
|
||||||
{
|
|
||||||
var dict = expressionValues[contextName].AssertDictionary($"expected context {contextName} to be a dictionary");
|
|
||||||
context.ResolvePathsInExpressionValuesDictionary(dict, stepHost);
|
|
||||||
expressionValues[contextName] = dict;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ResolvePathsInExpressionValuesDictionary(this IExecutionContext context, DictionaryContextData dict, IStepHost stepHost)
|
|
||||||
{
|
|
||||||
foreach (var key in dict.Keys.ToList())
|
|
||||||
{
|
|
||||||
if (dict[key] is StringContextData)
|
|
||||||
{
|
|
||||||
var value = dict[key].ToString();
|
|
||||||
if (!string.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
dict[key] = new StringContextData(stepHost.ResolvePathForStepHost(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (dict[key] is DictionaryContextData)
|
|
||||||
{
|
|
||||||
var innerDict = dict[key].AssertDictionary("expected dictionary");
|
|
||||||
context.ResolvePathsInExpressionValuesDictionary(innerDict, stepHost);
|
|
||||||
var updatedDict = new DictionaryContextData();
|
|
||||||
foreach (var k in innerDict.Keys.ToList())
|
|
||||||
{
|
|
||||||
updatedDict[k] = innerDict[k];
|
|
||||||
}
|
|
||||||
dict[key] = updatedDict;
|
|
||||||
}
|
|
||||||
else if (dict[key] is CaseSensitiveDictionaryContextData)
|
|
||||||
{
|
|
||||||
var innerDict = dict[key].AssertDictionary("expected dictionary");
|
|
||||||
context.ResolvePathsInExpressionValuesDictionary(innerDict, stepHost);
|
|
||||||
var updatedDict = new CaseSensitiveDictionaryContextData();
|
|
||||||
foreach (var k in innerDict.Keys.ToList())
|
|
||||||
{
|
|
||||||
updatedDict[k] = innerDict[k];
|
|
||||||
}
|
|
||||||
dict[key] = updatedDict;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class TemplateTraceWriter : ObjectTemplating.ITraceWriter
|
internal sealed class TemplateTraceWriter : ObjectTemplating.ITraceWriter
|
||||||
|
|||||||
@@ -151,17 +151,6 @@ namespace GitHub.Runner.Worker.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (line.Contains("fatal: unsafe repository", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
_executionContext.StepTelemetry.ErrorMessages.Add(line);
|
|
||||||
var gitUnsafeDirNotice = new DTWebApi.Issue
|
|
||||||
{
|
|
||||||
Message = $"You may experience error caused by a recently git safe directory enforcement. For more information see: https://github.blog/changelog/xxx",
|
|
||||||
Type = DTWebApi.IssueType.Notice,
|
|
||||||
};
|
|
||||||
_executionContext.AddIssue(gitUnsafeDirNotice);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regular output
|
// Regular output
|
||||||
_executionContext.Output(line);
|
_executionContext.Output(line);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Channels;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.DistributedTask.WebApi;
|
||||||
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
|
using GitHub.Services.WebApi;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Worker.Handlers
|
namespace GitHub.Runner.Worker.Handlers
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -132,7 +132,7 @@
|
|||||||
"continue-on-error": "boolean-steps-context",
|
"continue-on-error": "boolean-steps-context",
|
||||||
"working-directory": "string-steps-context",
|
"working-directory": "string-steps-context",
|
||||||
"shell": {
|
"shell": {
|
||||||
"type": "string-steps-context",
|
"type": "non-empty-string",
|
||||||
"required": true
|
"required": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
public override bool IsAuthenticationChallenge(IHttpResponse webResponse)
|
public override bool IsAuthenticationChallenge(IHttpResponse webResponse)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"FederatedCredential.IsAuthenticationChallenge");
|
||||||
if (webResponse == null)
|
if (webResponse == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ namespace GitHub.Services.Common
|
|||||||
IHttpResponse response,
|
IHttpResponse response,
|
||||||
IssuedToken failedToken)
|
IssuedToken failedToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("IssuedTokenCredential.CreateTokenProvider");
|
||||||
if (response != null && !IsAuthenticationChallenge(response))
|
if (response != null && !IsAuthenticationChallenge(response))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
@@ -99,12 +100,14 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
throw new InvalidOperationException($"The {nameof(TokenStorageUrl)} property must have a value if the {nameof(Storage)} property is set on this instance of {GetType().Name}.");
|
throw new InvalidOperationException($"The {nameof(TokenStorageUrl)} property must have a value if the {nameof(Storage)} property is set on this instance of {GetType().Name}.");
|
||||||
}
|
}
|
||||||
|
// System.Console.WriteLine($"IssuedTokenCredential.CreateTokenProvider: TokenStorageUrl: {TokenStorageUrl}");
|
||||||
InitialToken = Storage.RetrieveToken(TokenStorageUrl, CredentialType);
|
InitialToken = Storage.RetrieveToken(TokenStorageUrl, CredentialType);
|
||||||
}
|
}
|
||||||
|
|
||||||
IssuedTokenProvider provider = OnCreateTokenProvider(serverUrl, response);
|
IssuedTokenProvider provider = OnCreateTokenProvider(serverUrl, response);
|
||||||
if (provider != null)
|
if (provider != null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"IssuedTokenCredential.CreateTokenProvider: provider: {provider}");
|
||||||
provider.TokenStorageUrl = TokenStorageUrl;
|
provider.TokenStorageUrl = TokenStorageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +126,7 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
internal virtual string GetAuthenticationChallenge(IHttpResponse webResponse)
|
internal virtual string GetAuthenticationChallenge(IHttpResponse webResponse)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"IssuedTokenCredential.GetAuthenticationChallenge");
|
||||||
IEnumerable<String> values;
|
IEnumerable<String> values;
|
||||||
if (!webResponse.Headers.TryGetValues(Internal.HttpHeaders.WwwAuthenticate, out values))
|
if (!webResponse.Headers.TryGetValues(Internal.HttpHeaders.WwwAuthenticate, out values))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ namespace GitHub.Services.Common
|
|||||||
TaskScheduler scheduler,
|
TaskScheduler scheduler,
|
||||||
IVssCredentialPrompt credentialPrompt)
|
IVssCredentialPrompt credentialPrompt)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.ctor");
|
||||||
this.PromptType = promptType;
|
this.PromptType = promptType;
|
||||||
|
|
||||||
if (promptType == CredentialPromptType.PromptIfNeeded && scheduler == null)
|
if (promptType == CredentialPromptType.PromptIfNeeded && scheduler == null)
|
||||||
@@ -150,6 +151,7 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.get_PromptType");
|
||||||
return m_promptType;
|
return m_promptType;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
@@ -170,6 +172,7 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.get_Federated");
|
||||||
return m_federatedCredential;
|
return m_federatedCredential;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,6 +187,7 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.get_Storage");
|
||||||
return m_credentialStorage;
|
return m_credentialStorage;
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
@@ -203,6 +207,7 @@ namespace GitHub.Services.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal virtual bool TryGetValidAdalToken(IVssCredentialPrompt prompt)
|
internal virtual bool TryGetValidAdalToken(IVssCredentialPrompt prompt)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.TryGetValidAdalToken");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,6 +223,7 @@ namespace GitHub.Services.Common
|
|||||||
IHttpResponse webResponse,
|
IHttpResponse webResponse,
|
||||||
IssuedToken failedToken)
|
IssuedToken failedToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssCredential.CreateTokenProvider");
|
||||||
ArgumentUtility.CheckForNull(serverUrl, "serverUrl");
|
ArgumentUtility.CheckForNull(serverUrl, "serverUrl");
|
||||||
|
|
||||||
IssuedTokenProvider tokenProvider = null;
|
IssuedTokenProvider tokenProvider = null;
|
||||||
@@ -263,6 +269,7 @@ namespace GitHub.Services.Common
|
|||||||
Uri serverUrl,
|
Uri serverUrl,
|
||||||
out IssuedTokenProvider provider)
|
out IssuedTokenProvider provider)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.TryGetTokenProvider");
|
||||||
ArgumentUtility.CheckForNull(serverUrl, "serverUrl");
|
ArgumentUtility.CheckForNull(serverUrl, "serverUrl");
|
||||||
|
|
||||||
lock (m_thisLock)
|
lock (m_thisLock)
|
||||||
@@ -272,11 +279,13 @@ namespace GitHub.Services.Common
|
|||||||
{
|
{
|
||||||
if (m_federatedCredential != null)
|
if (m_federatedCredential != null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.TryGetTokenProvider: Using federated credential");
|
||||||
m_currentProvider = m_federatedCredential.CreateTokenProvider(serverUrl, null, null);
|
m_currentProvider = m_federatedCredential.CreateTokenProvider(serverUrl, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_currentProvider != null)
|
if (m_currentProvider != null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.TryGetTokenProvider: Issued token provider created");
|
||||||
VssHttpEventSource.Log.IssuedTokenProviderCreated(VssTraceActivity.Current, m_currentProvider);
|
VssHttpEventSource.Log.IssuedTokenProviderCreated(VssTraceActivity.Current, m_currentProvider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -294,6 +303,7 @@ namespace GitHub.Services.Common
|
|||||||
/// <returns>True if this is an token authentication redirect, false otherwise</returns>
|
/// <returns>True if this is an token authentication redirect, false otherwise</returns>
|
||||||
internal bool IsAuthenticationChallenge(IHttpResponse webResponse)
|
internal bool IsAuthenticationChallenge(IHttpResponse webResponse)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.IsAuthenticationChallenge");
|
||||||
if (webResponse == null)
|
if (webResponse == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -313,6 +323,7 @@ namespace GitHub.Services.Common
|
|||||||
Uri serviceLocation,
|
Uri serviceLocation,
|
||||||
string identityProvider)
|
string identityProvider)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.SignOut");
|
||||||
// Remove the token in the storage and the current token provider. Note that we don't
|
// Remove the token in the storage and the current token provider. Note that we don't
|
||||||
// call InvalidateToken here because we want to remove the whole token not just its value
|
// call InvalidateToken here because we want to remove the whole token not just its value
|
||||||
if ((m_currentProvider != null) && (m_currentProvider.CurrentToken != null))
|
if ((m_currentProvider != null) && (m_currentProvider.CurrentToken != null))
|
||||||
@@ -349,6 +360,7 @@ namespace GitHub.Services.Common
|
|||||||
string token,
|
string token,
|
||||||
IDictionary<string, string> attributes)
|
IDictionary<string, string> attributes)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.WriteAuthorizationToken");
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (int j = 0; j < token.Length; i++, j += 128)
|
for (int j = 0; j < token.Length; i++, j += 128)
|
||||||
{
|
{
|
||||||
@@ -360,6 +372,7 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
protected static string ReadAuthorizationToken(IDictionary<string, string> attributes)
|
protected static string ReadAuthorizationToken(IDictionary<string, string> attributes)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssCredentials.ReadAuthorizationToken");
|
||||||
string authTokenCountValue;
|
string authTokenCountValue;
|
||||||
if (attributes.TryGetValue("AuthTokenSegmentCount", out authTokenCountValue))
|
if (attributes.TryGetValue("AuthTokenSegmentCount", out authTokenCountValue))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ namespace GitHub.Services.Common
|
|||||||
VssHttpRequestSettings settings,
|
VssHttpRequestSettings settings,
|
||||||
HttpMessageHandler innerHandler)
|
HttpMessageHandler innerHandler)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.ctor");
|
||||||
this.Credentials = credentials;
|
this.Credentials = credentials;
|
||||||
this.Settings = settings;
|
this.Settings = settings;
|
||||||
this.ExpectContinue = settings.ExpectContinue;
|
this.ExpectContinue = settings.ExpectContinue;
|
||||||
@@ -122,6 +123,7 @@ namespace GitHub.Services.Common
|
|||||||
HttpRequestMessage request,
|
HttpRequestMessage request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync");
|
||||||
VssTraceActivity traceActivity = VssTraceActivity.Current;
|
VssTraceActivity traceActivity = VssTraceActivity.Current;
|
||||||
|
|
||||||
var traceInfo = VssHttpMessageHandlerTraceInfo.GetTraceInfo(request);
|
var traceInfo = VssHttpMessageHandlerTraceInfo.GetTraceInfo(request);
|
||||||
@@ -130,6 +132,7 @@ namespace GitHub.Services.Common
|
|||||||
if (!m_appliedClientCertificatesToTransportHandler &&
|
if (!m_appliedClientCertificatesToTransportHandler &&
|
||||||
request.RequestUri.Scheme == "https")
|
request.RequestUri.Scheme == "https")
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: !appliedClientCertificatesToTransportHandler");
|
||||||
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
|
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
|
||||||
if (httpClientHandler != null &&
|
if (httpClientHandler != null &&
|
||||||
this.Settings.ClientCertificateManager != null &&
|
this.Settings.ClientCertificateManager != null &&
|
||||||
@@ -144,6 +147,7 @@ namespace GitHub.Services.Common
|
|||||||
if (!m_appliedServerCertificateValidationCallbackToTransportHandler &&
|
if (!m_appliedServerCertificateValidationCallbackToTransportHandler &&
|
||||||
request.RequestUri.Scheme == "https")
|
request.RequestUri.Scheme == "https")
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: !appliedServerCertificateValidationCallbackToTransportHandler");
|
||||||
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
|
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
|
||||||
if (httpClientHandler != null &&
|
if (httpClientHandler != null &&
|
||||||
this.Settings.ServerCertificateValidationCallback != null)
|
this.Settings.ServerCertificateValidationCallback != null)
|
||||||
@@ -165,6 +169,7 @@ namespace GitHub.Services.Common
|
|||||||
IssuedTokenProvider provider;
|
IssuedTokenProvider provider;
|
||||||
if (this.Credentials.TryGetTokenProvider(request.RequestUri, out provider))
|
if (this.Credentials.TryGetTokenProvider(request.RequestUri, out provider))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: Got token provider from credentials");
|
||||||
token = provider.CurrentToken;
|
token = provider.CurrentToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +230,7 @@ namespace GitHub.Services.Common
|
|||||||
|
|
||||||
traceInfo?.TraceResponseContentTime();
|
traceInfo?.TraceResponseContentTime();
|
||||||
|
|
||||||
|
// System.Console.WriteLine($"VssHttpMessageHandler.SendAsync: Creating response wrapper");
|
||||||
responseWrapper = new HttpResponseMessageWrapper(response);
|
responseWrapper = new HttpResponseMessageWrapper(response);
|
||||||
|
|
||||||
if (!this.Credentials.IsAuthenticationChallenge(responseWrapper))
|
if (!this.Credentials.IsAuthenticationChallenge(responseWrapper))
|
||||||
@@ -232,6 +238,7 @@ namespace GitHub.Services.Common
|
|||||||
// Validate the token after it has been successfully authenticated with the server.
|
// Validate the token after it has been successfully authenticated with the server.
|
||||||
if (provider != null)
|
if (provider != null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.SendAsync: Validating token");
|
||||||
provider.ValidateToken(token, responseWrapper);
|
provider.ValidateToken(token, responseWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +250,7 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssHttpMessageHandler.SendAsync: Auth challenge. Response status code {response.StatusCode}; headers {response.Headers}");
|
||||||
// In the case of a Windows token, only apply it to the web proxy if it
|
// In the case of a Windows token, only apply it to the web proxy if it
|
||||||
// returned a 407 Proxy Authentication Required. If we didn't get this
|
// returned a 407 Proxy Authentication Required. If we didn't get this
|
||||||
// status code back, then the proxy (if there is one) is clearly working fine,
|
// status code back, then the proxy (if there is one) is clearly working fine,
|
||||||
@@ -288,6 +296,7 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now invoke the provider and await the result
|
// Now invoke the provider and await the result
|
||||||
|
// System.Console.WriteLine($"VssHttpMessageHandler.SendAsync: Calling GetTokenAsync");
|
||||||
token = await provider.GetTokenAsync(token, tokenSource.Token).ConfigureAwait(false);
|
token = await provider.GetTokenAsync(token, tokenSource.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
// I always see 0 here, but the method above could take more time so keep for now
|
// I always see 0 here, but the method above could take more time so keep for now
|
||||||
@@ -432,6 +441,7 @@ namespace GitHub.Services.Common
|
|||||||
activity != VssTraceActivity.Empty &&
|
activity != VssTraceActivity.Empty &&
|
||||||
!request.Headers.Contains(HttpHeaders.TfsSessionHeader))
|
!request.Headers.Contains(HttpHeaders.TfsSessionHeader))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssHttpMessageHandler.ApplyHeaders: Activity ID {activity.Id}");
|
||||||
request.Headers.Add(HttpHeaders.TfsSessionHeader, activity.Id.ToString("D"));
|
request.Headers.Add(HttpHeaders.TfsSessionHeader, activity.Id.ToString("D"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,13 +462,16 @@ namespace GitHub.Services.Common
|
|||||||
ICredentials credentialsToken = token as ICredentials;
|
ICredentials credentialsToken = token as ICredentials;
|
||||||
if (credentialsToken != null)
|
if (credentialsToken != null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Credentials token != null");
|
||||||
if (applyICredentialsToWebProxy)
|
if (applyICredentialsToWebProxy)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Apply credentials to web proxy");
|
||||||
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
|
HttpClientHandler httpClientHandler = m_transportHandler as HttpClientHandler;
|
||||||
|
|
||||||
if (httpClientHandler != null &&
|
if (httpClientHandler != null &&
|
||||||
httpClientHandler.Proxy != null)
|
httpClientHandler.Proxy != null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Setting proxy crednetials");
|
||||||
httpClientHandler.Proxy.Credentials = credentialsToken;
|
httpClientHandler.Proxy.Credentials = credentialsToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -467,6 +480,7 @@ namespace GitHub.Services.Common
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpMessageHandler.ApplyToken: Applying credentials to request");
|
||||||
token.ApplyTo(new HttpRequestMessageWrapper(request));
|
token.ApplyTo(new HttpRequestMessageWrapper(request));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,7 +493,8 @@ namespace GitHub.Services.Common
|
|||||||
HttpClientHandler httpClientHandler = handler as HttpClientHandler;
|
HttpClientHandler httpClientHandler = handler as HttpClientHandler;
|
||||||
if (httpClientHandler != null)
|
if (httpClientHandler != null)
|
||||||
{
|
{
|
||||||
httpClientHandler.AllowAutoRedirect = settings.AllowAutoRedirect;
|
// System.Console.WriteLine($"VssHttpMessageHandler.ApplySettings: Default credentials = {defaultCredentials} AllowAutoRedirect = {settings.AllowAutoRedirect}");
|
||||||
|
httpClientHandler.AllowAutoRedirect = true; //settings.AllowAutoRedirect;
|
||||||
httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
httpClientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
||||||
//Setting httpClientHandler.UseDefaultCredentials to false in .Net Core, clears httpClientHandler.Credentials if
|
//Setting httpClientHandler.UseDefaultCredentials to false in .Net Core, clears httpClientHandler.Credentials if
|
||||||
//credentials is already set to defaultcredentials. Therefore httpClientHandler.Credentials must be
|
//credentials is already set to defaultcredentials. Therefore httpClientHandler.Credentials must be
|
||||||
@@ -550,6 +565,7 @@ namespace GitHub.Services.Common
|
|||||||
Uri uri,
|
Uri uri,
|
||||||
String authType)
|
String authType)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"CredentialWrapper.GetCredential: InnerCredentials = {InnerCredentials}");
|
||||||
return InnerCredentials != null ? InnerCredentials.GetCredential(uri, authType) : null;
|
return InnerCredentials != null ? InnerCredentials.GetCredential(uri, authType) : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ using System.Net.Http.Headers;
|
|||||||
using System.Net.Http.Formatting;
|
using System.Net.Http.Formatting;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.Services.Common;
|
using GitHub.Services.Common;
|
||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
|
|
||||||
@@ -378,6 +379,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
/// <param name="requestId"></param>
|
/// <param name="requestId"></param>
|
||||||
/// <param name="lockToken"></param>
|
/// <param name="lockToken"></param>
|
||||||
/// <param name="request"></param>
|
/// <param name="request"></param>
|
||||||
|
/// <param name="targetHostId"></param>
|
||||||
/// <param name="userState"></param>
|
/// <param name="userState"></param>
|
||||||
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
@@ -386,6 +388,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
long requestId,
|
long requestId,
|
||||||
Guid lockToken,
|
Guid lockToken,
|
||||||
TaskAgentJobRequest request,
|
TaskAgentJobRequest request,
|
||||||
|
Guid targetHostId,
|
||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -396,6 +399,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
|
|
||||||
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||||
queryParams.Add("lockToken", lockToken.ToString());
|
queryParams.Add("lockToken", lockToken.ToString());
|
||||||
|
queryParams.Add("targetHostId", targetHostId.ToString());
|
||||||
|
|
||||||
return SendAsync<TaskAgentJobRequest>(
|
return SendAsync<TaskAgentJobRequest>(
|
||||||
httpMethod,
|
httpMethod,
|
||||||
@@ -703,6 +707,47 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
cancellationToken: cancellationToken);
|
cancellationToken: cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// [Preview API]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="scopeId"></param>
|
||||||
|
/// <param name="planType"></param>
|
||||||
|
/// <param name="planGroup"></param>
|
||||||
|
/// <param name="planId"></param>
|
||||||
|
/// <param name="instanceRefsJson"></param>
|
||||||
|
/// <param name="userState"></param>
|
||||||
|
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
|
||||||
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||||
|
public virtual Task<Pipelines.AgentJobRequestMessage> GetJobMessageAsync(
|
||||||
|
Guid scopeId,
|
||||||
|
Guid hostId,
|
||||||
|
string planType,
|
||||||
|
string planGroup,
|
||||||
|
Guid planId,
|
||||||
|
string instanceRefsJson,
|
||||||
|
object userState = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
HttpMethod httpMethod = new HttpMethod("GET");
|
||||||
|
Guid locationId = new Guid("25adab70-1379-4186-be8e-b643061ebe3a");
|
||||||
|
|
||||||
|
List<KeyValuePair<string, string>> queryParams = new List<KeyValuePair<string, string>>();
|
||||||
|
queryParams.Add("scopeId", scopeId.ToString());
|
||||||
|
queryParams.Add("hostId", hostId.ToString());
|
||||||
|
queryParams.Add("planType", planType);
|
||||||
|
queryParams.Add("planGroup", planGroup);
|
||||||
|
queryParams.Add("planId", planId.ToString());
|
||||||
|
queryParams.Add("instanceRefsJson", instanceRefsJson);
|
||||||
|
|
||||||
|
return SendAsync<Pipelines.AgentJobRequestMessage>(
|
||||||
|
httpMethod,
|
||||||
|
locationId,
|
||||||
|
version: new ApiResourceVersion(6.0, 1),
|
||||||
|
queryParameters: queryParams,
|
||||||
|
userState: userState,
|
||||||
|
cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// [Preview API]
|
/// [Preview API]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -717,6 +762,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
object userState = null,
|
object userState = null,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("TaskAgentHttpClientBase.CreateAgentSessionAsync");
|
||||||
HttpMethod httpMethod = new HttpMethod("POST");
|
HttpMethod httpMethod = new HttpMethod("POST");
|
||||||
Guid locationId = new Guid("134e239e-2df3-4794-a6f6-24f1f19ec8dc");
|
Guid locationId = new Guid("134e239e-2df3-4794-a6f6-24f1f19ec8dc");
|
||||||
object routeValues = new { poolId = poolId };
|
object routeValues = new { poolId = poolId };
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
public static class JobRequestMessageTypes
|
public static class JobRequestMessageTypes
|
||||||
{
|
{
|
||||||
public const String PipelineAgentJobRequest = "PipelineAgentJobRequest";
|
public const String PipelineAgentJobRequest = "PipelineAgentJobRequest";
|
||||||
|
public const String RunnerJobRequest = "RunnerJobRequest";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
Guid lockToken,
|
Guid lockToken,
|
||||||
DateTime finishTime,
|
DateTime finishTime,
|
||||||
TaskResult result,
|
TaskResult result,
|
||||||
|
Guid targetHostId,
|
||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
@@ -74,7 +75,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
Result = result,
|
Result = result,
|
||||||
};
|
};
|
||||||
|
|
||||||
return UpdateAgentRequestAsync(poolId, requestId, lockToken, request, userState, cancellationToken);
|
return UpdateAgentRequestAsync(poolId, requestId, lockToken, request, targetHostId, userState, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<TaskAgent>> GetAgentsAsync(
|
public Task<List<TaskAgent>> GetAgentsAsync(
|
||||||
@@ -152,6 +153,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
CancellationToken cancellationToken = default(CancellationToken),
|
CancellationToken cancellationToken = default(CancellationToken),
|
||||||
Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null)
|
Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("TaskAgentHttpClient.SendAsync 1");
|
||||||
return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, processResponse);
|
return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, processResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +172,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
||||||
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("TaskAgentHttpClient.SendAsync 2");
|
||||||
return await SendAsync<T>(requestMessage, userState, cancellationToken, processResponse).ConfigureAwait(false);
|
return await SendAsync<T>(requestMessage, userState, cancellationToken, processResponse).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,6 +183,7 @@ namespace GitHub.DistributedTask.WebApi
|
|||||||
CancellationToken cancellationToken = default(CancellationToken),
|
CancellationToken cancellationToken = default(CancellationToken),
|
||||||
Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null)
|
Func<HttpResponseMessage, CancellationToken, Task<T>> processResponse = null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("TaskAgentHttpClient.SendAsync 3");
|
||||||
if (processResponse == null)
|
if (processResponse == null)
|
||||||
{
|
{
|
||||||
processResponse = ReadContentAsAsync<T>;
|
processResponse = ReadContentAsAsync<T>;
|
||||||
|
|||||||
@@ -801,6 +801,7 @@ namespace GitHub.Services.WebApi.Location
|
|||||||
|
|
||||||
private async Task<ConnectionData> GetConnectionDataAsync(ConnectOptions connectOptions, int lastChangeId, CancellationToken cancellationToken)
|
private async Task<ConnectionData> GetConnectionDataAsync(ConnectOptions connectOptions, int lastChangeId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("ServerDataProvider.GetConnectionDataAsync");
|
||||||
int timeoutRetries = 1;
|
int timeoutRetries = 1;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ namespace GitHub.Services.OAuth
|
|||||||
|
|
||||||
internal override void ApplyTo(IHttpRequest request)
|
internal override void ApplyTo(IHttpRequest request)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthAccessToken.ApplyTo: Bearer {m_value}");
|
||||||
request.Headers.SetValue(Common.Internal.HttpHeaders.Authorization, $"Bearer {m_value}");
|
request.Headers.SetValue(Common.Internal.HttpHeaders.Authorization, $"Bearer {m_value}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ namespace GitHub.Services.OAuth
|
|||||||
Uri serverUrl,
|
Uri serverUrl,
|
||||||
IHttpResponse response)
|
IHttpResponse response)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthAccessTokenCredential.OnCreateTokenProvider");
|
||||||
return new VssOAuthAccessTokenProvider(this, serverUrl, null);
|
return new VssOAuthAccessTokenProvider(this, serverUrl, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ namespace GitHub.Services.OAuth
|
|||||||
Uri signInUrl)
|
Uri signInUrl)
|
||||||
: base(credential, serverUrl, signInUrl)
|
: base(credential, serverUrl, signInUrl)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthAccessTokenProvider.ctor");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Boolean GetTokenIsInteractive
|
public override Boolean GetTokenIsInteractive
|
||||||
|
|||||||
@@ -103,17 +103,23 @@ namespace GitHub.Services.OAuth
|
|||||||
/// <returns>True if the web response indicates an authorization challenge; otherwise, false</returns>
|
/// <returns>True if the web response indicates an authorization challenge; otherwise, false</returns>
|
||||||
public override Boolean IsAuthenticationChallenge(IHttpResponse webResponse)
|
public override Boolean IsAuthenticationChallenge(IHttpResponse webResponse)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge");
|
||||||
if (webResponse == null)
|
if (webResponse == null)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: webResponse is null");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (webResponse.StatusCode == HttpStatusCode.Found ||
|
if (webResponse.StatusCode == HttpStatusCode.Found ||
|
||||||
webResponse.StatusCode == HttpStatusCode.Unauthorized)
|
webResponse.StatusCode == HttpStatusCode.Unauthorized)
|
||||||
{
|
{
|
||||||
return webResponse.Headers.GetValues(Common.Internal.HttpHeaders.WwwAuthenticate).Any(x => x.IndexOf("Bearer", StringComparison.OrdinalIgnoreCase) >= 0);
|
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: found or unauthorized");
|
||||||
|
var result = webResponse.Headers.GetValues(Common.Internal.HttpHeaders.WwwAuthenticate).Any(x => x.IndexOf("Bearer", StringComparison.OrdinalIgnoreCase) >= 0);
|
||||||
|
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: {result}");
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// System.Console.WriteLine($"VssOAuthCredential.IsAuthenticationChallenge: false");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +127,7 @@ namespace GitHub.Services.OAuth
|
|||||||
Uri serverUrl,
|
Uri serverUrl,
|
||||||
IHttpResponse response)
|
IHttpResponse response)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthCredential.OnCreateTokenProvider");
|
||||||
return new VssOAuthTokenProvider(this, serverUrl);
|
return new VssOAuthTokenProvider(this, serverUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ namespace GitHub.Services.OAuth
|
|||||||
VssOAuthTokenParameters tokenParameters = null,
|
VssOAuthTokenParameters tokenParameters = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// todo: qqq
|
||||||
VssTraceActivity traceActivity = VssTraceActivity.Current;
|
VssTraceActivity traceActivity = VssTraceActivity.Current;
|
||||||
using (HttpClient client = new HttpClient(CreateMessageHandler(this.AuthorizationUrl)))
|
using (HttpClient client = new HttpClient(CreateMessageHandler(this.AuthorizationUrl)))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace GitHub.Services.OAuth
|
|||||||
VssOAuthTokenParameters tokenParameters)
|
VssOAuthTokenParameters tokenParameters)
|
||||||
: base(credential, serverUrl, authorizationUrl)
|
: base(credential, serverUrl, authorizationUrl)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.ctor");
|
||||||
m_grant = grant;
|
m_grant = grant;
|
||||||
m_tokenParameters = tokenParameters;
|
m_tokenParameters = tokenParameters;
|
||||||
m_clientCredential = clientCrential;
|
m_clientCredential = clientCrential;
|
||||||
@@ -59,6 +60,7 @@ namespace GitHub.Services.OAuth
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.get_Grant");
|
||||||
return m_grant;
|
return m_grant;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,6 +72,7 @@ namespace GitHub.Services.OAuth
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.get_ClientCredential");
|
||||||
return m_clientCredential;
|
return m_clientCredential;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,6 +84,7 @@ namespace GitHub.Services.OAuth
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.get_TokenParameters");
|
||||||
return m_tokenParameters;
|
return m_tokenParameters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,6 +96,7 @@ namespace GitHub.Services.OAuth
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.get_GetTokenIsInteractive");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,6 +105,7 @@ namespace GitHub.Services.OAuth
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.get_AuthenticationParameter");
|
||||||
if (this.ClientCredential == null)
|
if (this.ClientCredential == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -115,12 +121,14 @@ namespace GitHub.Services.OAuth
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.get_AuthenticationScheme");
|
||||||
return "Bearer";
|
return "Bearer";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> ValidateCredentialAsync(CancellationToken cancellationToken)
|
public async Task<string> ValidateCredentialAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.ValidateCredentialAsync: Calling VssOAuthTokenHttpClient.GetTokenAsync");
|
||||||
var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl);
|
var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl);
|
||||||
var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken);
|
var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken);
|
||||||
|
|
||||||
@@ -139,6 +147,7 @@ namespace GitHub.Services.OAuth
|
|||||||
IssuedToken failedToken,
|
IssuedToken failedToken,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.OnGetTokenAsync");
|
||||||
if (this.SignInUrl == null ||
|
if (this.SignInUrl == null ||
|
||||||
this.Grant == null ||
|
this.Grant == null ||
|
||||||
this.ClientCredential == null)
|
this.ClientCredential == null)
|
||||||
@@ -151,6 +160,7 @@ namespace GitHub.Services.OAuth
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl);
|
var tokenHttpClient = new VssOAuthTokenHttpClient(this.SignInUrl);
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.OnGetTokenAsync: Calling VssOAuthTokenHttpClient.GetTokenAsync; sign-in url {this.SignInUrl.AbsoluteUri}");
|
||||||
var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken).ConfigureAwait(false);
|
var tokenResponse = await tokenHttpClient.GetTokenAsync(this.Grant, this.ClientCredential, this.TokenParameters, cancellationToken).ConfigureAwait(false);
|
||||||
if (!String.IsNullOrEmpty(tokenResponse.AccessToken))
|
if (!String.IsNullOrEmpty(tokenResponse.AccessToken))
|
||||||
{
|
{
|
||||||
@@ -197,6 +207,7 @@ namespace GitHub.Services.OAuth
|
|||||||
|
|
||||||
protected virtual IssuedToken CreateIssuedToken(VssOAuthTokenResponse tokenResponse)
|
protected virtual IssuedToken CreateIssuedToken(VssOAuthTokenResponse tokenResponse)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssOAuthTokenProvider.CreateIssuedToken");
|
||||||
if (tokenResponse.ExpiresIn > 0)
|
if (tokenResponse.ExpiresIn > 0)
|
||||||
{
|
{
|
||||||
return new VssOAuthAccessToken(tokenResponse.AccessToken, DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn));
|
return new VssOAuthAccessToken(tokenResponse.AccessToken, DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn));
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ namespace GitHub.Services.WebApi
|
|||||||
IDictionary<String, String> parameters,
|
IDictionary<String, String> parameters,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssConnection.ConnectAsync");
|
||||||
CheckForDisposed();
|
CheckForDisposed();
|
||||||
// Set the connectMode on the credential's FederatedPrompt
|
// Set the connectMode on the credential's FederatedPrompt
|
||||||
if (Credentials.Federated != null && Credentials.Federated.Prompt != null)
|
if (Credentials.Federated != null && Credentials.Federated.Prompt != null)
|
||||||
|
|||||||
@@ -390,6 +390,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 1");
|
||||||
return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken);
|
return SendAsync<T>(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,6 +405,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 2");
|
||||||
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
||||||
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -422,6 +424,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 3");
|
||||||
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
||||||
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, additionalHeaders, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -455,6 +458,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 4");
|
||||||
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
||||||
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -473,6 +477,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 5");
|
||||||
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
using (VssTraceActivity.GetOrCreate().EnterCorrelationScope())
|
||||||
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
using (HttpRequestMessage requestMessage = await CreateRequestMessageAsync(method, locationId, routeValues, version, content, queryParameters, userState, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
@@ -501,6 +506,7 @@ namespace GitHub.Services.WebApi
|
|||||||
CancellationToken cancellationToken = default(CancellationToken),
|
CancellationToken cancellationToken = default(CancellationToken),
|
||||||
String mediaType = c_jsonMediaType)
|
String mediaType = c_jsonMediaType)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 1");
|
||||||
return CreateRequestMessageAsync(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, mediaType);
|
return CreateRequestMessageAsync(method, null, locationId, routeValues, version, content, queryParameters, userState, cancellationToken, mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,6 +532,7 @@ namespace GitHub.Services.WebApi
|
|||||||
CancellationToken cancellationToken = default(CancellationToken),
|
CancellationToken cancellationToken = default(CancellationToken),
|
||||||
String mediaType = c_jsonMediaType)
|
String mediaType = c_jsonMediaType)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 2");
|
||||||
// Lookup the location
|
// Lookup the location
|
||||||
ApiResourceLocation location = await GetResourceLocationAsync(locationId, userState, cancellationToken).ConfigureAwait(false);
|
ApiResourceLocation location = await GetResourceLocationAsync(locationId, userState, cancellationToken).ConfigureAwait(false);
|
||||||
if (location == null)
|
if (location == null)
|
||||||
@@ -555,6 +562,7 @@ namespace GitHub.Services.WebApi
|
|||||||
IEnumerable<KeyValuePair<String, String>> queryParameters = null,
|
IEnumerable<KeyValuePair<String, String>> queryParameters = null,
|
||||||
String mediaType = c_jsonMediaType)
|
String mediaType = c_jsonMediaType)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 3");
|
||||||
return CreateRequestMessage(method, null, location, routeValues, version, content, queryParameters, mediaType);
|
return CreateRequestMessage(method, null, location, routeValues, version, content, queryParameters, mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,6 +586,7 @@ namespace GitHub.Services.WebApi
|
|||||||
IEnumerable<KeyValuePair<String, String>> queryParameters = null,
|
IEnumerable<KeyValuePair<String, String>> queryParameters = null,
|
||||||
String mediaType = c_jsonMediaType)
|
String mediaType = c_jsonMediaType)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.CreateRequestMessageAsync 4");
|
||||||
CheckForDisposed();
|
CheckForDisposed();
|
||||||
// Negotiate the request version to send
|
// Negotiate the request version to send
|
||||||
ApiResourceVersion requestVersion = NegotiateRequestVersion(location, version);
|
ApiResourceVersion requestVersion = NegotiateRequestVersion(location, version);
|
||||||
@@ -749,12 +758,14 @@ namespace GitHub.Services.WebApi
|
|||||||
//from deadlocking...
|
//from deadlocking...
|
||||||
using (HttpResponseMessage response = await this.SendAsync(message, userState, cancellationToken).ConfigureAwait(false))
|
using (HttpResponseMessage response = await this.SendAsync(message, userState, cancellationToken).ConfigureAwait(false))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 6");
|
||||||
return await ReadContentAsAsync<T>(response, cancellationToken).ConfigureAwait(false);
|
return await ReadContentAsAsync<T>(response, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<T> ReadContentAsAsync<T>(HttpResponseMessage response, CancellationToken cancellationToken = default(CancellationToken))
|
protected async Task<T> ReadContentAsAsync<T>(HttpResponseMessage response, CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssHttpClientBase.ReadContentAsAsync {response.Headers}");
|
||||||
CheckForDisposed();
|
CheckForDisposed();
|
||||||
Boolean isJson = IsJsonResponse(response);
|
Boolean isJson = IsJsonResponse(response);
|
||||||
bool mismatchContentType = false;
|
bool mismatchContentType = false;
|
||||||
@@ -766,17 +777,20 @@ namespace GitHub.Services.WebApi
|
|||||||
!typeof(Byte[]).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) &&
|
!typeof(Byte[]).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()) &&
|
||||||
!typeof(JObject).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()))
|
!typeof(JObject).GetTypeInfo().IsAssignableFrom(typeof(T).GetTypeInfo()))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.ReadContentAsAsync: isJson 1");
|
||||||
// expect it to come back wrapped, if it isn't it is a bug!
|
// expect it to come back wrapped, if it isn't it is a bug!
|
||||||
var wrapper = await ReadJsonContentAsync<VssJsonCollectionWrapper<T>>(response, cancellationToken).ConfigureAwait(false);
|
var wrapper = await ReadJsonContentAsync<VssJsonCollectionWrapper<T>>(response, cancellationToken).ConfigureAwait(false);
|
||||||
return wrapper.Value;
|
return wrapper.Value;
|
||||||
}
|
}
|
||||||
else if (isJson)
|
else if (isJson)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.ReadContentAsAsync: isJson 2");
|
||||||
return await ReadJsonContentAsync<T>(response, cancellationToken).ConfigureAwait(false);
|
return await ReadJsonContentAsync<T>(response, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (JsonReaderException)
|
catch (JsonReaderException)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.ReadContentAsAsync: mismatchContentType");
|
||||||
// We thought the content was JSON but failed to parse.
|
// We thought the content was JSON but failed to parse.
|
||||||
// In this case, do nothing and utilize the HandleUnknownContentType call below
|
// In this case, do nothing and utilize the HandleUnknownContentType call below
|
||||||
mismatchContentType = true;
|
mismatchContentType = true;
|
||||||
@@ -802,6 +816,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 7");
|
||||||
// the default in httpClient for HttpCompletionOption is ResponseContentRead so that is what we do here
|
// the default in httpClient for HttpCompletionOption is ResponseContentRead so that is what we do here
|
||||||
return this.SendAsync(
|
return this.SendAsync(
|
||||||
message,
|
message,
|
||||||
@@ -816,6 +831,7 @@ namespace GitHub.Services.WebApi
|
|||||||
Object userState = null,
|
Object userState = null,
|
||||||
CancellationToken cancellationToken = default(CancellationToken))
|
CancellationToken cancellationToken = default(CancellationToken))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.SendAsync 8");
|
||||||
CheckForDisposed();
|
CheckForDisposed();
|
||||||
if (message.Headers.UserAgent != null)
|
if (message.Headers.UserAgent != null)
|
||||||
{
|
{
|
||||||
@@ -851,6 +867,7 @@ namespace GitHub.Services.WebApi
|
|||||||
//ConfigureAwait(false) enables the continuation to be run outside
|
//ConfigureAwait(false) enables the continuation to be run outside
|
||||||
//any captured SyncronizationContext (such as ASP.NET's) which keeps things
|
//any captured SyncronizationContext (such as ASP.NET's) which keeps things
|
||||||
//from deadlocking...
|
//from deadlocking...
|
||||||
|
// System.Console.WriteLine($"VssHttpClientBase.SendAsync 8: Calling Client.SendAsync {message}");
|
||||||
HttpResponseMessage response = await Client.SendAsync(message, completionOption, cancellationToken).ConfigureAwait(false);
|
HttpResponseMessage response = await Client.SendAsync(message, completionOption, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// Inject delay or failure for testing
|
// Inject delay or failure for testing
|
||||||
@@ -868,6 +885,7 @@ namespace GitHub.Services.WebApi
|
|||||||
[Obsolete("Use VssHttpClientBase.HandleResponseAsync instead")]
|
[Obsolete("Use VssHttpClientBase.HandleResponseAsync instead")]
|
||||||
protected virtual void HandleResponse(HttpResponseMessage response)
|
protected virtual void HandleResponse(HttpResponseMessage response)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.HandleResponse 1");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -875,6 +893,7 @@ namespace GitHub.Services.WebApi
|
|||||||
HttpResponseMessage response,
|
HttpResponseMessage response,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine($"VssHttpClientBase.HandleResponse 2 status code {response.StatusCode} headers {response.Headers}");
|
||||||
response.Trace();
|
response.Trace();
|
||||||
VssHttpEventSource.Log.HttpRequestStop(VssTraceActivity.Current, response);
|
VssHttpEventSource.Log.HttpRequestStop(VssTraceActivity.Current, response);
|
||||||
|
|
||||||
@@ -886,6 +905,7 @@ namespace GitHub.Services.WebApi
|
|||||||
}
|
}
|
||||||
else if (ShouldThrowError(response))
|
else if (ShouldThrowError(response))
|
||||||
{
|
{
|
||||||
|
// System.Console.WriteLine("VssHttpClientBase.HandleResponse: Should throw error");
|
||||||
Exception exToThrow = null;
|
Exception exToThrow = null;
|
||||||
if (IsJsonResponse(response))
|
if (IsJsonResponse(response))
|
||||||
{
|
{
|
||||||
@@ -909,6 +929,7 @@ namespace GitHub.Services.WebApi
|
|||||||
{
|
{
|
||||||
message = response.ReasonPhrase;
|
message = response.ReasonPhrase;
|
||||||
}
|
}
|
||||||
|
// System.Console.WriteLine($"VssHttpClientBase.HandleResponse: Exception message {message}");
|
||||||
exToThrow = new VssServiceResponseException(response.StatusCode, message, exToThrow);
|
exToThrow = new VssServiceResponseException(response.StatusCode, message, exToThrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -708,85 +708,33 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Fact]
|
||||||
[InlineData("configure", "once")]
|
|
||||||
[InlineData("remove", "disableupdate")]
|
|
||||||
[InlineData("remove", "ephemeral")]
|
|
||||||
[InlineData("remove", "once")]
|
|
||||||
[InlineData("remove", "replace")]
|
|
||||||
[InlineData("remove", "runasservice")]
|
|
||||||
[InlineData("remove", "unattended")]
|
|
||||||
[InlineData("run", "disableupdate")]
|
|
||||||
[InlineData("run", "ephemeral")]
|
|
||||||
[InlineData("run", "replace")]
|
|
||||||
[InlineData("run", "runasservice")]
|
|
||||||
[InlineData("run", "unattended")]
|
|
||||||
[InlineData("warmup", "disableupdate")]
|
|
||||||
[InlineData("warmup", "ephemeral")]
|
|
||||||
[InlineData("warmup", "once")]
|
|
||||||
[InlineData("warmup", "replace")]
|
|
||||||
[InlineData("warmup", "runasservice")]
|
|
||||||
[InlineData("warmup", "unattended")]
|
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", nameof(CommandSettings))]
|
[Trait("Category", nameof(CommandSettings))]
|
||||||
public void ValidateInvalidFlagCommandCombination(string validCommand, string flag)
|
public void ValidateFlags()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
// Arrange.
|
// Arrange.
|
||||||
var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{flag}" });
|
var command = new CommandSettings(hc, args: new string[] { "--badflag" });
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Contains(flag, command.Validate());
|
Assert.Contains("badflag", command.Validate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
[Fact]
|
||||||
[InlineData("remove", "auth", "bar arg value")]
|
|
||||||
[InlineData("remove", "labels", "bar arg value")]
|
|
||||||
[InlineData("remove", "monitorsocketaddress", "bar arg value")]
|
|
||||||
[InlineData("remove", "name", "bar arg value")]
|
|
||||||
[InlineData("remove", "runnergroup", "bar arg value")]
|
|
||||||
[InlineData("remove", "url", "bar arg value")]
|
|
||||||
[InlineData("remove", "username", "bar arg value")]
|
|
||||||
[InlineData("remove", "windowslogonaccount", "bar arg value")]
|
|
||||||
[InlineData("remove", "windowslogonpassword", "bar arg value")]
|
|
||||||
[InlineData("remove", "work", "bar arg value")]
|
|
||||||
[InlineData("run", "auth", "bad arg value")]
|
|
||||||
[InlineData("run", "labels", "bad arg value")]
|
|
||||||
[InlineData("run", "monitorsocketaddress", "bad arg value")]
|
|
||||||
[InlineData("run", "name", "bad arg value")]
|
|
||||||
[InlineData("run", "pat", "bad arg value")]
|
|
||||||
[InlineData("run", "runnergroup", "bad arg value")]
|
|
||||||
[InlineData("run", "token", "bad arg value")]
|
|
||||||
[InlineData("run", "url", "bad arg value")]
|
|
||||||
[InlineData("run", "username", "bad arg value")]
|
|
||||||
[InlineData("run", "windowslogonaccount", "bad arg value")]
|
|
||||||
[InlineData("run", "windowslogonpassword", "bad arg value")]
|
|
||||||
[InlineData("run", "work", "bad arg value")]
|
|
||||||
[InlineData("warmup", "auth", "bad arg value")]
|
|
||||||
[InlineData("warmup", "labels", "bad arg value")]
|
|
||||||
[InlineData("warmup", "monitorsocketaddress", "bad arg value")]
|
|
||||||
[InlineData("warmup", "name", "bad arg value")]
|
|
||||||
[InlineData("warmup", "pat", "bad arg value")]
|
|
||||||
[InlineData("warmup", "runnergroup", "bad arg value")]
|
|
||||||
[InlineData("warmup", "token", "bad arg value")]
|
|
||||||
[InlineData("warmup", "url", "bad arg value")]
|
|
||||||
[InlineData("warmup", "username", "bad arg value")]
|
|
||||||
[InlineData("warmup", "windowslogonaccount", "bad arg value")]
|
|
||||||
[InlineData("warmup", "windowslogonpassword", "bad arg value")]
|
|
||||||
[InlineData("warmup", "work", "bad arg value")]
|
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", nameof(CommandSettings))]
|
[Trait("Category", nameof(CommandSettings))]
|
||||||
public void ValidateInvalidArgCommandCombination(string validCommand, string arg, string argValue)
|
public void ValidateArgs()
|
||||||
{
|
{
|
||||||
using (TestHostContext hc = CreateTestContext())
|
using (TestHostContext hc = CreateTestContext())
|
||||||
{
|
{
|
||||||
// Arrange.
|
// Arrange.
|
||||||
var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{arg}", argValue });
|
var command = new CommandSettings(hc, args: new string[] { "--badargname", "bad arg value" });
|
||||||
|
|
||||||
// Assert.
|
// Assert.
|
||||||
Assert.Contains(arg, command.Validate());
|
Assert.Contains("badargname", command.Validate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,73 +758,6 @@ namespace GitHub.Runner.Common.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("configure", "help")]
|
|
||||||
[InlineData("configure", "version")]
|
|
||||||
[InlineData("configure", "commit")]
|
|
||||||
[InlineData("configure", "check")]
|
|
||||||
[InlineData("configure", "disableupdate")]
|
|
||||||
[InlineData("configure", "ephemeral")]
|
|
||||||
[InlineData("configure", "replace")]
|
|
||||||
[InlineData("configure", "runasservice")]
|
|
||||||
[InlineData("configure", "unattended")]
|
|
||||||
[InlineData("remove", "help")]
|
|
||||||
[InlineData("remove", "version")]
|
|
||||||
[InlineData("remove", "commit")]
|
|
||||||
[InlineData("remove", "check")]
|
|
||||||
[InlineData("run", "help")]
|
|
||||||
[InlineData("run", "version")]
|
|
||||||
[InlineData("run", "commit")]
|
|
||||||
[InlineData("run", "check")]
|
|
||||||
[InlineData("run", "once")]
|
|
||||||
[InlineData("warmup", "help")]
|
|
||||||
[InlineData("warmup", "version")]
|
|
||||||
[InlineData("warmup", "commit")]
|
|
||||||
[InlineData("warmup", "check")]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", nameof(CommandSettings))]
|
|
||||||
public void ValidateGoodFlagCommandCombination(string validCommand, string flag)
|
|
||||||
{
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
// Arrange.
|
|
||||||
var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{flag}" });
|
|
||||||
|
|
||||||
// Assert.
|
|
||||||
Assert.True(command.Validate().Count == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[Theory]
|
|
||||||
[InlineData("configure", "auth", "good arg value")]
|
|
||||||
[InlineData("configure", "labels", "good arg value")]
|
|
||||||
[InlineData("configure", "monitorsocketaddress", "good arg value")]
|
|
||||||
[InlineData("configure", "name", "good arg value")]
|
|
||||||
[InlineData("configure", "pat", "good arg value")]
|
|
||||||
[InlineData("configure", "runnergroup", "good arg value")]
|
|
||||||
[InlineData("configure", "token", "good arg value")]
|
|
||||||
[InlineData("configure", "url", "good arg value")]
|
|
||||||
[InlineData("configure", "username", "good arg value")]
|
|
||||||
[InlineData("configure", "windowslogonaccount", "good arg value")]
|
|
||||||
[InlineData("configure", "windowslogonpassword", "good arg value")]
|
|
||||||
[InlineData("configure", "work", "good arg value")]
|
|
||||||
[InlineData("remove", "token", "good arg value")]
|
|
||||||
[InlineData("remove", "pat", "good arg value")]
|
|
||||||
[InlineData("run", "startuptype", "good arg value")]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", nameof(CommandSettings))]
|
|
||||||
public void ValidateGoodArgCommandCombination(string validCommand, string arg, string argValue)
|
|
||||||
{
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
// Arrange.
|
|
||||||
var command = new CommandSettings(hc, args: new string[] { validCommand, $"--{arg}", argValue });
|
|
||||||
|
|
||||||
// Assert.
|
|
||||||
Assert.True(command.Validate().Count == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
|
private TestHostContext CreateTestContext([CallerMemberName] string testName = "")
|
||||||
{
|
{
|
||||||
TestHostContext hc = new TestHostContext(this, testName);
|
TestHostContext hc = new TestHostContext(this, testName);
|
||||||
|
|||||||
@@ -6,8 +6,6 @@ using System.Threading;
|
|||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using GitHub.Runner.Worker.Container;
|
|
||||||
using GitHub.Runner.Worker.Handlers;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||||
@@ -726,149 +724,5 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
|
|
||||||
return hc;
|
return hc;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void GetExpressionValues_ContainerStepHost()
|
|
||||||
{
|
|
||||||
using (TestHostContext hc = CreateTestContext())
|
|
||||||
{
|
|
||||||
const string source = "/home/username/Projects/work/runner/_layout";
|
|
||||||
var containerInfo = new ContainerInfo();
|
|
||||||
containerInfo.ContainerId = "test";
|
|
||||||
|
|
||||||
containerInfo.AddPathTranslateMapping($"{source}/_work", "/__w");
|
|
||||||
containerInfo.AddPathTranslateMapping($"{source}/_temp", "/__t");
|
|
||||||
containerInfo.AddPathTranslateMapping($"{source}/externals", "/__e");
|
|
||||||
|
|
||||||
containerInfo.AddPathTranslateMapping($"{source}/_work/_temp/_github_home", "/github/home");
|
|
||||||
containerInfo.AddPathTranslateMapping($"{source}/_work/_temp/_github_workflow", "/github/workflow");
|
|
||||||
|
|
||||||
foreach (var v in new List<string>() {
|
|
||||||
$"{source}/_work",
|
|
||||||
$"{source}/externals",
|
|
||||||
$"{source}/_work/_temp",
|
|
||||||
$"{source}/_work/_actions",
|
|
||||||
$"{source}/_work/_tool",
|
|
||||||
})
|
|
||||||
{
|
|
||||||
containerInfo.MountVolumes.Add(new MountVolume(v, containerInfo.TranslateToContainerPath(v)));
|
|
||||||
};
|
|
||||||
|
|
||||||
var stepHost = new ContainerStepHost();
|
|
||||||
stepHost.Container = containerInfo;
|
|
||||||
|
|
||||||
var ec = new Runner.Worker.ExecutionContext();
|
|
||||||
ec.Initialize(hc);
|
|
||||||
|
|
||||||
var inputGithubContext = new GitHubContext();
|
|
||||||
var inputeRunnerContext = new RunnerContext();
|
|
||||||
|
|
||||||
// string context data
|
|
||||||
inputGithubContext["action_path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_actions/owner/composite/main");
|
|
||||||
inputGithubContext["action"] = new StringContextData("__owner_composite");
|
|
||||||
inputGithubContext["api_url"] = new StringContextData("https://api.github.com/custom/path");
|
|
||||||
inputGithubContext["env"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_runner_file_commands/set_env_265698aa-7f38-40f5-9316-5c01a3153672");
|
|
||||||
inputGithubContext["path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_runner_file_commands/add_path_265698aa-7f38-40f5-9316-5c01a3153672");
|
|
||||||
inputGithubContext["event_path"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp/_github_workflow/event.json");
|
|
||||||
inputGithubContext["repository"] = new StringContextData("owner/repo-name");
|
|
||||||
inputGithubContext["run_id"] = new StringContextData("2033211332");
|
|
||||||
inputGithubContext["workflow"] = new StringContextData("Name of Workflow");
|
|
||||||
inputGithubContext["workspace"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/step-order/step-order");
|
|
||||||
inputeRunnerContext["temp"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_temp");
|
|
||||||
inputeRunnerContext["tool_cache"] = new StringContextData("/home/username/Projects/work/runner/_layout/_work/_tool");
|
|
||||||
|
|
||||||
// dictionary context data
|
|
||||||
var githubEvent = new DictionaryContextData();
|
|
||||||
githubEvent["inputs"] = null;
|
|
||||||
githubEvent["ref"] = new StringContextData("refs/heads/main");
|
|
||||||
githubEvent["repository"] = new DictionaryContextData();
|
|
||||||
githubEvent["sender"] = new DictionaryContextData();
|
|
||||||
githubEvent["workflow"] = new StringContextData(".github/workflows/composite_step_host_translate.yaml");
|
|
||||||
|
|
||||||
inputGithubContext["event"] = githubEvent;
|
|
||||||
|
|
||||||
ec.ExpressionValues["github"] = inputGithubContext;
|
|
||||||
ec.ExpressionValues["runner"] = inputeRunnerContext;
|
|
||||||
|
|
||||||
var ecExpect = new Runner.Worker.ExecutionContext();
|
|
||||||
ecExpect.Initialize(hc);
|
|
||||||
|
|
||||||
var expectedGithubEvent = new DictionaryContextData();
|
|
||||||
expectedGithubEvent["inputs"] = null;
|
|
||||||
expectedGithubEvent["ref"] = new StringContextData("refs/heads/main");
|
|
||||||
expectedGithubEvent["repository"] = new DictionaryContextData();
|
|
||||||
expectedGithubEvent["sender"] = new DictionaryContextData();
|
|
||||||
expectedGithubEvent["workflow"] = new StringContextData(".github/workflows/composite_step_host_translate.yaml");
|
|
||||||
var expectedGithubContext = new GitHubContext();
|
|
||||||
var expectedRunnerContext = new RunnerContext();
|
|
||||||
expectedGithubContext["action_path"] = new StringContextData("/__w/_actions/owner/composite/main");
|
|
||||||
expectedGithubContext["action"] = new StringContextData("__owner_composite");
|
|
||||||
expectedGithubContext["api_url"] = new StringContextData("https://api.github.com/custom/path");
|
|
||||||
expectedGithubContext["env"] = new StringContextData("/__w/_temp/_runner_file_commands/set_env_265698aa-7f38-40f5-9316-5c01a3153672");
|
|
||||||
expectedGithubContext["path"] = new StringContextData("/__w/_temp/_runner_file_commands/add_path_265698aa-7f38-40f5-9316-5c01a3153672");
|
|
||||||
expectedGithubContext["event_path"] = new StringContextData("/github/workflow/event.json");
|
|
||||||
expectedGithubContext["repository"] = new StringContextData("owner/repo-name");
|
|
||||||
expectedGithubContext["run_id"] = new StringContextData("2033211332");
|
|
||||||
expectedGithubContext["workflow"] = new StringContextData("Name of Workflow");
|
|
||||||
expectedGithubContext["workspace"] = new StringContextData("/__w/step-order/step-order");
|
|
||||||
expectedGithubContext["event"] = expectedGithubEvent;
|
|
||||||
expectedRunnerContext["temp"] = new StringContextData("/__w/_temp");
|
|
||||||
expectedRunnerContext["tool_cache"] = new StringContextData("/__w/_tool");
|
|
||||||
|
|
||||||
ecExpect.ExpressionValues["github"] = expectedGithubContext;
|
|
||||||
ecExpect.ExpressionValues["runner"] = expectedRunnerContext;
|
|
||||||
|
|
||||||
var translatedExpressionValues = ec.GetExpressionValues(stepHost);
|
|
||||||
|
|
||||||
foreach (var contextName in new string[] { "github", "runner" })
|
|
||||||
{
|
|
||||||
var dict = translatedExpressionValues[contextName].AssertDictionary($"expected context github to be a dictionary");
|
|
||||||
var expectedExpressionValues = ecExpect.ExpressionValues[contextName].AssertDictionary("expect dict");
|
|
||||||
foreach (var key in dict.Keys.ToList())
|
|
||||||
{
|
|
||||||
if (dict[key] is StringContextData)
|
|
||||||
{
|
|
||||||
var expect = dict[key].AssertString("expect string");
|
|
||||||
var outcome = expectedExpressionValues[key].AssertString("expect string");
|
|
||||||
Assert.Equal(expect.Value, outcome.Value);
|
|
||||||
}
|
|
||||||
else if (dict[key] is DictionaryContextData || dict[key] is CaseSensitiveDictionaryContextData)
|
|
||||||
{
|
|
||||||
var expectDict = dict[key].AssertDictionary("expect dict");
|
|
||||||
var actualDict = expectedExpressionValues[key].AssertDictionary("expect dict");
|
|
||||||
Assert.True(ExpressionValuesAssertEqual(expectDict, actualDict));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ExpressionValuesAssertEqual(DictionaryContextData expect, DictionaryContextData actual)
|
|
||||||
{
|
|
||||||
foreach (var key in expect.Keys.ToList())
|
|
||||||
{
|
|
||||||
if (expect[key] is StringContextData)
|
|
||||||
{
|
|
||||||
var expectValue = expect[key].AssertString("expect string");
|
|
||||||
var actualValue = actual[key].AssertString("expect string");
|
|
||||||
if (expectValue.Equals(actualValue))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (expect[key] is DictionaryContextData || expect[key] is CaseSensitiveDictionaryContextData)
|
|
||||||
{
|
|
||||||
var expectDict = expect[key].AssertDictionary("expect dict");
|
|
||||||
var actualDict = actual[key].AssertDictionary("expect dict");
|
|
||||||
if (!ExpressionValuesAssertEqual(expectDict, actualDict))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
@@ -937,20 +937,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
[Trait("Level", "L0")]
|
|
||||||
[Trait("Category", "Worker")]
|
|
||||||
public void CaptureTelemetryForGitUnsafeRepository()
|
|
||||||
{
|
|
||||||
using (Setup())
|
|
||||||
using (_outputManager)
|
|
||||||
{
|
|
||||||
Process("fatal: unsafe repository ('/github/workspace' is owned by someone else)");
|
|
||||||
Assert.Contains("fatal: unsafe repository ('/github/workspace' is owned by someone else)", _executionContext.Object.StepTelemetry.ErrorMessages);
|
|
||||||
Assert.Contains(_issues, x => x.Item1.Type == DTWebApi.IssueType.Notice && x.Item1.Message.Contains("You may experience error caused by a recently git safe directory enforcement"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TestHostContext Setup(
|
private TestHostContext Setup(
|
||||||
[CallerMemberName] string name = "",
|
[CallerMemberName] string name = "",
|
||||||
IssueMatchersConfig matchers = null,
|
IssueMatchersConfig matchers = null,
|
||||||
@@ -976,8 +962,6 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
Variables = _variables,
|
Variables = _variables,
|
||||||
WriteDebug = true,
|
WriteDebug = true,
|
||||||
});
|
});
|
||||||
_executionContext.Setup(x => x.StepTelemetry)
|
|
||||||
.Returns(new DTWebApi.ActionsStepTelemetry());
|
|
||||||
_executionContext.Setup(x => x.GetMatchers())
|
_executionContext.Setup(x => x.GetMatchers())
|
||||||
.Returns(matchers?.Matchers ?? new List<IssueMatcherConfig>());
|
.Returns(matchers?.Matchers ?? new List<IssueMatcherConfig>());
|
||||||
_executionContext.Setup(x => x.Add(It.IsAny<OnMatcherChanged>()))
|
_executionContext.Setup(x => x.Add(It.IsAny<OnMatcherChanged>()))
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ using Xunit;
|
|||||||
using GitHub.Runner.Worker;
|
using GitHub.Runner.Worker;
|
||||||
using GitHub.Runner.Worker.Handlers;
|
using GitHub.Runner.Worker.Handlers;
|
||||||
using GitHub.Runner.Worker.Container;
|
using GitHub.Runner.Worker.Container;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
|
||||||
using System.Linq;
|
|
||||||
using GitHub.DistributedTask.Pipelines;
|
|
||||||
|
|
||||||
namespace GitHub.Runner.Common.Tests.Worker
|
namespace GitHub.Runner.Common.Tests.Worker
|
||||||
{
|
{
|
||||||
|
|||||||
14
src/dev.sh
14
src/dev.sh
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
#
|
#
|
||||||
# ./dev.sh build/layout/test/package [Debug/Release]
|
# ./dev.sh build/layout/test/package [Debug/Release] [linux-x64|linux-x86|linux-arm64|linux-arm|osx-x64|win-x64|win-x86] [use-broker]
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ set -e
|
|||||||
DEV_CMD=$1
|
DEV_CMD=$1
|
||||||
DEV_CONFIG=$2
|
DEV_CONFIG=$2
|
||||||
DEV_TARGET_RUNTIME=$3
|
DEV_TARGET_RUNTIME=$3
|
||||||
|
DEV_USE_BROKER=$4
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
LAYOUT_DIR="$SCRIPT_DIR/../_layout"
|
LAYOUT_DIR="$SCRIPT_DIR/../_layout"
|
||||||
@@ -81,6 +82,13 @@ elif [[ "$CURRENT_PLATFORM" == 'darwin' ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ -n "$DEV_USE_BROKER" ]; then
|
||||||
|
USE_BROKER='-p:USE_BROKER="true"'
|
||||||
|
else
|
||||||
|
USE_BROKER=''
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
function failed()
|
function failed()
|
||||||
{
|
{
|
||||||
local error=${1:-Undefined error}
|
local error=${1:-Undefined error}
|
||||||
@@ -114,13 +122,13 @@ function heading()
|
|||||||
function build ()
|
function build ()
|
||||||
{
|
{
|
||||||
heading "Building ..."
|
heading "Building ..."
|
||||||
dotnet msbuild -t:Build -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" ./dir.proj || failed build
|
dotnet msbuild -t:Build -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" $USE_BROKER ./dir.proj || failed build
|
||||||
}
|
}
|
||||||
|
|
||||||
function layout ()
|
function layout ()
|
||||||
{
|
{
|
||||||
heading "Create layout ..."
|
heading "Create layout ..."
|
||||||
dotnet msbuild -t:layout -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" ./dir.proj || failed build
|
dotnet msbuild -t:layout -p:PackageRuntime="${RUNTIME_ID}" -p:BUILDCONFIG="${BUILD_CONFIG}" -p:RunnerVersion="${RUNNER_VERSION}" $USE_BROKER ./dir.proj || failed build
|
||||||
|
|
||||||
#change execution flag to allow running with sudo
|
#change execution flag to allow running with sudo
|
||||||
if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then
|
if [[ ("$CURRENT_PLATFORM" == "linux") || ("$CURRENT_PLATFORM" == "darwin") ]]; then
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
2.290.0
|
2.289.2
|
||||||
|
|||||||
Reference in New Issue
Block a user