mirror of
https://github.com/actions/runner.git
synced 2025-12-13 19:03:44 +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;
|
executionContext.Result = TaskResult.Failed;
|
||||||
throw;
|
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 (!FeatureManager.IsContainerHooksEnabled(executionContext.Global.Variables))
|
||||||
{
|
{
|
||||||
if (state.ImagesToPull.Count > 0)
|
if (state.ImagesToPull.Count > 0)
|
||||||
@@ -907,7 +915,14 @@ namespace GitHub.Runner.Worker
|
|||||||
Directory.CreateDirectory(stagingDirectory);
|
Directory.CreateDirectory(stagingDirectory);
|
||||||
|
|
||||||
#if OS_WINDOWS
|
#if OS_WINDOWS
|
||||||
|
try
|
||||||
|
{
|
||||||
ZipFile.ExtractToDirectory(archiveFile, stagingDirectory);
|
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
|
#else
|
||||||
string tar = WhichUtil.Which("tar", require: true, trace: Trace);
|
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);
|
int exitCode = await processInvoker.ExecuteAsync(stagingDirectory, tar, $"-xzf \"{archiveFile}\"", null, executionContext.CancellationToken);
|
||||||
if (exitCode != 0)
|
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
|
#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]
|
[Fact]
|
||||||
[Trait("Level", "L0")]
|
[Trait("Level", "L0")]
|
||||||
[Trait("Category", "Worker")]
|
[Trait("Category", "Worker")]
|
||||||
|
|||||||
Reference in New Issue
Block a user