github.com/mavryk-network/mvgo@v1.19.9/internal/compose/alpha/run.go (about) 1 // Copyright (c) 2023 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc, abdul@blockwatch.cc 3 4 package alpha 5 6 import ( 7 "fmt" 8 "path/filepath" 9 10 "github.com/mavryk-network/mvgo/internal/compose" 11 ) 12 13 // 1 load yaml file 14 // 2 create accounts 15 // 3 process pipeline 16 17 func (e *Engine) Run(ctx compose.Context, fname string) error { 18 spec, err := compose.ParseFile[Spec](fname) 19 if err != nil { 20 return err 21 } 22 ctx.WithPath(filepath.Dir(fname)) 23 for _, a := range spec.Accounts { 24 if acc, err := ctx.MakeAccount(int(a.Id), a.Name); err != nil { 25 return err 26 } else { 27 ctx.Log.Infof("Account %s %s", a.Name, acc.Address) 28 } 29 } 30 for n, v := range spec.Variables { 31 ctx.AddVariable(n, v) 32 } 33 if err := spec.Validate(ctx); err != nil { 34 return err 35 } 36 37 // rewire loggers 38 defer ctx.RestoreLogger() 39 for _, p := range spec.Pipelines { 40 if err := ctx.Cache().Load(p.Hash64(), !ctx.ShouldResume()); err != nil { 41 return err 42 } 43 ctx.Log.Infof("Running pipeline %s", p.Name) 44 for i, task := range p.Tasks[ctx.Cache().Get():] { 45 ctx.SwitchLogger(fmt.Sprintf("%s[%d/%d]", p.Name, i+1, p.Len()), task.Log) 46 if task.Skip { 47 if err := ctx.Cache().Update(i); err != nil { 48 return err 49 } 50 continue 51 } 52 t, err := NewTask(task.Type) 53 if err != nil { 54 return fmt.Errorf("%s[%d] (%s): %v", p.Name, i, task.Type, err) 55 } 56 57 ctx.Log.Debugf("%s %s", task.Type, task.Destination) 58 59 // Build 60 op, opts, err := t.Build(ctx, task) 61 if err != nil { 62 if err == compose.ErrSkip { 63 if err := ctx.Cache().Update(i); err != nil { 64 return err 65 } 66 continue 67 } 68 return fmt.Errorf("%s[%d] (%s): %v", p.Name, i, task.Type, err) 69 } 70 71 // send 72 opts.Confirmations = 0 73 rcpt, err := ctx.Send(op, opts) 74 if err != nil { 75 switch task.OnError { 76 case ErrorModeFail: 77 return fmt.Errorf("%s[%d] (%s): %v", p.Name, i, task.Type, err) 78 case ErrorModeWarn: 79 ctx.Log.Warnf("%s[%d] (%s): %v", p.Name, i, task.Type, err) 80 } 81 } else { 82 // log receipt 83 ctx.Log.Infof("%s SUCCESS block=%d hash=%s", t.Type(), rcpt.Height, rcpt.Op.Hash) 84 } 85 86 // handle receipt 87 if task.Alias != "" { 88 addr, _ := rcpt.OriginatedContract() 89 ctx.AddVariable(task.Alias, addr.String()) 90 ctx.Log.Infof("NEW contract %s %s", task.Alias, addr) 91 } 92 93 // update pipeline cache 94 if err := ctx.Cache().Update(i); err != nil { 95 return err 96 } 97 } 98 ctx.RestoreLogger() 99 } 100 return nil 101 } 102 103 func (e *Engine) Validate(ctx compose.Context, fname string) error { 104 spec, err := compose.ParseFile[Spec](fname) 105 if err != nil { 106 return err 107 } 108 ctx.WithPath(filepath.Dir(fname)) 109 for _, a := range spec.Accounts { 110 if _, err := ctx.MakeAccount(int(a.Id), a.Name); err != nil { 111 return err 112 } 113 } 114 for n, v := range spec.Variables { 115 ctx.AddVariable(n, v) 116 } 117 if err := spec.Validate(ctx); err != nil { 118 return err 119 } 120 for _, p := range spec.Pipelines { 121 ctx.Log.Debugf("Validating pipeline %s", p.Name) 122 for i, task := range p.Tasks { 123 t, err := NewTask(task.Type) 124 if err != nil { 125 return fmt.Errorf("%s[%d] (%s): %v", p.Name, i, task.Type, err) 126 } 127 if err := t.Validate(ctx, task); err != nil { 128 return fmt.Errorf("%s[%d] (%s): %v", p.Name, i, task.Type, err) 129 } 130 if task.Type == "deploy" && task.Alias != "" { 131 script, err := ParseScript(ctx, task) 132 if err != nil { 133 return fmt.Errorf("parse script: %v", err) 134 } 135 acc, _ := ctx.MakeAccount(-2, task.Alias) 136 ctx.AddVariable(task.Alias, acc.Address.String()) 137 ctx.Contracts[acc.Address] = script 138 } 139 } 140 } 141 return nil 142 }