Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull upstream #2178

Merged
merged 22 commits into from
Oct 5, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
01fd044
Escaping key and quoting it to avoid key based command injection (#2062)
nikola-jokic Aug 23, 2022
cba19c4
Release notes for 2.296.0 (#2078)
AvaStancu Aug 23, 2022
5989479
Validate lines and columns for Annotations (#2082)
konradpabjan Aug 24, 2022
95459de
docker: escape key-value pair as -e KEY and VALUE being environment v…
nikola-jokic Aug 31, 2022
5e0c2ef
2.296.1 Release (#2092) (#2099)
fhammerl Sep 2, 2022
7578675
fix ACTIONS_RUNNER_CONTAINER_HOOKS name in ADR (#2098)
nikola-jokic Sep 6, 2022
ed191b7
Port hotfix to main branch (#2108)
thboop Sep 9, 2022
6e6410d
fix for issue #2009 - composite summary file (#2077)
ruvceskistefan Sep 12, 2022
32845a5
Bump @actions/core from 1.2.6 to 1.9.1 in /src/Misc/expressionFunc/ha…
rentziass Sep 15, 2022
6cdd272
Remove unused imports (#2124)
JoannaaKL Sep 15, 2022
3a1c897
Remove unused imports (#2126)
JoannaaKL Sep 15, 2022
0678e8d
Add Release branches to pull request spec (#2134)
thboop Sep 19, 2022
15cbadb
Add file commands for save-state and set-output (#2118)
rentziass Sep 26, 2022
ae2f4a6
POC: Windows arm64 runner build (#2022)
thboop Sep 26, 2022
bc67f99
Add link to blog post to node 12 warn (#2156)
takost Sep 26, 2022
01ff38f
2.297.0 release notes (#2155)
thboop Sep 26, 2022
dca4f67
Adding a new vars context for non-secret variables (#2096)
tauhid621 Sep 30, 2022
9492691
Avastancu/joannaakl/service container error log (#2110)
JoannaaKL Oct 3, 2022
920fba9
Add warning for users using deprecated commands (#2164)
rentziass Oct 4, 2022
4935be5
Prepare release notes for v2.298.0 (#2169)
rentziass Oct 4, 2022
1379ed2
Fix incorrect template vars to show SHA for WIN-ARM64 (#2171)
fhammerl Oct 4, 2022
86d0ee8
Backport 2.298.1 (#2175)
fhammerl Oct 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add file commands for save-state and set-output (#2118)
  • Loading branch information
rentziass authored Sep 26, 2022
commit 15cbadb4af5499072564f48f709da888f860121c
2 changes: 2 additions & 0 deletions src/Runner.Common/ExtensionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ private List<IExtension> LoadExtensions<T>() where T : class, IExtension
Add<T>(extensions, "GitHub.Runner.Worker.AddPathFileCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.SetEnvFileCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.CreateStepSummaryCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.SaveStateFileCommand, Runner.Worker");
Add<T>(extensions, "GitHub.Runner.Worker.SetOutputFileCommand, Runner.Worker");
break;
case "GitHub.Runner.Listener.Check.ICheckExtension":
Add<T>(extensions, "GitHub.Runner.Listener.Check.InternetCheck, Runner.Listener");
Expand Down
308 changes: 199 additions & 109 deletions src/Runner.Worker/FileCommandManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<<EOF
else if (heredocIndex >= 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);
}
}

Expand All @@ -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
Expand Down Expand Up @@ -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<string, string>(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<KeyValuePair<string, string>>
{
private IExecutionContext _context;
private string _filePath;

public EnvFileKeyValuePairs(IExecutionContext context, string filePath)
{
_context = context;
_filePath = filePath;
}

public IEnumerator<KeyValuePair<string, string>> 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<<EOF
else if (heredocIndex >= 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<string, string>(key, output);
}

line = ReadLine(text, ref index);
}
}

System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
// Invoke IEnumerator<KeyValuePair<string, string>> 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);
}
}
}
2 changes: 2 additions & 0 deletions src/Runner.Worker/GitHubContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public sealed class GitHubContext : DictionaryContextData, IEnvironmentContextDa
"graphql_url",
"head_ref",
"job",
"output",
"path",
"ref_name",
"ref_protected",
Expand All @@ -34,6 +35,7 @@ public sealed class GitHubContext : DictionaryContextData, IEnvironmentContextDa
"run_number",
"server_url",
"sha",
"state",
"step_summary",
"triggering_actor",
"workflow",
Expand Down
Loading