mirror of
https://github.com/actions/runner.git
synced 2025-12-10 20:36:49 +00:00
Mark action download failures as infra failures (#2827)
* Mark action download failures as infra failures * Fix Windows variable name * Update src/Runner.Worker/ActionManager.cs Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com> --------- Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com>
This commit is contained in:
@@ -115,6 +115,14 @@ namespace GitHub.Runner.Worker
|
||||
executionContext.Result = TaskResult.Failed;
|
||||
throw;
|
||||
}
|
||||
catch (InvalidActionArchiveException ex)
|
||||
{
|
||||
// Log the error and fail the PrepareActionsAsync Initialization.
|
||||
Trace.Error($"Caught exception from PrepareActionsAsync Initialization: {ex}");
|
||||
executionContext.InfrastructureError(ex.Message);
|
||||
executionContext.Result = TaskResult.Failed;
|
||||
throw;
|
||||
}
|
||||
if (!FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables))
|
||||
{
|
||||
if (state.ImagesToPull.Count > 0)
|
||||
@@ -907,7 +915,14 @@ namespace GitHub.Runner.Worker
|
||||
Directory.CreateDirectory(stagingDirectory);
|
||||
|
||||
#if OS_WINDOWS
|
||||
ZipFile.ExtractToDirectory(archiveFile, stagingDirectory);
|
||||
try
|
||||
{
|
||||
ZipFile.ExtractToDirectory(archiveFile, stagingDirectory);
|
||||
}
|
||||
catch (InvalidDataException e)
|
||||
{
|
||||
throw new InvalidActionArchiveException($"Can't un-zip archive file: {archiveFile}. action being checked out: {downloadInfo.NameWithOwner}@{downloadInfo.Ref}. error: {e}.");
|
||||
}
|
||||
#else
|
||||
string tar = WhichUtil.Which("tar", require: true, trace: Trace);
|
||||
|
||||
@@ -933,7 +948,7 @@ namespace GitHub.Runner.Worker
|
||||
int exitCode = await processInvoker.ExecuteAsync(stagingDirectory, tar, $"-xzf \"{archiveFile}\"", null, executionContext.CancellationToken);
|
||||
if (exitCode != 0)
|
||||
{
|
||||
throw new NotSupportedException($"Can't use 'tar -xzf' extract archive file: {archiveFile}. return code: {exitCode}.");
|
||||
throw new InvalidActionArchiveException($"Can't use 'tar -xzf' extract archive file: {archiveFile}. Action being checked out: {downloadInfo.NameWithOwner}@{downloadInfo.Ref}. return code: {exitCode}.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2516,4 +2516,23 @@ namespace GitHub.DistributedTask.WebApi
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public sealed class InvalidActionArchiveException : DistributedTaskException
|
||||
{
|
||||
public InvalidActionArchiveException(String message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public InvalidActionArchiveException(String message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
private InvalidActionArchiveException(SerializationInfo info, StreamingContext context)
|
||||
: base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +96,63 @@ namespace GitHub.Runner.Common.Tests.Worker
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
public async void PrepareActions_DownloadActionFromDotCom_ZipFileError()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Arrange
|
||||
Setup();
|
||||
const string ActionName = "ownerName/sample-action";
|
||||
var actions = new List<Pipelines.ActionStep>
|
||||
{
|
||||
new Pipelines.ActionStep()
|
||||
{
|
||||
Name = "action",
|
||||
Id = Guid.NewGuid(),
|
||||
Reference = new Pipelines.RepositoryPathReference()
|
||||
{
|
||||
Name = ActionName,
|
||||
Ref = "main",
|
||||
RepositoryType = "GitHub"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Create a corrupted ZIP file for testing
|
||||
var tempDir = _hc.GetDirectory(WellKnownDirectory.Temp);
|
||||
Directory.CreateDirectory(tempDir);
|
||||
var archiveFile = Path.Combine(tempDir, Path.GetRandomFileName());
|
||||
using (var fileStream = new FileStream(archiveFile, FileMode.Create))
|
||||
{
|
||||
// Used Co-Pilot for magic bytes here. They represent the tar header and just need to be invalid for the CLI to break.
|
||||
var buffer = new byte[] { 0x50, 0x4B, 0x03, 0x04, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00 };
|
||||
fileStream.Write(buffer, 0, buffer.Length);
|
||||
}
|
||||
using var stream = File.OpenRead(archiveFile);
|
||||
|
||||
string dotcomArchiveLink = GetLinkToActionArchive("https://api.github.com", ActionName, "main");
|
||||
var mockClientHandler = new Mock<HttpClientHandler>();
|
||||
mockClientHandler.Protected().Setup<Task<HttpResponseMessage>>("SendAsync", ItExpr.Is<HttpRequestMessage>(m => m.RequestUri == new Uri(dotcomArchiveLink)), ItExpr.IsAny<CancellationToken>())
|
||||
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) });
|
||||
|
||||
var mockHandlerFactory = new Mock<IHttpClientHandlerFactory>();
|
||||
mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny<RunnerWebProxy>())).Returns(mockClientHandler.Object);
|
||||
_hc.SetSingleton(mockHandlerFactory.Object);
|
||||
|
||||
_configurationStore.Object.GetSettings().IsHostedServer = true;
|
||||
|
||||
// Act + Assert
|
||||
await Assert.ThrowsAsync<InvalidActionArchiveException>(async () => await _actionManager.PrepareActionsAsync(_ec.Object, actions));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Teardown();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[Trait("Level", "L0")]
|
||||
[Trait("Category", "Worker")]
|
||||
|
||||
Reference in New Issue
Block a user