Monorepo for Tangled tangled.org
6

Configure Feed

Select the types of activity you want to include in your feed.

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