diff --git a/go.mod b/go.mod index a67f7385..56a473a3 100644 --- a/go.mod +++ b/go.mod @@ -43,17 +43,17 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.14.0 - github.com/stretchr/testify v1.10.0 + github.com/stretchr/testify v1.11.1 github.com/tonistiigi/go-csvvalue v0.0.0-20240814133006-030d3b2625d0 github.com/zclconf/go-cty v1.13.0 - go.opentelemetry.io/otel/trace v1.20.0 + go.opentelemetry.io/otel/trace v1.39.0 go.opentelemetry.io/proto/otlp v0.12.0 golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 - golang.org/x/net v0.25.0 - golang.org/x/sync v0.12.0 - golang.org/x/term v0.29.0 - google.golang.org/grpc v1.59.0 - google.golang.org/protobuf v1.32.0 + golang.org/x/net v0.48.0 + golang.org/x/sync v0.19.0 + golang.org/x/term v0.38.0 + google.golang.org/grpc v1.79.2 + google.golang.org/protobuf v1.36.10 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -82,7 +82,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/catppuccin/go v0.3.0 // indirect github.com/cenkalti/backoff/v4 v4.2.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/x/ansi v0.8.0 // indirect github.com/charmbracelet/x/cellbuf v0.0.13 // indirect @@ -102,17 +102,17 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/fvbommel/sortorder v1.0.1 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-viper/mapstructure/v2 v2.0.0 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gofrs/uuid v4.0.0+incompatible // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.3.1 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect @@ -168,27 +168,27 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 // indirect - go.opentelemetry.io/otel v1.20.0 // indirect + go.opentelemetry.io/otel v1.39.0 // indirect go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 // indirect 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.33.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/oauth2 v0.11.0 // indirect - golang.org/x/sys v0.31.0 // indirect - golang.org/x/text v0.23.0 // indirect + go.opentelemetry.io/otel/metric v1.39.0 // indirect + go.opentelemetry.io/otel/sdk v1.39.0 // indirect + golang.org/x/crypto v0.46.0 // indirect + golang.org/x/mod v0.30.0 // indirect + golang.org/x/oauth2 v0.34.0 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect golang.org/x/time v0.1.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/appengine v1.6.7 // indirect + golang.org/x/tools v0.39.0 // indirect google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect k8s.io/apimachinery v0.25.4 // indirect diff --git a/go.sum b/go.sum index 88cbab5b..59b5ec66 100644 --- a/go.sum +++ b/go.sum @@ -29,9 +29,8 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= -cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= -cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= -cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -136,8 +135,8 @@ github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= github.com/charmbracelet/bubbletea v1.3.4 h1:kCg7B+jSCFPLYRA52SDZjr51kG/fMUEoPoZrkaDHyoI= @@ -181,8 +180,8 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi1KW7R5esrLE= github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= @@ -253,8 +252,8 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= -github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= +github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/erikgeiser/promptkit v0.9.0 h1:3qL1mS/ntCrXdb8sTP/ka82CJ9kEQaGuYXNrYJkWYBc= @@ -295,8 +294,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7 github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -347,8 +346,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -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/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= @@ -365,8 +364,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= @@ -389,8 +388,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= @@ -461,8 +460,8 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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= @@ -612,8 +611,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= @@ -656,8 +655,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/theupdateframework/notary v0.6.1 h1:7wshjstgS9x9F5LuB1L5mBI2xNMObWqjz+cjWoom6l0= @@ -697,6 +696,8 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.0 h1:WUMhXWqLmFlznidWF4B9iML8VMdZy4TzJVYzdYTCuaM= @@ -704,8 +705,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0. go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0 h1:1eHu3/pUSWaOgltNK3WJFaywKsTIr/PwvHyDmi0lQA0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.0/go.mod h1:HyABWq60Uy1kjJSa2BVOxUVao8Cdick5AWSKPutqy6U= go.opentelemetry.io/otel v1.4.1/go.mod h1:StM6F/0fSwpd8dKWDCdRr7uRvEPYdW0hBSlbdTiUde4= -go.opentelemetry.io/otel v1.20.0 h1:vsb/ggIY+hUjD/zCAQHpzTmndPqv/ml2ArbsbfBYTAc= -go.opentelemetry.io/otel v1.20.0/go.mod h1:oUIGj3D77RwJdM6PPZImDpSZGDvkD9fhesHny69JFrs= +go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= +go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1 h1:imIM3vRDMyZK1ypQlQlO+brE22I9lRhJsBDXpDWjlz8= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.4.1/go.mod h1:VpP4/RMn8bv8gNo9uK7/IMY4mtWLELsS+JIP0inH0h4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.4.1 h1:WPpPsAAs8I2rA47v5u0558meKmmwm1Dj99ZbqCV8sZ8= @@ -714,20 +715,23 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1 h1:AxqDiG go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.4.1/go.mod h1:c6E4V3/U+miqjs/8l950wggHGL1qzlp0Ypj9xoGrPqo= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1 h1:8qOago/OqoFclMUUj/184tZyRdDZFpcejSjbk5Jrl6Y= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.4.1/go.mod h1:VwYo0Hak6Efuy0TXsZs8o1hnV3dHDPNtDbycG0hI8+M= -go.opentelemetry.io/otel/metric v1.20.0 h1:ZlrO8Hu9+GAhnepmRGhSU7/VkpjrNowxRN9GyKR4wzA= -go.opentelemetry.io/otel/metric v1.20.0/go.mod h1:90DRw3nfK4D7Sm/75yQ00gTJxtkBxX+wu6YaNymbpVM= +go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0= +go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs= go.opentelemetry.io/otel/sdk v1.4.1/go.mod h1:NBwHDgDIBYjwK2WNu1OPgsIc2IJzmBXNnvIJxJc8BpE= -go.opentelemetry.io/otel/sdk v1.20.0 h1:5Jf6imeFZlZtKv9Qbo6qt2ZkmWtdWx/wzcCbNUlAWGM= -go.opentelemetry.io/otel/sdk v1.20.0/go.mod h1:rmkSx1cZCm/tn16iWDn1GQbLtsW/LvsdEEFzCSRM6V0= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= go.opentelemetry.io/otel/trace v1.4.1/go.mod h1:iYEVbroFCNut9QkwEczV9vMRPHNKSSwYZjulEtsmhFc= -go.opentelemetry.io/otel/trace v1.20.0 h1:+yxVAPZPbQhbC3OfAkeIVTky6iTFpcr4SiY9om7mXSQ= -go.opentelemetry.io/otel/trace v1.20.0/go.mod h1:HJSK7F/hA5RlzpZ0zKDCHCDHm556LCDtKaAo6JmBFUU= +go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= +go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.12.0 h1:CMJ/3Wp7iOWES+CYLfnBv+DVmPbB+kmy9PJ92XvlR6c= go.opentelemetry.io/proto/otlp v0.12.0/go.mod h1:TsIjwGWIx5VFYv9KGVlOpxoBl5Dy+63SUguV7GGvlSQ= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -740,8 +744,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.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= +golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= 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= @@ -778,8 +782,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -821,8 +825,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.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= 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= @@ -834,8 +838,8 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= +golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -847,8 +851,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= -golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= +golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -916,14 +920,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.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= +golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q= +golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg= 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= @@ -932,8 +936,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -990,12 +994,14 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1021,7 +1027,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1064,10 +1069,10 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d h1:VBu5YqKPv6XiJ199exd8Br+Aetz+o08F+PLMnwJQHAY= google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= -google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= +google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1088,8 +1093,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.79.2 h1:fRMD94s2tITpyJGtBBn7MkMseNpOZU8ZxgC3MMBaXRU= +google.golang.org/grpc v1.79.2/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1103,8 +1108,9 @@ 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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= 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 7248907e..f9bd907c 100644 --- a/pkg/api/rpc.go +++ b/pkg/api/rpc.go @@ -67,6 +67,10 @@ func NewVariableServiceClient() civ1connect.VariableServiceClient { return civ1connect.NewVariableServiceClient(getHTTPClient(getBaseURL()), getBaseURL(), WithUserAgent()) } +func NewComputeClient() civ1connect.DepotComputeServiceClient { + return civ1connect.NewDepotComputeServiceClient(getHTTPClient(getBaseURL()), getBaseURL(), WithUserAgent(), connect.WithGRPC()) +} + func WithAuthentication[T any](req *connect.Request[T], token string) *connect.Request[T] { req.Header().Add("Authorization", "Bearer "+token) return req diff --git a/pkg/cmd/buildctl/proxy.go b/pkg/cmd/buildctl/proxy.go index dde6dddf..99cfe679 100644 --- a/pkg/cmd/buildctl/proxy.go +++ b/pkg/cmd/buildctl/proxy.go @@ -996,6 +996,21 @@ type HealthProxy struct { state func() *ProxyState } +func (p *HealthProxy) List(ctx context.Context, in *health.HealthListRequest) (*health.HealthListResponse, error) { + md, ok := metadata.FromIncomingContext(ctx) + if ok { + ctx = metadata.NewOutgoingContext(ctx, md) + } + + state := p.state() + if state.Err != nil { + return nil, state.Err + } + + client := health.NewHealthClient(state.Conn) + return client.List(ctx, in) +} + func (p *HealthProxy) Check(ctx context.Context, in *health.HealthCheckRequest) (*health.HealthCheckResponse, error) { md, ok := metadata.FromIncomingContext(ctx) if ok { diff --git a/pkg/cmd/compute/compute.go b/pkg/cmd/compute/compute.go new file mode 100644 index 00000000..fcc8b7b5 --- /dev/null +++ b/pkg/cmd/compute/compute.go @@ -0,0 +1,28 @@ +package compute + +import ( + "github.com/spf13/cobra" +) + +func NewCmdCompute() *cobra.Command { + cmd := &cobra.Command{ + Use: "compute [flags] [compute args...]", + Short: "Manage Depot compute", + Long: `Compute is the building block of Depot CI. + +The command enables user to start, stop and interact with compute instances. + +Subcommands: + exec Execute arbitrary commands within the compute. Streams stdout, stderr and exit code. + exec-pipe Execute a command, then stream bytes to the command's stdin. + pty Open a pseudo-terminal within the compute.`, + } + + cmd.PersistentFlags().String("token", "", "Depot API token") + + cmd.AddCommand(newComputeExec()) + cmd.AddCommand(newComputePty()) + cmd.AddCommand(newComputeExecPipe()) + + return cmd +} diff --git a/pkg/cmd/compute/exec-pipe.go b/pkg/cmd/compute/exec-pipe.go new file mode 100644 index 00000000..aaf5537c --- /dev/null +++ b/pkg/cmd/compute/exec-pipe.go @@ -0,0 +1,135 @@ +package compute + +import ( + "context" + "errors" + "fmt" + "io" + "os" + + "github.com/depot/cli/pkg/api" + "github.com/depot/cli/pkg/helpers" + civ1 "github.com/depot/cli/pkg/proto/depot/ci/v1" + "github.com/spf13/cobra" +) + +func newComputeExecPipe() *cobra.Command { + cmd := &cobra.Command{ + Use: "exec-pipe [flags]", + Short: "Execute a command within the compute, then stream bytes to stdin", + Long: "Execute a command within the compute, then stream bytes to stdin", + Example: ` + # Pipe text into a file in the compute + echo "Hello Depot" | depot compute exec-pipe --sandbox-id 1234567890 --session-id 1234567890 -- /bin/bash -lc "tee /tmp/hello.txt" + + # Pipe a tarball into the compute + tar czf - ./src | depot compute exec-pipe --sandbox-id 1234567890 --session-id 1234567890 -- /bin/bash -lc "tar xzf - -C /workspace" +`, + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + token, err := cmd.Flags().GetString("token") + cobra.CheckErr(err) + + token, err = helpers.ResolveOrgAuth(ctx, token) + if err != nil { + return fmt.Errorf("failed to resolve token: %w", err) + } + + sandboxID, err := cmd.Flags().GetString("sandbox-id") + cobra.CheckErr(err) + + if sandboxID == "" { + return fmt.Errorf("sandbox-id is required") + } + + sessionID, err := cmd.Flags().GetString("session-id") + cobra.CheckErr(err) + + if sessionID == "" { + return fmt.Errorf("session-id is required") + } + + timeout, err := cmd.Flags().GetInt("timeout") + cobra.CheckErr(err) + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + client := api.NewComputeClient() + stream := client.ExecPipe(ctx) + stream.RequestHeader().Set("Authorization", "Bearer "+token) + + // Send init message with the command. + if err := stream.Send(&civ1.ExecuteCommandPipeRequest{ + Message: &civ1.ExecuteCommandPipeRequest_Init{ + Init: &civ1.ExecuteCommandRequest{ + SandboxId: sandboxID, + SessionId: sessionID, + Command: &civ1.Command{ + CommandArray: args, + TimeoutMs: int32(timeout), + }, + }, + }, + }); err != nil { + return fmt.Errorf("send init: %w", err) + } + + // Forward stdin to the stream in a goroutine. + go func() { + buf := make([]byte, 4096) //nolint:mnd + for { + select { + case <-ctx.Done(): + return + default: + } + n, err := os.Stdin.Read(buf) + if n > 0 { + data := make([]byte, n) + copy(data, buf[:n]) + if sendErr := stream.Send(&civ1.ExecuteCommandPipeRequest{ + Message: &civ1.ExecuteCommandPipeRequest_Stdin{Stdin: data}, + }); sendErr != nil { + return + } + } + if err != nil { + _ = stream.CloseRequest() + return + } + } + }() + + // Read responses from the stream. + for { + resp, err := stream.Receive() + if err != nil { + if errors.Is(err, io.EOF) { + return nil + } + return fmt.Errorf("stream error: %w", err) + } + switch v := resp.Message.(type) { + case *civ1.ExecuteCommandResponse_Stdout: + fmt.Fprint(os.Stdout, v.Stdout) + case *civ1.ExecuteCommandResponse_Stderr: + fmt.Fprint(os.Stderr, v.Stderr) + case *civ1.ExecuteCommandResponse_ExitCode: + if v.ExitCode != 0 { + os.Exit(int(v.ExitCode)) + } + return nil + } + } + }, + } + + cmd.Flags().String("sandbox-id", "", "ID of the compute to execute the command against") + cmd.Flags().String("session-id", "", "The session the compute belongs to") + cmd.Flags().Int("timeout", 0, "The execution timeout in milliseconds") + + return cmd +} diff --git a/pkg/cmd/compute/exec.go b/pkg/cmd/compute/exec.go new file mode 100644 index 00000000..5e8a75c5 --- /dev/null +++ b/pkg/cmd/compute/exec.go @@ -0,0 +1,100 @@ +package compute + +import ( + "fmt" + "os" + + "connectrpc.com/connect" + "github.com/depot/cli/pkg/api" + "github.com/depot/cli/pkg/helpers" + civ1 "github.com/depot/cli/pkg/proto/depot/ci/v1" + "github.com/spf13/cobra" +) + +func newComputeExec() *cobra.Command { + cmd := &cobra.Command{ + Use: "exec [flags]", + Short: "Execute a command within the compute", + Long: "Execute a command within the compute", + Example: ` + # execute command within the compute + depot compute exec --sandbox-id 1234567890 --session-id 1234567890 -- /bin/bash -lc whoami + + # execute command with timeout (30 seconds) + depot compute exec --sandbox-id 1234567890 --session-id 1234567890 --timeout 30000 -- /bin/bash -lc whoami + + # execute complex command + depot compute exec --sandbox-id 1234567890 --session-id 1234567890 -- /bin/bash -lc 'for i in {1..10}; do echo $i; sleep 1; done' +`, + Args: cobra.MinimumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + token, err := cmd.Flags().GetString("token") + cobra.CheckErr(err) + + token, err = helpers.ResolveOrgAuth(ctx, token) + if err != nil { + return fmt.Errorf("failed to resolve token: %w", err) + } + + sandboxID, err := cmd.Flags().GetString("sandbox-id") + cobra.CheckErr(err) + + if sandboxID == "" { + return fmt.Errorf("sandbox-id is required") + } + + sessionID, err := cmd.Flags().GetString("session-id") + cobra.CheckErr(err) + + if sessionID == "" { + return fmt.Errorf("session-id is required") + } + + timeout, err := cmd.Flags().GetInt("timeout") + cobra.CheckErr(err) + + client := api.NewComputeClient() + + stream, err := client.RemoteExec(ctx, api.WithAuthentication(connect.NewRequest(&civ1.ExecuteCommandRequest{ + SandboxId: sandboxID, + SessionId: sessionID, + Command: &civ1.Command{ + CommandArray: args, + TimeoutMs: int32(timeout), + }, + }), token)) + if err != nil { + // nolint:wrapcheck + return err + } + + for stream.Receive() { + msg := stream.Msg() + switch v := msg.Message.(type) { + case *civ1.ExecuteCommandResponse_Stdout: + fmt.Fprint(os.Stdout, v.Stdout) + case *civ1.ExecuteCommandResponse_Stderr: + fmt.Fprint(os.Stderr, v.Stderr) + case *civ1.ExecuteCommandResponse_ExitCode: + if v.ExitCode != 0 { + os.Exit(int(v.ExitCode)) + } + return nil + } + } + if err := stream.Err(); err != nil { + return fmt.Errorf("stream error: %w", err) + } + + return nil + }, + } + + cmd.Flags().String("sandbox-id", "", "ID of the compute to execute the command against") + cmd.Flags().String("session-id", "", "The session the compute belongs to") + cmd.Flags().Int("timeout", 0, "The execution timeout in milliseconds") + + return cmd +} diff --git a/pkg/cmd/compute/pty.go b/pkg/cmd/compute/pty.go new file mode 100644 index 00000000..347eeb6b --- /dev/null +++ b/pkg/cmd/compute/pty.go @@ -0,0 +1,192 @@ +package compute + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "os/signal" + "strings" + "syscall" + + "github.com/depot/cli/pkg/api" + "github.com/depot/cli/pkg/helpers" + civ1 "github.com/depot/cli/pkg/proto/depot/ci/v1" + "github.com/spf13/cobra" + "golang.org/x/term" +) + +func newComputePty() *cobra.Command { + cmd := &cobra.Command{ + Use: "pty [flags]", + Short: "Open a pseudo-terminal within the compute", + Long: "Open a pseudo-terminal within the compute", + Example: ` + # open a pseudo-terminal within the compute + depot compute pty --sandbox-id 1234567890 --session-id 1234567890 + + # set terminal workdir + depot compute pty --sandbox-id 1234567890 --session-id 1234567890 --cwd /tmp + + # set terminal environment variables + depot compute pty --sandbox-id 1234567890 --session-id 1234567890 --env FOO=BAR --env BAR=FOO +`, + RunE: func(cmd *cobra.Command, args []string) error { + ctx := cmd.Context() + + token, err := cmd.Flags().GetString("token") + cobra.CheckErr(err) + + token, err = helpers.ResolveOrgAuth(ctx, token) + if err != nil { + return fmt.Errorf("failed to resolve token: %w", err) + } + + sandboxID, err := cmd.Flags().GetString("sandbox-id") + cobra.CheckErr(err) + + if sandboxID == "" { + return fmt.Errorf("sandbox-id is required") + } + + sessionID, err := cmd.Flags().GetString("session-id") + cobra.CheckErr(err) + + if sessionID == "" { + return fmt.Errorf("session-id is required") + } + + cwd, err := cmd.Flags().GetString("cwd") + cobra.CheckErr(err) + + envSlice, err := cmd.Flags().GetStringArray("env") + cobra.CheckErr(err) + + envMap := make(map[string]string, len(envSlice)) + for _, e := range envSlice { + k, v, ok := strings.Cut(e, "=") + if !ok { + return fmt.Errorf("invalid env format %q, expected KEY=VALUE", e) + } + envMap[k] = v + } + + // Get current terminal size. + fd := int(os.Stdin.Fd()) + rows, cols := 24, 80 //nolint:mnd + if w, h, err := term.GetSize(fd); err == nil { + cols, rows = w, h + } + + // Put terminal in raw mode. + oldState, err := term.MakeRaw(fd) + if err != nil { + return fmt.Errorf("make raw: %w", err) + } + defer term.Restore(fd, oldState) //nolint:errcheck + + // Restore terminal on signals that would otherwise leave it raw. + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + go func() { + <-sigCh + term.Restore(fd, oldState) //nolint:errcheck + os.Exit(1) + }() + defer signal.Stop(sigCh) + + client := api.NewComputeClient() + stream := client.OpenPtySession(ctx) + stream.RequestHeader().Set("Authorization", "Bearer "+token) + + // Send init message. + if err := stream.Send(&civ1.OpenPtySessionRequest{ + Message: &civ1.OpenPtySessionRequest_Init{ + Init: &civ1.PtySession{ + SandboxId: sandboxID, + SessionId: sessionID, + Cwd: cwd, + Env: envMap, + Rows: uint32(rows), + Cols: uint32(cols), + }, + }, + }); err != nil { + return fmt.Errorf("send pty init: %w", err) + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + sendCh := make(chan *civ1.OpenPtySessionRequest, 1) + + go func() { + for { + select { + case msg := <-sendCh: + _ = stream.Send(msg) + case <-ctx.Done(): + _ = stream.CloseRequest() + return + } + } + }() + + // Watch for terminal resize events (no-op on Windows). + stopResize := watchTerminalResize(ctx, fd, sendCh) + defer stopResize() + + // Forward stdin to the stream. + go func() { + buf := make([]byte, 4096) //nolint:mnd + for { + n, err := os.Stdin.Read(buf) + if n > 0 { + data := make([]byte, n) + copy(data, buf[:n]) + select { + case sendCh <- &civ1.OpenPtySessionRequest{ + Message: &civ1.OpenPtySessionRequest_Stdin{Stdin: data}, + }: + case <-ctx.Done(): + return + } + } + if err != nil { + return + } + } + }() + + // Read stdout and exit code from the stream. + for { + resp, err := stream.Receive() + if err != nil { + if errors.Is(err, io.EOF) { + return nil + } + return fmt.Errorf("recv: %w", err) + } + switch m := resp.GetMessage().(type) { + case *civ1.OpenPtySessionResponse_Stdout: + os.Stdout.Write(m.Stdout) //nolint:errcheck + case *civ1.OpenPtySessionResponse_ExitCode: + fmt.Fprintf(os.Stderr, "\r\n[exit %d]\r\n", m.ExitCode) + if m.ExitCode != 0 { + term.Restore(fd, oldState) //nolint:errcheck + os.Exit(int(m.ExitCode)) + } + return nil + } + } + }, + } + + cmd.Flags().String("sandbox-id", "", "ID of the compute to execute the command against") + cmd.Flags().String("session-id", "", "The session the compute belongs to") + cmd.Flags().String("cwd", "", "Workdir within the compute. If not provided or invalid, home directory is used.") + cmd.Flags().StringArray("env", nil, "Environment variables to set (KEY=VALUE), can be specified multiple times.") + + return cmd +} diff --git a/pkg/cmd/compute/pty_resize_unix.go b/pkg/cmd/compute/pty_resize_unix.go new file mode 100644 index 00000000..f1cca3ac --- /dev/null +++ b/pkg/cmd/compute/pty_resize_unix.go @@ -0,0 +1,55 @@ +//go:build !windows + +package compute + +import ( + "context" + "os" + "os/signal" + "syscall" + + civ1 "github.com/depot/cli/pkg/proto/depot/ci/v1" + "golang.org/x/term" +) + +// watchTerminalResize listens for SIGWINCH and sends resize messages via sendCh. +// Stops when ctx is cancelled. Returns a cleanup function to stop watching. +func watchTerminalResize( + ctx context.Context, + fd int, + sendCh chan<- *civ1.OpenPtySessionRequest, +) func() { + sigwinch := make(chan os.Signal, 1) + signal.Notify(sigwinch, syscall.SIGWINCH) + + go func() { + for { + select { + case <-ctx.Done(): + return + case _, ok := <-sigwinch: + if !ok { + return + } + w, h, err := term.GetSize(fd) + if err != nil { + continue + } + select { + case sendCh <- &civ1.OpenPtySessionRequest{ + Message: &civ1.OpenPtySessionRequest_WindowResize{ + WindowResize: &civ1.WindowResize{ + Rows: uint32(h), + Cols: uint32(w), + }, + }, + }: + case <-ctx.Done(): + return + } + } + } + }() + + return func() { signal.Stop(sigwinch) } +} diff --git a/pkg/cmd/compute/pty_resize_windows.go b/pkg/cmd/compute/pty_resize_windows.go new file mode 100644 index 00000000..66246fb8 --- /dev/null +++ b/pkg/cmd/compute/pty_resize_windows.go @@ -0,0 +1,16 @@ +package compute + +import ( + "context" + + civ1 "github.com/depot/cli/pkg/proto/depot/ci/v1" +) + +// watchTerminalResize is a no-op on Windows since SIGWINCH is not available. +func watchTerminalResize( + _ context.Context, + _ int, + _ chan<- *civ1.OpenPtySessionRequest, +) func() { + return func() {} +} diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 55ec29c5..9b3692dc 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -12,6 +12,7 @@ import ( cargoCmd "github.com/depot/cli/pkg/cmd/cargo" ciCmd "github.com/depot/cli/pkg/cmd/ci" claudeCmd "github.com/depot/cli/pkg/cmd/claude" + computeCmd "github.com/depot/cli/pkg/cmd/compute" dockerCmd "github.com/depot/cli/pkg/cmd/docker" "github.com/depot/cli/pkg/cmd/exec" "github.com/depot/cli/pkg/cmd/gocache" @@ -83,6 +84,7 @@ func NewCmdRoot(version, buildDate string) *cobra.Command { cmd.AddCommand(gocache.NewCmdGoCache()) cmd.AddCommand(exec.NewCmdExec()) cmd.AddCommand(ciCmd.NewCmdCI()) + cmd.AddCommand(computeCmd.NewCmdCompute()) return cmd } diff --git a/pkg/proto/depot/ci/v1/api.pb.go b/pkg/proto/depot/ci/v1/api.pb.go new file mode 100644 index 00000000..6682be8c --- /dev/null +++ b/pkg/proto/depot/ci/v1/api.pb.go @@ -0,0 +1,926 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: depot/ci/v1/api.proto + +package civ1 + +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) +) + +// WindowResize describes the pseudo terminal width and height. +type WindowResize struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Rows uint32 `protobuf:"varint,1,opt,name=rows,proto3" json:"rows,omitempty"` + Cols uint32 `protobuf:"varint,2,opt,name=cols,proto3" json:"cols,omitempty"` +} + +func (x *WindowResize) Reset() { + *x = WindowResize{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *WindowResize) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*WindowResize) ProtoMessage() {} + +func (x *WindowResize) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_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 WindowResize.ProtoReflect.Descriptor instead. +func (*WindowResize) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{0} +} + +func (x *WindowResize) GetRows() uint32 { + if x != nil { + return x.Rows + } + return 0 +} + +func (x *WindowResize) GetCols() uint32 { + if x != nil { + return x.Cols + } + return 0 +} + +// OpenPtySessionRequest describes the building blocks of starting a pty session. +type OpenPtySessionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Message: + // + // *OpenPtySessionRequest_Init + // *OpenPtySessionRequest_Stdin + // *OpenPtySessionRequest_WindowResize + Message isOpenPtySessionRequest_Message `protobuf_oneof:"message"` +} + +func (x *OpenPtySessionRequest) Reset() { + *x = OpenPtySessionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OpenPtySessionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OpenPtySessionRequest) ProtoMessage() {} + +func (x *OpenPtySessionRequest) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_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 OpenPtySessionRequest.ProtoReflect.Descriptor instead. +func (*OpenPtySessionRequest) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{1} +} + +func (m *OpenPtySessionRequest) GetMessage() isOpenPtySessionRequest_Message { + if m != nil { + return m.Message + } + return nil +} + +func (x *OpenPtySessionRequest) GetInit() *PtySession { + if x, ok := x.GetMessage().(*OpenPtySessionRequest_Init); ok { + return x.Init + } + return nil +} + +func (x *OpenPtySessionRequest) GetStdin() []byte { + if x, ok := x.GetMessage().(*OpenPtySessionRequest_Stdin); ok { + return x.Stdin + } + return nil +} + +func (x *OpenPtySessionRequest) GetWindowResize() *WindowResize { + if x, ok := x.GetMessage().(*OpenPtySessionRequest_WindowResize); ok { + return x.WindowResize + } + return nil +} + +type isOpenPtySessionRequest_Message interface { + isOpenPtySessionRequest_Message() +} + +type OpenPtySessionRequest_Init struct { + Init *PtySession `protobuf:"bytes,1,opt,name=init,proto3,oneof"` +} + +type OpenPtySessionRequest_Stdin struct { + Stdin []byte `protobuf:"bytes,2,opt,name=stdin,proto3,oneof"` +} + +type OpenPtySessionRequest_WindowResize struct { + WindowResize *WindowResize `protobuf:"bytes,3,opt,name=window_resize,json=windowResize,proto3,oneof"` +} + +func (*OpenPtySessionRequest_Init) isOpenPtySessionRequest_Message() {} + +func (*OpenPtySessionRequest_Stdin) isOpenPtySessionRequest_Message() {} + +func (*OpenPtySessionRequest_WindowResize) isOpenPtySessionRequest_Message() {} + +// PtySession represents the available pty configurations. +type PtySession struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Cwd string `protobuf:"bytes,3,opt,name=cwd,proto3" json:"cwd,omitempty"` + Env map[string]string `protobuf:"bytes,4,rep,name=env,proto3" json:"env,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Rows uint32 `protobuf:"varint,5,opt,name=rows,proto3" json:"rows,omitempty"` + Cols uint32 `protobuf:"varint,6,opt,name=cols,proto3" json:"cols,omitempty"` +} + +func (x *PtySession) Reset() { + *x = PtySession{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PtySession) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PtySession) ProtoMessage() {} + +func (x *PtySession) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_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 PtySession.ProtoReflect.Descriptor instead. +func (*PtySession) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{2} +} + +func (x *PtySession) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +func (x *PtySession) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *PtySession) GetCwd() string { + if x != nil { + return x.Cwd + } + return "" +} + +func (x *PtySession) GetEnv() map[string]string { + if x != nil { + return x.Env + } + return nil +} + +func (x *PtySession) GetRows() uint32 { + if x != nil { + return x.Rows + } + return 0 +} + +func (x *PtySession) GetCols() uint32 { + if x != nil { + return x.Cols + } + return 0 +} + +// OpenPtySessionResponse returns stdout and exit code. +type OpenPtySessionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Message: + // + // *OpenPtySessionResponse_Stdout + // *OpenPtySessionResponse_ExitCode + Message isOpenPtySessionResponse_Message `protobuf_oneof:"message"` +} + +func (x *OpenPtySessionResponse) Reset() { + *x = OpenPtySessionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *OpenPtySessionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OpenPtySessionResponse) ProtoMessage() {} + +func (x *OpenPtySessionResponse) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_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 OpenPtySessionResponse.ProtoReflect.Descriptor instead. +func (*OpenPtySessionResponse) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{3} +} + +func (m *OpenPtySessionResponse) GetMessage() isOpenPtySessionResponse_Message { + if m != nil { + return m.Message + } + return nil +} + +func (x *OpenPtySessionResponse) GetStdout() []byte { + if x, ok := x.GetMessage().(*OpenPtySessionResponse_Stdout); ok { + return x.Stdout + } + return nil +} + +func (x *OpenPtySessionResponse) GetExitCode() int32 { + if x, ok := x.GetMessage().(*OpenPtySessionResponse_ExitCode); ok { + return x.ExitCode + } + return 0 +} + +type isOpenPtySessionResponse_Message interface { + isOpenPtySessionResponse_Message() +} + +type OpenPtySessionResponse_Stdout struct { + Stdout []byte `protobuf:"bytes,1,opt,name=stdout,proto3,oneof"` +} + +type OpenPtySessionResponse_ExitCode struct { + ExitCode int32 `protobuf:"varint,2,opt,name=exit_code,json=exitCode,proto3,oneof"` +} + +func (*OpenPtySessionResponse_Stdout) isOpenPtySessionResponse_Message() {} + +func (*OpenPtySessionResponse_ExitCode) isOpenPtySessionResponse_Message() {} + +// ExecuteCommandRequest executes a command within the respective compute. +type ExecuteCommandRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SandboxId string `protobuf:"bytes,1,opt,name=sandbox_id,json=sandboxId,proto3" json:"sandbox_id,omitempty"` + SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Command *Command `protobuf:"bytes,3,opt,name=command,proto3" json:"command,omitempty"` +} + +func (x *ExecuteCommandRequest) Reset() { + *x = ExecuteCommandRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteCommandRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteCommandRequest) ProtoMessage() {} + +func (x *ExecuteCommandRequest) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_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 ExecuteCommandRequest.ProtoReflect.Descriptor instead. +func (*ExecuteCommandRequest) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{4} +} + +func (x *ExecuteCommandRequest) GetSandboxId() string { + if x != nil { + return x.SandboxId + } + return "" +} + +func (x *ExecuteCommandRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *ExecuteCommandRequest) GetCommand() *Command { + if x != nil { + return x.Command + } + return nil +} + +// ExecuteCommandPipeRequest executes a command, then streams bytes to stdin. +type ExecuteCommandPipeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Message: + // + // *ExecuteCommandPipeRequest_Init + // *ExecuteCommandPipeRequest_Stdin + Message isExecuteCommandPipeRequest_Message `protobuf_oneof:"message"` +} + +func (x *ExecuteCommandPipeRequest) Reset() { + *x = ExecuteCommandPipeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteCommandPipeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteCommandPipeRequest) ProtoMessage() {} + +func (x *ExecuteCommandPipeRequest) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_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 ExecuteCommandPipeRequest.ProtoReflect.Descriptor instead. +func (*ExecuteCommandPipeRequest) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{5} +} + +func (m *ExecuteCommandPipeRequest) GetMessage() isExecuteCommandPipeRequest_Message { + if m != nil { + return m.Message + } + return nil +} + +func (x *ExecuteCommandPipeRequest) GetInit() *ExecuteCommandRequest { + if x, ok := x.GetMessage().(*ExecuteCommandPipeRequest_Init); ok { + return x.Init + } + return nil +} + +func (x *ExecuteCommandPipeRequest) GetStdin() []byte { + if x, ok := x.GetMessage().(*ExecuteCommandPipeRequest_Stdin); ok { + return x.Stdin + } + return nil +} + +type isExecuteCommandPipeRequest_Message interface { + isExecuteCommandPipeRequest_Message() +} + +type ExecuteCommandPipeRequest_Init struct { + Init *ExecuteCommandRequest `protobuf:"bytes,1,opt,name=init,proto3,oneof"` +} + +type ExecuteCommandPipeRequest_Stdin struct { + Stdin []byte `protobuf:"bytes,2,opt,name=stdin,proto3,oneof"` +} + +func (*ExecuteCommandPipeRequest_Init) isExecuteCommandPipeRequest_Message() {} + +func (*ExecuteCommandPipeRequest_Stdin) isExecuteCommandPipeRequest_Message() {} + +// Command encapsulates a command. +type Command struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CommandArray []string `protobuf:"bytes,1,rep,name=command_array,json=commandArray,proto3" json:"command_array,omitempty"` + TimeoutMs int32 `protobuf:"varint,2,opt,name=timeout_ms,json=timeoutMs,proto3" json:"timeout_ms,omitempty"` +} + +func (x *Command) Reset() { + *x = Command{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Command) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Command) ProtoMessage() {} + +func (x *Command) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_proto_msgTypes[6] + 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 Command.ProtoReflect.Descriptor instead. +func (*Command) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{6} +} + +func (x *Command) GetCommandArray() []string { + if x != nil { + return x.CommandArray + } + return nil +} + +func (x *Command) GetTimeoutMs() int32 { + if x != nil { + return x.TimeoutMs + } + return 0 +} + +// ExecuteCommandResponse returns the command execution results. +type ExecuteCommandResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Message: + // + // *ExecuteCommandResponse_Stdout + // *ExecuteCommandResponse_Stderr + // *ExecuteCommandResponse_ExitCode + Message isExecuteCommandResponse_Message `protobuf_oneof:"message"` +} + +func (x *ExecuteCommandResponse) Reset() { + *x = ExecuteCommandResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_depot_ci_v1_api_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecuteCommandResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecuteCommandResponse) ProtoMessage() {} + +func (x *ExecuteCommandResponse) ProtoReflect() protoreflect.Message { + mi := &file_depot_ci_v1_api_proto_msgTypes[7] + 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 ExecuteCommandResponse.ProtoReflect.Descriptor instead. +func (*ExecuteCommandResponse) Descriptor() ([]byte, []int) { + return file_depot_ci_v1_api_proto_rawDescGZIP(), []int{7} +} + +func (m *ExecuteCommandResponse) GetMessage() isExecuteCommandResponse_Message { + if m != nil { + return m.Message + } + return nil +} + +func (x *ExecuteCommandResponse) GetStdout() string { + if x, ok := x.GetMessage().(*ExecuteCommandResponse_Stdout); ok { + return x.Stdout + } + return "" +} + +func (x *ExecuteCommandResponse) GetStderr() string { + if x, ok := x.GetMessage().(*ExecuteCommandResponse_Stderr); ok { + return x.Stderr + } + return "" +} + +func (x *ExecuteCommandResponse) GetExitCode() int32 { + if x, ok := x.GetMessage().(*ExecuteCommandResponse_ExitCode); ok { + return x.ExitCode + } + return 0 +} + +type isExecuteCommandResponse_Message interface { + isExecuteCommandResponse_Message() +} + +type ExecuteCommandResponse_Stdout struct { + Stdout string `protobuf:"bytes,1,opt,name=stdout,proto3,oneof"` +} + +type ExecuteCommandResponse_Stderr struct { + Stderr string `protobuf:"bytes,2,opt,name=stderr,proto3,oneof"` +} + +type ExecuteCommandResponse_ExitCode struct { + ExitCode int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3,oneof"` +} + +func (*ExecuteCommandResponse_Stdout) isExecuteCommandResponse_Message() {} + +func (*ExecuteCommandResponse_Stderr) isExecuteCommandResponse_Message() {} + +func (*ExecuteCommandResponse_ExitCode) isExecuteCommandResponse_Message() {} + +var File_depot_ci_v1_api_proto protoreflect.FileDescriptor + +var file_depot_ci_v1_api_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2f, 0x63, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, + 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, + 0x69, 0x2e, 0x76, 0x31, 0x22, 0x36, 0x0a, 0x0c, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x65, + 0x73, 0x69, 0x7a, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x6c, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x6c, 0x73, 0x22, 0xab, 0x01, 0x0a, + 0x15, 0x4f, 0x70, 0x65, 0x6e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, + 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x73, 0x74, 0x64, 0x69, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x64, 0x69, 0x6e, 0x12, 0x40, 0x0a, + 0x0d, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x48, + 0x00, 0x52, 0x0c, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x52, 0x65, 0x73, 0x69, 0x7a, 0x65, 0x42, + 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xf0, 0x01, 0x0a, 0x0a, 0x50, + 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6e, + 0x64, 0x62, 0x6f, 0x78, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x77, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x77, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x65, 0x6e, 0x76, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, + 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, + 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x12, 0x12, 0x0a, + 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x72, 0x6f, 0x77, + 0x73, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x63, 0x6f, 0x6c, 0x73, 0x1a, 0x36, 0x0a, 0x08, 0x45, 0x6e, 0x76, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x5c, 0x0a, + 0x16, 0x4f, 0x70, 0x65, 0x6e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, + 0x74, 0x12, 0x1d, 0x0a, 0x09, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, + 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x15, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x61, 0x6e, 0x64, 0x62, + 0x6f, 0x78, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x22, 0x78, 0x0a, 0x19, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x69, 0x70, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x38, 0x0a, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x69, 0x6e, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x73, 0x74, + 0x64, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x64, + 0x69, 0x6e, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, + 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x72, 0x72, 0x61, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x72, 0x61, 0x79, 0x12, 0x1d, 0x0a, + 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x22, 0x76, 0x0a, 0x16, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, + 0x12, 0x18, 0x0a, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x12, 0x1d, 0x0a, 0x09, 0x65, 0x78, + 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, + 0x08, 0x65, 0x78, 0x69, 0x74, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x32, 0xaa, 0x02, 0x0a, 0x13, 0x44, 0x65, 0x70, 0x6f, 0x74, 0x43, 0x6f, + 0x6d, 0x70, 0x75, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0e, + 0x4f, 0x70, 0x65, 0x6e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, + 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x50, 0x74, 0x79, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x0a, 0x52, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x12, 0x22, 0x2e, 0x64, 0x65, 0x70, 0x6f, + 0x74, 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x08, 0x45, 0x78, 0x65, 0x63, 0x50, 0x69, 0x70, 0x65, + 0x12, 0x26, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x69, 0x70, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, + 0x2e, 0x63, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, + 0x01, 0x42, 0x9a, 0x01, 0x0a, 0x0f, 0x63, 0x6f, 0x6d, 0x2e, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2e, + 0x63, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x08, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x65, + 0x70, 0x6f, 0x74, 0x2f, 0x63, 0x6c, 0x69, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x64, 0x65, 0x70, 0x6f, 0x74, 0x2f, 0x63, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x63, 0x69, + 0x76, 0x31, 0xa2, 0x02, 0x03, 0x44, 0x43, 0x58, 0xaa, 0x02, 0x0b, 0x44, 0x65, 0x70, 0x6f, 0x74, + 0x2e, 0x43, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0b, 0x44, 0x65, 0x70, 0x6f, 0x74, 0x5c, 0x43, + 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x17, 0x44, 0x65, 0x70, 0x6f, 0x74, 0x5c, 0x43, 0x69, 0x5c, + 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x0d, 0x44, 0x65, 0x70, 0x6f, 0x74, 0x3a, 0x3a, 0x43, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_depot_ci_v1_api_proto_rawDescOnce sync.Once + file_depot_ci_v1_api_proto_rawDescData = file_depot_ci_v1_api_proto_rawDesc +) + +func file_depot_ci_v1_api_proto_rawDescGZIP() []byte { + file_depot_ci_v1_api_proto_rawDescOnce.Do(func() { + file_depot_ci_v1_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_depot_ci_v1_api_proto_rawDescData) + }) + return file_depot_ci_v1_api_proto_rawDescData +} + +var file_depot_ci_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_depot_ci_v1_api_proto_goTypes = []interface{}{ + (*WindowResize)(nil), // 0: depot.ci.v1.WindowResize + (*OpenPtySessionRequest)(nil), // 1: depot.ci.v1.OpenPtySessionRequest + (*PtySession)(nil), // 2: depot.ci.v1.PtySession + (*OpenPtySessionResponse)(nil), // 3: depot.ci.v1.OpenPtySessionResponse + (*ExecuteCommandRequest)(nil), // 4: depot.ci.v1.ExecuteCommandRequest + (*ExecuteCommandPipeRequest)(nil), // 5: depot.ci.v1.ExecuteCommandPipeRequest + (*Command)(nil), // 6: depot.ci.v1.Command + (*ExecuteCommandResponse)(nil), // 7: depot.ci.v1.ExecuteCommandResponse + nil, // 8: depot.ci.v1.PtySession.EnvEntry +} +var file_depot_ci_v1_api_proto_depIdxs = []int32{ + 2, // 0: depot.ci.v1.OpenPtySessionRequest.init:type_name -> depot.ci.v1.PtySession + 0, // 1: depot.ci.v1.OpenPtySessionRequest.window_resize:type_name -> depot.ci.v1.WindowResize + 8, // 2: depot.ci.v1.PtySession.env:type_name -> depot.ci.v1.PtySession.EnvEntry + 6, // 3: depot.ci.v1.ExecuteCommandRequest.command:type_name -> depot.ci.v1.Command + 4, // 4: depot.ci.v1.ExecuteCommandPipeRequest.init:type_name -> depot.ci.v1.ExecuteCommandRequest + 1, // 5: depot.ci.v1.DepotComputeService.OpenPtySession:input_type -> depot.ci.v1.OpenPtySessionRequest + 4, // 6: depot.ci.v1.DepotComputeService.RemoteExec:input_type -> depot.ci.v1.ExecuteCommandRequest + 5, // 7: depot.ci.v1.DepotComputeService.ExecPipe:input_type -> depot.ci.v1.ExecuteCommandPipeRequest + 3, // 8: depot.ci.v1.DepotComputeService.OpenPtySession:output_type -> depot.ci.v1.OpenPtySessionResponse + 7, // 9: depot.ci.v1.DepotComputeService.RemoteExec:output_type -> depot.ci.v1.ExecuteCommandResponse + 7, // 10: depot.ci.v1.DepotComputeService.ExecPipe:output_type -> depot.ci.v1.ExecuteCommandResponse + 8, // [8:11] is the sub-list for method output_type + 5, // [5:8] is the sub-list for method input_type + 5, // [5:5] is the sub-list for extension type_name + 5, // [5:5] is the sub-list for extension extendee + 0, // [0:5] is the sub-list for field type_name +} + +func init() { file_depot_ci_v1_api_proto_init() } +func file_depot_ci_v1_api_proto_init() { + if File_depot_ci_v1_api_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_depot_ci_v1_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WindowResize); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OpenPtySessionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PtySession); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*OpenPtySessionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteCommandRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteCommandPipeRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Command); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_depot_ci_v1_api_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecuteCommandResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_depot_ci_v1_api_proto_msgTypes[1].OneofWrappers = []interface{}{ + (*OpenPtySessionRequest_Init)(nil), + (*OpenPtySessionRequest_Stdin)(nil), + (*OpenPtySessionRequest_WindowResize)(nil), + } + file_depot_ci_v1_api_proto_msgTypes[3].OneofWrappers = []interface{}{ + (*OpenPtySessionResponse_Stdout)(nil), + (*OpenPtySessionResponse_ExitCode)(nil), + } + file_depot_ci_v1_api_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*ExecuteCommandPipeRequest_Init)(nil), + (*ExecuteCommandPipeRequest_Stdin)(nil), + } + file_depot_ci_v1_api_proto_msgTypes[7].OneofWrappers = []interface{}{ + (*ExecuteCommandResponse_Stdout)(nil), + (*ExecuteCommandResponse_Stderr)(nil), + (*ExecuteCommandResponse_ExitCode)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_depot_ci_v1_api_proto_rawDesc, + NumEnums: 0, + NumMessages: 9, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_depot_ci_v1_api_proto_goTypes, + DependencyIndexes: file_depot_ci_v1_api_proto_depIdxs, + MessageInfos: file_depot_ci_v1_api_proto_msgTypes, + }.Build() + File_depot_ci_v1_api_proto = out.File + file_depot_ci_v1_api_proto_rawDesc = nil + file_depot_ci_v1_api_proto_goTypes = nil + file_depot_ci_v1_api_proto_depIdxs = nil +} diff --git a/pkg/proto/depot/ci/v1/civ1connect/api.connect.go b/pkg/proto/depot/ci/v1/civ1connect/api.connect.go new file mode 100644 index 00000000..97caadd4 --- /dev/null +++ b/pkg/proto/depot/ci/v1/civ1connect/api.connect.go @@ -0,0 +1,165 @@ +// Code generated by protoc-gen-connect-go. DO NOT EDIT. +// +// Source: depot/ci/v1/api.proto + +package civ1connect + +import ( + connect "connectrpc.com/connect" + context "context" + errors "errors" + v1 "github.com/depot/cli/pkg/proto/depot/ci/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.IsAtLeastVersion0_1_0 + +const ( + // DepotComputeServiceName is the fully-qualified name of the DepotComputeService service. + DepotComputeServiceName = "depot.ci.v1.DepotComputeService" +) + +// 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 ( + // DepotComputeServiceOpenPtySessionProcedure is the fully-qualified name of the + // DepotComputeService's OpenPtySession RPC. + DepotComputeServiceOpenPtySessionProcedure = "/depot.ci.v1.DepotComputeService/OpenPtySession" + // DepotComputeServiceRemoteExecProcedure is the fully-qualified name of the DepotComputeService's + // RemoteExec RPC. + DepotComputeServiceRemoteExecProcedure = "/depot.ci.v1.DepotComputeService/RemoteExec" + // DepotComputeServiceExecPipeProcedure is the fully-qualified name of the DepotComputeService's + // ExecPipe RPC. + DepotComputeServiceExecPipeProcedure = "/depot.ci.v1.DepotComputeService/ExecPipe" +) + +// DepotComputeServiceClient is a client for the depot.ci.v1.DepotComputeService service. +type DepotComputeServiceClient interface { + // OpenPtySession opens a pseudo terminal session + OpenPtySession(context.Context) *connect.BidiStreamForClient[v1.OpenPtySessionRequest, v1.OpenPtySessionResponse] + // RemoteExec executes provided command against the respective Compute. + RemoteExec(context.Context, *connect.Request[v1.ExecuteCommandRequest]) (*connect.ServerStreamForClient[v1.ExecuteCommandResponse], error) + // ExecPipe executes a command, then streams bytes to stdin. + ExecPipe(context.Context) *connect.BidiStreamForClient[v1.ExecuteCommandPipeRequest, v1.ExecuteCommandResponse] +} + +// NewDepotComputeServiceClient constructs a client for the depot.ci.v1.DepotComputeService 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 NewDepotComputeServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) DepotComputeServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &depotComputeServiceClient{ + openPtySession: connect.NewClient[v1.OpenPtySessionRequest, v1.OpenPtySessionResponse]( + httpClient, + baseURL+DepotComputeServiceOpenPtySessionProcedure, + opts..., + ), + remoteExec: connect.NewClient[v1.ExecuteCommandRequest, v1.ExecuteCommandResponse]( + httpClient, + baseURL+DepotComputeServiceRemoteExecProcedure, + opts..., + ), + execPipe: connect.NewClient[v1.ExecuteCommandPipeRequest, v1.ExecuteCommandResponse]( + httpClient, + baseURL+DepotComputeServiceExecPipeProcedure, + opts..., + ), + } +} + +// depotComputeServiceClient implements DepotComputeServiceClient. +type depotComputeServiceClient struct { + openPtySession *connect.Client[v1.OpenPtySessionRequest, v1.OpenPtySessionResponse] + remoteExec *connect.Client[v1.ExecuteCommandRequest, v1.ExecuteCommandResponse] + execPipe *connect.Client[v1.ExecuteCommandPipeRequest, v1.ExecuteCommandResponse] +} + +// OpenPtySession calls depot.ci.v1.DepotComputeService.OpenPtySession. +func (c *depotComputeServiceClient) OpenPtySession(ctx context.Context) *connect.BidiStreamForClient[v1.OpenPtySessionRequest, v1.OpenPtySessionResponse] { + return c.openPtySession.CallBidiStream(ctx) +} + +// RemoteExec calls depot.ci.v1.DepotComputeService.RemoteExec. +func (c *depotComputeServiceClient) RemoteExec(ctx context.Context, req *connect.Request[v1.ExecuteCommandRequest]) (*connect.ServerStreamForClient[v1.ExecuteCommandResponse], error) { + return c.remoteExec.CallServerStream(ctx, req) +} + +// ExecPipe calls depot.ci.v1.DepotComputeService.ExecPipe. +func (c *depotComputeServiceClient) ExecPipe(ctx context.Context) *connect.BidiStreamForClient[v1.ExecuteCommandPipeRequest, v1.ExecuteCommandResponse] { + return c.execPipe.CallBidiStream(ctx) +} + +// DepotComputeServiceHandler is an implementation of the depot.ci.v1.DepotComputeService service. +type DepotComputeServiceHandler interface { + // OpenPtySession opens a pseudo terminal session + OpenPtySession(context.Context, *connect.BidiStream[v1.OpenPtySessionRequest, v1.OpenPtySessionResponse]) error + // RemoteExec executes provided command against the respective Compute. + RemoteExec(context.Context, *connect.Request[v1.ExecuteCommandRequest], *connect.ServerStream[v1.ExecuteCommandResponse]) error + // ExecPipe executes a command, then streams bytes to stdin. + ExecPipe(context.Context, *connect.BidiStream[v1.ExecuteCommandPipeRequest, v1.ExecuteCommandResponse]) error +} + +// NewDepotComputeServiceHandler 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 NewDepotComputeServiceHandler(svc DepotComputeServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + depotComputeServiceOpenPtySessionHandler := connect.NewBidiStreamHandler( + DepotComputeServiceOpenPtySessionProcedure, + svc.OpenPtySession, + opts..., + ) + depotComputeServiceRemoteExecHandler := connect.NewServerStreamHandler( + DepotComputeServiceRemoteExecProcedure, + svc.RemoteExec, + opts..., + ) + depotComputeServiceExecPipeHandler := connect.NewBidiStreamHandler( + DepotComputeServiceExecPipeProcedure, + svc.ExecPipe, + opts..., + ) + return "/depot.ci.v1.DepotComputeService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case DepotComputeServiceOpenPtySessionProcedure: + depotComputeServiceOpenPtySessionHandler.ServeHTTP(w, r) + case DepotComputeServiceRemoteExecProcedure: + depotComputeServiceRemoteExecHandler.ServeHTTP(w, r) + case DepotComputeServiceExecPipeProcedure: + depotComputeServiceExecPipeHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedDepotComputeServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedDepotComputeServiceHandler struct{} + +func (UnimplementedDepotComputeServiceHandler) OpenPtySession(context.Context, *connect.BidiStream[v1.OpenPtySessionRequest, v1.OpenPtySessionResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("depot.ci.v1.DepotComputeService.OpenPtySession is not implemented")) +} + +func (UnimplementedDepotComputeServiceHandler) RemoteExec(context.Context, *connect.Request[v1.ExecuteCommandRequest], *connect.ServerStream[v1.ExecuteCommandResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("depot.ci.v1.DepotComputeService.RemoteExec is not implemented")) +} + +func (UnimplementedDepotComputeServiceHandler) ExecPipe(context.Context, *connect.BidiStream[v1.ExecuteCommandPipeRequest, v1.ExecuteCommandResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("depot.ci.v1.DepotComputeService.ExecPipe is not implemented")) +} diff --git a/proto/depot/ci/v1/api.proto b/proto/depot/ci/v1/api.proto new file mode 100644 index 00000000..d81ea9bc --- /dev/null +++ b/proto/depot/ci/v1/api.proto @@ -0,0 +1,78 @@ +syntax = "proto3"; + +package depot.ci.v1; + +option go_package = "github.com/depot/cli/pkg/proto/depot/ci/v1;civ1"; + +// DepotComputeApi is a collection of public APIs to manage Compute on Depot platform. +service DepotComputeService { + // OpenPtySession opens a pseudo terminal session + rpc OpenPtySession(stream OpenPtySessionRequest) returns (stream OpenPtySessionResponse); + // RemoteExec executes provided command against the respective Compute. + rpc RemoteExec(ExecuteCommandRequest) returns (stream ExecuteCommandResponse); + // ExecPipe executes a command, then streams bytes to stdin. + rpc ExecPipe(stream ExecuteCommandPipeRequest) returns (stream ExecuteCommandResponse); +} + +// WindowResize describes the pseudo terminal width and height. +message WindowResize { + uint32 rows = 1; + uint32 cols = 2; +} + +// OpenPtySessionRequest describes the building blocks of starting a pty session. +message OpenPtySessionRequest { + oneof message { + PtySession init = 1; + bytes stdin = 2; + WindowResize window_resize = 3; + } +} + +// PtySession represents the available pty configurations. +message PtySession { + string sandbox_id = 1; + string session_id = 2; + string cwd = 3; + map env = 4; + uint32 rows = 5; + uint32 cols = 6; +} + +// OpenPtySessionResponse returns stdout and exit code. +message OpenPtySessionResponse { + oneof message { + bytes stdout = 1; + int32 exit_code = 2; + } +} + +// ExecuteCommandRequest executes a command within the respective compute. +message ExecuteCommandRequest { + string sandbox_id = 1; + string session_id = 2; + Command command = 3; +} + +// ExecuteCommandPipeRequest executes a command, then streams bytes to stdin. +message ExecuteCommandPipeRequest { + oneof message { + ExecuteCommandRequest init = 1; + bytes stdin = 2; + } +} + +// Command encapsulates a command. +message Command { + repeated string command_array = 1; + int32 timeout_ms = 2; +} + +// ExecuteCommandResponse returns the command execution results. +message ExecuteCommandResponse { + oneof message { + string stdout = 1; + string stderr = 2; + int32 exit_code = 3; + } +} \ No newline at end of file