This commit is contained in:
Tatyana Kostromskaya
2022-10-25 14:02:30 +00:00
9 changed files with 140 additions and 26 deletions

13
.vscode/launch.json vendored
View File

@@ -12,7 +12,10 @@
],
"cwd": "${workspaceFolder}/src",
"console": "integratedTerminal",
"requireExactSource": false
"requireExactSource": false,
"env": {
"USE_BROKER_FLOW": "1"
}
},
{
"name": "Run",
@@ -24,7 +27,10 @@
],
"cwd": "${workspaceFolder}/src",
"console": "integratedTerminal",
"requireExactSource": false
"requireExactSource": false,
"env": {
"USE_BROKER_FLOW": "1"
}
},
{
"name": "Configure",
@@ -54,5 +60,4 @@
"requireExactSource": false
},
],
}
}

View File

@@ -38,7 +38,7 @@ namespace GitHub.Runner.Common
Task<TaskAgentSession> CreateAgentSessionAsync(Int32 poolId, TaskAgentSession session, CancellationToken cancellationToken);
Task DeleteAgentMessageAsync(Int32 poolId, Int64 messageId, Guid sessionId, CancellationToken cancellationToken);
Task DeleteAgentSessionAsync(Int32 poolId, Guid sessionId, CancellationToken cancellationToken);
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken);
Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken);
// job request
Task<TaskAgentJobRequest> GetAgentRequestAsync(int poolId, long requestId, CancellationToken cancellationToken);
@@ -297,10 +297,10 @@ namespace GitHub.Runner.Common
return _messageTaskAgentClient.DeleteAgentSessionAsync(poolId, sessionId, cancellationToken: cancellationToken);
}
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken)
public Task<TaskAgentMessage> GetAgentMessageAsync(Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, string runnerVersion, CancellationToken cancellationToken)
{
CheckConnection(RunnerConnectionType.MessageQueue);
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, cancellationToken: cancellationToken);
return _messageTaskAgentClient.GetMessageAsync(poolId, sessionId, lastMessageId, status, runnerVersion, cancellationToken: cancellationToken);
}
//-----------------------------------------------------------------

View File

@@ -211,6 +211,7 @@ namespace GitHub.Runner.Listener
_session.SessionId,
_lastMessageId,
runnerStatus,
BuildConstants.RunnerPackage.Version,
_getMessagesTokenSource.Token);
// Decrypt the message body if the session is using encryption

View File

