feat: allow to spawn and run a local reusable workflow (#1423)
* feat: allow to spawn and run a local reusable workflow This change contains the ability to parse/plan/run a local reusable workflow. There are still numerous things missing: - inputs - secrets - outputs * feat: add workflow_call inputs * test: improve inputs test * feat: add input defaults * feat: allow expressions in inputs * feat: use context specific expression evaluator * refactor: prepare for better re-usability * feat: add secrets for reusable workflows * test: use secrets during test run * feat: handle reusable workflow outputs Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
		| @@ -55,7 +55,7 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map | ||||
| 		// todo: should be unavailable | ||||
| 		// but required to interpolate/evaluate the step outputs on the job | ||||
| 		Steps:    rc.getStepsContext(), | ||||
| 		Secrets:  rc.Config.Secrets, | ||||
| 		Secrets:  getWorkflowSecrets(ctx, rc), | ||||
| 		Strategy: strategy, | ||||
| 		Matrix:   rc.Matrix, | ||||
| 		Needs:    using, | ||||
| @@ -101,7 +101,7 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step) | ||||
| 		Env:      *step.getEnv(), | ||||
| 		Job:      rc.getJobContext(), | ||||
| 		Steps:    rc.getStepsContext(), | ||||
| 		Secrets:  rc.Config.Secrets, | ||||
| 		Secrets:  getWorkflowSecrets(ctx, rc), | ||||
| 		Strategy: strategy, | ||||
| 		Matrix:   rc.Matrix, | ||||
| 		Needs:    using, | ||||
| @@ -315,6 +315,8 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str | ||||
| func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]interface{} { | ||||
| 	inputs := map[string]interface{}{} | ||||
|  | ||||
| 	setupWorkflowInputs(ctx, &inputs, rc) | ||||
|  | ||||
| 	var env map[string]string | ||||
| 	if step != nil { | ||||
| 		env = *step.getEnv() | ||||
| @@ -347,3 +349,54 @@ func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *mod | ||||
|  | ||||
| 	return inputs | ||||
| } | ||||
|  | ||||
| func setupWorkflowInputs(ctx context.Context, inputs *map[string]interface{}, rc *RunContext) { | ||||
| 	if rc.caller != nil { | ||||
| 		config := rc.Run.Workflow.WorkflowCallConfig() | ||||
|  | ||||
| 		for name, input := range config.Inputs { | ||||
| 			value := rc.caller.runContext.Run.Job().With[name] | ||||
| 			if value != nil { | ||||
| 				if str, ok := value.(string); ok { | ||||
| 					// evaluate using the calling RunContext (outside) | ||||
| 					value = rc.caller.runContext.ExprEval.Interpolate(ctx, str) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if value == nil && config != nil && config.Inputs != nil { | ||||
| 				value = input.Default | ||||
| 				if rc.ExprEval != nil { | ||||
| 					if str, ok := value.(string); ok { | ||||
| 						// evaluate using the called RunContext (inside) | ||||
| 						value = rc.ExprEval.Interpolate(ctx, str) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			(*inputs)[name] = value | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func getWorkflowSecrets(ctx context.Context, rc *RunContext) map[string]string { | ||||
| 	if rc.caller != nil { | ||||
| 		job := rc.caller.runContext.Run.Job() | ||||
| 		secrets := job.Secrets() | ||||
|  | ||||
| 		if secrets == nil && job.InheritSecrets() { | ||||
| 			secrets = rc.caller.runContext.Config.Secrets | ||||
| 		} | ||||
|  | ||||
| 		if secrets == nil { | ||||
| 			secrets = map[string]string{} | ||||
| 		} | ||||
|  | ||||
| 		for k, v := range secrets { | ||||
| 			secrets[k] = rc.caller.runContext.ExprEval.Interpolate(ctx, v) | ||||
| 		} | ||||
|  | ||||
| 		return secrets | ||||
| 	} | ||||
|  | ||||
| 	return rc.Config.Secrets | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user