From 3b2791997ff18e93eaa2e2a82c60690a63fd3f28 Mon Sep 17 00:00:00 2001 From: Cyril Tovena Date: Thu, 25 Jan 2024 18:07:22 +0100 Subject: [PATCH 01/31] Experimental: Adds a Github Integration to fetch profiled code --- api/gen/proto/go/vcs/v1/vcs.pb.go | 499 ++++++ api/gen/proto/go/vcs/v1/vcs_vtproto.pb.go | 1380 +++++++++++++++++ .../go/vcs/v1/vcsv1connect/vcs.connect.go | 170 ++ .../go/vcs/v1/vcsv1connect/vcs.connect.mux.go | 37 + api/openapiv2/gen/phlare.swagger.json | 27 + api/vcs/v1/vcs.proto | 37 + ebpf/go.mod | 3 +- ebpf/go.sum | 4 - go.mod | 9 +- go.sum | 16 + pkg/api/api.go | 13 +- pkg/api/vcs.html | 132 ++ pkg/frontend/frontend_vcs.go | 22 + pkg/pprof/pprof_test.go | 1 - pkg/querier/cookie.go | 101 ++ pkg/querier/cookie_test.go | 24 + pkg/querier/golang/gen.go | 58 + pkg/querier/golang/packages.go | 47 + pkg/querier/golang/packages_gen.go | 267 ++++ pkg/querier/grpc_handler.go | 16 +- pkg/querier/vcs.go | 664 ++++++++ pkg/querier/vcs_test.go | 587 +++++++ pkg/util/connectgrpc/connectgrpc.go | 6 +- 23 files changed, 4107 insertions(+), 13 deletions(-) create mode 100644 api/gen/proto/go/vcs/v1/vcs.pb.go create mode 100644 api/gen/proto/go/vcs/v1/vcs_vtproto.pb.go create mode 100644 api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.go create mode 100644 api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.mux.go create mode 100644 api/vcs/v1/vcs.proto create mode 100644 pkg/api/vcs.html create mode 100644 pkg/frontend/frontend_vcs.go create mode 100644 pkg/querier/cookie.go create mode 100644 pkg/querier/cookie_test.go create mode 100644 pkg/querier/golang/gen.go create mode 100644 pkg/querier/golang/packages.go create mode 100644 pkg/querier/golang/packages_gen.go create mode 100644 pkg/querier/vcs.go create mode 100644 pkg/querier/vcs_test.go diff --git a/api/gen/proto/go/vcs/v1/vcs.pb.go b/api/gen/proto/go/vcs/v1/vcs.pb.go new file mode 100644 index 0000000000..005cce91ad --- /dev/null +++ b/api/gen/proto/go/vcs/v1/vcs.pb.go @@ -0,0 +1,499 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.32.0 +// protoc (unknown) +// source: vcs/v1/vcs.proto + +package vcsv1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type GithubAppRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GithubAppRequest) Reset() { + *x = GithubAppRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vcs_v1_vcs_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GithubAppRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GithubAppRequest) ProtoMessage() {} + +func (x *GithubAppRequest) ProtoReflect() protoreflect.Message { + mi := &file_vcs_v1_vcs_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GithubAppRequest.ProtoReflect.Descriptor instead. +func (*GithubAppRequest) Descriptor() ([]byte, []int) { + return file_vcs_v1_vcs_proto_rawDescGZIP(), []int{0} +} + +type GithubAppResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClientID string `protobuf:"bytes,1,opt,name=clientID,proto3" json:"clientID,omitempty"` +} + +func (x *GithubAppResponse) Reset() { + *x = GithubAppResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_vcs_v1_vcs_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GithubAppResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GithubAppResponse) ProtoMessage() {} + +func (x *GithubAppResponse) ProtoReflect() protoreflect.Message { + mi := &file_vcs_v1_vcs_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GithubAppResponse.ProtoReflect.Descriptor instead. +func (*GithubAppResponse) Descriptor() ([]byte, []int) { + return file_vcs_v1_vcs_proto_rawDescGZIP(), []int{1} +} + +func (x *GithubAppResponse) GetClientID() string { + if x != nil { + return x.ClientID + } + return "" +} + +type GithubLoginRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AuthorizationCode string `protobuf:"bytes,1,opt,name=authorizationCode,proto3" json:"authorizationCode,omitempty"` +} + +func (x *GithubLoginRequest) Reset() { + *x = GithubLoginRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vcs_v1_vcs_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GithubLoginRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GithubLoginRequest) ProtoMessage() {} + +func (x *GithubLoginRequest) ProtoReflect() protoreflect.Message { + mi := &file_vcs_v1_vcs_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GithubLoginRequest.ProtoReflect.Descriptor instead. +func (*GithubLoginRequest) Descriptor() ([]byte, []int) { + return file_vcs_v1_vcs_proto_rawDescGZIP(), []int{2} +} + +func (x *GithubLoginRequest) GetAuthorizationCode() string { + if x != nil { + return x.AuthorizationCode + } + return "" +} + +type GithubLoginResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GithubLoginResponse) Reset() { + *x = GithubLoginResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_vcs_v1_vcs_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GithubLoginResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GithubLoginResponse) ProtoMessage() {} + +func (x *GithubLoginResponse) ProtoReflect() protoreflect.Message { + mi := &file_vcs_v1_vcs_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GithubLoginResponse.ProtoReflect.Descriptor instead. +func (*GithubLoginResponse) Descriptor() ([]byte, []int) { + return file_vcs_v1_vcs_proto_rawDescGZIP(), []int{3} +} + +type GetFileRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // the full path to the repository + RepositoryURL string `protobuf:"bytes,1,opt,name=repositoryURL,proto3" json:"repositoryURL,omitempty"` + // the vcs ref to get the file from + Ref string `protobuf:"bytes,2,opt,name=ref,proto3" json:"ref,omitempty"` + // the path to the file as provided by the symbols + LocalPath string `protobuf:"bytes,3,opt,name=localPath,proto3" json:"localPath,omitempty"` +} + +func (x *GetFileRequest) Reset() { + *x = GetFileRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_vcs_v1_vcs_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFileRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileRequest) ProtoMessage() {} + +func (x *GetFileRequest) ProtoReflect() protoreflect.Message { + mi := &file_vcs_v1_vcs_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileRequest.ProtoReflect.Descriptor instead. +func (*GetFileRequest) Descriptor() ([]byte, []int) { + return file_vcs_v1_vcs_proto_rawDescGZIP(), []int{4} +} + +func (x *GetFileRequest) GetRepositoryURL() string { + if x != nil { + return x.RepositoryURL + } + return "" +} + +func (x *GetFileRequest) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +func (x *GetFileRequest) GetLocalPath() string { + if x != nil { + return x.LocalPath + } + return "" +} + +type GetFileResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // base64 content of the file + Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` + // the full URL to the file + URL string `protobuf:"bytes,2,opt,name=URL,proto3" json:"URL,omitempty"` +} + +func (x *GetFileResponse) Reset() { + *x = GetFileResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_vcs_v1_vcs_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFileResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFileResponse) ProtoMessage() {} + +func (x *GetFileResponse) ProtoReflect() protoreflect.Message { + mi := &file_vcs_v1_vcs_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFileResponse.ProtoReflect.Descriptor instead. +func (*GetFileResponse) Descriptor() ([]byte, []int) { + return file_vcs_v1_vcs_proto_rawDescGZIP(), []int{5} +} + +func (x *GetFileResponse) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +func (x *GetFileResponse) GetURL() string { + if x != nil { + return x.URL + } + return "" +} + +var File_vcs_v1_vcs_proto protoreflect.FileDescriptor + +var file_vcs_v1_vcs_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x76, 0x63, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x76, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x06, 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2f, + 0x0a, 0x11, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x44, 0x22, + 0x42, 0x0a, 0x12, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x11, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6f, 0x64, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x66, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x0d, + 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x55, 0x52, 0x4c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x55, + 0x52, 0x4c, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x72, 0x65, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, + 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x61, + 0x74, 0x68, 0x22, 0x3d, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x10, 0x0a, 0x03, 0x55, 0x52, 0x4c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x55, 0x52, + 0x4c, 0x32, 0xd8, 0x01, 0x0a, 0x0a, 0x56, 0x43, 0x53, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x42, 0x0a, 0x09, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x12, 0x18, 0x2e, + 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x70, 0x70, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x0b, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x12, 0x1a, 0x2e, 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1b, 0x2e, 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x69, 0x74, 0x68, 0x75, 0x62, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3c, + 0x0a, 0x07, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x76, 0x63, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x69, + 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x8b, 0x01, 0x0a, + 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x63, 0x73, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x56, 0x63, 0x73, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x66, 0x61, 0x6e, 0x61, 0x2f, 0x70, 0x79, 0x72, 0x6f, + 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x63, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x63, + 0x73, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x56, 0x58, 0x58, 0xaa, 0x02, 0x06, 0x56, 0x63, 0x73, 0x2e, + 0x56, 0x31, 0xca, 0x02, 0x06, 0x56, 0x63, 0x73, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x12, 0x56, 0x63, + 0x73, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x07, 0x56, 0x63, 0x73, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_vcs_v1_vcs_proto_rawDescOnce sync.Once + file_vcs_v1_vcs_proto_rawDescData = file_vcs_v1_vcs_proto_rawDesc +) + +func file_vcs_v1_vcs_proto_rawDescGZIP() []byte { + file_vcs_v1_vcs_proto_rawDescOnce.Do(func() { + file_vcs_v1_vcs_proto_rawDescData = protoimpl.X.CompressGZIP(file_vcs_v1_vcs_proto_rawDescData) + }) + return file_vcs_v1_vcs_proto_rawDescData +} + +var file_vcs_v1_vcs_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_vcs_v1_vcs_proto_goTypes = []interface{}{ + (*GithubAppRequest)(nil), // 0: vcs.v1.GithubAppRequest + (*GithubAppResponse)(nil), // 1: vcs.v1.GithubAppResponse + (*GithubLoginRequest)(nil), // 2: vcs.v1.GithubLoginRequest + (*GithubLoginResponse)(nil), // 3: vcs.v1.GithubLoginResponse + (*GetFileRequest)(nil), // 4: vcs.v1.GetFileRequest + (*GetFileResponse)(nil), // 5: vcs.v1.GetFileResponse +} +var file_vcs_v1_vcs_proto_depIdxs = []int32{ + 0, // 0: vcs.v1.VCSService.GithubApp:input_type -> vcs.v1.GithubAppRequest + 2, // 1: vcs.v1.VCSService.GithubLogin:input_type -> vcs.v1.GithubLoginRequest + 4, // 2: vcs.v1.VCSService.GetFile:input_type -> vcs.v1.GetFileRequest + 1, // 3: vcs.v1.VCSService.GithubApp:output_type -> vcs.v1.GithubAppResponse + 3, // 4: vcs.v1.VCSService.GithubLogin:output_type -> vcs.v1.GithubLoginResponse + 5, // 5: vcs.v1.VCSService.GetFile:output_type -> vcs.v1.GetFileResponse + 3, // [3:6] is the sub-list for method output_type + 0, // [0:3] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_vcs_v1_vcs_proto_init() } +func file_vcs_v1_vcs_proto_init() { + if File_vcs_v1_vcs_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_vcs_v1_vcs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GithubAppRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vcs_v1_vcs_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GithubAppResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vcs_v1_vcs_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GithubLoginRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vcs_v1_vcs_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GithubLoginResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vcs_v1_vcs_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFileRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_vcs_v1_vcs_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetFileResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_vcs_v1_vcs_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_vcs_v1_vcs_proto_goTypes, + DependencyIndexes: file_vcs_v1_vcs_proto_depIdxs, + MessageInfos: file_vcs_v1_vcs_proto_msgTypes, + }.Build() + File_vcs_v1_vcs_proto = out.File + file_vcs_v1_vcs_proto_rawDesc = nil + file_vcs_v1_vcs_proto_goTypes = nil + file_vcs_v1_vcs_proto_depIdxs = nil +} diff --git a/api/gen/proto/go/vcs/v1/vcs_vtproto.pb.go b/api/gen/proto/go/vcs/v1/vcs_vtproto.pb.go new file mode 100644 index 0000000000..c01808e89e --- /dev/null +++ b/api/gen/proto/go/vcs/v1/vcs_vtproto.pb.go @@ -0,0 +1,1380 @@ +// Code generated by protoc-gen-go-vtproto. DO NOT EDIT. +// protoc-gen-go-vtproto version: v0.0.0-20230725111439-5b3aae6571b8 +// source: vcs/v1/vcs.proto + +package vcsv1 + +import ( + context "context" + fmt "fmt" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + proto "google.golang.org/protobuf/proto" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + io "io" + bits "math/bits" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +func (m *GithubAppRequest) CloneVT() *GithubAppRequest { + if m == nil { + return (*GithubAppRequest)(nil) + } + r := &GithubAppRequest{} + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GithubAppRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GithubAppResponse) CloneVT() *GithubAppResponse { + if m == nil { + return (*GithubAppResponse)(nil) + } + r := &GithubAppResponse{ + ClientID: m.ClientID, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GithubAppResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GithubLoginRequest) CloneVT() *GithubLoginRequest { + if m == nil { + return (*GithubLoginRequest)(nil) + } + r := &GithubLoginRequest{ + AuthorizationCode: m.AuthorizationCode, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GithubLoginRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GithubLoginResponse) CloneVT() *GithubLoginResponse { + if m == nil { + return (*GithubLoginResponse)(nil) + } + r := &GithubLoginResponse{} + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GithubLoginResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GetFileRequest) CloneVT() *GetFileRequest { + if m == nil { + return (*GetFileRequest)(nil) + } + r := &GetFileRequest{ + RepositoryURL: m.RepositoryURL, + Ref: m.Ref, + LocalPath: m.LocalPath, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetFileRequest) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *GetFileResponse) CloneVT() *GetFileResponse { + if m == nil { + return (*GetFileResponse)(nil) + } + r := &GetFileResponse{ + Content: m.Content, + URL: m.URL, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *GetFileResponse) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (this *GithubAppRequest) EqualVT(that *GithubAppRequest) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *GithubAppRequest) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*GithubAppRequest) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *GithubAppResponse) EqualVT(that *GithubAppResponse) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.ClientID != that.ClientID { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *GithubAppResponse) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*GithubAppResponse) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *GithubLoginRequest) EqualVT(that *GithubLoginRequest) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.AuthorizationCode != that.AuthorizationCode { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *GithubLoginRequest) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*GithubLoginRequest) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *GithubLoginResponse) EqualVT(that *GithubLoginResponse) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *GithubLoginResponse) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*GithubLoginResponse) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *GetFileRequest) EqualVT(that *GetFileRequest) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.RepositoryURL != that.RepositoryURL { + return false + } + if this.Ref != that.Ref { + return false + } + if this.LocalPath != that.LocalPath { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *GetFileRequest) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*GetFileRequest) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *GetFileResponse) EqualVT(that *GetFileResponse) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Content != that.Content { + return false + } + if this.URL != that.URL { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *GetFileResponse) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*GetFileResponse) + if !ok { + return false + } + return this.EqualVT(that) +} + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.32.0 or later. +const _ = grpc.SupportPackageIsVersion7 + +// VCSServiceClient is the client API for VCSService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type VCSServiceClient interface { + GithubApp(ctx context.Context, in *GithubAppRequest, opts ...grpc.CallOption) (*GithubAppResponse, error) + GithubLogin(ctx context.Context, in *GithubLoginRequest, opts ...grpc.CallOption) (*GithubLoginResponse, error) + GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (*GetFileResponse, error) +} + +type vCSServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewVCSServiceClient(cc grpc.ClientConnInterface) VCSServiceClient { + return &vCSServiceClient{cc} +} + +func (c *vCSServiceClient) GithubApp(ctx context.Context, in *GithubAppRequest, opts ...grpc.CallOption) (*GithubAppResponse, error) { + out := new(GithubAppResponse) + err := c.cc.Invoke(ctx, "/vcs.v1.VCSService/GithubApp", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *vCSServiceClient) GithubLogin(ctx context.Context, in *GithubLoginRequest, opts ...grpc.CallOption) (*GithubLoginResponse, error) { + out := new(GithubLoginResponse) + err := c.cc.Invoke(ctx, "/vcs.v1.VCSService/GithubLogin", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *vCSServiceClient) GetFile(ctx context.Context, in *GetFileRequest, opts ...grpc.CallOption) (*GetFileResponse, error) { + out := new(GetFileResponse) + err := c.cc.Invoke(ctx, "/vcs.v1.VCSService/GetFile", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// VCSServiceServer is the server API for VCSService service. +// All implementations must embed UnimplementedVCSServiceServer +// for forward compatibility +type VCSServiceServer interface { + GithubApp(context.Context, *GithubAppRequest) (*GithubAppResponse, error) + GithubLogin(context.Context, *GithubLoginRequest) (*GithubLoginResponse, error) + GetFile(context.Context, *GetFileRequest) (*GetFileResponse, error) + mustEmbedUnimplementedVCSServiceServer() +} + +// UnimplementedVCSServiceServer must be embedded to have forward compatible implementations. +type UnimplementedVCSServiceServer struct { +} + +func (UnimplementedVCSServiceServer) GithubApp(context.Context, *GithubAppRequest) (*GithubAppResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GithubApp not implemented") +} +func (UnimplementedVCSServiceServer) GithubLogin(context.Context, *GithubLoginRequest) (*GithubLoginResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GithubLogin not implemented") +} +func (UnimplementedVCSServiceServer) GetFile(context.Context, *GetFileRequest) (*GetFileResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetFile not implemented") +} +func (UnimplementedVCSServiceServer) mustEmbedUnimplementedVCSServiceServer() {} + +// UnsafeVCSServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to VCSServiceServer will +// result in compilation errors. +type UnsafeVCSServiceServer interface { + mustEmbedUnimplementedVCSServiceServer() +} + +func RegisterVCSServiceServer(s grpc.ServiceRegistrar, srv VCSServiceServer) { + s.RegisterService(&VCSService_ServiceDesc, srv) +} + +func _VCSService_GithubApp_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GithubAppRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VCSServiceServer).GithubApp(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vcs.v1.VCSService/GithubApp", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VCSServiceServer).GithubApp(ctx, req.(*GithubAppRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _VCSService_GithubLogin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GithubLoginRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VCSServiceServer).GithubLogin(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vcs.v1.VCSService/GithubLogin", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VCSServiceServer).GithubLogin(ctx, req.(*GithubLoginRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _VCSService_GetFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetFileRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(VCSServiceServer).GetFile(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/vcs.v1.VCSService/GetFile", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(VCSServiceServer).GetFile(ctx, req.(*GetFileRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// VCSService_ServiceDesc is the grpc.ServiceDesc for VCSService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var VCSService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "vcs.v1.VCSService", + HandlerType: (*VCSServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GithubApp", + Handler: _VCSService_GithubApp_Handler, + }, + { + MethodName: "GithubLogin", + Handler: _VCSService_GithubLogin_Handler, + }, + { + MethodName: "GetFile", + Handler: _VCSService_GetFile_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "vcs/v1/vcs.proto", +} + +func (m *GithubAppRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GithubAppRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GithubAppRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + return len(dAtA) - i, nil +} + +func (m *GithubAppResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GithubAppResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GithubAppResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.ClientID) > 0 { + i -= len(m.ClientID) + copy(dAtA[i:], m.ClientID) + i = encodeVarint(dAtA, i, uint64(len(m.ClientID))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GithubLoginRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GithubLoginRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GithubLoginRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.AuthorizationCode) > 0 { + i -= len(m.AuthorizationCode) + copy(dAtA[i:], m.AuthorizationCode) + i = encodeVarint(dAtA, i, uint64(len(m.AuthorizationCode))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GithubLoginResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GithubLoginResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GithubLoginResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + return len(dAtA) - i, nil +} + +func (m *GetFileRequest) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetFileRequest) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetFileRequest) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.LocalPath) > 0 { + i -= len(m.LocalPath) + copy(dAtA[i:], m.LocalPath) + i = encodeVarint(dAtA, i, uint64(len(m.LocalPath))) + i-- + dAtA[i] = 0x1a + } + if len(m.Ref) > 0 { + i -= len(m.Ref) + copy(dAtA[i:], m.Ref) + i = encodeVarint(dAtA, i, uint64(len(m.Ref))) + i-- + dAtA[i] = 0x12 + } + if len(m.RepositoryURL) > 0 { + i -= len(m.RepositoryURL) + copy(dAtA[i:], m.RepositoryURL) + i = encodeVarint(dAtA, i, uint64(len(m.RepositoryURL))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *GetFileResponse) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GetFileResponse) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *GetFileResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.URL) > 0 { + i -= len(m.URL) + copy(dAtA[i:], m.URL) + i = encodeVarint(dAtA, i, uint64(len(m.URL))) + i-- + dAtA[i] = 0x12 + } + if len(m.Content) > 0 { + i -= len(m.Content) + copy(dAtA[i:], m.Content) + i = encodeVarint(dAtA, i, uint64(len(m.Content))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarint(dAtA []byte, offset int, v uint64) int { + offset -= sov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GithubAppRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *GithubAppResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ClientID) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *GithubLoginRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.AuthorizationCode) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *GithubLoginResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + n += len(m.unknownFields) + return n +} + +func (m *GetFileRequest) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.RepositoryURL) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Ref) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.LocalPath) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *GetFileResponse) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Content) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.URL) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func sov(x uint64) (n int) { + return (bits.Len64(x|1) + 6) / 7 +} +func soz(x uint64) (n int) { + return sov(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GithubAppRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GithubAppRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GithubAppRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GithubAppResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GithubAppResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GithubAppResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ClientID", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ClientID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GithubLoginRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GithubLoginRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GithubLoginRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AuthorizationCode", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AuthorizationCode = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GithubLoginResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GithubLoginResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GithubLoginResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetFileRequest) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetFileRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetFileRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RepositoryURL", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RepositoryURL = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ref = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LocalPath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LocalPath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *GetFileResponse) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GetFileResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GetFileResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Content", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Content = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field URL", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.URL = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} + +func skip(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflow + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflow + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflow + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLength + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroup + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLength + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLength = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflow = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroup = fmt.Errorf("proto: unexpected end of group") +) diff --git a/api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.go b/api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.go new file mode 100644 index 0000000000..ed3cb9c698 --- /dev/null +++ b/api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.go @@ -0,0 +1,170 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: vcs/v1/vcs.proto + +package vcsv1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/grafana/pyroscope/api/gen/proto/go/vcs/v1" + http "net/http" + strings "strings" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion1_13_0 + +const ( + // VCSServiceName is the fully-qualified name of the VCSService service. + VCSServiceName = "vcs.v1.VCSService" +) + +// These constants are the fully-qualified names of the RPCs defined in this package. They're +// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route. +// +// Note that these are different from the fully-qualified method names used by +// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to +// reflection-formatted method names, remove the leading slash and convert the remaining slash to a +// period. +const ( + // VCSServiceGithubAppProcedure is the fully-qualified name of the VCSService's GithubApp RPC. + VCSServiceGithubAppProcedure = "/vcs.v1.VCSService/GithubApp" + // VCSServiceGithubLoginProcedure is the fully-qualified name of the VCSService's GithubLogin RPC. + VCSServiceGithubLoginProcedure = "/vcs.v1.VCSService/GithubLogin" + // VCSServiceGetFileProcedure is the fully-qualified name of the VCSService's GetFile RPC. + VCSServiceGetFileProcedure = "/vcs.v1.VCSService/GetFile" +) + +// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. +var ( + vCSServiceServiceDescriptor = v1.File_vcs_v1_vcs_proto.Services().ByName("VCSService") + vCSServiceGithubAppMethodDescriptor = vCSServiceServiceDescriptor.Methods().ByName("GithubApp") + vCSServiceGithubLoginMethodDescriptor = vCSServiceServiceDescriptor.Methods().ByName("GithubLogin") + vCSServiceGetFileMethodDescriptor = vCSServiceServiceDescriptor.Methods().ByName("GetFile") +) + +// VCSServiceClient is a client for the vcs.v1.VCSService service. +type VCSServiceClient interface { + GithubApp(context.Context, *connect.Request[v1.GithubAppRequest]) (*connect.Response[v1.GithubAppResponse], error) + GithubLogin(context.Context, *connect.Request[v1.GithubLoginRequest]) (*connect.Response[v1.GithubLoginResponse], error) + GetFile(context.Context, *connect.Request[v1.GetFileRequest]) (*connect.Response[v1.GetFileResponse], error) +} + +// NewVCSServiceClient constructs a client for the vcs.v1.VCSService service. By default, it uses +// the Connect protocol with the binary Protobuf Codec, asks for gzipped responses, and sends +// uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the connect.WithGRPC() or +// connect.WithGRPCWeb() options. +// +// The URL supplied here should be the base URL for the Connect or gRPC server (for example, +// http://api.acme.com or https://acme.com/grpc). +func NewVCSServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) VCSServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &vCSServiceClient{ + githubApp: connect.NewClient[v1.GithubAppRequest, v1.GithubAppResponse]( + httpClient, + baseURL+VCSServiceGithubAppProcedure, + connect.WithSchema(vCSServiceGithubAppMethodDescriptor), + connect.WithClientOptions(opts...), + ), + githubLogin: connect.NewClient[v1.GithubLoginRequest, v1.GithubLoginResponse]( + httpClient, + baseURL+VCSServiceGithubLoginProcedure, + connect.WithSchema(vCSServiceGithubLoginMethodDescriptor), + connect.WithClientOptions(opts...), + ), + getFile: connect.NewClient[v1.GetFileRequest, v1.GetFileResponse]( + httpClient, + baseURL+VCSServiceGetFileProcedure, + connect.WithSchema(vCSServiceGetFileMethodDescriptor), + connect.WithClientOptions(opts...), + ), + } +} + +// vCSServiceClient implements VCSServiceClient. +type vCSServiceClient struct { + githubApp *connect.Client[v1.GithubAppRequest, v1.GithubAppResponse] + githubLogin *connect.Client[v1.GithubLoginRequest, v1.GithubLoginResponse] + getFile *connect.Client[v1.GetFileRequest, v1.GetFileResponse] +} + +// GithubApp calls vcs.v1.VCSService.GithubApp. +func (c *vCSServiceClient) GithubApp(ctx context.Context, req *connect.Request[v1.GithubAppRequest]) (*connect.Response[v1.GithubAppResponse], error) { + return c.githubApp.CallUnary(ctx, req) +} + +// GithubLogin calls vcs.v1.VCSService.GithubLogin. +func (c *vCSServiceClient) GithubLogin(ctx context.Context, req *connect.Request[v1.GithubLoginRequest]) (*connect.Response[v1.GithubLoginResponse], error) { + return c.githubLogin.CallUnary(ctx, req) +} + +// GetFile calls vcs.v1.VCSService.GetFile. +func (c *vCSServiceClient) GetFile(ctx context.Context, req *connect.Request[v1.GetFileRequest]) (*connect.Response[v1.GetFileResponse], error) { + return c.getFile.CallUnary(ctx, req) +} + +// VCSServiceHandler is an implementation of the vcs.v1.VCSService service. +type VCSServiceHandler interface { + GithubApp(context.Context, *connect.Request[v1.GithubAppRequest]) (*connect.Response[v1.GithubAppResponse], error) + GithubLogin(context.Context, *connect.Request[v1.GithubLoginRequest]) (*connect.Response[v1.GithubLoginResponse], error) + GetFile(context.Context, *connect.Request[v1.GetFileRequest]) (*connect.Response[v1.GetFileResponse], error) +} + +// NewVCSServiceHandler builds an HTTP handler from the service implementation. It returns the path +// on which to mount the handler and the handler itself. +// +// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf +// and JSON codecs. They also support gzip compression. +func NewVCSServiceHandler(svc VCSServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + vCSServiceGithubAppHandler := connect.NewUnaryHandler( + VCSServiceGithubAppProcedure, + svc.GithubApp, + connect.WithSchema(vCSServiceGithubAppMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + vCSServiceGithubLoginHandler := connect.NewUnaryHandler( + VCSServiceGithubLoginProcedure, + svc.GithubLogin, + connect.WithSchema(vCSServiceGithubLoginMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + vCSServiceGetFileHandler := connect.NewUnaryHandler( + VCSServiceGetFileProcedure, + svc.GetFile, + connect.WithSchema(vCSServiceGetFileMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + return "/vcs.v1.VCSService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case VCSServiceGithubAppProcedure: + vCSServiceGithubAppHandler.ServeHTTP(w, r) + case VCSServiceGithubLoginProcedure: + vCSServiceGithubLoginHandler.ServeHTTP(w, r) + case VCSServiceGetFileProcedure: + vCSServiceGetFileHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedVCSServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedVCSServiceHandler struct{} + +func (UnimplementedVCSServiceHandler) GithubApp(context.Context, *connect.Request[v1.GithubAppRequest]) (*connect.Response[v1.GithubAppResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("vcs.v1.VCSService.GithubApp is not implemented")) +} + +func (UnimplementedVCSServiceHandler) GithubLogin(context.Context, *connect.Request[v1.GithubLoginRequest]) (*connect.Response[v1.GithubLoginResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("vcs.v1.VCSService.GithubLogin is not implemented")) +} + +func (UnimplementedVCSServiceHandler) GetFile(context.Context, *connect.Request[v1.GetFileRequest]) (*connect.Response[v1.GetFileResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("vcs.v1.VCSService.GetFile is not implemented")) +} diff --git a/api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.mux.go b/api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.mux.go new file mode 100644 index 0000000000..ed00ae731d --- /dev/null +++ b/api/gen/proto/go/vcs/v1/vcsv1connect/vcs.connect.mux.go @@ -0,0 +1,37 @@ +// Code generated by protoc-gen-connect-go-mux. DO NOT EDIT. +// +// Source: vcs/v1/vcs.proto + +package vcsv1connect + +import ( + connect "connectrpc.com/connect" + mux "github.com/gorilla/mux" +) + +// This is a compile-time assertion to ensure that this generated file and the connect package are +// compatible. If you get a compiler error that this constant is not defined, this code was +// generated with a version of connect newer than the one compiled into your binary. You can fix the +// problem by either regenerating this code with an older version of connect or updating the connect +// version compiled into your binary. +const _ = connect.IsAtLeastVersion0_1_0 + +// RegisterVCSServiceHandler register an HTTP handler to a mux.Router from the service +// implementation. +func RegisterVCSServiceHandler(mux *mux.Router, svc VCSServiceHandler, opts ...connect.HandlerOption) { + mux.Handle("/vcs.v1.VCSService/GithubApp", connect.NewUnaryHandler( + "/vcs.v1.VCSService/GithubApp", + svc.GithubApp, + opts..., + )) + mux.Handle("/vcs.v1.VCSService/GithubLogin", connect.NewUnaryHandler( + "/vcs.v1.VCSService/GithubLogin", + svc.GithubLogin, + opts..., + )) + mux.Handle("/vcs.v1.VCSService/GetFile", connect.NewUnaryHandler( + "/vcs.v1.VCSService/GetFile", + svc.GetFile, + opts..., + )) +} diff --git a/api/openapiv2/gen/phlare.swagger.json b/api/openapiv2/gen/phlare.swagger.json index 605453247f..82413177e9 100644 --- a/api/openapiv2/gen/phlare.swagger.json +++ b/api/openapiv2/gen/phlare.swagger.json @@ -23,6 +23,9 @@ { "name": "StoreGatewayService" }, + { + "name": "VCSService" + }, { "name": "Version" } @@ -599,6 +602,19 @@ } } }, + "v1GetFileResponse": { + "type": "object", + "properties": { + "content": { + "type": "string", + "title": "base64 content of the file" + }, + "URL": { + "type": "string", + "title": "the full URL to the file" + } + } + }, "v1GetSettingsResponse": { "type": "object", "properties": { @@ -611,6 +627,17 @@ } } }, + "v1GithubAppResponse": { + "type": "object", + "properties": { + "clientID": { + "type": "string" + } + } + }, + "v1GithubLoginResponse": { + "type": "object" + }, "v1Hints": { "type": "object", "properties": { diff --git a/api/vcs/v1/vcs.proto b/api/vcs/v1/vcs.proto new file mode 100644 index 0000000000..2520c725f4 --- /dev/null +++ b/api/vcs/v1/vcs.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; + +package vcs.v1; + +service VCSService { + rpc GithubApp(GithubAppRequest) returns (GithubAppResponse) {} + rpc GithubLogin(GithubLoginRequest) returns (GithubLoginResponse) {} + rpc GetFile(GetFileRequest) returns (GetFileResponse) {} +} +message GithubAppRequest { +} + +message GithubAppResponse { + string clientID = 1; +} + +message GithubLoginRequest { + string authorizationCode = 1; +} + +message GithubLoginResponse {} + +message GetFileRequest { + // the full path to the repository + string repositoryURL = 1; + // the vcs ref to get the file from + string ref = 2; + // the path to the file as provided by the symbols + string localPath = 3; +} + +message GetFileResponse { + // base64 content of the file + string content = 1; + // the full URL to the file + string URL = 2; +} diff --git a/ebpf/go.mod b/ebpf/go.mod index dd3e96525f..dc01c82d25 100644 --- a/ebpf/go.mod +++ b/ebpf/go.mod @@ -16,7 +16,6 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/prometheus/common v0.44.0 - github.com/prometheus/prometheus v0.48.1 github.com/samber/lo v1.38.1 github.com/stretchr/testify v1.8.4 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa @@ -29,8 +28,8 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect - github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/jpillora/backoff v1.0.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect diff --git a/ebpf/go.sum b/ebpf/go.sum index 0ad34d4cdf..f2db3c3d41 100644 --- a/ebpf/go.sum +++ b/ebpf/go.sum @@ -30,8 +30,6 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/grafana/pyroscope/api v0.2.0 h1:TzOxL0s6SiaLEy944ZAKgHcx/JDRJXu4O8ObwkqR6p4= github.com/grafana/pyroscope/api v0.2.0/go.mod h1:nhH+xai9cYFgs6lMy/+L0pKj0d5yCMwji/QAiQFCP+U= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= -github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4= github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU= @@ -58,8 +56,6 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= -github.com/prometheus/prometheus v0.48.1 h1:CTszphSNTXkuCG6O0IfpKdHcJkvvnAAE1GbELKS+NFk= -github.com/prometheus/prometheus v0.48.1/go.mod h1:SRw624aMAxTfryAcP8rOjg4S/sHHaetx2lyJJ2nM83g= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= diff --git a/go.mod b/go.mod index 20f673920f..bcb9bbdfb6 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( connectrpc.com/connect v1.14.0 connectrpc.com/grpchealth v1.3.0 + github.com/PuerkitoBio/goquery v1.8.1 github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 github.com/briandowns/spinner v1.23.0 github.com/cespare/xxhash/v2 v2.2.0 @@ -22,6 +23,7 @@ require ( github.com/gogo/status v1.1.1 github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da github.com/google/go-cmp v0.6.0 + github.com/google/go-github/v58 v58.0.1-0.20240111193443-e9f52699f5e5 github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 github.com/google/uuid v1.4.0 github.com/gorilla/mux v1.8.0 @@ -37,6 +39,7 @@ require ( github.com/json-iterator/go v1.1.12 github.com/k0kubun/pp/v3 v3.2.0 github.com/klauspost/compress v1.17.3 + github.com/kubescape/go-git-url v0.0.27 github.com/mattn/go-isatty v0.0.19 github.com/minio/minio-go/v7 v7.0.61 github.com/mitchellh/go-wordwrap v1.0.1 @@ -64,6 +67,7 @@ require ( go.uber.org/goleak v1.2.1 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/net v0.19.0 + golang.org/x/oauth2 v0.15.0 golang.org/x/sync v0.5.0 golang.org/x/sys v0.15.0 golang.org/x/text v0.14.0 @@ -92,6 +96,7 @@ require ( github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible // indirect github.com/andybalholm/brotli v1.0.5 // indirect + github.com/andybalholm/cascadia v1.3.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect @@ -108,6 +113,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.19.2 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/chainguard-dev/git-urls v1.0.2 // indirect github.com/clbanning/mxj v1.8.4 // indirect github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -117,6 +123,7 @@ require ( github.com/efficientgo/core v1.0.0-rc.2 // indirect github.com/efficientgo/e2e v0.14.1-0.20230710114240-c316eb95ae5b // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/github/go-pipe v1.0.2 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -207,7 +214,6 @@ require ( go.uber.org/zap v1.24.0 // indirect golang.org/x/crypto v0.17.0 // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/term v0.15.0 // indirect golang.org/x/tools v0.15.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect @@ -217,6 +223,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect ) replace ( diff --git a/go.sum b/go.sum index 11b56dd64a..df5b63422b 100644 --- a/go.sum +++ b/go.sum @@ -64,6 +64,8 @@ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3 github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= +github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= @@ -80,6 +82,8 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible h1:KXeJoM1wo9I/6xPTyt6qC github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= +github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= @@ -132,6 +136,8 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ= +github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -198,6 +204,8 @@ github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/github/go-pipe v1.0.2 h1:befTXflsc6ir/h9f6Q7QCDmfojoBswD1MfQrPhmmSoA= +github.com/github/go-pipe v1.0.2/go.mod h1:/GvNLA516QlfGGMtfv4PC/5/CdzL9X4af/AJYhmLD54= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -348,6 +356,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v58 v58.0.1-0.20240111193443-e9f52699f5e5 h1:Cm3eMs9Qj7fqDQOascVTJg37N0T7Vb2foS//WopCpWw= +github.com/google/go-github/v58 v58.0.1-0.20240111193443-e9f52699f5e5/go.mod h1:k4hxDKEfoWpSqFlc8LTpGd9fu2KrV1YAa6Hi6FmDNY4= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= @@ -503,6 +513,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kubescape/go-git-url v0.0.27 h1:nvHDwuFs4ezOJ5CGL9U7ZL6gRMneWZdelBs0KEK8yb8= +github.com/kubescape/go-git-url v0.0.27/go.mod h1:3ddc1HEflms1vMhD9owt/3FBES070UaYTUarcjx8jDk= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/linode/linodego v1.23.0 h1:s0ReCZtuN9Z1IoUN9w1RLeYO1dMZUGPwOQ/IBFsBHtU= @@ -862,9 +874,11 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -959,6 +973,7 @@ golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1171,6 +1186,7 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= k8s.io/utils v0.0.0-20230711102312-30195339c3c7 h1:ZgnF1KZsYxWIifwSNZFZgNtWE89WI5yiP5WwlfDoIyc= +k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/pkg/api/api.go b/pkg/api/api.go index 6809da358a..5d277e5af5 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -30,6 +30,7 @@ import ( "github.com/grafana/pyroscope/api/gen/proto/go/settings/v1/settingsv1connect" statusv1 "github.com/grafana/pyroscope/api/gen/proto/go/status/v1" "github.com/grafana/pyroscope/api/gen/proto/go/storegateway/v1/storegatewayv1connect" + "github.com/grafana/pyroscope/api/gen/proto/go/vcs/v1/vcsv1connect" "github.com/grafana/pyroscope/api/gen/proto/go/version/v1/versionv1connect" "github.com/grafana/pyroscope/api/openapiv2" "github.com/grafana/pyroscope/pkg/compactor" @@ -232,9 +233,19 @@ func (a *API) RegisterRing(r http.Handler) { }) } +type QuerierSvc interface { + querierv1connect.QuerierServiceHandler + vcsv1connect.VCSServiceHandler +} + // RegisterQuerier registers the endpoints associated with the querier. -func (a *API) RegisterQuerier(svc querierv1connect.QuerierServiceHandler) { +func (a *API) RegisterQuerier(svc QuerierSvc) { querierv1connect.RegisterQuerierServiceHandler(a.server.HTTP, svc, a.grpcAuthMiddleware, a.grpcLogMiddleware) + vcsv1connect.RegisterVCSServiceHandler(a.server.HTTP, svc, a.grpcAuthMiddleware, a.grpcLogMiddleware) + // todo remove this once we have a proper UI for the VCS + a.RegisterRoute("/vcs", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, "./pkg/api/vcs.html") + }), true, true, "GET", "POST") } func (a *API) RegisterPyroscopeHandlers(client querierv1connect.QuerierServiceClient) { diff --git a/pkg/api/vcs.html b/pkg/api/vcs.html new file mode 100644 index 0000000000..008244518c --- /dev/null +++ b/pkg/api/vcs.html @@ -0,0 +1,132 @@ + + + + + + + Github OAuth App + + + + + + +
+ + + + + +
+

