diff --git a/src/Runner.Common/HostContext.cs b/src/Runner.Common/HostContext.cs index 8126f8c95..b9a44fa2b 100644 --- a/src/Runner.Common/HostContext.cs +++ b/src/Runner.Common/HostContext.cs @@ -1,18 +1,19 @@ -using System; +using GitHub.Runner.Common.Util; +using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; -using System.Diagnostics.Tracing; using System.Globalization; using System.IO; using System.Linq; -using System.Net.Http; -using System.Net.Http.Headers; using System.Reflection; using System.Runtime.Loader; using System.Threading; using System.Threading.Tasks; +using System.Diagnostics; +using System.Net.Http; +using System.Diagnostics.Tracing; using GitHub.DistributedTask.Logging; +using System.Net.Http.Headers; using GitHub.Runner.Sdk; namespace GitHub.Runner.Common @@ -614,8 +615,9 @@ namespace GitHub.Runner.Common { public static HttpClientHandler CreateHttpClientHandler(this IHostContext context) { - var handlerFactory = context.GetService(); - return handlerFactory.CreateClientHandler(context.WebProxy); + HttpClientHandler clientHandler = new HttpClientHandler(); + clientHandler.Proxy = context.WebProxy; + return clientHandler; } } diff --git a/src/Runner.Common/HttpClientHandlerFactory.cs b/src/Runner.Common/HttpClientHandlerFactory.cs deleted file mode 100644 index f507dd7af..000000000 --- a/src/Runner.Common/HttpClientHandlerFactory.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Net.Http; -using GitHub.Runner.Sdk; - -namespace GitHub.Runner.Common -{ - [ServiceLocator(Default = typeof(HttpClientHandlerFactory))] - public interface IHttpClientHandlerFactory : IRunnerService - { - HttpClientHandler CreateClientHandler(RunnerWebProxy webProxy); - } - - public class HttpClientHandlerFactory : RunnerService, IHttpClientHandlerFactory - { - public HttpClientHandler CreateClientHandler(RunnerWebProxy webProxy) - { - return new HttpClientHandler() { Proxy = webProxy }; - } - } -} \ No newline at end of file diff --git a/src/Runner.Worker/ActionManager.cs b/src/Runner.Worker/ActionManager.cs index 6865a7852..533841659 100644 --- a/src/Runner.Worker/ActionManager.cs +++ b/src/Runner.Worker/ActionManager.cs @@ -1,19 +1,21 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; -using System.Net; +using System.Threading; +using System.Threading.Tasks; using System.Net.Http; using System.Net.Http.Headers; using System.Text; -using System.Threading; -using System.Threading.Tasks; using GitHub.DistributedTask.ObjectTemplating.Tokens; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Common; +using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using GitHub.Runner.Worker.Container; using GitHub.Services.Common; +using Newtonsoft.Json; using Pipelines = GitHub.DistributedTask.Pipelines; using PipelineTemplateConstants = GitHub.DistributedTask.Pipelines.ObjectTemplating.PipelineTemplateConstants; @@ -71,7 +73,13 @@ namespace GitHub.Runner.Worker } // Clear the cache (for self-hosted runners) - IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken); + // Note, temporarily avoid this step for the on-premises product, to avoid rate limiting. + var configurationStore = HostContext.GetService(); + var isHostedServer = configurationStore.GetSettings().IsHostedServer; + if (isHostedServer) + { + IOUtil.DeleteDirectory(HostContext.GetDirectory(WellKnownDirectory.Actions), executionContext.CancellationToken); + } foreach (var action in actions) { @@ -482,7 +490,7 @@ namespace GitHub.Runner.Worker ArgUtil.NotNullOrEmpty(repositoryReference.Ref, nameof(repositoryReference.Ref)); string destDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), repositoryReference.Name.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar), repositoryReference.Ref); - string watermarkFile = GetWatermarkFilePath(destDirectory); + string watermarkFile = destDirectory + ".completed"; if (File.Exists(watermarkFile)) { executionContext.Debug($"Action '{repositoryReference.Name}@{repositoryReference.Ref}' already downloaded at '{destDirectory}'."); @@ -496,84 +504,27 @@ namespace GitHub.Runner.Worker executionContext.Output($"Download action repository '{repositoryReference.Name}@{repositoryReference.Ref}'"); } - var configurationStore = HostContext.GetService(); - var isHostedServer = configurationStore.GetSettings().IsHostedServer; - if (isHostedServer) - { - string apiUrl = GetApiUrl(executionContext); - string archiveLink = BuildLinkToActionArchive(apiUrl, repositoryReference.Name, repositoryReference.Ref); - Trace.Info($"Download archive '{archiveLink}' to '{destDirectory}'."); - await DownloadRepositoryActionAsync(executionContext, archiveLink, destDirectory); - return; - } - else - { - string apiUrl = GetApiUrl(executionContext); - - // URLs to try: - var archiveLinks = new List { - // A built-in action or an action the user has created, on their GHES instance - // Example: https://my-ghes/api/v3/repos/my-org/my-action/tarball/v1 - BuildLinkToActionArchive(apiUrl, repositoryReference.Name, repositoryReference.Ref), - - // A community action, synced to their GHES instance - // Example: https://my-ghes/api/v3/repos/actions-community/some-org-some-action/tarball/v1 - BuildLinkToActionArchive(apiUrl, $"actions-community/{repositoryReference.Name.Replace("/", "-")}", repositoryReference.Ref) - }; - - foreach (var archiveLink in archiveLinks) - { - Trace.Info($"Download archive '{archiveLink}' to '{destDirectory}'."); - try - { - await DownloadRepositoryActionAsync(executionContext, archiveLink, destDirectory); - return; - } - catch (ActionNotFoundException) - { - Trace.Info($"Failed to find the action '{repositoryReference.Name}' at ref '{repositoryReference.Ref}' at {archiveLink}"); - continue; - } - } - throw new ActionNotFoundException($"Failed to find the action '{repositoryReference.Name}' at ref '{repositoryReference.Ref}'. Paths attempted: {string.Join(", ", archiveLinks)}"); - } - } - - private string GetApiUrl(IExecutionContext executionContext) - { - string apiUrl = executionContext.GetGitHubContext("api_url"); - if (!string.IsNullOrEmpty(apiUrl)) - { - return apiUrl; - } - // Once the api_url is set for hosted, we can remove this fallback (it doesn't make sense for GHES) - return "https://api.github.com"; - } - - private static string BuildLinkToActionArchive(string apiUrl, string repository, string @ref) - { #if OS_WINDOWS - return $"{apiUrl}/repos/{repository}/zipball/{@ref}"; + string archiveLink = $"https://api.github.com/repos/{repositoryReference.Name}/zipball/{repositoryReference.Ref}"; #else - return $"{apiUrl}/repos/{repository}/tarball/{@ref}"; + string archiveLink = $"https://api.github.com/repos/{repositoryReference.Name}/tarball/{repositoryReference.Ref}"; #endif - } + Trace.Info($"Download archive '{archiveLink}' to '{destDirectory}'."); - private async Task DownloadRepositoryActionAsync(IExecutionContext executionContext, string link, string destDirectory) - { //download and extract action in a temp folder and rename it on success string tempDirectory = Path.Combine(HostContext.GetDirectory(WellKnownDirectory.Actions), "_temp_" + Guid.NewGuid()); Directory.CreateDirectory(tempDirectory); + #if OS_WINDOWS string archiveFile = Path.Combine(tempDirectory, $"{Guid.NewGuid()}.zip"); #else string archiveFile = Path.Combine(tempDirectory, $"{Guid.NewGuid()}.tar.gz"); #endif - - Trace.Info($"Save archive '{link}' into {archiveFile}."); + Trace.Info($"Save archive '{archiveLink}' into {archiveFile}."); try { + int retryCount = 0; // Allow up to 20 * 60s for any action to be downloaded from github graph. @@ -590,76 +541,64 @@ namespace GitHub.Runner.Worker using (var httpClientHandler = HostContext.CreateHttpClientHandler()) using (var httpClient = new HttpClient(httpClientHandler)) { - var authToken = Environment.GetEnvironmentVariable("_GITHUB_ACTION_TOKEN"); - if (string.IsNullOrEmpty(authToken)) + var configurationStore = HostContext.GetService(); + var isHostedServer = configurationStore.GetSettings().IsHostedServer; + if (isHostedServer) { - // TODO: Deprecate the PREVIEW_ACTION_TOKEN - authToken = executionContext.Variables.Get("PREVIEW_ACTION_TOKEN"); - } - - if (!string.IsNullOrEmpty(authToken)) - { - HostContext.SecretMasker.AddValue(authToken); - var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"PAT:{authToken}")); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken); - } - else - { - var accessToken = executionContext.GetGitHubContext("token"); - var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"x-access-token:{accessToken}")); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken); - } - - httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents); - using (var response = await httpClient.GetAsync(link)) - { - if (response.IsSuccessStatusCode) + var authToken = Environment.GetEnvironmentVariable("_GITHUB_ACTION_TOKEN"); + if (string.IsNullOrEmpty(authToken)) { - using (var result = await response.Content.ReadAsStreamAsync()) - { - await result.CopyToAsync(fs, _defaultCopyBufferSize, actionDownloadCancellation.Token); - await fs.FlushAsync(actionDownloadCancellation.Token); - - // download succeed, break out the retry loop. - break; - } + // TODO: Deprecate the PREVIEW_ACTION_TOKEN + authToken = executionContext.Variables.Get("PREVIEW_ACTION_TOKEN"); } - else if (response.StatusCode == HttpStatusCode.NotFound) + + if (!string.IsNullOrEmpty(authToken)) { - // It doesn't make sense to retry in this case, so just stop - throw new ActionNotFoundException(new Uri(link)); + HostContext.SecretMasker.AddValue(authToken); + var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"PAT:{authToken}")); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken); } else { - // Something else bad happened, let's go to our retry logic - response.EnsureSuccessStatusCode(); + var accessToken = executionContext.GetGitHubContext("token"); + var base64EncodingToken = Convert.ToBase64String(Encoding.UTF8.GetBytes($"x-access-token:{accessToken}")); + httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodingToken); } } + else + { + // Intentionally empty. Temporary for GHES alpha release, download from dotcom unauthenticated. + } + + httpClient.DefaultRequestHeaders.UserAgent.AddRange(HostContext.UserAgents); + using (var result = await httpClient.GetStreamAsync(archiveLink)) + { + await result.CopyToAsync(fs, _defaultCopyBufferSize, actionDownloadCancellation.Token); + await fs.FlushAsync(actionDownloadCancellation.Token); + + // download succeed, break out the retry loop. + break; + } } } catch (OperationCanceledException) when (executionContext.CancellationToken.IsCancellationRequested) { - Trace.Info("Action download has been cancelled."); - throw; - } - catch (ActionNotFoundException) - { - Trace.Info($"The action at '{link}' does not exist"); + Trace.Info($"Action download has been cancelled."); throw; } catch (Exception ex) when (retryCount < 2) { retryCount++; - Trace.Error($"Fail to download archive '{link}' -- Attempt: {retryCount}"); + Trace.Error($"Fail to download archive '{archiveLink}' -- Attempt: {retryCount}"); Trace.Error(ex); if (actionDownloadTimeout.Token.IsCancellationRequested) { // action download didn't finish within timeout - executionContext.Warning($"Action '{link}' didn't finish download within {timeoutSeconds} seconds."); + executionContext.Warning($"Action '{archiveLink}' didn't finish download within {timeoutSeconds} seconds."); } else { - executionContext.Warning($"Failed to download action '{link}'. Error: {ex.Message}"); + executionContext.Warning($"Failed to download action '{archiveLink}'. Error {ex.Message}"); } } } @@ -673,7 +612,7 @@ namespace GitHub.Runner.Worker } ArgUtil.NotNullOrEmpty(archiveFile, nameof(archiveFile)); - executionContext.Debug($"Download '{link}' to '{archiveFile}'"); + executionContext.Debug($"Download '{archiveLink}' to '{archiveFile}'"); var stagingDirectory = Path.Combine(tempDirectory, "_staging"); Directory.CreateDirectory(stagingDirectory); @@ -723,7 +662,6 @@ namespace GitHub.Runner.Worker } Trace.Verbose("Create watermark file indicate action download succeed."); - string watermarkFile = GetWatermarkFilePath(destDirectory); File.WriteAllText(watermarkFile, DateTime.UtcNow.ToString()); executionContext.Debug($"Archive '{archiveFile}' has been unzipped into '{destDirectory}'."); @@ -748,8 +686,6 @@ namespace GitHub.Runner.Worker } } - private string GetWatermarkFilePath(string directory) => directory + ".completed"; - private ActionContainer PrepareRepositoryActionAsync(IExecutionContext executionContext, Pipelines.ActionStep repositoryAction) { var repositoryReference = repositoryAction.Reference as Pipelines.RepositoryPathReference; @@ -995,3 +931,4 @@ namespace GitHub.Runner.Worker public string ActionRepository { get; set; } } } + diff --git a/src/Runner.Worker/ActionNotFoundException.cs b/src/Runner.Worker/ActionNotFoundException.cs deleted file mode 100644 index 9e67af44f..000000000 --- a/src/Runner.Worker/ActionNotFoundException.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Runtime.Serialization; - -namespace GitHub.Runner.Worker -{ - public class ActionNotFoundException : Exception - { - public ActionNotFoundException(Uri actionUri) - : base(FormatMessage(actionUri)) - { - } - - public ActionNotFoundException(string message) - : base(message) - { - } - - public ActionNotFoundException(string message, System.Exception inner) - : base(message, inner) - { - } - - protected ActionNotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - - private static string FormatMessage(Uri actionUri) - { - return $"An action could not be found at the URI '{actionUri}'"; - } - } -} \ No newline at end of file diff --git a/src/Test/L0/RunnerWebProxyL0.cs b/src/Test/L0/RunnerWebProxyL0.cs index 3c1704f6c..b83371d6a 100644 --- a/src/Test/L0/RunnerWebProxyL0.cs +++ b/src/Test/L0/RunnerWebProxyL0.cs @@ -16,9 +16,7 @@ namespace GitHub.Runner.Common.Tests private static readonly List SkippedFiles = new List() { "Runner.Common\\HostContext.cs", - "Runner.Common/HostContext.cs", - "Runner.Common\\HttpClientHandlerFactory.cs", - "Runner.Common/HttpClientHandlerFactory.cs" + "Runner.Common/HostContext.cs" }; [Fact] diff --git a/src/Test/L0/Worker/ActionManagerL0.cs b/src/Test/L0/Worker/ActionManagerL0.cs index 90d203147..59d7ed17c 100644 --- a/src/Test/L0/Worker/ActionManagerL0.cs +++ b/src/Test/L0/Worker/ActionManagerL0.cs @@ -1,21 +1,19 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Net; -using System.Net.Http; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using GitHub.DistributedTask.Expressions2; +using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.Pipelines.ContextData; using GitHub.DistributedTask.WebApi; -using GitHub.Runner.Sdk; +using GitHub.Runner.Common.Util; using GitHub.Runner.Worker; using GitHub.Runner.Worker.Container; using Moq; -using Moq.Protected; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; using Xunit; using Pipelines = GitHub.DistributedTask.Pipelines; @@ -116,175 +114,47 @@ namespace GitHub.Runner.Common.Tests.Worker [Fact] [Trait("Level", "L0")] [Trait("Category", "Worker")] - public async void PrepareActions_DownloadBuiltInActionFromGraph_OnPremises() + public async void PrepareActions_SkipDownloadActionFromGraphWhenCached_OnPremises() { try { // Arrange Setup(); - const string ActionName = "actions/sample-action"; + var actionId = Guid.NewGuid(); var actions = new List { new Pipelines.ActionStep() { Name = "action", - Id = Guid.NewGuid(), + Id = actionId, Reference = new Pipelines.RepositoryPathReference() { - Name = ActionName, + Name = "actions/no-such-action", Ref = "master", RepositoryType = "GitHub" } } }; - - // Return a valid action from GHES via mock - const string ApiUrl = "https://ghes.example.com/api/v3"; - string expectedArchiveLink = GetLinkToActionArchive(ApiUrl, ActionName, "master"); - string archiveFile = await CreateRepoArchive(); - using var stream = File.OpenRead(archiveFile); - var mockClientHandler = new Mock(); - mockClientHandler.Protected().Setup>("SendAsync", ItExpr.Is(m => m.RequestUri == new Uri(expectedArchiveLink)), ItExpr.IsAny()) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) }); - - var mockHandlerFactory = new Mock(); - mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny())).Returns(mockClientHandler.Object); - _hc.SetSingleton(mockHandlerFactory.Object); - - _ec.Setup(x => x.GetGitHubContext("api_url")).Returns(ApiUrl); _configurationStore.Object.GetSettings().IsHostedServer = false; + var actionDirectory = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), "actions/no-such-action", "master"); + Directory.CreateDirectory(actionDirectory); + var watermarkFile = $"{actionDirectory}.completed"; + File.WriteAllText(watermarkFile, DateTime.UtcNow.ToString()); + var actionFile = Path.Combine(actionDirectory, "action.yml"); + File.WriteAllText(actionFile, @" +name: ""no-such-action"" +runs: + using: node12 + main: no-such-action.js +"); + var testFile = Path.Combine(actionDirectory, "test-file"); + File.WriteAllText(testFile, "asdf"); - //Act + // Act await _actionManager.PrepareActionsAsync(_ec.Object, actions); - //Assert - var watermarkFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), ActionName, "master.completed"); - Assert.True(File.Exists(watermarkFile)); - - var actionYamlFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), ActionName, "master", "action.yml"); - Assert.True(File.Exists(actionYamlFile)); - _hc.GetTrace().Info(File.ReadAllText(actionYamlFile)); - } - finally - { - Teardown(); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Worker")] - public async void PrepareActions_DownloadCommunityActionFromGraph_OnPremises() - { - try - { - // Arrange - Setup(); - const string ActionName = "ownerName/sample-action"; - const string MungedActionName = "actions-community/ownerName-sample-action"; - var actions = new List - { - new Pipelines.ActionStep() - { - Name = "action", - Id = Guid.NewGuid(), - Reference = new Pipelines.RepositoryPathReference() - { - Name = ActionName, - Ref = "master", - RepositoryType = "GitHub" - } - } - }; - - // Return a valid action from GHES via mock - const string ApiUrl = "https://ghes.example.com/api/v3"; - string builtInArchiveLink = GetLinkToActionArchive(ApiUrl, ActionName, "master"); - string mungedArchiveLink = GetLinkToActionArchive(ApiUrl, MungedActionName, "master"); - string archiveFile = await CreateRepoArchive(); - using var stream = File.OpenRead(archiveFile); - var mockClientHandler = new Mock(); - mockClientHandler.Protected().Setup>("SendAsync", ItExpr.Is(m => m.RequestUri == new Uri(builtInArchiveLink)), ItExpr.IsAny()) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NotFound)); - mockClientHandler.Protected().Setup>("SendAsync", ItExpr.Is(m => m.RequestUri == new Uri(mungedArchiveLink)), ItExpr.IsAny()) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) }); - - var mockHandlerFactory = new Mock(); - mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny())).Returns(mockClientHandler.Object); - _hc.SetSingleton(mockHandlerFactory.Object); - - _ec.Setup(x => x.GetGitHubContext("api_url")).Returns(ApiUrl); - _configurationStore.Object.GetSettings().IsHostedServer = false; - - //Act - await _actionManager.PrepareActionsAsync(_ec.Object, actions); - - //Assert - var watermarkFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), ActionName, "master.completed"); - Assert.True(File.Exists(watermarkFile)); - - var actionYamlFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), ActionName, "master", "action.yml"); - Assert.True(File.Exists(actionYamlFile)); - _hc.GetTrace().Info(File.ReadAllText(actionYamlFile)); - } - finally - { - Teardown(); - } - } - - [Fact] - [Trait("Level", "L0")] - [Trait("Category", "Worker")] - public async void PrepareActions_DownloadUnknownActionFromGraph_OnPremises() - { - try - { - // Arrange - Setup(); - const string ActionName = "ownerName/sample-action"; - var actions = new List - { - new Pipelines.ActionStep() - { - Name = "action", - Id = Guid.NewGuid(), - Reference = new Pipelines.RepositoryPathReference() - { - Name = ActionName, - Ref = "master", - RepositoryType = "GitHub" - } - } - }; - - // Return a valid action from GHES via mock - const string ApiUrl = "https://ghes.example.com/api/v3"; - string archiveLink = GetLinkToActionArchive(ApiUrl, ActionName, "master"); - string archiveFile = await CreateRepoArchive(); - using var stream = File.OpenRead(archiveFile); - var mockClientHandler = new Mock(); - mockClientHandler.Protected().Setup>("SendAsync", ItExpr.IsAny(), ItExpr.IsAny()) - .ReturnsAsync(new HttpResponseMessage(HttpStatusCode.NotFound)); - - var mockHandlerFactory = new Mock(); - mockHandlerFactory.Setup(p => p.CreateClientHandler(It.IsAny())).Returns(mockClientHandler.Object); - _hc.SetSingleton(mockHandlerFactory.Object); - - _ec.Setup(x => x.GetGitHubContext("api_url")).Returns(ApiUrl); - _configurationStore.Object.GetSettings().IsHostedServer = false; - - //Act - Func action = async () => await _actionManager.PrepareActionsAsync(_ec.Object, actions); - - //Assert - await Assert.ThrowsAsync(action); - - var watermarkFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), ActionName, "master.completed"); - Assert.False(File.Exists(watermarkFile)); - - var actionYamlFile = Path.Combine(_hc.GetDirectory(WellKnownDirectory.Actions), ActionName, "master", "action.yml"); - Assert.False(File.Exists(actionYamlFile)); + // Assert + Assert.True(File.Exists(testFile)); } finally { @@ -992,7 +862,7 @@ namespace GitHub.Runner.Common.Tests.Worker name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1092,7 +962,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1191,7 +1061,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1259,7 +1129,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1341,7 +1211,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1440,7 +1310,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1538,7 +1408,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1606,7 +1476,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1677,7 +1547,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'GitHub' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1777,7 +1647,7 @@ runs: name: 'Hello World' description: 'Greet the world and record the time' author: 'Test Corporation' -inputs: +inputs: greeting: # id of input description: 'The greeting we choose - will print ""{greeting}, World!"" on stdout' required: true @@ -1867,82 +1737,6 @@ runs: }; } - /// - /// Creates a sample action in an archive on disk, similar to the archive - /// retrieved from GitHub's or GHES' repository API. - /// - /// The path on disk to the archive. -#if OS_WINDOWS - private Task CreateRepoArchive() -#else - private async Task CreateRepoArchive() -#endif - { - const string Content = @" -# Container action -name: 'Hello World' -description: 'Greet the world' -author: 'GitHub' -icon: 'hello.svg' # vector art to display in the GitHub Marketplace -color: 'green' # optional, decorates the entry in the GitHub Marketplace -runs: - using: 'node12' - main: 'task.js' -"; - CreateAction(yamlContent: Content, instance: out _, directory: out string directory); - - var tempDir = _hc.GetDirectory(WellKnownDirectory.Temp); - Directory.CreateDirectory(tempDir); - var archiveFile = Path.Combine(tempDir, Path.GetRandomFileName()); - var trace = _hc.GetTrace(); - -#if OS_WINDOWS - ZipFile.CreateFromDirectory(directory, archiveFile, CompressionLevel.Fastest, includeBaseDirectory: true); - return Task.FromResult(archiveFile); -#else - string tar = WhichUtil.Which("tar", require: true, trace: trace); - - // tar -xzf - using (var processInvoker = new ProcessInvokerWrapper()) - { - processInvoker.Initialize(_hc); - processInvoker.OutputDataReceived += new EventHandler((sender, args) => - { - if (!string.IsNullOrEmpty(args.Data)) - { - trace.Info(args.Data); - } - }); - - processInvoker.ErrorDataReceived += new EventHandler((sender, args) => - { - if (!string.IsNullOrEmpty(args.Data)) - { - trace.Error(args.Data); - } - }); - - string cwd = Path.GetDirectoryName(directory); - string inputDirectory = Path.GetFileName(directory); - int exitCode = await processInvoker.ExecuteAsync(_hc.GetDirectory(WellKnownDirectory.Bin), tar, $"-czf \"{archiveFile}\" -C \"{cwd}\" \"{inputDirectory}\"", null, CancellationToken.None); - if (exitCode != 0) - { - throw new NotSupportedException($"Can't use 'tar -czf' to create archive file: {archiveFile}. return code: {exitCode}."); - } - } - return archiveFile; -#endif - } - - private static string GetLinkToActionArchive(string apiUrl, string repository, string @ref) - { -#if OS_WINDOWS - return $"{apiUrl}/repos/{repository}/zipball/{@ref}"; -#else - return $"{apiUrl}/repos/{repository}/tarball/{@ref}"; -#endif - } - private void Setup([CallerMemberName] string name = "") { _ecTokenSource?.Dispose(); @@ -1978,7 +1772,6 @@ runs: _hc.SetSingleton(_dockerManager.Object); _hc.SetSingleton(_pluginManager.Object); _hc.SetSingleton(actionManifest); - _hc.SetSingleton(new HttpClientHandlerFactory()); _configurationStore = new Mock(); _configurationStore