This repository has no description
0

Configure Feed

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

core / spindle / xrpc / xrpc.go
3.1 kB 101 lines
1package xrpc 2 3import ( 4 "context" 5 _ "embed" 6 "encoding/json" 7 "errors" 8 "fmt" 9 "log/slog" 10 "net/http" 11 12 "github.com/bluesky-social/indigo/atproto/syntax" 13 "github.com/go-chi/chi/v5" 14 15 "tangled.org/core/api/tangled" 16 "tangled.org/core/idresolver" 17 "tangled.org/core/notifier" 18 "tangled.org/core/rbac" 19 "tangled.org/core/spindle/config" 20 "tangled.org/core/spindle/db" 21 "tangled.org/core/spindle/models" 22 "tangled.org/core/spindle/secrets" 23 xrpcerr "tangled.org/core/xrpc/errors" 24 "tangled.org/core/xrpc/serviceauth" 25) 26 27const ActorDid = serviceauth.ActorDid 28 29var ErrNoMatchingWorkflows = errors.New("no workflows to run") 30 31func requireSha(sha string) error { 32 if len(sha) != 40 { 33 return fmt.Errorf("sha must be a 40-character commit hash") 34 } 35 return nil 36} 37 38// this is to break an import cycle. spindle imports this package for Xrpc, 39// so this package can't import *spindle.Spindle back. 40type PipelineTrigger interface { 41 TriggerManual(ctx context.Context, repoDid syntax.DID, sha, ref string, workflows []string, sourceRepo syntax.DID, pull PullContext, inputs []*tangled.Pipeline_Pair) (syntax.ATURI, error) 42 DescribeWorkflowDefinition(ctx context.Context, repoDid syntax.DID, sha string, sourceRepo syntax.DID) (*tangled.CiDescribeWorkflowDefinition_Output, error) 43} 44 45type PullContext struct { 46 IsPullRequest bool 47 Pull syntax.ATURI 48 SourceBranch string 49 TargetBranch string 50} 51 52type Xrpc struct { 53 Logger *slog.Logger 54 Db *db.DB 55 Enforcer *rbac.Enforcer 56 Engines map[string]models.Engine 57 Config *config.Config 58 Resolver *idresolver.Resolver 59 Vault secrets.Manager 60 Notifier *notifier.Notifier 61 ServiceAuth *serviceauth.ServiceAuth 62 Trigger PipelineTrigger 63} 64 65func (x *Xrpc) Router() http.Handler { 66 r := chi.NewRouter() 67 68 r.Group(func(r chi.Router) { 69 r.Use(x.ServiceAuth.VerifyServiceAuth) 70 71 r.Post("/"+tangled.RepoAddSecretNSID, x.AddSecret) 72 r.Post("/"+tangled.RepoRemoveSecretNSID, x.RemoveSecret) 73 r.Get("/"+tangled.RepoListSecretsNSID, x.ListSecrets) 74 r.Post("/"+tangled.CiCancelPipelineNSID, x.CancelPipeline) 75 r.Post("/"+tangled.CiTriggerPipelineNSID, x.TriggerPipeline) 76 }) 77 78 // service query endpoints (no auth required) 79 r.Get("/"+tangled.OwnerNSID, x.Owner) 80 r.Get("/"+tangled.CiDescribeWorkflowDefinitionNSID, x.DescribeWorkflowDefinition) 81 r.Get("/"+tangled.CiSubscribePipelineLogsNSID, x.HandleCiSubscribePipelineLogs) 82 r.Get("/"+tangled.CiQueryPipelinesNSID, x.HandleCiQueryPipelines) 83 r.Get("/"+tangled.CiGetPipelineNSID, x.HandleCiGetPipeline) 84 85 return r 86} 87 88// this is slightly different from http_util::write_error to follow the spec: 89// 90// the json object returned must include an "error" and a "message" 91func writeError(w http.ResponseWriter, e xrpcerr.XrpcError, status int) { 92 w.Header().Set("Content-Type", "application/json") 93 w.WriteHeader(status) 94 json.NewEncoder(w).Encode(e) 95} 96 97func writeJson(w http.ResponseWriter, status int, response any) error { 98 w.Header().Set("Content-Type", "application/json") 99 w.WriteHeader(status) 100 return json.NewEncoder(w).Encode(response) 101}