+  

+  
+
+
+
diff --git a/pkg/frontend/frontend_vcs.go b/pkg/frontend/frontend_vcs.go
new file mode 100644
index 0000000000..778a164111
--- /dev/null
+++ b/pkg/frontend/frontend_vcs.go
@@ -0,0 +1,22 @@
+package frontend
+
+import (
+	"context"
+
+	"connectrpc.com/connect"
+
+	vcsv1 "github.com/grafana/pyroscope/api/gen/proto/go/vcs/v1"
+	"github.com/grafana/pyroscope/pkg/util/connectgrpc"
+)
+
+func (f *Frontend) GithubApp(ctx context.Context, req *connect.Request[vcsv1.GithubAppRequest]) (*connect.Response[vcsv1.GithubAppResponse], error) {
+	return connectgrpc.RoundTripUnary[vcsv1.GithubAppRequest, vcsv1.GithubAppResponse](ctx, f, req)
+}
+
+func (f *Frontend) GithubLogin(ctx context.Context, req *connect.Request[vcsv1.GithubLoginRequest]) (*connect.Response[vcsv1.GithubLoginResponse], error) {
+	return connectgrpc.RoundTripUnary[vcsv1.GithubLoginRequest, vcsv1.GithubLoginResponse](ctx, f, req)
+}
+
+func (f *Frontend) GetFile(ctx context.Context, req *connect.Request[vcsv1.GetFileRequest]) (*connect.Response[vcsv1.GetFileResponse], error) {
+	return connectgrpc.RoundTripUnary[vcsv1.GetFileRequest, vcsv1.GetFileResponse](ctx, f, req)
+}
diff --git a/pkg/pprof/pprof_test.go b/pkg/pprof/pprof_test.go
index 758d82c86f..70fd7db9b4 100644
--- a/pkg/pprof/pprof_test.go
+++ b/pkg/pprof/pprof_test.go
@@ -1009,7 +1009,6 @@ func Test_SampleExporter_Partial(t *testing.T) {
 		Period: 10000000,
 	}
 	requireProfilesEqual(t, expected, n)
