Skip to content

Commit 1101ca1

Browse files
authored
Add buf plugin registry commit commands (#3498)
1 parent 1c39351 commit 1101ca1

File tree

11 files changed

+800
-17
lines changed

11 files changed

+800
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
determinisitic.
99
- Add `buf plugin push` command to push a plugin to the Buf Schema Registry.
1010
Only WebAssembly check plugins are supported at this time.
11+
- Add `buf registry plugin commit {add-label,info,list,resolve}` to manage BSR plugin commits.
1112

1213
## [v1.47.2] - 2024-11-14
1314

private/buf/bufprint/bufprint.go

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -199,28 +199,38 @@ func PrintEntity(writer io.Writer, format Format, entity Entity) error {
199199
}
200200
}
201201

202-
// NewLabelEntity returns a new label entity to print.
203-
func NewLabelEntity(label *modulev1.Label, moduleFullName bufparse.FullName) Entity {
202+
// NewLabelEntity returns a new label entity to print. It takes a label as an
203+
// interface to allow for modulev1.Label and pluginv1beta1.Label to be passed.
204+
func NewLabelEntity(label interface {
205+
GetName() string
206+
GetCommitId() string
207+
GetCreateTime() *timestamppb.Timestamp
208+
GetArchiveTime() *timestamppb.Timestamp
209+
}, moduleFullName bufparse.FullName) Entity {
204210
var archiveTime *time.Time
205-
if label.ArchiveTime != nil {
206-
timeValue := label.ArchiveTime.AsTime()
211+
if label.GetArchiveTime() != nil {
212+
timeValue := label.GetArchiveTime().AsTime()
207213
archiveTime = &timeValue
208214
}
209215
return outputLabel{
210-
Name: label.Name,
211-
Commit: label.CommitId,
212-
CreateTime: label.CreateTime.AsTime(),
216+
Name: label.GetName(),
217+
Commit: label.GetCommitId(),
218+
CreateTime: label.GetCreateTime().AsTime(),
213219
ArchiveTime: archiveTime,
214-
moduleFullName: moduleFullName,
220+
entityFullName: moduleFullName,
215221
}
216222
}
217223

218-
// NewCommitEntity returns a new commit entity to print.
219-
func NewCommitEntity(commit *modulev1.Commit, moduleFullName bufparse.FullName) Entity {
224+
// NewCommitEntity returns a new commit entity to print. It takes a commit as
225+
// an interface to allow for modulev1.Commit and pluginv1beta1.Commit to be passed.
226+
func NewCommitEntity(commit interface {
227+
GetId() string
228+
GetCreateTime() *timestamppb.Timestamp
229+
}, moduleFullName bufparse.FullName) Entity {
220230
return outputCommit{
221-
Commit: commit.Id,
222-
CreateTime: commit.CreateTime.AsTime(),
223-
moduleFullName: moduleFullName,
231+
Commit: commit.GetId(),
232+
CreateTime: commit.GetCreateTime().AsTime(),
233+
entityFullName: moduleFullName,
224234
}
225235
}
226236

@@ -434,22 +444,22 @@ type outputLabel struct {
434444
CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"`
435445
ArchiveTime *time.Time `json:"archive_time,omitempty" bufprint:"Archive Time,omitempty"`
436446

437-
moduleFullName bufparse.FullName
447+
entityFullName bufparse.FullName
438448
}
439449

440450
func (l outputLabel) fullName() string {
441-
return fmt.Sprintf("%s:%s", l.moduleFullName.String(), l.Name)
451+
return fmt.Sprintf("%s:%s", l.entityFullName.String(), l.Name)
442452
}
443453

444454
type outputCommit struct {
445455
Commit string `json:"commit,omitempty" bufprint:"Commit"`
446456
CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"`
447457

448-
moduleFullName bufparse.FullName
458+
entityFullName bufparse.FullName
449459
}
450460

451461
func (c outputCommit) fullName() string {
452-
return fmt.Sprintf("%s:%s", c.moduleFullName.String(), c.Commit)
462+
return fmt.Sprintf("%s:%s", c.entityFullName.String(), c.Commit)
453463
}
454464

455465
type outputModule struct {

private/buf/cmd/buf/buf.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ import (
8282
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationdelete"
8383
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationinfo"
8484
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/organization/organizationupdate"
85+
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel"
86+
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitinfo"
87+
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitlist"
88+
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitresolve"
8589
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincreate"
8690
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugindelete"
8791
"github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugininfo"
@@ -268,6 +272,16 @@ func NewRootCommand(name string) *appcmd.Command {
268272
Use: "plugin",
269273
Short: "Manage BSR plugins",
270274
SubCommands: []*appcmd.Command{
275+
{
276+
Use: "commit",
277+
Short: "Manage a plugin's commits",
278+
SubCommands: []*appcmd.Command{
279+
plugincommitaddlabel.NewCommand("add-label", builder, ""),
280+
plugincommitinfo.NewCommand("info", builder, ""),
281+
plugincommitlist.NewCommand("list", builder, ""),
282+
plugincommitresolve.NewCommand("resolve", builder, ""),
283+
},
284+
},
271285
plugincreate.NewCommand("create", builder),
272286
plugininfo.NewCommand("info", builder),
273287
plugindelete.NewCommand("delete", builder),
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// Copyright 2020-2024 Buf Technologies, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package plugincommitaddlabel
16+
17+
import (
18+
"context"
19+
"fmt"
20+
21+
pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1"
22+
"connectrpc.com/connect"
23+
"github.com/bufbuild/buf/private/buf/bufcli"
24+
"github.com/bufbuild/buf/private/buf/bufprint"
25+
"github.com/bufbuild/buf/private/bufpkg/bufparse"
26+
"github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin"
27+
"github.com/bufbuild/buf/private/pkg/app/appcmd"
28+
"github.com/bufbuild/buf/private/pkg/app/appext"
29+
"github.com/bufbuild/buf/private/pkg/slicesext"
30+
"github.com/bufbuild/buf/private/pkg/uuidutil"
31+
"github.com/spf13/pflag"
32+
)
33+
34+
const (
35+
formatFlagName = "format"
36+
labelsFlagName = "label"
37+
)
38+
39+
// NewCommand returns a new Command.
40+
func NewCommand(
41+
name string,
42+
builder appext.SubCommandBuilder,
43+
deprecated string,
44+
) *appcmd.Command {
45+
flags := newFlags()
46+
return &appcmd.Command{
47+
Use: name + " <remote/owner/plugin:commit> --label <label>",
48+
Short: "Add labels to a commit",
49+
Args: appcmd.ExactArgs(1),
50+
Deprecated: deprecated,
51+
Run: builder.NewRunFunc(
52+
func(ctx context.Context, container appext.Container) error {
53+
return run(ctx, container, flags)
54+
},
55+
),
56+
BindFlags: flags.Bind,
57+
}
58+
}
59+
60+
type flags struct {
61+
Format string
62+
Labels []string
63+
}
64+
65+
func newFlags() *flags {
66+
return &flags{}
67+
}
68+
69+
func (f *flags) Bind(flagSet *pflag.FlagSet) {
70+
flagSet.StringVar(
71+
&f.Format,
72+
formatFlagName,
73+
bufprint.FormatText.String(),
74+
fmt.Sprintf(`The output format to use. Must be one of %s`, bufprint.AllFormatsString),
75+
)
76+
flagSet.StringSliceVar(
77+
&f.Labels,
78+
labelsFlagName,
79+
nil,
80+
"The labels to add to the commit. Must have at least one",
81+
)
82+
}
83+
84+
func run(
85+
ctx context.Context,
86+
container appext.Container,
87+
flags *flags,
88+
) error {
89+
pluginRef, err := bufparse.ParseRef(container.Arg(0))
90+
if err != nil {
91+
return appcmd.WrapInvalidArgumentError(err)
92+
}
93+
if pluginRef.Ref() == "" {
94+
return appcmd.NewInvalidArgumentError("commit is required")
95+
}
96+
commitID := pluginRef.Ref()
97+
if _, err := uuidutil.FromDashless(commitID); err != nil {
98+
return appcmd.NewInvalidArgumentErrorf("invalid commit: %w", err)
99+
}
100+
labels := flags.Labels
101+
if len(labels) == 0 {
102+
return appcmd.NewInvalidArgumentError("must create at least one label")
103+
}
104+
format, err := bufprint.ParseFormat(flags.Format)
105+
if err != nil {
106+
return appcmd.WrapInvalidArgumentError(err)
107+
}
108+
clientConfig, err := bufcli.NewConnectClientConfig(container)
109+
if err != nil {
110+
return err
111+
}
112+
pluginClientProvider := bufregistryapiplugin.NewClientProvider(clientConfig)
113+
labelServiceClient := pluginClientProvider.V1Beta1LabelServiceClient(pluginRef.FullName().Registry())
114+
requestValues := slicesext.Map(labels, func(label string) *pluginv1beta1.CreateOrUpdateLabelsRequest_Value {
115+
return &pluginv1beta1.CreateOrUpdateLabelsRequest_Value{
116+
LabelRef: &pluginv1beta1.LabelRef{
117+
Value: &pluginv1beta1.LabelRef_Name_{
118+
Name: &pluginv1beta1.LabelRef_Name{
119+
Owner: pluginRef.FullName().Owner(),
120+
Plugin: pluginRef.FullName().Name(),
121+
Label: label,
122+
},
123+
},
124+
},
125+
CommitId: commitID,
126+
}
127+
})
128+
resp, err := labelServiceClient.CreateOrUpdateLabels(
129+
ctx,
130+
connect.NewRequest(
131+
&pluginv1beta1.CreateOrUpdateLabelsRequest{
132+
Values: requestValues,
133+
},
134+
),
135+
)
136+
if err != nil {
137+
// Not explicitly handling error with connect.CodeNotFound as
138+
// it can be Plugin or Commit not found error. May be caused by
139+
// a misformatted ID.
140+
return err
141+
}
142+
return bufprint.PrintNames(
143+
container.Stdout(),
144+
format,
145+
slicesext.Map(resp.Msg.Labels, func(label *pluginv1beta1.Label) bufprint.Entity {
146+
return bufprint.NewLabelEntity(label, pluginRef.FullName())
147+
})...,
148+
)
149+
}

private/buf/cmd/buf/command/registry/plugin/plugincommit/plugincommitaddlabel/usage.gen.go

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

0 commit comments

Comments
 (0)