harness-drone/plugin/converter/starlark/args.go
Eoin McAfee 1ebfe95277
Add support for nested data objects within templates (#3110)
* Add support for nested data objects within templates
2021-08-02 17:23:02 +01:00

179 lines
5.8 KiB
Go

// Copyright 2019 Drone IO, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package starlark
import (
"fmt"
"reflect"
"github.com/drone/drone/core"
"go.starlark.net/starlark"
"go.starlark.net/starlarkstruct"
)
// TODO(bradrydzewski) add repository id
// TODO(bradrydzewski) add repository timeout
// TODO(bradrydzewski) add repository counter
// TODO(bradrydzewski) add repository created
// TODO(bradrydzewski) add repository updated
// TODO(bradrydzewski) add repository synced
// TODO(bradrydzewski) add repository version
// TODO(bradrydzewski) add build id, will always be zero value
// TODO(bradrydzewski) add build number, will always be zero value
// TODO(bradrydzewski) add build started, will always be zero value
// TODO(bradrydzewski) add build finished, will always be zero value
// TODO(bradrydzewski) add build created, will always be zero value
// TODO(bradrydzewski) add build updated, will always be zero value
// TODO(bradrydzewski) add build parent
// TODO(bradrydzewski) add build timestamp
func createArgs(repo *core.Repository, build *core.Build, input map[string]interface{}) ([]starlark.Value, error) {
inputArgs, err := fromInput(input)
if err != nil {
return nil, err
}
args := []starlark.Value{
starlarkstruct.FromStringDict(
starlark.String("context"),
starlark.StringDict{
"repo": starlarkstruct.FromStringDict(starlark.String("repo"), fromRepo(repo)),
"build": starlarkstruct.FromStringDict(starlark.String("build"), fromBuild(build)),
"input": starlarkstruct.FromStringDict(starlark.String("input"), inputArgs),
},
),
}
return args, nil
}
func fromInput(input map[string]interface{}) (starlark.StringDict, error) {
out := map[string]starlark.Value{}
for key, value := range input {
v := reflect.ValueOf(value)
result, err := toValue(v)
if err != nil {
return nil, err
}
out[key] = result
}
return out, nil
}
func toValue(val reflect.Value) (starlark.Value, error) {
kind := val.Kind()
if kind == reflect.Ptr {
kind = val.Elem().Kind()
}
switch kind {
case reflect.Bool:
return starlark.Bool(val.Bool()), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return starlark.MakeInt64(val.Int()), nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return starlark.MakeUint64(val.Uint()), nil
case reflect.Float32, reflect.Float64:
return starlark.Float(val.Float()), nil
case reflect.Map:
dict := new(starlark.Dict)
for _, key := range val.MapKeys() {
value := val.MapIndex(key)
getValue, err := toValue(reflect.ValueOf(value.Interface()))
if err != nil {
return nil, err
}
dict.SetKey(
starlark.String(fmt.Sprint(key)),
getValue,
)
}
return dict, nil
case reflect.String:
return starlark.String(val.String()), nil
case reflect.Slice, reflect.Array:
list := new(starlark.List)
for i := 0; i < val.Len(); i++ {
keyValue := val.Index(i).Interface()
vOf := reflect.ValueOf(keyValue)
result, err := toValue(vOf)
if err != nil {
return nil, err
}
list.Append(result)
}
return list, nil
}
return nil, fmt.Errorf("type %T is not a supported starlark type", val.Interface())
}
func fromBuild(v *core.Build) starlark.StringDict {
return starlark.StringDict{
"event": starlark.String(v.Event),
"action": starlark.String(v.Action),
"cron": starlark.String(v.Cron),
"environment": starlark.String(v.Deploy),
"link": starlark.String(v.Link),
"branch": starlark.String(v.Target),
"source": starlark.String(v.Source),
"before": starlark.String(v.Before),
"after": starlark.String(v.After),
"target": starlark.String(v.Target),
"ref": starlark.String(v.Ref),
"commit": starlark.String(v.After),
"title": starlark.String(v.Title),
"message": starlark.String(v.Message),
"source_repo": starlark.String(v.Fork),
"author_login": starlark.String(v.Author),
"author_name": starlark.String(v.AuthorName),
"author_email": starlark.String(v.AuthorEmail),
"author_avatar": starlark.String(v.AuthorAvatar),
"sender": starlark.String(v.Sender),
"debug": starlark.Bool(v.Debug),
"params": fromMap(v.Params),
}
}
func fromRepo(v *core.Repository) starlark.StringDict {
return starlark.StringDict{
"uid": starlark.String(v.UID),
"name": starlark.String(v.Name),
"namespace": starlark.String(v.Namespace),
"slug": starlark.String(v.Slug),
"git_http_url": starlark.String(v.HTTPURL),
"git_ssh_url": starlark.String(v.SSHURL),
"link": starlark.String(v.Link),
"branch": starlark.String(v.Branch),
"config": starlark.String(v.Config),
"private": starlark.Bool(v.Private),
"visibility": starlark.String(v.Visibility),
"active": starlark.Bool(v.Active),
"trusted": starlark.Bool(v.Trusted),
"protected": starlark.Bool(v.Protected),
"ignore_forks": starlark.Bool(v.IgnoreForks),
"ignore_pull_requests": starlark.Bool(v.IgnorePulls),
}
}
func fromMap(m map[string]string) *starlark.Dict {
dict := new(starlark.Dict)
for k, v := range m {
dict.SetKey(
starlark.String(k),
starlark.String(v),
)
}
return dict
}