Monorepo for Tangled tangled.org
1

Configure Feed

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

core / spindle / xrpc / xrpc.go
2.8 kB 88 lines
1package xrpc 2 3import ( 4 "context" 5 _ "embed" 6 "encoding/json" 7 "errors" 8 "log/slog" 9 "net/http" 10 11 "github.com/bluesky-social/indigo/atproto/syntax" 12 "github.com/go-chi/chi/v5" 13 14 "tangled.org/core/api/tangled" 15 "tangled.org/core/idresolver" 16 "tangled.org/core/notifier" 17 "tangled.org/core/rbac" 18 "tangled.org/core/spindle/config" 19 "tangled.org/core/spindle/db" 20 "tangled.org/core/spindle/models" 21 "tangled.org/core/spindle/secrets" 22 xrpcerr "tangled.org/core/xrpc/errors" 23 "tangled.org/core/xrpc/serviceauth" 24) 25 26const ActorDid = serviceauth.ActorDid 27 28// ErrNoMatchingWorkflows is returned when a manual dispatch resolves to no 29// workflows to run: the repo defines none at the requested commit, or none of 30// the requested workflow names exist. 31var ErrNoMatchingWorkflows = errors.New("no workflows to run") 32 33// PipelineTrigger builds and enqueues a manually-dispatched pipeline. It is 34// implemented by *spindle.Spindle, which owns the queue and engines; the xrpc 35// handler only does auth and input validation before delegating here. 36type PipelineTrigger interface { 37 TriggerManual(ctx context.Context, repoDid syntax.DID, sha, ref string, workflows []string) (syntax.ATURI, error) 38} 39 40type Xrpc struct { 41 Logger *slog.Logger 42 Db *db.DB 43 Enforcer *rbac.Enforcer 44 Engines map[string]models.Engine 45 Config *config.Config 46 Resolver *idresolver.Resolver 47 Vault secrets.Manager 48 Notifier *notifier.Notifier 49 ServiceAuth *serviceauth.ServiceAuth 50 Trigger PipelineTrigger 51} 52 53func (x *Xrpc) Router() http.Handler { 54 r := chi.NewRouter() 55 56 r.Group(func(r chi.Router) { 57 r.Use(x.ServiceAuth.VerifyServiceAuth) 58 59 r.Post("/"+tangled.RepoAddSecretNSID, x.AddSecret) 60 r.Post("/"+tangled.RepoRemoveSecretNSID, x.RemoveSecret) 61 r.Get("/"+tangled.RepoListSecretsNSID, x.ListSecrets) 62 r.Post("/"+tangled.CiPipelineCancelPipelineNSID, x.CancelPipeline) 63 r.Post("/"+tangled.CiPipelineTriggerPipelineNSID, x.TriggerPipeline) 64 }) 65 66 // service query endpoints (no auth required) 67 r.Get("/"+tangled.OwnerNSID, x.Owner) 68 r.Get("/"+tangled.CiPipelineSubscribeLogsNSID, x.HandleCiPipelineSubscribeLogs) 69 r.Get("/"+tangled.CiQueryPipelinesNSID, x.HandleCiQueryPipelines) 70 r.Get("/"+tangled.CiGetPipelineNSID, x.HandleCiGetPipeline) 71 72 return r 73} 74 75// this is slightly different from http_util::write_error to follow the spec: 76// 77// the json object returned must include an "error" and a "message" 78func writeError(w http.ResponseWriter, e xrpcerr.XrpcError, status int) { 79 w.Header().Set("Content-Type", "application/json") 80 w.WriteHeader(status) 81 json.NewEncoder(w).Encode(e) 82} 83 84func writeJson(w http.ResponseWriter, status int, response any) error { 85 w.Header().Set("Content-Type", "application/json") 86 w.WriteHeader(status) 87 return json.NewEncoder(w).Encode(response) 88}