mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Allow mocked updates for E2E testing (#1654)
* Allow mock update messages * Kill node process see other PR * Better comments * Better comparison for archiveFile * Revert merge comment mistakes Co-authored-by: Ferenc Hammerl <hammerl.ferenc@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ using GitHub.Runner.Common;
|
|||||||
using GitHub.Runner.Sdk;
|
using GitHub.Runner.Sdk;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using GitHub.Runner.Listener.Check;
|
using GitHub.Runner.Listener.Check;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace GitHub.Runner.Listener
|
namespace GitHub.Runner.Listener
|
||||||
{
|
{
|
||||||
@@ -407,6 +408,27 @@ namespace GitHub.Runner.Listener
|
|||||||
{
|
{
|
||||||
autoUpdateInProgress = true;
|
autoUpdateInProgress = true;
|
||||||
var runnerUpdateMessage = JsonUtility.FromString<AgentRefreshMessage>(message.Body);
|
var runnerUpdateMessage = JsonUtility.FromString<AgentRefreshMessage>(message.Body);
|
||||||
|
#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}");
|
||||||
|
runnerUpdateMessage = new AgentRefreshMessage(runnerUpdateMessage.AgentId, mockTargetVersion, runnerUpdateMessage.Timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
var selfUpdater = HostContext.GetService<ISelfUpdater>();
|
var selfUpdater = HostContext.GetService<ISelfUpdater>();
|
||||||
selfUpdateTask = selfUpdater.SelfUpdate(runnerUpdateMessage, jobDispatcher, false, HostContext.RunnerShutdownToken);
|
selfUpdateTask = selfUpdater.SelfUpdate(runnerUpdateMessage, jobDispatcher, false, HostContext.RunnerShutdownToken);
|
||||||
Trace.Info("Refresh message received, kick-off selfupdate background process.");
|
Trace.Info("Refresh message received, kick-off selfupdate background process.");
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ namespace GitHub.Runner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await DownloadLatestRunner(token);
|
await DownloadLatestRunner(token, updateMessage.TargetVersion);
|
||||||
Trace.Info($"Download latest runner and unzip into runner root.");
|
Trace.Info($"Download latest runner and unzip into runner root.");
|
||||||
|
|
||||||
// wait till all running job finish
|
// wait till all running job finish
|
||||||
@@ -206,7 +206,7 @@ namespace GitHub.Runner.Listener
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task DownloadLatestRunner(CancellationToken token)
|
private async Task DownloadLatestRunner(CancellationToken token, string targetVersion)
|
||||||
{
|
{
|
||||||
string latestRunnerDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), Constants.Path.UpdateDirectory);
|
string latestRunnerDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Work), Constants.Path.UpdateDirectory);
|
||||||
IOUtil.DeleteDirectory(latestRunnerDirectory, token);
|
IOUtil.DeleteDirectory(latestRunnerDirectory, token);
|
||||||
@@ -266,14 +266,57 @@ namespace GitHub.Runner.Listener
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
archiveFile = await DownLoadRunner(latestRunnerDirectory, packageDownloadUrl, packageHashValue, token);
|
#if DEBUG
|
||||||
|
// Much of the update process (targetVersion, archive) is server-side, this is a way to control it from here for testing specific update scenarios
|
||||||
|
// Add files like 'runner2.281.2.tar.gz' or 'runner2.283.0.zip' (depending on your platform) to your runner root folder
|
||||||
|
// Note that runners still need to be older than the server's runner version in order to receive an 'AgentRefreshMessage' and trigger this update
|
||||||
|
// Wrapped in #if DEBUG as this should not be in the RELEASE build
|
||||||
|
if (StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_IS_MOCK_UPDATE")))
|
||||||
|
{
|
||||||
|
var waitForDebugger = StringUtil.ConvertToBoolean(Environment.GetEnvironmentVariable("GITHUB_ACTIONS_RUNNER_IS_MOCK_UPDATE_WAIT_FOR_DEBUGGER"));
|
||||||
|
if (waitForDebugger)
|
||||||
|
{
|
||||||
|
int waitInSeconds = 20;
|
||||||
|
while (!Debugger.IsAttached && waitInSeconds-- > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
Debugger.Break();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_targetPackage.Platform.StartsWith("win"))
|
||||||
|
{
|
||||||
|
archiveFile = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Root), $"runner{targetVersion}.zip");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archiveFile = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Root), $"runner{targetVersion}.tar.gz");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(archiveFile))
|
||||||
|
{
|
||||||
|
_updateTrace.Enqueue($"Mocking update with file: '{archiveFile}' and targetVersion: '{targetVersion}', nothing is downloaded");
|
||||||
|
_terminal.WriteLine($"Mocking update with file: '{archiveFile}' and targetVersion: '{targetVersion}', nothing is downloaded");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archiveFile = null;
|
||||||
|
_terminal.WriteLine($"Mock runner archive not found at {archiveFile} for target version {targetVersion}, proceeding with download instead");
|
||||||
|
_updateTrace.Enqueue($"Mock runner archive not found at {archiveFile} for target version {targetVersion}, proceeding with download instead");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// archiveFile is not null only if we mocked it above
|
||||||
if (string.IsNullOrEmpty(archiveFile))
|
if (string.IsNullOrEmpty(archiveFile))
|
||||||
{
|
{
|
||||||
throw new TaskCanceledException($"Runner package '{packageDownloadUrl}' failed after {Constants.RunnerDownloadRetryMaxAttempts} download attempts");
|
archiveFile = await DownLoadRunner(latestRunnerDirectory, packageDownloadUrl, packageHashValue, token);
|
||||||
}
|
|
||||||
|
|
||||||
await ValidateRunnerHash(archiveFile, packageHashValue);
|
if (string.IsNullOrEmpty(archiveFile))
|
||||||
|
{
|
||||||
|
throw new TaskCanceledException($"Runner package '{packageDownloadUrl}' failed after {Constants.RunnerDownloadRetryMaxAttempts} download attempts");
|
||||||
|
}
|
||||||
|
await ValidateRunnerHash(archiveFile, packageHashValue);
|
||||||
|
}
|
||||||
|
|
||||||
await ExtractRunnerPackage(archiveFile, latestRunnerDirectory, token);
|
await ExtractRunnerPackage(archiveFile, latestRunnerDirectory, token);
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/Test/TestData/mock_update_messages.json
Normal file
1
src/Test/TestData/mock_update_messages.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ "2.283.2": {"targetVersion":"2.284.1"}, "2.284.1": {"targetVersion":"2.285.0"}}
|
||||||
Reference in New Issue
Block a user