Mirror of @tangled.org/core. Running on a Raspberry Pi Zero 2 (Please be gentle).
0
fork

Configure Feed

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

knotserver,hook: print messages to the git client, implement verbose-ci push option

Signed-off-by: dusk <y.bera003.06@protonmail.com>

authored by

dusk and committed by
Tangled
c21b68ec 9b88f855

+59 -5
+14
hook/hook.go
··· 3 3 import ( 4 4 "bufio" 5 5 "context" 6 + "encoding/json" 6 7 "fmt" 7 8 "net/http" 8 9 "os" ··· 11 10 12 11 "github.com/urfave/cli/v3" 13 12 ) 13 + 14 + type HookResponse struct { 15 + Messages []string `json:"messages"` 16 + } 14 17 15 18 // The hook command is nested like so: 16 19 // ··· 91 86 92 87 if resp.StatusCode != http.StatusOK { 93 88 return fmt.Errorf("unexpected status code: %d", resp.StatusCode) 89 + } 90 + 91 + var data HookResponse 92 + if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { 93 + return fmt.Errorf("failed to decode response: %w", err) 94 + } 95 + 96 + for _, message := range data.Messages { 97 + fmt.Println(message) 94 98 } 95 99 96 100 return nil
+45 -5
knotserver/internal.go
··· 13 13 "github.com/go-chi/chi/v5" 14 14 "github.com/go-chi/chi/v5/middleware" 15 15 "tangled.sh/tangled.sh/core/api/tangled" 16 + "tangled.sh/tangled.sh/core/hook" 16 17 "tangled.sh/tangled.sh/core/knotserver/config" 17 18 "tangled.sh/tangled.sh/core/knotserver/db" 18 19 "tangled.sh/tangled.sh/core/knotserver/git" ··· 66 65 } 67 66 68 67 type PushOptions struct { 69 - skipCi bool 68 + skipCi bool 69 + verboseCi bool 70 70 } 71 71 72 72 func (h *InternalHandle) PostReceiveHook(w http.ResponseWriter, r *http.Request) { ··· 103 101 if option == "skip-ci" || option == "ci-skip" { 104 102 pushOptions.skipCi = true 105 103 } 104 + if option == "verbose-ci" || option == "ci-verbose" { 105 + pushOptions.verboseCi = true 106 + } 107 + } 108 + 109 + resp := hook.HookResponse{ 110 + Messages: make([]string, 0), 106 111 } 107 112 108 113 for _, line := range lines { ··· 119 110 // non-fatal 120 111 } 121 112 122 - err = h.triggerPipeline(line, gitUserDid, repoDid, repoName, pushOptions) 113 + err = h.triggerPipeline(&resp.Messages, line, gitUserDid, repoDid, repoName, pushOptions) 123 114 if err != nil { 124 115 l.Error("failed to trigger pipeline", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) 125 116 // non-fatal 126 117 } 127 118 } 119 + 120 + writeJSON(w, resp) 128 121 } 129 122 130 123 func (h *InternalHandle) insertRefUpdate(line git.PostReceiveLine, gitUserDid, repoDid, repoName string) error { ··· 172 161 return h.db.InsertEvent(event, h.n) 173 162 } 174 163 175 - func (h *InternalHandle) triggerPipeline(line git.PostReceiveLine, gitUserDid, repoDid, repoName string, pushOptions PushOptions) error { 164 + func (h *InternalHandle) triggerPipeline(clientMsgs *[]string, line git.PostReceiveLine, gitUserDid, repoDid, repoName string, pushOptions PushOptions) error { 176 165 if pushOptions.skipCi { 177 166 return nil 178 167 } ··· 197 186 return err 198 187 } 199 188 189 + pipelineParseErrors := []string{} 190 + 200 191 var pipeline workflow.Pipeline 201 192 for _, e := range workflowDir { 202 193 if !e.IsFile { ··· 213 200 214 201 wf, err := workflow.FromFile(e.Name, contents) 215 202 if err != nil { 216 - // TODO: log here, respond to client that is pushing 217 203 h.l.Error("failed to parse workflow", "err", err, "path", fpath) 204 + pipelineParseErrors = append(pipelineParseErrors, fmt.Sprintf("- at %s: %s\n", fpath, err)) 218 205 continue 219 206 } 220 207 ··· 239 226 }, 240 227 } 241 228 242 - // TODO: send the diagnostics back to the user here via stderr 243 229 cp := compiler.Compile(pipeline) 244 230 eventJson, err := json.Marshal(cp) 245 231 if err != nil { 246 232 return err 233 + } 234 + 235 + if pushOptions.verboseCi { 236 + hasDiagnostics := false 237 + if len(pipelineParseErrors) > 0 { 238 + hasDiagnostics = true 239 + *clientMsgs = append(*clientMsgs, "error: failed to parse workflow(s):") 240 + for _, error := range pipelineParseErrors { 241 + *clientMsgs = append(*clientMsgs, error) 242 + } 243 + } 244 + if len(compiler.Diagnostics.Errors) > 0 { 245 + hasDiagnostics = true 246 + *clientMsgs = append(*clientMsgs, "error(s) on pipeline:") 247 + for _, error := range compiler.Diagnostics.Errors { 248 + *clientMsgs = append(*clientMsgs, fmt.Sprintf("- %s:", error)) 249 + } 250 + } 251 + if len(compiler.Diagnostics.Warnings) > 0 { 252 + hasDiagnostics = true 253 + *clientMsgs = append(*clientMsgs, "warning(s) on pipeline:") 254 + for _, warning := range compiler.Diagnostics.Warnings { 255 + *clientMsgs = append(*clientMsgs, fmt.Sprintf("- at %s: %s: %s", warning.Path, warning.Type, warning.Reason)) 256 + } 257 + } 258 + if !hasDiagnostics { 259 + *clientMsgs = append(*clientMsgs, "success: pipeline compiled with no diagnostics") 260 + } 247 261 } 248 262 249 263 // do not run empty pipelines