From e9c0adb456684638ea3f3ba8ffd528d5ac6199b6 Mon Sep 17 00:00:00 2001 From: Edward McFarlane Date: Thu, 28 Nov 2024 16:11:17 -0500 Subject: [PATCH 1/2] Add buf registry plugin label commands --- private/buf/bufcli/flags_args.go | 18 +- private/buf/bufprint/bufprint.go | 44 ++-- private/buf/cmd/buf/buf.go | 14 ++ .../modulelabellist/modulelabellist.go | 2 +- .../pluginlabelarchive/pluginlabelarchive.go | 107 ++++++++++ .../pluginlabelarchive/usage.gen.go | 19 ++ .../pluginlabelinfo/pluginlabelinfo.go | 130 ++++++++++++ .../pluginlabel/pluginlabelinfo/usage.gen.go | 19 ++ .../pluginlabellist/pluginlabellist.go | 189 ++++++++++++++++++ .../pluginlabel/pluginlabellist/usage.gen.go | 19 ++ .../pluginlabelunarchive.go | 107 ++++++++++ .../pluginlabelunarchive/usage.gen.go | 19 ++ 12 files changed, 667 insertions(+), 20 deletions(-) create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/pluginlabelarchive.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/pluginlabelinfo.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/pluginlabellist.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/usage.gen.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/pluginlabelunarchive.go create mode 100644 private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/usage.gen.go diff --git a/private/buf/bufcli/flags_args.go b/private/buf/bufcli/flags_args.go index e8d2ca56f7..d46f795e41 100644 --- a/private/buf/bufcli/flags_args.go +++ b/private/buf/bufcli/flags_args.go @@ -318,8 +318,8 @@ func VisibilityFlagToPluginVisibilityAllowUnspecified(visibility string) (plugin } } -// ArchiveStatusFlagToArchiveStatusFilter parses the given string as a modulev1.ListLabelsRequest_ArchiveFilter. -func ArchiveStatusFlagToArchiveStatusFilter(archiveStatus string) (modulev1.ListLabelsRequest_ArchiveFilter, error) { +// ArchiveStatusFlagToModuleArchiveStatusFilter parses the given string as a modulev1.ListLabelsRequest_ArchiveFilter. +func ArchiveStatusFlagToModuleArchiveStatusFilter(archiveStatus string) (modulev1.ListLabelsRequest_ArchiveFilter, error) { switch archiveStatus { case archivedArchiveStatus: return modulev1.ListLabelsRequest_ARCHIVE_FILTER_ARCHIVED_ONLY, nil @@ -332,6 +332,20 @@ func ArchiveStatusFlagToArchiveStatusFilter(archiveStatus string) (modulev1.List } } +// ArchiveStatusFlagToPluginArchiveStatusFilter parses the given string as a pluginv1beta1.ListLabelsRequest_ArchiveFilter. +func ArchiveStatusFlagToPluginArchiveStatusFilter(archiveStatus string) (pluginv1beta1.ListLabelsRequest_ArchiveFilter, error) { + switch archiveStatus { + case archivedArchiveStatus: + return pluginv1beta1.ListLabelsRequest_ARCHIVE_FILTER_ARCHIVED_ONLY, nil + case unarchivedArchiveStatus: + return pluginv1beta1.ListLabelsRequest_ARCHIVE_FILTER_UNARCHIVED_ONLY, nil + case allArchiveStatus: + return pluginv1beta1.ListLabelsRequest_ARCHIVE_FILTER_ALL, nil + default: + return 0, fmt.Errorf("invalid archive status: %s", archiveStatus) + } +} + // ValidateRequiredFlag validates that the required flag is set. func ValidateRequiredFlag[T comparable](flagName string, value T) error { var zero T diff --git a/private/buf/bufprint/bufprint.go b/private/buf/bufprint/bufprint.go index 28dd537109..ad2524707f 100644 --- a/private/buf/bufprint/bufprint.go +++ b/private/buf/bufprint/bufprint.go @@ -199,28 +199,38 @@ func PrintEntity(writer io.Writer, format Format, entity Entity) error { } } -// NewLabelEntity returns a new label entity to print. -func NewLabelEntity(label *modulev1.Label, moduleFullName bufparse.FullName) Entity { +// NewLabelEntity returns a new label entity to print. It takes a label as an +// interface to allow for modulev1.Label and pluginv1beta1.Label to be passed. +func NewLabelEntity(label interface { + GetName() string + GetCommitId() string + GetCreateTime() *timestamppb.Timestamp + GetArchiveTime() *timestamppb.Timestamp +}, moduleFullName bufparse.FullName) Entity { var archiveTime *time.Time - if label.ArchiveTime != nil { - timeValue := label.ArchiveTime.AsTime() + if label.GetArchiveTime() != nil { + timeValue := label.GetArchiveTime().AsTime() archiveTime = &timeValue } return outputLabel{ - Name: label.Name, - Commit: label.CommitId, - CreateTime: label.CreateTime.AsTime(), + Name: label.GetName(), + Commit: label.GetCommitId(), + CreateTime: label.GetCreateTime().AsTime(), ArchiveTime: archiveTime, - moduleFullName: moduleFullName, + entityFullName: moduleFullName, } } -// NewCommitEntity returns a new commit entity to print. -func NewCommitEntity(commit *modulev1.Commit, moduleFullName bufparse.FullName) Entity { +// NewCommitEntity returns a new commit entity to print. It takes a commit as +// an interface to allow for modulev1.Commit and pluginv1beta1.Commit to be passed. +func NewCommitEntity(commit interface { + GetId() string + GetCreateTime() *timestamppb.Timestamp +}, moduleFullName bufparse.FullName) Entity { return outputCommit{ - Commit: commit.Id, - CreateTime: commit.CreateTime.AsTime(), - moduleFullName: moduleFullName, + Commit: commit.GetId(), + CreateTime: commit.GetCreateTime().AsTime(), + entityFullName: moduleFullName, } } @@ -434,22 +444,22 @@ type outputLabel struct { CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"` ArchiveTime *time.Time `json:"archive_time,omitempty" bufprint:"Archive Time,omitempty"` - moduleFullName bufparse.FullName + entityFullName bufparse.FullName } func (l outputLabel) fullName() string { - return fmt.Sprintf("%s:%s", l.moduleFullName.String(), l.Name) + return fmt.Sprintf("%s:%s", l.entityFullName.String(), l.Name) } type outputCommit struct { Commit string `json:"commit,omitempty" bufprint:"Commit"` CreateTime time.Time `json:"create_time,omitempty" bufprint:"Create Time"` - moduleFullName bufparse.FullName + entityFullName bufparse.FullName } func (c outputCommit) fullName() string { - return fmt.Sprintf("%s:%s", c.moduleFullName.String(), c.Commit) + return fmt.Sprintf("%s:%s", c.entityFullName.String(), c.Commit) } type outputModule struct { diff --git a/private/buf/cmd/buf/buf.go b/private/buf/cmd/buf/buf.go index 776b611c06..f1870fec55 100644 --- a/private/buf/cmd/buf/buf.go +++ b/private/buf/cmd/buf/buf.go @@ -84,6 +84,10 @@ import ( "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugincreate" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugindelete" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/plugininfo" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist" + "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/plugin/pluginupdate" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/registrycc" "github.com/bufbuild/buf/private/buf/cmd/buf/command/registry/registrylogin" @@ -260,6 +264,16 @@ func NewRootCommand(name string) *appcmd.Command { Use: "plugin", Short: "Manage BSR plugins", SubCommands: []*appcmd.Command{ + { + Use: "label", + Short: "Manage a plugin's labels", + SubCommands: []*appcmd.Command{ + pluginlabelarchive.NewCommand("archive", builder, ""), + pluginlabelinfo.NewCommand("info", builder, ""), + pluginlabellist.NewCommand("list", builder, ""), + pluginlabelunarchive.NewCommand("unarchive", builder, ""), + }, + }, plugincreate.NewCommand("create", builder), plugininfo.NewCommand("info", builder), plugindelete.NewCommand("delete", builder), diff --git a/private/buf/cmd/buf/command/registry/module/modulelabel/modulelabellist/modulelabellist.go b/private/buf/cmd/buf/command/registry/module/modulelabel/modulelabellist/modulelabellist.go index c354a3b9c9..c6266bfa36 100644 --- a/private/buf/cmd/buf/command/registry/module/modulelabel/modulelabellist/modulelabellist.go +++ b/private/buf/cmd/buf/command/registry/module/modulelabel/modulelabellist/modulelabellist.go @@ -110,7 +110,7 @@ func run( if err != nil { return appcmd.WrapInvalidArgumentError(err) } - archiveStatusFitler, err := bufcli.ArchiveStatusFlagToArchiveStatusFilter(flags.ArchiveStatus) + archiveStatusFitler, err := bufcli.ArchiveStatusFlagToModuleArchiveStatusFilter(flags.ArchiveStatus) if err != nil { return appcmd.WrapInvalidArgumentError(err) } diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/pluginlabelarchive.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/pluginlabelarchive.go new file mode 100644 index 0000000000..5491ef1e6c --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/pluginlabelarchive.go @@ -0,0 +1,107 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pluginlabelarchive + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/spf13/pflag" +) + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, + deprecated string, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Archive a plugin label", + Args: appcmd.ExactArgs(1), + Deprecated: deprecated, + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { +} + +func run( + ctx context.Context, + container appext.Container, + _ *flags, +) error { + pluginRef, err := bufparse.ParseRef(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + labelName := pluginRef.Ref() + if labelName == "" { + return appcmd.NewInvalidArgumentError("label is required") + } + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginFullName := pluginRef.FullName() + labelServiceClient := bufregistryapiplugin.NewClientProvider(clientConfig).V1Beta1LabelServiceClient(pluginFullName.Registry()) + // ArchiveLabelsResponse is empty. + if _, err := labelServiceClient.ArchiveLabels( + ctx, + connect.NewRequest( + &pluginv1beta1.ArchiveLabelsRequest{ + LabelRefs: []*pluginv1beta1.LabelRef{ + { + Value: &pluginv1beta1.LabelRef_Name_{ + Name: &pluginv1beta1.LabelRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + Label: labelName, + }, + }, + }, + }, + }, + ), + ); err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewLabelNotFoundError(pluginRef) + } + return err + } + _, err = fmt.Fprintf(container.Stdout(), "Archived %s.\n", pluginRef) + return err +} diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/usage.gen.go new file mode 100644 index 0000000000..061264fa65 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelarchive/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package pluginlabelarchive + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/pluginlabelinfo.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/pluginlabelinfo.go new file mode 100644 index 0000000000..1a95b150f2 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/pluginlabelinfo.go @@ -0,0 +1,130 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pluginlabelinfo + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/buf/bufprint" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/syserror" + "github.com/spf13/pflag" +) + +const formatFlagName = "format" + +// NewCommand returns a new Command +func NewCommand( + name string, + builder appext.SubCommandBuilder, + deprecated string, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Show label information", + Args: appcmd.ExactArgs(1), + Deprecated: deprecated, + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + Format string +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + flagSet.StringVar( + &f.Format, + formatFlagName, + bufprint.FormatText.String(), + fmt.Sprintf(`The output format to use. Must be one of %s`, bufprint.AllFormatsString), + ) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) error { + pluginRef, err := bufparse.ParseRef(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + labelName := pluginRef.Ref() + if labelName == "" { + return appcmd.NewInvalidArgumentError("label is required") + } + format, err := bufprint.ParseFormat(flags.Format) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginClientProvider := bufregistryapiplugin.NewClientProvider(clientConfig) + pluginFullName := pluginRef.FullName() + labelServiceClient := pluginClientProvider.V1Beta1LabelServiceClient(pluginFullName.Registry()) + resp, err := labelServiceClient.GetLabels( + ctx, + connect.NewRequest( + &pluginv1beta1.GetLabelsRequest{ + LabelRefs: []*pluginv1beta1.LabelRef{ + { + Value: &pluginv1beta1.LabelRef_Name_{ + Name: &pluginv1beta1.LabelRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + Label: labelName, + }, + }, + }, + }, + }, + ), + ) + if err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewLabelNotFoundError(pluginRef) + } + return err + } + labels := resp.Msg.Labels + if len(labels) != 1 { + return syserror.Newf("expect 1 label from response, got %d", len(labels)) + } + return bufprint.PrintEntity( + container.Stdout(), + format, + bufprint.NewLabelEntity(labels[0], pluginFullName), + ) +} diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/usage.gen.go new file mode 100644 index 0000000000..c2e8f677ce --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelinfo/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package pluginlabelinfo + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/pluginlabellist.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/pluginlabellist.go new file mode 100644 index 0000000000..06fe606d29 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/pluginlabellist.go @@ -0,0 +1,189 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pluginlabellist + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/buf/bufprint" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/bufbuild/buf/private/pkg/slicesext" + "github.com/spf13/pflag" +) + +const ( + archiveStatusName = "archive-status" + pageSizeFlagName = "page-size" + pageTokenFlagName = "page-token" + reverseFlagName = "reverse" + formatFlagName = "format" + + defaultPageSize = 10 +) + +// NewCommand returns a new Command +func NewCommand( + name string, + builder appext.SubCommandBuilder, + deprecated string, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "List plugin labels", + Args: appcmd.ExactArgs(1), + Deprecated: deprecated, + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { + ArchiveStatus string + PageSize uint32 + PageToken string + Reverse bool + Format string +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { + bufcli.BindArchiveStatus(flagSet, &f.ArchiveStatus, archiveStatusName) + flagSet.Uint32Var( + &f.PageSize, + pageSizeFlagName, + defaultPageSize, + `The page size.`, + ) + flagSet.StringVar( + &f.PageToken, + pageTokenFlagName, + "", + `The page token. If more results are available, a "next_page" key is present in the --format=json output`, + ) + flagSet.BoolVar( + &f.Reverse, + reverseFlagName, + false, + `Reverse the results`, + ) + flagSet.StringVar( + &f.Format, + formatFlagName, + bufprint.FormatText.String(), + fmt.Sprintf(`The output format to use. Must be one of %s`, bufprint.AllFormatsString), + ) +} + +func run( + ctx context.Context, + container appext.Container, + flags *flags, +) error { + pluginRef, err := bufparse.ParseRef(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + archiveStatusFitler, err := bufcli.ArchiveStatusFlagToPluginArchiveStatusFilter(flags.ArchiveStatus) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + format, err := bufprint.ParseFormat(flags.Format) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginClientProvider := bufregistryapiplugin.NewClientProvider(clientConfig) + pluginFullName := pluginRef.FullName() + labelServiceClient := pluginClientProvider.V1Beta1LabelServiceClient(pluginFullName.Registry()) + order := pluginv1beta1.ListLabelsRequest_ORDER_UPDATE_TIME_DESC + if flags.Reverse { + order = pluginv1beta1.ListLabelsRequest_ORDER_UPDATE_TIME_ASC + } + resp, err := labelServiceClient.ListLabels( + ctx, + connect.NewRequest( + &pluginv1beta1.ListLabelsRequest{ + PageSize: flags.PageSize, + PageToken: flags.PageToken, + ResourceRef: &pluginv1beta1.ResourceRef{ + Value: &pluginv1beta1.ResourceRef_Name_{ + Name: &pluginv1beta1.ResourceRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + Child: &pluginv1beta1.ResourceRef_Name_Ref{ + Ref: pluginRef.Ref(), + }, + }, + }, + }, + Order: order, + ArchiveFilter: archiveStatusFitler, + }, + ), + ) + if err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewRefNotFoundError(pluginRef) + } + return err + } + return bufprint.PrintPage( + container.Stdout(), + format, + resp.Msg.NextPageToken, + nextPageCommand(container, flags, resp.Msg.NextPageToken), + slicesext.Map(resp.Msg.Labels, func(label *pluginv1beta1.Label) bufprint.Entity { + return bufprint.NewLabelEntity(label, pluginFullName) + }), + ) +} + +func nextPageCommand(container appext.Container, flags *flags, nextPageToken string) string { + if nextPageToken == "" { + return "" + } + command := fmt.Sprintf("buf registry plugin label list %s", container.Arg(0)) + if flags.ArchiveStatus != bufcli.DefaultArchiveStatus { + command = fmt.Sprintf("%s --%s %s", command, archiveStatusName, flags.ArchiveStatus) + } + if flags.PageSize != defaultPageSize { + command = fmt.Sprintf("%s --%s %d", command, pageSizeFlagName, flags.PageSize) + } + if flags.Reverse { + command = fmt.Sprintf("%s --%s", command, reverseFlagName) + } + if flags.Format != bufprint.FormatText.String() { + command = fmt.Sprintf("%s --%s %s", command, formatFlagName, flags.Format) + } + return fmt.Sprintf("%s --%s %s", command, pageTokenFlagName, nextPageToken) +} diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/usage.gen.go new file mode 100644 index 0000000000..da5e5d88c1 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabellist/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package pluginlabellist + +import _ "github.com/bufbuild/buf/private/usage" diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/pluginlabelunarchive.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/pluginlabelunarchive.go new file mode 100644 index 0000000000..9493221211 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/pluginlabelunarchive.go @@ -0,0 +1,107 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pluginlabelunarchive + +import ( + "context" + "fmt" + + pluginv1beta1 "buf.build/gen/go/bufbuild/registry/protocolbuffers/go/buf/registry/plugin/v1beta1" + "connectrpc.com/connect" + "github.com/bufbuild/buf/private/buf/bufcli" + "github.com/bufbuild/buf/private/bufpkg/bufparse" + "github.com/bufbuild/buf/private/bufpkg/bufregistryapi/bufregistryapiplugin" + "github.com/bufbuild/buf/private/pkg/app/appcmd" + "github.com/bufbuild/buf/private/pkg/app/appext" + "github.com/spf13/pflag" +) + +// NewCommand returns a new Command. +func NewCommand( + name string, + builder appext.SubCommandBuilder, + deprecated string, +) *appcmd.Command { + flags := newFlags() + return &appcmd.Command{ + Use: name + " ", + Short: "Unarchive a plugin label", + Args: appcmd.ExactArgs(1), + Deprecated: deprecated, + Run: builder.NewRunFunc( + func(ctx context.Context, container appext.Container) error { + return run(ctx, container, flags) + }, + ), + BindFlags: flags.Bind, + } +} + +type flags struct { +} + +func newFlags() *flags { + return &flags{} +} + +func (f *flags) Bind(flagSet *pflag.FlagSet) { +} + +func run( + ctx context.Context, + container appext.Container, + _ *flags, +) error { + pluginRef, err := bufparse.ParseRef(container.Arg(0)) + if err != nil { + return appcmd.WrapInvalidArgumentError(err) + } + labelName := pluginRef.Ref() + if labelName == "" { + return appcmd.NewInvalidArgumentError("label is required") + } + clientConfig, err := bufcli.NewConnectClientConfig(container) + if err != nil { + return err + } + pluginFullName := pluginRef.FullName() + labelServiceClient := bufregistryapiplugin.NewClientProvider(clientConfig).V1Beta1LabelServiceClient(pluginFullName.Registry()) + // UnarchiveLabelsResponse is empty. + if _, err := labelServiceClient.UnarchiveLabels( + ctx, + connect.NewRequest( + &pluginv1beta1.UnarchiveLabelsRequest{ + LabelRefs: []*pluginv1beta1.LabelRef{ + { + Value: &pluginv1beta1.LabelRef_Name_{ + Name: &pluginv1beta1.LabelRef_Name{ + Owner: pluginFullName.Owner(), + Plugin: pluginFullName.Name(), + Label: labelName, + }, + }, + }, + }, + }, + ), + ); err != nil { + if connect.CodeOf(err) == connect.CodeNotFound { + return bufcli.NewLabelNotFoundError(pluginRef) + } + return err + } + _, err = fmt.Fprintf(container.Stdout(), "Unarchived %s.\n", pluginRef) + return err +} diff --git a/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/usage.gen.go b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/usage.gen.go new file mode 100644 index 0000000000..aebf7f89d6 --- /dev/null +++ b/private/buf/cmd/buf/command/registry/plugin/pluginlabel/pluginlabelunarchive/usage.gen.go @@ -0,0 +1,19 @@ +// Copyright 2020-2024 Buf Technologies, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Generated. DO NOT EDIT. + +package pluginlabelunarchive + +import _ "github.com/bufbuild/buf/private/usage" From 34385d4705466506bb4f5c2605b3736310cce83a Mon Sep 17 00:00:00 2001 From: Edward McFarlane Date: Tue, 3 Dec 2024 16:25:38 -0500 Subject: [PATCH 2/2] Add CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc2dc40a4d..ae0f7c7b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ determinisitic. - Add `buf plugin push` command to push a plugin to the Buf Schema Registry. Only WebAssembly check plugins are supported at this time. +- Add `buf registry plugin label {archive,info,list,unarchive}` to manage BSR plugin commits. ## [v1.47.2] - 2024-11-14