mirror of
https://code.forgejo.org/forgejo/runner.git
synced 2025-09-15 18:57:01 +00:00
Add support for composite actions (#514)
* Add support for composite actions * Fix to make more complex composite actions work * Fix to make more complex composite actions work * Let's validate the steps in the composite steps to fail on uses and run's without shell, like the real world * Add support for composite actions * Add workflow to test composite actions * Log instead of panicing when output is mismatched * Merge maps so environment variables are not lost * Remove Debug * Correect merge error * Remove invalid composite tests. * Fix composite test Co-authored-by: Casey Lee <cplee@nektos.com> Co-authored-by: monkers <mikem@msquaredconsulting.co.uk> Co-authored-by: Mike Moncrieffe <69815687+mikemonkers@users.noreply.github.com>
This commit is contained in:
parent
952e823339
commit
13092e269b
11 changed files with 236 additions and 16 deletions
62
act/runner/step_context.go
Normal file → Executable file
62
act/runner/step_context.go
Normal file → Executable file
|
@ -489,10 +489,72 @@ func (sc *StepContext) runAction(actionDir string, actionPath string) common.Exe
|
|||
).Finally(
|
||||
stepContainer.Remove().IfBool(!rc.Config.ReuseContainers),
|
||||
)(ctx)
|
||||
case model.ActionRunsUsingComposite:
|
||||
for outputName, output := range action.Outputs {
|
||||
re := regexp.MustCompile(`\${{ steps\.([a-zA-Z_][a-zA-Z0-9_-]+)\.outputs\.([a-zA-Z_][a-zA-Z0-9_-]+) }}`)
|
||||
matches := re.FindStringSubmatch(output.Value)
|
||||
if len(matches) > 2 {
|
||||
if sc.RunContext.OutputMappings == nil {
|
||||
sc.RunContext.OutputMappings = make(map[MappableOutput]MappableOutput)
|
||||
}
|
||||
|
||||
k := MappableOutput{StepID: matches[1], OutputName: matches[2]}
|
||||
v := MappableOutput{StepID: step.ID, OutputName: outputName}
|
||||
sc.RunContext.OutputMappings[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
var executors []common.Executor
|
||||
stepID := 0
|
||||
for _, compositeStep := range action.Runs.Steps {
|
||||
stepClone := compositeStep
|
||||
// Take a copy of the run context structure (rc is a pointer)
|
||||
// Then take the address of the new structure
|
||||
rcCloneStr := *rc
|
||||
rcClone := &rcCloneStr
|
||||
if stepClone.ID == "" {
|
||||
stepClone.ID = fmt.Sprintf("composite-%d", stepID)
|
||||
stepID++
|
||||
}
|
||||
rcClone.CurrentStep = stepClone.ID
|
||||
|
||||
if err := compositeStep.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Setup the outputs for the composite steps
|
||||
if _, ok := rcClone.StepResults[stepClone.ID]; ! ok {
|
||||
rcClone.StepResults[stepClone.ID] = &stepResult{
|
||||
Success: true,
|
||||
Outputs: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
stepClone.Run = strings.ReplaceAll(stepClone.Run, "${{ github.action_path }}", filepath.Join(containerActionDir, actionName))
|
||||
|
||||
stepContext := StepContext{
|
||||
RunContext: rcClone,
|
||||
Step: &stepClone,
|
||||
Env: mergeMaps(sc.Env, stepClone.Env),
|
||||
}
|
||||
|
||||
// Interpolate the outer inputs into the composite step with items
|
||||
exprEval := sc.NewExpressionEvaluator()
|
||||
for k, v := range stepContext.Step.With {
|
||||
|
||||
if strings.Contains(v, "inputs") {
|
||||
stepContext.Step.With[k] = exprEval.Interpolate(v)
|
||||
}
|
||||
}
|
||||
|
||||
executors = append(executors, stepContext.Executor())
|
||||
}
|
||||
return common.NewPipelineExecutor(executors...)(ctx)
|
||||
default:
|
||||
return fmt.Errorf(fmt.Sprintf("The runs.using key must be one of: %v, got %s", []string{
|
||||
model.ActionRunsUsingDocker,
|
||||
model.ActionRunsUsingNode12,
|
||||
model.ActionRunsUsingComposite,
|
||||
}, action.Runs.Using))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue