Merge branch 'master' of github.com:drone/drone into redis-pubsub

This commit is contained in:
Marko Gaćeša 2021-08-02 18:48:29 +02:00
commit 4369d292c2
9 changed files with 178 additions and 15 deletions

View file

@ -0,0 +1,27 @@
## Commit Checklist
Thank you for creating a pull request! To help us review / merge this can you make sure that your PR adheres as much as possible to the following.
### The Basics
- Commit is a single logical unit of work, only use multiple commits if doing different tasks
- Commit does not include commented out code or unneeded files
- rebase of main branch
### The Content
- Must include testing for bug or feature
- Must include appropriate documentation changes if it is introducing a new feature or changing existing functionality
- Must pass existing test suites
### The Commit Message
- Short meaningful description (ex: remove deprecated steps)
- Uses the imperative, present tense: "change", not "changed" or "changes"
- Includes motivation for the change, and contrasts its implementation with the previous behavior
### The Pull Request
- What is the reason for this change
- Example usage of the failure for a bug, or configuration and expected output for a feature
- Steps to test the change

View file

@ -15,6 +15,9 @@
package starlark
import (
"fmt"
"reflect"
"github.com/drone/drone/core"
"go.starlark.net/starlark"
@ -38,27 +41,82 @@ import (
// TODO(bradrydzewski) add build parent
// TODO(bradrydzewski) add build timestamp
func createArgs(repo *core.Repository, build *core.Build, input map[string]interface{}) []starlark.Value {
return []starlark.Value{
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"), fromInput(input)),
"input": starlarkstruct.FromStringDict(starlark.String("input"), inputArgs),
},
),
}
return args, nil
}
func fromInput(input map[string]interface{}) starlark.StringDict {
func fromInput(input map[string]interface{}) (starlark.StringDict, error) {
out := map[string]starlark.Value{}
for k, v := range input {
if s, ok := v.(string); ok {
out[k] = starlark.String(s)
for key, value := range input {
v := reflect.ValueOf(value)
result, err := toValue(v)
if err != nil {
return nil, err
}
out[key] = result
}
return out
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 {

View file

@ -94,7 +94,10 @@ func Parse(req *core.ConvertArgs, template *core.Template, templateData map[stri
// create the input args and invoke the main method
// using the input args.
args := createArgs(req.Repo, req.Build, templateData)
args, err := createArgs(req.Repo, req.Build, templateData)
if err != nil {
return "", err
}
// set the maximum number of operations in the script. this
// mitigates long running scripts.

View file

@ -70,6 +70,7 @@ func (p *templatePlugin) Convert(ctx context.Context, req *core.ConvertArgs) (*c
if err != nil {
return nil, err
}
// Check if file is of type Starlark
if strings.HasSuffix(templateArgs.Load, ".script") ||
strings.HasSuffix(templateArgs.Load, ".star") ||

View file

@ -237,3 +237,65 @@ func TestTemplatePluginConvertJsonnet(t *testing.T) {
t.Errorf("Want %q got %q", want, got)
}
}
func TestTemplateNestedValuesPluginConvertStarlark(t *testing.T) {
templateArgs, err := ioutil.ReadFile("testdata/starlark-nested.template.yml")
if err != nil {
t.Error(err)
return
}
req := &core.ConvertArgs{
Build: &core.Build{
After: "3d21ec53a331a6f037a91c368710b99387d012c1",
},
Repo: &core.Repository{
Slug: "octocat/hello-world",
Config: ".drone.yml",
Namespace: "octocat",
},
Config: &core.Config{
Data: string(templateArgs),
},
}
beforeInput, err := ioutil.ReadFile("testdata/starlark.input-nested.star")
if err != nil {
t.Error(err)
return
}
after, err := ioutil.ReadFile("testdata/starlark.input-nested.star.golden")
if err != nil {
t.Error(err)
return
}
template := &core.Template{
Name: "test.nested.starlark",
Data: string(beforeInput),
Namespace: "octocat",
}
controller := gomock.NewController(t)
defer controller.Finish()
templates := mock.NewMockTemplateStore(controller)
templates.EXPECT().FindName(gomock.Any(), template.Name, req.Repo.Namespace).Return(template, nil)
plugin := Template(templates)
config, err := plugin.Convert(noContext, req)
if err != nil {
t.Error(err)
return
}
if config == nil {
t.Error("Want non-nil configuration")
return
}
if want, got := config.Data, string(after); want != got {
t.Errorf("Want %q got %q", want, got)
}
}

View file

@ -0,0 +1,8 @@
kind: template
load: test.nested.starlark
data:
builds:
name: build
image: mcr.microsoft.com/dotnet/sdk:5.0
commands:
- dotnet build

View file

@ -0,0 +1,8 @@
def main(ctx):
return {
"kind": "pipeline",
"name": "default",
"steps": [
ctx.input.builds
]
}

View file

@ -0,0 +1 @@
{"kind": "pipeline", "name": "default", "steps": [{"name": "build", "image": "mcr.microsoft.com/dotnet/sdk:5.0", "commands": ["dotnet build"]}]}

View file

@ -64,13 +64,11 @@ func (c *redisCanceller) Cancelled(ctx context.Context, id int64) (isCancelled b
result, err := c.rdb.Get(ctx, redisCancelValuePrefix+ids).Result()
if err != nil && err != redis.Nil {
fmt.Println("GOT AN ERROR", err.Error()) //////////////////////////////////////////////////////
return
}
isCancelled = err != redis.Nil && result == redisCancelValue
if isCancelled {
fmt.Println("BUILD IS CANCELED", result) ////////////////////////////////////////////////
return
}
@ -109,11 +107,8 @@ func (c *redisCanceller) Cancelled(ctx context.Context, id int64) (isCancelled b
}
if id == idMessage {
fmt.Println("BUILD HAS JUST BEEN CANCELED", m.Payload) ////////////////////////////////////////////////
chResult <- true
} else { //////////////////////
fmt.Println("SOMETHING ELSE IS CANCELLED", m.Payload) ////////////////////////////////////////////////
} /////////////////////////////
}
case <-ctx.Done():
return