public ActionDefinitionData Load(IExecutionContext executionContext, string manifestFile) { var templateContext = CreateContext(executionContext); ActionDefinitionData actionDefinition = new ActionDefinitionData(); // Clean up file name real quick // Instead of using Regex which can be computationally expensive, // we can just remove the # of characters from the fileName according to the length of the basePath string basePath = HostContext.GetDirectory(WellKnownDirectory.Actions); string fileRelativePath = manifestFile; if (manifestFile.Contains(basePath)) { fileRelativePath = manifestFile.Remove(0, basePath.Length + 1); } try { var token = default(TemplateToken); // Get the file ID var fileId = templateContext.GetFileId(fileRelativePath); // Add this file to the FileTable in executionContext if it hasn't been added already // we use > since fileID is 1 indexed if (fileId > executionContext.FileTable.Count) { executionContext.FileTable.Add(fileRelativePath); } // Read the file var fileContent = File.ReadAllText(manifestFile); using (var stringReader = new StringReader(fileContent)) { var yamlObjectReader = new YamlObjectReader(fileId, stringReader); token = TemplateReader.Read(templateContext, "action-root", yamlObjectReader, fileId, out _); } var actionMapping = token.AssertMapping("action manifest root"); var actionOutputs = default(MappingToken); var actionRunValueToken = default(TemplateToken); foreach (var actionPair in actionMapping) { var propertyName = actionPair.Key.AssertString($"action.yml property key"); switch (propertyName.Value) { case "name": actionDefinition.Name = actionPair.Value.AssertString("name").Value; break; case "outputs": if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA"))) { actionOutputs = actionPair.Value.AssertMapping("outputs"); break; } Trace.Info($"Ignore action property outputs. Outputs for a whole action is not supported yet."); break; case "description": actionDefinition.Description = actionPair.Value.AssertString("description").Value; break; case "inputs": ConvertInputs(templateContext, actionPair.Value, actionDefinition); break; case "runs": // Defer runs token evaluation to after for loop to ensure that order of outputs doesn't matter. actionRunValueToken = actionPair.Value; break; default: Trace.Info($"Ignore action property {propertyName}."); break; } } // Evaluate Runs Last if (actionRunValueToken != null) { actionDefinition.Execution = ConvertRuns(executionContext, templateContext, actionRunValueToken, actionOutputs); } } catch (Exception ex) { Trace.Error(ex); templateContext.Errors.Add(ex); } if (templateContext.Errors.Count > 0) { foreach (var error in templateContext.Errors) { Trace.Error($"Action.yml load error: {error.Message}"); executionContext.Error(error.Message); } throw new ArgumentException($"Fail to load {fileRelativePath}"); } if (actionDefinition.Execution == null) { executionContext.Debug($"Loaded action.yml file: {StringUtil.ConvertToJson(actionDefinition)}"); throw new ArgumentException($"Top level 'runs:' section is required for {fileRelativePath}"); } else { Trace.Info($"Loaded action.yml file: {StringUtil.ConvertToJson(actionDefinition)}"); } return(actionDefinition); }
public ActionDefinitionData Load(IExecutionContext executionContext, string manifestFile) { var context = CreateContext(executionContext, null); ActionDefinitionData actionDefinition = new ActionDefinitionData(); try { var token = default(TemplateToken); // Get the file ID var fileId = context.GetFileId(manifestFile); var fileContent = File.ReadAllText(manifestFile); using (var stringReader = new StringReader(fileContent)) { var yamlObjectReader = new YamlObjectReader(null, stringReader); token = TemplateReader.Read(context, "action-root", yamlObjectReader, fileId, out _); } var actionMapping = token.AssertMapping("action manifest root"); foreach (var actionPair in actionMapping) { var propertyName = actionPair.Key.AssertString($"action.yml property key"); switch (propertyName.Value) { case "name": actionDefinition.Name = actionPair.Value.AssertString("name").Value; break; case "description": actionDefinition.Description = actionPair.Value.AssertString("description").Value; break; case "inputs": ConvertInputs(context, actionPair.Value, actionDefinition); break; case "runs": actionDefinition.Execution = ConvertRuns(context, actionPair.Value); break; default: Trace.Info($"Ignore action property {propertyName}."); break; } } } catch (Exception ex) { Trace.Error(ex); context.Errors.Add(ex); } if (context.Errors.Count > 0) { foreach (var error in context.Errors) { Trace.Error($"Action.yml load error: {error.Message}"); executionContext.Error(error.Message); } throw new ArgumentException($"Fail to load {manifestFile}"); } if (actionDefinition.Execution == null) { executionContext.Debug($"Loaded action.yml file: {StringUtil.ConvertToJson(actionDefinition)}"); throw new ArgumentException($"Top level 'run:' section is required for {manifestFile}"); } else { Trace.Info($"Loaded action.yml file: {StringUtil.ConvertToJson(actionDefinition)}"); } return(actionDefinition); }