diff --git a/buf.gen.yaml b/buf.gen.yaml index 97dfc00..8ab206d 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -7,6 +7,7 @@ managed: except: - buf.build/googleapis/googleapis - buf.build/depot/buildkit + - buf.build/depot/api plugins: - plugin: buf.build/protocolbuffers/go:v1.31.0 out: pkg/proto diff --git a/go.mod b/go.mod index abe6e1d..5a83ab3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,9 @@ module github.com/depot/cli go 1.20 require ( - connectrpc.com/connect v1.13.0 + buf.build/gen/go/depot/api/connectrpc/go v1.15.0-20240221184445-e8316610338f.1 + buf.build/gen/go/depot/api/protocolbuffers/go v1.32.0-20240221184445-e8316610338f.1 + connectrpc.com/connect v1.15.0 github.com/adrg/xdg v0.4.0 github.com/briandowns/spinner v1.18.1 github.com/charmbracelet/bubbles v0.16.1 @@ -44,10 +46,10 @@ require ( go.opentelemetry.io/otel/trace v1.20.0 go.opentelemetry.io/proto/otlp v0.12.0 golang.org/x/exp v0.0.0-20220428152302-39d4317da171 - golang.org/x/net v0.17.0 + golang.org/x/net v0.21.0 golang.org/x/sync v0.3.0 google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -164,11 +166,11 @@ require ( go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 // indirect go.opentelemetry.io/otel/metric v1.20.0 // indirect go.opentelemetry.io/otel/sdk v1.20.0 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/oauth2 v0.11.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/term v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/term v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.1.0 // indirect golang.org/x/tools v0.6.0 // indirect diff --git a/go.sum b/go.sum index d40ead7..10519aa 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,7 @@ +buf.build/gen/go/depot/api/connectrpc/go v1.15.0-20240221184445-e8316610338f.1 h1:VYpSRSXBgukO/q1IhlY362qbFbQ0c60c9R8773vSdzI= +buf.build/gen/go/depot/api/connectrpc/go v1.15.0-20240221184445-e8316610338f.1/go.mod h1:u3UQrhy7mXGU+2gMag3WeI7FZgLd2GsQxpWqt2ZSNvg= +buf.build/gen/go/depot/api/protocolbuffers/go v1.32.0-20240221184445-e8316610338f.1 h1:kgC5f06snCbDMa9hN8DY5MEYSeQzBMSXXB3z4SUX5ao= +buf.build/gen/go/depot/api/protocolbuffers/go v1.32.0-20240221184445-e8316610338f.1/go.mod h1:MP5BDdzxwFdhf/KEm27tKfz9dKjtC9C1kXdpuSOb09g= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -38,8 +42,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -connectrpc.com/connect v1.13.0 h1:lGs5maZZzWOOD+PFFiOt5OncKmMsk9ZdPwpy5jcmaYg= -connectrpc.com/connect v1.13.0/go.mod h1:uHAFHtYgeSZJxXrkN1IunDpKghnTXhYbVh0wW4StPW0= +connectrpc.com/connect v1.15.0 h1:lFdeCbZrVVDydAqwr4xGV2y+ULn+0Z73s5JBj2LikWo= +connectrpc.com/connect v1.15.0/go.mod h1:bQmjpDY8xItMnttnurVgOkHUBMRT9cpsNi2O4AjKhmA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -677,8 +681,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -759,8 +763,8 @@ golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -854,14 +858,14 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -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/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1042,8 +1046,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/api/rpc.go b/pkg/api/rpc.go index 21815de..ee1e825 100644 --- a/pkg/api/rpc.go +++ b/pkg/api/rpc.go @@ -4,6 +4,7 @@ import ( "net/http" "os" + "buf.build/gen/go/depot/api/connectrpc/go/depot/core/v1/corev1connect" "connectrpc.com/connect" "github.com/depot/cli/pkg/proto/depot/cli/v1/cliv1connect" "github.com/depot/cli/pkg/proto/depot/cli/v1beta1/cliv1beta1connect" @@ -33,6 +34,14 @@ func NewProjectsClient() cliv1beta1connect.ProjectsServiceClient { return cliv1beta1connect.NewProjectsServiceClient(http.DefaultClient, baseURL, WithUserAgent()) } +func NewSDKProjectsClient() corev1connect.ProjectServiceClient { + baseURL := os.Getenv("DEPOT_API_URL") + if baseURL == "" { + baseURL = "https://api.depot.dev" + } + return corev1connect.NewProjectServiceClient(http.DefaultClient, baseURL, WithUserAgent()) +} + func NewPushClient() cliv1connect.PushServiceClient { baseURL := os.Getenv("DEPOT_API_URL") if baseURL == "" { diff --git a/pkg/cmd/list/list.go b/pkg/cmd/list/list.go index f747fc0..64c2361 100644 --- a/pkg/cmd/list/list.go +++ b/pkg/cmd/list/list.go @@ -16,7 +16,7 @@ func NewCmdList() *cobra.Command { }, } - cmd.AddCommand(NewCmdProjects()) + cmd.AddCommand(NewCmdProjects("projects", "p")) cmd.AddCommand(NewCmdBuilds()) return cmd diff --git a/pkg/cmd/list/projects.go b/pkg/cmd/list/projects.go index db9303d..29a625c 100644 --- a/pkg/cmd/list/projects.go +++ b/pkg/cmd/list/projects.go @@ -21,15 +21,15 @@ import ( "github.com/spf13/cobra" ) -func NewCmdProjects() *cobra.Command { +func NewCmdProjects(commandName, commandAlias string) *cobra.Command { var ( token string outputFormat string ) cmd := &cobra.Command{ - Use: "projects", - Aliases: []string{"p"}, + Use: commandName, + Aliases: []string{commandAlias}, Short: "List depot projects", RunE: func(cmd *cobra.Command, args []string) error { token, err := helpers.ResolveToken(context.Background(), token) diff --git a/pkg/cmd/projects/create.go b/pkg/cmd/projects/create.go new file mode 100644 index 0000000..844c6e4 --- /dev/null +++ b/pkg/cmd/projects/create.go @@ -0,0 +1,93 @@ +// Creates a depot project. +package projects + +import ( + "encoding/json" + "fmt" + + corev1 "buf.build/gen/go/depot/api/protocolbuffers/go/depot/core/v1" + "connectrpc.com/connect" + "github.com/depot/cli/pkg/api" + "github.com/depot/cli/pkg/helpers" + "github.com/spf13/cobra" +) + +func NewCmdCreate() *cobra.Command { + var ( + token string + orgID string + region string + keepGigabytes int64 + ) + + cmd := &cobra.Command{ + Use: "create [flags] ", + Aliases: []string{"c"}, + Args: cobra.MaximumNArgs(1), + Short: "Create depot project", + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) < 1 { + return fmt.Errorf("project name is required") + } + ctx := cmd.Context() + projectName := args[0] + + token, err := helpers.ResolveToken(ctx, token) + if err != nil { + return err + } + + if token == "" { + return fmt.Errorf("missing API token, please run `depot login`") + } + + projectClient := api.NewSDKProjectsClient() + req := corev1.CreateProjectRequest{ + Name: projectName, + RegionId: region, + CachePolicy: &corev1.CachePolicy{ + KeepBytes: keepGigabytes * 1024 * 1024 * 1024, + }, + } + if orgID != "" { + req.OrganizationId = &orgID + } + + res, err := projectClient.CreateProject(ctx, api.WithAuthentication(connect.NewRequest(&req), token)) + if err != nil { + return err + } + project := NewCreateResponse(res.Msg.GetProject()) + buf, err := json.Marshal(project) + if err != nil { + return err + } + fmt.Printf("%s\n", buf) + + return nil + }, + } + + flags := cmd.Flags() + flags.SortFlags = false + flags.StringVar(&token, "token", "", "Depot token") + flags.StringVarP(&orgID, "organization", "o", "", "Depot organization ID") + flags.StringVar(®ion, "region", "us-east-1", "Build data will be stored in the chosen region") + flags.Int64Var(&keepGigabytes, "cache-storage-policy", 50, "Build cache to keep per architecture in GB") + + return cmd +} + +type CreateResponse struct { + ProjectId string `json:"project_id,omitempty"` + Name string `json:"name,omitempty"` + CachePolicy *corev1.CachePolicy `json:"cache_policy,omitempty"` +} + +func NewCreateResponse(project *corev1.Project) *CreateResponse { + return &CreateResponse{ + ProjectId: project.GetProjectId(), + Name: project.GetName(), + CachePolicy: project.GetCachePolicy(), + } +} diff --git a/pkg/cmd/projects/projects.go b/pkg/cmd/projects/projects.go new file mode 100644 index 0000000..f49d2a8 --- /dev/null +++ b/pkg/cmd/projects/projects.go @@ -0,0 +1,22 @@ +package projects + +import ( + "github.com/depot/cli/pkg/cmd/list" + "github.com/spf13/cobra" +) + +func NewCmdProjects() *cobra.Command { + cmd := &cobra.Command{ + Use: "projects", + Aliases: []string{"p"}, + Short: "Create or display depot project information", + RunE: func(cmd *cobra.Command, args []string) error { + return cmd.Help() + }, + } + + cmd.AddCommand(NewCmdCreate()) + cmd.AddCommand(list.NewCmdProjects("list", "ls")) + + return cmd +} diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index b58375c..b667838 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -14,6 +14,7 @@ import ( "github.com/depot/cli/pkg/cmd/list" loginCmd "github.com/depot/cli/pkg/cmd/login" logout "github.com/depot/cli/pkg/cmd/logout" + "github.com/depot/cli/pkg/cmd/projects" "github.com/depot/cli/pkg/cmd/pull" "github.com/depot/cli/pkg/cmd/push" "github.com/depot/cli/pkg/cmd/registry" @@ -60,6 +61,7 @@ func NewCmdRoot(version, buildDate string) *cobra.Command { cmd.AddCommand(versionCmd.NewCmdVersion(version, buildDate)) cmd.AddCommand(dockerCmd.NewCmdConfigureDocker(dockerCli)) cmd.AddCommand(registry.NewCmdRegistry()) + cmd.AddCommand(projects.NewCmdProjects()) return cmd } diff --git a/proto/buf.lock b/proto/buf.lock index 2c7dae9..5b47a31 100644 --- a/proto/buf.lock +++ b/proto/buf.lock @@ -1,6 +1,11 @@ # Generated by buf. DO NOT EDIT. version: v1 deps: + - remote: buf.build + owner: depot + repository: api + commit: e8316610338f48f48fe00f55fe1108a8 + digest: shake256:dd4a2eedc9419fe6638afde1cf75f40943ee6d10fa445e32a99cf183f414e473d60d1f95554d174ebf25d4f05557dd62053cc7b77e23396cb6c2100d08bfecbe - remote: buf.build owner: depot repository: buildkit diff --git a/proto/buf.yaml b/proto/buf.yaml index 5980400..a214a57 100644 --- a/proto/buf.yaml +++ b/proto/buf.yaml @@ -1,5 +1,6 @@ version: v1 deps: + - buf.build/depot/api - buf.build/depot/buildkit breaking: use: