Esempio n. 1
0
        public async Task RunAsync()
        {
            // Validate args.
            Trace.Entering();
            ArgUtil.NotNull(ExecutionContext, nameof(ExecutionContext));
            ArgUtil.NotNull(Action, nameof(Action));
            var taskManager    = HostContext.GetService <IActionManager>();
            var handlerFactory = HostContext.GetService <IHandlerFactory>();

            // Load the task definition and choose the handler.
            Definition definition = taskManager.LoadAction(ExecutionContext, Action);

            ArgUtil.NotNull(definition, nameof(definition));

            ActionExecutionData handlerData = definition.Data?.Execution;

            ArgUtil.NotNull(handlerData, nameof(handlerData));

            // The action has post cleanup defined.
            // we need to create timeline record for them and add them to the step list that StepRunner is using
            if (handlerData.HasCleanup && Stage == ActionRunStage.Main)
            {
                string postDisplayName = null;
                if (this.DisplayName.StartsWith(PipelineTemplateConstants.RunDisplayPrefix))
                {
                    postDisplayName = $"Post {this.DisplayName.Substring(PipelineTemplateConstants.RunDisplayPrefix.Length)}";
                }
                else
                {
                    postDisplayName = $"Post {this.DisplayName}";
                }

                var repositoryReference = Action.Reference as RepositoryPathReference;
                var pathString          = string.IsNullOrEmpty(repositoryReference.Path) ? string.Empty : $"/{repositoryReference.Path}";
                var repoString          = string.IsNullOrEmpty(repositoryReference.Ref) ? $"{repositoryReference.Name}{pathString}" :
                                          $"{repositoryReference.Name}{pathString}@{repositoryReference.Ref}";

                ExecutionContext.Debug($"Register post job cleanup for action: {repoString}");

                var actionRunner = HostContext.CreateService <IActionRunner>();
                actionRunner.Action      = Action;
                actionRunner.Stage       = ActionRunStage.Post;
                actionRunner.Condition   = handlerData.CleanupCondition;
                actionRunner.DisplayName = postDisplayName;

                ExecutionContext.RegisterPostJobStep($"{actionRunner.Action.Name}_post", actionRunner);
            }

            IStepHost stepHost = HostContext.CreateService <IDefaultStepHost>();

            // Makes directory for event_path data
            var tempDirectory     = HostContext.GetDirectory(WellKnownDirectory.Temp);
            var workflowDirectory = Path.Combine(tempDirectory, "_github_workflow");

            Directory.CreateDirectory(workflowDirectory);

            var gitHubEvent = ExecutionContext.GetGitHubContext("event");

            // adds the GitHub event path/file if the event exists
            if (gitHubEvent != null)
            {
                var workflowFile = Path.Combine(workflowDirectory, "event.json");
                Trace.Info($"Write event payload to {workflowFile}");
                File.WriteAllText(workflowFile, gitHubEvent, new UTF8Encoding(false));
                ExecutionContext.SetGitHubContext("event_path", workflowFile);
            }

            // Setup container stephost for running inside the container.
            if (ExecutionContext.Container != null)
            {
                // Make sure required container is already created.
                ArgUtil.NotNullOrEmpty(ExecutionContext.Container.ContainerId, nameof(ExecutionContext.Container.ContainerId));
                var containerStepHost = HostContext.CreateService <IContainerStepHost>();
                containerStepHost.Container = ExecutionContext.Container;
                stepHost = containerStepHost;
            }

            // Load the inputs.
            ExecutionContext.Debug("Loading inputs");
            var templateEvaluator = ExecutionContext.ToPipelineTemplateEvaluator();
            var inputs            = templateEvaluator.EvaluateStepInputs(Action.Inputs, ExecutionContext.ExpressionValues, ExecutionContext.ExpressionFunctions);

            foreach (KeyValuePair <string, string> input in inputs)
            {
                string message = "";
                if (definition.Data?.Deprecated?.TryGetValue(input.Key, out message) == true)
                {
                    ExecutionContext.Warning(String.Format("Input '{0}' has been deprecated with message: {1}", input.Key, message));
                }
            }

            // Merge the default inputs from the definition
            if (definition.Data?.Inputs != null)
            {
                var manifestManager = HostContext.GetService <IActionManifestManager>();
                foreach (var input in (definition.Data?.Inputs))
                {
                    string key = input.Key.AssertString("action input name").Value;
                    if (!inputs.ContainsKey(key))
                    {
                        inputs[key] = manifestManager.EvaluateDefaultInput(ExecutionContext, key, input.Value);
                    }
                }
            }

            // Load the action environment.
            ExecutionContext.Debug("Loading env");
            var environment = new Dictionary <String, String>(VarUtil.EnvironmentVariableKeyComparer);

#if OS_WINDOWS
            var envContext = ExecutionContext.ExpressionValues["env"] as DictionaryContextData;
#else
            var envContext = ExecutionContext.ExpressionValues["env"] as CaseSensitiveDictionaryContextData;
#endif
            // Apply environment from env context, env context contains job level env and action's evn block
            foreach (var env in envContext)
            {
                environment[env.Key] = env.Value.ToString();
            }

            // Apply action's intra-action state at last
            foreach (var state in ExecutionContext.IntraActionState)
            {
                environment[$"STATE_{state.Key}"] = state.Value ?? string.Empty;
            }

            // Create the handler.
            IHandler handler = handlerFactory.Create(
                ExecutionContext,
                Action.Reference,
                stepHost,
                handlerData,
                inputs,
                environment,
                ExecutionContext.Variables,
                actionDirectory: definition.Directory);

            // Print out action details
            handler.PrintActionDetails(Stage);

            // Run the task.
            await handler.RunAsync(Stage);
        }