Switch to interface{} instead of map[string]... (#700)

* fix: change `env` to be an interface

allows to use GitHub functions like `fromJson()`

* fix: change matrix to an interface instead of map

This allows to use GitHub functions like `fromJson()` to create dynamic
matrixes

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Ryan (hackercat) 2021-06-06 14:53:18 +00:00 committed by GitHub
parent fa93f4d5e7
commit 33ccfa6f3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 20 deletions

View file

@ -58,7 +58,7 @@ type Job struct {
Name string `yaml:"name"`
RawNeeds yaml.Node `yaml:"needs"`
RawRunsOn yaml.Node `yaml:"runs-on"`
Env map[string]string `yaml:"env"`
Env interface{} `yaml:"env"`
If yaml.Node `yaml:"if"`
Steps []*Step `yaml:"steps"`
TimeoutMinutes int64 `yaml:"timeout-minutes"`
@ -70,9 +70,9 @@ type Job struct {
// Strategy for the job
type Strategy struct {
FailFast bool `yaml:"fail-fast"`
MaxParallel int `yaml:"max-parallel"`
Matrix map[string][]interface{} `yaml:"matrix"`
FailFast bool `yaml:"fail-fast"`
MaxParallel int `yaml:"max-parallel"`
Matrix interface{} `yaml:"matrix"`
}
// Default settings that will apply to all steps in the job or workflow
@ -148,23 +148,75 @@ func (j *Job) RunsOn() []string {
return nil
}
func environment(e interface{}) map[string]string {
env := make(map[string]string)
switch t := e.(type) {
case map[string]interface{}:
for k, v := range t {
switch t := v.(type) {
case string:
env[k] = t
case interface{}:
env[k] = ""
}
}
case map[string]string:
for k, v := range e.(map[string]string) {
env[k] = v
}
}
return env
}
func (j *Job) Environment() map[string]string {
return environment(j.Env)
}
func (j *Job) Matrix() map[string][]interface{} {
a := reflect.ValueOf(j.Strategy.Matrix)
if a.Type().Kind() == reflect.Map {
output := make(map[string][]interface{})
for _, e := range a.MapKeys() {
v := a.MapIndex(e)
switch t := v.Interface().(type) {
case []interface{}:
output[e.String()] = t
case interface{}:
var in []interface{}
in = append(in, t)
output[e.String()] = in
}
}
return output
}
return nil
}
// GetMatrixes returns the matrix cross product
func (j *Job) GetMatrixes() []map[string]interface{} {
matrixes := make([]map[string]interface{}, 0)
if j.Strategy != nil {
m := j.Matrix()
includes := make([]map[string]interface{}, 0)
for _, v := range j.Strategy.Matrix["include"] {
includes = append(includes, v.(map[string]interface{}))
for _, v := range m["include"] {
switch t := v.(type) {
case []interface{}:
for _, i := range t {
includes = append(includes, i.(map[string]interface{}))
}
case interface{}:
includes = append(includes, v.(map[string]interface{}))
}
}
delete(j.Strategy.Matrix, "include")
delete(m, "include")
excludes := make([]map[string]interface{}, 0)
for _, v := range j.Strategy.Matrix["exclude"] {
for _, v := range m["exclude"] {
excludes = append(excludes, v.(map[string]interface{}))
}
delete(j.Strategy.Matrix, "exclude")
delete(m, "exclude")
matrixProduct := common.CartesianProduct(j.Strategy.Matrix)
matrixProduct := common.CartesianProduct(m)
MATRIX:
for _, matrix := range matrixProduct {
@ -217,7 +269,7 @@ type Step struct {
Run string `yaml:"run"`
WorkingDirectory string `yaml:"working-directory"`
Shell string `yaml:"shell"`
Env map[string]string `yaml:"env"`
Env interface{} `yaml:"env"`
With map[string]string `yaml:"with"`
ContinueOnError bool `yaml:"continue-on-error"`
TimeoutMinutes int64 `yaml:"timeout-minutes"`
@ -235,18 +287,20 @@ func (s *Step) String() string {
return s.ID
}
func (s *Step) Environment() map[string]string {
return environment(s.Env)
}
// GetEnv gets the env for a step
func (s *Step) GetEnv() map[string]string {
rtnEnv := make(map[string]string)
for k, v := range s.Env {
rtnEnv[k] = v
}
env := s.Environment()
for k, v := range s.With {
envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(k), "_")
envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey))
rtnEnv[envKey] = v
env[envKey] = v
}
return rtnEnv
return env
}
// ShellCommand returns the command for the shell

View file

@ -55,7 +55,7 @@ type stepResult struct {
// GetEnv returns the env for the context
func (rc *RunContext) GetEnv() map[string]string {
if rc.Env == nil {
rc.Env = mergeMaps(rc.Config.Env, rc.Run.Workflow.Env, rc.Run.Job().Env)
rc.Env = mergeMaps(rc.Config.Env, rc.Run.Workflow.Env, rc.Run.Job().Environment())
}
rc.Env["ACT"] = "true"
return rc.Env

View file

@ -574,13 +574,15 @@ func (sc *StepContext) execAsComposite(ctx context.Context, step *model.Step, _
stepClone.Env = make(map[string]string)
}
actionPath := filepath.Join(containerActionDir, actionName)
stepClone.Env["GITHUB_ACTION_PATH"] = actionPath
env := stepClone.Environment()
env["GITHUB_ACTION_PATH"] = actionPath
stepClone.Run = strings.ReplaceAll(stepClone.Run, "${{ github.action_path }}", actionPath)
stepContext := StepContext{
RunContext: rcClone,
Step: &stepClone,
Env: mergeMaps(sc.Env, stepClone.Env),
Env: mergeMaps(sc.Env, env),
}
// Interpolate the outer inputs into the composite step with items