Skip to content

Commit a20a930

Browse files
authored
feat(referrer): add cursor-based pagination to discover endpoints (#2896)
Signed-off-by: Miguel Martinez Trivino <miguel@chainloop.dev>
1 parent b8cc511 commit a20a930

20 files changed

Lines changed: 562 additions & 136 deletions

app/cli/cmd/referrer_discover.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2023 The Chainloop Authors.
2+
// Copyright 2023-2026 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package cmd
1818
import (
1919
"context"
2020

21+
"github.com/chainloop-dev/chainloop/app/cli/cmd/options"
2122
"github.com/chainloop-dev/chainloop/app/cli/cmd/output"
2223
"github.com/chainloop-dev/chainloop/app/cli/pkg/action"
2324
"github.com/spf13/cobra"
@@ -26,18 +27,24 @@ import (
2627
func newReferrerDiscoverCmd() *cobra.Command {
2728
var digest, kind string
2829
var fromPublicIndex bool
30+
paginationOpts := &options.PaginationOpts{DefaultLimit: 20}
2931

3032
cmd := &cobra.Command{
3133
Use: "discover",
3234
Short: "(Preview) inspect pieces of evidence or artifacts stored through Chainloop",
3335
RunE: func(cmd *cobra.Command, args []string) error {
34-
var res *action.ReferrerItem
36+
pagination := &action.PaginationOpts{
37+
Limit: paginationOpts.Limit,
38+
NextCursor: paginationOpts.NextCursor,
39+
}
40+
41+
var res *action.ReferrerDiscoverResult
3542
var err error
3643

3744
if fromPublicIndex {
38-
res, err = action.NewReferrerDiscoverPublicIndex(ActionOpts).Run(context.Background(), digest, kind)
45+
res, err = action.NewReferrerDiscoverPublicIndex(ActionOpts).Run(context.Background(), digest, kind, pagination)
3946
} else {
40-
res, err = action.NewReferrerDiscoverPrivate(ActionOpts).Run(context.Background(), digest, kind)
47+
res, err = action.NewReferrerDiscoverPrivate(ActionOpts).Run(context.Background(), digest, kind, pagination)
4148
}
4249

4350
if err != nil {
@@ -55,6 +62,7 @@ func newReferrerDiscoverCmd() *cobra.Command {
5562
cmd.Flags().StringVarP(&kind, "kind", "k", "", "optional kind of the referrer, used to disambiguate between multiple referrers with the same digest")
5663
cobra.CheckErr(err)
5764
cmd.Flags().BoolVar(&fromPublicIndex, "public", false, "discover from public shared index instead of your organizations'")
65+
paginationOpts.AddFlags(cmd)
5866

5967
return cmd
6068
}

app/cli/documentation/cli-reference.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,8 @@ Options
15181518
-d, --digest string hash of the attestation, piece of evidence or artifact, i.e sha256:deadbeef
15191519
-h, --help help for discover
15201520
-k, --kind string optional kind of the referrer, used to disambiguate between multiple referrers with the same digest
1521+
--limit int number of items to show (default 20)
1522+
--next string cursor to load the next page
15211523
--public discover from public shared index instead of your organizations'
15221524
```
15231525

app/cli/pkg/action/referrer_discover.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2023 The Chainloop Authors.
2+
// Copyright 2023-2026 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -40,36 +40,62 @@ type ReferrerItem struct {
4040
Annotations map[string]string `json:"annotations,omitempty"`
4141
}
4242

43+
type ReferrerDiscoverResult struct {
44+
Item *ReferrerItem `json:"result"`
45+
NextCursor string `json:"nextCursor,omitempty"`
46+
}
47+
4348
func NewReferrerDiscoverPrivate(cfg *ActionsOpts) *ReferrerDiscover {
4449
return &ReferrerDiscover{cfg}
4550
}
4651

47-
func (action *ReferrerDiscover) Run(ctx context.Context, digest, kind string) (*ReferrerItem, error) {
52+
func (action *ReferrerDiscover) Run(ctx context.Context, digest, kind string, p *PaginationOpts) (*ReferrerDiscoverResult, error) {
4853
client := pb.NewReferrerServiceClient(action.cfg.CPConnection)
4954
resp, err := client.DiscoverPrivate(ctx, &pb.ReferrerServiceDiscoverPrivateRequest{
50-
Digest: digest, Kind: kind,
55+
Digest: digest,
56+
Kind: kind,
57+
Pagination: paginationOptsToPb(p),
5158
})
5259
if err != nil {
5360
return nil, err
5461
}
5562

56-
return pbReferrerItemToAction(resp.Result), nil
63+
return newReferrerDiscoverResult(resp.Result, resp.GetPagination()), nil
5764
}
5865

5966
func NewReferrerDiscoverPublicIndex(cfg *ActionsOpts) *ReferrerDiscoverPublic {
6067
return &ReferrerDiscoverPublic{cfg}
6168
}
6269

63-
func (action *ReferrerDiscoverPublic) Run(ctx context.Context, digest, kind string) (*ReferrerItem, error) {
70+
func (action *ReferrerDiscoverPublic) Run(ctx context.Context, digest, kind string, p *PaginationOpts) (*ReferrerDiscoverResult, error) {
6471
client := pb.NewReferrerServiceClient(action.cfg.CPConnection)
6572
resp, err := client.DiscoverPublicShared(ctx, &pb.DiscoverPublicSharedRequest{
66-
Digest: digest, Kind: kind,
73+
Digest: digest,
74+
Kind: kind,
75+
Pagination: paginationOptsToPb(p),
6776
})
6877
if err != nil {
6978
return nil, err
7079
}
7180

72-
return pbReferrerItemToAction(resp.Result), nil
81+
return newReferrerDiscoverResult(resp.Result, resp.GetPagination()), nil
82+
}
83+
84+
func paginationOptsToPb(p *PaginationOpts) *pb.CursorPaginationRequest {
85+
if p == nil {
86+
return nil
87+
}
88+
return &pb.CursorPaginationRequest{
89+
Limit: int32(p.Limit),
90+
Cursor: p.NextCursor,
91+
}
92+
}
93+
94+
func newReferrerDiscoverResult(item *pb.ReferrerItem, p *pb.CursorPaginationResponse) *ReferrerDiscoverResult {
95+
return &ReferrerDiscoverResult{
96+
Item: pbReferrerItemToAction(item),
97+
NextCursor: p.GetNextCursor(),
98+
}
7399
}
74100

75101
func pbReferrerItemToAction(in *pb.ReferrerItem) *ReferrerItem {

app/controlplane/api/controlplane/v1/referrer.pb.go

Lines changed: 84 additions & 29 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/controlplane/api/controlplane/v1/referrer.proto

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright 2024 The Chainloop Authors.
2+
// Copyright 2024-2026 The Chainloop Authors.
33
//
44
// Licensed under the Apache License, Version 2.0 (the "License");
55
// you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ syntax = "proto3";
1818
package controlplane.v1;
1919

2020
import "buf/validate/validate.proto";
21+
import "controlplane/v1/pagination.proto";
2122
import "google/api/annotations.proto";
2223
import "google/protobuf/timestamp.proto";
2324
import "protoc-gen-openapiv2/options/annotations.proto";
@@ -57,6 +58,8 @@ message ReferrerServiceDiscoverPrivateRequest {
5758
// Kind is the optional type of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ...
5859
// Used to filter and resolve ambiguities
5960
string kind = 2;
61+
// Pagination options for the references list
62+
CursorPaginationRequest pagination = 3;
6063

6164
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
6265
json_schema: {
@@ -73,6 +76,8 @@ message DiscoverPublicSharedRequest {
7376
// Kind is the optional type of referrer, i.e CONTAINER_IMAGE, GIT_HEAD, ...
7477
// Used to filter and resolve ambiguities
7578
string kind = 2;
79+
// Pagination options for the references list
80+
CursorPaginationRequest pagination = 3;
7681

7782
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
7883
json_schema: {
@@ -86,6 +91,8 @@ message DiscoverPublicSharedRequest {
8691
message DiscoverPublicSharedResponse {
8792
// Result is the discovered referrer item
8893
ReferrerItem result = 1;
94+
// Pagination information for the references list
95+
CursorPaginationResponse pagination = 2;
8996

9097
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
9198
json_schema: {
@@ -99,6 +106,8 @@ message DiscoverPublicSharedResponse {
99106
message ReferrerServiceDiscoverPrivateResponse {
100107
// Result is the discovered referrer item
101108
ReferrerItem result = 1;
109+
// Pagination information for the references list
110+
CursorPaginationResponse pagination = 2;
102111

103112
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = {
104113
json_schema: {

app/controlplane/api/controlplane/v1/referrer_grpc.pb.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)