-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Composite Actions Support for Multiple Run Steps #549
Conversation
c4848ee
to
c6c0571
Compare
76af6f9
to
038e5e2
Compare
src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConverter.cs
Show resolved
Hide resolved
src/Runner.Worker/ActionManager.cs
Outdated
else if (definition.Data.Execution.ExecutionType == ActionExecutionType.Composite && !String.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA"))) | ||
{ | ||
var compositeAction = definition.Data.Execution as CompositeActionExecutionData; | ||
Trace.Info($"Action steps: {compositeAction.Steps}."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this will print Action steps: Object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the json representation is desired (too noisy? esp with large inline scripts?) then see StringUtil or IOUtil (has function to convert to/from json)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TingluoHuang thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, compositeAction.Steps
is of type List<Pipelines.ActionStep>
. If we were to output this, what would be the best way to output the values in a json string format?
Right now, this Trace.info statement returns the object string representation: GitHub.DistributedTask.Pipelines.ActionStep
If we were to print out the steps, it might make more sense to print them out in the LoadCompositeSteps
function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From @TingluoHuang (thanks Ting!!) :
Verbose will shows up only in dev mode (you build the runner from source code.)
Trace.Info($"Load {compositeAction.Steps.Count} action steps.");
Trace.Verbose($"Details: {StringUtil.ConvertToJson(compositeAction.Steps}");
So, I'll do that.
{ | ||
if (stepsLoaded == null) | ||
{ | ||
throw new ArgumentNullException($"No steps provided."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this error give the user enough context to know where the problem is? Like does it convey that an error happened when loading the path-to-action.yml
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i guess we would have the same problem with the other place too (in this file)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this error makes sense and is appropriate.
At the top of ConvertRuns
:
var stepsLoaded = default(List<Pipelines.ActionStep>);
Then, we check in the action.yml
file to see if there is any steps
token:
case "steps":
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TESTING_COMPOSITE_ACTIONS_ALPHA")))
{
var steps = run.Value.AssertSequence("steps");
var evaluator = executionContext.ToPipelineTemplateEvaluator();
stepsLoaded = evaluator.LoadCompositeSteps(steps);
break;
}
throw new Exception("You aren't supposed to be using Composite Actions yet!");
If there are any issues with loading the steps, there would be an error reported in the LoadCompositeSteps()
or LoadStep()
function in the pipeline template evaulator. If the steps attribute is empty, there would be no error and LoadCompositeSteps would return the default value of List which is equivalent to null.
Thus, if stepsLoaded
is null, it must be because there was no steps
attribute written in the action.yml
by the user.
Thus, I believe throwing this message is appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: Add a more helpful error message + including file name, etc. to show user that it's because of their yaml file
(Just add TODO for now)
// placed after the queued composite steps | ||
// This will take only O(n+m) time which would be just as efficient if we refactored the code of JobSteps to a PriorityQueue | ||
// This temp Queue is created in the CompositeActionHandler. | ||
var newGuid = Guid.NewGuid(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm worried a little bit because we're not adding the contexts from the job message, like we normally do when creating steps.
I know this is what Post does, but wouldnt surprise me if there is a bug there too.
It may be safe, since we're copying the root node (maybe job message contexts copied there first so safe?)
Let's add a TODO comment in the code like "// TODO: confirm whether not copying message contexts is safe".
I can help look into this more. It's tedious because values are delay expanded sometimes (sometimes evaluated early, like DisplayName). I wish the code were designed simpler... hmm thinking about alternatives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added TODO. Leaving open for visibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After more testing for the env flow, I realized that the display name does not evaluate the env variables. This has to do with not passing the context. See: #557 (comment)
Ex: https://github.com/ethanchewy/testing-actions/runs/795652488?check_suite_focus=true
Building in support will occur in the env flow PR: #557
Never mind, in both the composite action and workflow steps, the environment contexts are evaluated correctly: https://github.com/ethanchewy/testing-actions/actions/runs/143774560
Still investigating but for now I think the contexts are handled correctly for the composite action steps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tl;dr The context is exposed correctly in env flow PR and solves this concern
In the env flow PR, I handle the contexts for each correctly: https://github.com/actions/runner/pull/557/files#diff-e3d54b1d0cbdce4d358272df29857cf2R225 by setting the step.EnvironmentVariables
to the environment variables.
Demo: https://github.com/ethanchewy/testing-actions/actions/runs/143774560
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, since we add each of our composite steps to JobSteps, eventually each of the steps will be run via the ScriptHandler.
In the ScriptHandler, it exposes the context to the step/job: https://github.com/actions/runner/blob/master/src/Runner.Worker/Handlers/ScriptHandler.cs#L248-L258
src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateConstants.cs
Outdated
Show resolved
Hide resolved
src/Sdk/DTPipelines/Pipelines/ObjectTemplating/PipelineTemplateEvaluator.cs
Show resolved
Hide resolved
This comment has been minimized.
This comment has been minimized.
@@ -0,0 +1,97 @@ | |||
using System.IO; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sort
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
system first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
named at the bottom
step.ExecutionContext = Root.CreateChild(newGuid, step.DisplayName, newGuid.ToString("N"), null, null); | ||
step.ExecutionContext.ExpressionValues["inputs"] = inputsData; | ||
// TODO: confirm whether not copying message contexts is safe | ||
Root.JobSteps.Insert(0, step); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: Replace 0 with location so that the steps are ordered.
"job", | ||
"runner", | ||
"env", | ||
"hashFiles(1,255)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"always(0,0)",
"failure(0,0)",
"cancelled(0,0)",
"success(0,0)",
"hashFiles(1,255)"
@@ -400,7 +426,8 @@ public class PipelineTemplateEvaluator | |||
private TemplateContext CreateContext( | |||
DictionaryContextData contextData, | |||
IList<IFunctionInfo> expressionFunctions, | |||
IEnumerable<KeyValuePair<String, Object>> expressionState = null) | |||
IEnumerable<KeyValuePair<String, Object>> expressionState = null, | |||
bool setMissingContext = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe switch to false when going to server (and also switch the logic in the function to reflect this). We'll put these changes in the server side.
* Composite Action Run Steps * Clean up trace messages + add Trace debug in ActionManager * Change String to string * Add comma to Composite * Change JobSteps to a List, Change Register Step function name * Add TODO, remove unn. content * Remove unnecessary code * Fix unit tests * Add verbose trace logs which are only viewable by devs * Sort usings in Composite Action Handler * Change 0 to location * Update context variables in composite action yaml * Add helpful error message for null steps
In this PR, we support executing multiple run steps with custom inputs in a composite action. You can use this feature by writing
using: "composite"
in the action.yml file. Our goal for our first version is to be able to run simple, multiple steps in an action.yml file. This first step allows for users to run a list of steps in theaction.yml
file rather than invoking a javascript entry point. This will eventually allow us to support nesting of actions within an action, etc.Here is an in-depth example:
ethanchewy/test-composite/action.yml
:workflow.yml
Github UI Action View: https://github.com/ethanchewy/testing-actions/runs/778225962?check_suite_focus=true
What this doesn't support yet (for future PRs):
How this was implemented at a high level:
We have one queue that keeps track of the composite actions transformed into a job step (in the process, it’s added to the Root node) => then we requeue in a way where these composite actions are executed first.
None of the steps are actually evaluated by the CompositeActionsHandler but they are pushed to the front of the job step queue and handled by other handlers depending on its type (ex: Script handler).
This is an experimental feature that can only be turned on via turning the feature flag on:
export TESTING_COMPOSITE_ACTIONS_ALPHA=1
./run.sh