Example #1
0
        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);
        }
Example #2
0
        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);
        }