-
 }
 
 func Test_GroupSamplesWithout_Go_CPU_profile(t *testing.T) {
diff --git a/pkg/querier/cookie.go b/pkg/querier/cookie.go
new file mode 100644
index 0000000000..ee77070256
--- /dev/null
+++ b/pkg/querier/cookie.go
@@ -0,0 +1,101 @@
+package querier
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/rand"
+	"encoding/base64"
+	"encoding/json"
+	"io"
+	"os"
+
+	"golang.org/x/oauth2"
+)
+
+var githubSessionSecret = os.Getenv("GITHUB_SESSION_SECRET")
+
+func encryptAES256(token *oauth2.Token) (string, error) {
+	keyBytes := []byte(githubSessionSecret)
+	textBytes, err := json.Marshal(token)
+	if err != nil {
+		return "", err
+	}
+
+	// Create AES cipher block
+	block, err := aes.NewCipher(keyBytes)
+	if err != nil {
+		return "", err
+	}
+
+	// Generate a random IV
+	iv := make([]byte, aes.BlockSize)
+	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
+		return "", err
+	}
+
+	// Pad the plaintext if needed
+	blockSize := block.BlockSize()
+	textBytes = PKCS7Padding(textBytes, blockSize)
+
+	// Create a new AES cipher block mode with IV
+	blockMode := cipher.NewCBCEncrypter(block, iv)
+
+	// Encrypt the plaintext
+	ciphertext := make([]byte, len(textBytes))
+	blockMode.CryptBlocks(ciphertext, textBytes)
+
+	// Combine IV and ciphertext, then encode to base64
+	encryptedData := append(iv, ciphertext...)
+	encodedText := base64.StdEncoding.EncodeToString(encryptedData)
+
+	return encodedText, nil
+}
+
+func decryptAES256(encodedText string) (*oauth2.Token, error) {
+	keyBytes := []byte(githubSessionSecret)
+
+	// Decode the base64-encoded string
+	encryptedData, err := base64.StdEncoding.DecodeString(encodedText)
+	if err != nil {
+		return nil, err
+	}
+
+	// Extract IV from the first block
+	iv := encryptedData[:aes.BlockSize]
+	ciphertext := encryptedData[aes.BlockSize:]
+
+	// Create AES cipher block
+	block, err := aes.NewCipher(keyBytes)
+	if err != nil {
+		return nil, err
+	}
+
+	// Create a new AES cipher block mode with IV
+	blockMode := cipher.NewCBCDecrypter(block, iv)
+
+	// Decrypt the ciphertext
+	plaintext := make([]byte, len(ciphertext))
+	blockMode.CryptBlocks(plaintext, ciphertext)
+
+	// Remove PKCS7 padding
+	plaintext = PKCS7Unpadding(plaintext)
+
+	var token oauth2.Token
+	err = json.Unmarshal(plaintext, &token)
+
+	return &token, err
+}
+
+// PKCS7Padding pads the input to be a multiple of blockSize using PKCS7 padding.
+func PKCS7Padding(data []byte, blockSize int) []byte {
+	padding := blockSize - len(data)%blockSize
+	padText := bytes.Repeat([]byte{byte(padding)}, padding)
+	return append(data, padText...)
+}
+
+// PKCS7Unpadding removes PKCS7 padding from the input.
+func PKCS7Unpadding(data []byte) []byte {
+	padding := int(data[len(data)-1])
+	return data[:len(data)-padding]
+}
diff --git a/pkg/querier/cookie_test.go b/pkg/querier/cookie_test.go
new file mode 100644
index 0000000000..17bdd081d3
--- /dev/null
+++ b/pkg/querier/cookie_test.go
@@ -0,0 +1,24 @@
+package querier
+
+import (
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/require"
+	"golang.org/x/oauth2"
+)
+
+func TestEncodeOAuth(t *testing.T) {
+	token := &oauth2.Token{
+		AccessToken:  "a1b2c3d4e5f6",
+		TokenType:    "access_token",
+		RefreshToken: "a1b2c3d4e5f6",
+		Expiry:       time.Unix(200, 0),
+	}
+	enc, err := encryptAES256(token)
+	require.NoError(t, err)
+	require.NotEmpty(t, enc)
+	actual, err := decryptAES256(enc)
+	require.NoError(t, err)
+	require.Equal(t, token, actual)
+}
diff --git a/pkg/querier/golang/gen.go b/pkg/querier/golang/gen.go
new file mode 100644
index 0000000000..11c0b5e2e8
--- /dev/null
+++ b/pkg/querier/golang/gen.go
@@ -0,0 +1,58 @@
+//go:build ignore
+
+package main
+
+import (
+	"bytes"
+	"context"
+	"html/template"
+	"io"
+	"log"
+	"os"
+
+	"github.com/github/go-pipe/pipe"
+
+	"github.com/grafana/pyroscope/pkg/querier/golang"
+)
+
+func main() {
+	// todo: In the future we might want to support more than one version
+	// Or even list all files from standard packages to improve matching.
+	packages, err := golang.StdPackages("")
+	if err != nil {
+		log.Fatal(err)
+	}
+	t := template.Must(template.New("packages").Parse(packagesTemplate))
+	var buff bytes.Buffer
+	p := pipe.New(pipe.WithStdout(&buff))
+	p.Add(
+		pipe.Function("", func(ctx context.Context, env pipe.Env, stdin io.Reader, stdout io.Writer) error {
+			err = t.Execute(stdout, packages)
+			if err != nil {
+				log.Fatal(err)
+			}
+			return nil
+		}),
+		// This might be a bit overkill, but it's nice to have a consistent format.
+		// todo: We could use "go/format" package only that will simplify the code but also remove the needs
+		// for expected installed binaries.
+		pipe.Command("gofmt"),
+		pipe.Command("goimports"),
+	)
+	p.Run(context.Background())
+	err = os.WriteFile("packages_gen.go", buff.Bytes(), 0666)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+var packagesTemplate = `
+package golang
+// Code generated. DO NOT EDIT.
+
+var StandardPackages = map[string]struct{}{
+	{{- range $key, $value := .}}
+	"{{$key}}": {},
+	{{- end}}
+}
+`
diff --git a/pkg/querier/golang/packages.go b/pkg/querier/golang/packages.go
new file mode 100644
index 0000000000..466c4ac585
--- /dev/null
+++ b/pkg/querier/golang/packages.go
@@ -0,0 +1,47 @@
+//go:generate go run gen.go > packages_gen.go
+
+package golang
+
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"strings"
+
+	"github.com/PuerkitoBio/goquery"
+)
+
+func StdPackages(version string) (map[string]struct{}, error) {
+	if version != "" {
+		version = "@go" + version
+	}
+	res, err := http.Get(fmt.Sprintf("https://pkg.go.dev/std%s", version))
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+	if res.StatusCode != 200 {
+		log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
+	}
+	// Load the HTML document
+	doc, err := goquery.NewDocumentFromReader(res.Body)
+	if err != nil {
+		return nil, err
+	}
+	packages := map[string]struct{}{}
+	doc.Find("tbody").Each(func(i int, s *goquery.Selection) {
+		// For each item found, get the title
+		s.Find("a").Each(func(i int, s *goquery.Selection) {
+			href, ok := s.Attr("href")
+			if !ok {
+				return
+			}
+			// extract the package name from the href
+			// /crypto/internal/alias@go1.21.6
+			if len(strings.Split(href, "@")) > 1 {
+				packages[strings.Trim(strings.Split(href, "@")[0], "/")] = struct{}{}
+			}
+		})
+	})
+	return packages, nil
+}
diff --git a/pkg/querier/golang/packages_gen.go b/pkg/querier/golang/packages_gen.go
new file mode 100644
index 0000000000..07f71d7e07
--- /dev/null
+++ b/pkg/querier/golang/packages_gen.go
@@ -0,0 +1,267 @@
+package golang
+
+// Code generated. DO NOT EDIT.
+
+var StandardPackages = map[string]struct{}{
+	"archive/tar":                        {},
+	"archive/zip":                        {},
+	"bufio":                              {},
+	"builtin":                            {},
+	"bytes":                              {},
+	"cmp":                                {},
+	"compress/bzip2":                     {},
+	"compress/flate":                     {},
+	"compress/gzip":                      {},
+	"compress/lzw":                       {},
+	"compress/zlib":                      {},
+	"container/heap":                     {},
+	"container/list":                     {},
+	"container/ring":                     {},
+	"context":                            {},
+	"crypto":                             {},
+	"crypto/aes":                         {},
+	"crypto/cipher":                      {},
+	"crypto/des":                         {},
+	"crypto/dsa":                         {},
+	"crypto/ecdh":                        {},
+	"crypto/ecdsa":                       {},
+	"crypto/ed25519":                     {},
+	"crypto/elliptic":                    {},
+	"crypto/hmac":                        {},
+	"crypto/internal/alias":              {},
+	"crypto/internal/bigmod":             {},
+	"crypto/internal/boring":             {},
+	"crypto/internal/boring/bbig":        {},
+	"crypto/internal/boring/bcache":      {},
+	"crypto/internal/boring/sig":         {},
+	"crypto/internal/edwards25519":       {},
+	"crypto/internal/edwards25519/field": {},
+	"crypto/internal/nistec":             {},
+	"crypto/internal/nistec/fiat":        {},
+	"crypto/internal/randutil":           {},
+	"crypto/md5":                         {},
+	"crypto/rand":                        {},
+	"crypto/rc4":                         {},
+	"crypto/rsa":                         {},
+	"crypto/sha1":                        {},
+	"crypto/sha256":                      {},
+	"crypto/sha512":                      {},
+	"crypto/subtle":                      {},
+	"crypto/tls":                         {},
+	"crypto/x509":                        {},
+	"crypto/x509/internal/macos":         {},
+	"crypto/x509/pkix":                   {},
+	"database/sql":                       {},
+	"database/sql/driver":                {},
+	"debug/buildinfo":                    {},
+	"debug/dwarf":                        {},
+	"debug/elf":                          {},
+	"debug/gosym":                        {},
+	"debug/macho":                        {},
+	"debug/pe":                           {},
+	"debug/plan9obj":                     {},
+	"embed":                              {},
+	"encoding":                           {},
+	"encoding/ascii85":                   {},
+	"encoding/asn1":                      {},
+	"encoding/base32":                    {},
+	"encoding/base64":                    {},
+	"encoding/binary":                    {},
+	"encoding/csv":                       {},
+	"encoding/gob":                       {},
+	"encoding/hex":                       {},
+	"encoding/json":                      {},
+	"encoding/pem":                       {},
+	"encoding/xml":                       {},
+	"errors":                             {},
+	"expvar":                             {},
+	"flag":                               {},
+	"fmt":                                {},
+	"go/ast":                             {},
+	"go/build":                           {},
+	"go/build/constraint":                {},
+	"go/constant":                        {},
+	"go/doc":                             {},
+	"go/doc/comment":                     {},
+	"go/format":                          {},
+	"go/importer":                        {},
+	"go/internal/gccgoimporter":          {},
+	"go/internal/gcimporter":             {},
+	"go/internal/srcimporter":            {},
+	"go/internal/typeparams":             {},
+	"go/parser":                          {},
+	"go/printer":                         {},
+	"go/scanner":                         {},
+	"go/token":                           {},
+	"go/types":                           {},
+	"hash":                               {},
+	"hash/adler32":                       {},
+	"hash/crc32":                         {},
+	"hash/crc64":                         {},
+	"hash/fnv":                           {},
+	"hash/maphash":                       {},
+	"html":                               {},
+	"html/template":                      {},
+	"image":                              {},
+	"image/color":                        {},
+	"image/color/palette":                {},
+	"image/draw":                         {},
+	"image/gif":                          {},
+	"image/internal/imageutil":           {},
+	"image/jpeg":                         {},
+	"image/png":                          {},
+	"index/suffixarray":                  {},
+	"internal/abi":                       {},
+	"internal/bisect":                    {},
+	"internal/buildcfg":                  {},
+	"internal/bytealg":                   {},
+	"internal/cfg":                       {},
+	"internal/coverage":                  {},
+	"internal/coverage/calloc":           {},
+	"internal/coverage/cformat":          {},
+	"internal/coverage/cmerge":           {},
+	"internal/coverage/decodecounter":    {},
+	"internal/coverage/decodemeta":       {},
+	"internal/coverage/encodecounter":    {},
+	"internal/coverage/encodemeta":       {},
+	"internal/coverage/pods":             {},
+	"internal/coverage/rtcov":            {},
+	"internal/coverage/slicereader":      {},
+	"internal/coverage/slicewriter":      {},
+	"internal/coverage/stringtab":        {},
+	"internal/coverage/uleb128":          {},
+	"internal/cpu":                       {},
+	"internal/dag":                       {},
+	"internal/diff":                      {},
+	"internal/fmtsort":                   {},
+	"internal/fuzz":                      {},
+	"internal/goarch":                    {},
+	"internal/godebug":                   {},
+	"internal/godebugs":                  {},
+	"internal/goexperiment":              {},
+	"internal/goos":                      {},
+	"internal/goroot":                    {},
+	"internal/goversion":                 {},
+	"internal/intern":                    {},
+	"internal/itoa":                      {},
+	"internal/lazyregexp":                {},
+	"internal/lazytemplate":              {},
+	"internal/nettrace":                  {},
+	"internal/obscuretestdata":           {},
+	"internal/oserror":                   {},
+	"internal/pkgbits":                   {},
+	"internal/platform":                  {},
+	"internal/poll":                      {},
+	"internal/profile":                   {},
+	"internal/race":                      {},
+	"internal/reflectlite":               {},
+	"internal/safefilepath":              {},
+	"internal/saferio":                   {},
+	"internal/singleflight":              {},
+	"internal/syscall/execenv":           {},
+	"internal/syscall/unix":              {},
+	"internal/syscall/windows":           {},
+	"internal/syscall/windows/registry":  {},
+	"internal/syscall/windows/sysdll":    {},
+	"internal/sysinfo":                   {},
+	"internal/testenv":                   {},
+	"internal/testlog":                   {},
+	"internal/testpty":                   {},
+	"internal/trace":                     {},
+	"internal/txtar":                     {},
+	"internal/types/errors":              {},
+	"internal/unsafeheader":              {},
+	"internal/xcoff":                     {},
+	"internal/zstd":                      {},
+	"io":                                 {},
+	"io/fs":                              {},
+	"io/ioutil":                          {},
+	"log":                                {},
+	"log/internal":                       {},
+	"log/slog":                           {},
+	"log/slog/internal":                  {},
+	"log/slog/internal/benchmarks":       {},
+	"log/slog/internal/buffer":           {},
+	"log/slog/internal/slogtest":         {},
+	"log/syslog":                         {},
+	"maps":                               {},
+	"math":                               {},
+	"math/big":                           {},
+	"math/bits":                          {},
+	"math/cmplx":                         {},
+	"math/rand":                          {},
+	"mime":                               {},
+	"mime/multipart":                     {},
+	"mime/quotedprintable":               {},
+	"net":                                {},
+	"net/http":                           {},
+	"net/http/cgi":                       {},
+	"net/http/cookiejar":                 {},
+	"net/http/fcgi":                      {},
+	"net/http/httptest":                  {},
+	"net/http/httptrace":                 {},
+	"net/http/httputil":                  {},
+	"net/http/internal":                  {},
+	"net/http/internal/ascii":            {},
+	"net/http/internal/testcert":         {},
+	"net/http/pprof":                     {},
+	"net/internal/socktest":              {},
+	"net/mail":                           {},
+	"net/netip":                          {},
+	"net/rpc":                            {},
+	"net/rpc/jsonrpc":                    {},
+	"net/smtp":                           {},
+	"net/textproto":                      {},
+	"net/url":                            {},
+	"os":                                 {},
+	"os/exec":                            {},
+	"os/exec/internal/fdtest":            {},
+	"os/signal":                          {},
+	"os/user":                            {},
+	"path":                               {},
+	"path/filepath":                      {},
+	"plugin":                             {},
+	"reflect":                            {},
+	"reflect/internal/example1":          {},
+	"reflect/internal/example2":          {},
+	"regexp":                             {},
+	"regexp/syntax":                      {},
+	"runtime":                            {},
+	"runtime/cgo":                        {},
+	"runtime/coverage":                   {},
+	"runtime/debug":                      {},
+	"runtime/internal/atomic":            {},
+	"runtime/internal/math":              {},
+	"runtime/internal/startlinetest":     {},
+	"runtime/internal/sys":               {},
+	"runtime/internal/syscall":           {},
+	"runtime/metrics":                    {},
+	"runtime/pprof":                      {},
+	"runtime/race":                       {},
+	"runtime/race/internal/amd64v1":      {},
+	"runtime/trace":                      {},
+	"slices":                             {},
+	"sort":                               {},
+	"strconv":                            {},
+	"strings":                            {},
+	"sync":                               {},
+	"sync/atomic":                        {},
+	"syscall":                            {},
+	"syscall/js":                         {},
+	"testing":                            {},
+	"testing/fstest":                     {},
+	"testing/internal/testdeps":          {},
+	"testing/iotest":                     {},
+	"testing/quick":                      {},
+	"testing/slogtest":                   {},
+	"text/scanner":                       {},
+	"text/tabwriter":                     {},
+	"text/template":                      {},
+	"text/template/parse":                {},
+	"time":                               {},
+	"time/tzdata":                        {},
+	"unicode":                            {},
+	"unicode/utf16":                      {},
+	"unicode/utf8":                       {},
+	"unsafe":                             {},
+}
diff --git a/pkg/querier/grpc_handler.go b/pkg/querier/grpc_handler.go
index e0c27c8e35..2daade44ad 100644
--- a/pkg/querier/grpc_handler.go
+++ b/pkg/querier/grpc_handler.go
@@ -1,11 +1,21 @@
 package querier
 
 import (
+	"net/http"
+
 	"github.com/grafana/pyroscope/api/gen/proto/go/querier/v1/querierv1connect"
+	vcsv1connect "github.com/grafana/pyroscope/api/gen/proto/go/vcs/v1/vcsv1connect"
 	"github.com/grafana/pyroscope/pkg/util/connectgrpc"
 )
 