@@ -466,6 +466,50 @@ namespace GitHub.Runner.Listener
Trace.Info("Refresh message received, skip autoupdate since a previous autoupdate is already running.");
}
}
else if (string.Equals(message.MessageType, RunnerRefreshMessage.MessageType, StringComparison.OrdinalIgnoreCase))
{
if (autoUpdateInProgress == false)
{
autoUpdateInProgress = true;
var runnerUpdateMessage = JsonUtility.FromString<RunnerRefreshMessage>(message.Body);
//////////////////////////////
_term.WriteLine($"TargetVersion: {runnerUpdateMessage.TargetVersion}");
_term.WriteLine($"AgentId: {runnerUpdateMessage.AgentId}");
_term.WriteLine($"Timeout: {runnerUpdateMessage.Timeout.ToString()}");
//////////////////////////////
var agentRefreshMessage = new AgentRefreshMessage(runnerUpdateMessage.AgentId, runnerUpdateMessage.TargetVersion, TimeSpan.FromMilliseconds(runnerUpdateMessage.Timeout));
#if DEBUG
// Can mock the update for testing
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_IS_MOCK_UPDATE")))
{
// The mock_update_messages.json file should be an object with keys being the current version and values being the targeted mock version object
// Example: { "2.283.2": {"targetVersion":"2.284.1"}, "2.284.1": {"targetVersion":"2.285.0"}}
var mockUpdatesPath = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Root), "mock_update_messages.json");
if (File.Exists(mockUpdatesPath))
{
var mockUpdateMessages = JsonUtility.FromString<Dictionary<string, AgentRefreshMessage>>(File.ReadAllText(mockUpdatesPath));
if (mockUpdateMessages.ContainsKey(BuildConstants.RunnerPackage.Version))
{
var mockTargetVersion = mockUpdateMessages[BuildConstants.RunnerPackage.Version].TargetVersion;
_term.WriteLine($"Mocking update, using version {mockTargetVersion} instead of {runnerUpdateMessage.TargetVersion}");
Trace.Info($"Mocking update, using version {mockTargetVersion} instead of {runnerUpdateMessage.TargetVersion}");
agentRefreshMessage = new AgentRefreshMessage(agentRefreshMessage.AgentId, mockTargetVersion, agentRefreshMessage.Timeout);
}
}
}
#endif
var selfUpdater = HostContext.GetService<ISelfUpdater>();
selfUpdateTask = selfUpdater.SelfUpdate(agentRefreshMessage, jobDispatcher, false, HostContext.RunnerShutdownToken);
Trace.Info("Refresh message received, kick-off selfupdate background process.");
}
else
{
Trace.Info("Refresh message received, skip autoupdate since a previous autoupdate is already running.");
}
}
else if (string.Equals(message.MessageType, JobRequestMessageTypes.PipelineAgentJobRequest, StringComparison.OrdinalIgnoreCase))
{
if (autoUpdateInProgress || runOnceJobReceived)

View File

@@ -73,13 +73,12 @@ namespace GitHub.Runner.Listener
// we will just go with the full package.
var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(token);
_cloneAndCalculateContentHashTask = CloneAndCalculateAssetsHash(_dotnetRuntimeCloneDirectory, _externalsCloneDirectory, linkedTokenSource.Token);
_terminal.WriteLine("Self-update");
if (!await UpdateNeeded(updateMessage.TargetVersion, token))
{
Trace.Info($"Can't find available update package.");
return false;
}
Trace.Info($"An update is available.");
_updateTrace.Enqueue($"RunnerPlatform: {_targetPackage.Platform}");
@@ -171,9 +170,12 @@ namespace GitHub.Runner.Listener
// old server won't send target version as part of update message.
if (string.IsNullOrEmpty(targetVersion))
{
_terminal.WriteLine("Debug 1");
var packages = await _runnerServer.GetPackagesAsync(_packageType, _platform, 1, true, token);
_terminal.WriteLine("Debug 2");
if (packages == null || packages.Count == 0)
{
_terminal.WriteLine("Debug 3");
Trace.Info($"There is no package for {_packageType} and {_platform}.");
return false;
}
@@ -182,14 +184,20 @@ namespace GitHub.Runner.Listener
}
else
{
_targetPackage = await _runnerServer.GetPackageAsync(_packageType, _platform, targetVersion, true, token);
_terminal.WriteLine("Debug 4");
_targetPackage = new PackageMetadata() { Platform = BuildConstants.RunnerPackage.PackageName,
Version = new PackageVersion(targetVersion),
DownloadUrl = $"https://github.com/actions/runner/releases/download/v{targetVersion}/actions-runner-{BuildConstants.RunnerPackage.PackageName}-{targetVersion}.tar.gz" };
// _targetPackage = await _runnerServer.GetPackageAsync(_packageType, _platform, targetVersion, true, token);
_terminal.WriteLine("Debug 5");
if (_targetPackage == null)
{
_terminal.WriteLine("Debug 6");
Trace.Info($"There is no package for {_packageType} and {_platform} with version {targetVersion}.");
return false;
}
}
_terminal.WriteLine("Debug 7");
Trace.Info($"Version '{_targetPackage.Version}' of '{_targetPackage.Type}' package available in server.");
PackageVersion serverVersion = new PackageVersion(_targetPackage.Version);
Trace.Info($"Current running runner version is {BuildConstants.RunnerPackage.Version}");

View File

@@ -450,6 +450,8 @@ namespace GitHub.DistributedTask.WebApi
/// <param name="poolId"></param>
/// <param name="sessionId"></param>
/// <param name="lastMessageId"></param>
/// <param name="status"></param>
/// <param name="runnerversion"></param>
/// <param name="userState"></param>
/// <param name="cancellationToken">The cancellation token to cancel operation.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
@@ -458,6 +460,7 @@ namespace GitHub.DistributedTask.WebApi
Guid sessionId,
long? lastMessageId = null,
TaskAgentStatus? status = null,
string runnerversion = "",
object userState = null,
CancellationToken cancellationToken = default)
{
@@ -475,6 +478,10 @@ namespace GitHub.DistributedTask.WebApi
{
queryParams.Add("status", status.Value.ToString());
}
if (!string.IsNullOrWhiteSpace(runnerversion))
{
queryParams.Add("runnerversion", runnerversion);
}
return SendAsync<TaskAgentMessage>(
httpMethod,

View File

@@ -0,0 +1,49 @@
using Newtonsoft.Json;
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class RunnerRefreshMessage
{
public static readonly String MessageType = "RunnerRefresh";
[JsonConstructor]
internal RunnerRefreshMessage()
{
}
public RunnerRefreshMessage(
Int32 agentId,
String targetVersion,
int? timeout = null)
{
this.AgentId = agentId;
this.Timeout = timeout ?? TimeSpan.FromMinutes(60).Milliseconds;
this.TargetVersion = targetVersion;
}
[DataMember]
public Int32 AgentId
{
get;
private set;
}
[DataMember]
public int Timeout
{
get;
private set;
}
[DataMember]
public String TargetVersion
{
get;
private set;
}
}
}

View File

@@ -131,7 +131,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void GetNextMessage()
@@ -192,7 +192,7 @@ namespace GitHub.Runner.Common.Tests.Listener
_runnerServer
.Setup(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()))
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(async (Int32 poolId, Guid sessionId, Int64? lastMessageId, TaskAgentStatus status, CancellationToken cancellationToken) =>
{
await Task.Yield();
@@ -208,7 +208,7 @@ namespace GitHub.Runner.Common.Tests.Listener
//Assert
_runnerServer
.Verify(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()), Times.Exactly(arMessages.Length));
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Exactly(arMessages.Length));
}
}
@@ -293,7 +293,7 @@ namespace GitHub.Runner.Common.Tests.Listener
_runnerServer
.Setup(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()))
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Throws(new TaskAgentAccessTokenExpiredException("test"));
try
{
@@ -311,7 +311,7 @@ namespace GitHub.Runner.Common.Tests.Listener
//Assert
_runnerServer
.Verify(x => x.GetAgentMessageAsync(
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<CancellationToken>()), Times.Once);
_settings.PoolId, expectedSession.SessionId, It.IsAny<long?>(), TaskAgentStatus.Online, It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
_runnerServer
.Verify(x => x.DeleteAgentSessionAsync(

View File

@@ -82,7 +82,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync()
@@ -143,7 +143,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_NoUpdateOnOldVersion()
@@ -196,7 +196,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_DownloadRetry()
@@ -251,7 +251,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_ValidateHash()
@@ -306,7 +306,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_CloneHash_RuntimeAndExternals()
@@ -381,7 +381,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_Cancel_CloneHashTask_WhenNotNeeded()
@@ -445,7 +445,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_UseExternalsTrimmedPackage()
@@ -531,7 +531,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_UseExternalsRuntimeTrimmedPackage()
@@ -624,7 +624,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_NotUseExternalsRuntimeTrimmedPackageOnHashMismatch()
@@ -711,7 +711,7 @@ namespace GitHub.Runner.Common.Tests.Listener
}
}
[Fact]
[Fact (Skip = "specific reason")]
[Trait("Level", "L0")]
[Trait("Category", "Runner")]
public async void TestSelfUpdateAsync_FallbackToFullPackage()