mirror of
https://github.com/actions/runner.git
synced 2025-12-10 12:36:23 +00:00
preserve workflow file/line/column for better error messages (#356)
This commit is contained in:
@@ -32,6 +32,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public sealed class ActionManifestManager : RunnerService, IActionManifestManager
|
public sealed class ActionManifestManager : RunnerService, IActionManifestManager
|
||||||
{
|
{
|
||||||
private TemplateSchema _actionManifestSchema;
|
private TemplateSchema _actionManifestSchema;
|
||||||
|
private IReadOnlyList<String> _fileTable;
|
||||||
|
|
||||||
public override void Initialize(IHostContext hostContext)
|
public override void Initialize(IHostContext hostContext)
|
||||||
{
|
{
|
||||||
@@ -61,6 +62,9 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// Get the file ID
|
// Get the file ID
|
||||||
var fileId = context.GetFileId(manifestFile);
|
var fileId = context.GetFileId(manifestFile);
|
||||||
|
_fileTable = context.GetFileTable();
|
||||||
|
|
||||||
|
// Read the file
|
||||||
var fileContent = File.ReadAllText(manifestFile);
|
var fileContent = File.ReadAllText(manifestFile);
|
||||||
using (var stringReader = new StringReader(fileContent))
|
using (var stringReader = new StringReader(fileContent))
|
||||||
{
|
{
|
||||||
@@ -265,6 +269,15 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the file table
|
||||||
|
if (_fileTable?.Count > 0)
|
||||||
|
{
|
||||||
|
for (var i = 0 ; i < _fileTable.Count ; i++)
|
||||||
|
{
|
||||||
|
result.GetFileId(_fileTable[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,566 +428,5 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a YAML file into a TemplateToken
|
|
||||||
/// </summary>
|
|
||||||
internal sealed class YamlObjectReader : IObjectReader
|
|
||||||
{
|
|
||||||
internal YamlObjectReader(
|
|
||||||
Int32? fileId,
|
|
||||||
TextReader input)
|
|
||||||
{
|
|
||||||
m_fileId = fileId;
|
|
||||||
m_parser = new Parser(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean AllowLiteral(out LiteralToken value)
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() is Scalar scalar)
|
|
||||||
{
|
|
||||||
// Tag specified
|
|
||||||
if (!string.IsNullOrEmpty(scalar.Tag))
|
|
||||||
{
|
|
||||||
// String tag
|
|
||||||
if (string.Equals(scalar.Tag, c_stringTag, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
value = new StringToken(m_fileId, scalar.Start.Line, scalar.Start.Column, scalar.Value);
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Not plain style
|
|
||||||
if (scalar.Style != ScalarStyle.Plain)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException($"The scalar style '{scalar.Style}' on line {scalar.Start.Line} and column {scalar.Start.Column} is not valid with the tag '{scalar.Tag}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Boolean, Float, Integer, or Null
|
|
||||||
switch (scalar.Tag)
|
|
||||||
{
|
|
||||||
case c_booleanTag:
|
|
||||||
value = ParseBoolean(scalar);
|
|
||||||
break;
|
|
||||||
case c_floatTag:
|
|
||||||
value = ParseFloat(scalar);
|
|
||||||
break;
|
|
||||||
case c_integerTag:
|
|
||||||
value = ParseInteger(scalar);
|
|
||||||
break;
|
|
||||||
case c_nullTag:
|
|
||||||
value = ParseNull(scalar);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new NotSupportedException($"Unexpected tag '{scalar.Tag}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Plain style, determine type using YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
|
||||||
if (scalar.Style == ScalarStyle.Plain)
|
|
||||||
{
|
|
||||||
if (MatchNull(scalar, out var nullToken))
|
|
||||||
{
|
|
||||||
value = nullToken;
|
|
||||||
}
|
|
||||||
else if (MatchBoolean(scalar, out var booleanToken))
|
|
||||||
{
|
|
||||||
value = booleanToken;
|
|
||||||
}
|
|
||||||
else if (MatchInteger(scalar, out var numberToken) ||
|
|
||||||
MatchFloat(scalar, out numberToken))
|
|
||||||
{
|
|
||||||
value = numberToken;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
value = new StringToken(m_fileId, scalar.Start.Line, scalar.Start.Column, scalar.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise assume string
|
|
||||||
value = new StringToken(m_fileId, scalar.Start.Line, scalar.Start.Column, scalar.Value);
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean AllowSequenceStart(out SequenceToken value)
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() is SequenceStart sequenceStart)
|
|
||||||
{
|
|
||||||
value = new SequenceToken(m_fileId, sequenceStart.Start.Line, sequenceStart.Start.Column);
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean AllowSequenceEnd()
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() is SequenceEnd)
|
|
||||||
{
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean AllowMappingStart(out MappingToken value)
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() is MappingStart mappingStart)
|
|
||||||
{
|
|
||||||
value = new MappingToken(m_fileId, mappingStart.Start.Line, mappingStart.Start.Column);
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean AllowMappingEnd()
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() is MappingEnd)
|
|
||||||
{
|
|
||||||
MoveNext();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Consumes the last parsing events, which are expected to be DocumentEnd and StreamEnd.
|
|
||||||
/// </summary>
|
|
||||||
public void ValidateEnd()
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() is DocumentEnd)
|
|
||||||
{
|
|
||||||
MoveNext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected document end parse event");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EvaluateCurrent() is StreamEnd)
|
|
||||||
{
|
|
||||||
MoveNext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected stream end parse event");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MoveNext())
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected end of parse events");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Consumes the first parsing events, which are expected to be StreamStart and DocumentStart.
|
|
||||||
/// </summary>
|
|
||||||
public void ValidateStart()
|
|
||||||
{
|
|
||||||
if (EvaluateCurrent() != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Unexpected parser state");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!MoveNext())
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected a parse event");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EvaluateCurrent() is StreamStart)
|
|
||||||
{
|
|
||||||
MoveNext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected stream start parse event");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EvaluateCurrent() is DocumentStart)
|
|
||||||
{
|
|
||||||
MoveNext();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Expected document start parse event");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParsingEvent EvaluateCurrent()
|
|
||||||
{
|
|
||||||
if (m_current == null)
|
|
||||||
{
|
|
||||||
m_current = m_parser.Current;
|
|
||||||
if (m_current != null)
|
|
||||||
{
|
|
||||||
if (m_current is Scalar scalar)
|
|
||||||
{
|
|
||||||
// Verify not using achors
|
|
||||||
if (scalar.Anchor != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Anchors are not currently supported. Remove the anchor '{scalar.Anchor}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_current is MappingStart mappingStart)
|
|
||||||
{
|
|
||||||
// Verify not using achors
|
|
||||||
if (mappingStart.Anchor != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Anchors are not currently supported. Remove the anchor '{mappingStart.Anchor}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (m_current is SequenceStart sequenceStart)
|
|
||||||
{
|
|
||||||
// Verify not using achors
|
|
||||||
if (sequenceStart.Anchor != null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Anchors are not currently supported. Remove the anchor '{sequenceStart.Anchor}'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!(m_current is MappingEnd) &&
|
|
||||||
!(m_current is SequenceEnd) &&
|
|
||||||
!(m_current is DocumentStart) &&
|
|
||||||
!(m_current is DocumentEnd) &&
|
|
||||||
!(m_current is StreamStart) &&
|
|
||||||
!(m_current is StreamEnd))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unexpected parsing event type: {m_current.GetType().Name}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_current;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean MoveNext()
|
|
||||||
{
|
|
||||||
m_current = null;
|
|
||||||
return m_parser.MoveNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BooleanToken ParseBoolean(Scalar scalar)
|
|
||||||
{
|
|
||||||
if (MatchBoolean(scalar, out var token))
|
|
||||||
{
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowInvalidValue(scalar, c_booleanTag); // throws
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NumberToken ParseFloat(Scalar scalar)
|
|
||||||
{
|
|
||||||
if (MatchFloat(scalar, out var token))
|
|
||||||
{
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowInvalidValue(scalar, c_floatTag); // throws
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NumberToken ParseInteger(Scalar scalar)
|
|
||||||
{
|
|
||||||
if (MatchInteger(scalar, out var token))
|
|
||||||
{
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowInvalidValue(scalar, c_integerTag); // throws
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
private NullToken ParseNull(Scalar scalar)
|
|
||||||
{
|
|
||||||
if (MatchNull(scalar, out var token))
|
|
||||||
{
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowInvalidValue(scalar, c_nullTag); // throws
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean MatchBoolean(
|
|
||||||
Scalar scalar,
|
|
||||||
out BooleanToken value)
|
|
||||||
{
|
|
||||||
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
|
||||||
switch (scalar.Value ?? string.Empty)
|
|
||||||
{
|
|
||||||
case "true":
|
|
||||||
case "True":
|
|
||||||
case "TRUE":
|
|
||||||
value = new BooleanToken(m_fileId, scalar.Start.Line, scalar.Start.Column, true);
|
|
||||||
return true;
|
|
||||||
case "false":
|
|
||||||
case "False":
|
|
||||||
case "FALSE":
|
|
||||||
value = new BooleanToken(m_fileId, scalar.Start.Line, scalar.Start.Column, false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean MatchFloat(
|
|
||||||
Scalar scalar,
|
|
||||||
out NumberToken value)
|
|
||||||
{
|
|
||||||
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
|
||||||
var str = scalar.Value;
|
|
||||||
if (!string.IsNullOrEmpty(str))
|
|
||||||
{
|
|
||||||
// Check for [-+]?(\.inf|\.Inf|\.INF)|\.nan|\.NaN|\.NAN
|
|
||||||
switch (str)
|
|
||||||
{
|
|
||||||
case ".inf":
|
|
||||||
case ".Inf":
|
|
||||||
case ".INF":
|
|
||||||
case "+.inf":
|
|
||||||
case "+.Inf":
|
|
||||||
case "+.INF":
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, Double.PositiveInfinity);
|
|
||||||
return true;
|
|
||||||
case "-.inf":
|
|
||||||
case "-.Inf":
|
|
||||||
case "-.INF":
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, Double.NegativeInfinity);
|
|
||||||
return true;
|
|
||||||
case ".nan":
|
|
||||||
case ".NaN":
|
|
||||||
case ".NAN":
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, Double.NaN);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise check [-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?
|
|
||||||
|
|
||||||
// Skip leading sign
|
|
||||||
var index = str[0] == '-' || str[0] == '+' ? 1 : 0;
|
|
||||||
|
|
||||||
// Check for integer portion
|
|
||||||
var length = str.Length;
|
|
||||||
var hasInteger = false;
|
|
||||||
while (index < length && str[index] >= '0' && str[index] <= '9')
|
|
||||||
{
|
|
||||||
hasInteger = true;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for decimal point
|
|
||||||
var hasDot = false;
|
|
||||||
if (index < length && str[index] == '.')
|
|
||||||
{
|
|
||||||
hasDot = true;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for decimal portion
|
|
||||||
var hasDecimal = false;
|
|
||||||
while (index < length && str[index] >= '0' && str[index] <= '9')
|
|
||||||
{
|
|
||||||
hasDecimal = true;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check [-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)
|
|
||||||
if ((hasDot && hasDecimal) || hasInteger)
|
|
||||||
{
|
|
||||||
// Check for end
|
|
||||||
if (index == length)
|
|
||||||
{
|
|
||||||
// Try parse
|
|
||||||
if (Double.TryParse(str, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var doubleValue))
|
|
||||||
{
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, doubleValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Otherwise exceeds range
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ThrowInvalidValue(scalar, c_floatTag); // throws
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check [eE][-+]?[0-9]
|
|
||||||
else if (index < length && (str[index] == 'e' || str[index] == 'E'))
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
|
|
||||||
// Skip sign
|
|
||||||
if (index < length && (str[index] == '-' || str[index] == '+'))
|
|
||||||
{
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for exponent
|
|
||||||
var hasExponent = false;
|
|
||||||
while (index < length && str[index] >= '0' && str[index] <= '9')
|
|
||||||
{
|
|
||||||
hasExponent = true;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for end
|
|
||||||
if (hasExponent && index == length)
|
|
||||||
{
|
|
||||||
// Try parse
|
|
||||||
if (Double.TryParse(str, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out var doubleValue))
|
|
||||||
{
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, (Double)doubleValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// Otherwise exceeds range
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ThrowInvalidValue(scalar, c_floatTag); // throws
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean MatchInteger(
|
|
||||||
Scalar scalar,
|
|
||||||
out NumberToken value)
|
|
||||||
{
|
|
||||||
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
|
||||||
var str = scalar.Value;
|
|
||||||
if (!string.IsNullOrEmpty(str))
|
|
||||||
{
|
|
||||||
// Check for [0-9]+
|
|
||||||
var firstChar = str[0];
|
|
||||||
if (firstChar >= '0' && firstChar <= '9' &&
|
|
||||||
str.Skip(1).All(x => x >= '0' && x <= '9'))
|
|
||||||
{
|
|
||||||
// Try parse
|
|
||||||
if (Double.TryParse(str, NumberStyles.None, CultureInfo.InvariantCulture, out var doubleValue))
|
|
||||||
{
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, doubleValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise exceeds range
|
|
||||||
ThrowInvalidValue(scalar, c_integerTag); // throws
|
|
||||||
}
|
|
||||||
// Check for (-|+)[0-9]+
|
|
||||||
else if ((firstChar == '-' || firstChar == '+') &&
|
|
||||||
str.Length > 1 &&
|
|
||||||
str.Skip(1).All(x => x >= '0' && x <= '9'))
|
|
||||||
{
|
|
||||||
// Try parse
|
|
||||||
if (Double.TryParse(str, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var doubleValue))
|
|
||||||
{
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, doubleValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise exceeds range
|
|
||||||
ThrowInvalidValue(scalar, c_integerTag); // throws
|
|
||||||
}
|
|
||||||
// Check for 0x[0-9a-fA-F]+
|
|
||||||
else if (firstChar == '0' &&
|
|
||||||
str.Length > 2 &&
|
|
||||||
str[1] == 'x' &&
|
|
||||||
str.Skip(2).All(x => (x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')))
|
|
||||||
{
|
|
||||||
// Try parse
|
|
||||||
if (Int32.TryParse(str.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var integerValue))
|
|
||||||
{
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, integerValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise exceeds range
|
|
||||||
ThrowInvalidValue(scalar, c_integerTag); // throws
|
|
||||||
}
|
|
||||||
// Check for 0o[0-9]+
|
|
||||||
else if (firstChar == '0' &&
|
|
||||||
str.Length > 2 &&
|
|
||||||
str[1] == 'o' &&
|
|
||||||
str.Skip(2).All(x => x >= '0' && x <= '7'))
|
|
||||||
{
|
|
||||||
// Try parse
|
|
||||||
var integerValue = default(Int32);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
integerValue = Convert.ToInt32(str.Substring(2), 8);
|
|
||||||
}
|
|
||||||
// Otherwise exceeds range
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
ThrowInvalidValue(scalar, c_integerTag); // throws
|
|
||||||
}
|
|
||||||
|
|
||||||
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, integerValue);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Boolean MatchNull(
|
|
||||||
Scalar scalar,
|
|
||||||
out NullToken value)
|
|
||||||
{
|
|
||||||
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
|
||||||
switch (scalar.Value ?? string.Empty)
|
|
||||||
{
|
|
||||||
case "":
|
|
||||||
case "null":
|
|
||||||
case "Null":
|
|
||||||
case "NULL":
|
|
||||||
case "~":
|
|
||||||
value = new NullToken(m_fileId, scalar.Start.Line, scalar.Start.Column);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThrowInvalidValue(
|
|
||||||
Scalar scalar,
|
|
||||||
String tag)
|
|
||||||
{
|
|
||||||
throw new NotSupportedException($"The value '{scalar.Value}' on line {scalar.Start.Line} and column {scalar.Start.Column} is invalid for the type '{scalar.Tag}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
private const String c_booleanTag = "tag:yaml.org,2002:bool";
|
|
||||||
private const String c_floatTag = "tag:yaml.org,2002:float";
|
|
||||||
private const String c_integerTag = "tag:yaml.org,2002:int";
|
|
||||||
private const String c_nullTag = "tag:yaml.org,2002:null";
|
|
||||||
private const String c_stringTag = "tag:yaml.org,2002:string";
|
|
||||||
private readonly Int32? m_fileId;
|
|
||||||
private readonly Parser m_parser;
|
|
||||||
private ParsingEvent m_current;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,9 +141,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// Load the inputs.
|
// Load the inputs.
|
||||||
ExecutionContext.Debug("Loading inputs");
|
ExecutionContext.Debug("Loading inputs");
|
||||||
var templateTrace = ExecutionContext.ToTemplateTraceWriter();
|
var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
|
||||||
var schema = new PipelineTemplateSchemaFactory().CreateSchema();
|
|
||||||
var templateEvaluator = new PipelineTemplateEvaluator(templateTrace, schema);
|
|
||||||
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues);
|
var inputs = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues);
|
||||||
|
|
||||||
foreach (KeyValuePair<string, string> input in inputs)
|
foreach (KeyValuePair<string, string> input in inputs)
|
||||||
@@ -295,8 +293,7 @@ namespace GitHub.Runner.Worker
|
|||||||
return displayName;
|
return displayName;
|
||||||
}
|
}
|
||||||
// Try evaluating fully
|
// Try evaluating fully
|
||||||
var schema = new PipelineTemplateSchemaFactory().CreateSchema();
|
var templateEvaluator = context.ToPipelineTemplateEvaluator();
|
||||||
var templateEvaluator = new PipelineTemplateEvaluator(context.ToTemplateTraceWriter(), schema);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
didFullyEvaluate = templateEvaluator.TryEvaluateStepDisplayName(tokenToParse, contextData, out displayName);
|
didFullyEvaluate = templateEvaluator.TryEvaluateStepDisplayName(tokenToParse, contextData, out displayName);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using GitHub.Runner.Worker.Container;
|
|||||||
using GitHub.Services.WebApi;
|
using GitHub.Services.WebApi;
|
||||||
using GitHub.DistributedTask.Pipelines;
|
using GitHub.DistributedTask.Pipelines;
|
||||||
using GitHub.DistributedTask.Pipelines.ContextData;
|
using GitHub.DistributedTask.Pipelines.ContextData;
|
||||||
|
using GitHub.DistributedTask.Pipelines.ObjectTemplating;
|
||||||
using GitHub.DistributedTask.WebApi;
|
using GitHub.DistributedTask.WebApi;
|
||||||
using GitHub.Runner.Common.Util;
|
using GitHub.Runner.Common.Util;
|
||||||
using GitHub.Runner.Common;
|
using GitHub.Runner.Common;
|
||||||
@@ -49,6 +50,7 @@ namespace GitHub.Runner.Worker
|
|||||||
HashSet<string> OutputVariables { get; }
|
HashSet<string> OutputVariables { get; }
|
||||||
IDictionary<String, String> EnvironmentVariables { get; }
|
IDictionary<String, String> EnvironmentVariables { get; }
|
||||||
IDictionary<String, ContextScope> Scopes { get; }
|
IDictionary<String, ContextScope> Scopes { get; }
|
||||||
|
IList<String> FileTable { get; }
|
||||||
StepsContext StepsContext { get; }
|
StepsContext StepsContext { get; }
|
||||||
DictionaryContextData ExpressionValues { get; }
|
DictionaryContextData ExpressionValues { get; }
|
||||||
List<string> PrependPath { get; }
|
List<string> PrependPath { get; }
|
||||||
@@ -141,6 +143,7 @@ namespace GitHub.Runner.Worker
|
|||||||
public HashSet<string> OutputVariables => _outputvariables;
|
public HashSet<string> OutputVariables => _outputvariables;
|
||||||
public IDictionary<String, String> EnvironmentVariables { get; private set; }
|
public IDictionary<String, String> EnvironmentVariables { get; private set; }
|
||||||
public IDictionary<String, ContextScope> Scopes { get; private set; }
|
public IDictionary<String, ContextScope> Scopes { get; private set; }
|
||||||
|
public IList<String> FileTable { get; private set; }
|
||||||
public StepsContext StepsContext { get; private set; }
|
public StepsContext StepsContext { get; private set; }
|
||||||
public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData();
|
public DictionaryContextData ExpressionValues { get; } = new DictionaryContextData();
|
||||||
public bool WriteDebug { get; private set; }
|
public bool WriteDebug { get; private set; }
|
||||||
@@ -266,6 +269,7 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
child.EnvironmentVariables = EnvironmentVariables;
|
child.EnvironmentVariables = EnvironmentVariables;
|
||||||
child.Scopes = Scopes;
|
child.Scopes = Scopes;
|
||||||
|
child.FileTable = FileTable;
|
||||||
child.StepsContext = StepsContext;
|
child.StepsContext = StepsContext;
|
||||||
foreach (var pair in ExpressionValues)
|
foreach (var pair in ExpressionValues)
|
||||||
{
|
{
|
||||||
@@ -569,6 +573,9 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File table
|
||||||
|
FileTable = new List<String>(message.FileTable ?? new string[0]);
|
||||||
|
|
||||||
// Expression functions
|
// Expression functions
|
||||||
if (Variables.GetBoolean("System.HashFilesV2") == true)
|
if (Variables.GetBoolean("System.HashFilesV2") == true)
|
||||||
{
|
{
|
||||||
@@ -886,6 +893,13 @@ namespace GitHub.Runner.Worker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PipelineTemplateEvaluator ToPipelineTemplateEvaluator(this IExecutionContext context)
|
||||||
|
{
|
||||||
|
var templateTrace = context.ToTemplateTraceWriter();
|
||||||
|
var schema = new PipelineTemplateSchemaFactory().CreateSchema();
|
||||||
|
return new PipelineTemplateEvaluator(templateTrace, schema, context.FileTable);
|
||||||
|
}
|
||||||
|
|
||||||
public static ObjectTemplating.ITraceWriter ToTemplateTraceWriter(this IExecutionContext context)
|
public static ObjectTemplating.ITraceWriter ToTemplateTraceWriter(this IExecutionContext context)
|
||||||
{
|
{
|
||||||
return new TemplateTraceWriter(context);
|
return new TemplateTraceWriter(context);
|
||||||
|
|||||||
@@ -78,9 +78,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// Evaluate the job-level environment variables
|
// Evaluate the job-level environment variables
|
||||||
context.Debug("Evaluating job-level environment variables");
|
context.Debug("Evaluating job-level environment variables");
|
||||||
var templateTrace = context.ToTemplateTraceWriter();
|
var templateEvaluator = context.ToPipelineTemplateEvaluator();
|
||||||
var schema = new PipelineTemplateSchemaFactory().CreateSchema();
|
|
||||||
var templateEvaluator = new PipelineTemplateEvaluator(templateTrace, schema);
|
|
||||||
foreach (var token in message.EnvironmentVariables)
|
foreach (var token in message.EnvironmentVariables)
|
||||||
{
|
{
|
||||||
var environmentVariables = templateEvaluator.EvaluateStepEnvironment(token, jobContext.ExpressionValues, VarUtil.EnvironmentVariableKeyComparer);
|
var environmentVariables = templateEvaluator.EvaluateStepEnvironment(token, jobContext.ExpressionValues, VarUtil.EnvironmentVariableKeyComparer);
|
||||||
|
|||||||
@@ -98,9 +98,7 @@ namespace GitHub.Runner.Worker
|
|||||||
step.ExecutionContext.SetGitHubContext("action", actionStep.Action.Name);
|
step.ExecutionContext.SetGitHubContext("action", actionStep.Action.Name);
|
||||||
|
|
||||||
// Evaluate and merge action's env block to env context
|
// Evaluate and merge action's env block to env context
|
||||||
var templateTrace = step.ExecutionContext.ToTemplateTraceWriter();
|
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator();
|
||||||
var schema = new PipelineTemplateSchemaFactory().CreateSchema();
|
|
||||||
var templateEvaluator = new PipelineTemplateEvaluator(templateTrace, schema);
|
|
||||||
var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, VarUtil.EnvironmentVariableKeyComparer);
|
var actionEnvironment = templateEvaluator.EvaluateStepEnvironment(actionStep.Action.Environment, step.ExecutionContext.ExpressionValues, VarUtil.EnvironmentVariableKeyComparer);
|
||||||
foreach (var env in actionEnvironment)
|
foreach (var env in actionEnvironment)
|
||||||
{
|
{
|
||||||
@@ -247,7 +245,7 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
// Set the timeout
|
// Set the timeout
|
||||||
var timeoutMinutes = 0;
|
var timeoutMinutes = 0;
|
||||||
var templateEvaluator = CreateTemplateEvaluator(step.ExecutionContext);
|
var templateEvaluator = step.ExecutionContext.ToPipelineTemplateEvaluator();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
timeoutMinutes = templateEvaluator.EvaluateStepTimeout(step.Timeout, step.ExecutionContext.ExpressionValues);
|
timeoutMinutes = templateEvaluator.EvaluateStepTimeout(step.Timeout, step.ExecutionContext.ExpressionValues);
|
||||||
@@ -389,7 +387,7 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Debug($"Initializing scope '{scope.Name}'");
|
executionContext.Debug($"Initializing scope '{scope.Name}'");
|
||||||
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scope.ParentName);
|
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scope.ParentName);
|
||||||
executionContext.ExpressionValues["inputs"] = !String.IsNullOrEmpty(scope.ParentName) ? scopeInputs[scope.ParentName] : null;
|
executionContext.ExpressionValues["inputs"] = !String.IsNullOrEmpty(scope.ParentName) ? scopeInputs[scope.ParentName] : null;
|
||||||
var templateEvaluator = CreateTemplateEvaluator(executionContext);
|
var templateEvaluator = executionContext.ToPipelineTemplateEvaluator();
|
||||||
var inputs = default(DictionaryContextData);
|
var inputs = default(DictionaryContextData);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -445,7 +443,7 @@ namespace GitHub.Runner.Worker
|
|||||||
executionContext.Debug($"Finalizing scope '{scope.Name}'");
|
executionContext.Debug($"Finalizing scope '{scope.Name}'");
|
||||||
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scope.Name);
|
executionContext.ExpressionValues["steps"] = stepsContext.GetScope(scope.Name);
|
||||||
executionContext.ExpressionValues["inputs"] = null;
|
executionContext.ExpressionValues["inputs"] = null;
|
||||||
var templateEvaluator = CreateTemplateEvaluator(executionContext);
|
var templateEvaluator = executionContext.ToPipelineTemplateEvaluator();
|
||||||
var outputs = default(DictionaryContextData);
|
var outputs = default(DictionaryContextData);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -477,12 +475,5 @@ namespace GitHub.Runner.Worker
|
|||||||
|
|
||||||
executionContext.Complete(result, resultCode: resultCode);
|
executionContext.Complete(result, resultCode: resultCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PipelineTemplateEvaluator CreateTemplateEvaluator(IExecutionContext executionContext)
|
|
||||||
{
|
|
||||||
var templateTrace = executionContext.ToTemplateTraceWriter();
|
|
||||||
var schema = new PipelineTemplateSchemaFactory().CreateSchema();
|
|
||||||
return new PipelineTemplateEvaluator(templateTrace, schema);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ namespace GitHub.DistributedTask.ObjectTemplating
|
|||||||
id = FileIds.Count + 1;
|
id = FileIds.Count + 1;
|
||||||
FileIds.Add(file, id);
|
FileIds.Add(file, id);
|
||||||
FileNames.Add(file);
|
FileNames.Add(file);
|
||||||
|
Memory.AddBytes(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
@@ -191,7 +192,12 @@ namespace GitHub.DistributedTask.ObjectTemplating
|
|||||||
|
|
||||||
internal String GetFileName(Int32 fileId)
|
internal String GetFileName(Int32 fileId)
|
||||||
{
|
{
|
||||||
return FileNames[fileId - 1];
|
return FileNames.Count >= fileId ? FileNames[fileId - 1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IReadOnlyList<String> GetFileTable()
|
||||||
|
{
|
||||||
|
return FileNames.AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String GetErrorPrefix(
|
private String GetErrorPrefix(
|
||||||
@@ -199,9 +205,9 @@ namespace GitHub.DistributedTask.ObjectTemplating
|
|||||||
Int32? line,
|
Int32? line,
|
||||||
Int32? column)
|
Int32? column)
|
||||||
{
|
{
|
||||||
if (fileId != null)
|
var fileName = fileId.HasValue ? GetFileName(fileId.Value) : null;
|
||||||
|
if (!String.IsNullOrEmpty(fileName))
|
||||||
{
|
{
|
||||||
var fileName = GetFileName(fileId.Value);
|
|
||||||
if (line != null && column != null)
|
if (line != null && column != null)
|
||||||
{
|
{
|
||||||
return $"{fileName} {TemplateStrings.LineColumn(line, column)}:";
|
return $"{fileName} {TemplateStrings.LineColumn(line, column)}:";
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
Column = column;
|
Column = column;
|
||||||
}
|
}
|
||||||
|
|
||||||
[IgnoreDataMember]
|
[DataMember(Name = "file", EmitDefaultValue = false)]
|
||||||
internal Int32? FileId { get; set; }
|
internal Int32? FileId { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "line", EmitDefaultValue = false)]
|
[DataMember(Name = "line", EmitDefaultValue = false)]
|
||||||
internal Int32? Line { get; }
|
internal Int32? Line { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "col", EmitDefaultValue = false)]
|
[DataMember(Name = "col", EmitDefaultValue = false)]
|
||||||
internal Int32? Column { get; }
|
internal Int32? Column { get; private set; }
|
||||||
|
|
||||||
[DataMember(Name = "type", EmitDefaultValue = false)]
|
[DataMember(Name = "type", EmitDefaultValue = false)]
|
||||||
internal Int32 Type { get; }
|
internal Int32 Type { get; }
|
||||||
|
|||||||
@@ -115,13 +115,12 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
Object value,
|
Object value,
|
||||||
JsonSerializer serializer)
|
JsonSerializer serializer)
|
||||||
{
|
{
|
||||||
base.WriteJson(writer, value, serializer);
|
|
||||||
if (value is TemplateToken token)
|
if (value is TemplateToken token)
|
||||||
{
|
{
|
||||||
switch (token.Type)
|
switch (token.Type)
|
||||||
{
|
{
|
||||||
case TokenType.Null:
|
case TokenType.Null:
|
||||||
if (token.Line == null && token.Column == null)
|
if (token.FileId == null && token.Line == null && token.Column == null)
|
||||||
{
|
{
|
||||||
writer.WriteNull();
|
writer.WriteNull();
|
||||||
}
|
}
|
||||||
@@ -130,12 +129,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -146,7 +150,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
|
|
||||||
case TokenType.Boolean:
|
case TokenType.Boolean:
|
||||||
var booleanToken = token as BooleanToken;
|
var booleanToken = token as BooleanToken;
|
||||||
if (token.Line == null && token.Column == null)
|
if (token.FileId == null && token.Line == null && token.Column == null)
|
||||||
{
|
{
|
||||||
writer.WriteValue(booleanToken.Value);
|
writer.WriteValue(booleanToken.Value);
|
||||||
}
|
}
|
||||||
@@ -155,12 +159,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -173,7 +182,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
|
|
||||||
case TokenType.Number:
|
case TokenType.Number:
|
||||||
var numberToken = token as NumberToken;
|
var numberToken = token as NumberToken;
|
||||||
if (token.Line == null && token.Column == null)
|
if (token.FileId == null && token.Line == null && token.Column == null)
|
||||||
{
|
{
|
||||||
writer.WriteValue(numberToken.Value);
|
writer.WriteValue(numberToken.Value);
|
||||||
}
|
}
|
||||||
@@ -182,12 +191,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -200,7 +214,7 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
|
|
||||||
case TokenType.String:
|
case TokenType.String:
|
||||||
var stringToken = token as StringToken;
|
var stringToken = token as StringToken;
|
||||||
if (token.Line == null && token.Column == null)
|
if (token.FileId == null && token.Line == null && token.Column == null)
|
||||||
{
|
{
|
||||||
writer.WriteValue(stringToken.Value);
|
writer.WriteValue(stringToken.Value);
|
||||||
}
|
}
|
||||||
@@ -209,12 +223,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -230,12 +249,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -253,12 +277,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -273,12 +302,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
@@ -301,12 +335,17 @@ namespace GitHub.DistributedTask.ObjectTemplating.Tokens
|
|||||||
writer.WriteStartObject();
|
writer.WriteStartObject();
|
||||||
writer.WritePropertyName("type");
|
writer.WritePropertyName("type");
|
||||||
writer.WriteValue(token.Type);
|
writer.WriteValue(token.Type);
|
||||||
|
if (token.FileId != null)
|
||||||
|
{
|
||||||
|
writer.WritePropertyName("file");
|
||||||
|
writer.WriteValue(token.FileId);
|
||||||
|
}
|
||||||
if (token.Line != null)
|
if (token.Line != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("line");
|
writer.WritePropertyName("line");
|
||||||
writer.WriteValue(token.Line);
|
writer.WriteValue(token.Line);
|
||||||
}
|
}
|
||||||
if (token.Line != null)
|
if (token.Column != null)
|
||||||
{
|
{
|
||||||
writer.WritePropertyName("col");
|
writer.WritePropertyName("col");
|
||||||
writer.WriteValue(token.Column);
|
writer.WriteValue(token.Column);
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ namespace GitHub.DistributedTask.Pipelines
|
|||||||
DictionaryContextData contextData,
|
DictionaryContextData contextData,
|
||||||
WorkspaceOptions workspaceOptions,
|
WorkspaceOptions workspaceOptions,
|
||||||
IEnumerable<JobStep> steps,
|
IEnumerable<JobStep> steps,
|
||||||
IEnumerable<ContextScope> scopes)
|
IEnumerable<ContextScope> scopes,
|
||||||
|
IList<String> fileTable)
|
||||||
{
|
{
|
||||||
this.MessageType = JobRequestMessageTypes.PipelineAgentJobRequest;
|
this.MessageType = JobRequestMessageTypes.PipelineAgentJobRequest;
|
||||||
this.Plan = plan;
|
this.Plan = plan;
|
||||||
@@ -74,6 +75,11 @@ namespace GitHub.DistributedTask.Pipelines
|
|||||||
this.ContextData[pair.Key] = pair.Value;
|
this.ContextData[pair.Key] = pair.Value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fileTable?.Count > 0)
|
||||||
|
{
|
||||||
|
m_fileTable = new List<String>(fileTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[DataMember]
|
[DataMember]
|
||||||
@@ -237,6 +243,18 @@ namespace GitHub.DistributedTask.Pipelines
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IList<String> FileTable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (m_fileTable == null)
|
||||||
|
{
|
||||||
|
m_fileTable = new List<String>();
|
||||||
|
}
|
||||||
|
return m_fileTable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// todo: remove after feature-flag DistributedTask.EvaluateContainerOnRunner is enabled everywhere
|
// todo: remove after feature-flag DistributedTask.EvaluateContainerOnRunner is enabled everywhere
|
||||||
public void SetJobSidecarContainers(IDictionary<String, String> value)
|
public void SetJobSidecarContainers(IDictionary<String, String> value)
|
||||||
{
|
{
|
||||||
@@ -345,6 +363,11 @@ namespace GitHub.DistributedTask.Pipelines
|
|||||||
m_environmentVariables = null;
|
m_environmentVariables = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_fileTable?.Count == 0)
|
||||||
|
{
|
||||||
|
m_fileTable = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_maskHints?.Count == 0)
|
if (m_maskHints?.Count == 0)
|
||||||
{
|
{
|
||||||
m_maskHints = null;
|
m_maskHints = null;
|
||||||
@@ -374,6 +397,9 @@ namespace GitHub.DistributedTask.Pipelines
|
|||||||
[DataMember(Name = "EnvironmentVariables", EmitDefaultValue = false)]
|
[DataMember(Name = "EnvironmentVariables", EmitDefaultValue = false)]
|
||||||
private List<TemplateToken> m_environmentVariables;
|
private List<TemplateToken> m_environmentVariables;
|
||||||
|
|
||||||
|
[DataMember(Name = "FileTable", EmitDefaultValue = false)]
|
||||||
|
private List<String> m_fileTable;
|
||||||
|
|
||||||
[DataMember(Name = "Mask", EmitDefaultValue = false)]
|
[DataMember(Name = "Mask", EmitDefaultValue = false)]
|
||||||
private List<MaskHint> m_maskHints;
|
private List<MaskHint> m_maskHints;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
{
|
{
|
||||||
public PipelineTemplateEvaluator(
|
public PipelineTemplateEvaluator(
|
||||||
ITraceWriter trace,
|
ITraceWriter trace,
|
||||||
TemplateSchema schema)
|
TemplateSchema schema,
|
||||||
|
IList<String> fileTable)
|
||||||
{
|
{
|
||||||
if (!String.Equals(schema.Version, PipelineTemplateConstants.Workflow_1_0, StringComparison.Ordinal))
|
if (!String.Equals(schema.Version, PipelineTemplateConstants.Workflow_1_0, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
@@ -28,6 +29,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
|
|
||||||
m_trace = trace;
|
m_trace = trace;
|
||||||
m_schema = schema;
|
m_schema = schema;
|
||||||
|
m_fileTable = fileTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Int32 MaxDepth => 50;
|
public Int32 MaxDepth => 50;
|
||||||
@@ -324,6 +326,16 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
TraceWriter = m_trace,
|
TraceWriter = m_trace,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Add the file table
|
||||||
|
if (m_fileTable?.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var file in m_fileTable)
|
||||||
|
{
|
||||||
|
result.GetFileId(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add named context
|
||||||
if (contextData != null)
|
if (contextData != null)
|
||||||
{
|
{
|
||||||
foreach (var pair in contextData)
|
foreach (var pair in contextData)
|
||||||
@@ -346,6 +358,7 @@ namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
|||||||
|
|
||||||
private readonly ITraceWriter m_trace;
|
private readonly ITraceWriter m_trace;
|
||||||
private readonly TemplateSchema m_schema;
|
private readonly TemplateSchema m_schema;
|
||||||
|
private readonly IList<String> m_fileTable;
|
||||||
private readonly String[] s_contextNames = new[]
|
private readonly String[] s_contextNames = new[]
|
||||||
{
|
{
|
||||||
PipelineTemplateConstants.GitHub,
|
PipelineTemplateConstants.GitHub,
|
||||||
|
|||||||
@@ -0,0 +1,572 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using GitHub.DistributedTask.ObjectTemplating;
|
||||||
|
using GitHub.DistributedTask.ObjectTemplating.Tokens;
|
||||||
|
using YamlDotNet.Core;
|
||||||
|
using YamlDotNet.Core.Events;
|
||||||
|
|
||||||
|
namespace GitHub.DistributedTask.Pipelines.ObjectTemplating
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a YAML file into a TemplateToken
|
||||||
|
/// </summary>
|
||||||
|
public sealed class YamlObjectReader : IObjectReader
|
||||||
|
{
|
||||||
|
internal YamlObjectReader(
|
||||||
|
Int32? fileId,
|
||||||
|
TextReader input)
|
||||||
|
{
|
||||||
|
m_fileId = fileId;
|
||||||
|
m_parser = new Parser(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean AllowLiteral(out LiteralToken value)
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() is Scalar scalar)
|
||||||
|
{
|
||||||
|
// Tag specified
|
||||||
|
if (!String.IsNullOrEmpty(scalar.Tag))
|
||||||
|
{
|
||||||
|
// String tag
|
||||||
|
if (String.Equals(scalar.Tag, c_stringTag, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
value = new StringToken(m_fileId, scalar.Start.Line, scalar.Start.Column, scalar.Value);
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not plain style
|
||||||
|
if (scalar.Style != ScalarStyle.Plain)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException($"The scalar style '{scalar.Style}' on line {scalar.Start.Line} and column {scalar.Start.Column} is not valid with the tag '{scalar.Tag}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boolean, Float, Integer, or Null
|
||||||
|
switch (scalar.Tag)
|
||||||
|
{
|
||||||
|
case c_booleanTag:
|
||||||
|
value = ParseBoolean(scalar);
|
||||||
|
break;
|
||||||
|
case c_floatTag:
|
||||||
|
value = ParseFloat(scalar);
|
||||||
|
break;
|
||||||
|
case c_integerTag:
|
||||||
|
value = ParseInteger(scalar);
|
||||||
|
break;
|
||||||
|
case c_nullTag:
|
||||||
|
value = ParseNull(scalar);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"Unexpected tag '{scalar.Tag}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plain style, determine type using YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
||||||
|
if (scalar.Style == ScalarStyle.Plain)
|
||||||
|
{
|
||||||
|
if (MatchNull(scalar, out var nullToken))
|
||||||
|
{
|
||||||
|
value = nullToken;
|
||||||
|
}
|
||||||
|
else if (MatchBoolean(scalar, out var booleanToken))
|
||||||
|
{
|
||||||
|
value = booleanToken;
|
||||||
|
}
|
||||||
|
else if (MatchInteger(scalar, out var numberToken) ||
|
||||||
|
MatchFloat(scalar, out numberToken))
|
||||||
|
{
|
||||||
|
value = numberToken;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = new StringToken(m_fileId, scalar.Start.Line, scalar.Start.Column, scalar.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise assume string
|
||||||
|
value = new StringToken(m_fileId, scalar.Start.Line, scalar.Start.Column, scalar.Value);
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean AllowSequenceStart(out SequenceToken value)
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() is SequenceStart sequenceStart)
|
||||||
|
{
|
||||||
|
value = new SequenceToken(m_fileId, sequenceStart.Start.Line, sequenceStart.Start.Column);
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean AllowSequenceEnd()
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() is SequenceEnd)
|
||||||
|
{
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean AllowMappingStart(out MappingToken value)
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() is MappingStart mappingStart)
|
||||||
|
{
|
||||||
|
value = new MappingToken(m_fileId, mappingStart.Start.Line, mappingStart.Start.Column);
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean AllowMappingEnd()
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() is MappingEnd)
|
||||||
|
{
|
||||||
|
MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Consumes the last parsing events, which are expected to be DocumentEnd and StreamEnd.
|
||||||
|
/// </summary>
|
||||||
|
public void ValidateEnd()
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() is DocumentEnd)
|
||||||
|
{
|
||||||
|
MoveNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Expected document end parse event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EvaluateCurrent() is StreamEnd)
|
||||||
|
{
|
||||||
|
MoveNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Expected stream end parse event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MoveNext())
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Expected end of parse events");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Consumes the first parsing events, which are expected to be StreamStart and DocumentStart.
|
||||||
|
/// </summary>
|
||||||
|
public void ValidateStart()
|
||||||
|
{
|
||||||
|
if (EvaluateCurrent() != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Unexpected parser state");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MoveNext())
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Expected a parse event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EvaluateCurrent() is StreamStart)
|
||||||
|
{
|
||||||
|
MoveNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Expected stream start parse event");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EvaluateCurrent() is DocumentStart)
|
||||||
|
{
|
||||||
|
MoveNext();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Expected document start parse event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParsingEvent EvaluateCurrent()
|
||||||
|
{
|
||||||
|
if (m_current == null)
|
||||||
|
{
|
||||||
|
m_current = m_parser.Current;
|
||||||
|
if (m_current != null)
|
||||||
|
{
|
||||||
|
if (m_current is Scalar scalar)
|
||||||
|
{
|
||||||
|
// Verify not using achors
|
||||||
|
if (scalar.Anchor != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Anchors are not currently supported. Remove the anchor '{scalar.Anchor}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_current is MappingStart mappingStart)
|
||||||
|
{
|
||||||
|
// Verify not using achors
|
||||||
|
if (mappingStart.Anchor != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Anchors are not currently supported. Remove the anchor '{mappingStart.Anchor}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_current is SequenceStart sequenceStart)
|
||||||
|
{
|
||||||
|
// Verify not using achors
|
||||||
|
if (sequenceStart.Anchor != null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Anchors are not currently supported. Remove the anchor '{sequenceStart.Anchor}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!(m_current is MappingEnd) &&
|
||||||
|
!(m_current is SequenceEnd) &&
|
||||||
|
!(m_current is DocumentStart) &&
|
||||||
|
!(m_current is DocumentEnd) &&
|
||||||
|
!(m_current is StreamStart) &&
|
||||||
|
!(m_current is StreamEnd))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Unexpected parsing event type: {m_current.GetType().Name}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_current;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean MoveNext()
|
||||||
|
{
|
||||||
|
m_current = null;
|
||||||
|
return m_parser.MoveNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BooleanToken ParseBoolean(Scalar scalar)
|
||||||
|
{
|
||||||
|
if (MatchBoolean(scalar, out var token))
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowInvalidValue(scalar, c_booleanTag); // throws
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NumberToken ParseFloat(Scalar scalar)
|
||||||
|
{
|
||||||
|
if (MatchFloat(scalar, out var token))
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowInvalidValue(scalar, c_floatTag); // throws
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NumberToken ParseInteger(Scalar scalar)
|
||||||
|
{
|
||||||
|
if (MatchInteger(scalar, out var token))
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowInvalidValue(scalar, c_integerTag); // throws
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NullToken ParseNull(Scalar scalar)
|
||||||
|
{
|
||||||
|
if (MatchNull(scalar, out var token))
|
||||||
|
{
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowInvalidValue(scalar, c_nullTag); // throws
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean MatchBoolean(
|
||||||
|
Scalar scalar,
|
||||||
|
out BooleanToken value)
|
||||||
|
{
|
||||||
|
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
||||||
|
switch (scalar.Value ?? String.Empty)
|
||||||
|
{
|
||||||
|
case "true":
|
||||||
|
case "True":
|
||||||
|
case "TRUE":
|
||||||
|
value = new BooleanToken(m_fileId, scalar.Start.Line, scalar.Start.Column, true);
|
||||||
|
return true;
|
||||||
|
case "false":
|
||||||
|
case "False":
|
||||||
|
case "FALSE":
|
||||||
|
value = new BooleanToken(m_fileId, scalar.Start.Line, scalar.Start.Column, false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean MatchFloat(
|
||||||
|
Scalar scalar,
|
||||||
|
out NumberToken value)
|
||||||
|
{
|
||||||
|
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
||||||
|
var str = scalar.Value;
|
||||||
|
if (!String.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
// Check for [-+]?(\.inf|\.Inf|\.INF)|\.nan|\.NaN|\.NAN
|
||||||
|
switch (str)
|
||||||
|
{
|
||||||
|
case ".inf":
|
||||||
|
case ".Inf":
|
||||||
|
case ".INF":
|
||||||
|
case "+.inf":
|
||||||
|
case "+.Inf":
|
||||||
|
case "+.INF":
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, Double.PositiveInfinity);
|
||||||
|
return true;
|
||||||
|
case "-.inf":
|
||||||
|
case "-.Inf":
|
||||||
|
case "-.INF":
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, Double.NegativeInfinity);
|
||||||
|
return true;
|
||||||
|
case ".nan":
|
||||||
|
case ".NaN":
|
||||||
|
case ".NAN":
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, Double.NaN);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise check [-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?
|
||||||
|
|
||||||
|
// Skip leading sign
|
||||||
|
var index = str[0] == '-' || str[0] == '+' ? 1 : 0;
|
||||||
|
|
||||||
|
// Check for integer portion
|
||||||
|
var length = str.Length;
|
||||||
|
var hasInteger = false;
|
||||||
|
while (index < length && str[index] >= '0' && str[index] <= '9')
|
||||||
|
{
|
||||||
|
hasInteger = true;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for decimal point
|
||||||
|
var hasDot = false;
|
||||||
|
if (index < length && str[index] == '.')
|
||||||
|
{
|
||||||
|
hasDot = true;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for decimal portion
|
||||||
|
var hasDecimal = false;
|
||||||
|
while (index < length && str[index] >= '0' && str[index] <= '9')
|
||||||
|
{
|
||||||
|
hasDecimal = true;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check [-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)
|
||||||
|
if ((hasDot && hasDecimal) || hasInteger)
|
||||||
|
{
|
||||||
|
// Check for end
|
||||||
|
if (index == length)
|
||||||
|
{
|
||||||
|
// Try parse
|
||||||
|
if (Double.TryParse(str, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var doubleValue))
|
||||||
|
{
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, doubleValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Otherwise exceeds range
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowInvalidValue(scalar, c_floatTag); // throws
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check [eE][-+]?[0-9]
|
||||||
|
else if (index < length && (str[index] == 'e' || str[index] == 'E'))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
|
||||||
|
// Skip sign
|
||||||
|
if (index < length && (str[index] == '-' || str[index] == '+'))
|
||||||
|
{
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for exponent
|
||||||
|
var hasExponent = false;
|
||||||
|
while (index < length && str[index] >= '0' && str[index] <= '9')
|
||||||
|
{
|
||||||
|
hasExponent = true;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for end
|
||||||
|
if (hasExponent && index == length)
|
||||||
|
{
|
||||||
|
// Try parse
|
||||||
|
if (Double.TryParse(str, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out var doubleValue))
|
||||||
|
{
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, (Double)doubleValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Otherwise exceeds range
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ThrowInvalidValue(scalar, c_floatTag); // throws
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean MatchInteger(
|
||||||
|
Scalar scalar,
|
||||||
|
out NumberToken value)
|
||||||
|
{
|
||||||
|
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
||||||
|
var str = scalar.Value;
|
||||||
|
if (!String.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
// Check for [0-9]+
|
||||||
|
var firstChar = str[0];
|
||||||
|
if (firstChar >= '0' && firstChar <= '9' &&
|
||||||
|
str.Skip(1).All(x => x >= '0' && x <= '9'))
|
||||||
|
{
|
||||||
|
// Try parse
|
||||||
|
if (Double.TryParse(str, NumberStyles.None, CultureInfo.InvariantCulture, out var doubleValue))
|
||||||
|
{
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, doubleValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise exceeds range
|
||||||
|
ThrowInvalidValue(scalar, c_integerTag); // throws
|
||||||
|
}
|
||||||
|
// Check for (-|+)[0-9]+
|
||||||
|
else if ((firstChar == '-' || firstChar == '+') &&
|
||||||
|
str.Length > 1 &&
|
||||||
|
str.Skip(1).All(x => x >= '0' && x <= '9'))
|
||||||
|
{
|
||||||
|
// Try parse
|
||||||
|
if (Double.TryParse(str, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out var doubleValue))
|
||||||
|
{
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, doubleValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise exceeds range
|
||||||
|
ThrowInvalidValue(scalar, c_integerTag); // throws
|
||||||
|
}
|
||||||
|
// Check for 0x[0-9a-fA-F]+
|
||||||
|
else if (firstChar == '0' &&
|
||||||
|
str.Length > 2 &&
|
||||||
|
str[1] == 'x' &&
|
||||||
|
str.Skip(2).All(x => (x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')))
|
||||||
|
{
|
||||||
|
// Try parse
|
||||||
|
if (Int32.TryParse(str.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var integerValue))
|
||||||
|
{
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, integerValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise exceeds range
|
||||||
|
ThrowInvalidValue(scalar, c_integerTag); // throws
|
||||||
|
}
|
||||||
|
// Check for 0o[0-9]+
|
||||||
|
else if (firstChar == '0' &&
|
||||||
|
str.Length > 2 &&
|
||||||
|
str[1] == 'o' &&
|
||||||
|
str.Skip(2).All(x => x >= '0' && x <= '7'))
|
||||||
|
{
|
||||||
|
// Try parse
|
||||||
|
var integerValue = default(Int32);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
integerValue = Convert.ToInt32(str.Substring(2), 8);
|
||||||
|
}
|
||||||
|
// Otherwise exceeds range
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
ThrowInvalidValue(scalar, c_integerTag); // throws
|
||||||
|
}
|
||||||
|
|
||||||
|
value = new NumberToken(m_fileId, scalar.Start.Line, scalar.Start.Column, integerValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean MatchNull(
|
||||||
|
Scalar scalar,
|
||||||
|
out NullToken value)
|
||||||
|
{
|
||||||
|
// YAML 1.2 "core" schema https://yaml.org/spec/1.2/spec.html#id2804923
|
||||||
|
switch (scalar.Value ?? String.Empty)
|
||||||
|
{
|
||||||
|
case "":
|
||||||
|
case "null":
|
||||||
|
case "Null":
|
||||||
|
case "NULL":
|
||||||
|
case "~":
|
||||||
|
value = new NullToken(m_fileId, scalar.Start.Line, scalar.Start.Column);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThrowInvalidValue(
|
||||||
|
Scalar scalar,
|
||||||
|
String tag)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException($"The value '{scalar.Value}' on line {scalar.Start.Line} and column {scalar.Start.Column} is invalid for the type '{scalar.Tag}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
private const String c_booleanTag = "tag:yaml.org,2002:bool";
|
||||||
|
private const String c_floatTag = "tag:yaml.org,2002:float";
|
||||||
|
private const String c_integerTag = "tag:yaml.org,2002:int";
|
||||||
|
private const String c_nullTag = "tag:yaml.org,2002:null";
|
||||||
|
private const String c_stringTag = "tag:yaml.org,2002:string";
|
||||||
|
private readonly Int32? m_fileId;
|
||||||
|
private readonly Parser m_parser;
|
||||||
|
private ParsingEvent m_current;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
||||||
TimelineReference timeline = null;
|
TimelineReference timeline = null;
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
var result = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "someJob", "someJob", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
|
result.ContextData["github"] = new Pipelines.ContextData.DictionaryContextData();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace GitHub.Runner.Common.Tests.Listener
|
|||||||
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
||||||
TimelineReference timeline = null;
|
TimelineReference timeline = null;
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
return new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JobCancelMessage CreateJobCancelMessage()
|
private JobCancelMessage CreateJobCancelMessage()
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
TimelineReference timeline = new TimelineReference();
|
TimelineReference timeline = new TimelineReference();
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
string jobName = "some job name";
|
string jobName = "some job name";
|
||||||
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
||||||
{
|
{
|
||||||
Alias = Pipelines.PipelineConstants.SelfAlias,
|
Alias = Pipelines.PipelineConstants.SelfAlias,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
TimelineReference timeline = new TimelineReference();
|
TimelineReference timeline = new TimelineReference();
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
string jobName = "some job name";
|
string jobName = "some job name";
|
||||||
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
||||||
{
|
{
|
||||||
Alias = Pipelines.PipelineConstants.SelfAlias,
|
Alias = Pipelines.PipelineConstants.SelfAlias,
|
||||||
@@ -101,7 +101,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
TimelineReference timeline = new TimelineReference();
|
TimelineReference timeline = new TimelineReference();
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
string jobName = "some job name";
|
string jobName = "some job name";
|
||||||
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
||||||
{
|
{
|
||||||
Alias = Pipelines.PipelineConstants.SelfAlias,
|
Alias = Pipelines.PipelineConstants.SelfAlias,
|
||||||
@@ -152,7 +152,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
TimelineReference timeline = new TimelineReference();
|
TimelineReference timeline = new TimelineReference();
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
string jobName = "some job name";
|
string jobName = "some job name";
|
||||||
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, jobName, jobName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
jobRequest.Resources.Repositories.Add(new Pipelines.RepositoryResource()
|
||||||
{
|
{
|
||||||
Alias = Pipelines.PipelineConstants.SelfAlias,
|
Alias = Pipelines.PipelineConstants.SelfAlias,
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
};
|
};
|
||||||
|
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null);
|
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, "test", "test", null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), steps, null, null);
|
||||||
GitHubContext github = new GitHubContext();
|
GitHubContext github = new GitHubContext();
|
||||||
github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner");
|
github["repository"] = new Pipelines.ContextData.StringContextData("actions/runner");
|
||||||
_message.ContextData.Add("github", github);
|
_message.ContextData.Add("github", github);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
TaskOrchestrationPlanReference plan = new TaskOrchestrationPlanReference();
|
||||||
TimelineReference timeline = new Timeline(Guid.NewGuid());
|
TimelineReference timeline = new Timeline(Guid.NewGuid());
|
||||||
Guid jobId = Guid.NewGuid();
|
Guid jobId = Guid.NewGuid();
|
||||||
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null);
|
_message = new Pipelines.AgentJobRequestMessage(plan, timeline, jobId, testName, testName, null, null, null, new Dictionary<string, VariableValue>(), new List<MaskHint>(), new Pipelines.JobResources(), new Pipelines.ContextData.DictionaryContextData(), new Pipelines.WorkspaceOptions(), new List<Pipelines.ActionStep>(), null, null);
|
||||||
_message.Variables[Constants.Variables.System.Culture] = "en-US";
|
_message.Variables[Constants.Variables.System.Culture] = "en-US";
|
||||||
_message.Resources.Endpoints.Add(new ServiceEndpoint()
|
_message.Resources.Endpoints.Add(new ServiceEndpoint()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ namespace GitHub.Runner.Common.Tests.Worker
|
|||||||
new Pipelines.ContextData.DictionaryContextData()
|
new Pipelines.ContextData.DictionaryContextData()
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List<MaskHint>(), resources, context, null, actions, null);
|
var jobRequest = new Pipelines.AgentJobRequestMessage(plan, timeline, JobId, jobName, jobName, new StringToken(null, null, null, "ubuntu"), sidecarContainers, null, variables, new List<MaskHint>(), resources, context, null, actions, null, null);
|
||||||
return jobRequest;
|
return jobRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user