-func NewGRPCHandler(svc querierv1connect.QuerierServiceHandler) connectgrpc.GRPCHandler {
-	_, h := querierv1connect.NewQuerierServiceHandler(svc)
-	return connectgrpc.NewHandler(h)
+type QuerierSvc interface {
+	querierv1connect.QuerierServiceHandler
+	vcsv1connect.VCSServiceHandler
+}
+
+func NewGRPCHandler(svc QuerierSvc) connectgrpc.GRPCHandler {
+	mux := http.NewServeMux()
+	mux.Handle(querierv1connect.NewQuerierServiceHandler(svc))
+	mux.Handle(vcsv1connect.NewVCSServiceHandler(svc))
+	return connectgrpc.NewHandler(mux)
 }
diff --git a/pkg/querier/vcs.go b/pkg/querier/vcs.go
new file mode 100644
index 0000000000..3bbf4254aa
--- /dev/null
+++ b/pkg/querier/vcs.go
@@ -0,0 +1,664 @@
+package querier
+
+import (
+	"context"
+	"encoding/base64"
+	"errors"
+	"fmt"
+	"io"
+	"net/http"
+	"os"
+	"path/filepath"
+	"strings"
+	"time"
+
+	"connectrpc.com/connect"
+	"github.com/PuerkitoBio/goquery"
+	"github.com/go-kit/log"
+	"github.com/go-kit/log/level"
+	"github.com/google/go-github/v58/github"
+	giturl "github.com/kubescape/go-git-url"
+	"github.com/kubescape/go-git-url/apis"
+	"golang.org/x/mod/modfile"
+	"golang.org/x/mod/module"
+	"golang.org/x/mod/semver"
+	"golang.org/x/oauth2"
+	o2endpoints "golang.org/x/oauth2/endpoints"
+
+	vcsv1 "github.com/grafana/pyroscope/api/gen/proto/go/vcs/v1"
+	vcsv1connect "github.com/grafana/pyroscope/api/gen/proto/go/vcs/v1/vcsv1connect"
+	"github.com/grafana/pyroscope/pkg/querier/golang"
+	"github.com/grafana/regexp"
+)
+
+var (
+	githubClientID                                    = os.Getenv("GITHUB_CLIENT_ID")
+	githubClientSecret                                = os.Getenv("GITHUB_CLIENT_SECRET")
+	_                  vcsv1connect.VCSServiceHandler = (*Querier)(nil)
+)
+
+// todo better package structure.
+// vcs_service_test.go
+// vcs_service.go
+// source/find.go
+// source/golang/find.go
+
+func (q *Querier) GithubApp(ctx context.Context, req *connect.Request[vcsv1.GithubAppRequest]) (*connect.Response[vcsv1.GithubAppResponse], error) {
+	return connect.NewResponse(&vcsv1.GithubAppResponse{
+		ClientID: githubClientID,
+	}), nil
+}
+
+func (q *Querier) GithubLogin(ctx context.Context, req *connect.Request[vcsv1.GithubLoginRequest]) (*connect.Response[vcsv1.GithubLoginResponse], error) {
+	auth, err := githubOauthConfig()
+	if err != nil {
+		return nil, err
+	}
+	token, err := auth.Exchange(ctx, req.Msg.AuthorizationCode)
+	if err != nil {
+		return nil, err
+	}
+	cookieValue, err := encryptAES256(token)
+	if err != nil {
+		return nil, err
+	}
+	// Sets a cookie with the encrypted token.
+	// Only the server can decrypt the cookie.
+	cookie := http.Cookie{
+		Name:  "GitSession",
+		Value: cookieValue,
+		// Refresh expiry is 6 months based on github docs
+		Expires:  time.Now().Add(15811200 * time.Second),
+		HttpOnly: true,
+		Secure:   true,
+		SameSite: http.SameSiteLaxMode,
+	}
+	resp := connect.NewResponse(&vcsv1.GithubLoginResponse{})
+	resp.Header().Add("Set-Cookie", cookie.String())
+	return resp, nil
+}
+
+func (q *Querier) GetFile(ctx context.Context, req *connect.Request[vcsv1.GetFileRequest]) (*connect.Response[vcsv1.GetFileResponse], error) {
+	gitURL, err := giturl.NewGitURL(req.Msg.RepositoryURL) // initialize and parse the URL
+	if err != nil {
+		return nil, connect.NewError(connect.CodeInvalidArgument, err)
+	}
+	if gitURL.GetProvider() != apis.ProviderGitHub.String() {
+		return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("only GitHub repositories are supported"))
+	}
+	cookie, err := (&http.Request{Header: req.Header()}).Cookie("GitSession")
+	if err != nil {
+		return nil, err
+	}
+	// todo: we can support multiple provider: bitbucket, gitlab, etc.
+	client, err := NewGithubClient(ctx, cookie)
+	if err == nil {
+		// todo should clear cookie this doesn't work yet.
+		cookie.MaxAge = -1
+		err := connect.NewError(
+			connect.CodeUnauthenticated,
+			err,
+		)
+		cookie.Value = ""
+		err.Meta().Set("Set-Cookie", cookie.String())
+		return nil, err
+	}
+
+	res, err := findFile(ctx, fileFinder{
+		path:   req.Msg.LocalPath,
+		ref:    req.Msg.Ref,
+		repo:   gitURL,
+		client: client,
+		logger: log.With(q.logger, "repo", gitURL.GetRepoName()),
+	})
+	if err != nil {
+		if errors.Is(err, ErrNotFound) {
+			return nil, connect.NewError(connect.CodeNotFound, err)
+		}
+		return nil, err
+	}
+	return connect.NewResponse(res), nil
+}
+
+func toString(s *string) string {
+	if s == nil {
+		return ""
+	}
+	return *s
+}
+
+type githubClient struct {
+	client *github.Client
+}
+
+// NewGithubClient returns a github client for the given code token exchange.
+// We might want to move this to it's own package if we support multiple providers.
+func NewGithubClient(ctx context.Context, cookie *http.Cookie) (*githubClient, error) {
+	auth, err := githubOauthConfig()
+	if err != nil {
+		return nil, err
+	}
+	token, err := decryptAES256(cookie.Value)
+	if err != nil {
+		return nil, err
+	}
+
+	return &githubClient{
+		client: github.NewClient(auth.Client(ctx, token)),
+	}, nil
+}
+
+func githubOauthConfig() (*oauth2.Config, error) {
+	if githubClientID == "" {
+		return nil, errors.New("missing GITHUB_CLIENT_ID environment variable")
+	}
+	if githubClientSecret == "" {
+		return nil, errors.New("missing GITHUB_CLIENT_SECRET environment variable")
+	}
+	return &oauth2.Config{
+		ClientID:     githubClientID,
+		ClientSecret: githubClientSecret,
+		Endpoint:     o2endpoints.GitHub,
+	}, nil
+}
+
+var ErrNotFound = errors.New("file not found")
+
+func (gh *githubClient) GetFile(ctx context.Context, owner, repo, path, ref string) (*VCSFile, error) {
+	// We could abstract away git provider using git protocol
+	// git clone https://x-access-token:@github.com/owner/repo.git
+	// For now we use the github client.
+	file, _, _, err := gh.client.Repositories.GetContents(ctx, owner, repo, path, &github.RepositoryContentGetOptions{Ref: ref})
+	if err != nil {
+		var githubErr *github.ErrorResponse
+		if ok := errors.As(err, &githubErr); ok && githubErr.Response.StatusCode == http.StatusNotFound {
+			return nil, fmt.Errorf("%w: %s", ErrNotFound, err)
+		}
+		return nil, err
+	}
+	if file.Type != nil && *file.Type != "file" {
+		return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("path is not a file"))
+	}
+	content, err := file.GetContent()
+	if err != nil {
+		return nil, err
+	}
+	return &VCSFile{
+		Content: content,
+		URL:     toString(file.DownloadURL),
+	}, nil
+}
+
+type VCSFile struct {
+	Content string
+	URL     string
+}
+
+type VCSClient interface {
+	GetFile(ctx context.Context, owner, repo, path, ref string) (*VCSFile, error)
+}
+
+// todo should be a struct with function no need to pass all of this aorund.
+type fileFinder struct {
+	path, ref string
+	repo      giturl.IGitURL
+
+	client VCSClient
+	logger log.Logger
+}
+
+func findFile(ctx context.Context, arg fileFinder) (*vcsv1.GetFileResponse, error) {
+	switch filepath.Ext(arg.path) {
+	case ".go":
+		return findGoFile(ctx, arg)
+	// todo: we can support multiple file types: go, java, python, etc.
+	default:
+		// by default we return the file content at the given path without any processing.
+		content, err := arg.client.GetFile(ctx, arg.repo.GetOwnerName(), arg.repo.GetRepoName(), arg.path, arg.ref)
+		if err != nil {
+			return nil, err
+		}
+		return newFileResponse(content.Content, content.URL)
+	}
+}
+
+func newFileResponse(content, url string) (*vcsv1.GetFileResponse, error) {
+	return &vcsv1.GetFileResponse{
+		Content: base64.StdEncoding.EncodeToString([]byte(content)),
+		URL:     url,
+	}, nil
+}
+
+func findGoFile(ctx context.Context, arg fileFinder) (*vcsv1.GetFileResponse, error) {
+	std, err := findGoStdFile(ctx, arg)
+	if err != nil {
+		return nil, err
+	}
+	if std != nil {
+		return std, nil
+	}
+
+	deps, err := findGoDependencyFile(ctx, arg)
+	if err != nil {
+		return nil, err
+	}
+	if deps != nil {
+		return deps, nil
+	}
+	// Try to find the file in the repo.
+	path := strings.TrimPrefix(arg.path, strings.Join([]string{arg.repo.GetHostName(), arg.repo.GetOwnerName(), arg.repo.GetRepoName()}, "/"))
+	path = strings.TrimLeft(path, "/")
+	for {
+		content, err := arg.client.GetFile(ctx, arg.repo.GetOwnerName(), arg.repo.GetRepoName(), path, arg.ref)
+		if err != nil && errors.Is(err, ErrNotFound) {
+			i := strings.Index(path, "/")
+			if i < 0 {
+				return nil, err
+			}
+			// remove the first path segment
+			path = path[i+1:]
+			continue
+		}
+		if err != nil {
+			return nil, err
+		}
+		return newFileResponse(content.Content, content.URL)
+
+	}
+}
+
+var versionSuffixRE = regexp.MustCompile(`/v[0-9]+[/]*`)
+
+func findGoDependencyFile(ctx context.Context, arg fileFinder) (*vcsv1.GetFileResponse, error) {
+	// if the path contains /vendor/ we can assume it's a dependency and it's versioned in the repo.
+	vIdx := strings.Index(arg.path, "/vendor/")
+	if vIdx > 0 {
+		relativePath := strings.TrimPrefix(arg.path[vIdx:], "/")
+		content, err := arg.client.GetFile(ctx, arg.repo.GetOwnerName(), arg.repo.GetRepoName(), relativePath, arg.ref)
+		if err != nil {
+			return nil, err
+		}
+		return newFileResponse(content.Content, content.URL)
+	}
+	mod, ok := parseGoModuleFilePath(arg.path)
+	if !ok {
+		return nil, nil
+	}
+	var err error
+	mainModule := module.Version{
+		Path:    filepath.Join(arg.repo.GetHostName(), arg.repo.GetOwnerName(), arg.repo.GetRepoName()),
+		Version: module.PseudoVersion("", "", time.Time{}, arg.ref),
+	}
+	// we found a go module dependency
+	modf, err := fetchGoMod(ctx, arg)
+	if err != nil {
+		level.Warn(arg.logger).Log("msg", "failed to fetch go.mod file", "err", err)
+	} else {
+		mainModule.Path = modf.Module.Mod.Path
+	}
+	// process go.mod file to find/correct the dependency version.
+	mod = applyGoModule(modf, mod)
+	mod, err = resolveVanityGoModule(ctx, mod, http.DefaultClient)
+	if err != nil {
+		return nil, fmt.Errorf("failed resolving vanity URL: %w", err)
+	}
+	mod = resolveLocalFile(mod, mainModule)
+	// remove the version suffix
+	mod.Path = versionSuffixRE.ReplaceAllString(mod.Path, "")
+	return fetchGoDependencyFile(ctx, mod, arg.client)
+}
+
+func fetchGoDependencyFile(ctx context.Context, module goModuleFile, client VCSClient) (*vcsv1.GetFileResponse, error) {
+	switch {
+	case strings.HasPrefix(module.Path, "github.com/"):
+		return fetchGithubModuleFile(ctx, module, client)
+	case strings.HasPrefix(module.Path, "go.googlesource.com/"):
+		return fetchGoogleSourceDependencyFile(ctx, module, http.DefaultClient)
+	}
+	return nil, nil
+}
+
+func fetchGithubModuleFile(ctx context.Context, mod goModuleFile, client VCSClient) (*vcsv1.GetFileResponse, error) {
+	// todo: what if this is not a github repo?
+	// 		VSClient should support querying multiple repo providers.
+	githubFile, err := parseGithubRepo(mod)
+	if err != nil {
+		return nil, err
+	}
+	content, err := client.GetFile(ctx, githubFile.Owner, githubFile.Repo, githubFile.Path, githubFile.Ref)
+	if err != nil {
+		return nil, err
+	}
+	return newFileResponse(content.Content, content.URL)
+}
+
+type GitHubFile struct {
+	Owner, Repo, Ref, Path string
+}
+
+func parseGithubRepo(mod goModuleFile) (GitHubFile, error) {
+	if !strings.HasPrefix(mod.Path, "github.com/") {
+		return GitHubFile{}, fmt.Errorf("invalid github URL: %s", mod.Path)
+	}
+	version, err := refFromVersion(mod.Version.Version)
+	if err != nil {
+		return GitHubFile{}, err
+	}
+	if version == "" {
+		version = "main"
+	}
+	parts := strings.Split(mod.Path, "/")
+	if len(parts) < 3 {
+		return GitHubFile{}, fmt.Errorf("invalid github URL: %s", mod.Path)
+	}
+	return GitHubFile{
+		Owner: parts[1],
+		Repo:  parts[2],
+		Ref:   version,
+		Path:  filepath.Join(strings.Join(parts[3:], "/"), mod.filePath),
+	}, nil
+}
+
+func refFromVersion(version string) (string, error) {
+	if module.IsPseudoVersion(version) {
+		rev, err := module.PseudoVersionRev(version)
+		if err != nil {
+			return "", err
+		}
+		return rev, nil
+	}
+	if sem := semver.Canonical(version); sem != "" {
+		return sem, nil
+	}
+
+	return version, nil
+}
+
+// curl https://go.googlesource.com/oauth2/+/4ce7bbb2ffdc6daed06e2ec28916fd08d96bc3ea/amazon/amazon.go
+// curl https://go.googlesource.com/oauth2/+/4ce7bbb2f/amazon/amazon.go\?format\=TEXT
+// curl https://go.googlesource.com/oauth2/+/v0.16.0/amazon/amazon.go\?format\=TEXT
+func fetchGoogleSourceDependencyFile(ctx context.Context, mod goModuleFile, httpClient *http.Client) (*vcsv1.GetFileResponse, error) {
+	parts := strings.Split(strings.Trim(mod.Path, "/"), "/")
+	if len(parts) < 2 {
+		return nil, fmt.Errorf("invalid google source path: %s", mod.Path)
+	}
+	projectName := parts[1]
+	filePath := mod.filePath
+	extraPath := strings.Join(parts[2:], "/")
+	if extraPath != "" {
+		filePath = filepath.Join(extraPath, filePath)
+	}
+	version, err := refFromVersion(mod.Version.Version)
+	if err != nil {
+		return nil, err
+	}
+	if version == "" {
+		version = "master"
+	}
+	url := fmt.Sprintf("https://go.googlesource.com/%s/+/%s/%s?format=TEXT", projectName, version, filePath)
+	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	resp, err := httpClient.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != http.StatusOK {
+		return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("failed to fetch go lib %s: %s", mod.Path, resp.Status))
+	}
+	content, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+	decoded, err := base64.StdEncoding.DecodeString(string(content))
+	if err != nil {
+		return nil, err
+	}
+	return newFileResponse(string(decoded), url)
+}
+
+func resolveLocalFile(module goModuleFile, mainModule module.Version) goModuleFile {
+	if !strings.HasPrefix(module.Path, ".") {
+		return module
+	}
+	module.Version.Version = mainModule.Version
+	module.Path = filepath.Join(mainModule.Path, module.Path)
+	return module
+}
+
+// normally go-import meta tag should be used to resolve vanity.
+//
+//	curl -v 'https://google.golang.org/protobuf?go-get=1'
+//
+// careful follow redirect see: curl -L -v 'connectrpc.com/connect?go-get=1'
+// if go-source meta tag is present prefer it over go-import.
+// see https://go.dev/ref/mod#vcs-find
+func resolveVanityGoModule(ctx context.Context, module goModuleFile, httpClient *http.Client) (goModuleFile, error) {
+	if strings.Contains(module.Path, "github.com/") {
+		return module, nil
+	}
+	// see https://labix.org/gopkg.in
+	// gopkg.in/pkg.v3      → github.com/go-pkg/pkg (branch/tag v3, v3.N, or v3.N.M)
+	// gopkg.in/user/pkg.v3 → github.com/user/pkg   (branch/tag v3, v3.N, or v3.N.M)
+	if strings.Contains(module.Path, "gopkg.in/") {
+		parts := strings.Split(module.Path, "/")
+		if len(parts) < 2 {
+			return goModuleFile{}, fmt.Errorf("invalid gopkg.in path: %s", module.Path)
+		}
+		packageNameParts := strings.Split(parts[len(parts)-1], ".")
+		if len(packageNameParts) < 2 || packageNameParts[0] == "" {
+			return goModuleFile{}, fmt.Errorf("invalid gopkg.in path: %s", module.Path)
+		}
+		switch len(parts) {
+		case 2:
+			module.Path = fmt.Sprintf("github.com/go-%s/%s", packageNameParts[0], packageNameParts[0])
+		case 3:
+			module.Path = fmt.Sprintf("github.com/%s/%s", parts[1], packageNameParts[0])
+		default:
+			return goModuleFile{}, fmt.Errorf("invalid gopkg.in path: %s", module.Path)
+		}
+		return module, nil
+	}
+	req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://%s?go-get=1", strings.TrimRight(module.Path, "/")), nil)
+	if err != nil {
+		return goModuleFile{}, err
+	}
+	resp, err := httpClient.Do(req)
+	if err != nil {
+		return goModuleFile{}, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != http.StatusOK {
+		return goModuleFile{}, connect.NewError(connect.CodeNotFound, fmt.Errorf("failed to fetch go lib %s: %s", module.Path, resp.Status))
+	}
+
+	// look for go-source meta tag first
+	doc, err := goquery.NewDocumentFromReader(resp.Body)
+	if err != nil {
+		return goModuleFile{}, err
+	}
+	var found bool
+	// 
+	// 
+	doc.Find("meta[name='go-source']").Each(func(i int, s *goquery.Selection) {
+		content, ok := s.Attr("content")
+		if !ok {
+			return
+		}
+		content = cleanWhiteSpace(content)
+		parts := strings.Split(content, " ")
+		if len(parts) < 2 {
+			return
+		}
+
+		// prefer github if available in go-source
+		if !found && strings.Contains(module.Path, parts[0]) && strings.Contains(parts[1], "github.com/") {
+			found = true
+			subPath := strings.Replace(module.Path, parts[0], "", 1)
+			module.Path = filepath.Join(strings.TrimRight(
+				strings.TrimPrefix(
+					strings.TrimPrefix(parts[1], "https://"),
+					"http://",
+				), "/"),
+				subPath,
+			)
+
+		}
+	})
+	if found {
+		return module, nil
+	}
+	// 
+	// 
+	// 
+	doc.Find("meta[name='go-import']").Each(func(i int, s *goquery.Selection) {
+		content, ok := s.Attr("content")
+		if !ok {
+			return
+		}
+		parts := strings.Split(cleanWhiteSpace(content), " ")
+		if len(parts) < 3 {
+			return
+		}
+
+		if !found && strings.Contains(module.Path, parts[0]) && parts[1] == "git" {
+			found = true
+			subPath := strings.Replace(module.Path, parts[0], "", 1)
+			module.Path = filepath.Join(strings.TrimRight(
+				strings.TrimPrefix(
+					strings.TrimPrefix(parts[2], "https://"),
+					"http://",
+				), "/"),
+				subPath,
+			)
+
+		}
+	})
+	return module, nil
+}
+
+func cleanWhiteSpace(s string) string {
+	space := false
+	return strings.Map(func(r rune) rune {
+		if r == '\n' || r == '\t' {
+			return -1
+		}
+		if r == ' ' && space {
+			return -1
+		}
+		space = r == ' '
+		return r
+	}, s)
+}
+
+// todo should move to golang package. and add tests
+func applyGoModule(modf *modfile.File, module goModuleFile) goModuleFile {
+	if modf == nil {
+		return module
+	}
+	for _, req := range modf.Require {
+		if req.Mod.Path == module.Path {
+			module.Version.Version = req.Mod.Version
+		}
+	}
+	for _, req := range modf.Replace {
+		if req.Old.Path == module.Path {
+			module.Path = req.New.Path
+			module.Version.Version = req.New.Version
+		}
+	}
+	return module
+}
+
+type goModuleFile struct {
+	module.Version
+	filePath string
+}
+
+func (m goModuleFile) String() string {
+	return fmt.Sprintf("%s@%s", m.Path, m.Version)
+}
+
+func parseGoModuleFilePath(path string) (goModuleFile, bool) {
+	parts := strings.Split(path, "@v")
+	if len(parts) != 2 {
+		return goModuleFile{}, false
+	}
+	first := strings.Index(parts[1], "/")
+	if first < 0 {
+		return goModuleFile{}, false
+	}
+	filePath := parts[1][first+1:]
+	modulePath := parts[0]
+	// searching for the first domain name
+	domainParts := strings.Split(modulePath, "/")
+	for i, part := range domainParts {
+		if strings.Contains(part, ".") {
+			return goModuleFile{
+				Version: module.Version{
+					Path:    strings.Join(domainParts[i:], "/"),
+					Version: "v" + parts[1][:first],
+				},
+				filePath: filePath,
+			}, true
+		}
+	}
+	return goModuleFile{}, false
+}
+
+func fetchGoMod(ctx context.Context, arg fileFinder) (*modfile.File, error) {
+	content, err := arg.client.GetFile(ctx, arg.repo.GetOwnerName(), arg.repo.GetRepoName(), "go.mod", arg.ref)
+	if err != nil {
+		return nil, err
+	}
+	return modfile.Parse("go.mod", []byte(content.Content), nil)
+}
+
+// findGoStdFile returns the file content if the given path is a standard go package.
+func findGoStdFile(ctx context.Context, arg fileFinder) (*vcsv1.GetFileResponse, error) {
+	if len(arg.path) == 0 {
+		return nil, nil
+	}
+	path := strings.TrimSuffix(arg.path, "/usr/local/go/src/")
+	path = strings.TrimSuffix(path, "$GOROOT/src/")
+	fileName := filepath.Base(arg.path)
+	packageName := strings.TrimSuffix(path, "/"+fileName)
+
+	// Todo: Send more metadata from SDK to fetch the correct version of Go std packages.
+	// For this we should use arbitrary k/v metadata in our request so that we don't need to change the API.
+	// I thought about using go.mod go version but it's a min and doesn't guarantee it hasn't been built with a higher version.
+	// Alternatively we could interpret the build system and use the version of the go compiler.
+	ref := "master"
+	isVendor := strings.HasPrefix(packageName, "vendor/")
+
+	if _, isStd := golang.StandardPackages[packageName]; !isVendor && !isStd {
+		return nil, nil
+	}
+	return fetchGoStd(ctx, path, ref)
+}
+
+// todo should move to golang package.
+func fetchGoStd(ctx context.Context, path, ref string) (*vcsv1.GetFileResponse, error) {
+	// https://raw.githubusercontent.com/golang/go/master/src/archive/tar/format.go
+	url := fmt.Sprintf(`https://raw.githubusercontent.com/golang/go/%s/src/%s`, ref, path)
+	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
+	if err != nil {
+		return nil, err
+	}
+	resp, err := http.DefaultClient.Do(req) // todo: use a custom client with timeout
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	if resp.StatusCode != http.StatusOK {
+		return nil, connect.NewError(connect.CodeNotFound, fmt.Errorf("failed to fetch go lib %s: %s", url, resp.Status))
+	}
+	content, err := io.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+
+	return newFileResponse(string(content), url)
+}
diff --git a/pkg/querier/vcs_test.go b/pkg/querier/vcs_test.go
new file mode 100644
index 0000000000..8792c870e5
--- /dev/null
+++ b/pkg/querier/vcs_test.go
@@ -0,0 +1,587 @@
+package querier
+
+import (
+	"context"
+	"encoding/base64"
+	"net/http"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+	"golang.org/x/mod/modfile"
+	"golang.org/x/mod/module"
+)
+
+func TestResolveSymbolPath(t *testing.T) {
+	// Loki
+	// $GOROOT/src/unicode/utf8/utf8.go
+	// $GOROOT/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go
+	// $GOROOT/src/vendor/golang.org/x/crypto/cryptobyte/builder.go
+	// $GOROOT/src/vendor/golang.org/x/crypto/cryptobyte/string.go
+	// $GOROOT/src/vendor/golang.org/x/net/dns/dnsmessage/message.go
+	// $GOROOT/src/vendor/golang.org/x/net/http/httpguts/httplex.go
+	// $GOROOT/src/vendor/golang.org/x/net/http/httpproxy/proxy.go
+	// $GOROOT/src/vendor/golang.org/x/net/http2/hpack/encode.go
+	// $GOROOT/src/vendor/golang.org/x/net/http2/hpack/hpack.go
+	// $GOROOT/src/vendor/golang.org/x/net/http2/hpack/huffman.go
+	// $GOROOT/src/vendor/golang.org/x/net/http2/hpack/tables.go
+	// /src/enterprise-logs/pkg/enterprise/loki/labelaccess/codec.go
+	// /src/enterprise-logs/pkg/enterprise/loki/labelaccess/grpc.go
+	// /src/enterprise-logs/pkg/enterprise/loki/labelaccess/middleware.go
+	// /src/enterprise-logs/pkg/enterprise/loki/labelaccess/propagation.go
+	// /src/enterprise-logs/pkg/enterprise/loki/labelaccess/request_chunk_filterer.go
+	// /src/enterprise-logs/vendor/github.com/DmitriyVTitov/size/size.go
+
+	// Mimir
+	// $GOROOT/src/vendor/golang.org/x/crypto/hkdf/hkdf.go
+	// $GOROOT/src/vendor/golang.org/x/net/dns/dnsmessage/message.go
+	// $GOROOT/src/vendor/golang.org/x/net/http/httpguts/httplex.go
+	// /drone/src/pkg/enterprise/admin/usage/quota.go
+	// /drone/src/pkg/enterprise/mimir/instrumentation/node/diskstats.go
+	// /drone/src/pkg/enterprise/mimir/instrumentation/node/filesystem.go
+	// /drone/src/pkg/enterprise/mimir/instrumentation/node/node.go
+	// /drone/src/pkg/enterprise/mimir/instrumentation/node/vmstat.go
+	// /drone/src/pkg/enterprise/mimir/version/version.go
+	// /drone/src/vendor/cloud.google.com/go/internal/retry.go
+	// /drone/src/vendor/cloud.google.com/go/internal/trace/trace.go
+	// /drone/src/vendor/cloud.google.com/go/storage/acl.go
+	// /drone/src/vendor/cloud.google.com/go/storage/bucket.go
+
+	// Pyroscope prod
+	// fmt/errors.go
+	// fmt/format.go
+	// fmt/print.go
+	// fmt/scan.go
+	// github.com/armon/go-metrics@v0.4.1/metrics.go
+	// github.com/armon/go-metrics@v0.4.1/prometheus/prometheus.go
+	// github.com/armon/go-metrics@v0.4.1/start.go
+	// github.com/grafana/pyroscope-go/godeltaprof@v0.1.6/internal/pprof/protobuf.go
+	// github.com/grafana/pyroscope/api/gen/proto/go/google/v1/profile.pb.go
+	// github.com/grafana/pyroscope/api/gen/proto/go/google/v1/profile_vtproto.pb.go
+
+	// Tempo
+	// /drone/src/cmd/tempo/app/app.go
+	// /drone/src/cmd/tempo/app/config.go
+	// /drone/src/modules/distributor/distributor.go
+	// /drone/src/modules/distributor/forwarder.go
+	// /drone/src/tempodb/backend/gcs/gcs.go
+	// /drone/src/tempodb/backend/instrumentation/backend_transports.go
+	// /drone/src/vendor/cloud.google.com/go/internal/retry.go
+	// /drone/src/vendor/github.com/go-logfmt/logfmt/jsonstring.go
+	// /drone/src/vendor/github.com/gogo/protobuf/proto/clone.go
+	// /drone/src/vendor/google.golang.org/protobuf/proto/merge.go
+	// /usr/local/go/src/bufio/bufio.go
+	// /usr/local/go/src/bufio/scan.go
+	// /usr/local/go/src/bytes/buffer.go
+
+	// kine
+	// /go/pkg/mod/github.com/cespare/xxhash/v2@v2.2.0/xxhash.go
+	// /go/pkg/mod/github.com/cespare/xxhash/v2@v2.2.0/xxhash_unsafe.go
+	// /go/pkg/mod/github.com/golang/protobuf@v1.5.3/proto/proto.go
+	// /go/pkg/mod/github.com/golang/protobuf@v1.5.3/proto/wire.go
+	// /go/src/github.com/k3s-io/kine/pkg/broadcaster/broadcaster.go
+	// /go/src/github.com/k3s-io/kine/pkg/drivers/cockroach/cockroach.go
+	// /go/src/github.com/k3s-io/kine/pkg/drivers/generic/generic.go
+	// /usr/local/go/src/bufio/bufio.go
+	// /usr/local/go/src/bufio/scan.go
+	// /usr/local/go/src/bytes/buffer.go
+	// /usr/local/go/src/bytes/bytes.go
+
+	// grafana
+	// /drone/src/pkg/web/router.go
+	// /drone/src/pkg/web/tree.go
+	// /opt/drone/gomodcache/github.com/!f!zambia/eagle@v0.0.2/eagle.go
+	// /opt/drone/gomodcache/github.com/centrifugal/centrifuge@v0.29.1/broker_memory.go
+	// /opt/drone/gomodcache/github.com/centrifugal/centrifuge@v0.29.1/hub.go
+	// /usr/local/go/src/crypto/internal/edwards25519/field/fe_amd64.s
+	// /usr/local/go/src/crypto/rsa/pss.go
+	// /usr/local/go/src/crypto/rsa/rsa.go
+	// vendor/golang.org/x/crypto/cryptobyte/asn1.go
+	// vendor/golang.org/x/crypto/cryptobyte/builder.go
+	// vendor/golang.org/x/crypto/cryptobyte/string.go
+	// vendor/golang.org/x/crypto/hkdf/hkdf.go
+	// vendor/golang.org/x/net/dns/dnsmessage/message.go
+	// vendor/golang.org/x/net/http/httpguts/httplex.go
+	// vendor/golang.org/x/net/http2/hpack/encode.go
+	// vendor/golang.org/x/net/http2/hpack/hpack.go
+	// vendor/golang.org/x/net/http2/hpack/huffman.go
+	// vendor/golang.org/x/net/http2/hpack/tables.go
+
+	for _, tt := range []struct {
+		name     string
+		input    string
+		expected string
+	}{
+		{
+			name:     "github",
+			input:    "github.com/grafana/grafana/pkg/querier/vcs.go",
+			expected: "github.com/grafana/grafana/pkg/querier/vcs.go",
+		},
+	} {
+		t.Run(tt.name, func(t *testing.T) {
+			// actual := resolveSymbolPath(tt.input)
+			// if actual != tt.expected {
+			// 	t.Errorf("expected %s, got %s", tt.expected, actual)
+			// }
+		})
+	}
+}
+
+func Test_FindGoStdFile(t *testing.T) {
+	// /usr/local/go/src/bufio/bufio.go
+	// $GOROOT/src/unicode/utf8/utf8.go
+	// fmt/scan.go
+	// $GOROOT/src/vendor/golang.org/x/crypto/cryptobyte/asn1.go
+	// /usr/local/go/src/vendor/golang.org/x/net/http2/hpack/tables.go
+
+	f, err := findGoStdFile(context.Background(), fileFinder{
+		path: "/usr/local/go/src/bufio/bufio.go",
+	})
+	require.NoError(t, err)
+	require.NotNil(t, f)
+}
+
+func Test_FindGoDependencyFile(t *testing.T) {
+	// github.com/armon/go-metrics@v0.4.1/metrics.go
+	// github.com/grafana/pyroscope-go/godeltaprof@v0.1.6/internal/pprof/protobuf.go
+	// /go/pkg/mod/github.com/golang/protobuf@v1.5.3/proto/wire.go
+	// /drone/src/vendor/cloud.google.com/go/storage/bucket.go
+	// /src/enterprise-logs/vendor/github.com/DmitriyVTitov/size/size.go
+	// /drone/src/vendor/google.golang.org/protobuf/proto/merge.go
+
+	f, err := findGoDependencyFile(context.Background(), fileFinder{
+		path: "/drone/src/vendor/cloud.google.com/go/storage/bucket.go",
+	})
+	require.NoError(t, err)
+	require.NotNil(t, f)
+}
+
+func Test_ParseModulePath(t *testing.T) {
+	for _, tt := range []struct {
+		input      string
+		expectedOk bool
+		expected   goModuleFile
+	}{
+		{
+			"github.com/armon/go-metrics@v0.4.1/metrics.go",
+			true,
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/armon/go-metrics",
+					Version: "v0.4.1",
+				},
+				filePath: "metrics.go",
+			},
+		},
+		{
+			"/go/pkg/mod/github.com/golang/protobuf@v1.5.3/proto/wire.go",
+			true,
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/golang/protobuf",
+					Version: "v1.5.3",
+				},
+				filePath: "proto/wire.go",
+			},
+		},
+		{
+			"/go/pkg/mod/golang.org/x/net@v1.5.3/http2/hpack/tables.go",
+			true,
+			goModuleFile{
+				Version: module.Version{
+					Path:    "golang.org/x/net",
+					Version: "v1.5.3",
+				},
+				filePath: "http2/hpack/tables.go",
+			},
+		},
+	} {
+		t.Run(tt.input, func(t *testing.T) {
+			mod, ok := parseGoModuleFilePath(tt.input)
+			require.Equal(t, tt.expectedOk, ok)
+			require.Equal(t, tt.expected, mod)
+		})
+	}
+}
+
+func Test_ApplyGoModule(t *testing.T) {
+	modf, err := modfile.Parse(
+		"go.mod",
+		[]byte(`
+module github.com/grafana/pyroscope
+
+go 1.16
+
+require (
+	github.com/grafana/grafana-plugin-sdk-go v0.3.0
+	connectrpc.com/connect v1.14.0
+	connectrpc.com/grpchealth v1.3.0
+)
+
+require (
+	github.com/!azure/go-autorest v0.11.16-0.20210324193631-8d5b6a9c4f9e // indirect
+	golang.org/x/crypto v0.0.0-20210322153248-8c942d7d6b5c // indirect
+	golang.org/x/term v0.15.0 // indirect
+	golang.org/x/tools v0.15.0 // indirect
+	google.golang.org/api v0.152.0 // indirect
+	k8s.io/utils v0.0.0-20230711102312-30195339c3c7 // indirect
+)
+
+replace (
+	github.com/thanos-io/objstore => github.com/grafana/objstore v0.0.0-20231121154247-84f91ea90e72
+	gopkg.in/yaml.v3 => github.com/colega/go-yaml-yaml v0.0.0-20220720105220-255a8d16d094
+	github.com/grafana/pyroscope/api => ./api
+)
+		`), nil)
+	require.NoError(t, err)
+	for _, tt := range []struct {
+		in       goModuleFile
+		expected goModuleFile
+	}{
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/grafana-plugin-sdk-go",
+					Version: "v0.4.0",
+				},
+				filePath: "plugin.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/grafana-plugin-sdk-go",
+					Version: "v0.3.0",
+				},
+				filePath: "plugin.go",
+			},
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/thanos-io/objstore",
+					Version: "v0.4.0",
+				},
+				filePath: "client.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/objstore",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/pyroscope/api",
+					Version: "v0.4.0",
+				},
+				filePath: "foo_gen.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "./api",
+					// todo the version should be set to the current version of the module
+				},
+				filePath: "foo_gen.go",
+			},
+		},
+	} {
+		t.Run(tt.in.String(), func(t *testing.T) {
+			actual := applyGoModule(modf, tt.in)
+			require.Equal(t, tt.expected, actual)
+		})
+	}
+}
+
+func Test_ParseGithubRepo(t *testing.T) {
+	for _, tt := range []struct {
+		input       goModuleFile
+		expected    GitHubFile
+		expectedErr bool
+	}{
+		{
+			goModuleFile{},
+			GitHubFile{},
+			true,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/grafana/grafana-plugin-sdk-go",
+				},
+			},
+			GitHubFile{
+				Owner: "grafana",
+				Repo:  "grafana-plugin-sdk-go",
+				Ref:   "main",
+			},
+			false,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/grafana-plugin-sdk-go",
+					Version: "v0.3.0",
+				},
+				filePath: "plugin.go",
+			},
+			GitHubFile{
+				Owner: "grafana",
+				Repo:  "grafana-plugin-sdk-go",
+				Ref:   "v0.3.0",
+				Path:  "plugin.go",
+			},
+			false,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/grafana-plugin-sdk-go/bar",
+					Version: "v0.3.0-rc1",
+				},
+				filePath: "plugin.go",
+			},
+			GitHubFile{
+				Owner: "grafana",
+				Repo:  "grafana-plugin-sdk-go",
+				Ref:   "v0.3.0-rc1",
+				Path:  "bar/plugin.go",
+			},
+			false,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/grafana/grafana-plugin-sdk-go/bar",
+					Version: "v0.14.1-0.20230710114240-c316eb95ae5b",
+				},
+				filePath: "plugin.go",
+			},
+			GitHubFile{
+				Owner: "grafana",
+				Repo:  "grafana-plugin-sdk-go",
+				Ref:   "c316eb95ae5b",
+				Path:  "bar/plugin.go",
+			},
+			false,
+		},
+	} {
+		t.Run(tt.input.String(), func(t *testing.T) {
+			actual, err := parseGithubRepo(tt.input)
+			if tt.expectedErr {
+				require.Error(t, err)
+				return
+			}
+			require.NoError(t, err)
+			require.Equal(t, tt.expected, actual)
+		})
+	}
+}
+
+func Test_refFromVersion(t *testing.T) {
+	for _, tt := range []struct {
+		input    string
+		expected string
+	}{
+		{
+			"v0.3.0",
+			"v0.3.0",
+		},
+		{
+			"v0.3.0-rc1",
+			"v0.3.0-rc1",
+		},
+		{
+			"v0.3.0-0.20230710114240-c316eb95ae5b",
+			"c316eb95ae5b",
+		},
+		{
+			"v2.2.6+incompatible",
+			"v2.2.6",
+		},
+	} {
+		t.Run(tt.input, func(t *testing.T) {
+			actual, err := refFromVersion(tt.input)
+			require.NoError(t, err)
+			require.Equal(t, tt.expected, actual)
+		})
+	}
+}
+
+func Test_ResolveVanityGoModule(t *testing.T) {
+	for _, tt := range []struct {
+		in          goModuleFile
+		expected    goModuleFile
+		expectedErr error
+	}{
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "gopkg.in/yaml.v3",
+				},
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/go-yaml/yaml",
+				},
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "gopkg.in/alecthomas/kingpin.v2",
+				},
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/alecthomas/kingpin",
+				},
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "golang.org/x/oauth2",
+				},
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "go.googlesource.com/oauth2",
+				},
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "k8s.io/utils",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/kubernetes/utils",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "cloud.google.com/go/storage",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/googleapis/google-cloud-go/storage",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/oklog/ulid",
+				},
+				filePath: "foo.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/oklog/ulid",
+				},
+				filePath: "foo.go",
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "google.golang.org/genproto/googleapis/api",
+				},
+				filePath: "foo.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/googleapis/go-genproto/googleapis/api",
+				},
+				filePath: "foo.go",
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path:    "google.golang.org/protobuf",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path:    "github.com/protocolbuffers/protobuf-go",
+					Version: "v0.0.0-20231121154247-84f91ea90e72",
+				},
+				filePath: "client.go",
+			},
+			nil,
+		},
+		{
+			goModuleFile{
+				Version: module.Version{
+					Path: "connectrpc.com/grpchealth",
+				},
+				filePath: "client.go",
+			},
+			goModuleFile{
+				Version: module.Version{
+					Path: "github.com/connectrpc/grpchealth-go",
+				},
+				filePath: "client.go",
+			},
+			nil,
+		},
+	} {
+		tt := tt
+		t.Run(tt.in.String(), func(t *testing.T) {
+			t.Parallel()
+			actual, err := resolveVanityGoModule(context.Background(), tt.in, http.DefaultClient)
+			require.Equal(t, tt.expectedErr, err)
+			require.Equal(t, tt.expected, actual)
+		})
+	}
+}
+
+func Test_FetchGoogleSourceDependencyFile(t *testing.T) {
+	content, err := fetchGoogleSourceDependencyFile(context.Background(), goModuleFile{
+		Version: module.Version{
+			Path:    "go.googlesource.com/oauth2",
+			Version: "v0.16.0",
+		},
+		filePath: "amazon/amazon.go",
+	}, http.DefaultClient)
+	require.NoError(t, err)
+	decoded, err := base64.StdEncoding.DecodeString(content.Content)
+	require.NoError(t, err)
+	require.Contains(t, string(decoded), "package amazon")
+	require.Equal(t, "https://go.googlesource.com/oauth2/+/v0.16.0/amazon/amazon.go?format=TEXT", content.URL)
+}
+
+func Test_FetchGoStd(t *testing.T) {
+	file, err := fetchGoStd(context.Background(), "bufio/bufio.go", "master")
+	require.NoError(t, err)
+	fileContent, err := base64.StdEncoding.DecodeString(file.Content)
+	require.NoError(t, err)
+
+	// todo mock
+	require.Contains(t, string(fileContent), "// Copyright 2009 The Go Authors.")
+	require.Equal(t, `https://raw.githubusercontent.com/golang/go/master/src/bufio/bufio.go`, file.URL)
+}
diff --git a/pkg/util/connectgrpc/connectgrpc.go b/pkg/util/connectgrpc/connectgrpc.go
index 838956d7bf..c84f93895f 100644
--- a/pkg/util/connectgrpc/connectgrpc.go
+++ b/pkg/util/connectgrpc/connectgrpc.go
@@ -165,6 +165,11 @@ func decodeResponse[Resp any](r *httpgrpc.HTTPResponse) (*connect.Response[Resp]
 		return nil, err
 	}
 	resp := &connect.Response[Resp]{Msg: new(Resp)}
