forked from tangled.org/core
this repo has no description
at master 3.1 kB view raw
1package workflow 2 3import ( 4 "errors" 5 "fmt" 6 7 "tangled.sh/tangled.sh/core/api/tangled" 8) 9 10type RawWorkflow struct { 11 Name string 12 Contents []byte 13} 14 15type RawPipeline = []RawWorkflow 16 17type Compiler struct { 18 Trigger tangled.Pipeline_TriggerMetadata 19 Diagnostics Diagnostics 20} 21 22type Diagnostics struct { 23 Errors []Error 24 Warnings []Warning 25} 26 27func (d *Diagnostics) IsEmpty() bool { 28 return len(d.Errors) == 0 && len(d.Warnings) == 0 29} 30 31func (d *Diagnostics) Combine(o Diagnostics) { 32 d.Errors = append(d.Errors, o.Errors...) 33 d.Warnings = append(d.Warnings, o.Warnings...) 34} 35 36func (d *Diagnostics) AddWarning(path string, kind WarningKind, reason string) { 37 d.Warnings = append(d.Warnings, Warning{path, kind, reason}) 38} 39 40func (d *Diagnostics) AddError(path string, err error) { 41 d.Errors = append(d.Errors, Error{path, err}) 42} 43 44func (d Diagnostics) IsErr() bool { 45 return len(d.Errors) != 0 46} 47 48type Error struct { 49 Path string 50 Error error 51} 52 53func (e Error) String() string { 54 return fmt.Sprintf("error: %s: %s", e.Path, e.Error.Error()) 55} 56 57type Warning struct { 58 Path string 59 Type WarningKind 60 Reason string 61} 62 63func (w Warning) String() string { 64 return fmt.Sprintf("warning: %s: %s: %s", w.Path, w.Type, w.Reason) 65} 66 67var ( 68 MissingEngine error = errors.New("missing engine") 69) 70 71type WarningKind string 72 73var ( 74 WorkflowSkipped WarningKind = "workflow skipped" 75 InvalidConfiguration WarningKind = "invalid configuration" 76) 77 78func (compiler *Compiler) Parse(p RawPipeline) Pipeline { 79 var pp Pipeline 80 81 for _, w := range p { 82 wf, err := FromFile(w.Name, w.Contents) 83 if err != nil { 84 compiler.Diagnostics.AddError(w.Name, err) 85 continue 86 } 87 88 pp = append(pp, wf) 89 } 90 91 return pp 92} 93 94// convert a repositories' workflow files into a fully compiled pipeline that runners accept 95func (compiler *Compiler) Compile(p Pipeline) tangled.Pipeline { 96 cp := tangled.Pipeline{ 97 TriggerMetadata: &compiler.Trigger, 98 } 99 100 for _, wf := range p { 101 cw := compiler.compileWorkflow(wf) 102 103 if cw == nil { 104 continue 105 } 106 107 cp.Workflows = append(cp.Workflows, cw) 108 } 109 110 return cp 111} 112 113func (compiler *Compiler) compileWorkflow(w Workflow) *tangled.Pipeline_Workflow { 114 cw := &tangled.Pipeline_Workflow{} 115 116 if !w.Match(compiler.Trigger) { 117 compiler.Diagnostics.AddWarning( 118 w.Name, 119 WorkflowSkipped, 120 fmt.Sprintf("did not match trigger %s", compiler.Trigger.Kind), 121 ) 122 return nil 123 } 124 125 // validate clone options 126 compiler.analyzeCloneOptions(w) 127 128 cw.Name = w.Name 129 130 if w.Engine == "" { 131 compiler.Diagnostics.AddError(w.Name, MissingEngine) 132 return nil 133 } 134 135 cw.Engine = w.Engine 136 cw.Raw = w.Raw 137 138 o := w.CloneOpts.AsRecord() 139 cw.Clone = &o 140 141 return cw 142} 143 144func (compiler *Compiler) analyzeCloneOptions(w Workflow) { 145 if w.CloneOpts.Skip && w.CloneOpts.IncludeSubmodules { 146 compiler.Diagnostics.AddWarning( 147 w.Name, 148 InvalidConfiguration, 149 "cannot apply `clone.skip` and `clone.submodules`", 150 ) 151 } 152 153 if w.CloneOpts.Skip && w.CloneOpts.Depth > 0 { 154 compiler.Diagnostics.AddWarning( 155 w.Name, 156 InvalidConfiguration, 157 "cannot apply `clone.skip` and `clone.depth`", 158 ) 159 } 160}