forked from tangled.org/core
Monorepo for Tangled

knotserver: trigger pipeline compilation upon push

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li 8a50fb39 beb7fce4

verified
Changed files
+89
knotserver
+89
knotserver/internal.go
··· 6 6 "log/slog" 7 7 "net/http" 8 8 "path/filepath" 9 + "strings" 9 10 11 + securejoin "github.com/cyphar/filepath-securejoin" 10 12 "github.com/go-chi/chi/v5" 11 13 "github.com/go-chi/chi/v5/middleware" 12 14 "tangled.sh/tangled.sh/core/api/tangled" ··· 15 17 "tangled.sh/tangled.sh/core/knotserver/git" 16 18 "tangled.sh/tangled.sh/core/knotserver/notifier" 17 19 "tangled.sh/tangled.sh/core/rbac" 20 + "tangled.sh/tangled.sh/core/workflow" 18 21 ) 19 22 20 23 type InternalHandle struct { ··· 92 95 l.Error("failed to insert op", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) 93 96 // non-fatal 94 97 } 98 + 99 + err = h.triggerPipeline(line, gitUserDid, repoDid, repoName) 100 + if err != nil { 101 + l.Error("failed to trigger pipeline", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) 102 + // non-fatal 103 + } 95 104 } 96 105 } 97 106 ··· 112 121 event := db.Event{ 113 122 Rkey: TID(), 114 123 Nsid: tangled.GitRefUpdateNSID, 124 + EventJson: string(eventJson), 125 + } 126 + 127 + return h.db.InsertEvent(event, h.n) 128 + } 129 + 130 + func (h *InternalHandle) triggerPipeline(line git.PostReceiveLine, gitUserDid, repoDid, repoName string) error { 131 + const ( 132 + WorkflowDir = ".tangled/workflows" 133 + ) 134 + 135 + didSlashRepo, err := securejoin.SecureJoin(repoDid, repoName) 136 + if err != nil { 137 + return err 138 + } 139 + 140 + repoPath, err := securejoin.SecureJoin(h.c.Repo.ScanPath, didSlashRepo) 141 + if err != nil { 142 + return err 143 + } 144 + 145 + gr, err := git.Open(repoPath, line.Ref) 146 + if err != nil { 147 + return err 148 + } 149 + 150 + workflowDir, err := gr.FileTree(context.Background(), WorkflowDir) 151 + if err != nil { 152 + return err 153 + } 154 + 155 + var pipeline workflow.Pipeline 156 + for _, e := range workflowDir { 157 + if !e.IsFile { 158 + continue 159 + } 160 + 161 + fpath := filepath.Join(WorkflowDir, e.Name) 162 + contents, err := gr.RawContent(fpath) 163 + if err != nil { 164 + continue 165 + } 166 + 167 + wf, err := workflow.FromFile(e.Name, contents) 168 + if err != nil { 169 + // TODO: log here, respond to client that is pushing 170 + continue 171 + } 172 + 173 + pipeline = append(pipeline, wf) 174 + } 175 + 176 + trigger := tangled.Pipeline_PushTriggerData{ 177 + Ref: line.Ref, 178 + OldSha: line.OldSha, 179 + NewSha: line.NewSha, 180 + } 181 + 182 + compiler := workflow.Compiler{ 183 + Trigger: tangled.Pipeline_TriggerMetadata{ 184 + Kind: string(workflow.TriggerKindPush), 185 + Push: &trigger, 186 + Repo: &tangled.Pipeline_TriggerRepo{ 187 + Did: repoDid, 188 + Knot: h.c.Server.Hostname, 189 + Repo: repoName, 190 + }, 191 + }, 192 + } 193 + 194 + // TODO: send the diagnostics back to the user here via stderr 195 + cp := compiler.Compile(pipeline) 196 + eventJson, err := json.Marshal(cp) 197 + if err != nil { 198 + return err 199 + } 200 + 201 + event := db.Event{ 202 + Rkey: TID(), 203 + Nsid: tangled.PipelineNSID, 115 204 EventJson: string(eventJson), 116 205 } 117 206