+	for _, h := range r.Headers {
+		for _, v := range h.Values {
+			resp.Header().Add(h.Key, v)
+		}
+	}
 	if err := proto.Unmarshal(r.Body, resp.Any().(proto.Message)); err != nil {
 		return nil, err
 	}
@@ -353,5 +358,4 @@ func (g *httpgrpcClient) Do(req *http.Request) (*http.Response, error) {
 		StatusCode:    int(resp.Code),
 		Header:        httpgrpcHeaderToConnectHeader(resp.Headers),
 	}, nil
-
 }

From 996394974f65e9b35d2fd282441d7cc0efc52f0c Mon Sep 17 00:00:00 2001
From: Cyril Tovena 
Date: Thu, 25 Jan 2024 18:18:02 +0100
Subject: [PATCH 02/31] Fixes temp test

---
 pkg/querier/vcs.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pkg/querier/vcs.go b/pkg/querier/vcs.go
index 3bbf4254aa..f9655d9312 100644
--- a/pkg/querier/vcs.go
+++ b/pkg/querier/vcs.go
@@ -92,7 +92,7 @@ func (q *Querier) GetFile(ctx context.Context, req *connect.Request[vcsv1.GetFil
 	}
 	// todo: we can support multiple provider: bitbucket, gitlab, etc.
 	client, err := NewGithubClient(ctx, cookie)
-	if err == nil {
+	if err != nil {
 		// todo should clear cookie this doesn't work yet.
 		cookie.MaxAge = -1
 		err := connect.NewError(

From 017f4006af018c7dac31824a4585cc863ac17fa8 Mon Sep 17 00:00:00 2001
From: Cyril Tovena 
Date: Fri, 26 Jan 2024 12:01:41 +0100
Subject: [PATCH 03/31] Fixes cookie deletion and use external encryption

---
 ebpf/go.mod                         | 13 ++---
 ebpf/go.sum                         | 26 +++++-----
 go.mod                              |  4 +-
 go.sum                              |  4 +-
 go.work.sum                         | 51 ++++++++++++++++--
 pkg/api/vcs.html                    |  2 -
 pkg/querier/cookie.go               | 80 +++++------------------------
 pkg/querier/cookie_test.go          |  4 +-
 pkg/querier/vcs.go                  |  7 ++-
 pkg/util/connectgrpc/connectgrpc.go |  8 ++-
 10 files changed, 99 insertions(+), 100 deletions(-)

diff --git a/ebpf/go.mod b/ebpf/go.mod
index dc01c82d25..694812ad25 100644
--- a/ebpf/go.mod
+++ b/ebpf/go.mod
@@ -8,17 +8,18 @@ require (
 	github.com/cespare/xxhash/v2 v2.2.0
 	github.com/cilium/ebpf v0.11.0
 	github.com/go-kit/log v0.2.1
-	github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98
+	github.com/google/pprof v0.0.0-20231205033806-a5a03c77bf08
 	github.com/grafana/pyroscope/api v0.2.0
 	github.com/hashicorp/golang-lru/v2 v2.0.5
 	github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab
-	github.com/klauspost/compress v1.17.3
+	github.com/klauspost/compress v1.17.4
 	github.com/pkg/errors v0.9.1
 	github.com/prometheus/client_golang v1.17.0
-	github.com/prometheus/common v0.44.0
+	github.com/prometheus/common v0.45.0
+	github.com/prometheus/prometheus v0.49.1
 	github.com/samber/lo v1.38.1
 	github.com/stretchr/testify v1.8.4
-	golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
+	golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb
 	golang.org/x/sys v0.15.0
 )
 
@@ -28,10 +29,10 @@ require (
 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 	github.com/go-logfmt/logfmt v0.6.0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
-	github.com/google/go-cmp v0.6.0 // indirect
 	github.com/gorilla/mux v1.8.0 // indirect
+	github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect
 	github.com/jpillora/backoff v1.0.0 // indirect
-	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+	github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
 	github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 	github.com/prometheus/client_model v0.5.0 // indirect
diff --git a/ebpf/go.sum b/ebpf/go.sum
index f2db3c3d41..d740a6203e 100644
--- a/ebpf/go.sum
+++ b/ebpf/go.sum
@@ -17,31 +17,32 @@ github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
 github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
 github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
 github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
-github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
-github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
+github.com/google/pprof v0.0.0-20231205033806-a5a03c77bf08 h1:PxlBVtIFHR/mtWk2i0gTEdCz+jBnqiuHNSki0epDbVs=
+github.com/google/pprof v0.0.0-20231205033806-a5a03c77bf08/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
 github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/grafana/pyroscope/api v0.2.0 h1:TzOxL0s6SiaLEy944ZAKgHcx/JDRJXu4O8ObwkqR6p4=
 github.com/grafana/pyroscope/api v0.2.0/go.mod h1:nhH+xai9cYFgs6lMy/+L0pKj0d5yCMwji/QAiQFCP+U=
+github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww=
+github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A=
 github.com/hashicorp/golang-lru/v2 v2.0.5 h1:wW7h1TG88eUIJ2i69gaE3uNVtEPIagzhGvHgwfx2Vm4=
 github.com/hashicorp/golang-lru/v2 v2.0.5/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
 github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
 github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
 github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
 github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
-github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
-github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
-github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
+github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -52,10 +53,12 @@ github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1
 github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
 github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
 github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
-github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
-github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
+github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
+github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
 github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
 github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
+github.com/prometheus/prometheus v0.49.1 h1:90mDvjrFnca2m+0qPSIDr3y7iHPTAagOAElz7j+HtGk=
+github.com/prometheus/prometheus v0.49.1/go.mod h1:aDogiyqmv3aBIWDb5z5Sdcxuuf2BOfiJwOIm9JGpMnI=
 github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
 github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
 github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
@@ -63,14 +66,13 @@ github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXn
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
-golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
+golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
+golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
 golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
 golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
 golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/go.mod b/go.mod
index bcb9bbdfb6..d0674ec0c7 100644
--- a/go.mod
+++ b/go.mod
@@ -43,6 +43,7 @@ require (
 	github.com/mattn/go-isatty v0.0.19
 	github.com/minio/minio-go/v7 v7.0.61
 	github.com/mitchellh/go-wordwrap v1.0.1
+	github.com/oauth2-proxy/oauth2-proxy/v7 v7.5.1
 	github.com/oklog/ulid v1.3.1
 	github.com/olekukonko/tablewriter v0.0.5
 	github.com/onsi/ginkgo/v2 v2.11.0
@@ -66,6 +67,7 @@ require (
 	go.uber.org/atomic v1.11.0
 	go.uber.org/goleak v1.2.1
 	golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
+	golang.org/x/mod v0.14.0
 	golang.org/x/net v0.19.0
 	golang.org/x/oauth2 v0.15.0
 	golang.org/x/sync v0.5.0
@@ -123,7 +125,6 @@ require (
 	github.com/efficientgo/core v1.0.0-rc.2 // indirect
 	github.com/efficientgo/e2e v0.14.1-0.20230710114240-c316eb95ae5b // indirect
 	github.com/fsnotify/fsnotify v1.6.0 // indirect
-	github.com/github/go-pipe v1.0.2 // indirect
 	github.com/go-logfmt/logfmt v0.6.0 // indirect
 	github.com/go-logr/logr v1.2.4 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
@@ -213,7 +214,6 @@ require (
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.24.0 // indirect
 	golang.org/x/crypto v0.17.0 // indirect
-	golang.org/x/mod v0.14.0 // indirect
 	golang.org/x/term v0.15.0 // indirect
 	golang.org/x/tools v0.15.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
diff --git a/go.sum b/go.sum
index df5b63422b..204094bae9 100644
--- a/go.sum
+++ b/go.sum
@@ -204,8 +204,6 @@ github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
 github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
-github.com/github/go-pipe v1.0.2 h1:befTXflsc6ir/h9f6Q7QCDmfojoBswD1MfQrPhmmSoA=
-github.com/github/go-pipe v1.0.2/go.mod h1:/GvNLA516QlfGGMtfv4PC/5/CdzL9X4af/AJYhmLD54=
 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -588,6 +586,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW
 github.com/ncw/swift v1.0.53 h1:luHjjTNtekIEvHg5KdAFIBaH7bWfNkefwFnpDffSIks=
 github.com/ncw/swift v1.0.53/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/oauth2-proxy/oauth2-proxy/v7 v7.5.1 h1:zu+o5Zk0MJxeZTAKhgybBVm6GZwI6D8CD0WzCR8sESQ=
+github.com/oauth2-proxy/oauth2-proxy/v7 v7.5.1/go.mod h1:9TIUszoaT174lwycQ2XmG4h5KVEfgqmVL1SISuIqu04=
 github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
diff --git a/go.work.sum b/go.work.sum
index 8a9fbdd30e..7b51b25ed3 100644
--- a/go.work.sum
+++ b/go.work.sum
@@ -800,6 +800,8 @@ github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1 h1:oPdPEZFSbl7
 github.com/AzureAD/microsoft-authentication-library-for-go v0.8.1/go.mod h1:4qFor3D/HDsvBME35Xy9rwW9DecL+M2sNw1ybjPtwA0=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY=
 github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o=
+github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb h1:ZVN4Iat3runWOFLaBCDVU5a9X/XikSRBosye++6gojw=
+github.com/Bose/minisentinel v0.0.0-20200130220412-917c5a9223bb/go.mod h1:WsAABbY4HQBgd3mGuG4KMNTbHJCPvx9IVBHzysbknss=
 github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw=
 github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
@@ -883,6 +885,8 @@ github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZp
 github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
 github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI=
 github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
+github.com/alicebob/miniredis/v2 v2.23.0 h1:+lwAJYjvvdIVg6doFHuotFjueJ/7KY10xo/vm3X3Scw=
+github.com/alicebob/miniredis/v2 v2.23.0/go.mod h1:XNqvJdQJv5mSuVMc0ynneafpnL/zv52acZ6kqeS0t88=
 github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/antonmedv/expr v1.12.5 h1:Fq4okale9swwL3OeLLs9WD9H6GbgBLJyN/NUHRv+n0E=
@@ -959,6 +963,8 @@ github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NR
 github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
+github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
+github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
 github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
 github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
 github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
@@ -969,10 +975,14 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM
 github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
 github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
 github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
+github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
 github.com/boynux/squid-exporter v1.10.5-0.20230618153315-c1fae094e18e h1:C1vYe728vM2FpXaICJuDRt5zgGyRdMmUGYnVfM7WcLY=
 github.com/boynux/squid-exporter v1.10.5-0.20230618153315-c1fae094e18e/go.mod h1:8NpZERGK+R9DGuZqqsKfnf2qI/rh7yBT8End29IvgNA=
 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0=
 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
+github.com/bsm/redislock v0.9.1 h1:uTTZU82xg2PjI8X5T9PGcX/5k1FX3Id7bqkwy1As6c0=
+github.com/bsm/redislock v0.9.1/go.mod h1:ToFoB1xQbOJYG7e2ZBiPXotlhImqWgEa4+u/lLQ1nSc=
 github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
 github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
 github.com/burningalchemist/sql_exporter v0.0.0-20221222155641-2ff59aa75200 h1:1zECtssRshqhP8+DELKyWeg8rxaRC5OO72kJQhrJOE8=
@@ -1009,9 +1019,11 @@ github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmt
 github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
 github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
 github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
+github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
 github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
 github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
+github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
 github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY=
 github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=
 github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
@@ -1046,6 +1058,8 @@ github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvA
 github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
 github.com/containerd/ttrpc v1.1.0 h1:GbtyLRxb0gOLR0TYQWt3O6B0NvT8tMdorEHqIQo/lWI=
 github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
+github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw=
+github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM=
 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/cortexproject/cortex v1.11.0 h1:kx2iBVLZdu7Qjv7dbN4Ek2ax2nICsyoBL+DdEcAetOQ=
@@ -1309,6 +1323,8 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
 github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
 github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
 github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
@@ -1690,6 +1706,8 @@ github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfE
 github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0=
+github.com/justinas/alice v1.2.0 h1:+MHSA/vccVCF4Uq37S42jwlkvI2Xzl7zTPCN5BnZNVo=
+github.com/justinas/alice v1.2.0/go.mod h1:fN5HRH/reO/zrUflLfTN43t3vXvKzvZIENsNEe7i7qA=
 github.com/kardianos/service v1.2.0 h1:bGuZ/epo3vrt8IPC7mnKQolqFeYJb7Cs8Rk4PSOBB/g=
 github.com/kardianos/service v1.2.0/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
 github.com/karrick/godirwalk v1.10.3 h1:lOpSw2vJP0y5eLBW906QwKsUK/fe/QDyoqM5rnnuPDY=
@@ -1798,6 +1816,8 @@ github.com/mattn/goreman v0.3.5/go.mod h1:ahZuLhEo4pfYmf56GLNu/pjTxfeE389h43IHKM
 github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
 github.com/maxatome/go-testdeep v1.12.0 h1:Ql7Go8Tg0C1D/uMMX59LAoYK7LffeJQ6X2T04nTH68g=
 github.com/maxatome/go-testdeep v1.12.0/go.mod h1:lPZc/HAcJMP92l7yI6TRz1aZN5URwUBUAfUNvrclaNM=
+github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa h1:hI1uC2A3vJFjwvBn0G0a7QBRdBUp6Y048BtLAHRTKPo=
+github.com/mbland/hmacauth v0.0.0-20170912233209-44256dfd4bfa/go.mod h1:8vxFeeg++MqgCHwehSuwTlYCF0ALyDJbYJ1JsKi7v6s=
 github.com/mdlayher/ethtool v0.0.0-20221212131811-ba3b4bc2e02c h1:Y7LoKqIgD7vmqJ7+6ZVnADuwUO+m3tGXbf2lK0OvjIw=
 github.com/mdlayher/ethtool v0.0.0-20221212131811-ba3b4bc2e02c/go.mod h1:i0nPbE+sL2G3OtdIb9SXxW/T4UiAwh6rxPW7zcuX+KQ=
 github.com/mdlayher/genetlink v1.3.1 h1:roBiPnual+eqtRkKX2Jb8UQN5ZPWnhDCGj/wR6Jlz2w=
@@ -1921,6 +1941,10 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
 github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
 github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/oauth2-proxy/mockoidc v0.0.0-20220221072942-e3afe97dec43 h1:V9YiO92tYBmVgVcKhdxK6I4avJCefBM+0Db4WM2dank=
+github.com/oauth2-proxy/mockoidc v0.0.0-20220221072942-e3afe97dec43/go.mod h1:rW25Kyd08Wdn3UVn0YBsDTSvReu0jqpmJKzxITPSjks=
+github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404 h1:ZpzR4Ou1nhldBG/vEzauoqyaUlofaUcLkv1C/gBK8ls=
+github.com/oauth2-proxy/tools/reference-gen v0.0.0-20210118095127-56ffd7384404/go.mod h1:YpORG8zs14vNlpXvuHYnnDvWazIRaDk02MaY8lafqdI=
 github.com/observiq/ctimefmt v1.0.0 h1:r7vTJ+Slkrt9fZ67mkf+mA6zAdR5nGIJRMTzkUyvilk=
 github.com/observiq/ctimefmt v1.0.0/go.mod h1:mxi62//WbSpG/roCO1c6MqZ7zQTvjVtYheqHN3eOjvc=
 github.com/ohler55/ojg v1.18.7 h1:sC7zy0usEiWa6bvx3NU1yZH4kCA2F3Qzs6iiDX4+xdk=
@@ -1934,6 +1958,8 @@ github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
 github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
 github.com/oliver006/redis_exporter v1.51.0 h1:nhRpeawfiraIiYprVY1l8iaiXjQn6fqG24G9R7QoXNA=
 github.com/oliver006/redis_exporter v1.51.0/go.mod h1:DygrV+nXovoyQv2KDb454PG33ktpu0BoLr5bUeNT64A=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88=
 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/jaegerexporter v0.80.0 h1:/cUNpmtNRN+AhONVb5gzkqZv6w3GtB1hhpc73ngi9Z8=
@@ -2046,6 +2072,8 @@ github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwb
 github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
 github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
 github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
+github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
+github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
 github.com/percona/mongodb_exporter v0.39.1-0.20230706092307-28432707eb65 h1:SOB6SH1o//vt7uOWA47Nvahd0lVOLH1vjrBzEECuB+o=
 github.com/percona/mongodb_exporter v0.39.1-0.20230706092307-28432707eb65/go.mod h1:VIKFC7G2UtRRESarb2FniLKUIXrBAh/hHiHdAjCcRGs=
 github.com/performancecopilot/speed v3.0.0+incompatible h1:2WnRzIquHa5QxaJKShDkLM+sc0JPuwhXzK8OYOyt3Vg=
@@ -2149,6 +2177,8 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhD
 github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE=
+github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
 github.com/redis/rueidis v1.0.14-go1.18 h1:dGir5z8w8X1ex7JWO/Zx2FMBrZgQ8Yjm+lw9fPLSNGw=
 github.com/redis/rueidis v1.0.14-go1.18/go.mod h1:HGekzV3HbmzFmRK6j0xic8Z9119+ECoGMjeN1TV1NYU=
 github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
@@ -2164,6 +2194,7 @@ github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
+github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
 github.com/rs/cors v1.9.0 h1:l9HGsTsHJcvW14Nk7J9KFz8bzeAWXn3CG6bgt7LsrAE=
 github.com/rs/cors v1.9.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
 github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
@@ -2217,15 +2248,20 @@ github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY52
 github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo=
 github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
 github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
+github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
 github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
 github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
 github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
 github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
 github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
 github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
+github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
+github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
 github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
 github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
 github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
@@ -2273,6 +2309,10 @@ github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5 h1:+UB2BJA85
 github.com/vishvananda/netlink v1.1.1-0.20210330154013-f5de75959ad5/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
 github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA=
 github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
+github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
+github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
+github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
 github.com/vmware/govmomi v0.27.2 h1:Ecooqg069gUbl5EuWYwcrvzRqMkah9J8BXaf9HCEGVM=
 github.com/vmware/govmomi v0.27.2/go.mod h1:daTuJEcQosNMXYJOeku0qdBJP9SOLLWB3Mqz8THtv6o=
 github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
@@ -2495,7 +2535,6 @@ golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su
 golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
 golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
 golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
@@ -2507,6 +2546,7 @@ golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
 golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
 golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
+golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
 golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0=
 golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM=
 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -2550,7 +2590,6 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
 golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
@@ -2586,6 +2625,7 @@ golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
 golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
 golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
+golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
 golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
 gomodules.xyz/jsonpatch/v2 v2.3.0 h1:8NFhfS6gzxNqjLIYnZxg319wZ5Qjnx4m/CcX+Klzazc=
@@ -2677,8 +2717,12 @@ gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1
 gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs=
 gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
 gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
+gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
 gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
 gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
+gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
+gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 gopkg.in/telebot.v3 v3.1.2 h1:uw3zobPBnexytTsIPyxsS10xHRLXCf5f2GQhBxp6NaU=
 gopkg.in/telebot.v3 v3.1.2/go.mod h1:GJKwwWqp9nSkIVN51eRKU78aB5f5OnQuWdwiIZfPbko=
 gopkg.in/telebot.v3 v3.1.3 h1:T+CTyOWpZMqp3ALHSweNgp1awQ9nMXdRAMpe/r6x9/s=
@@ -2706,6 +2750,8 @@ k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU=
 k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
 k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo=
 k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo=
+k8s.io/gengo v0.0.0-20201113003025-83324d819ded h1:JApXBKYyB7l9xx+DK7/+mFjC7A9Bt5A93FPvFD0HIFE=
+k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c h1:GohjlNKauSai7gN4wsJkeZ3WAJx4Sh+oT/b5IYn5suA=
 k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
 k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
@@ -2714,7 +2760,6 @@ k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4Va
 k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 k8s.io/utils v0.0.0-20230308161112-d77c459e9343/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
-k8s.io/utils v0.0.0-20230711102312-30195339c3c7/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
 rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=
 rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4=
 rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY=
diff --git a/pkg/api/vcs.html b/pkg/api/vcs.html
index 008244518c..52769d779d 100644
--- a/pkg/api/vcs.html
+++ b/pkg/api/vcs.html
@@ -21,8 +21,6 @@
   

   

   
-
-
-

From a1f47cfda87ec6d507640ca2f07193ad38792559 Mon Sep 17 00:00:00 2001
From: Cyril Tovena 
Date: Mon, 19 Feb 2024 10:11:52 +0100
Subject: [PATCH 31/31] Add automatic git ref to self profiling

---
 pkg/phlare/phlare.go | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/pkg/phlare/phlare.go b/pkg/phlare/phlare.go
index 4c07f95668..80d8273318 100644
--- a/pkg/phlare/phlare.go
+++ b/pkg/phlare/phlare.go
@@ -10,6 +10,7 @@ import (
 	"net/http"
 	"os"
 	"runtime"
+	"runtime/debug"
 	"sort"
 	"strings"
 
@@ -385,9 +386,10 @@ func (f *Phlare) Run() error {
 				ApplicationName: "pyroscope",
 				ServerAddress:   fmt.Sprintf("http://%s:%d", "localhost", f.Cfg.Server.HTTPListenPort),
 				Tags: map[string]string{
-					"hostname": os.Getenv("HOSTNAME"),
-					"target":   "all",
-					"version":  version.Version,
+					"hostname":           os.Getenv("HOSTNAME"),
+					"target":             "all",
+					"service_git_ref":    serviceGitRef(),
+					"service_repository": "https://github.com/grafana/pyroscope",
 				},
 				ProfileTypes: []pyroscope.ProfileType{
 					pyroscope.ProfileCPU,
@@ -561,3 +563,19 @@ func printRoutes(r *mux.Router) {
 		fmt.Printf("failed to walk routes %s\n", err)
 	}
 }
+
+// serviceGitRef attempts to find the git revision of the service. Default to HEAD.
+func serviceGitRef() string {
+	if version.Revision != "" {
+		return version.Revision
+	}
+	buildInfo, ok := debug.ReadBuildInfo()
+	if ok {
+		for _, setting := range buildInfo.Settings {
+			if setting.Key == "vcs.revision" {
+				return setting.Value
+			}
+		}
+	}
+	return "HEAD"
+}