From 01fd04464d931699c6989f7c366a5ff3e155fe56 Mon Sep 17 00:00:00 2001 From: Nikola Jokic <97525037+nikola-jokic@users.noreply.github.com> Date: Tue, 23 Aug 2022 07:42:29 -0700 Subject: [PATCH 01/22] Escaping key and quoting it to avoid key based command injection (#2062) * escaping key and quoting it to avoid key based command injection * extracted creation of flags to DockerUtil, with testing included --- .../Container/DockerCommandManager.cs | 6 +-- src/Runner.Worker/Container/DockerUtil.cs | 25 ++++++++- src/Runner.Worker/Handlers/StepHost.cs | 4 +- src/Test/L0/Container/DockerUtilL0.cs | 54 +++++++++++++++++++ 4 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/Runner.Worker/Container/DockerCommandManager.cs b/src/Runner.Worker/Container/DockerCommandManager.cs index 86cf0eeedf2..a0c158bdf68 100644 --- a/src/Runner.Worker/Container/DockerCommandManager.cs +++ b/src/Runner.Worker/Container/DockerCommandManager.cs @@ -131,11 +131,11 @@ public async Task DockerCreate(IExecutionContext context, ContainerInfo { if (String.IsNullOrEmpty(env.Value)) { - dockerOptions.Add($"-e \"{env.Key}\""); + dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key)); } else { - dockerOptions.Add($"-e \"{env.Key}={env.Value.Replace("\"", "\\\"")}\""); + dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key, env.Value)); } } @@ -202,7 +202,7 @@ public async Task DockerRun(IExecutionContext context, ContainerInfo contai { // e.g. -e MY_SECRET maps the value into the exec'ed process without exposing // the value directly in the command - dockerOptions.Add($"-e {env.Key}"); + dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key)); } // Watermark for GitHub Action environment diff --git a/src/Runner.Worker/Container/DockerUtil.cs b/src/Runner.Worker/Container/DockerUtil.cs index 02c2ece5b79..bde59f5b641 100644 --- a/src/Runner.Worker/Container/DockerUtil.cs +++ b/src/Runner.Worker/Container/DockerUtil.cs @@ -17,7 +17,7 @@ public static List ParseDockerPort(IList portMappingLines) string pattern = $"^(?<{targetPort}>\\d+)/(?<{proto}>\\w+) -> (?<{host}>.+):(?<{hostPort}>\\d+)$"; List portMappings = new List(); - foreach(var line in portMappingLines) + foreach (var line in portMappingLines) { Match m = Regex.Match(line, pattern, RegexOptions.None, TimeSpan.FromSeconds(1)); if (m.Success) @@ -61,5 +61,28 @@ public static string ParseRegistryHostnameFromImageName(string name) } return ""; } + + public static string CreateEscapedOption(string flag, string key) + { + if (String.IsNullOrEmpty(key)) + { + return ""; + } + return $"{flag} \"{EscapeString(key)}\""; + } + + public static string CreateEscapedOption(string flag, string key, string value) + { + if (String.IsNullOrEmpty(key)) + { + return ""; + } + return $"{flag} \"{EscapeString(key)}={EscapeString(value)}\""; + } + + private static string EscapeString(string value) + { + return value.Replace("\\", "\\\\").Replace("\"", "\\\""); + } } } diff --git a/src/Runner.Worker/Handlers/StepHost.cs b/src/Runner.Worker/Handlers/StepHost.cs index 95feaca9aef..1270dd90e6f 100644 --- a/src/Runner.Worker/Handlers/StepHost.cs +++ b/src/Runner.Worker/Handlers/StepHost.cs @@ -193,7 +193,7 @@ public async Task ExecuteAsync(IExecutionContext context, TranslateToContainerPath(environment); await containerHookManager.RunScriptStepAsync(context, Container, - workingDirectory, + workingDirectory, fileName, arguments, environment, @@ -216,7 +216,7 @@ await containerHookManager.RunScriptStepAsync(context, { // e.g. -e MY_SECRET maps the value into the exec'ed process without exposing // the value directly in the command - dockerCommandArgs.Add($"-e {env.Key}"); + dockerCommandArgs.Add(DockerUtil.CreateEscapedOption("-e", env.Key)); } if (!string.IsNullOrEmpty(PrependPath)) { diff --git a/src/Test/L0/Container/DockerUtilL0.cs b/src/Test/L0/Container/DockerUtilL0.cs index c069255a85c..e5ae05fda72 100644 --- a/src/Test/L0/Container/DockerUtilL0.cs +++ b/src/Test/L0/Container/DockerUtilL0.cs @@ -144,5 +144,59 @@ public void ParseRegistryHostnameFromImageName(string input, string expected) var actual = DockerUtil.ParseRegistryHostnameFromImageName(input); Assert.Equal(expected, actual); } + + [Theory] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + [InlineData("", "")] + [InlineData("HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #")] + [InlineData("HOME \"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \"\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #")] + public void CreateEscapedOption_keyOnly(string input, string escaped) + { + var flag = "--example"; + var actual = DockerUtil.CreateEscapedOption(flag, input); + string expected; + if (String.IsNullOrEmpty(input)) + { + expected = ""; + } + else + { + expected = $"{flag} \"{escaped}\""; + } + Assert.Equal(expected, actual); + } + + [Theory] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + [InlineData("HOME", "", "HOME", "")] + [InlineData("HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #")] + [InlineData("HOME \"alpine:3.8 sh -c id #", "HOME \"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \\\"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \"\"alpine:3.8 sh -c id #", "HOME \"\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #")] + [InlineData("HOME \"\\\"alpine:3.8 sh -c id #", "HOME \"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #")] + public void CreateEscapedOption_keyValue(string keyInput, string valueInput, string escapedKey, string escapedValue) + { + var flag = "--example"; + var actual = DockerUtil.CreateEscapedOption(flag, keyInput, valueInput); + string expected; + if (String.IsNullOrEmpty(keyInput)) + { + expected = ""; + } + else + { + expected = $"{flag} \"{escapedKey}={escapedValue}\""; + } + Assert.Equal(expected, actual); + } } } From cba19c4d7e1cf8071a4b4f7e24de98eb3d0e6d0f Mon Sep 17 00:00:00 2001 From: Ava Stancu Date: Tue, 23 Aug 2022 16:42:40 +0200 Subject: [PATCH 02/22] Release notes for 2.296.0 (#2078) * Update releaseNote.md * Update runnerversion --- releaseNote.md | 12 +++++------- src/runnerversion | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/releaseNote.md b/releaseNote.md index ae05e6dc92f..91255a46fae 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -1,11 +1,9 @@ -## Features -- GHES: Support connecting to GitHub Enterprise Server Actions Service on a subdomain ## Bugs -- Fixed a bug where GITHUB_ENV would not update correctly between composite action steps (#1794) -- Fixed runner update bug caused by `update.sh|cmd` running too long (#2044) +- Avoid key based command injection via Docker command arguments (#2062) ## Misc -- Bump Newtonsoft.Json from 11.0.2 to 13.0.1 (#2012) -- Change a periodic token expiry log message level from `WARNING` to `VERBOSE` (#2021) +- Added step context name and start/finish time in step telemetry (#2069) +- Improved error logs when there is a missing 'using' token configuration in the metadata file (#2052) +- Added full job name and nested workflow details in log (#2049) ## Windows x64 We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows. @@ -32,7 +30,7 @@ curl -O -L https://github.com/actions/runner/releases/download/v tar xzf ./actions-runner-osx-x64-.tar.gz ``` -## [Pre-release] OSX arm64 (Apple silicon) +## OSX arm64 (Apple silicon) ``` bash # Create a folder diff --git a/src/runnerversion b/src/runnerversion index ea0fe6c4e2c..d1ad399cbf4 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.295.0 +2.296.0 From 59894790de7eae8950ef010af114281f4e9fce69 Mon Sep 17 00:00:00 2001 From: Konrad Pabjan Date: Wed, 24 Aug 2022 16:02:51 -0400 Subject: [PATCH 03/22] Validate lines and columns for Annotations (#2082) --- src/Runner.Worker/ActionCommandManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Runner.Worker/ActionCommandManager.cs b/src/Runner.Worker/ActionCommandManager.cs index 0bcde5f5354..a705d67ed40 100644 --- a/src/Runner.Worker/ActionCommandManager.cs +++ b/src/Runner.Worker/ActionCommandManager.cs @@ -585,6 +585,8 @@ public abstract class IssueCommandExtension : RunnerService, IActionCommandExten public void ProcessCommand(IExecutionContext context, string inputLine, ActionCommand command, ContainerInfo container) { + ValidateLinesAndColumns(command, context); + command.Properties.TryGetValue(IssueCommandProperties.File, out string file); command.Properties.TryGetValue(IssueCommandProperties.Line, out string line); command.Properties.TryGetValue(IssueCommandProperties.Column, out string column); From 95459dea5f9a131ec084e2e2b53e8c87f61db81e Mon Sep 17 00:00:00 2001 From: Nikola Jokic <97525037+nikola-jokic@users.noreply.github.com> Date: Wed, 31 Aug 2022 10:39:58 -0700 Subject: [PATCH 04/22] docker: escape key-value pair as -e KEY and VALUE being environment var (#2091) * docker: escape key-value pair as -e KEY and VALUE being environment var * removed code duplication, removed unused method and test --- .../Container/DockerCommandManager.cs | 13 ++++++--- src/Runner.Worker/Container/DockerUtil.cs | 9 ------- src/Test/L0/Container/DockerUtilL0.cs | 27 ------------------- 3 files changed, 10 insertions(+), 39 deletions(-) diff --git a/src/Runner.Worker/Container/DockerCommandManager.cs b/src/Runner.Worker/Container/DockerCommandManager.cs index a0c158bdf68..4d4940c9752 100644 --- a/src/Runner.Worker/Container/DockerCommandManager.cs +++ b/src/Runner.Worker/Container/DockerCommandManager.cs @@ -107,6 +107,7 @@ public async Task DockerBuild(IExecutionContext context, string workingDire public async Task DockerCreate(IExecutionContext context, ContainerInfo container) { IList dockerOptions = new List(); + IDictionary environment = new Dictionary(); // OPTIONS dockerOptions.Add($"--name {container.ContainerDisplayName}"); dockerOptions.Add($"--label {DockerInstanceLabel}"); @@ -135,7 +136,8 @@ public async Task DockerCreate(IExecutionContext context, ContainerInfo } else { - dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key, env.Value)); + environment.Add(env.Key, env.Value); + dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key)); } } @@ -183,7 +185,7 @@ public async Task DockerCreate(IExecutionContext context, ContainerInfo dockerOptions.Add($"{container.ContainerEntryPointArgs}"); var optionsString = string.Join(" ", dockerOptions); - List outputStrings = await ExecuteDockerCommandAsync(context, "create", optionsString); + List outputStrings = await ExecuteDockerCommandAsync(context, "create", optionsString, environment); return outputStrings.FirstOrDefault(); } @@ -443,6 +445,11 @@ public Task DockerLogin(IExecutionContext context, string configFileDirecto } private async Task> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options) + { + return await ExecuteDockerCommandAsync(context, command, options, null); + } + + private async Task> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary environment) { string arg = $"{command} {options}".Trim(); context.Command($"{DockerPath} {arg}"); @@ -470,7 +477,7 @@ await processInvoker.ExecuteAsync( workingDirectory: context.GetGitHubContext("workspace"), fileName: DockerPath, arguments: arg, - environment: null, + environment: environment, requireExitCodeZero: true, outputEncoding: null, cancellationToken: CancellationToken.None); diff --git a/src/Runner.Worker/Container/DockerUtil.cs b/src/Runner.Worker/Container/DockerUtil.cs index bde59f5b641..e1ae6d3eeb4 100644 --- a/src/Runner.Worker/Container/DockerUtil.cs +++ b/src/Runner.Worker/Container/DockerUtil.cs @@ -71,15 +71,6 @@ public static string CreateEscapedOption(string flag, string key) return $"{flag} \"{EscapeString(key)}\""; } - public static string CreateEscapedOption(string flag, string key, string value) - { - if (String.IsNullOrEmpty(key)) - { - return ""; - } - return $"{flag} \"{EscapeString(key)}={EscapeString(value)}\""; - } - private static string EscapeString(string value) { return value.Replace("\\", "\\\\").Replace("\"", "\\\""); diff --git a/src/Test/L0/Container/DockerUtilL0.cs b/src/Test/L0/Container/DockerUtilL0.cs index e5ae05fda72..843aaf5efd1 100644 --- a/src/Test/L0/Container/DockerUtilL0.cs +++ b/src/Test/L0/Container/DockerUtilL0.cs @@ -171,32 +171,5 @@ public void CreateEscapedOption_keyOnly(string input, string escaped) } Assert.Equal(expected, actual); } - - [Theory] - [Trait("Level", "L0")] - [Trait("Category", "Worker")] - [InlineData("HOME", "", "HOME", "")] - [InlineData("HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #")] - [InlineData("HOME \"alpine:3.8 sh -c id #", "HOME \"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \\\"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \"\"alpine:3.8 sh -c id #", "HOME \"\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \"\\\"alpine:3.8 sh -c id #", "HOME \"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #")] - public void CreateEscapedOption_keyValue(string keyInput, string valueInput, string escapedKey, string escapedValue) - { - var flag = "--example"; - var actual = DockerUtil.CreateEscapedOption(flag, keyInput, valueInput); - string expected; - if (String.IsNullOrEmpty(keyInput)) - { - expected = ""; - } - else - { - expected = $"{flag} \"{escapedKey}={escapedValue}\""; - } - Assert.Equal(expected, actual); - } } } From 5e0c2ef8165ef645e165286e90ce460c1aa17b3c Mon Sep 17 00:00:00 2001 From: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com> Date: Fri, 2 Sep 2022 17:43:22 +0200 Subject: [PATCH 05/22] 2.296.1 Release (#2092) (#2099) * docker: escape key-value pair as -e KEY and VALUE being environment var * removed code duplication, removed unused method and test * add release notes Co-authored-by: Nikola Jokic Co-authored-by: Thomas Boop <52323235+thboop@users.noreply.github.com> Co-authored-by: Nikola Jokic --- releaseNote.md | 5 +---- src/runnerversion | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/releaseNote.md b/releaseNote.md index 91255a46fae..a6cb9c027f8 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -1,9 +1,6 @@ ## Bugs -- Avoid key based command injection via Docker command arguments (#2062) +- Fixed an issue where job and service container envs were corrupted (#2091) ## Misc -- Added step context name and start/finish time in step telemetry (#2069) -- Improved error logs when there is a missing 'using' token configuration in the metadata file (#2052) -- Added full job name and nested workflow details in log (#2049) ## Windows x64 We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows. diff --git a/src/runnerversion b/src/runnerversion index d1ad399cbf4..f7b71d4819b 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.296.0 +2.296.1 From 75786756bbe951b2a1ee3ca9e506888e61af7428 Mon Sep 17 00:00:00 2001 From: Nikola Jokic <97525037+nikola-jokic@users.noreply.github.com> Date: Tue, 6 Sep 2022 07:45:00 -0700 Subject: [PATCH 06/22] fix ACTIONS_RUNNER_CONTAINER_HOOKS name in ADR (#2098) --- docs/adrs/1891-container-hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adrs/1891-container-hooks.md b/docs/adrs/1891-container-hooks.md index 1ab14d85fcd..5c905e40588 100644 --- a/docs/adrs/1891-container-hooks.md +++ b/docs/adrs/1891-container-hooks.md @@ -16,7 +16,7 @@ We should give them that option, and publish examples how how they can create th - For example, the current runner overrides `HOME`, we can do that in the hook, but we shouldn't pass that hook as an ENV with the other env's the user has set, as that is not user input, it is how the runner invokes containers ## Interface -- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOK=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler. +- You will set the variable `ACTIONS_RUNNER_CONTAINER_HOOKS=/Users/foo/runner/hooks.js` which is the entrypoint to your hook handler. - There is no partial opt in, you must handle every hook - We will pass a command and some args via `stdin` - An exit code of 0 is a success, every other exit code is a failure From ed191b78ae33fb3dbc23b0135a9c4e355163dd31 Mon Sep 17 00:00:00 2001 From: Thomas Boop <52323235+thboop@users.noreply.github.com> Date: Fri, 9 Sep 2022 14:32:07 -0400 Subject: [PATCH 07/22] Port hotfix to main branch (#2108) * fix issue with env's overwriting environment * add release notes * handle value escaping * compile regex for runtime perf improvements --- releaseNote.md | 2 +- .../Container/DockerCommandManager.cs | 13 ++----- src/Runner.Worker/Container/DockerUtil.cs | 32 +++++++++++++++-- src/Test/L0/Container/DockerUtilL0.cs | 36 +++++++++++++++---- src/runnerversion | 2 +- 5 files changed, 64 insertions(+), 21 deletions(-) diff --git a/releaseNote.md b/releaseNote.md index a6cb9c027f8..b70766e7098 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -1,5 +1,5 @@ ## Bugs -- Fixed an issue where job and service container envs were corrupted (#2091) +- Fixed an issue where self hosted environments had their docker env's overwritten (#2107) ## Misc ## Windows x64 diff --git a/src/Runner.Worker/Container/DockerCommandManager.cs b/src/Runner.Worker/Container/DockerCommandManager.cs index 4d4940c9752..a0c158bdf68 100644 --- a/src/Runner.Worker/Container/DockerCommandManager.cs +++ b/src/Runner.Worker/Container/DockerCommandManager.cs @@ -107,7 +107,6 @@ public async Task DockerBuild(IExecutionContext context, string workingDire public async Task DockerCreate(IExecutionContext context, ContainerInfo container) { IList dockerOptions = new List(); - IDictionary environment = new Dictionary(); // OPTIONS dockerOptions.Add($"--name {container.ContainerDisplayName}"); dockerOptions.Add($"--label {DockerInstanceLabel}"); @@ -136,8 +135,7 @@ public async Task DockerCreate(IExecutionContext context, ContainerInfo } else { - environment.Add(env.Key, env.Value); - dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key)); + dockerOptions.Add(DockerUtil.CreateEscapedOption("-e", env.Key, env.Value)); } } @@ -185,7 +183,7 @@ public async Task DockerCreate(IExecutionContext context, ContainerInfo dockerOptions.Add($"{container.ContainerEntryPointArgs}"); var optionsString = string.Join(" ", dockerOptions); - List outputStrings = await ExecuteDockerCommandAsync(context, "create", optionsString, environment); + List outputStrings = await ExecuteDockerCommandAsync(context, "create", optionsString); return outputStrings.FirstOrDefault(); } @@ -445,11 +443,6 @@ public Task DockerLogin(IExecutionContext context, string configFileDirecto } private async Task> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options) - { - return await ExecuteDockerCommandAsync(context, command, options, null); - } - - private async Task> ExecuteDockerCommandAsync(IExecutionContext context, string command, string options, IDictionary environment) { string arg = $"{command} {options}".Trim(); context.Command($"{DockerPath} {arg}"); @@ -477,7 +470,7 @@ await processInvoker.ExecuteAsync( workingDirectory: context.GetGitHubContext("workspace"), fileName: DockerPath, arguments: arg, - environment: environment, + environment: null, requireExitCodeZero: true, outputEncoding: null, cancellationToken: CancellationToken.None); diff --git a/src/Runner.Worker/Container/DockerUtil.cs b/src/Runner.Worker/Container/DockerUtil.cs index e1ae6d3eeb4..97a53759bc7 100644 --- a/src/Runner.Worker/Container/DockerUtil.cs +++ b/src/Runner.Worker/Container/DockerUtil.cs @@ -6,6 +6,9 @@ namespace GitHub.Runner.Worker.Container { public class DockerUtil { + private static readonly Regex QuoteEscape = new Regex(@"(\\*)" + "\"", RegexOptions.Compiled); + private static readonly Regex EndOfStringEscape = new Regex(@"(\\+)$", RegexOptions.Compiled); + public static List ParseDockerPort(IList portMappingLines) { const string targetPort = "targetPort"; @@ -68,12 +71,37 @@ public static string CreateEscapedOption(string flag, string key) { return ""; } - return $"{flag} \"{EscapeString(key)}\""; + return $"{flag} {EscapeString(key)}"; + } + + public static string CreateEscapedOption(string flag, string key, string value) + { + if (String.IsNullOrEmpty(key)) + { + return ""; + } + var escapedString = EscapeString($"{key}={value}"); + return $"{flag} {escapedString}"; } private static string EscapeString(string value) { - return value.Replace("\\", "\\\\").Replace("\"", "\\\""); + if (String.IsNullOrEmpty(value)) + { + return ""; + } + // Dotnet escaping rules are weird here, we can only escape \ if it precedes a " + // If a double quotation mark follows two or an even number of backslashes, each proceeding backslash pair is replaced with one backslash and the double quotation mark is removed. + // If a double quotation mark follows an odd number of backslashes, including just one, each preceding pair is replaced with one backslash and the remaining backslash is removed; however, in this case the double quotation mark is not removed. + // https://docs.microsoft.com/en-us/dotnet/api/system.environment.getcommandlineargs?redirectedfrom=MSDN&view=net-6.0#remarks + + // First, find any \ followed by a " and double the number of \ + 1. + value = QuoteEscape.Replace(value, @"$1$1\" + "\""); + // Next, what if it ends in `\`, it would escape the end quote. So, we need to detect that at the end of the string and perform the same escape + // Luckily, we can just use the $ character with detects the end of string in regex + value = EndOfStringEscape.Replace(value, @"$1$1"); + // Finally, wrap it in quotes + return $"\"{value}\""; } } } diff --git a/src/Test/L0/Container/DockerUtilL0.cs b/src/Test/L0/Container/DockerUtilL0.cs index 843aaf5efd1..1e45d598e89 100644 --- a/src/Test/L0/Container/DockerUtilL0.cs +++ b/src/Test/L0/Container/DockerUtilL0.cs @@ -149,13 +149,12 @@ public void ParseRegistryHostnameFromImageName(string input, string expected) [Trait("Level", "L0")] [Trait("Category", "Worker")] [InlineData("", "")] - [InlineData("HOME alpine:3.8 sh -c id #", "HOME alpine:3.8 sh -c id #")] - [InlineData("HOME \"alpine:3.8 sh -c id #", "HOME \\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \\\"alpine:3.8 sh -c id #", "HOME \\\\\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \\\\\"alpine:3.8 sh -c id #", "HOME \\\\\\\\\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \"\"alpine:3.8 sh -c id #", "HOME \\\"\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \\\"\"alpine:3.8 sh -c id #", "HOME \\\\\\\"\\\"alpine:3.8 sh -c id #")] - [InlineData("HOME \"\\\"alpine:3.8 sh -c id #", "HOME \\\"\\\\\\\"alpine:3.8 sh -c id #")] + [InlineData("foo", "foo")] + [InlineData("foo \\ bar", "foo \\ bar")] + [InlineData("foo \\", "foo \\\\")] + [InlineData("foo \\\\", "foo \\\\\\\\")] + [InlineData("foo \\\" bar", "foo \\\\\\\" bar")] + [InlineData("foo \\\\\" bar", "foo \\\\\\\\\\\" bar")] public void CreateEscapedOption_keyOnly(string input, string escaped) { var flag = "--example"; @@ -171,5 +170,28 @@ public void CreateEscapedOption_keyOnly(string input, string escaped) } Assert.Equal(expected, actual); } + + [Theory] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + [InlineData("foo", "bar", "foo=bar")] + [InlineData("foo\\", "bar", "foo\\=bar")] + [InlineData("foo\\", "bar\\", "foo\\=bar\\\\")] + [InlineData("foo \\","bar \\", "foo \\=bar \\\\")] + public void CreateEscapedOption_keyValue(string keyInput, string valueInput, string escapedString) + { + var flag = "--example"; + var actual = DockerUtil.CreateEscapedOption(flag, keyInput, valueInput); + string expected; + if (String.IsNullOrEmpty(keyInput)) + { + expected = ""; + } + else + { + expected = $"{flag} \"{escapedString}\""; + } + Assert.Equal(expected, actual); + } } } diff --git a/src/runnerversion b/src/runnerversion index f7b71d4819b..ffb30427c2f 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.296.1 +2.296.2 From 6e6410d300760046f2df8ee90a57b0c3fb0d322b Mon Sep 17 00:00:00 2001 From: Stefan Ruvceski <96768603+ruvceskistefan@users.noreply.github.com> Date: Mon, 12 Sep 2022 20:51:36 +0200 Subject: [PATCH 08/22] fix for issue #2009 - composite summary file (#2077) --- src/Runner.Worker/FileCommandManager.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Runner.Worker/FileCommandManager.cs b/src/Runner.Worker/FileCommandManager.cs index a55050de13b..145291ccd4f 100644 --- a/src/Runner.Worker/FileCommandManager.cs +++ b/src/Runner.Worker/FileCommandManager.cs @@ -68,7 +68,7 @@ public void ProcessFiles(IExecutionContext context, ContainerInfo container) { try { - fileCommand.ProcessCommand(context, Path.Combine(_fileCommandDirectory, fileCommand.FilePrefix + _fileSuffix),container); + fileCommand.ProcessCommand(context, Path.Combine(_fileCommandDirectory, fileCommand.FilePrefix + _fileSuffix), container); } catch (Exception ex) { @@ -118,7 +118,7 @@ public void ProcessCommand(IExecutionContext context, string filePath, Container if (File.Exists(filePath)) { var lines = File.ReadAllLines(filePath, Encoding.UTF8); - foreach(var line in lines) + foreach (var line in lines) { if (line == string.Empty) { @@ -312,7 +312,9 @@ public void ProcessCommand(IExecutionContext context, string filePath, Container } } - var attachmentName = context.Id.ToString(); + var attachmentName = !context.IsEmbedded + ? context.Id.ToString() + : context.EmbeddedId.ToString(); Trace.Info($"Queueing file ({filePath}) for attachment upload ({attachmentName})"); // Attachments must be added to the parent context (job), not the current context (step) From 32845a5448e3687b863303807cc58de402604ce5 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Thu, 15 Sep 2022 10:43:28 +0100 Subject: [PATCH 09/22] Bump @actions/core from 1.2.6 to 1.9.1 in /src/Misc/expressionFunc/hashFiles (#2123) --- src/Misc/expressionFunc/hashFiles/README.md | 5 +- .../hashFiles/package-lock.json | 62 +- src/Misc/layoutbin/hashFiles/index.js | 2618 ++++++++++++++++- 3 files changed, 2526 insertions(+), 159 deletions(-) diff --git a/src/Misc/expressionFunc/hashFiles/README.md b/src/Misc/expressionFunc/hashFiles/README.md index 6283ee8b0d4..c23d01e6efb 100644 --- a/src/Misc/expressionFunc/hashFiles/README.md +++ b/src/Misc/expressionFunc/hashFiles/README.md @@ -1 +1,4 @@ -To update hashFiles under `Misc/layoutbin` run `npm install && npm run all` \ No newline at end of file +To compile this package (output will be stored in `Misc/layoutbin`) run `npm install && npm run all`. + +> Note: this package also needs to be recompiled for dependabot PRs updating one of +> its dependencies. diff --git a/src/Misc/expressionFunc/hashFiles/package-lock.json b/src/Misc/expressionFunc/hashFiles/package-lock.json index 272830a94d7..c584d01b315 100644 --- a/src/Misc/expressionFunc/hashFiles/package-lock.json +++ b/src/Misc/expressionFunc/hashFiles/package-lock.json @@ -22,9 +22,13 @@ } }, "node_modules/@actions/core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", - "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } }, "node_modules/@actions/glob": { "version": "0.1.0", @@ -35,6 +39,14 @@ "minimatch": "^3.0.4" } }, + "node_modules/@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "dependencies": { + "tunnel": "^0.0.6" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", @@ -2381,6 +2393,14 @@ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -2442,6 +2462,14 @@ "punycode": "^2.1.0" } }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", @@ -2503,9 +2531,13 @@ }, "dependencies": { "@actions/core": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz", - "integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", + "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "requires": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } }, "@actions/glob": { "version": "0.1.0", @@ -2516,6 +2548,14 @@ "minimatch": "^3.0.4" } }, + "@actions/http-client": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz", + "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==", + "requires": { + "tunnel": "^0.0.6" + } + }, "@eslint/eslintrc": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", @@ -4189,6 +4229,11 @@ "tslib": "^1.8.1" } }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4231,6 +4276,11 @@ "punycode": "^2.1.0" } }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, "v8-compile-cache": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", diff --git a/src/Misc/layoutbin/hashFiles/index.js b/src/Misc/layoutbin/hashFiles/index.js index 912b3c45be4..e0bf2f96b47 100644 --- a/src/Misc/layoutbin/hashFiles/index.js +++ b/src/Misc/layoutbin/hashFiles/index.js @@ -43,6 +43,199 @@ module.exports = /************************************************************************/ /******/ ({ +/***/ 16: +/***/ (function(module) { + +module.exports = require("tls"); + +/***/ }), + +/***/ 22: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _validate = _interopRequireDefault(__webpack_require__(78)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports.default = _default; + +/***/ }), + +/***/ 36: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Indicates whether a pattern matches a path + */ +var MatchKind; +(function (MatchKind) { + /** Not matched */ + MatchKind[MatchKind["None"] = 0] = "None"; + /** Matched if the path is a directory */ + MatchKind[MatchKind["Directory"] = 1] = "Directory"; + /** Matched if the path is a regular file */ + MatchKind[MatchKind["File"] = 2] = "File"; + /** Matched */ + MatchKind[MatchKind["All"] = 3] = "All"; +})(MatchKind = exports.MatchKind || (exports.MatchKind = {})); +//# sourceMappingURL=internal-match-kind.js.map + +/***/ }), + +/***/ 62: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "v1", { + enumerable: true, + get: function () { + return _v.default; + } +}); +Object.defineProperty(exports, "v3", { + enumerable: true, + get: function () { + return _v2.default; + } +}); +Object.defineProperty(exports, "v4", { + enumerable: true, + get: function () { + return _v3.default; + } +}); +Object.defineProperty(exports, "v5", { + enumerable: true, + get: function () { + return _v4.default; + } +}); +Object.defineProperty(exports, "NIL", { + enumerable: true, + get: function () { + return _nil.default; + } +}); +Object.defineProperty(exports, "version", { + enumerable: true, + get: function () { + return _version.default; + } +}); +Object.defineProperty(exports, "validate", { + enumerable: true, + get: function () { + return _validate.default; + } +}); +Object.defineProperty(exports, "stringify", { + enumerable: true, + get: function () { + return _stringify.default; + } +}); +Object.defineProperty(exports, "parse", { + enumerable: true, + get: function () { + return _parse.default; + } +}); + +var _v = _interopRequireDefault(__webpack_require__(893)); + +var _v2 = _interopRequireDefault(__webpack_require__(209)); + +var _v3 = _interopRequireDefault(__webpack_require__(733)); + +var _v4 = _interopRequireDefault(__webpack_require__(384)); + +var _nil = _interopRequireDefault(__webpack_require__(327)); + +var _version = _interopRequireDefault(__webpack_require__(695)); + +var _validate = _interopRequireDefault(__webpack_require__(78)); + +var _stringify = _interopRequireDefault(__webpack_require__(411)); + +var _parse = _interopRequireDefault(__webpack_require__(22)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 78: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _regex = _interopRequireDefault(__webpack_require__(456)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports.default = _default; + +/***/ }), + /***/ 82: /***/ (function(__unusedmodule, exports) { @@ -51,6 +244,7 @@ module.exports = // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ Object.defineProperty(exports, "__esModule", { value: true }); +exports.toCommandProperties = exports.toCommandValue = void 0; /** * Sanitizes an input into a string so it can be passed into issueCommand safely * @param input input to sanitize into a string @@ -65,6 +259,26 @@ function toCommandValue(input) { return JSON.stringify(input); } exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; //# sourceMappingURL=utils.js.map /***/ }), @@ -1012,14 +1226,27 @@ function regExpEscape (s) { "use strict"; // For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); +exports.issueCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__webpack_require__(747)); @@ -1042,101 +1269,556 @@ exports.issueCommand = issueCommand; /***/ }), -/***/ 281: +/***/ 141: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); + +var net = __webpack_require__(631); +var tls = __webpack_require__(16); +var http = __webpack_require__(605); +var https = __webpack_require__(211); +var events = __webpack_require__(614); +var assert = __webpack_require__(357); +var util = __webpack_require__(669); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } }; -Object.defineProperty(exports, "__esModule", { value: true }); -const internal_globber_1 = __webpack_require__(297); -/** - * Constructs a globber - * - * @param patterns Patterns separated by newlines - * @param options Glob options - */ -function create(patterns, options) { - return __awaiter(this, void 0, void 0, function* () { - return yield internal_globber_1.DefaultGlobber.create(patterns, options); + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); } -exports.create = create; -//# sourceMappingURL=glob.js.map + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + /***/ }), -/***/ 297: -/***/ (function(__unusedmodule, exports, __webpack_require__) { +/***/ 177: +/***/ (function(__unusedmodule, exports) { "use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __asyncValues = (this && this.__asyncValues) || function (o) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var m = o[Symbol.asyncIterator], i; - return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); - function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } - function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } -}; -var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } -var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { - if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); - var g = generator.apply(thisArg, _arguments || []), i, q = []; - return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; - function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } - function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } - function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } - function fulfill(value) { resume("next", value); } - function reject(value) { resume("throw", value); } - function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } -}; Object.defineProperty(exports, "__esModule", { value: true }); -const core = __webpack_require__(470); -const fs = __webpack_require__(747); -const globOptionsHelper = __webpack_require__(601); -const path = __webpack_require__(622); -const patternHelper = __webpack_require__(597); -const internal_match_kind_1 = __webpack_require__(327); -const internal_pattern_1 = __webpack_require__(923); -const internal_search_state_1 = __webpack_require__(728); -const IS_WINDOWS = process.platform === 'win32'; -class DefaultGlobber { - constructor(options) { - this.patterns = []; - this.searchPaths = []; - this.options = globOptionsHelper.getOptions(options); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; } - getSearchPaths() { - // Return a copy - return this.searchPaths.slice(); + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + return new URL(proxyVar); } - glob() { - var e_1, _a; - return __awaiter(this, void 0, void 0, function* () { - const result = []; - try { - for (var _b = __asyncValues(this.globGenerator()), _c; _c = yield _b.next(), !_c.done;) { - const itemPath = _c.value; - result.push(itemPath); - } - } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperReqHosts.some(x => x === upperNoProxyItem)) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 209: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _v = _interopRequireDefault(__webpack_require__(212)); + +var _md = _interopRequireDefault(__webpack_require__(803)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports.default = _default; + +/***/ }), + +/***/ 211: +/***/ (function(module) { + +module.exports = require("https"); + +/***/ }), + +/***/ 212: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__webpack_require__(411)); + +var _parse = _interopRequireDefault(__webpack_require__(22)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 281: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const internal_globber_1 = __webpack_require__(297); +/** + * Constructs a globber + * + * @param patterns Patterns separated by newlines + * @param options Glob options + */ +function create(patterns, options) { + return __awaiter(this, void 0, void 0, function* () { + return yield internal_globber_1.DefaultGlobber.create(patterns, options); + }); +} +exports.create = create; +//# sourceMappingURL=glob.js.map + +/***/ }), + +/***/ 297: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } +var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const core = __webpack_require__(470); +const fs = __webpack_require__(747); +const globOptionsHelper = __webpack_require__(601); +const path = __webpack_require__(622); +const patternHelper = __webpack_require__(597); +const internal_match_kind_1 = __webpack_require__(36); +const internal_pattern_1 = __webpack_require__(923); +const internal_search_state_1 = __webpack_require__(728); +const IS_WINDOWS = process.platform === 'win32'; +class DefaultGlobber { + constructor(options) { + this.patterns = []; + this.searchPaths = []; + this.options = globOptionsHelper.getOptions(options); + } + getSearchPaths() { + // Return a copy + return this.searchPaths.slice(); + } + glob() { + var e_1, _a; + return __awaiter(this, void 0, void 0, function* () { + const result = []; + try { + for (var _b = __asyncValues(this.globGenerator()), _c; _c = yield _b.next(), !_c.done;) { + const itemPath = _c.value; + result.push(itemPath); + } + } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { @@ -1509,22 +2191,13 @@ function expand(str, isTop) { "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -/** - * Indicates whether a pattern matches a path - */ -var MatchKind; -(function (MatchKind) { - /** Not matched */ - MatchKind[MatchKind["None"] = 0] = "None"; - /** Matched if the path is a directory */ - MatchKind[MatchKind["Directory"] = 1] = "Directory"; - /** Matched if the path is a regular file */ - MatchKind[MatchKind["File"] = 2] = "File"; - /** Matched */ - MatchKind[MatchKind["All"] = 3] = "All"; -})(MatchKind = exports.MatchKind || (exports.MatchKind = {})); -//# sourceMappingURL=internal-match-kind.js.map + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports.default = _default; /***/ }), @@ -1561,7 +2234,7 @@ const crypto = __importStar(__webpack_require__(417)); const fs = __importStar(__webpack_require__(747)); const glob = __importStar(__webpack_require__(281)); const path = __importStar(__webpack_require__(622)); -const stream = __importStar(__webpack_require__(413)); +const stream = __importStar(__webpack_require__(794)); const util = __importStar(__webpack_require__(669)); function run() { var e_1, _a; @@ -1738,10 +2411,80 @@ exports.Path = Path; /***/ }), +/***/ 384: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _v = _interopRequireDefault(__webpack_require__(212)); + +var _sha = _interopRequireDefault(__webpack_require__(498)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports.default = _default; + +/***/ }), + +/***/ 411: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _validate = _interopRequireDefault(__webpack_require__(78)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports.default = _default; + +/***/ }), + /***/ 413: -/***/ (function(module) { +/***/ (function(module, __unusedexports, __webpack_require__) { + +module.exports = __webpack_require__(141); -module.exports = require("stream"); /***/ }), @@ -1752,43 +2495,668 @@ module.exports = require("crypto"); /***/ }), -/***/ 431: +/***/ 425: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); return result; }; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; Object.defineProperty(exports, "__esModule", { value: true }); -const os = __importStar(__webpack_require__(87)); -const utils_1 = __webpack_require__(82); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__webpack_require__(605)); +const https = __importStar(__webpack_require__(211)); +const pm = __importStar(__webpack_require__(177)); +const tunnel = __importStar(__webpack_require__(413)); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers = exports.Headers || (exports.Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); /** - * Commands - * - * Command Format: - * ::name key=value,key=value::message - * - * Examples: - * ::warning::This is the message - * ::set-env name=MY_VAR::some value + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com */ -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; } -exports.issueCommand = issueCommand; -function issue(name, message = '') { - issueCommand(name, {}, message); +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } } -exports.issue = issue; -const CMD_STRING = '::'; -class Command { - constructor(command, properties, message) { +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (this._keepAlive && !useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if reusing agent across request and tunneling agent isn't assigned create a new agent + if (this._keepAlive && !agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + // if not using private agent and tunnel agent isn't setup then use global agent + if (!agent) { + agent = usingSsl ? https.globalAgent : http.globalAgent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 431: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__webpack_require__(87)); +const utils_1 = __webpack_require__(82); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { if (!command) { command = 'missing.command'; } @@ -1838,11 +3206,45 @@ function escapeProperty(s) { /***/ }), +/***/ 456: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports.default = _default; + +/***/ }), + /***/ 470: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -1852,19 +3254,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; - result["default"] = mod; - return result; -}; Object.defineProperty(exports, "__esModule", { value: true }); +exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; const command_1 = __webpack_require__(431); const file_command_1 = __webpack_require__(102); const utils_1 = __webpack_require__(82); const os = __importStar(__webpack_require__(87)); const path = __importStar(__webpack_require__(622)); +const uuid_1 = __webpack_require__(62); +const oidc_utils_1 = __webpack_require__(742); /** * The code to exit an action */ @@ -1893,7 +3291,14 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - const delimiter = '_GitHubActionsFileCommandDelimeter_'; + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. + if (name.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedVal.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; file_command_1.issueCommand('ENV', commandValue); } @@ -1926,7 +3331,9 @@ function addPath(inputPath) { } exports.addPath = addPath; /** - * Gets the value of an input. The value is also trimmed. + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. * * @param name name of the input to get * @param options optional. See InputOptions. @@ -1937,9 +3344,49 @@ function getInput(name, options) { if (options && options.required && !val) { throw new Error(`Input required and not supplied: ${name}`); } + if (options && options.trimWhitespace === false) { + return val; + } return val.trim(); } exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + return inputs; +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; /** * Sets the value of an output. * @@ -1948,6 +3395,7 @@ exports.getInput = getInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { + process.stdout.write(os.EOL); command_1.issueCommand('set-output', { name }, value); } exports.setOutput = setOutput; @@ -1994,19 +3442,30 @@ exports.debug = debug; /** * Adds an error issue * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. */ -function error(message) { - command_1.issue('error', message instanceof Error ? message.toString() : message); +function error(message, properties = {}) { + command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); } exports.error = error; /** - * Adds an warning issue + * Adds a warning issue * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. */ -function warning(message) { - command_1.issue('warning', message instanceof Error ? message.toString() : message); +function warning(message, properties = {}) { + command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); } exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; /** * Writes info to log with console.log. * @param message info message @@ -2079,29 +3538,235 @@ function getState(name) { return process.env[`STATE_${name}`] || ''; } exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __webpack_require__(665); +Object.defineProperty(exports, "summary", { enumerable: true, get: function () { return summary_1.summary; } }); +/** + * @deprecated use core.summary + */ +var summary_2 = __webpack_require__(665); +Object.defineProperty(exports, "markdownSummary", { enumerable: true, get: function () { return summary_2.markdownSummary; } }); +/** + * Path exports + */ +var path_utils_1 = __webpack_require__(573); +Object.defineProperty(exports, "toPosixPath", { enumerable: true, get: function () { return path_utils_1.toPosixPath; } }); +Object.defineProperty(exports, "toWin32Path", { enumerable: true, get: function () { return path_utils_1.toWin32Path; } }); +Object.defineProperty(exports, "toPlatformPath", { enumerable: true, get: function () { return path_utils_1.toPlatformPath; } }); //# sourceMappingURL=core.js.map /***/ }), -/***/ 597: +/***/ 498: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const pathHelper = __webpack_require__(972); -const internal_match_kind_1 = __webpack_require__(327); -const IS_WINDOWS = process.platform === 'win32'; -/** - * Given an array of patterns, returns an array of paths to search. - * Duplicates and paths under other included paths are filtered out. - */ -function getSearchPaths(patterns) { - // Ignore negate patterns - patterns = patterns.filter(x => !x.negate); - // Create a map of all search paths - const searchPathMap = {}; - for (const pattern of patterns) { + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _crypto = _interopRequireDefault(__webpack_require__(417)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports.default = _default; + +/***/ }), + +/***/ 554: +/***/ (function(__unusedmodule, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 573: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__webpack_require__(622)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 597: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +const pathHelper = __webpack_require__(972); +const internal_match_kind_1 = __webpack_require__(36); +const IS_WINDOWS = process.platform === 'win32'; +/** + * Given an array of patterns, returns an array of paths to search. + * Duplicates and paths under other included paths are filtered out. + */ +function getSearchPaths(patterns) { + // Ignore negate patterns + patterns = patterns.filter(x => !x.negate); + // Create a map of all search paths + const searchPathMap = {}; + for (const pattern of patterns) { const key = IS_WINDOWS ? pattern.searchPath.toUpperCase() : pattern.searchPath; @@ -2201,6 +3866,20 @@ exports.getOptions = getOptions; /***/ }), +/***/ 605: +/***/ (function(module) { + +module.exports = require("http"); + +/***/ }), + +/***/ 614: +/***/ (function(module) { + +module.exports = require("events"); + +/***/ }), + /***/ 621: /***/ (function(module) { @@ -2275,6 +3954,303 @@ module.exports = require("path"); /***/ }), +/***/ 631: +/***/ (function(module) { + +module.exports = require("net"); + +/***/ }), + +/***/ 665: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __webpack_require__(87); +const fs_1 = __webpack_require__(747); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + /***/ 669: /***/ (function(module) { @@ -2282,6 +4258,34 @@ module.exports = require("util"); /***/ }), +/***/ 695: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _validate = _interopRequireDefault(__webpack_require__(78)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports.default = _default; + +/***/ }), + /***/ 728: /***/ (function(__unusedmodule, exports) { @@ -2299,6 +4303,134 @@ exports.SearchState = SearchState; /***/ }), +/***/ 733: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _rng = _interopRequireDefault(__webpack_require__(844)); + +var _stringify = _interopRequireDefault(__webpack_require__(411)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports.default = _default; + +/***/ }), + +/***/ 742: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.OidcClient = void 0; +const http_client_1 = __webpack_require__(425); +const auth_1 = __webpack_require__(554); +const core_1 = __webpack_require__(470); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.result.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + core_1.debug(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + core_1.setSecret(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + /***/ 747: /***/ (function(module) { @@ -2306,6 +4438,188 @@ module.exports = require("fs"); /***/ }), +/***/ 794: +/***/ (function(module) { + +module.exports = require("stream"); + +/***/ }), + +/***/ 803: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _crypto = _interopRequireDefault(__webpack_require__(417)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports.default = _default; + +/***/ }), + +/***/ 844: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = rng; + +var _crypto = _interopRequireDefault(__webpack_require__(417)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 893: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = void 0; + +var _rng = _interopRequireDefault(__webpack_require__(844)); + +var _stringify = _interopRequireDefault(__webpack_require__(411)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports.default = _default; + +/***/ }), + /***/ 896: /***/ (function(module) { @@ -2337,7 +4651,7 @@ const os = __webpack_require__(87); const path = __webpack_require__(622); const pathHelper = __webpack_require__(972); const minimatch_1 = __webpack_require__(93); -const internal_match_kind_1 = __webpack_require__(327); +const internal_match_kind_1 = __webpack_require__(36); const internal_path_1 = __webpack_require__(383); const IS_WINDOWS = process.platform === 'win32'; class Pattern { From 6cdd27263b9a4739c7b4b4a3222c763c50c9f279 Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Thu, 15 Sep 2022 12:14:10 +0200 Subject: [PATCH 10/22] Remove unused imports (#2124) --- src/Runner.Common/ActionCommand.cs | 1 - src/Runner.Common/ActionResult.cs | 2 -- src/Runner.Common/CommandLineParser.cs | 1 - src/Runner.Common/ConfigurationStore.cs | 1 - src/Runner.Common/ExtensionManager.cs | 1 - src/Runner.Common/HostTraceListener.cs | 1 - src/Runner.Common/JobNotification.cs | 5 +---- src/Runner.Common/JobServer.cs | 3 +-- .../Listener/Configuration/ConfigurationManagerL0.cs | 4 +--- src/Test/L0/Listener/RunnerL0.cs | 3 +-- src/Test/L0/PagingLoggerL0.cs | 1 - src/Test/L0/ProcessInvokerL0.cs | 3 +-- src/Test/L0/ServiceControlManagerL0.cs | 3 --- src/Test/L0/Util/ArgUtilL0.cs | 1 - src/Test/L0/Util/UrlUtilL0.cs | 3 +-- src/Test/L0/Util/VssUtilL0.cs | 4 ---- .../L0/Worker/Expressions/ConditionFunctionsL0.cs | 12 +++++------- src/Test/L0/Worker/JobExtensionL0.cs | 3 +-- src/Test/L0/Worker/JobRunnerL0.cs | 4 +--- src/Test/L0/Worker/OutputManagerL0.cs | 1 - src/Test/L0/Worker/StepHostL0.cs | 5 +---- src/Test/L0/Worker/VariablesL0.cs | 4 +--- 22 files changed, 15 insertions(+), 51 deletions(-) diff --git a/src/Runner.Common/ActionCommand.cs b/src/Runner.Common/ActionCommand.cs index 3e25176b840..68ded964c57 100644 --- a/src/Runner.Common/ActionCommand.cs +++ b/src/Runner.Common/ActionCommand.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using System.Collections.Generic; diff --git a/src/Runner.Common/ActionResult.cs b/src/Runner.Common/ActionResult.cs index db68b685249..bb1622d6780 100644 --- a/src/Runner.Common/ActionResult.cs +++ b/src/Runner.Common/ActionResult.cs @@ -1,5 +1,3 @@ -using System; - namespace GitHub.Runner.Common { public enum ActionResult diff --git a/src/Runner.Common/CommandLineParser.cs b/src/Runner.Common/CommandLineParser.cs index bca3b461ab8..abcd8bd4de9 100644 --- a/src/Runner.Common/CommandLineParser.cs +++ b/src/Runner.Common/CommandLineParser.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using System; using System.Collections.Generic; using GitHub.DistributedTask.Logging; diff --git a/src/Runner.Common/ConfigurationStore.cs b/src/Runner.Common/ConfigurationStore.cs index ca526c77fe1..7cce70f601d 100644 --- a/src/Runner.Common/ConfigurationStore.cs +++ b/src/Runner.Common/ConfigurationStore.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using System.IO; diff --git a/src/Runner.Common/ExtensionManager.cs b/src/Runner.Common/ExtensionManager.cs index 29f99b62834..c7fbab73bcd 100644 --- a/src/Runner.Common/ExtensionManager.cs +++ b/src/Runner.Common/ExtensionManager.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using System.Collections.Concurrent; diff --git a/src/Runner.Common/HostTraceListener.cs b/src/Runner.Common/HostTraceListener.cs index e11edc5b492..e022eb0e47b 100644 --- a/src/Runner.Common/HostTraceListener.cs +++ b/src/Runner.Common/HostTraceListener.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using System.Diagnostics; diff --git a/src/Runner.Common/JobNotification.cs b/src/Runner.Common/JobNotification.cs index ee20fb452f4..c171e4e69e9 100644 --- a/src/Runner.Common/JobNotification.cs +++ b/src/Runner.Common/JobNotification.cs @@ -1,10 +1,7 @@ -using System; -using System.IO; -using System.IO.Pipes; +using System; using System.Net; using System.Net.Sockets; using System.Text; -using System.Threading; using System.Threading.Tasks; namespace GitHub.Runner.Common diff --git a/src/Runner.Common/JobServer.cs b/src/Runner.Common/JobServer.cs index 1cac64f65b6..4a37311ca03 100644 --- a/src/Runner.Common/JobServer.cs +++ b/src/Runner.Common/JobServer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -13,7 +13,6 @@ using GitHub.Services.Common; using GitHub.Services.WebApi; using GitHub.Services.WebApi.Utilities.Internal; -using Newtonsoft.Json; namespace GitHub.Runner.Common { diff --git a/src/Test/L0/Listener/Configuration/ConfigurationManagerL0.cs b/src/Test/L0/Listener/Configuration/ConfigurationManagerL0.cs index 197cf7e5202..20ec96a784a 100644 --- a/src/Test/L0/Listener/Configuration/ConfigurationManagerL0.cs +++ b/src/Test/L0/Listener/Configuration/ConfigurationManagerL0.cs @@ -1,13 +1,11 @@ -using GitHub.DistributedTask.WebApi; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Listener; using GitHub.Runner.Listener.Configuration; using GitHub.Runner.Common.Util; using GitHub.Services.WebApi; using Moq; -using Newtonsoft.Json; using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Security.Cryptography; diff --git a/src/Test/L0/Listener/RunnerL0.cs b/src/Test/L0/Listener/RunnerL0.cs index acaff40eb5f..a1c283a9f0a 100644 --- a/src/Test/L0/Listener/RunnerL0.cs +++ b/src/Test/L0/Listener/RunnerL0.cs @@ -1,4 +1,4 @@ -using GitHub.DistributedTask.WebApi; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Listener; using GitHub.Runner.Listener.Configuration; using Moq; @@ -9,7 +9,6 @@ using Xunit; using GitHub.Services.WebApi; using Pipelines = GitHub.DistributedTask.Pipelines; -using GitHub.Runner.Common.Util; namespace GitHub.Runner.Common.Tests.Listener { diff --git a/src/Test/L0/PagingLoggerL0.cs b/src/Test/L0/PagingLoggerL0.cs index 2c1c3b0ba42..799428aa6eb 100644 --- a/src/Test/L0/PagingLoggerL0.cs +++ b/src/Test/L0/PagingLoggerL0.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using Moq; using System; using System.IO; diff --git a/src/Test/L0/ProcessInvokerL0.cs b/src/Test/L0/ProcessInvokerL0.cs index 629abb0a010..11dcf8d2ae0 100644 --- a/src/Test/L0/ProcessInvokerL0.cs +++ b/src/Test/L0/ProcessInvokerL0.cs @@ -1,11 +1,10 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; using Xunit; -using GitHub.Runner.Common.Util; using System.Threading.Channels; using GitHub.Runner.Sdk; using System.Linq; diff --git a/src/Test/L0/ServiceControlManagerL0.cs b/src/Test/L0/ServiceControlManagerL0.cs index c7fe84cda87..f94ded572c2 100644 --- a/src/Test/L0/ServiceControlManagerL0.cs +++ b/src/Test/L0/ServiceControlManagerL0.cs @@ -1,7 +1,4 @@ -using System; using System.Runtime.CompilerServices; -using System.Text.RegularExpressions; -using GitHub.Runner.Common; using GitHub.Runner.Listener.Configuration; using Xunit; diff --git a/src/Test/L0/Util/ArgUtilL0.cs b/src/Test/L0/Util/ArgUtilL0.cs index 7ede3bed7fd..e0e0b34545d 100644 --- a/src/Test/L0/Util/ArgUtilL0.cs +++ b/src/Test/L0/Util/ArgUtilL0.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using Xunit; diff --git a/src/Test/L0/Util/UrlUtilL0.cs b/src/Test/L0/Util/UrlUtilL0.cs index b84db224256..6100be5dd4f 100644 --- a/src/Test/L0/Util/UrlUtilL0.cs +++ b/src/Test/L0/Util/UrlUtilL0.cs @@ -1,5 +1,4 @@ -using System; -using GitHub.Runner.Common.Util; +using System; using GitHub.Runner.Sdk; using Xunit; diff --git a/src/Test/L0/Util/VssUtilL0.cs b/src/Test/L0/Util/VssUtilL0.cs index 62577eff8d5..30ed8569219 100644 --- a/src/Test/L0/Util/VssUtilL0.cs +++ b/src/Test/L0/Util/VssUtilL0.cs @@ -1,10 +1,6 @@ -using GitHub.Runner.Common.Util; using GitHub.Services.Common; using System; -using System.Collections.Generic; -using System.Net.Http.Headers; using Xunit; -using System.Text.RegularExpressions; using GitHub.Runner.Sdk; namespace GitHub.Runner.Common.Tests.Util diff --git a/src/Test/L0/Worker/Expressions/ConditionFunctionsL0.cs b/src/Test/L0/Worker/Expressions/ConditionFunctionsL0.cs index 2ca10bffdcc..e4c809c47d9 100644 --- a/src/Test/L0/Worker/Expressions/ConditionFunctionsL0.cs +++ b/src/Test/L0/Worker/Expressions/ConditionFunctionsL0.cs @@ -1,10 +1,8 @@ -using System; -using System.Collections.Generic; +using System; using System.Runtime.CompilerServices; using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.ObjectTemplating; using GitHub.DistributedTask.Pipelines.ObjectTemplating; -using GitHub.DistributedTask.WebApi; using GitHub.Runner.Worker; using GitHub.Runner.Worker.Expressions; using Moq; @@ -121,8 +119,8 @@ public void FailureFunctionComposite(ActionResult jobStatus, ActionResult? actio var executionContext = InitializeExecutionContext(hc); executionContext.Setup(x => x.GetGitHubContext("action_status")).Returns(actionStatus.ToString()); - executionContext.Setup( x=> x.IsEmbedded).Returns(true); - executionContext.Setup( x=> x.Stage).Returns(ActionRunStage.Main); + executionContext.Setup(x => x.IsEmbedded).Returns(true); + executionContext.Setup(x => x.Stage).Returns(ActionRunStage.Main); _jobContext.Status = jobStatus; @@ -181,8 +179,8 @@ public void SuccessFunctionComposite(ActionResult jobStatus, ActionResult? actio var executionContext = InitializeExecutionContext(hc); executionContext.Setup(x => x.GetGitHubContext("action_status")).Returns(actionStatus.ToString()); - executionContext.Setup( x=> x.IsEmbedded).Returns(true); - executionContext.Setup( x=> x.Stage).Returns(ActionRunStage.Main); + executionContext.Setup(x => x.IsEmbedded).Returns(true); + executionContext.Setup(x => x.Stage).Returns(ActionRunStage.Main); _jobContext.Status = jobStatus; diff --git a/src/Test/L0/Worker/JobExtensionL0.cs b/src/Test/L0/Worker/JobExtensionL0.cs index 9f7cbd2f51a..e3955c65398 100644 --- a/src/Test/L0/Worker/JobExtensionL0.cs +++ b/src/Test/L0/Worker/JobExtensionL0.cs @@ -1,4 +1,4 @@ -using GitHub.DistributedTask.WebApi; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Worker; using Moq; using System; @@ -8,7 +8,6 @@ using System.Threading.Tasks; using Xunit; using System.Threading; -using GitHub.DistributedTask.ObjectTemplating.Tokens; using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Common.Tests.Worker diff --git a/src/Test/L0/Worker/JobRunnerL0.cs b/src/Test/L0/Worker/JobRunnerL0.cs index 198d378b9b9..1bb7f1ac099 100644 --- a/src/Test/L0/Worker/JobRunnerL0.cs +++ b/src/Test/L0/Worker/JobRunnerL0.cs @@ -1,14 +1,12 @@ -using GitHub.DistributedTask.WebApi; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Worker; using Moq; using System; using System.Collections.Generic; -using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Xunit; using System.Threading; -using System.Collections.ObjectModel; using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Common.Tests.Worker diff --git a/src/Test/L0/Worker/OutputManagerL0.cs b/src/Test/L0/Worker/OutputManagerL0.cs index 85045802a35..e0364e9f0fc 100644 --- a/src/Test/L0/Worker/OutputManagerL0.cs +++ b/src/Test/L0/Worker/OutputManagerL0.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Runtime.CompilerServices; diff --git a/src/Test/L0/Worker/StepHostL0.cs b/src/Test/L0/Worker/StepHostL0.cs index 0130b84cbad..24f2600dc65 100644 --- a/src/Test/L0/Worker/StepHostL0.cs +++ b/src/Test/L0/Worker/StepHostL0.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -7,9 +7,6 @@ using GitHub.Runner.Worker; using GitHub.Runner.Worker.Handlers; using GitHub.Runner.Worker.Container; -using GitHub.DistributedTask.Pipelines.ContextData; -using System.Linq; -using GitHub.DistributedTask.Pipelines; using GitHub.DistributedTask.WebApi; namespace GitHub.Runner.Common.Tests.Worker diff --git a/src/Test/L0/Worker/VariablesL0.cs b/src/Test/L0/Worker/VariablesL0.cs index b0e943aa4c0..5b7d50b4db3 100644 --- a/src/Test/L0/Worker/VariablesL0.cs +++ b/src/Test/L0/Worker/VariablesL0.cs @@ -1,6 +1,4 @@ -using GitHub.DistributedTask.WebApi; -using GitHub.Runner.Common.Util; -using GitHub.Runner.Sdk; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Worker; using System.Collections.Generic; using System.Globalization; From 3a1c89715cccc9ec2cf55c0903a8466de839d7fe Mon Sep 17 00:00:00 2001 From: JoannaaKL Date: Thu, 15 Sep 2022 15:55:45 +0200 Subject: [PATCH 11/22] Remove unused imports (#2126) --- src/Runner.Common/Logging.cs | 1 - src/Runner.Common/ProcessInvoker.cs | 2 +- src/Runner.Common/RunServer.cs | 5 +---- src/Runner.Common/RunnerServer.cs | 3 +-- src/Runner.Common/ThrottlingReportHandler.cs | 3 +-- src/Runner.Common/TraceManager.cs | 1 - src/Runner.Common/Tracing.cs | 2 -- src/Runner.Common/Util/VarUtil.cs | 5 +---- src/Runner.Listener/Checks/GitCheck.cs | 3 +-- src/Runner.Listener/Checks/NodeJsCheck.cs | 3 +-- src/Runner.Listener/CommandSettings.cs | 1 - src/Runner.Listener/Configuration/PromptManager.cs | 10 +++++----- src/Runner.Listener/Configuration/RSAFileKeyManager.cs | 1 - .../Configuration/SystemdControlManager.cs | 3 +-- src/Runner.Listener/Program.cs | 2 -- src/Runner.Listener/Runner.cs | 1 - src/Runner.PluginHost/Program.cs | 5 +---- src/Runner.Plugins/Artifact/PipelinesServer.cs | 2 -- src/Runner.Plugins/Repository/GitCliManager.cs | 2 -- .../Repository/v1.0/GitSourceProvider.cs | 2 -- src/Runner.Plugins/Repository/v1.0/RepositoryPlugin.cs | 5 +---- .../Repository/v1.1/GitSourceProvider.cs | 2 -- src/Runner.Plugins/Repository/v1.1/RepositoryPlugin.cs | 6 +----- src/Runner.Sdk/ActionPlugin.cs | 4 +--- src/Runner.Sdk/Util/IOUtil.cs | 1 - src/Runner.Sdk/Util/PathUtil.cs | 1 - src/Runner.Sdk/Util/StringUtil.cs | 6 +----- src/Runner.Worker/ActionManifestManager.cs | 5 +---- src/Runner.Worker/ActionRunner.cs | 3 +-- src/Runner.Worker/ConditionTraceWriter.cs | 1 - src/Runner.Worker/FileCommandManager.cs | 4 +--- src/Runner.Worker/IEnvironmentContextData.cs | 1 - src/Runner.Worker/JobExtension.cs | 4 +--- src/Runner.Worker/JobExtensionRunner.cs | 3 +-- 34 files changed, 23 insertions(+), 80 deletions(-) diff --git a/src/Runner.Common/Logging.cs b/src/Runner.Common/Logging.cs index b4c8d6f3240..40be5cdcff0 100644 --- a/src/Runner.Common/Logging.cs +++ b/src/Runner.Common/Logging.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using System; using System.IO; diff --git a/src/Runner.Common/ProcessInvoker.cs b/src/Runner.Common/ProcessInvoker.cs index 021c6db5e02..7b5fbb7fcf2 100644 --- a/src/Runner.Common/ProcessInvoker.cs +++ b/src/Runner.Common/ProcessInvoker.cs @@ -1,4 +1,4 @@ -using GitHub.Runner.Common.Util; +using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using System.Collections.Generic; diff --git a/src/Runner.Common/RunServer.cs b/src/Runner.Common/RunServer.cs index 7df8da7a8fa..981a61b7f0c 100644 --- a/src/Runner.Common/RunServer.cs +++ b/src/Runner.Common/RunServer.cs @@ -1,11 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Runtime.Serialization; +using System; using System.Threading; using System.Threading.Tasks; using GitHub.DistributedTask.Pipelines; using GitHub.DistributedTask.WebApi; -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using GitHub.Services.Common; using GitHub.Services.WebApi; diff --git a/src/Runner.Common/RunnerServer.cs b/src/Runner.Common/RunnerServer.cs index 0ab7a628503..6f335a4aa3b 100644 --- a/src/Runner.Common/RunnerServer.cs +++ b/src/Runner.Common/RunnerServer.cs @@ -1,9 +1,8 @@ -using GitHub.DistributedTask.WebApi; +using GitHub.DistributedTask.WebApi; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using GitHub.Runner.Common.Util; using GitHub.Services.WebApi; using GitHub.Services.Common; using GitHub.Runner.Sdk; diff --git a/src/Runner.Common/ThrottlingReportHandler.cs b/src/Runner.Common/ThrottlingReportHandler.cs index 969df606f3a..7b08ae0db0e 100644 --- a/src/Runner.Common/ThrottlingReportHandler.cs +++ b/src/Runner.Common/ThrottlingReportHandler.cs @@ -1,10 +1,9 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using GitHub.Services.Common.Internal; diff --git a/src/Runner.Common/TraceManager.cs b/src/Runner.Common/TraceManager.cs index 2500eb82a56..ebbaefa89ed 100644 --- a/src/Runner.Common/TraceManager.cs +++ b/src/Runner.Common/TraceManager.cs @@ -1,4 +1,3 @@ -using GitHub.Runner.Common.Util; using System; using System.Collections.Concurrent; using System.Diagnostics; diff --git a/src/Runner.Common/Tracing.cs b/src/Runner.Common/Tracing.cs index b72070103e1..a0d93b658bc 100644 --- a/src/Runner.Common/Tracing.cs +++ b/src/Runner.Common/Tracing.cs @@ -1,5 +1,3 @@ - -using GitHub.Runner.Common.Util; using Newtonsoft.Json; using System; using System.Diagnostics; diff --git a/src/Runner.Common/Util/VarUtil.cs b/src/Runner.Common/Util/VarUtil.cs index b9860e151b5..4fcd69d6158 100644 --- a/src/Runner.Common/Util/VarUtil.cs +++ b/src/Runner.Common/Util/VarUtil.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using GitHub.Runner.Sdk; +using System; namespace GitHub.Runner.Common.Util { diff --git a/src/Runner.Listener/Checks/GitCheck.cs b/src/Runner.Listener/Checks/GitCheck.cs index 201210a7b9c..203abd3b4ea 100644 --- a/src/Runner.Listener/Checks/GitCheck.cs +++ b/src/Runner.Listener/Checks/GitCheck.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; using System.Threading; using System.Threading.Tasks; using GitHub.Runner.Common; @@ -168,4 +167,4 @@ await processInvoker.ExecuteAsync( return result; } } -} \ No newline at end of file +} diff --git a/src/Runner.Listener/Checks/NodeJsCheck.cs b/src/Runner.Listener/Checks/NodeJsCheck.cs index 931b248fe4a..29fb282e07b 100644 --- a/src/Runner.Listener/Checks/NodeJsCheck.cs +++ b/src/Runner.Listener/Checks/NodeJsCheck.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; using System.Threading; using System.Threading.Tasks; using GitHub.Runner.Common; @@ -179,4 +178,4 @@ await processInvoker.ExecuteAsync( return result; } } -} \ No newline at end of file +} diff --git a/src/Runner.Listener/CommandSettings.cs b/src/Runner.Listener/CommandSettings.cs index 40c2cc27cd8..ca0ea1b7da5 100644 --- a/src/Runner.Listener/CommandSettings.cs +++ b/src/Runner.Listener/CommandSettings.cs @@ -4,7 +4,6 @@ using System.Collections; using System.Collections.Generic; using System.Linq; -using GitHub.DistributedTask.Logging; using GitHub.Runner.Common; using GitHub.Runner.Sdk; diff --git a/src/Runner.Listener/Configuration/PromptManager.cs b/src/Runner.Listener/Configuration/PromptManager.cs index 49d6259b098..f04f17069aa 100644 --- a/src/Runner.Listener/Configuration/PromptManager.cs +++ b/src/Runner.Listener/Configuration/PromptManager.cs @@ -1,5 +1,4 @@ using GitHub.Runner.Common; -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; @@ -72,7 +71,7 @@ public string ReadValue( { return defaultValue; } - else if (isOptional) + else if (isOptional) { return string.Empty; } @@ -87,11 +86,12 @@ public string ReadValue( // Write the message prompt. _terminal.Write($"{description} "); - if(!string.IsNullOrEmpty(defaultValue)) + if (!string.IsNullOrEmpty(defaultValue)) { _terminal.Write($"[press Enter for {defaultValue}] "); } - else if (isOptional){ + else if (isOptional) + { _terminal.Write($"[press Enter to skip] "); } @@ -112,7 +112,7 @@ public string ReadValue( return string.Empty; } } - + // Return the value if it is not empty and it is valid. // Otherwise try the loop again. if (!string.IsNullOrEmpty(value)) diff --git a/src/Runner.Listener/Configuration/RSAFileKeyManager.cs b/src/Runner.Listener/Configuration/RSAFileKeyManager.cs index 3e5ed40a06c..2552a9f2ea6 100644 --- a/src/Runner.Listener/Configuration/RSAFileKeyManager.cs +++ b/src/Runner.Listener/Configuration/RSAFileKeyManager.cs @@ -3,7 +3,6 @@ using System.IO; using System.Security.Cryptography; using System.Threading; -using GitHub.Runner.Common.Util; using GitHub.Runner.Common; using GitHub.Runner.Sdk; diff --git a/src/Runner.Listener/Configuration/SystemdControlManager.cs b/src/Runner.Listener/Configuration/SystemdControlManager.cs index 28eaa75715b..9024416a364 100644 --- a/src/Runner.Listener/Configuration/SystemdControlManager.cs +++ b/src/Runner.Listener/Configuration/SystemdControlManager.cs @@ -1,4 +1,4 @@ -#if OS_LINUX +#if OS_LINUX using System; using System.Collections.Generic; using System.IO; @@ -6,7 +6,6 @@ using System.Text; using GitHub.Runner.Common.Util; using GitHub.Runner.Common; -using GitHub.Runner.Sdk; namespace GitHub.Runner.Listener.Configuration { diff --git a/src/Runner.Listener/Program.cs b/src/Runner.Listener/Program.cs index 537cda1c71e..4d52bed8f68 100644 --- a/src/Runner.Listener/Program.cs +++ b/src/Runner.Listener/Program.cs @@ -1,12 +1,10 @@ using GitHub.Runner.Common; -using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; using System; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.InteropServices; -using System.Threading; using System.Threading.Tasks; namespace GitHub.Runner.Listener diff --git a/src/Runner.Listener/Runner.cs b/src/Runner.Listener/Runner.cs index dae439595a7..13cc7fe97aa 100644 --- a/src/Runner.Listener/Runner.cs +++ b/src/Runner.Listener/Runner.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.IO.Compression; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; diff --git a/src/Runner.PluginHost/Program.cs b/src/Runner.PluginHost/Program.cs index d823c6fa1af..2496132586c 100644 --- a/src/Runner.PluginHost/Program.cs +++ b/src/Runner.PluginHost/Program.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections.Generic; +using System; using System.Globalization; using System.IO; -using System.Linq; using System.Reflection; using System.Runtime.Loader; using System.Text; using System.Threading; -using System.Threading.Tasks; using GitHub.Runner.Sdk; using GitHub.DistributedTask.WebApi; diff --git a/src/Runner.Plugins/Artifact/PipelinesServer.cs b/src/Runner.Plugins/Artifact/PipelinesServer.cs index 6f712404551..8b51dbd72c5 100644 --- a/src/Runner.Plugins/Artifact/PipelinesServer.cs +++ b/src/Runner.Plugins/Artifact/PipelinesServer.cs @@ -1,5 +1,3 @@ -using System; -using System.IO; using System.Threading; using System.Threading.Tasks; using GitHub.Actions.Pipelines.WebApi; diff --git a/src/Runner.Plugins/Repository/GitCliManager.cs b/src/Runner.Plugins/Repository/GitCliManager.cs index 0ed051645a7..338e17a6e76 100644 --- a/src/Runner.Plugins/Repository/GitCliManager.cs +++ b/src/Runner.Plugins/Repository/GitCliManager.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -9,7 +8,6 @@ using System.IO; using GitHub.Runner.Sdk; using GitHub.Services.Common; -using GitHub.DistributedTask.Pipelines.ContextData; namespace GitHub.Runner.Plugins.Repository { diff --git a/src/Runner.Plugins/Repository/v1.0/GitSourceProvider.cs b/src/Runner.Plugins/Repository/v1.0/GitSourceProvider.cs index b762cafcbba..f567a1338b8 100644 --- a/src/Runner.Plugins/Repository/v1.0/GitSourceProvider.cs +++ b/src/Runner.Plugins/Repository/v1.0/GitSourceProvider.cs @@ -6,11 +6,9 @@ using System.IO; using System.Text.RegularExpressions; using System.Text; -using System.Diagnostics; using GitHub.Runner.Sdk; using System.Linq; using GitHub.DistributedTask.WebApi; -using GitHub.Services.WebApi; namespace GitHub.Runner.Plugins.Repository.v1_0 { diff --git a/src/Runner.Plugins/Repository/v1.0/RepositoryPlugin.cs b/src/Runner.Plugins/Repository/v1.0/RepositoryPlugin.cs index a216ac306ad..df8bd33639c 100644 --- a/src/Runner.Plugins/Repository/v1.0/RepositoryPlugin.cs +++ b/src/Runner.Plugins/Repository/v1.0/RepositoryPlugin.cs @@ -1,12 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System; using System.Threading; using System.Threading.Tasks; using GitHub.Runner.Sdk; using Pipelines = GitHub.DistributedTask.Pipelines; using System.IO; -using GitHub.DistributedTask.Pipelines.ContextData; using System.Text.RegularExpressions; using GitHub.DistributedTask.Pipelines.Expressions; using System.Text; diff --git a/src/Runner.Plugins/Repository/v1.1/GitSourceProvider.cs b/src/Runner.Plugins/Repository/v1.1/GitSourceProvider.cs index 539b2b763f1..b2f50f45813 100644 --- a/src/Runner.Plugins/Repository/v1.1/GitSourceProvider.cs +++ b/src/Runner.Plugins/Repository/v1.1/GitSourceProvider.cs @@ -4,9 +4,7 @@ using System.Threading; using System.Threading.Tasks; using System.IO; -using System.Text.RegularExpressions; using System.Text; -using System.Diagnostics; using GitHub.Runner.Sdk; using System.Linq; using GitHub.DistributedTask.WebApi; diff --git a/src/Runner.Plugins/Repository/v1.1/RepositoryPlugin.cs b/src/Runner.Plugins/Repository/v1.1/RepositoryPlugin.cs index 3d6c87422a5..04c62b30194 100644 --- a/src/Runner.Plugins/Repository/v1.1/RepositoryPlugin.cs +++ b/src/Runner.Plugins/Repository/v1.1/RepositoryPlugin.cs @@ -1,13 +1,9 @@ -using System; -using System.Collections.Generic; -using System.Linq; +using System; using System.Threading; using System.Threading.Tasks; using GitHub.Runner.Sdk; using Pipelines = GitHub.DistributedTask.Pipelines; using System.IO; -using GitHub.DistributedTask.Pipelines.ContextData; -using System.Text.RegularExpressions; using GitHub.DistributedTask.Pipelines.Expressions; using System.Text; diff --git a/src/Runner.Sdk/ActionPlugin.cs b/src/Runner.Sdk/ActionPlugin.cs index 2a9d87a0a06..0a0f33ab457 100644 --- a/src/Runner.Sdk/ActionPlugin.cs +++ b/src/Runner.Sdk/ActionPlugin.cs @@ -1,7 +1,6 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; -using System.Net.Http; using System.Net.Http.Headers; using System.Runtime.InteropServices; using System.Threading; @@ -11,7 +10,6 @@ using GitHub.Services.Common; using GitHub.Services.WebApi; using Newtonsoft.Json; -using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Sdk { diff --git a/src/Runner.Sdk/Util/IOUtil.cs b/src/Runner.Sdk/Util/IOUtil.cs index 1c8a0cd506c..94a674da3b4 100644 --- a/src/Runner.Sdk/Util/IOUtil.cs +++ b/src/Runner.Sdk/Util/IOUtil.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Reflection; using System.Security.Cryptography; using System.Text; using System.Threading; diff --git a/src/Runner.Sdk/Util/PathUtil.cs b/src/Runner.Sdk/Util/PathUtil.cs index ac1704b5c8b..7a7575d20f5 100644 --- a/src/Runner.Sdk/Util/PathUtil.cs +++ b/src/Runner.Sdk/Util/PathUtil.cs @@ -1,4 +1,3 @@ -using System; using System.IO; namespace GitHub.Runner.Sdk diff --git a/src/Runner.Sdk/Util/StringUtil.cs b/src/Runner.Sdk/Util/StringUtil.cs index f5111ec89d4..e55fd7f4624 100644 --- a/src/Runner.Sdk/Util/StringUtil.cs +++ b/src/Runner.Sdk/Util/StringUtil.cs @@ -1,11 +1,7 @@ -using GitHub.Services.WebApi; +using GitHub.Services.WebApi; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Globalization; -using System.IO; -using System.Reflection; using System.Text; namespace GitHub.Runner.Sdk diff --git a/src/Runner.Worker/ActionManifestManager.cs b/src/Runner.Worker/ActionManifestManager.cs index 193c8a6eed9..a49a8e5eb2e 100644 --- a/src/Runner.Worker/ActionManifestManager.cs +++ b/src/Runner.Worker/ActionManifestManager.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Threading; @@ -10,9 +10,6 @@ using GitHub.DistributedTask.ObjectTemplating; using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.Pipelines.ContextData; -using YamlDotNet.Core; -using YamlDotNet.Core.Events; -using System.Globalization; using System.Linq; using Pipelines = GitHub.DistributedTask.Pipelines; diff --git a/src/Runner.Worker/ActionRunner.cs b/src/Runner.Worker/ActionRunner.cs index 1d18118a44c..257d6010942 100644 --- a/src/Runner.Worker/ActionRunner.cs +++ b/src/Runner.Worker/ActionRunner.cs @@ -1,6 +1,5 @@ -using System; +using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using GitHub.DistributedTask.ObjectTemplating; using GitHub.DistributedTask.ObjectTemplating.Tokens; diff --git a/src/Runner.Worker/ConditionTraceWriter.cs b/src/Runner.Worker/ConditionTraceWriter.cs index 951e4b4b219..1f98987ccd9 100644 --- a/src/Runner.Worker/ConditionTraceWriter.cs +++ b/src/Runner.Worker/ConditionTraceWriter.cs @@ -1,6 +1,5 @@ using System; using System.Text; -using GitHub.DistributedTask.Pipelines; using GitHub.Runner.Common; using GitHub.Runner.Sdk; using ObjectTemplating = GitHub.DistributedTask.ObjectTemplating; diff --git a/src/Runner.Worker/FileCommandManager.cs b/src/Runner.Worker/FileCommandManager.cs index 145291ccd4f..37aacfbe60a 100644 --- a/src/Runner.Worker/FileCommandManager.cs +++ b/src/Runner.Worker/FileCommandManager.cs @@ -1,9 +1,7 @@ -using GitHub.DistributedTask.WebApi; +using GitHub.DistributedTask.WebApi; using GitHub.Runner.Worker.Container; using GitHub.Runner.Common; -using GitHub.Runner.Sdk; using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; diff --git a/src/Runner.Worker/IEnvironmentContextData.cs b/src/Runner.Worker/IEnvironmentContextData.cs index b07bb169a9f..52b43e52be1 100644 --- a/src/Runner.Worker/IEnvironmentContextData.cs +++ b/src/Runner.Worker/IEnvironmentContextData.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; public interface IEnvironmentContextData diff --git a/src/Runner.Worker/JobExtension.cs b/src/Runner.Worker/JobExtension.cs index 09bbdd479d2..14004ecaf25 100644 --- a/src/Runner.Worker/JobExtension.cs +++ b/src/Runner.Worker/JobExtension.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -7,7 +7,6 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; -using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.ObjectTemplating.Tokens; using GitHub.DistributedTask.Pipelines; using GitHub.DistributedTask.Pipelines.ContextData; @@ -16,7 +15,6 @@ using GitHub.Runner.Common; using GitHub.Runner.Common.Util; using GitHub.Runner.Sdk; -using GitHub.Runner.Worker; using Pipelines = GitHub.DistributedTask.Pipelines; namespace GitHub.Runner.Worker diff --git a/src/Runner.Worker/JobExtensionRunner.cs b/src/Runner.Worker/JobExtensionRunner.cs index 48c2c2358e3..62fc3287fa3 100644 --- a/src/Runner.Worker/JobExtensionRunner.cs +++ b/src/Runner.Worker/JobExtensionRunner.cs @@ -1,6 +1,5 @@ -using System; +using System; using System.Threading.Tasks; -using GitHub.DistributedTask.Expressions2; using GitHub.DistributedTask.ObjectTemplating.Tokens; namespace GitHub.Runner.Worker From 0678e8df09681d438c469a603b0a671eb8199690 Mon Sep 17 00:00:00 2001 From: Thomas Boop <52323235+thboop@users.noreply.github.com> Date: Mon, 19 Sep 2022 11:28:46 -0400 Subject: [PATCH 12/22] Add Release branches to pull request spec (#2134) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67aeb533cbb..59d693aa68e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on: - '**.md' pull_request: branches: - - '*' + - '**' paths-ignore: - '**.md' From 15cbadb4af5499072564f48f709da888f860121c Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Mon, 26 Sep 2022 10:17:46 +0100 Subject: [PATCH 13/22] Add file commands for save-state and set-output (#2118) --- src/Runner.Common/ExtensionManager.cs | 2 + src/Runner.Worker/FileCommandManager.cs | 308 ++++++++----- src/Runner.Worker/GitHubContext.cs | 2 + src/Test/L0/Worker/SaveStateFileCommandL0.cs | 438 ++++++++++++++++++ src/Test/L0/Worker/SetOutputFileCommandL0.cs | 444 +++++++++++++++++++ 5 files changed, 1085 insertions(+), 109 deletions(-) create mode 100644 src/Test/L0/Worker/SaveStateFileCommandL0.cs create mode 100644 src/Test/L0/Worker/SetOutputFileCommandL0.cs diff --git a/src/Runner.Common/ExtensionManager.cs b/src/Runner.Common/ExtensionManager.cs index c7fbab73bcd..6f1bfc5d7b6 100644 --- a/src/Runner.Common/ExtensionManager.cs +++ b/src/Runner.Common/ExtensionManager.cs @@ -60,6 +60,8 @@ private List LoadExtensions() where T : class, IExtension Add(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker"); Add(extensions, "GitHub.Runner.Worker.SetEnvFileCommand, Runner.Worker"); Add(extensions, "GitHub.Runner.Worker.CreateStepSummaryCommand, Runner.Worker"); + Add(extensions, "GitHub.Runner.Worker.SaveStateFileCommand, Runner.Worker"); + Add(extensions, "GitHub.Runner.Worker.SetOutputFileCommand, Runner.Worker"); break; case "GitHub.Runner.Listener.Check.ICheckExtension": Add(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener"); diff --git a/src/Runner.Worker/FileCommandManager.cs b/src/Runner.Worker/FileCommandManager.cs index 37aacfbe60a..66362f6812a 100644 --- a/src/Runner.Worker/FileCommandManager.cs +++ b/src/Runner.Worker/FileCommandManager.cs @@ -138,74 +138,10 @@ public sealed class SetEnvFileCommand : RunnerService, IFileCommandExtension public void ProcessCommand(IExecutionContext context, string filePath, ContainerInfo container) { - try - { - var text = File.ReadAllText(filePath) ?? string.Empty; - var index = 0; - var line = ReadLine(text, ref index); - while (line != null) - { - if (!string.IsNullOrEmpty(line)) - { - var equalsIndex = line.IndexOf("=", StringComparison.Ordinal); - var heredocIndex = line.IndexOf("<<", StringComparison.Ordinal); - - // Normal style NAME=VALUE - if (equalsIndex >= 0 && (heredocIndex < 0 || equalsIndex < heredocIndex)) - { - var split = line.Split(new[] { '=' }, 2, StringSplitOptions.None); - if (string.IsNullOrEmpty(line)) - { - throw new Exception($"Invalid environment variable format '{line}'. Environment variable name must not be empty"); - } - SetEnvironmentVariable(context, split[0], split[1]); - } - // Heredoc style NAME<= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex)) - { - var split = line.Split(new[] { "<<" }, 2, StringSplitOptions.None); - if (string.IsNullOrEmpty(split[0]) || string.IsNullOrEmpty(split[1])) - { - throw new Exception($"Invalid environment variable format '{line}'. Environment variable name must not be empty and delimiter must not be empty"); - } - var name = split[0]; - var delimiter = split[1]; - var startIndex = index; // Start index of the value (inclusive) - var endIndex = index; // End index of the value (exclusive) - var tempLine = ReadLine(text, ref index, out var newline); - while (!string.Equals(tempLine, delimiter, StringComparison.Ordinal)) - { - if (tempLine == null) - { - throw new Exception($"Invalid environment variable value. Matching delimiter not found '{delimiter}'"); - } - if (newline == null) - { - throw new Exception($"Invalid environment variable value. EOF marker missing new line."); - } - endIndex = index - newline.Length; - tempLine = ReadLine(text, ref index, out newline); - } - - var value = endIndex > startIndex ? text.Substring(startIndex, endIndex - startIndex) : string.Empty; - SetEnvironmentVariable(context, name, value); - } - else - { - throw new Exception($"Invalid environment variable format '{line}'"); - } - } - - line = ReadLine(text, ref index); - } - } - catch (DirectoryNotFoundException) + var pairs = new EnvFileKeyValuePairs(context, filePath); + foreach (var pair in pairs) { - context.Debug($"Environment variables file does not exist '{filePath}'"); - } - catch (FileNotFoundException) - { - context.Debug($"Environment variables file does not exist '{filePath}'"); + SetEnvironmentVariable(context, pair.Key, pair.Value); } } @@ -218,48 +154,6 @@ private static void SetEnvironmentVariable( context.SetEnvContext(name, value); context.Debug($"{name}='{value}'"); } - - private static string ReadLine( - string text, - ref int index) - { - return ReadLine(text, ref index, out _); - } - - private static string ReadLine( - string text, - ref int index, - out string newline) - { - if (index >= text.Length) - { - newline = null; - return null; - } - - var originalIndex = index; - var lfIndex = text.IndexOf("\n", index, StringComparison.Ordinal); - if (lfIndex < 0) - { - index = text.Length; - newline = null; - return text.Substring(originalIndex); - } - -#if OS_WINDOWS - var crLFIndex = text.IndexOf("\r\n", index, StringComparison.Ordinal); - if (crLFIndex >= 0 && crLFIndex < lfIndex) - { - index = crLFIndex + 2; // Skip over CRLF - newline = "\r\n"; - return text.Substring(originalIndex, crLFIndex - originalIndex); - } -#endif - - index = lfIndex + 1; // Skip over LF - newline = "\n"; - return text.Substring(originalIndex, lfIndex - originalIndex); - } } public sealed class CreateStepSummaryCommand : RunnerService, IFileCommandExtension @@ -325,4 +219,200 @@ public void ProcessCommand(IExecutionContext context, string filePath, Container } } } + + public sealed class SaveStateFileCommand : RunnerService, IFileCommandExtension + { + public string ContextName => "state"; + public string FilePrefix => "save_state_"; + + public Type ExtensionType => typeof(IFileCommandExtension); + + public void ProcessCommand(IExecutionContext context, string filePath, ContainerInfo container) + { + var pairs = new EnvFileKeyValuePairs(context, filePath); + foreach (var pair in pairs) + { + // Embedded steps (composite) keep track of the state at the root level + if (context.IsEmbedded) + { + var id = context.EmbeddedId; + if (!context.Root.EmbeddedIntraActionState.ContainsKey(id)) + { + context.Root.EmbeddedIntraActionState[id] = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + context.Root.EmbeddedIntraActionState[id][pair.Key] = pair.Value; + } + // Otherwise modify the ExecutionContext + else + { + context.IntraActionState[pair.Key] = pair.Value; + } + + context.Debug($"Save intra-action state {pair.Key} = {pair.Value}"); + } + } + } + + public sealed class SetOutputFileCommand : RunnerService, IFileCommandExtension + { + public string ContextName => "output"; + public string FilePrefix => "set_output_"; + + public Type ExtensionType => typeof(IFileCommandExtension); + + public void ProcessCommand(IExecutionContext context, string filePath, ContainerInfo container) + { + var pairs = new EnvFileKeyValuePairs(context, filePath); + foreach (var pair in pairs) + { + context.SetOutput(pair.Key, pair.Value, out var reference); + context.Debug($"Set output {pair.Key} = {pair.Value}"); + } + } + } + + public sealed class EnvFileKeyValuePairs: IEnumerable> + { + private IExecutionContext _context; + private string _filePath; + + public EnvFileKeyValuePairs(IExecutionContext context, string filePath) + { + _context = context; + _filePath = filePath; + } + + public IEnumerator> GetEnumerator() + { + var text = string.Empty; + try + { + text = File.ReadAllText(_filePath) ?? string.Empty; + } + catch (DirectoryNotFoundException) + { + _context.Debug($"File does not exist '{_filePath}'"); + yield break; + } + catch (FileNotFoundException) + { + _context.Debug($"File does not exist '{_filePath}'"); + yield break; + } + + var index = 0; + var line = ReadLine(text, ref index); + while (line != null) + { + if (!string.IsNullOrEmpty(line)) + { + var key = string.Empty; + var output = string.Empty; + + var equalsIndex = line.IndexOf("=", StringComparison.Ordinal); + var heredocIndex = line.IndexOf("<<", StringComparison.Ordinal); + + // Normal style NAME=VALUE + if (equalsIndex >= 0 && (heredocIndex < 0 || equalsIndex < heredocIndex)) + { + var split = line.Split(new[] { '=' }, 2, StringSplitOptions.None); + if (string.IsNullOrEmpty(line)) + { + throw new Exception($"Invalid format '{line}'. Name must not be empty"); + } + + key = split[0]; + output = split[1]; + } + + // Heredoc style NAME<= 0 && (equalsIndex < 0 || heredocIndex < equalsIndex)) + { + var split = line.Split(new[] { "<<" }, 2, StringSplitOptions.None); + if (string.IsNullOrEmpty(split[0]) || string.IsNullOrEmpty(split[1])) + { + throw new Exception($"Invalid format '{line}'. Name must not be empty and delimiter must not be empty"); + } + key = split[0]; + var delimiter = split[1]; + var startIndex = index; // Start index of the value (inclusive) + var endIndex = index; // End index of the value (exclusive) + var tempLine = ReadLine(text, ref index, out var newline); + while (!string.Equals(tempLine, delimiter, StringComparison.Ordinal)) + { + if (tempLine == null) + { + throw new Exception($"Invalid value. Matching delimiter not found '{delimiter}'"); + } + if (newline == null) + { + throw new Exception($"Invalid value. EOF marker missing new line."); + } + endIndex = index - newline.Length; + tempLine = ReadLine(text, ref index, out newline); + } + + output = endIndex > startIndex ? text.Substring(startIndex, endIndex - startIndex) : string.Empty; + } + else + { + throw new Exception($"Invalid format '{line}'"); + } + + yield return new KeyValuePair(key, output); + } + + line = ReadLine(text, ref index); + } + } + + System.Collections.IEnumerator + System.Collections.IEnumerable.GetEnumerator() + { + // Invoke IEnumerator> GetEnumerator() above. + return GetEnumerator(); + } + + private static string ReadLine( + string text, + ref int index) + { + return ReadLine(text, ref index, out _); + } + + private static string ReadLine( + string text, + ref int index, + out string newline) + { + if (index >= text.Length) + { + newline = null; + return null; + } + + var originalIndex = index; + var lfIndex = text.IndexOf("\n", index, StringComparison.Ordinal); + if (lfIndex < 0) + { + index = text.Length; + newline = null; + return text.Substring(originalIndex); + } + +#if OS_WINDOWS + var crLFIndex = text.IndexOf("\r\n", index, StringComparison.Ordinal); + if (crLFIndex >= 0 && crLFIndex < lfIndex) + { + index = crLFIndex + 2; // Skip over CRLF + newline = "\r\n"; + return text.Substring(originalIndex, crLFIndex - originalIndex); + } +#endif + + index = lfIndex + 1; // Skip over LF + newline = "\n"; + return text.Substring(originalIndex, lfIndex - originalIndex); + } + } } diff --git a/src/Runner.Worker/GitHubContext.cs b/src/Runner.Worker/GitHubContext.cs index cdefd45b405..f320705eba0 100644 --- a/src/Runner.Worker/GitHubContext.cs +++ b/src/Runner.Worker/GitHubContext.cs @@ -21,6 +21,7 @@ public sealed class GitHubContext : DictionaryContextData, IEnvironmentContextDa "graphql_url", "head_ref", "job", + "output", "path", "ref_name", "ref_protected", @@ -34,6 +35,7 @@ public sealed class GitHubContext : DictionaryContextData, IEnvironmentContextDa "run_number", "server_url", "sha", + "state", "step_summary", "triggering_actor", "workflow", diff --git a/src/Test/L0/Worker/SaveStateFileCommandL0.cs b/src/Test/L0/Worker/SaveStateFileCommandL0.cs new file mode 100644 index 00000000000..45296c70978 --- /dev/null +++ b/src/Test/L0/Worker/SaveStateFileCommandL0.cs @@ -0,0 +1,438 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; +using GitHub.Runner.Common.Util; +using GitHub.Runner.Sdk; +using GitHub.Runner.Worker; +using GitHub.Runner.Worker.Container; +using GitHub.Runner.Worker.Handlers; +using Moq; +using Xunit; +using DTWebApi = GitHub.DistributedTask.WebApi; + +namespace GitHub.Runner.Common.Tests.Worker +{ + public sealed class SaveStateFileCommandL0 + { + private Mock _executionContext; + private List> _issues; + private string _rootDirectory; + private SaveStateFileCommand _saveStateFileCommand; + private Dictionary _intraActionState; + private ITraceWriter _trace; + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_DirectoryNotFound() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "directory-not-found", "env"); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(0, _intraActionState.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_NotFound() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "file-not-found"); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(0, _intraActionState.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_EmptyFile() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "empty-file"); + var content = new List(); + WriteContent(stateFile, content); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(0, _intraActionState.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Simple() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + "MY_STATE=MY VALUE", + }; + WriteContent(stateFile, content); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(1, _intraActionState.Count); + Assert.Equal("MY VALUE", _intraActionState["MY_STATE"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Simple_SkipEmptyLines() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + string.Empty, + "MY_STATE=my value", + string.Empty, + "MY_STATE_2=my second value", + string.Empty, + }; + WriteContent(stateFile, content); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(2, _intraActionState.Count); + Assert.Equal("my value", _intraActionState["MY_STATE"]); + Assert.Equal("my second value", _intraActionState["MY_STATE_2"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Simple_EmptyValue() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple-empty-value"); + var content = new List + { + "MY_STATE=", + }; + WriteContent(stateFile, content); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(1, _intraActionState.Count); + Assert.Equal(string.Empty, _intraActionState["MY_STATE"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Simple_MultipleValues() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + "MY_STATE=my value", + "MY_STATE_2=", + "MY_STATE_3=my third value", + }; + WriteContent(stateFile, content); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(3, _intraActionState.Count); + Assert.Equal("my value", _intraActionState["MY_STATE"]); + Assert.Equal(string.Empty, _intraActionState["MY_STATE_2"]); + Assert.Equal("my third value", _intraActionState["MY_STATE_3"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Simple_SpecialCharacters() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + "MY_STATE==abc", + "MY_STATE_2=def=ghi", + "MY_STATE_3=jkl=", + }; + WriteContent(stateFile, content); + _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(3, _intraActionState.Count); + Assert.Equal("=abc", _intraActionState["MY_STATE"]); + Assert.Equal("def=ghi", _intraActionState["MY_STATE_2"]); + Assert.Equal("jkl=", _intraActionState["MY_STATE_3"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Heredoc() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "heredoc"); + var content = new List + { + "MY_STATE< + { + "MY_STATE< + { + string.Empty, + "MY_STATE< + { + "MY_STATE<<=EOF", + "hello", + "one", + "=EOF", + "MY_STATE_2<< + { + "MY_STATE<(() => _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null)); + Assert.Contains("Matching delimiter not found", ex.Message); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Heredoc_MissingNewLineMultipleLines() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "heredoc"); + var content = new List + { + "MY_STATE<(() => _saveStateFileCommand.ProcessCommand(_executionContext.Object, stateFile, null)); + Assert.Contains("EOF marker missing new line", ex.Message); + } + } + +#if OS_WINDOWS + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SaveStateFileCommand_Heredoc_PreservesNewline() + { + using (var hostContext = Setup()) + { + var newline = "\n"; + var stateFile = Path.Combine(_rootDirectory, "heredoc"); + var content = new List + { + "MY_STATE< content, + string newline = null) + { + if (string.IsNullOrEmpty(newline)) + { + newline = Environment.NewLine; + } + + var encoding = new UTF8Encoding(true); // Emit BOM + var contentStr = string.Join(newline, content); + File.WriteAllText(path, contentStr, encoding); + } + + private TestHostContext Setup([CallerMemberName] string name = "") + { + _issues = new List>(); + _intraActionState = new Dictionary(); + + var hostContext = new TestHostContext(this, name); + + // Trace + _trace = hostContext.GetTrace(); + + // Directory for test data + var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work); + ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory)); + Directory.CreateDirectory(workDirectory); + _rootDirectory = Path.Combine(workDirectory, nameof(SaveStateFileCommandL0)); + Directory.CreateDirectory(_rootDirectory); + + // Execution context + _executionContext = new Mock(); + _executionContext.Setup(x => x.Global) + .Returns(new GlobalContext + { + EnvironmentVariables = new Dictionary(VarUtil.EnvironmentVariableKeyComparer), + WriteDebug = true, + }); + _executionContext.Setup(x => x.AddIssue(It.IsAny(), It.IsAny())) + .Callback((DTWebApi.Issue issue, string logMessage) => + { + _issues.Add(new Tuple(issue, logMessage)); + var message = !string.IsNullOrEmpty(logMessage) ? logMessage : issue.Message; + _trace.Info($"Issue '{issue.Type}': {message}"); + }); + _executionContext.Setup(x => x.Write(It.IsAny(), It.IsAny())) + .Callback((string tag, string message) => + { + _trace.Info($"{tag}{message}"); + }); + _executionContext.Setup(x => x.IntraActionState) + .Returns(_intraActionState); + + // SaveStateFileCommand + _saveStateFileCommand = new SaveStateFileCommand(); + _saveStateFileCommand.Initialize(hostContext); + + return hostContext; + } + } +} diff --git a/src/Test/L0/Worker/SetOutputFileCommandL0.cs b/src/Test/L0/Worker/SetOutputFileCommandL0.cs new file mode 100644 index 00000000000..8af9695db46 --- /dev/null +++ b/src/Test/L0/Worker/SetOutputFileCommandL0.cs @@ -0,0 +1,444 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; +using GitHub.Runner.Common.Util; +using GitHub.Runner.Sdk; +using GitHub.Runner.Worker; +using GitHub.Runner.Worker.Container; +using GitHub.Runner.Worker.Handlers; +using Moq; +using Xunit; +using DTWebApi = GitHub.DistributedTask.WebApi; + +namespace GitHub.Runner.Common.Tests.Worker +{ + public sealed class SetOutputFileCommandL0 + { + private Mock _executionContext; + private List> _issues; + private Dictionary _outputs; + private string _rootDirectory; + private SetOutputFileCommand _setOutputFileCommand; + private ITraceWriter _trace; + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_DirectoryNotFound() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "directory-not-found", "env"); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(0, _outputs.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_NotFound() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "file-not-found"); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(0, _outputs.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_EmptyFile() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "empty-file"); + var content = new List(); + WriteContent(stateFile, content); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(0, _outputs.Count); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Simple() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + "MY_OUTPUT=MY VALUE", + }; + WriteContent(stateFile, content); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(1, _outputs.Count); + Assert.Equal("MY VALUE", _outputs["MY_OUTPUT"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Simple_SkipEmptyLines() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + string.Empty, + "MY_OUTPUT=my value", + string.Empty, + "MY_OUTPUT_2=my second value", + string.Empty, + }; + WriteContent(stateFile, content); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(2, _outputs.Count); + Assert.Equal("my value", _outputs["MY_OUTPUT"]); + Assert.Equal("my second value", _outputs["MY_OUTPUT_2"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Simple_EmptyValue() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple-empty-value"); + var content = new List + { + "MY_OUTPUT=", + }; + WriteContent(stateFile, content); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(1, _outputs.Count); + Assert.Equal(string.Empty, _outputs["MY_OUTPUT"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Simple_MultipleValues() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + "MY_OUTPUT=my value", + "MY_OUTPUT_2=", + "MY_OUTPUT_3=my third value", + }; + WriteContent(stateFile, content); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(3, _outputs.Count); + Assert.Equal("my value", _outputs["MY_OUTPUT"]); + Assert.Equal(string.Empty, _outputs["MY_OUTPUT_2"]); + Assert.Equal("my third value", _outputs["MY_OUTPUT_3"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Simple_SpecialCharacters() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "simple"); + var content = new List + { + "MY_OUTPUT==abc", + "MY_OUTPUT_2=def=ghi", + "MY_OUTPUT_3=jkl=", + }; + WriteContent(stateFile, content); + _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null); + Assert.Equal(0, _issues.Count); + Assert.Equal(3, _outputs.Count); + Assert.Equal("=abc", _outputs["MY_OUTPUT"]); + Assert.Equal("def=ghi", _outputs["MY_OUTPUT_2"]); + Assert.Equal("jkl=", _outputs["MY_OUTPUT_3"]); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Heredoc() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "heredoc"); + var content = new List + { + "MY_OUTPUT< + { + "MY_OUTPUT< + { + string.Empty, + "MY_OUTPUT< + { + "MY_OUTPUT<<=EOF", + "hello", + "one", + "=EOF", + "MY_OUTPUT_2<< + { + "MY_OUTPUT<(() => _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null)); + Assert.Contains("Matching delimiter not found", ex.Message); + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Heredoc_MissingNewLineMultipleLines() + { + using (var hostContext = Setup()) + { + var stateFile = Path.Combine(_rootDirectory, "heredoc"); + var content = new List + { + "MY_OUTPUT<(() => _setOutputFileCommand.ProcessCommand(_executionContext.Object, stateFile, null)); + Assert.Contains("EOF marker missing new line", ex.Message); + } + } + +#if OS_WINDOWS + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void SetOutputFileCommand_Heredoc_PreservesNewline() + { + using (var hostContext = Setup()) + { + var newline = "\n"; + var stateFile = Path.Combine(_rootDirectory, "heredoc"); + var content = new List + { + "MY_OUTPUT< content, + string newline = null) + { + if (string.IsNullOrEmpty(newline)) + { + newline = Environment.NewLine; + } + + var encoding = new UTF8Encoding(true); // Emit BOM + var contentStr = string.Join(newline, content); + File.WriteAllText(path, contentStr, encoding); + } + + private TestHostContext Setup([CallerMemberName] string name = "") + { + _issues = new List>(); + _outputs = new Dictionary(); + + var hostContext = new TestHostContext(this, name); + + // Trace + _trace = hostContext.GetTrace(); + + // Directory for test data + var workDirectory = hostContext.GetDirectory(WellKnownDirectory.Work); + ArgUtil.NotNullOrEmpty(workDirectory, nameof(workDirectory)); + Directory.CreateDirectory(workDirectory); + _rootDirectory = Path.Combine(workDirectory, nameof(SetOutputFileCommandL0)); + Directory.CreateDirectory(_rootDirectory); + + // Execution context + _executionContext = new Mock(); + _executionContext.Setup(x => x.Global) + .Returns(new GlobalContext + { + EnvironmentVariables = new Dictionary(VarUtil.EnvironmentVariableKeyComparer), + WriteDebug = true, + }); + _executionContext.Setup(x => x.AddIssue(It.IsAny(), It.IsAny())) + .Callback((DTWebApi.Issue issue, string logMessage) => + { + _issues.Add(new Tuple(issue, logMessage)); + var message = !string.IsNullOrEmpty(logMessage) ? logMessage : issue.Message; + _trace.Info($"Issue '{issue.Type}': {message}"); + }); + _executionContext.Setup(x => x.Write(It.IsAny(), It.IsAny())) + .Callback((string tag, string message) => + { + _trace.Info($"{tag}{message}"); + }); + + var reference = string.Empty; + _executionContext.Setup(x => x.SetOutput(It.IsAny(), It.IsAny(), out reference)) + .Callback((string name, string value, out string reference) => + { + reference = value; + _outputs[name] = value; + }); + + // SetOutputFileCommand + _setOutputFileCommand = new SetOutputFileCommand(); + _setOutputFileCommand.Initialize(hostContext); + + return hostContext; + } + } +} From ae2f4a6f2724dbbbf764b3b77a2114d6c3603b95 Mon Sep 17 00:00:00 2001 From: Thomas Boop <52323235+thboop@users.noreply.github.com> Date: Mon, 26 Sep 2022 09:20:43 -0400 Subject: [PATCH 14/22] POC: Windows arm64 runner build (#2022) Prerelease for windows-arm64 runner build --- .github/workflows/build.yml | 10 ++- .github/workflows/release.yml | 77 +++++++++++++++++-- docs/contribute.md | 2 + releaseNote.md | 20 +++++ src/Directory.Build.props | 3 + src/Misc/contentHash/dotnetRuntime/win-arm64 | 1 + src/Misc/contentHash/externals/win-arm64 | 1 + src/Misc/externals.sh | 11 +++ src/Misc/runnerdotnetruntimeassets | 4 +- src/Runner.Common/Constants.cs | 15 +++- src/Runner.Common/Runner.Common.csproj | 2 +- src/Runner.Common/Util/NodeUtil.cs | 2 +- src/Runner.Listener/Program.cs | 12 +++ src/Runner.Listener/Runner.Listener.csproj | 2 +- .../Runner.PluginHost.csproj | 2 +- src/Runner.Plugins/Runner.Plugins.csproj | 2 +- src/Runner.Sdk/Runner.Sdk.csproj | 4 +- src/Runner.Service/Windows/App.config | 4 +- src/Runner.Service/Windows/AppARM.config | 6 ++ .../Windows/RunnerService.csproj | 14 +++- .../Handlers/NodeScriptActionHandler.cs | 10 ++- src/Runner.Worker/Runner.Worker.csproj | 2 +- src/Sdk/Sdk.csproj | 2 +- src/Test/L0/ConstantGenerationL0.cs | 1 + src/Test/L0/Listener/SelfUpdaterL0.cs | 2 +- src/Test/Test.csproj | 4 +- src/dev.sh | 35 +++++---- src/dir.proj | 12 +-- 28 files changed, 210 insertions(+), 52 deletions(-) create mode 100644 src/Misc/contentHash/dotnetRuntime/win-arm64 create mode 100644 src/Misc/contentHash/externals/win-arm64 create mode 100644 src/Runner.Service/Windows/AppARM.config diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 59d693aa68e..fd13c5b1260 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: build: strategy: matrix: - runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ] + runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, win-arm64, osx-x64, osx-arm64 ] include: - runtime: linux-x64 os: ubuntu-latest @@ -44,6 +44,10 @@ jobs: os: windows-2019 devScript: ./dev + - runtime: win-arm64 + os: windows-latest + devScript: ./dev + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -82,7 +86,7 @@ jobs: run: | ${{ matrix.devScript }} test working-directory: src - if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' + if: matrix.runtime != 'linux-arm64' && matrix.runtime != 'linux-arm' && matrix.runtime != 'osx-arm64' && matrix.runtime != 'win-arm64' # Create runner package tar.gz/zip - name: Package Release @@ -97,7 +101,7 @@ jobs: uses: actions/upload-artifact@v2 with: name: runner-package-${{ matrix.runtime }} - path: | + path: | _package _package_trims/trim_externals _package_trims/trim_runtime diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a3ec84623ce..20927e2176f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,29 +50,33 @@ jobs: linux-arm64-sha: ${{ steps.sha.outputs.linux-arm64-sha256 }} linux-arm-sha: ${{ steps.sha.outputs.linux-arm-sha256 }} win-x64-sha: ${{ steps.sha.outputs.win-x64-sha256 }} + win-arm64-sha: ${{ steps.sha.outputs.win-arm64-sha256 }} osx-x64-sha: ${{ steps.sha.outputs.osx-x64-sha256 }} osx-arm64-sha: ${{ steps.sha.outputs.osx-arm64-sha256 }} linux-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-x64-sha256 }} linux-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm64-sha256 }} linux-arm-sha-noexternals: ${{ steps.sha_noexternals.outputs.linux-arm-sha256 }} win-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-x64-sha256 }} + win-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.win-arm64-sha256 }} osx-x64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-x64-sha256 }} osx-arm64-sha-noexternals: ${{ steps.sha_noexternals.outputs.osx-arm64-sha256 }} linux-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-x64-sha256 }} linux-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm64-sha256 }} linux-arm-sha-noruntime: ${{ steps.sha_noruntime.outputs.linux-arm-sha256 }} win-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-x64-sha256 }} + win-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.win-arm64-sha256 }} osx-x64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-x64-sha256 }} osx-arm64-sha-noruntime: ${{ steps.sha_noruntime.outputs.osx-arm64-sha256 }} linux-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-x64-sha256 }} linux-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm64-sha256 }} linux-arm-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.linux-arm-sha256 }} win-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-x64-sha256 }} + win-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.win-arm64-sha256 }} osx-x64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-x64-sha256 }} osx-arm64-sha-noruntime-noexternals: ${{ steps.sha_noruntime_noexternals.outputs.osx-arm64-sha256 }} strategy: matrix: - runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64 ] + runtime: [ linux-x64, linux-arm64, linux-arm, win-x64, osx-x64, osx-arm64, win-arm64 ] include: - runtime: linux-x64 os: ubuntu-latest @@ -89,7 +93,7 @@ jobs: - runtime: osx-x64 os: macOS-latest devScript: ./dev.sh - + - runtime: osx-arm64 os: macOS-latest devScript: ./dev.sh @@ -98,6 +102,10 @@ jobs: os: windows-2019 devScript: ./dev + - runtime: win-arm64 + os: windows-latest + devScript: ./dev + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -158,9 +166,9 @@ jobs: id: sha_noruntime_noexternals name: Compute SHA256 working-directory: _package_trims/trim_runtime_externals - + - name: Create trimmedpackages.json for ${{ matrix.runtime }} - if: matrix.runtime == 'win-x64' + if: matrix.runtime == 'win-x64' || matrix.runtime == 'win-arm64' uses: actions/github-script@0.3.0 with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -180,7 +188,7 @@ jobs: fs.writeFileSync('${{ matrix.runtime }}-trimmedpackages.json', trimmedPackages) - name: Create trimmedpackages.json for ${{ matrix.runtime }} - if: matrix.runtime != 'win-x64' + if: matrix.runtime != 'win-x64' && matrix.runtime != 'win-arm64' uses: actions/github-script@0.3.0 with: github-token: ${{secrets.GITHUB_TOKEN}} @@ -239,24 +247,28 @@ jobs: const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '') var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(//g, runnerVersion) releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha-noexternals}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha-noruntime}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha-noruntime-noexternals}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}') @@ -271,6 +283,7 @@ jobs: run: | ls -l echo "${{needs.build.outputs.win-x64-sha}} actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c + echo "${{needs.build.outputs.win-arm64-sha}} actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip" | shasum -a 256 -c echo "${{needs.build.outputs.osx-x64-sha}} actions-runner-osx-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.osx-arm64-sha}} actions-runner-osx-arm64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c echo "${{needs.build.outputs.linux-x64-sha}} actions-runner-linux-x64-${{ steps.releaseNote.outputs.version }}.tar.gz" | shasum -a 256 -c @@ -300,6 +313,16 @@ jobs: asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}.zip asset_content_type: application/octet-stream + - name: Upload Release Asset (win-arm64) + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.createRelease.outputs.upload_url }} + asset_path: ${{ github.workspace }}/_package/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip + asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}.zip + asset_content_type: application/octet-stream + - name: Upload Release Asset (linux-x64) uses: actions/upload-release-asset@v1.0.1 env: @@ -361,6 +384,17 @@ jobs: asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noexternals.zip asset_content_type: application/octet-stream + # Upload release assets (trim externals) + - name: Upload Release Asset (win-arm64-noexternals) + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.createRelease.outputs.upload_url }} + asset_path: ${{ github.workspace }}/_package_trims/trim_externals/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.zip + asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noexternals.zip + asset_content_type: application/octet-stream + - name: Upload Release Asset (linux-x64-noexternals) uses: actions/upload-release-asset@v1.0.1 env: @@ -422,6 +456,17 @@ jobs: asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime.zip asset_content_type: application/octet-stream + # Upload release assets (trim runtime) + - name: Upload Release Asset (win-arm64-noruntime) + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.createRelease.outputs.upload_url }} + asset_path: ${{ github.workspace }}/_package_trims/trim_runtime/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.zip + asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime.zip + asset_content_type: application/octet-stream + - name: Upload Release Asset (linux-x64-noruntime) uses: actions/upload-release-asset@v1.0.1 env: @@ -483,6 +528,17 @@ jobs: asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip asset_content_type: application/octet-stream + # Upload release assets (trim runtime and externals) + - name: Upload Release Asset (win-arm64-noruntime-noexternals) + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.createRelease.outputs.upload_url }} + asset_path: ${{ github.workspace }}/_package_trims/trim_runtime_externals/actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip + asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-noruntime-noexternals.zip + asset_content_type: application/octet-stream + - name: Upload Release Asset (linux-x64-noruntime-noexternals) uses: actions/upload-release-asset@v1.0.1 env: @@ -544,6 +600,17 @@ jobs: asset_name: actions-runner-win-x64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json asset_content_type: application/octet-stream + # Upload release assets (trimmedpackages.json) + - name: Upload Release Asset (win-arm64-trimmedpackages.json) + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.createRelease.outputs.upload_url }} + asset_path: ${{ github.workspace }}/win-arm64-trimmedpackages.json + asset_name: actions-runner-win-arm64-${{ steps.releaseNote.outputs.version }}-trimmedpackages.json + asset_content_type: application/octet-stream + - name: Upload Release Asset (linux-x64-trimmedpackages.json) uses: actions/upload-release-asset@v1.0.1 env: diff --git a/docs/contribute.md b/docs/contribute.md index fab3563afc7..bb046f4cb9a 100644 --- a/docs/contribute.md +++ b/docs/contribute.md @@ -27,6 +27,8 @@ An ADR is an Architectural Decision Record. This allows consensus on the direct ![Win](res/win_sm.png) Visual Studio 2017 or newer [Install here](https://visualstudio.microsoft.com) (needed for dev sh script) +![Win-arm](res/win_sm.png) Visual Studio 2022 17.3 Preview or later. [Install here](https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes-preview) + ## Quickstart: Run a job from a real repository If you just want to get from building the sourcecode to using it to execute an action, you will need: diff --git a/releaseNote.md b/releaseNote.md index b70766e7098..9392b24cc30 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -16,6 +16,22 @@ Add-Type -AssemblyName System.IO.Compression.FileSystem ; [System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-x64-.zip", "$PWD") ``` +## [Pre-release] Windows arm64 +**Warning:** Windows arm64 runners are currently in preview status and use [unofficial versions of nodejs](https://unofficial-builds.nodejs.org/). They are not intended for production workflows. + +We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows. + +The following snipped needs to be run on `powershell`: +``` powershell +# Create a folder under the drive root +mkdir \actions-runner ; cd \actions-runner +# Download the latest runner package +Invoke-WebRequest -Uri https://github.com/actions/runner/releases/download/v/actions-runner-win-arm64-.zip -OutFile actions-runner-win-arm64-.zip +# Extract the installer +Add-Type -AssemblyName System.IO.Compression.FileSystem ; +[System.IO.Compression.ZipFile]::ExtractToDirectory("$PWD\actions-runner-win-arm64-.zip", "$PWD") +``` + ## OSX x64 ``` bash @@ -79,6 +95,7 @@ For additional details about configuring, running, or shutting down the runner p The SHA-256 checksums for the packages included in this build are shown below: - actions-runner-win-x64-.zip +- actions-runner-win-arm64-.zip - actions-runner-osx-x64-.tar.gz - actions-runner-osx-arm64-.tar.gz - actions-runner-linux-x64-.tar.gz @@ -86,6 +103,7 @@ The SHA-256 checksums for the packages included in this build are shown below: - actions-runner-linux-arm-.tar.gz - actions-runner-win-x64--noexternals.zip +- actions-runner-win-arm64--noexternals.zip - actions-runner-osx-x64--noexternals.tar.gz - actions-runner-osx-arm64--noexternals.tar.gz - actions-runner-linux-x64--noexternals.tar.gz @@ -93,6 +111,7 @@ The SHA-256 checksums for the packages included in this build are shown below: - actions-runner-linux-arm--noexternals.tar.gz - actions-runner-win-x64--noruntime.zip +- actions-runner-win-arm64--noruntime.zip - actions-runner-osx-x64--noruntime.tar.gz - actions-runner-osx-arm64--noruntime.tar.gz - actions-runner-linux-x64--noruntime.tar.gz @@ -100,6 +119,7 @@ The SHA-256 checksums for the packages included in this build are shown below: - actions-runner-linux-arm--noruntime.tar.gz - actions-runner-win-x64--noruntime-noexternals.zip +- actions-runner-win-arm64--noruntime-noexternals.zip - actions-runner-osx-x64--noruntime-noexternals.tar.gz - actions-runner-osx-arm64--noruntime-noexternals.tar.gz - actions-runner-linux-x64--noruntime-noexternals.tar.gz diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 1931b7f8f08..9db5faca37a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -24,6 +24,9 @@ $(DefineConstants);X86 + + $(DefineConstants);ARM64 + $(DefineConstants);X64 diff --git a/src/Misc/contentHash/dotnetRuntime/win-arm64 b/src/Misc/contentHash/dotnetRuntime/win-arm64 new file mode 100644 index 00000000000..8d279b0417b --- /dev/null +++ b/src/Misc/contentHash/dotnetRuntime/win-arm64 @@ -0,0 +1 @@ +39d0683f0f115a211cb10c473e9574c16549a19d4e9a6c637ded3d7022bf809f diff --git a/src/Misc/contentHash/externals/win-arm64 b/src/Misc/contentHash/externals/win-arm64 new file mode 100644 index 00000000000..bd10bc5ea31 --- /dev/null +++ b/src/Misc/contentHash/externals/win-arm64 @@ -0,0 +1 @@ +e5dace2d41cc0682d096dcce4970079ad48ec7107e46195970eecfdb3df2acef diff --git a/src/Misc/externals.sh b/src/Misc/externals.sh index b11b225f751..123c46ce5bd 100755 --- a/src/Misc/externals.sh +++ b/src/Misc/externals.sh @@ -3,6 +3,7 @@ PACKAGERUNTIME=$1 PRECACHE=$2 NODE_URL=https://nodejs.org/dist +UNOFFICIAL_NODE_URL=https://unofficial-builds.nodejs.org/download/release NODE12_VERSION="12.22.7" NODE16_VERSION="16.13.0" @@ -134,6 +135,16 @@ if [[ "$PACKAGERUNTIME" == "win-x64" || "$PACKAGERUNTIME" == "win-x86" ]]; then fi fi +# Download the external tools only for Windows. +if [[ "$PACKAGERUNTIME" == "win-arm64" ]]; then + # todo: replace these with official release when available + acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.exe" node16/bin + acquireExternalTool "$UNOFFICIAL_NODE_URL/v${NODE16_VERSION}/$PACKAGERUNTIME/node.lib" node16/bin + if [[ "$PRECACHE" != "" ]]; then + acquireExternalTool "https://github.com/microsoft/vswhere/releases/download/2.6.7/vswhere.exe" vswhere + fi +fi + # Download the external tools only for OSX. if [[ "$PACKAGERUNTIME" == "osx-x64" ]]; then acquireExternalTool "$NODE_URL/v${NODE12_VERSION}/node-v${NODE12_VERSION}-darwin-x64.tar.gz" node12 fix_nested_dir diff --git a/src/Misc/runnerdotnetruntimeassets b/src/Misc/runnerdotnetruntimeassets index 1cbb627713c..fa2d9e04b4c 100644 --- a/src/Misc/runnerdotnetruntimeassets +++ b/src/Misc/runnerdotnetruntimeassets @@ -66,12 +66,14 @@ libmscordbi.dylib libmscordbi.so Microsoft.CSharp.dll Microsoft.DiaSymReader.Native.amd64.dll +Microsoft.DiaSymReader.Native.arm64.dll Microsoft.VisualBasic.Core.dll Microsoft.VisualBasic.dll Microsoft.Win32.Primitives.dll Microsoft.Win32.Registry.dll mscordaccore.dll mscordaccore_amd64_amd64_6.0.522.21309.dll +mscordaccore_arm64_arm64_6.0.522.21309.dll mscordbi.dll mscorlib.dll mscorrc.debug.dll @@ -261,4 +263,4 @@ System.Xml.XmlSerializer.dll System.Xml.XPath.dll System.Xml.XPath.XDocument.dll ucrtbase.dll -WindowsBase.dll \ No newline at end of file +WindowsBase.dll diff --git a/src/Runner.Common/Constants.cs b/src/Runner.Common/Constants.cs index 0e756ae552d..25ccc96132f 100644 --- a/src/Runner.Common/Constants.cs +++ b/src/Runner.Common/Constants.cs @@ -77,7 +77,7 @@ public static class Runner public static readonly Architecture PlatformArchitecture = Architecture.X64; #elif ARM public static readonly Architecture PlatformArchitecture = Architecture.Arm; -#elif ARM64 +#elif ARM64 public static readonly Architecture PlatformArchitecture = Architecture.Arm64; #endif @@ -152,7 +152,7 @@ public static class Features public static readonly string DiskSpaceWarning = "runner.diskspace.warning"; public static readonly string Node12Warning = "DistributedTask.AddWarningToNode12Action"; public static readonly string UseContainerPathForTemplate = "DistributedTask.UseContainerPathForTemplate"; - public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks"; + public static readonly string AllowRunnerContainerHooks = "DistributedTask.AllowRunnerContainerHooks"; } public static readonly string InternalTelemetryIssueDataKey = "_internal_telemetry"; @@ -241,8 +241,8 @@ public static class Agent public static readonly string ToolsDirectory = "agent.ToolsDirectory"; // Set this env var to "node12" to downgrade the node version for internal functions (e.g hashfiles). This does NOT affect the version of node actions. - public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION"; - public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION"; + public static readonly string ForcedInternalNodeVersion = "ACTIONS_RUNNER_FORCED_INTERNAL_NODE_VERSION"; + public static readonly string ForcedActionsNodeVersion = "ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION"; } public static class System @@ -255,5 +255,12 @@ public static class System public static readonly string PhaseDisplayName = "system.phaseDisplayName"; } } + + public static class OperatingSystem + { + public static readonly int Windows11BuildVersion = 22000; + // Both windows 10 and windows 11 share the same Major Version 10, need to use the build version to differentiate + public static readonly int Windows11MajorVersion = 10; + } } } diff --git a/src/Runner.Common/Runner.Common.csproj b/src/Runner.Common/Runner.Common.csproj index bfbdc5f2e16..64bf4cda35a 100644 --- a/src/Runner.Common/Runner.Common.csproj +++ b/src/Runner.Common/Runner.Common.csproj @@ -3,7 +3,7 @@ net6.0 Library - win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64 + win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64 true NU1701;NU1603 $(Version) diff --git a/src/Runner.Common/Util/NodeUtil.cs b/src/Runner.Common/Util/NodeUtil.cs index 8fbf53bdf52..a9cbfc6df21 100644 --- a/src/Runner.Common/Util/NodeUtil.cs +++ b/src/Runner.Common/Util/NodeUtil.cs @@ -7,7 +7,7 @@ public static class NodeUtil { private const string _defaultNodeVersion = "node16"; -#if OS_OSX && ARM64 +#if (OS_OSX || OS_WINDOWS) && ARM64 public static readonly ReadOnlyCollection BuiltInNodeVersions = new(new[] { "node16" }); #else public static readonly ReadOnlyCollection BuiltInNodeVersions = new(new[] { "node12", "node16" }); diff --git a/src/Runner.Listener/Program.cs b/src/Runner.Listener/Program.cs index 4d52bed8f68..1482600ce95 100644 --- a/src/Runner.Listener/Program.cs +++ b/src/Runner.Listener/Program.cs @@ -58,6 +58,18 @@ private async static Task MainAsync(IHostContext context, string[] args) terminal.WriteLine("This runner version is built for Windows. Please install a correct build for your OS."); return Constants.Runner.ReturnCode.TerminatedError; } + #if ARM64 + // A little hacky, but windows gives no way to differentiate between windows 10 and 11. + // By default only 11 supports native x64 app emulation on arm, so we only want to support windows 11 + // https://docs.microsoft.com/en-us/windows/arm/overview#build-windows-apps-that-run-on-arm + // Windows 10 and 11 share a MajorVersion, so we also check the build version. Minor for both is 0, so doing < 0 doesn't really make a lot of sense. + if (Environment.OSVersion.Version.Major < Constants.OperatingSystem.Windows11MajorVersion || + Environment.OSVersion.Version.Build < Constants.OperatingSystem.Windows11BuildVersion) + { + terminal.WriteLine("Win-arm64 runners require windows 11 or later. Please upgrade your operating system."); + return Constants.Runner.ReturnCode.TerminatedError; + } + #endif break; default: terminal.WriteLine($"Running the runner on this platform is not supported. The current platform is {RuntimeInformation.OSDescription} and it was built for {Constants.Runner.Platform.ToString()}."); diff --git a/src/Runner.Listener/Runner.Listener.csproj b/src/Runner.Listener/Runner.Listener.csproj index 4298c753079..577847891be 100644 --- a/src/Runner.Listener/Runner.Listener.csproj +++ b/src/Runner.Listener/Runner.Listener.csproj @@ -3,7 +3,7 @@ net6.0 Exe - win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64 + win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64 true NU1701;NU1603 $(Version) diff --git a/src/Runner.PluginHost/Runner.PluginHost.csproj b/src/Runner.PluginHost/Runner.PluginHost.csproj index 7937a25164d..df30f3450a2 100644 --- a/src/Runner.PluginHost/Runner.PluginHost.csproj +++ b/src/Runner.PluginHost/Runner.PluginHost.csproj @@ -3,7 +3,7 @@ net6.0 Exe - win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64 + win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64 true NU1701;NU1603 $(Version) diff --git a/src/Runner.Plugins/Runner.Plugins.csproj b/src/Runner.Plugins/Runner.Plugins.csproj index 8314aea5187..39245a3f7a7 100644 --- a/src/Runner.Plugins/Runner.Plugins.csproj +++ b/src/Runner.Plugins/Runner.Plugins.csproj @@ -3,7 +3,7 @@ net6.0 Library - win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64 + win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64 true NU1701;NU1603 $(Version) diff --git a/src/Runner.Sdk/Runner.Sdk.csproj b/src/Runner.Sdk/Runner.Sdk.csproj index 63d6c0e186d..202e8669a64 100644 --- a/src/Runner.Sdk/Runner.Sdk.csproj +++ b/src/Runner.Sdk/Runner.Sdk.csproj @@ -3,12 +3,12 @@ net6.0 Library - win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64 + win-x64;win-x86;linux-x64;linux-arm64;linux-arm;osx-x64;osx-arm64;win-arm64 true NU1701;NU1603 $(Version) - + diff --git a/src/Runner.Service/Windows/App.config b/src/Runner.Service/Windows/App.config index 8e15646352e..486e3ea0979 100644 --- a/src/Runner.Service/Windows/App.config +++ b/src/Runner.Service/Windows/App.config @@ -1,6 +1,6 @@  - + - \ No newline at end of file + diff --git a/src/Runner.Service/Windows/AppARM.config b/src/Runner.Service/Windows/AppARM.config new file mode 100644 index 00000000000..ca9f6a32e67 --- /dev/null +++ b/src/Runner.Service/Windows/AppARM.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Runner.Service/Windows/RunnerService.csproj b/src/Runner.Service/Windows/RunnerService.csproj index 73fe4ecc655..238e67aac6e 100644 --- a/src/Runner.Service/Windows/RunnerService.csproj +++ b/src/Runner.Service/Windows/RunnerService.csproj @@ -11,10 +11,15 @@ RunnerService false false - v4.5 512 true + + v4.8 + + + v4.5 + AnyCPU true @@ -61,7 +66,10 @@ Resource.resx - + + + + @@ -71,7 +79,7 @@ - ## Misc -- Bumped `actions/core` dependency (#2123) +- Added a feature flag to start warning on `save-state` and `set-output` deprecation (#2164) +- Prepare supporting `vars` in workflow templates (#2096) ## Windows x64 We recommend configuring the runner in a root folder of the Windows drive (e.g. "C:\actions-runner"). This will help avoid issues related to service identity folder permissions and long file path restrictions on Windows. diff --git a/src/runnerversion b/src/runnerversion index 8b05c7a6bbc..4114f64cd7b 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.297.0 +2.298.0 From 1379ed2c7221d1a7dad2f9a467a035219843992b Mon Sep 17 00:00:00 2001 From: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com> Date: Tue, 4 Oct 2022 17:05:18 +0200 Subject: [PATCH 21/22] Fix incorrect template vars to show SHA for WIN-ARM64 (#2171) --- .github/workflows/release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 20927e2176f..abad70edaa7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -247,28 +247,28 @@ jobs: const runnerVersion = fs.readFileSync('${{ github.workspace }}/src/runnerversion', 'utf8').replace(/\n$/g, '') var releaseNote = fs.readFileSync('${{ github.workspace }}/releaseNote.md', 'utf8').replace(//g, runnerVersion) releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha}}') - releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm64-sha}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha-noexternals}}') - releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noexternals}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm64-sha-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha-noruntime}}') - releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noruntime}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-arm64-sha-noruntime}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-x64-sha-noruntime-noexternals}}') - releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noruntime-noexternals}}') + releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.win-arm64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-x64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.osx-arm64-sha-noruntime-noexternals}}') releaseNote = releaseNote.replace(//g, '${{needs.build.outputs.linux-x64-sha-noruntime-noexternals}}') From 86d0ee838991a87fceba4153cc429f9532b7e79b Mon Sep 17 00:00:00 2001 From: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com> Date: Tue, 4 Oct 2022 17:20:35 +0200 Subject: [PATCH 22/22] Backport 2.298.1 (#2175) * Update releaseNote.md * Update runnerversion --- releaseNote.md | 3 ++- src/runnerversion | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/releaseNote.md b/releaseNote.md index 6e9ca404816..5825dee692c 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -1,7 +1,8 @@ ## Features - Service containers startup error logs are now included in workflow's logs (#2110) - +## Bugs +- Fixed missing SHA for Windows arm64 release archive (#2171) ## Misc - Added a feature flag to start warning on `save-state` and `set-output` deprecation (#2164) diff --git a/src/runnerversion b/src/runnerversion index 4114f64cd7b..6abfac6bb9c 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.298.0 +2.298.1