diff --git a/.github/workflows/ci-protoc.yaml b/.github/workflows/ci-protoc.yaml index 53e08dd3b..16398f7bc 100644 --- a/.github/workflows/ci-protoc.yaml +++ b/.github/workflows/ci-protoc.yaml @@ -21,7 +21,7 @@ jobs: go-version-file: ./go.mod - uses: arduino/setup-protoc@v2 with: - version: "24.4" + version: "25.1" - name: Install proto tools run: make init-protoc-tools - name: Generate code diff --git a/.local-dev/config/ns.yaml b/.local-dev/config/ns.yaml index d9da72c19..ee27502b5 100644 --- a/.local-dev/config/ns.yaml +++ b/.local-dev/config/ns.yaml @@ -27,13 +27,11 @@ components: buildkit: address: tcp://buildkitd:1234 buildpack: - backend: docker - docker: - containerName: neoshowcase-buildpack-1 - remoteDir: /workspace - user: cnb - group: cnb - platformAPI: "0.11" + helper: + address: http://buildpack:1235 + listenPort: 1235 + remoteDir: /workspace + platformAPI: "0.11" controller: url: http://ns-controller:10000 priority: 0 diff --git a/.local-dev/ext-builder/.gitignore b/.local-dev/ext-builder/.gitignore deleted file mode 100644 index 41300772e..000000000 --- a/.local-dev/ext-builder/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.env -id_ed25519 diff --git a/.local-dev/ext-builder/Makefile b/.local-dev/ext-builder/Makefile new file mode 100644 index 000000000..f7e2e780f --- /dev/null +++ b/.local-dev/ext-builder/Makefile @@ -0,0 +1,48 @@ +.DEFAULT_GOAL := help +CLUSTER_NAME = ext-builder + +.PHONY: help +help: ## Display this help screen + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' + +.PHONY: k3d-up +k3d-up: ## Spin up k3d cluster + k3d cluster create $(CLUSTER_NAME) --image rancher/k3s:latest --no-lb --k3s-arg "--disable=traefik,servicelb,metrics-server" + +.PHONY: ensure-context +ensure-context: + kubectl config use-context k3d-$(CLUSTER_NAME) + +.PHONY: import +import: ensure-context ## Import ns-builder image into the cluster + sh -c 'cd ../../ && make build' + k3d image import --cluster $(CLUSTER_NAME) ghcr.io/traptitech/ns-builder:main + +.PHONY: apply +apply: ensure-context ## Apply manifests to k3d cluster + kustomize build . | kubectl apply -f - + +REPLICAS?=1 +.PHONY: scale +scale: ensure-context ## Scale the number of builder instances + kubectl scale deployment/ns-builder --replicas=$(REPLICAS) + +.PHONY: events +events: ensure-context ## Tail cluster events + kubectl get events --watch + +.PHONY: logs +logs: ensure-context ## Tail builder logs + kubectl logs --prefix --timestamps --all-containers --max-log-requests=100 -l app=ns-builder -f + +.PHONY: k3d-down +k3d-down: ## Spin down k3d cluster + k3d cluster delete $(CLUSTER_NAME) + +# --- all in one commands --- + +.PHONY: up +up: k3d-up import apply events + +.PHONY: down +down: k3d-down diff --git a/.local-dev/ext-builder/README.md b/.local-dev/ext-builder/README.md index 0517091d4..05a9223a0 100644 --- a/.local-dev/ext-builder/README.md +++ b/.local-dev/ext-builder/README.md @@ -4,10 +4,43 @@ Join external builder instance from outside the production (cluster) deployment ## Usage -1. Set config `./config.yaml` accordingly - - Fetch configuration from production if necessary -2. Set token (`NS_COMPONENTS_CONTROLLER_TOKEN`) in `.env` file -3. Prepare local forward if controller port is unreachable from the internet - - `ssh -L 0.0.0.0:10000:10.43.193.98:10000 c1-203` -4. `docker compose pull` -5. `docker compose up -d` +tl;dr: +Do "First time setup", and run `make up` / `make down` + +### First time setup + +1. Set up config files + - `./config/controller-url.txt` for controller URL + - `./config/controller-token.txt` for controller token + - `./config/known_hosts` for known hosts configuration + - `cp ~/.ssh/known_hosts ./config` should be enough +2. Prepare local forward if controller port is unreachable from the internet + - e.g. `ssh -L 0.0.0.0:10000:10.43.193.98:10000 c1-203` + +### Importing images + +To import ns images to the k3d cluster, `make import` + +### Spin up + +1. `make k3d-up` +2. `make apply` + +### Workaround for local registry + +ref: https://zenn.dev/toshikish/articles/7f555dbf1b4b7d + +Edit and add `rewrite name registry.local host.k3d.internal` inside the `.:53 {}` section: +`kubectl edit cm -n kube-system coredns` + +Restart CoreDNS afterwards: +`kubectl restart deployment/coredns -n kube-system` + +### Managing + +- To scale the number of builder instances, `make scale REPLICAS=3` +- To tail builder logs, `make logs` + +### Spin down + +1. `make k3d-down` diff --git a/.local-dev/ext-builder/builder-deployment.yaml b/.local-dev/ext-builder/builder-deployment.yaml new file mode 100644 index 000000000..36fe7cae8 --- /dev/null +++ b/.local-dev/ext-builder/builder-deployment.yaml @@ -0,0 +1,108 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ns-builder + +spec: + replicas: 1 + revisionHistoryLimit: 0 + selector: + matchLabels: + app: ns-builder + template: + metadata: + labels: + app: ns-builder + spec: + volumes: + - name: ns-bin + emptyDir: {} + - name: socket + emptyDir: {} + - name: config + configMap: + name: ns-config + - name: known-hosts + configMap: + name: known-hosts + + initContainers: + - name: buildpack-install + image: ghcr.io/traptitech/ns-builder:main + imagePullPolicy: Never + command: + - cp + - /app/ns + - /ns-bin + volumeMounts: + - mountPath: /ns-bin + name: ns-bin + + containers: + - name: buildpack + image: paketobuildpacks/builder-jammy-full:latest + imagePullPolicy: Always + command: + - /ns-bin/ns + - buildpack-helper + args: + - --loglevel=debug + - --config=/opt/config/ns.yaml + volumeMounts: + - mountPath: /ns-bin + name: ns-bin + - mountPath: /opt/config/ns.yaml + name: config + subPath: ns.yaml + + - name: buildkitd + image: moby/buildkit:latest + imagePullPolicy: Always + args: + - --addr + - unix:///run/buildkit/buildkitd.sock + readinessProbe: + exec: + command: + - buildctl + - debug + - workers + initialDelaySeconds: 5 + periodSeconds: 30 + livenessProbe: + exec: + command: + - buildctl + - debug + - workers + initialDelaySeconds: 5 + periodSeconds: 30 + securityContext: + privileged: true + volumeMounts: + - mountPath: /run/buildkit + name: socket + - mountPath: /etc/buildkit/buildkitd.toml + name: config + subPath: buildkitd.toml + + - name: builder + image: ghcr.io/traptitech/ns-builder:main + imagePullPolicy: Never + args: + - --loglevel=debug + - --config=/opt/config/ns.yaml + envFrom: + - configMapRef: + name: custom-config + - secretRef: + name: token + volumeMounts: + - mountPath: /run/buildkit + name: socket + - mountPath: /opt/config/ns.yaml + name: config + subPath: ns.yaml + - mountPath: /root/.ssh/known_hosts + name: known-hosts + subPath: known_hosts diff --git a/.local-dev/ext-builder/compose.yaml b/.local-dev/ext-builder/compose.yaml deleted file mode 100644 index b13676fb4..000000000 --- a/.local-dev/ext-builder/compose.yaml +++ /dev/null @@ -1,36 +0,0 @@ -services: - ns-builder: - image: ghcr.io/traptitech/ns-builder:main - command: --debug --loglevel=trace --config=/config.yaml - restart: always - environment: - NS_COMPONENTS_CONTROLLER_TOKEN: - volumes: - - /var/run/docker.sock:/var/run/docker.sock # for buildpack docker backend - - ./config.yaml:/config.yaml - - ~/.ssh/known_hosts:/root/.ssh/known_hosts - depends_on: - buildkitd: - condition: service_started - extra_hosts: - - host.docker.internal:host-gateway - - registry.local:host-gateway - - buildpack: - image: paketobuildpacks/builder-jammy-full:latest - restart: always - entrypoint: - - sleep - - infinity - extra_hosts: - - registry.local:host-gateway - - buildkitd: - image: moby/buildkit:latest - restart: always - privileged: true - command: --addr tcp://0.0.0.0:1234 - volumes: - - ../buildkitd/buildkitd.toml:/etc/buildkit/buildkitd.toml - extra_hosts: - - registry.local:host-gateway diff --git a/.local-dev/ext-builder/config.yaml b/.local-dev/ext-builder/config.yaml deleted file mode 100644 index 3ad884f7a..000000000 --- a/.local-dev/ext-builder/config.yaml +++ /dev/null @@ -1,15 +0,0 @@ -components: - builder: - buildkit: - address: tcp://buildkitd:1234 - buildpack: - backend: docker - docker: - containerName: ext-builder-buildpack-1 - remoteDir: /workspace - user: cnb - group: cnb - platformAPI: "0.11" - controller: - url: http://host.docker.internal:10000 - priority: 10 diff --git a/.local-dev/ext-builder/config/.gitignore b/.local-dev/ext-builder/config/.gitignore new file mode 100644 index 000000000..d3083c788 --- /dev/null +++ b/.local-dev/ext-builder/config/.gitignore @@ -0,0 +1,3 @@ +controller-token.txt +controller-url.txt +known_hosts diff --git a/.local-dev/ext-builder/config/buildkitd.toml b/.local-dev/ext-builder/config/buildkitd.toml new file mode 100644 index 000000000..1e2ed0ec2 --- /dev/null +++ b/.local-dev/ext-builder/config/buildkitd.toml @@ -0,0 +1,11 @@ +[registry."registry.local"] +http = true + +[worker.oci] +enabled = true +gc = true +gckeepstorage = 9000 + +[[worker.oci.gcpolicy]] +all = true +keepBytes = 1024000000 diff --git a/.local-dev/ext-builder/config/ns.yaml b/.local-dev/ext-builder/config/ns.yaml new file mode 100644 index 000000000..6003d40c6 --- /dev/null +++ b/.local-dev/ext-builder/config/ns.yaml @@ -0,0 +1,16 @@ +components: + builder: + buildkit: + address: unix:///run/buildkit/buildkitd.sock + buildpack: + helper: + address: http://localhost:1235 + listenPort: 1235 + remoteDir: /workspace + platformAPI: "0.11" + # controller: + # url: # e.g. http://host.k3d.internal:10000 + priority: 10 + + # controller: + # token: diff --git a/.local-dev/ext-builder/kustomization.yaml b/.local-dev/ext-builder/kustomization.yaml new file mode 100644 index 000000000..30e2e3d76 --- /dev/null +++ b/.local-dev/ext-builder/kustomization.yaml @@ -0,0 +1,19 @@ +resources: + - builder-deployment.yaml + +configMapGenerator: + - name: known-hosts + files: + - ./config/known_hosts + - name: ns-config + files: + - ./config/ns.yaml + - ./config/buildkitd.toml + - name: custom-config + files: + - NS_COMPONENTS_BUILDER_CONTROLLER_URL=./config/controller-url.txt + +secretGenerator: + - name: token + files: + - NS_COMPONENTS_CONTROLLER_TOKEN=./config/controller-token.txt diff --git a/.local-dev/manifest/ns-system/components/builder-deployment.yaml b/.local-dev/manifest/ns-system/components/builder-deployment.yaml index 5aec18851..606d59a66 100644 --- a/.local-dev/manifest/ns-system/components/builder-deployment.yaml +++ b/.local-dev/manifest/ns-system/components/builder-deployment.yaml @@ -14,17 +14,43 @@ spec: labels: app: ns-builder spec: - serviceAccountName: ns-builder + volumes: + - name: ns-bin + emptyDir: {} + - name: socket + emptyDir: {} + - name: config + configMap: + name: ns-config + + initContainers: + - name: buildpack-install + image: ghcr.io/traptitech/ns-builder:main + imagePullPolicy: Never + command: + - cp + - /app/ns + - /ns-bin + volumeMounts: + - mountPath: /ns-bin + name: ns-bin + containers: - name: buildpack image: paketobuildpacks/builder-jammy-full:latest imagePullPolicy: Always command: - - sleep - - infinity + - /ns-bin/ns + - buildpack-helper + args: + - --loglevel=debug + - --config=/opt/config/ns.yaml volumeMounts: - - mountPath: /workspace - name: buildpack + - mountPath: /ns-bin + name: ns-bin + - mountPath: /opt/config/ns.yaml + name: config + subPath: ns.yaml - name: buildkitd image: moby/buildkit:latest @@ -63,36 +89,9 @@ spec: args: - --loglevel=debug - --config=/opt/config/ns.yaml - env: - - name: NS_COMPONENTS_BUILDER_BUILDPACK_K8S_PODNAME - valueFrom: - fieldRef: - fieldPath: metadata.name volumeMounts: - - mountPath: /neoshowcase/buildpack - name: buildpack - mountPath: /run/buildkit name: socket - mountPath: /opt/config/ns.yaml name: config subPath: ns.yaml - - mountPath: /keys - name: keys - # - mountPath: /.docker - # name: secret - volumes: - - name: buildpack - emptyDir: {} - - name: socket - emptyDir: {} - - name: config - configMap: - name: ns-config - - name: keys - secret: - secretName: ns-keys - # - name: secret - # secret: - # secretName: registry-secret - # nodeSelector: - # neoshowcase.trap.jp/builder-node: "true" diff --git a/.local-dev/manifest/ns-system/components/builder-role-binding.yaml b/.local-dev/manifest/ns-system/components/builder-role-binding.yaml deleted file mode 100644 index a5b97f7db..000000000 --- a/.local-dev/manifest/ns-system/components/builder-role-binding.yaml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: ns-builder-binding - -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: ns-builder -subjects: - - kind: ServiceAccount - namespace: ns-system - name: ns-builder diff --git a/.local-dev/manifest/ns-system/components/builder-role.yaml b/.local-dev/manifest/ns-system/components/builder-role.yaml deleted file mode 100644 index 0d4808d2d..000000000 --- a/.local-dev/manifest/ns-system/components/builder-role.yaml +++ /dev/null @@ -1,12 +0,0 @@ -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: ns-builder - -rules: - - apiGroups: - - "" - resources: - - pods/exec - verbs: - - "*" diff --git a/.local-dev/manifest/ns-system/components/builder-service-account.yaml b/.local-dev/manifest/ns-system/components/builder-service-account.yaml deleted file mode 100644 index 10715959d..000000000 --- a/.local-dev/manifest/ns-system/components/builder-service-account.yaml +++ /dev/null @@ -1,4 +0,0 @@ -apiVersion: v1 -kind: ServiceAccount -metadata: - name: ns-builder diff --git a/.local-dev/manifest/ns-system/config/ns.yaml b/.local-dev/manifest/ns-system/config/ns.yaml index ef21ff855..c993e9648 100644 --- a/.local-dev/manifest/ns-system/config/ns.yaml +++ b/.local-dev/manifest/ns-system/config/ns.yaml @@ -31,16 +31,11 @@ components: buildkit: address: unix:///run/buildkit/buildkitd.sock buildpack: - backend: k8s - k8s: - namespace: ns-system - # podName: ns-builder # specified from env - containerName: buildpack - localDir: /neoshowcase/buildpack - remoteDir: /workspace - user: 1001 - group: 1000 - platformAPI: "0.11" + helper: + address: http://localhost:1235 + listenPort: 1235 + remoteDir: /workspace + platformAPI: "0.11" controller: url: http://ns-controller.ns-system.svc.cluster.local:10000 priority: 0 diff --git a/.local-dev/manifest/ns-system/kustomization.yaml b/.local-dev/manifest/ns-system/kustomization.yaml index c43fec535..2e7cc4af3 100644 --- a/.local-dev/manifest/ns-system/kustomization.yaml +++ b/.local-dev/manifest/ns-system/kustomization.yaml @@ -1,9 +1,6 @@ resources: # ls components/*.yaml | sed -e 's/^/ - /g' - components/builder-deployment.yaml - - components/builder-role-binding.yaml - - components/builder-role.yaml - - components/builder-service-account.yaml - components/controller-role-binding.yaml - components/controller-role.yaml - components/controller-service-account.yaml diff --git a/.local-dev/manifest/ns-system/services/registry-deployment.yaml b/.local-dev/manifest/ns-system/services/registry-deployment.yaml index 3299deded..ee8caa13c 100644 --- a/.local-dev/manifest/ns-system/services/registry-deployment.yaml +++ b/.local-dev/manifest/ns-system/services/registry-deployment.yaml @@ -14,10 +14,21 @@ spec: labels: app: registry spec: + volumes: + - name: registry + hostPath: + path: /opt/registry + - name: registry-config + configMap: + name: registry-config + defaultMode: 0755 + containers: - name: registry image: registry:2 env: + - name: REGISTRY_STORAGE_DELETE_ENABLED + value: "true" - name: REGISTRY_HTTP_ADDR value: ":80" ports: @@ -32,11 +43,3 @@ spec: - name: registry-config mountPath: /gc.sh subPath: gc.sh - volumes: - - name: registry - hostPath: - path: /opt/registry - - name: registry-config - configMap: - name: registry-config - defaultMode: 0755 diff --git a/Makefile b/Makefile index 7c4783742..c4a162c84 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -PROTOC_VERSION := 24.4 +PROTOC_VERSION := 25.1 TBLS_VERSION := 1.70.2 GO_REPO_ROOT_PACKAGE := "github.com/traPtitech/neoshowcase" @@ -15,20 +15,24 @@ EVANS_CMD := evans .PHONY: help help: ## Display this help screen - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' + @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' -.PHONY: init-protoc ## Install protoc +.PHONY: init-k3d +init-k3d: + curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash + +.PHONY: init-protoc init-protoc: @PROTOC_VERSION=$(PROTOC_VERSION) ./.local-dev/install-protoc.sh .PHONY: init-protoc-tools -init-protoc-tools: ## Install other protoc tools +init-protoc-tools: go install google.golang.org/protobuf/cmd/protoc-gen-go@latest go install connectrpc.com/connect/cmd/protoc-gen-connect-go@latest yarn global add @connectrpc/protoc-gen-connect-es @bufbuild/protoc-gen-es .PHONY: init -init: init-protoc init-protoc-tools ## Install commands +init: init-k3d init-protoc init-protoc-tools ## Install commands go mod download go install github.com/sqldef/sqldef/cmd/mysqldef@latest go install github.com/ktr0731/evans@latest diff --git a/api/proto/neoshowcase/protobuf/controller.proto b/api/proto/neoshowcase/protobuf/controller.proto index 0b189ed90..0e9d1a01b 100644 --- a/api/proto/neoshowcase/protobuf/controller.proto +++ b/api/proto/neoshowcase/protobuf/controller.proto @@ -29,7 +29,7 @@ message BuildLogPortion { message SaveArtifactRequest { Artifact artifact = 1; - bytes body = 2; + bytes body = 2; // TODO: stream contents? } message SaveBuildLogRequest { @@ -85,6 +85,34 @@ message BuilderResponse { } } +message CopyFileTreeRequest { + string destination = 1; + bytes tar_content = 2; // TODO: stream contents? +} + +message HelperExecEnv { + string key = 1; + string value = 2; +} + +message HelperExecRequest { + string work_dir = 1; + repeated string cmd = 2; + repeated HelperExecEnv envs = 3; +} + +message HelperExecResponse { + enum Type { + LOG = 0; + EXIT_CODE = 1; + } + Type type = 1; + oneof body { + bytes log = 2; + int32 exit_code = 3; + } +} + message SSGenRequest { enum Type { RELOAD = 0; @@ -118,6 +146,11 @@ service ControllerBuilderService { rpc ConnectBuilder(stream BuilderResponse) returns (stream BuilderRequest); } +service BuildpackHelperService { + rpc CopyFileTree(CopyFileTreeRequest) returns (google.protobuf.Empty); + rpc Exec(HelperExecRequest) returns (stream HelperExecResponse); +} + service ControllerSSGenService { rpc ConnectSSGen(google.protobuf.Empty) returns (stream SSGenRequest); } diff --git a/cmd/buildpack-helper/server.go b/cmd/buildpack-helper/server.go new file mode 100644 index 000000000..2153c3738 --- /dev/null +++ b/cmd/buildpack-helper/server.go @@ -0,0 +1,23 @@ +package buildpackhelper + +import ( + "context" + + "github.com/traPtitech/neoshowcase/pkg/domain/web" +) + +type APIServer struct { + *web.H2CServer +} + +type Server struct { + Helper *APIServer +} + +func (s *Server) Start(ctx context.Context) error { + return s.Helper.Start(ctx) +} + +func (s *Server) Shutdown(ctx context.Context) error { + return s.Helper.Shutdown(ctx) +} diff --git a/cmd/config.go b/cmd/config.go index ad63b3906..0f9861425 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -6,8 +6,7 @@ import ( "github.com/traPtitech/neoshowcase/pkg/infrastructure/backend/dockerimpl" "github.com/traPtitech/neoshowcase/pkg/infrastructure/backend/k8simpl" - bdockerimpl "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack/dockerimpl" - bk8simpl "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack/k8simpl" + "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack" "github.com/traPtitech/neoshowcase/pkg/infrastructure/dbmanager" "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc" "github.com/traPtitech/neoshowcase/pkg/infrastructure/log/loki" @@ -52,11 +51,7 @@ type BuilderConfig struct { Buildkit struct { Address string `mapstructure:"address" yaml:"address"` } `mapstructure:"buildkit" yaml:"buildkit"` - Buildpack struct { - Backend string `mapstructure:"backend" yaml:"backend"` - Docker bdockerimpl.Config `mapstructure:"docker" yaml:"docker"` - K8s bk8simpl.Config `mapstructure:"k8s" yaml:"k8s"` - } + Buildpack buildpack.Config `mapstructure:"buildpack" yaml:"buildpack"` Controller grpc.ControllerServiceClientConfig `mapstructure:"controller" yaml:"controller"` Priority int `mapstructure:"priority" yaml:"priority"` } @@ -148,20 +143,10 @@ func init() { viper.SetDefault("components.builder.buildkit.address", appdefaults.Address) - viper.SetDefault("components.builder.buildpack.backend", "docker") - viper.SetDefault("components.builder.buildpack.docker.containerName", "buildpack") - viper.SetDefault("components.builder.buildpack.docker.remoteDir", "/workspace") - viper.SetDefault("components.builder.buildpack.docker.user", "cnb") - viper.SetDefault("components.builder.buildpack.docker.group", "cnb") - viper.SetDefault("components.builder.buildpack.docker.platformAPI", "0.11") - viper.SetDefault("components.builder.buildpack.k8s.namespace", "ns-system") - viper.SetDefault("components.builder.buildpack.k8s.podName", "ns-builder") - viper.SetDefault("components.builder.buildpack.k8s.containerName", "buildpack") - viper.SetDefault("components.builder.buildpack.k8s.localDir", "/neoshowcase/buildpack") - viper.SetDefault("components.builder.buildpack.k8s.remoteDir", "/workspace") - viper.SetDefault("components.builder.buildpack.k8s.user", 1001) - viper.SetDefault("components.builder.buildpack.k8s.group", 1000) - viper.SetDefault("components.builder.buildpack.k8s.platformAPI", "0.11") + viper.SetDefault("components.builder.buildpack.helper.address", "http://localhost:1235") + viper.SetDefault("components.builder.buildpack.helper.listenPort", 1235) + viper.SetDefault("components.builder.buildpack.remoteDir", "/workspace") + viper.SetDefault("components.builder.buildpack.platformAPI", "0.11") viper.SetDefault("components.builder.controller.url", "http://ns-controller:10000") diff --git a/cmd/main.go b/cmd/main.go index 9c28c9ed3..b34455cee 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -71,6 +71,7 @@ func main() { rootCommand.AddCommand( componentCommand("auth-dev", NewAuthDev, ""), componentCommand("builder", NewBuilder, ""), + componentCommand("buildpack-helper", NewBuildpackHelper, ""), componentCommand("controller", NewController, ""), componentCommand("gateway", NewGateway, ""), componentCommand("gitea-integration", NewGiteaIntegration, `Synchronizes gitea user / organization repositories and its owners with configured interval. diff --git a/cmd/providers.go b/cmd/providers.go index 83a4a2f2b..effee6345 100644 --- a/cmd/providers.go +++ b/cmd/providers.go @@ -18,15 +18,14 @@ import ( "k8s.io/client-go/rest" authdev "github.com/traPtitech/neoshowcase/cmd/auth-dev" + buildpackhelper "github.com/traPtitech/neoshowcase/cmd/buildpack-helper" "github.com/traPtitech/neoshowcase/cmd/controller" "github.com/traPtitech/neoshowcase/cmd/gateway" "github.com/traPtitech/neoshowcase/pkg/domain" - "github.com/traPtitech/neoshowcase/pkg/domain/builder" "github.com/traPtitech/neoshowcase/pkg/domain/web" "github.com/traPtitech/neoshowcase/pkg/infrastructure/backend/dockerimpl" "github.com/traPtitech/neoshowcase/pkg/infrastructure/backend/k8simpl" - bdockerimpl "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack/dockerimpl" - bk8simpl "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack/k8simpl" + "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack" "github.com/traPtitech/neoshowcase/pkg/infrastructure/dbmanager" "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc" "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc/pb/pbconnect" @@ -63,6 +62,8 @@ var providers = wire.NewSet( giteaintegration.NewIntegration, grpc.NewAPIServiceServer, grpc.NewAuthInterceptor, + grpc.NewBuildpackHelperService, + provideBuildpackHelperClient, grpc.NewCacheInterceptor, grpc.NewControllerService, grpc.NewControllerServiceClient, @@ -95,7 +96,8 @@ var providers = wire.NewSet( domain.IntoPublicKey, provideStorage, provideAuthDevServer, - provideBuildpackBackend, + provideBuildpackHelperServer, + buildpack.NewBuildpackBackend, provideBuildkitClient, provideControllerServer, provideContainerLogger, @@ -150,16 +152,21 @@ func provideControllerBuilderServiceClient(c Config, auth *grpc.TokenAuthInterce ) } -func provideBuildpackBackend(c Config) (builder.BuildpackBackend, error) { - cc := c.Components.Builder - switch cc.Buildpack.Backend { - case "docker": - return bdockerimpl.NewBuildpackBackend(cc.Buildpack.Docker) - case "k8s": - return bk8simpl.NewBuildpackBackend(cc.Buildpack.K8s) - default: - return nil, errors.Errorf("invalid buildpack backend: %v", cc.Buildpack.Backend) +func provideBuildpackHelperClient(c Config) domain.BuildpackHelperServiceClient { + return grpc.NewBuildpackHelperServiceClient(c.Components.Builder.Buildpack.Helper.Address) +} + +func provideBuildpackHelperServer( + c Config, + helperServiceHandler pbconnect.BuildpackHelperServiceHandler, +) *buildpackhelper.APIServer { + wc := web.H2CConfig{ + Port: c.Components.Builder.Buildpack.Helper.ListenPort, + SetupRoute: func(mux *http.ServeMux) { + mux.Handle(pbconnect.NewBuildpackHelperServiceHandler(helperServiceHandler)) + }, } + return &buildpackhelper.APIServer{H2CServer: web.NewH2CServer(wc)} } func provideBuildkitClient(c Config) (*buildkit.Client, error) { diff --git a/cmd/wire.go b/cmd/wire.go index de120b80e..17ca8c399 100644 --- a/cmd/wire.go +++ b/cmd/wire.go @@ -9,6 +9,7 @@ import ( authdev "github.com/traPtitech/neoshowcase/cmd/auth-dev" "github.com/traPtitech/neoshowcase/cmd/builder" + buildpackhelper "github.com/traPtitech/neoshowcase/cmd/buildpack-helper" "github.com/traPtitech/neoshowcase/cmd/controller" "github.com/traPtitech/neoshowcase/cmd/gateway" giteaintegration "github.com/traPtitech/neoshowcase/cmd/gitea-integration" @@ -29,12 +30,22 @@ func NewAuthDev(c Config) (component, error) { func NewBuilder(c Config) (component, error) { wire.Build( providers, + wire.FieldsOf(new(BuilderConfig), "Buildpack"), wire.Bind(new(component), new(*builder.Server)), wire.Struct(new(builder.Server), "*"), ) return nil, nil } +func NewBuildpackHelper(c Config) (component, error) { + wire.Build( + providers, + wire.Bind(new(component), new(*buildpackhelper.Server)), + wire.Struct(new(buildpackhelper.Server), "*"), + ) + return nil, nil +} + func NewController(c Config) (component, error) { switch c.Components.Controller.Mode { case "docker": diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index 8b029d791..4b0ada033 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -10,6 +10,7 @@ import ( "github.com/cert-manager/cert-manager/pkg/client/clientset/versioned" "github.com/friendsofgo/errors" builder2 "github.com/traPtitech/neoshowcase/cmd/builder" + "github.com/traPtitech/neoshowcase/cmd/buildpack-helper" "github.com/traPtitech/neoshowcase/cmd/controller" "github.com/traPtitech/neoshowcase/cmd/gateway" giteaintegration2 "github.com/traPtitech/neoshowcase/cmd/gitea-integration" @@ -17,6 +18,7 @@ import ( "github.com/traPtitech/neoshowcase/pkg/domain" "github.com/traPtitech/neoshowcase/pkg/infrastructure/backend/dockerimpl" "github.com/traPtitech/neoshowcase/pkg/infrastructure/backend/k8simpl" + "github.com/traPtitech/neoshowcase/pkg/infrastructure/buildpack" "github.com/traPtitech/neoshowcase/pkg/infrastructure/dbmanager" "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc" "github.com/traPtitech/neoshowcase/pkg/infrastructure/repository" @@ -57,10 +59,11 @@ func NewBuilder(c Config) (component, error) { return nil, err } controllerBuilderServiceClient := provideControllerBuilderServiceClient(c, tokenAuthInterceptor) - buildpackBackend, err := provideBuildpackBackend(c) - if err != nil { - return nil, err - } + componentsConfig := c.Components + builderConfig := componentsConfig.Builder + buildpackConfig := builderConfig.Buildpack + buildpackHelperServiceClient := provideBuildpackHelperClient(c) + buildpackBackend := buildpack.NewBuildpackBackend(buildpackConfig, buildpackHelperServiceClient) service, err := builder.NewService(controllerBuilderServiceClient, client, buildpackBackend) if err != nil { return nil, err @@ -72,6 +75,15 @@ func NewBuilder(c Config) (component, error) { return server, nil } +func NewBuildpackHelper(c Config) (component, error) { + buildpackHelperServiceHandler := grpc.NewBuildpackHelperService() + apiServer := provideBuildpackHelperServer(c, buildpackHelperServiceHandler) + server := &buildpackhelper.Server{ + Helper: apiServer, + } + return server, nil +} + func NewControllerDocker(c Config) (component, error) { client, err := dockerimpl.NewClientFromEnv() if err != nil { diff --git a/compose.yaml b/compose.yaml index 1f06b0b6f..e930877c9 100644 --- a/compose.yaml +++ b/compose.yaml @@ -132,7 +132,6 @@ services: command: --debug --loglevel=trace --config=/config.yaml restart: always volumes: - - /var/run/docker.sock:/var/run/docker.sock - ./.local-dev/config/ns.yaml:/config.yaml - ./.local-dev/keys:/keys - ./.local-dev/local-storage:/data @@ -147,6 +146,44 @@ services: networks: - default + buildpack-install: + build: + context: . + target: ns + image: ghcr.io/traptitech/ns:main + restart: "no" + entrypoint: cp /app/ns /ns-bin + volumes: + - binary:/ns-bin + + buildpack: + image: paketobuildpacks/builder-jammy-full:latest + restart: always + entrypoint: + - /ns-bin/ns + - buildpack-helper + command: --debug --loglevel=trace --config=/config.yaml + expose: + - 1235 + volumes: + - binary:/ns-bin + - ./.local-dev/config/ns.yaml:/config.yaml + depends_on: + buildpack-install: + condition: service_completed_successfully + networks: + - default + + buildkitd: + image: moby/buildkit:latest + restart: always + privileged: true + command: --addr tcp://0.0.0.0:1234 + volumes: + - ./.local-dev/buildkitd/buildkitd.toml:/etc/buildkit/buildkitd.toml + networks: + - default + static-server: image: caddy:2-alpine restart: always @@ -232,25 +269,6 @@ services: networks: - default - buildpack: - image: paketobuildpacks/builder-jammy-full:latest - restart: always - entrypoint: - - sleep - - infinity - networks: - - default - - buildkitd: - image: moby/buildkit:latest - restart: always - privileged: true - command: --addr tcp://0.0.0.0:1234 - volumes: - - ./.local-dev/buildkitd/buildkitd.toml:/etc/buildkit/buildkitd.toml - networks: - - default - mysql: image: mariadb:10 restart: always @@ -411,3 +429,6 @@ networks: apps: name: neoshowcase_apps external: true + +volumes: + binary: diff --git a/pkg/domain/component.go b/pkg/domain/component.go index 3aa082690..995df28b5 100644 --- a/pkg/domain/component.go +++ b/pkg/domain/component.go @@ -2,6 +2,7 @@ package domain import ( "context" + "io" "github.com/go-git/go-git/v5/plumbing/transport/ssh" @@ -48,6 +49,17 @@ type ControllerBuilderServiceClient interface { ConnectBuilder(ctx context.Context, onRequest func(req *pb.BuilderRequest), response <-chan *pb.BuilderResponse) error } +type BuildpackHelperServiceClient interface { + CopyFileTree(ctx context.Context, destination string, tarStream io.Reader) error + Exec( + ctx context.Context, + workDir string, + cmd []string, + envs map[string]string, + logWriter io.Writer, + ) (code int, err error) +} + type ControllerSSGenService interface { pbconnect.ControllerSSGenServiceHandler BroadcastSSGen(req *pb.SSGenRequest) diff --git a/pkg/infrastructure/buildpack/backend.go b/pkg/infrastructure/buildpack/backend.go new file mode 100644 index 000000000..701cd7047 --- /dev/null +++ b/pkg/infrastructure/buildpack/backend.go @@ -0,0 +1,158 @@ +package buildpack + +import ( + "context" + "encoding/json" + "fmt" + log "github.com/sirupsen/logrus" + "io" + "os" + "path/filepath" + "strings" + + "github.com/docker/cli/cli/config/configfile" + types2 "github.com/docker/cli/cli/config/types" + "github.com/friendsofgo/errors" + + "github.com/traPtitech/neoshowcase/pkg/domain" + "github.com/traPtitech/neoshowcase/pkg/domain/builder" + "github.com/traPtitech/neoshowcase/pkg/util/tarfs" +) + +type backend struct { + config Config + client domain.BuildpackHelperServiceClient +} + +func NewBuildpackBackend( + config Config, + client domain.BuildpackHelperServiceClient, +) builder.BuildpackBackend { + return &backend{ + config: config, + client: client, + } +} + +func (b *backend) dockerAuth(imageConfig builder.ImageConfig) (s string, ok bool) { + if imageConfig.Registry.Username == "" && imageConfig.Registry.Password == "" { + return "", false + } + c := configfile.ConfigFile{ + AuthConfigs: map[string]types2.AuthConfig{ + imageConfig.Registry.Addr: { + Username: imageConfig.Registry.Username, + Password: imageConfig.Registry.Password, + }, + }, + } + bytes, _ := json.Marshal(&c) + return string(bytes), true +} + +func escapeSingleQuote(s string) string { + return strings.ReplaceAll(s, "'", "\\'") +} + +func (b *backend) exec(ctx context.Context, workDir string, cmd []string, env map[string]string, logWriter io.Writer) error { + code, err := b.client.Exec(ctx, workDir, cmd, env, logWriter) + if err != nil { + return err + } + if code != 0 { + return errors.Wrap(err, fmt.Sprintf("command exited with code %d", code)) + } + return nil +} + +func (b *backend) prepareAuth(imageConfig builder.ImageConfig) error { + auth, ok := b.dockerAuth(imageConfig) + if ok { + err := b.exec(context.Background(), "/", []string{"sh", "-c", "mkdir -p ~/.docker"}, nil, io.Discard) + if err != nil { + return errors.Wrap(err, "making ~/.docker directory") + } + err = b.exec(context.Background(), "/", []string{"sh", "-c", fmt.Sprintf(`echo '%s' > ~/.docker/config.json`, escapeSingleQuote(auth))}, nil, io.Discard) + if err != nil { + return errors.Wrap(err, "writing ~/.docker/config.json to builder") + } + } + return nil +} + +func (b *backend) prepareDir(ctx context.Context, localName, remoteName string) (remotePath string, cleanup func(), err error) { + remotePath = filepath.Join(b.config.RemoteDir, remoteName) + err = b.exec(ctx, b.config.RemoteDir, []string{"mkdir", remotePath}, nil, io.Discard) + if err != nil { + return "", nil, errors.Wrap(err, "making remote tmp dir") + } + cleanup = func() { + err := b.exec(context.Background(), b.config.RemoteDir, []string{"rm", "-r", remotePath}, nil, io.Discard) + if err != nil { + log.Errorf("failed to remove tmp repo dir: %+v", err) + } + } + + err = b.client.CopyFileTree(ctx, remotePath, tarfs.Compress(localName)) + if err != nil { + cleanup() + return "", nil, errors.Wrap(err, "copying files to container") + } + return remotePath, cleanup, nil +} + +func (b *backend) Pack( + ctx context.Context, + repoDir string, + imageDest string, + imageConfig builder.ImageConfig, + env map[string]string, + logWriter io.Writer, +) (path string, err error) { + err = b.prepareAuth(imageConfig) + if err != nil { + return "", err + } + + remoteRepoPath, cleanupRepoDir, err := b.prepareDir(ctx, repoDir, "ns-repo") + if err != nil { + return "", err + } + defer cleanupRepoDir() + + localEnvTmp, err := os.MkdirTemp("", "env-") + if err != nil { + return "", errors.Wrap(err, "creating env temp dir") + } + defer os.RemoveAll(localEnvTmp) + err = os.Mkdir(filepath.Join(localEnvTmp, "env"), 0700) + if err != nil { + return "", errors.Wrap(err, "creating platform env dir") + } + for k, v := range env { + err = os.WriteFile(filepath.Join(localEnvTmp, "env", k), []byte(v), 0600) + if err != nil { + return "", errors.Wrap(err, "creating env file") + } + } + remoteEnvPath, cleanupEnvDir, err := b.prepareDir(ctx, localEnvTmp, "ns-env") + if err != nil { + return "", err + } + defer cleanupEnvDir() + + // TODO: support pushing to insecure registry for local development + // https://github.com/buildpacks/lifecycle/issues/524 + // https://github.com/buildpacks/rfcs/blob/main/text/0111-support-insecure-registries.md + // Workaround: use registry host "*.local" to allow google/go-containerregistry to detect as http protocol + // see: https://github.com/traPtitech/NeoShowcase/issues/493 + err = b.exec(ctx, + remoteRepoPath, + []string{"/cnb/lifecycle/creator", "-skip-restore", "-platform=" + remoteEnvPath, "-app=.", imageDest}, + map[string]string{"CNB_PLATFORM_API": b.config.PlatformAPI}, + logWriter) + if err != nil { + return "", err + } + return remoteRepoPath, nil +} diff --git a/pkg/infrastructure/buildpack/config.go b/pkg/infrastructure/buildpack/config.go new file mode 100644 index 000000000..d78beedf7 --- /dev/null +++ b/pkg/infrastructure/buildpack/config.go @@ -0,0 +1,10 @@ +package buildpack + +type Config struct { + Helper struct { + Address string `mapstructure:"address" yaml:"address"` + ListenPort int `mapstructure:"listenPort" yaml:"listenPort"` + } `mapstructure:"helper" yaml:"helper"` + RemoteDir string `mapstructure:"remoteDir" yaml:"remoteDir"` + PlatformAPI string `mapstructure:"platformAPI" yaml:"platformAPI"` +} diff --git a/pkg/infrastructure/buildpack/dockerimpl/backend.go b/pkg/infrastructure/buildpack/dockerimpl/backend.go deleted file mode 100644 index eae0e1009..000000000 --- a/pkg/infrastructure/buildpack/dockerimpl/backend.go +++ /dev/null @@ -1,213 +0,0 @@ -package dockerimpl - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - "path/filepath" - "strings" - - "github.com/docker/cli/cli/config/configfile" - types2 "github.com/docker/cli/cli/config/types" - "github.com/docker/docker/api/types" - "github.com/docker/docker/client" - "github.com/docker/docker/pkg/stdcopy" - "github.com/friendsofgo/errors" - "github.com/samber/lo" - log "github.com/sirupsen/logrus" - - "github.com/traPtitech/neoshowcase/pkg/domain/builder" - "github.com/traPtitech/neoshowcase/pkg/util/ds" - "github.com/traPtitech/neoshowcase/pkg/util/tarfs" -) - -type dockerBackend struct { - c *client.Client - config Config -} - -func NewBuildpackBackend( - config Config, -) (builder.BuildpackBackend, error) { - c, err := client.NewClientWithOpts( - client.FromEnv, - // Using github.com/moby/moby of v25 master@032797ea4bcb (2023-09-05), required by github.com/moby/buildkit@v0.12.3, - // defaults to API version 1.44, which currently available docker installation does not support. - client.WithVersion("1.43"), - ) - if err != nil { - return nil, err - } - b := &dockerBackend{ - c: c, - config: config, - } - return b, nil -} - -func (d *dockerBackend) dockerAuth(imageConfig builder.ImageConfig) (s string, ok bool) { - if imageConfig.Registry.Username == "" && imageConfig.Registry.Password == "" { - return "", false - } - c := configfile.ConfigFile{ - AuthConfigs: map[string]types2.AuthConfig{ - imageConfig.Registry.Addr: { - Username: imageConfig.Registry.Username, - Password: imageConfig.Registry.Password, - }, - }, - } - b, _ := json.Marshal(&c) - return string(b), true -} - -func escapeSingleQuote(s string) string { - return strings.ReplaceAll(s, "'", "\\'") -} - -func (d *dockerBackend) prepareAuth(imageConfig builder.ImageConfig) error { - auth, ok := d.dockerAuth(imageConfig) - if ok { - err := d.exec(context.Background(), "/", []string{"sh", "-c", "mkdir -p ~/.docker"}, nil, io.Discard, io.Discard) - if err != nil { - return errors.Wrap(err, "making ~/.docker directory") - } - err = d.exec(context.Background(), "/", []string{"sh", "-c", fmt.Sprintf(`echo '%s' > ~/.docker/config.json`, escapeSingleQuote(auth))}, nil, io.Discard, io.Discard) - if err != nil { - return errors.Wrap(err, "writing ~/.docker/config.json to builder") - } - } - return nil -} - -func (d *dockerBackend) execRoot(ctx context.Context, workDir string, cmd []string, env map[string]string, outWriter, errWriter io.Writer) error { - return d._exec(ctx, true, workDir, cmd, env, outWriter, errWriter) -} - -func (d *dockerBackend) exec(ctx context.Context, workDir string, cmd []string, env map[string]string, outWriter, errWriter io.Writer) error { - return d._exec(ctx, false, workDir, cmd, env, outWriter, errWriter) -} - -func (d *dockerBackend) _exec(ctx context.Context, root bool, workDir string, cmd []string, env map[string]string, outWriter, errWriter io.Writer) error { - execConf := types.ExecConfig{ - AttachStderr: true, - AttachStdout: true, - WorkingDir: workDir, - Cmd: cmd, - Env: lo.MapToSlice(env, func(k, v string) string { return k + "=" + v }), - } - if root { - execConf.User = "root" - } else { - execConf.User = d.config.User - } - execID, err := d.c.ContainerExecCreate(ctx, d.config.ContainerName, execConf) - if err != nil { - return errors.Wrap(err, "creating exec") - } - - ex, err := d.c.ContainerExecAttach(ctx, execID.ID, types.ExecStartCheck{}) - if err != nil { - return errors.Wrap(err, "attaching exec process") - } - defer ex.Close() - - _, err = stdcopy.StdCopy(outWriter, errWriter, ex.Reader) - if err != nil { - return errors.Wrap(err, "reading exec response") - } - - res, err := d.c.ContainerExecInspect(ctx, execID.ID) - if err != nil { - return errors.Wrap(err, "inspecting exec result") - } - if res.ExitCode != 0 { - return errors.Errorf("exec %s failed with exit code %d", strings.Join(cmd, " "), res.ExitCode) - } - - return nil -} - -func (d *dockerBackend) prepareDir(ctx context.Context, localName, remoteName string) (remotePath string, cleanup func(), err error) { - remotePath = filepath.Join(d.config.RemoteDir, remoteName) - err = d.exec(ctx, d.config.RemoteDir, []string{"mkdir", remotePath}, nil, io.Discard, io.Discard) - if err != nil { - return "", nil, errors.Wrap(err, "making remote tmp dir") - } - cleanup = func() { - err := d.exec(context.Background(), d.config.RemoteDir, []string{"rm", "-r", remotePath}, nil, io.Discard, io.Discard) - if err != nil { - log.Errorf("failed to remove tmp repo dir: %+v", err) - } - } - - err = d.c.CopyToContainer(ctx, d.config.ContainerName, remotePath, tarfs.Compress(localName), types.CopyToContainerOptions{}) - if err != nil { - cleanup() - return "", nil, errors.Wrap(err, "copying files to container") - } - err = d.execRoot(ctx, d.config.RemoteDir, []string{"chown", "-R", d.config.User + ":" + d.config.Group, remotePath}, nil, io.Discard, io.Discard) - if err != nil { - cleanup() - return "", nil, errors.Wrap(err, "setting remote dir owner") - } - return remotePath, cleanup, nil -} - -func (d *dockerBackend) Pack( - ctx context.Context, - repoDir string, - imageDest string, - imageConfig builder.ImageConfig, - env map[string]string, - logWriter io.Writer, -) (path string, err error) { - err = d.prepareAuth(imageConfig) - if err != nil { - return "", err - } - - remoteRepoPath, cleanupRepoDir, err := d.prepareDir(ctx, repoDir, "ns-repo") - if err != nil { - return "", err - } - defer cleanupRepoDir() - - localEnvTmp, err := os.MkdirTemp("", "env-") - if err != nil { - return "", errors.Wrap(err, "creating env temp dir") - } - defer os.RemoveAll(localEnvTmp) - err = os.Mkdir(filepath.Join(localEnvTmp, "env"), 0700) - if err != nil { - return "", errors.Wrap(err, "creating platform env dir") - } - for k, v := range env { - err = os.WriteFile(filepath.Join(localEnvTmp, "env", k), []byte(v), 0600) - if err != nil { - return "", errors.Wrap(err, "creating env file") - } - } - remoteEnvPath, cleanupEnvDir, err := d.prepareDir(ctx, localEnvTmp, "ns-env") - if err != nil { - return "", err - } - defer cleanupEnvDir() - - // TODO: support pushing to insecure registry for local development - // https://github.com/buildpacks/lifecycle/issues/524 - // https://github.com/buildpacks/rfcs/blob/main/text/0111-support-insecure-registries.md - // Workaround: use registry host "*.local" to allow google/go-containerregistry to detect as http protocol - // see: https://github.com/traPtitech/NeoShowcase/issues/493 - err = d.exec(ctx, - remoteRepoPath, - []string{"/cnb/lifecycle/creator", "-skip-restore", "-platform=" + remoteEnvPath, "-app=.", imageDest}, - ds.MergeMap(env, map[string]string{"CNB_PLATFORM_API": d.config.PlatformAPI}), - logWriter, logWriter) - if err != nil { - return "", err - } - return remoteRepoPath, nil -} diff --git a/pkg/infrastructure/buildpack/dockerimpl/config.go b/pkg/infrastructure/buildpack/dockerimpl/config.go deleted file mode 100644 index ab1f7cd84..000000000 --- a/pkg/infrastructure/buildpack/dockerimpl/config.go +++ /dev/null @@ -1,9 +0,0 @@ -package dockerimpl - -type Config struct { - ContainerName string `mapstructure:"containerName" yaml:"containerName"` - RemoteDir string `mapstructure:"remoteDir" yaml:"remoteDir"` - User string `mapstructure:"user" yaml:"user"` - Group string `mapstructure:"group" yaml:"group"` - PlatformAPI string `mapstructure:"platformAPI" yaml:"platformAPI"` -} diff --git a/pkg/infrastructure/buildpack/k8simpl/backend.go b/pkg/infrastructure/buildpack/k8simpl/backend.go deleted file mode 100644 index 22c2e571b..000000000 --- a/pkg/infrastructure/buildpack/k8simpl/backend.go +++ /dev/null @@ -1,202 +0,0 @@ -package k8simpl - -import ( - "context" - "encoding/json" - "fmt" - "io" - "os" - "os/exec" - "path/filepath" - "strings" - - "github.com/docker/cli/cli/config/configfile" - types2 "github.com/docker/cli/cli/config/types" - "github.com/friendsofgo/errors" - log "github.com/sirupsen/logrus" - v1 "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/remotecommand" - - "github.com/traPtitech/neoshowcase/pkg/domain/builder" - "github.com/traPtitech/neoshowcase/pkg/util/ds" -) - -type k8sBackend struct { - c *kubernetes.Clientset - restConfig *rest.Config - config Config -} - -func NewBuildpackBackend( - config Config, -) (builder.BuildpackBackend, error) { - restConfig, err := rest.InClusterConfig() - if err != nil { - return nil, err - } - c, err := kubernetes.NewForConfig(restConfig) - if err != nil { - return nil, err - } - b := &k8sBackend{ - c: c, - restConfig: restConfig, - config: config, - } - return b, nil -} - -func (k *k8sBackend) dockerAuth(imageConfig builder.ImageConfig) (s string, ok bool) { - if imageConfig.Registry.Username == "" && imageConfig.Registry.Password == "" { - return "", false - } - c := configfile.ConfigFile{ - AuthConfigs: map[string]types2.AuthConfig{ - imageConfig.Registry.Addr: { - Username: imageConfig.Registry.Username, - Password: imageConfig.Registry.Password, - }, - }, - } - b, _ := json.Marshal(&c) - return string(b), true -} - -func escapeSingleQuote(s string) string { - return strings.ReplaceAll(s, "'", "\\'") -} - -func (k *k8sBackend) prepareAuth(imageConfig builder.ImageConfig) error { - auth, ok := k.dockerAuth(imageConfig) - if ok { - err := k.exec(context.Background(), "/", "mkdir -p ~/.docker", nil, io.Discard, io.Discard) - if err != nil { - return errors.Wrap(err, "making ~/.docker directory") - } - err = k.exec(context.Background(), "/", fmt.Sprintf(`echo '%s' > ~/.docker/config.json`, escapeSingleQuote(auth)), nil, io.Discard, io.Discard) - if err != nil { - return errors.Wrap(err, "writing ~/.docker/config.json to builder") - } - } - return nil -} - -func (k *k8sBackend) exec(ctx context.Context, workDir string, cmd string, env map[string]string, stdout io.Writer, stderr io.Writer) error { - req := k.c.CoreV1().RESTClient().Post().Resource("pods").Name(k.config.PodName). - Namespace(k.config.Namespace).SubResource("exec") - var shCmds []string - for k, v := range env { - shCmds = append(shCmds, fmt.Sprintf("export %v=\"%v\"", k, strings.ReplaceAll(v, `"`, `\"`))) - } - shCmds = append(shCmds, - "cd "+workDir, - cmd) - option := &v1.PodExecOptions{ - Command: []string{"sh", "-c", strings.Join(shCmds, " && ")}, - Stdout: true, - Stderr: true, - Container: k.config.ContainerName, - } - req.VersionedParams(option, scheme.ParameterCodec) - ex, err := remotecommand.NewSPDYExecutor(k.restConfig, "POST", req.URL()) - if err != nil { - return err - } - err = ex.StreamWithContext(ctx, remotecommand.StreamOptions{ - Stdout: stdout, - Stderr: stderr, - }) - if err != nil { - return err - } - return nil -} - -func (k *k8sBackend) prepareDir(ctx context.Context, localName, remoteName string) (remotePath string, cleanup func(), err error) { - localVolumePath := filepath.Join(k.config.LocalDir, remoteName) - remotePath = filepath.Join(k.config.RemoteDir, remoteName) - err = exec.CommandContext(ctx, "cp", "-r", localName, localVolumePath).Run() - if err != nil { - return "", nil, errors.Wrap(err, "copying files") - } - cleanup = func() { - err := exec.Command("rm", "-r", localVolumePath).Run() - if err != nil { - log.Errorf("failed to rm tmp dir: %+v", err) - } - } - - err = exec.CommandContext(ctx, "chown", "-R", fmt.Sprintf("%d:%d", k.config.User, k.config.Group), localVolumePath).Run() - if err != nil { - cleanup() - return "", nil, errors.Wrap(err, "setting remote dir owner") - } - // Build user (cnb 1001) and run user (cnb 1002) is different for paketobuildpacks/builder-jammy series - // Setting all file bits to 777 as a workaround, but not sure if this is the right way to handle this - err = exec.CommandContext(ctx, "chmod", "-R", "777", localVolumePath).Run() - if err != nil { - cleanup() - return "", nil, errors.Wrap(err, "setting remote dir mode") - } - return remotePath, cleanup, nil -} - -func (k *k8sBackend) Pack( - ctx context.Context, - repoDir string, - imageDest string, - imageConfig builder.ImageConfig, - env map[string]string, - logWriter io.Writer, -) (path string, err error) { - err = k.prepareAuth(imageConfig) - if err != nil { - return "", err - } - - // NOTE: safe to use the same remote name between builds, under the assumption that buildpack pod is not shared - remoteRepoPath, cleanupRepoDir, err := k.prepareDir(ctx, repoDir, "ns-repo") - if err != nil { - return "", err - } - defer cleanupRepoDir() - - localEnvTmp, err := os.MkdirTemp("", "env-") - if err != nil { - return "", errors.Wrap(err, "creating env temp dir") - } - defer os.RemoveAll(localEnvTmp) - err = os.Mkdir(filepath.Join(localEnvTmp, "env"), 0700) - if err != nil { - return "", errors.Wrap(err, "creating platform env dir") - } - for k, v := range env { - err = os.WriteFile(filepath.Join(localEnvTmp, "env", k), []byte(v), 0600) - if err != nil { - return "", errors.Wrap(err, "creating env file") - } - } - remoteEnvPath, cleanupEnvDir, err := k.prepareDir(ctx, localEnvTmp, "ns-env") - if err != nil { - return "", err - } - defer cleanupEnvDir() - - // TODO: support pushing to insecure registry for local development - // https://github.com/buildpacks/lifecycle/issues/524 - // https://github.com/buildpacks/rfcs/blob/main/text/0111-support-insecure-registries.md - // Workaround: use registry host "*.local" to allow google/go-containerregistry to detect as http protocol - // see: https://github.com/traPtitech/NeoShowcase/issues/493 - err = k.exec(ctx, - remoteRepoPath, - fmt.Sprintf("/cnb/lifecycle/creator -skip-restore -platform=%s -app=. %s", remoteEnvPath, imageDest), - ds.MergeMap(env, map[string]string{"CNB_PLATFORM_API": k.config.PlatformAPI}), - logWriter, logWriter) - if err != nil { - return "", err - } - return remoteRepoPath, nil -} diff --git a/pkg/infrastructure/buildpack/k8simpl/config.go b/pkg/infrastructure/buildpack/k8simpl/config.go deleted file mode 100644 index f771434d7..000000000 --- a/pkg/infrastructure/buildpack/k8simpl/config.go +++ /dev/null @@ -1,12 +0,0 @@ -package k8simpl - -type Config struct { - Namespace string `mapstructure:"namespace" yaml:"namespace"` - PodName string `mapstructure:"podName" yaml:"podName"` - ContainerName string `mapstructure:"containerName" yaml:"containerName"` - LocalDir string `mapstructure:"localDir" yaml:"localDir"` - RemoteDir string `mapstructure:"remoteDir" yaml:"remoteDir"` - User int `mapstructure:"user" yaml:"user"` - Group int `mapstructure:"group" yaml:"group"` - PlatformAPI string `mapstructure:"platformAPI" yaml:"platformAPI"` -} diff --git a/pkg/infrastructure/grpc/buildpack_helper_service.go b/pkg/infrastructure/grpc/buildpack_helper_service.go new file mode 100644 index 000000000..0319dab76 --- /dev/null +++ b/pkg/infrastructure/grpc/buildpack_helper_service.go @@ -0,0 +1,102 @@ +package grpc + +import ( + "bytes" + "context" + "github.com/friendsofgo/errors" + "golang.org/x/sync/errgroup" + "io" + "os" + "os/exec" + "sync" + + "connectrpc.com/connect" + "google.golang.org/protobuf/types/known/emptypb" + + "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc/pb" + "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc/pb/pbconnect" + "github.com/traPtitech/neoshowcase/pkg/util/ds" + "github.com/traPtitech/neoshowcase/pkg/util/tarfs" +) + +type BuildpackHelperService struct { + ssGenConnections []*ssGenConnection + lock sync.Mutex +} + +func NewBuildpackHelperService() pbconnect.BuildpackHelperServiceHandler { + return &BuildpackHelperService{} +} + +func (b *BuildpackHelperService) CopyFileTree(_ context.Context, req *connect.Request[pb.CopyFileTreeRequest]) (*connect.Response[emptypb.Empty], error) { + err := tarfs.Extract(bytes.NewReader(req.Msg.TarContent), req.Msg.Destination) + if err != nil { + return nil, err + } + res := connect.NewResponse(&emptypb.Empty{}) + return res, nil +} + +type buildpackHelperExec struct { + st *connect.ServerStream[pb.HelperExecResponse] +} + +var _ io.Writer = (*buildpackHelperExec)(nil) + +func (b *buildpackHelperExec) Write(p []byte) (n int, err error) { + err = b.st.Send(&pb.HelperExecResponse{ + Type: pb.HelperExecResponse_LOG, + Body: &pb.HelperExecResponse_Log{Log: p}, + }) + if err != nil { + return 0, err + } + return len(p), nil +} + +func (b *BuildpackHelperService) Exec(ctx context.Context, req *connect.Request[pb.HelperExecRequest], st *connect.ServerStream[pb.HelperExecResponse]) error { + if len(req.Msg.Cmd) == 0 { + return connect.NewError(connect.CodeInvalidArgument, errors.New("cmd cannot have length of 0")) + } + + // Prepare command + cmd := exec.CommandContext(ctx, req.Msg.Cmd[0], req.Msg.Cmd[1:]...) + cmd.Dir = req.Msg.WorkDir + cmd.Env = os.Environ() + additionalEnvs := ds.Map(req.Msg.Envs, func(env *pb.HelperExecEnv) string { return env.Key + "=" + env.Value }) + cmd.Env = append(cmd.Env, additionalEnvs...) // Inherit important envs such as CNB_STACK_ID + + pr, pw := io.Pipe() + cmd.Stdout = pw + cmd.Stderr = pw + + // Run command and send logs + var eg errgroup.Group + eg.Go(func() error { + dst := &buildpackHelperExec{st: st} + _, err := io.Copy(dst, pr) + return err + }) + cmdErr := cmd.Run() + _ = pw.Close() + logErr := eg.Wait() + if logErr != nil { + return logErr + } + + // Check exit code + var exitError *exec.ExitError + if errors.As(cmdErr, &exitError) { + return st.Send(&pb.HelperExecResponse{ + Type: pb.HelperExecResponse_EXIT_CODE, + Body: &pb.HelperExecResponse_ExitCode{ExitCode: int32(exitError.ExitCode())}, + }) + } + if cmdErr != nil { + return cmdErr + } + return st.Send(&pb.HelperExecResponse{ + Type: pb.HelperExecResponse_EXIT_CODE, + Body: &pb.HelperExecResponse_ExitCode{ExitCode: 0}, + }) +} diff --git a/pkg/infrastructure/grpc/buildpack_helper_service_client.go b/pkg/infrastructure/grpc/buildpack_helper_service_client.go new file mode 100644 index 000000000..5269e5d4e --- /dev/null +++ b/pkg/infrastructure/grpc/buildpack_helper_service_client.go @@ -0,0 +1,79 @@ +package grpc + +import ( + "connectrpc.com/connect" + "context" + "github.com/friendsofgo/errors" + "github.com/samber/lo" + "io" + + "github.com/traPtitech/neoshowcase/pkg/domain" + "github.com/traPtitech/neoshowcase/pkg/domain/web" + "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc/pb" + "github.com/traPtitech/neoshowcase/pkg/infrastructure/grpc/pb/pbconnect" +) + +type BuildpackHelperServiceClient struct { + client pbconnect.BuildpackHelperServiceClient +} + +func NewBuildpackHelperServiceClient( + address string, +) domain.BuildpackHelperServiceClient { + return &BuildpackHelperServiceClient{ + client: pbconnect.NewBuildpackHelperServiceClient(web.NewH2CClient(), address), + } +} + +func (b *BuildpackHelperServiceClient) CopyFileTree(ctx context.Context, destination string, tarStream io.Reader) error { + content, err := io.ReadAll(tarStream) + if err != nil { + return err + } + req := connect.NewRequest(&pb.CopyFileTreeRequest{ + Destination: destination, + TarContent: content, + }) + _, err = b.client.CopyFileTree(ctx, req) + return err +} + +func (b *BuildpackHelperServiceClient) Exec(ctx context.Context, workDir string, cmd []string, envs map[string]string, logWriter io.Writer) (int, error) { + arrayEnvs := lo.MapToSlice(envs, func(key string, value string) *pb.HelperExecEnv { + return &pb.HelperExecEnv{ + Key: key, + Value: value, + } + }) + req := connect.NewRequest(&pb.HelperExecRequest{ + WorkDir: workDir, + Cmd: cmd, + Envs: arrayEnvs, + }) + st, err := b.client.Exec(ctx, req) + if err != nil { + return 0, errors.Wrap(err, "requesting exec") + } + var exitCode *int + for st.Receive() { + msg := st.Msg() + switch msg.Type { + case pb.HelperExecResponse_LOG: + payload := msg.Body.(*pb.HelperExecResponse_Log).Log + _, err = logWriter.Write(payload) + if err != nil { + return 0, err + } + case pb.HelperExecResponse_EXIT_CODE: + payload := int(msg.Body.(*pb.HelperExecResponse_ExitCode).ExitCode) + exitCode = &payload + } + } + if err := st.Err(); err != nil { + return 0, errors.Wrap(err, "receiving logs") + } + if exitCode == nil { + return 0, errors.New("exit code not received") + } + return *exitCode, nil +} diff --git a/pkg/infrastructure/grpc/pb/controller.pb.go b/pkg/infrastructure/grpc/pb/controller.pb.go index 9e908f073..b2ae3715f 100644 --- a/pkg/infrastructure/grpc/pb/controller.pb.go +++ b/pkg/infrastructure/grpc/pb/controller.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.4 +// protoc-gen-go v1.32.0 +// protoc v4.25.1 // source: neoshowcase/protobuf/controller.proto package pb @@ -113,6 +113,52 @@ func (BuilderResponse_Type) EnumDescriptor() ([]byte, []int) { return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{10, 0} } +type HelperExecResponse_Type int32 + +const ( + HelperExecResponse_LOG HelperExecResponse_Type = 0 + HelperExecResponse_EXIT_CODE HelperExecResponse_Type = 1 +) + +// Enum value maps for HelperExecResponse_Type. +var ( + HelperExecResponse_Type_name = map[int32]string{ + 0: "LOG", + 1: "EXIT_CODE", + } + HelperExecResponse_Type_value = map[string]int32{ + "LOG": 0, + "EXIT_CODE": 1, + } +) + +func (x HelperExecResponse_Type) Enum() *HelperExecResponse_Type { + p := new(HelperExecResponse_Type) + *p = x + return p +} + +func (x HelperExecResponse_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HelperExecResponse_Type) Descriptor() protoreflect.EnumDescriptor { + return file_neoshowcase_protobuf_controller_proto_enumTypes[2].Descriptor() +} + +func (HelperExecResponse_Type) Type() protoreflect.EnumType { + return &file_neoshowcase_protobuf_controller_proto_enumTypes[2] +} + +func (x HelperExecResponse_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HelperExecResponse_Type.Descriptor instead. +func (HelperExecResponse_Type) EnumDescriptor() ([]byte, []int) { + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{14, 0} +} + type SSGenRequest_Type int32 const ( @@ -140,11 +186,11 @@ func (x SSGenRequest_Type) String() string { } func (SSGenRequest_Type) Descriptor() protoreflect.EnumDescriptor { - return file_neoshowcase_protobuf_controller_proto_enumTypes[2].Descriptor() + return file_neoshowcase_protobuf_controller_proto_enumTypes[3].Descriptor() } func (SSGenRequest_Type) Type() protoreflect.EnumType { - return &file_neoshowcase_protobuf_controller_proto_enumTypes[2] + return &file_neoshowcase_protobuf_controller_proto_enumTypes[3] } func (x SSGenRequest_Type) Number() protoreflect.EnumNumber { @@ -153,7 +199,7 @@ func (x SSGenRequest_Type) Number() protoreflect.EnumNumber { // Deprecated: Use SSGenRequest_Type.Descriptor instead. func (SSGenRequest_Type) EnumDescriptor() ([]byte, []int) { - return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{11, 0} + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{15, 0} } type GiteaIntegrationRequest_Type int32 @@ -183,11 +229,11 @@ func (x GiteaIntegrationRequest_Type) String() string { } func (GiteaIntegrationRequest_Type) Descriptor() protoreflect.EnumDescriptor { - return file_neoshowcase_protobuf_controller_proto_enumTypes[3].Descriptor() + return file_neoshowcase_protobuf_controller_proto_enumTypes[4].Descriptor() } func (GiteaIntegrationRequest_Type) Type() protoreflect.EnumType { - return &file_neoshowcase_protobuf_controller_proto_enumTypes[3] + return &file_neoshowcase_protobuf_controller_proto_enumTypes[4] } func (x GiteaIntegrationRequest_Type) Number() protoreflect.EnumNumber { @@ -196,7 +242,7 @@ func (x GiteaIntegrationRequest_Type) Number() protoreflect.EnumNumber { // Deprecated: Use GiteaIntegrationRequest_Type.Descriptor instead. func (GiteaIntegrationRequest_Type) EnumDescriptor() ([]byte, []int) { - return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{12, 0} + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{16, 0} } type ImageConfig struct { @@ -378,7 +424,7 @@ type SaveArtifactRequest struct { unknownFields protoimpl.UnknownFields Artifact *Artifact `protobuf:"bytes,1,opt,name=artifact,proto3" json:"artifact,omitempty"` - Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` + Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` // TODO: stream contents? } func (x *SaveArtifactRequest) Reset() { @@ -905,6 +951,268 @@ func (*BuilderResponse_Connected) isBuilderResponse_Body() {} func (*BuilderResponse_Settled) isBuilderResponse_Body() {} +type CopyFileTreeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Destination string `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"` + TarContent []byte `protobuf:"bytes,2,opt,name=tar_content,json=tarContent,proto3" json:"tar_content,omitempty"` // TODO: stream contents? +} + +func (x *CopyFileTreeRequest) Reset() { + *x = CopyFileTreeRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CopyFileTreeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CopyFileTreeRequest) ProtoMessage() {} + +func (x *CopyFileTreeRequest) ProtoReflect() protoreflect.Message { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[11] + 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 CopyFileTreeRequest.ProtoReflect.Descriptor instead. +func (*CopyFileTreeRequest) Descriptor() ([]byte, []int) { + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{11} +} + +func (x *CopyFileTreeRequest) GetDestination() string { + if x != nil { + return x.Destination + } + return "" +} + +func (x *CopyFileTreeRequest) GetTarContent() []byte { + if x != nil { + return x.TarContent + } + return nil +} + +type HelperExecEnv struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *HelperExecEnv) Reset() { + *x = HelperExecEnv{} + if protoimpl.UnsafeEnabled { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelperExecEnv) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelperExecEnv) ProtoMessage() {} + +func (x *HelperExecEnv) ProtoReflect() protoreflect.Message { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[12] + 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 HelperExecEnv.ProtoReflect.Descriptor instead. +func (*HelperExecEnv) Descriptor() ([]byte, []int) { + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{12} +} + +func (x *HelperExecEnv) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *HelperExecEnv) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + +type HelperExecRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + WorkDir string `protobuf:"bytes,1,opt,name=work_dir,json=workDir,proto3" json:"work_dir,omitempty"` + Cmd []string `protobuf:"bytes,2,rep,name=cmd,proto3" json:"cmd,omitempty"` + Envs []*HelperExecEnv `protobuf:"bytes,3,rep,name=envs,proto3" json:"envs,omitempty"` +} + +func (x *HelperExecRequest) Reset() { + *x = HelperExecRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelperExecRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelperExecRequest) ProtoMessage() {} + +func (x *HelperExecRequest) ProtoReflect() protoreflect.Message { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[13] + 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 HelperExecRequest.ProtoReflect.Descriptor instead. +func (*HelperExecRequest) Descriptor() ([]byte, []int) { + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{13} +} + +func (x *HelperExecRequest) GetWorkDir() string { + if x != nil { + return x.WorkDir + } + return "" +} + +func (x *HelperExecRequest) GetCmd() []string { + if x != nil { + return x.Cmd + } + return nil +} + +func (x *HelperExecRequest) GetEnvs() []*HelperExecEnv { + if x != nil { + return x.Envs + } + return nil +} + +type HelperExecResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type HelperExecResponse_Type `protobuf:"varint,1,opt,name=type,proto3,enum=neoshowcase.protobuf.HelperExecResponse_Type" json:"type,omitempty"` + // Types that are assignable to Body: + // + // *HelperExecResponse_Log + // *HelperExecResponse_ExitCode + Body isHelperExecResponse_Body `protobuf_oneof:"body"` +} + +func (x *HelperExecResponse) Reset() { + *x = HelperExecResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelperExecResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelperExecResponse) ProtoMessage() {} + +func (x *HelperExecResponse) ProtoReflect() protoreflect.Message { + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[14] + 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 HelperExecResponse.ProtoReflect.Descriptor instead. +func (*HelperExecResponse) Descriptor() ([]byte, []int) { + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{14} +} + +func (x *HelperExecResponse) GetType() HelperExecResponse_Type { + if x != nil { + return x.Type + } + return HelperExecResponse_LOG +} + +func (m *HelperExecResponse) GetBody() isHelperExecResponse_Body { + if m != nil { + return m.Body + } + return nil +} + +func (x *HelperExecResponse) GetLog() []byte { + if x, ok := x.GetBody().(*HelperExecResponse_Log); ok { + return x.Log + } + return nil +} + +func (x *HelperExecResponse) GetExitCode() int32 { + if x, ok := x.GetBody().(*HelperExecResponse_ExitCode); ok { + return x.ExitCode + } + return 0 +} + +type isHelperExecResponse_Body interface { + isHelperExecResponse_Body() +} + +type HelperExecResponse_Log struct { + Log []byte `protobuf:"bytes,2,opt,name=log,proto3,oneof"` +} + +type HelperExecResponse_ExitCode struct { + ExitCode int32 `protobuf:"varint,3,opt,name=exit_code,json=exitCode,proto3,oneof"` +} + +func (*HelperExecResponse_Log) isHelperExecResponse_Body() {} + +func (*HelperExecResponse_ExitCode) isHelperExecResponse_Body() {} + type SSGenRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -916,7 +1224,7 @@ type SSGenRequest struct { func (x *SSGenRequest) Reset() { *x = SSGenRequest{} if protoimpl.UnsafeEnabled { - mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[11] + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -929,7 +1237,7 @@ func (x *SSGenRequest) String() string { func (*SSGenRequest) ProtoMessage() {} func (x *SSGenRequest) ProtoReflect() protoreflect.Message { - mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[11] + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -942,7 +1250,7 @@ func (x *SSGenRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SSGenRequest.ProtoReflect.Descriptor instead. func (*SSGenRequest) Descriptor() ([]byte, []int) { - return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{11} + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{15} } func (x *SSGenRequest) GetType() SSGenRequest_Type { @@ -963,7 +1271,7 @@ type GiteaIntegrationRequest struct { func (x *GiteaIntegrationRequest) Reset() { *x = GiteaIntegrationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[12] + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -976,7 +1284,7 @@ func (x *GiteaIntegrationRequest) String() string { func (*GiteaIntegrationRequest) ProtoMessage() {} func (x *GiteaIntegrationRequest) ProtoReflect() protoreflect.Message { - mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[12] + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -989,7 +1297,7 @@ func (x *GiteaIntegrationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GiteaIntegrationRequest.ProtoReflect.Descriptor instead. func (*GiteaIntegrationRequest) Descriptor() ([]byte, []int) { - return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{12} + return file_neoshowcase_protobuf_controller_proto_rawDescGZIP(), []int{16} } func (x *GiteaIntegrationRequest) GetType() GiteaIntegrationRequest_Type { @@ -1013,7 +1321,7 @@ type ImageConfig_RegistryConfig struct { func (x *ImageConfig_RegistryConfig) Reset() { *x = ImageConfig_RegistryConfig{} if protoimpl.UnsafeEnabled { - mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[13] + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1026,7 +1334,7 @@ func (x *ImageConfig_RegistryConfig) String() string { func (*ImageConfig_RegistryConfig) ProtoMessage() {} func (x *ImageConfig_RegistryConfig) ProtoReflect() protoreflect.Message { - mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[13] + mi := &file_neoshowcase_protobuf_controller_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1190,104 +1498,145 @@ var file_neoshowcase_protobuf_controller_proto_rawDesc = []byte{ 0x73, 0x65, 0x74, 0x74, 0x6c, 0x65, 0x64, 0x22, 0x28, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x5f, 0x53, 0x45, 0x54, 0x54, 0x4c, 0x45, 0x44, 0x10, - 0x01, 0x42, 0x06, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x5f, 0x0a, 0x0c, 0x53, 0x53, 0x47, - 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, - 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x53, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, - 0x0a, 0x06, 0x52, 0x45, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x00, 0x22, 0x75, 0x0a, 0x17, 0x47, 0x69, + 0x01, 0x42, 0x06, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x58, 0x0a, 0x13, 0x43, 0x6f, 0x70, + 0x79, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x22, 0x37, 0x0a, 0x0d, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x45, 0x78, 0x65, + 0x63, 0x45, 0x6e, 0x76, 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, 0x22, 0x79, 0x0a, 0x11, + 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x19, 0x0a, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, + 0x63, 0x6d, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x12, 0x37, + 0x0a, 0x04, 0x65, 0x6e, 0x76, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6e, + 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x45, 0x6e, + 0x76, 0x52, 0x04, 0x65, 0x6e, 0x76, 0x73, 0x22, 0xb2, 0x01, 0x0a, 0x12, 0x48, 0x65, 0x6c, 0x70, + 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x6e, + 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x12, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, + 0x52, 0x03, 0x6c, 0x6f, 0x67, 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, 0x22, 0x1e, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, + 0x4c, 0x4f, 0x47, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x58, 0x49, 0x54, 0x5f, 0x43, 0x4f, + 0x44, 0x45, 0x10, 0x01, 0x42, 0x06, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x22, 0x5f, 0x0a, 0x0c, + 0x53, 0x53, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3b, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x6e, 0x65, 0x6f, + 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x53, 0x53, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x00, 0x22, 0x75, 0x0a, + 0x17, 0x47, 0x69, 0x74, 0x65, 0x61, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, + 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x69, 0x74, 0x65, 0x61, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x69, 0x74, 0x65, 0x61, - 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x12, 0x0a, - 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x59, 0x4e, 0x43, 0x10, - 0x00, 0x32, 0xf3, 0x03, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, - 0x66, 0x6f, 0x12, 0x54, 0x0a, 0x0f, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, - 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x53, 0x0a, 0x0d, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2a, 0x2e, 0x6e, 0x65, 0x6f, 0x73, - 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, - 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x58, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, - 0x6f, 0x67, 0x12, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x22, 0x12, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x53, 0x59, + 0x4e, 0x43, 0x10, 0x00, 0x32, 0xf3, 0x03, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x49, 0x0a, 0x0d, 0x47, 0x65, + 0x74, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, + 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x54, 0x0a, 0x0f, 0x46, 0x65, 0x74, 0x63, 0x68, 0x52, 0x65, + 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x30, 0x01, 0x12, 0x4b, 0x0a, 0x0b, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x73, - 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x9a, 0x04, 0x0a, 0x18, 0x43, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x12, 0x57, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, - 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x49, 0x0a, - 0x09, 0x50, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x24, 0x2e, 0x6e, 0x65, 0x6f, - 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, - 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x6f, 0x72, 0x74, 0x69, 0x6f, - 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x51, 0x0a, 0x0c, 0x53, - 0x61, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x29, 0x2e, 0x6e, 0x65, + 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x53, 0x0a, 0x0d, 0x52, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x2a, 0x2e, 0x6e, + 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x79, 0x6e, 0x63, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x58, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x12, 0x24, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, + 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, - 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x12, 0x29, + 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x30, 0x01, 0x12, 0x4b, 0x0a, + 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x24, 0x2e, 0x6e, + 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x9a, 0x04, 0x0a, 0x18, 0x43, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x57, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x42, 0x75, + 0x69, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x27, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, + 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x49, 0x6e, 0x66, 0x6f, + 0x12, 0x49, 0x0a, 0x09, 0x50, 0x69, 0x6e, 0x67, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x24, 0x2e, + 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x0e, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x12, 0x25, 0x2e, + 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x50, 0x6f, 0x72, + 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x28, 0x01, 0x12, 0x51, + 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, - 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x61, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x42, 0x75, 0x69, 0x6c, - 0x64, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x24, 0x2e, 0x6e, 0x65, 0x6f, - 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x28, 0x01, 0x30, 0x01, 0x32, 0x66, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, - 0x65, 0x72, 0x53, 0x53, 0x47, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, - 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x53, 0x47, 0x65, 0x6e, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, - 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x53, - 0x47, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x30, 0x01, 0x32, 0x77, 0x0a, 0x21, - 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x47, 0x69, 0x74, 0x65, 0x61, 0x49, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x12, 0x52, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x67, + 0x79, 0x12, 0x51, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4c, 0x6f, + 0x67, 0x12, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x42, 0x75, 0x69, + 0x6c, 0x64, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, - 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x69, 0x74, 0x65, - 0x61, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x30, 0x01, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x72, 0x61, 0x50, 0x74, 0x69, 0x74, 0x65, 0x63, 0x68, 0x2f, 0x6e, - 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x69, - 0x6e, 0x66, 0x72, 0x61, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2f, 0x67, 0x72, - 0x70, 0x63, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x61, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x42, + 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x12, 0x25, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, + 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, + 0x69, 0x6c, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x1a, 0x24, 0x2e, + 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x28, 0x01, 0x30, 0x01, 0x32, 0xc8, 0x01, 0x0a, 0x16, 0x42, 0x75, 0x69, 0x6c, + 0x64, 0x70, 0x61, 0x63, 0x6b, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x12, 0x51, 0x0a, 0x0c, 0x43, 0x6f, 0x70, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x54, 0x72, + 0x65, 0x65, 0x12, 0x29, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x46, 0x69, + 0x6c, 0x65, 0x54, 0x72, 0x65, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x5b, 0x0a, 0x04, 0x45, 0x78, 0x65, 0x63, 0x12, 0x27, 0x2e, + 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x70, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, + 0x63, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, + 0x6c, 0x70, 0x65, 0x72, 0x45, 0x78, 0x65, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x30, 0x01, 0x32, 0x66, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x53, 0x53, 0x47, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x0c, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x53, 0x53, 0x47, 0x65, 0x6e, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x22, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, + 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x53, 0x47, 0x65, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x30, 0x01, 0x32, 0x77, 0x0a, 0x21, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x47, 0x69, 0x74, 0x65, 0x61, 0x49, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x52, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x2d, 0x2e, 0x6e, 0x65, 0x6f, 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x69, 0x74, 0x65, 0x61, 0x49, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x30, 0x01, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x74, 0x72, 0x61, 0x50, 0x74, 0x69, 0x74, 0x65, 0x63, 0x68, 0x2f, 0x6e, 0x65, 0x6f, + 0x73, 0x68, 0x6f, 0x77, 0x63, 0x61, 0x73, 0x65, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x69, 0x6e, 0x66, + 0x72, 0x61, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x75, 0x72, 0x65, 0x2f, 0x67, 0x72, 0x70, 0x63, + 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1302,91 +1651,102 @@ func file_neoshowcase_protobuf_controller_proto_rawDescGZIP() []byte { return file_neoshowcase_protobuf_controller_proto_rawDescData } -var file_neoshowcase_protobuf_controller_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_neoshowcase_protobuf_controller_proto_msgTypes = make([]protoimpl.MessageInfo, 14) +var file_neoshowcase_protobuf_controller_proto_enumTypes = make([]protoimpl.EnumInfo, 5) +var file_neoshowcase_protobuf_controller_proto_msgTypes = make([]protoimpl.MessageInfo, 18) var file_neoshowcase_protobuf_controller_proto_goTypes = []interface{}{ (BuilderRequest_Type)(0), // 0: neoshowcase.protobuf.BuilderRequest.Type (BuilderResponse_Type)(0), // 1: neoshowcase.protobuf.BuilderResponse.Type - (SSGenRequest_Type)(0), // 2: neoshowcase.protobuf.SSGenRequest.Type - (GiteaIntegrationRequest_Type)(0), // 3: neoshowcase.protobuf.GiteaIntegrationRequest.Type - (*ImageConfig)(nil), // 4: neoshowcase.protobuf.ImageConfig - (*BuilderSystemInfo)(nil), // 5: neoshowcase.protobuf.BuilderSystemInfo - (*BuildLogPortion)(nil), // 6: neoshowcase.protobuf.BuildLogPortion - (*SaveArtifactRequest)(nil), // 7: neoshowcase.protobuf.SaveArtifactRequest - (*SaveBuildLogRequest)(nil), // 8: neoshowcase.protobuf.SaveBuildLogRequest - (*RepositoryPrivate)(nil), // 9: neoshowcase.protobuf.RepositoryPrivate - (*StartBuildRequest)(nil), // 10: neoshowcase.protobuf.StartBuildRequest - (*BuilderRequest)(nil), // 11: neoshowcase.protobuf.BuilderRequest - (*ConnectedBody)(nil), // 12: neoshowcase.protobuf.ConnectedBody - (*BuildSettled)(nil), // 13: neoshowcase.protobuf.BuildSettled - (*BuilderResponse)(nil), // 14: neoshowcase.protobuf.BuilderResponse - (*SSGenRequest)(nil), // 15: neoshowcase.protobuf.SSGenRequest - (*GiteaIntegrationRequest)(nil), // 16: neoshowcase.protobuf.GiteaIntegrationRequest - (*ImageConfig_RegistryConfig)(nil), // 17: neoshowcase.protobuf.ImageConfig.RegistryConfig - (*Artifact)(nil), // 18: neoshowcase.protobuf.Artifact - (*Repository)(nil), // 19: neoshowcase.protobuf.Repository - (*Application)(nil), // 20: neoshowcase.protobuf.Application - (*ApplicationEnvVars)(nil), // 21: neoshowcase.protobuf.ApplicationEnvVars - (*Build)(nil), // 22: neoshowcase.protobuf.Build - (*BuildIdRequest)(nil), // 23: neoshowcase.protobuf.BuildIdRequest - (BuildStatus)(0), // 24: neoshowcase.protobuf.BuildStatus - (*emptypb.Empty)(nil), // 25: google.protobuf.Empty - (*RepositoryIdRequest)(nil), // 26: neoshowcase.protobuf.RepositoryIdRequest - (*ApplicationIdRequest)(nil), // 27: neoshowcase.protobuf.ApplicationIdRequest - (*SystemInfo)(nil), // 28: neoshowcase.protobuf.SystemInfo - (*BuildLog)(nil), // 29: neoshowcase.protobuf.BuildLog + (HelperExecResponse_Type)(0), // 2: neoshowcase.protobuf.HelperExecResponse.Type + (SSGenRequest_Type)(0), // 3: neoshowcase.protobuf.SSGenRequest.Type + (GiteaIntegrationRequest_Type)(0), // 4: neoshowcase.protobuf.GiteaIntegrationRequest.Type + (*ImageConfig)(nil), // 5: neoshowcase.protobuf.ImageConfig + (*BuilderSystemInfo)(nil), // 6: neoshowcase.protobuf.BuilderSystemInfo + (*BuildLogPortion)(nil), // 7: neoshowcase.protobuf.BuildLogPortion + (*SaveArtifactRequest)(nil), // 8: neoshowcase.protobuf.SaveArtifactRequest + (*SaveBuildLogRequest)(nil), // 9: neoshowcase.protobuf.SaveBuildLogRequest + (*RepositoryPrivate)(nil), // 10: neoshowcase.protobuf.RepositoryPrivate + (*StartBuildRequest)(nil), // 11: neoshowcase.protobuf.StartBuildRequest + (*BuilderRequest)(nil), // 12: neoshowcase.protobuf.BuilderRequest + (*ConnectedBody)(nil), // 13: neoshowcase.protobuf.ConnectedBody + (*BuildSettled)(nil), // 14: neoshowcase.protobuf.BuildSettled + (*BuilderResponse)(nil), // 15: neoshowcase.protobuf.BuilderResponse + (*CopyFileTreeRequest)(nil), // 16: neoshowcase.protobuf.CopyFileTreeRequest + (*HelperExecEnv)(nil), // 17: neoshowcase.protobuf.HelperExecEnv + (*HelperExecRequest)(nil), // 18: neoshowcase.protobuf.HelperExecRequest + (*HelperExecResponse)(nil), // 19: neoshowcase.protobuf.HelperExecResponse + (*SSGenRequest)(nil), // 20: neoshowcase.protobuf.SSGenRequest + (*GiteaIntegrationRequest)(nil), // 21: neoshowcase.protobuf.GiteaIntegrationRequest + (*ImageConfig_RegistryConfig)(nil), // 22: neoshowcase.protobuf.ImageConfig.RegistryConfig + (*Artifact)(nil), // 23: neoshowcase.protobuf.Artifact + (*Repository)(nil), // 24: neoshowcase.protobuf.Repository + (*Application)(nil), // 25: neoshowcase.protobuf.Application + (*ApplicationEnvVars)(nil), // 26: neoshowcase.protobuf.ApplicationEnvVars + (*Build)(nil), // 27: neoshowcase.protobuf.Build + (*BuildIdRequest)(nil), // 28: neoshowcase.protobuf.BuildIdRequest + (BuildStatus)(0), // 29: neoshowcase.protobuf.BuildStatus + (*emptypb.Empty)(nil), // 30: google.protobuf.Empty + (*RepositoryIdRequest)(nil), // 31: neoshowcase.protobuf.RepositoryIdRequest + (*ApplicationIdRequest)(nil), // 32: neoshowcase.protobuf.ApplicationIdRequest + (*SystemInfo)(nil), // 33: neoshowcase.protobuf.SystemInfo + (*BuildLog)(nil), // 34: neoshowcase.protobuf.BuildLog } var file_neoshowcase_protobuf_controller_proto_depIdxs = []int32{ - 17, // 0: neoshowcase.protobuf.ImageConfig.registry:type_name -> neoshowcase.protobuf.ImageConfig.RegistryConfig - 4, // 1: neoshowcase.protobuf.BuilderSystemInfo.image_config:type_name -> neoshowcase.protobuf.ImageConfig - 18, // 2: neoshowcase.protobuf.SaveArtifactRequest.artifact:type_name -> neoshowcase.protobuf.Artifact - 19, // 3: neoshowcase.protobuf.RepositoryPrivate.repo:type_name -> neoshowcase.protobuf.Repository - 9, // 4: neoshowcase.protobuf.StartBuildRequest.repo:type_name -> neoshowcase.protobuf.RepositoryPrivate - 20, // 5: neoshowcase.protobuf.StartBuildRequest.app:type_name -> neoshowcase.protobuf.Application - 21, // 6: neoshowcase.protobuf.StartBuildRequest.app_envs:type_name -> neoshowcase.protobuf.ApplicationEnvVars - 22, // 7: neoshowcase.protobuf.StartBuildRequest.build:type_name -> neoshowcase.protobuf.Build + 22, // 0: neoshowcase.protobuf.ImageConfig.registry:type_name -> neoshowcase.protobuf.ImageConfig.RegistryConfig + 5, // 1: neoshowcase.protobuf.BuilderSystemInfo.image_config:type_name -> neoshowcase.protobuf.ImageConfig + 23, // 2: neoshowcase.protobuf.SaveArtifactRequest.artifact:type_name -> neoshowcase.protobuf.Artifact + 24, // 3: neoshowcase.protobuf.RepositoryPrivate.repo:type_name -> neoshowcase.protobuf.Repository + 10, // 4: neoshowcase.protobuf.StartBuildRequest.repo:type_name -> neoshowcase.protobuf.RepositoryPrivate + 25, // 5: neoshowcase.protobuf.StartBuildRequest.app:type_name -> neoshowcase.protobuf.Application + 26, // 6: neoshowcase.protobuf.StartBuildRequest.app_envs:type_name -> neoshowcase.protobuf.ApplicationEnvVars + 27, // 7: neoshowcase.protobuf.StartBuildRequest.build:type_name -> neoshowcase.protobuf.Build 0, // 8: neoshowcase.protobuf.BuilderRequest.type:type_name -> neoshowcase.protobuf.BuilderRequest.Type - 10, // 9: neoshowcase.protobuf.BuilderRequest.start_build:type_name -> neoshowcase.protobuf.StartBuildRequest - 23, // 10: neoshowcase.protobuf.BuilderRequest.cancel_build:type_name -> neoshowcase.protobuf.BuildIdRequest - 24, // 11: neoshowcase.protobuf.BuildSettled.status:type_name -> neoshowcase.protobuf.BuildStatus + 11, // 9: neoshowcase.protobuf.BuilderRequest.start_build:type_name -> neoshowcase.protobuf.StartBuildRequest + 28, // 10: neoshowcase.protobuf.BuilderRequest.cancel_build:type_name -> neoshowcase.protobuf.BuildIdRequest + 29, // 11: neoshowcase.protobuf.BuildSettled.status:type_name -> neoshowcase.protobuf.BuildStatus 1, // 12: neoshowcase.protobuf.BuilderResponse.type:type_name -> neoshowcase.protobuf.BuilderResponse.Type - 12, // 13: neoshowcase.protobuf.BuilderResponse.connected:type_name -> neoshowcase.protobuf.ConnectedBody - 13, // 14: neoshowcase.protobuf.BuilderResponse.settled:type_name -> neoshowcase.protobuf.BuildSettled - 2, // 15: neoshowcase.protobuf.SSGenRequest.type:type_name -> neoshowcase.protobuf.SSGenRequest.Type - 3, // 16: neoshowcase.protobuf.GiteaIntegrationRequest.type:type_name -> neoshowcase.protobuf.GiteaIntegrationRequest.Type - 25, // 17: neoshowcase.protobuf.ControllerService.GetSystemInfo:input_type -> google.protobuf.Empty - 26, // 18: neoshowcase.protobuf.ControllerService.FetchRepository:input_type -> neoshowcase.protobuf.RepositoryIdRequest - 27, // 19: neoshowcase.protobuf.ControllerService.RegisterBuild:input_type -> neoshowcase.protobuf.ApplicationIdRequest - 25, // 20: neoshowcase.protobuf.ControllerService.SyncDeployments:input_type -> google.protobuf.Empty - 23, // 21: neoshowcase.protobuf.ControllerService.StreamBuildLog:input_type -> neoshowcase.protobuf.BuildIdRequest - 23, // 22: neoshowcase.protobuf.ControllerService.CancelBuild:input_type -> neoshowcase.protobuf.BuildIdRequest - 25, // 23: neoshowcase.protobuf.ControllerBuilderService.GetBuilderSystemInfo:input_type -> google.protobuf.Empty - 23, // 24: neoshowcase.protobuf.ControllerBuilderService.PingBuild:input_type -> neoshowcase.protobuf.BuildIdRequest - 6, // 25: neoshowcase.protobuf.ControllerBuilderService.StreamBuildLog:input_type -> neoshowcase.protobuf.BuildLogPortion - 7, // 26: neoshowcase.protobuf.ControllerBuilderService.SaveArtifact:input_type -> neoshowcase.protobuf.SaveArtifactRequest - 8, // 27: neoshowcase.protobuf.ControllerBuilderService.SaveBuildLog:input_type -> neoshowcase.protobuf.SaveBuildLogRequest - 14, // 28: neoshowcase.protobuf.ControllerBuilderService.ConnectBuilder:input_type -> neoshowcase.protobuf.BuilderResponse - 25, // 29: neoshowcase.protobuf.ControllerSSGenService.ConnectSSGen:input_type -> google.protobuf.Empty - 25, // 30: neoshowcase.protobuf.ControllerGiteaIntegrationService.Connect:input_type -> google.protobuf.Empty - 28, // 31: neoshowcase.protobuf.ControllerService.GetSystemInfo:output_type -> neoshowcase.protobuf.SystemInfo - 25, // 32: neoshowcase.protobuf.ControllerService.FetchRepository:output_type -> google.protobuf.Empty - 25, // 33: neoshowcase.protobuf.ControllerService.RegisterBuild:output_type -> google.protobuf.Empty - 25, // 34: neoshowcase.protobuf.ControllerService.SyncDeployments:output_type -> google.protobuf.Empty - 29, // 35: neoshowcase.protobuf.ControllerService.StreamBuildLog:output_type -> neoshowcase.protobuf.BuildLog - 25, // 36: neoshowcase.protobuf.ControllerService.CancelBuild:output_type -> google.protobuf.Empty - 5, // 37: neoshowcase.protobuf.ControllerBuilderService.GetBuilderSystemInfo:output_type -> neoshowcase.protobuf.BuilderSystemInfo - 25, // 38: neoshowcase.protobuf.ControllerBuilderService.PingBuild:output_type -> google.protobuf.Empty - 25, // 39: neoshowcase.protobuf.ControllerBuilderService.StreamBuildLog:output_type -> google.protobuf.Empty - 25, // 40: neoshowcase.protobuf.ControllerBuilderService.SaveArtifact:output_type -> google.protobuf.Empty - 25, // 41: neoshowcase.protobuf.ControllerBuilderService.SaveBuildLog:output_type -> google.protobuf.Empty - 11, // 42: neoshowcase.protobuf.ControllerBuilderService.ConnectBuilder:output_type -> neoshowcase.protobuf.BuilderRequest - 15, // 43: neoshowcase.protobuf.ControllerSSGenService.ConnectSSGen:output_type -> neoshowcase.protobuf.SSGenRequest - 16, // 44: neoshowcase.protobuf.ControllerGiteaIntegrationService.Connect:output_type -> neoshowcase.protobuf.GiteaIntegrationRequest - 31, // [31:45] is the sub-list for method output_type - 17, // [17:31] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name + 13, // 13: neoshowcase.protobuf.BuilderResponse.connected:type_name -> neoshowcase.protobuf.ConnectedBody + 14, // 14: neoshowcase.protobuf.BuilderResponse.settled:type_name -> neoshowcase.protobuf.BuildSettled + 17, // 15: neoshowcase.protobuf.HelperExecRequest.envs:type_name -> neoshowcase.protobuf.HelperExecEnv + 2, // 16: neoshowcase.protobuf.HelperExecResponse.type:type_name -> neoshowcase.protobuf.HelperExecResponse.Type + 3, // 17: neoshowcase.protobuf.SSGenRequest.type:type_name -> neoshowcase.protobuf.SSGenRequest.Type + 4, // 18: neoshowcase.protobuf.GiteaIntegrationRequest.type:type_name -> neoshowcase.protobuf.GiteaIntegrationRequest.Type + 30, // 19: neoshowcase.protobuf.ControllerService.GetSystemInfo:input_type -> google.protobuf.Empty + 31, // 20: neoshowcase.protobuf.ControllerService.FetchRepository:input_type -> neoshowcase.protobuf.RepositoryIdRequest + 32, // 21: neoshowcase.protobuf.ControllerService.RegisterBuild:input_type -> neoshowcase.protobuf.ApplicationIdRequest + 30, // 22: neoshowcase.protobuf.ControllerService.SyncDeployments:input_type -> google.protobuf.Empty + 28, // 23: neoshowcase.protobuf.ControllerService.StreamBuildLog:input_type -> neoshowcase.protobuf.BuildIdRequest + 28, // 24: neoshowcase.protobuf.ControllerService.CancelBuild:input_type -> neoshowcase.protobuf.BuildIdRequest + 30, // 25: neoshowcase.protobuf.ControllerBuilderService.GetBuilderSystemInfo:input_type -> google.protobuf.Empty + 28, // 26: neoshowcase.protobuf.ControllerBuilderService.PingBuild:input_type -> neoshowcase.protobuf.BuildIdRequest + 7, // 27: neoshowcase.protobuf.ControllerBuilderService.StreamBuildLog:input_type -> neoshowcase.protobuf.BuildLogPortion + 8, // 28: neoshowcase.protobuf.ControllerBuilderService.SaveArtifact:input_type -> neoshowcase.protobuf.SaveArtifactRequest + 9, // 29: neoshowcase.protobuf.ControllerBuilderService.SaveBuildLog:input_type -> neoshowcase.protobuf.SaveBuildLogRequest + 15, // 30: neoshowcase.protobuf.ControllerBuilderService.ConnectBuilder:input_type -> neoshowcase.protobuf.BuilderResponse + 16, // 31: neoshowcase.protobuf.BuildpackHelperService.CopyFileTree:input_type -> neoshowcase.protobuf.CopyFileTreeRequest + 18, // 32: neoshowcase.protobuf.BuildpackHelperService.Exec:input_type -> neoshowcase.protobuf.HelperExecRequest + 30, // 33: neoshowcase.protobuf.ControllerSSGenService.ConnectSSGen:input_type -> google.protobuf.Empty + 30, // 34: neoshowcase.protobuf.ControllerGiteaIntegrationService.Connect:input_type -> google.protobuf.Empty + 33, // 35: neoshowcase.protobuf.ControllerService.GetSystemInfo:output_type -> neoshowcase.protobuf.SystemInfo + 30, // 36: neoshowcase.protobuf.ControllerService.FetchRepository:output_type -> google.protobuf.Empty + 30, // 37: neoshowcase.protobuf.ControllerService.RegisterBuild:output_type -> google.protobuf.Empty + 30, // 38: neoshowcase.protobuf.ControllerService.SyncDeployments:output_type -> google.protobuf.Empty + 34, // 39: neoshowcase.protobuf.ControllerService.StreamBuildLog:output_type -> neoshowcase.protobuf.BuildLog + 30, // 40: neoshowcase.protobuf.ControllerService.CancelBuild:output_type -> google.protobuf.Empty + 6, // 41: neoshowcase.protobuf.ControllerBuilderService.GetBuilderSystemInfo:output_type -> neoshowcase.protobuf.BuilderSystemInfo + 30, // 42: neoshowcase.protobuf.ControllerBuilderService.PingBuild:output_type -> google.protobuf.Empty + 30, // 43: neoshowcase.protobuf.ControllerBuilderService.StreamBuildLog:output_type -> google.protobuf.Empty + 30, // 44: neoshowcase.protobuf.ControllerBuilderService.SaveArtifact:output_type -> google.protobuf.Empty + 30, // 45: neoshowcase.protobuf.ControllerBuilderService.SaveBuildLog:output_type -> google.protobuf.Empty + 12, // 46: neoshowcase.protobuf.ControllerBuilderService.ConnectBuilder:output_type -> neoshowcase.protobuf.BuilderRequest + 30, // 47: neoshowcase.protobuf.BuildpackHelperService.CopyFileTree:output_type -> google.protobuf.Empty + 19, // 48: neoshowcase.protobuf.BuildpackHelperService.Exec:output_type -> neoshowcase.protobuf.HelperExecResponse + 20, // 49: neoshowcase.protobuf.ControllerSSGenService.ConnectSSGen:output_type -> neoshowcase.protobuf.SSGenRequest + 21, // 50: neoshowcase.protobuf.ControllerGiteaIntegrationService.Connect:output_type -> neoshowcase.protobuf.GiteaIntegrationRequest + 35, // [35:51] is the sub-list for method output_type + 19, // [19:35] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_neoshowcase_protobuf_controller_proto_init() } @@ -1529,7 +1889,7 @@ func file_neoshowcase_protobuf_controller_proto_init() { } } file_neoshowcase_protobuf_controller_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SSGenRequest); i { + switch v := v.(*CopyFileTreeRequest); i { case 0: return &v.state case 1: @@ -1541,7 +1901,7 @@ func file_neoshowcase_protobuf_controller_proto_init() { } } file_neoshowcase_protobuf_controller_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GiteaIntegrationRequest); i { + switch v := v.(*HelperExecEnv); i { case 0: return &v.state case 1: @@ -1553,6 +1913,54 @@ func file_neoshowcase_protobuf_controller_proto_init() { } } file_neoshowcase_protobuf_controller_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelperExecRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_neoshowcase_protobuf_controller_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelperExecResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_neoshowcase_protobuf_controller_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SSGenRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_neoshowcase_protobuf_controller_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GiteaIntegrationRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_neoshowcase_protobuf_controller_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ImageConfig_RegistryConfig); i { case 0: return &v.state @@ -1573,15 +1981,19 @@ func file_neoshowcase_protobuf_controller_proto_init() { (*BuilderResponse_Connected)(nil), (*BuilderResponse_Settled)(nil), } + file_neoshowcase_protobuf_controller_proto_msgTypes[14].OneofWrappers = []interface{}{ + (*HelperExecResponse_Log)(nil), + (*HelperExecResponse_ExitCode)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_neoshowcase_protobuf_controller_proto_rawDesc, - NumEnums: 4, - NumMessages: 14, + NumEnums: 5, + NumMessages: 18, NumExtensions: 0, - NumServices: 4, + NumServices: 5, }, GoTypes: file_neoshowcase_protobuf_controller_proto_goTypes, DependencyIndexes: file_neoshowcase_protobuf_controller_proto_depIdxs, diff --git a/pkg/infrastructure/grpc/pb/gateway.pb.go b/pkg/infrastructure/grpc/pb/gateway.pb.go index 43d8093e3..7513fa1df 100644 --- a/pkg/infrastructure/grpc/pb/gateway.pb.go +++ b/pkg/infrastructure/grpc/pb/gateway.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.4 +// protoc-gen-go v1.32.0 +// protoc v4.25.1 // source: neoshowcase/protobuf/gateway.proto package pb diff --git a/pkg/infrastructure/grpc/pb/null.pb.go b/pkg/infrastructure/grpc/pb/null.pb.go index 9aada78b3..e6d9dae61 100644 --- a/pkg/infrastructure/grpc/pb/null.pb.go +++ b/pkg/infrastructure/grpc/pb/null.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.31.0 -// protoc v4.24.4 +// protoc-gen-go v1.32.0 +// protoc v4.25.1 // source: neoshowcase/protobuf/null.proto package pb diff --git a/pkg/infrastructure/grpc/pb/pbconnect/controller.connect.go b/pkg/infrastructure/grpc/pb/pbconnect/controller.connect.go index 687ab9802..78903a050 100644 --- a/pkg/infrastructure/grpc/pb/pbconnect/controller.connect.go +++ b/pkg/infrastructure/grpc/pb/pbconnect/controller.connect.go @@ -26,6 +26,8 @@ const ( ControllerServiceName = "neoshowcase.protobuf.ControllerService" // ControllerBuilderServiceName is the fully-qualified name of the ControllerBuilderService service. ControllerBuilderServiceName = "neoshowcase.protobuf.ControllerBuilderService" + // BuildpackHelperServiceName is the fully-qualified name of the BuildpackHelperService service. + BuildpackHelperServiceName = "neoshowcase.protobuf.BuildpackHelperService" // ControllerSSGenServiceName is the fully-qualified name of the ControllerSSGenService service. ControllerSSGenServiceName = "neoshowcase.protobuf.ControllerSSGenService" // ControllerGiteaIntegrationServiceName is the fully-qualified name of the @@ -77,6 +79,12 @@ const ( // ControllerBuilderServiceConnectBuilderProcedure is the fully-qualified name of the // ControllerBuilderService's ConnectBuilder RPC. ControllerBuilderServiceConnectBuilderProcedure = "/neoshowcase.protobuf.ControllerBuilderService/ConnectBuilder" + // BuildpackHelperServiceCopyFileTreeProcedure is the fully-qualified name of the + // BuildpackHelperService's CopyFileTree RPC. + BuildpackHelperServiceCopyFileTreeProcedure = "/neoshowcase.protobuf.BuildpackHelperService/CopyFileTree" + // BuildpackHelperServiceExecProcedure is the fully-qualified name of the BuildpackHelperService's + // Exec RPC. + BuildpackHelperServiceExecProcedure = "/neoshowcase.protobuf.BuildpackHelperService/Exec" // ControllerSSGenServiceConnectSSGenProcedure is the fully-qualified name of the // ControllerSSGenService's ConnectSSGen RPC. ControllerSSGenServiceConnectSSGenProcedure = "/neoshowcase.protobuf.ControllerSSGenService/ConnectSSGen" @@ -101,6 +109,9 @@ var ( controllerBuilderServiceSaveArtifactMethodDescriptor = controllerBuilderServiceServiceDescriptor.Methods().ByName("SaveArtifact") controllerBuilderServiceSaveBuildLogMethodDescriptor = controllerBuilderServiceServiceDescriptor.Methods().ByName("SaveBuildLog") controllerBuilderServiceConnectBuilderMethodDescriptor = controllerBuilderServiceServiceDescriptor.Methods().ByName("ConnectBuilder") + buildpackHelperServiceServiceDescriptor = pb.File_neoshowcase_protobuf_controller_proto.Services().ByName("BuildpackHelperService") + buildpackHelperServiceCopyFileTreeMethodDescriptor = buildpackHelperServiceServiceDescriptor.Methods().ByName("CopyFileTree") + buildpackHelperServiceExecMethodDescriptor = buildpackHelperServiceServiceDescriptor.Methods().ByName("Exec") controllerSSGenServiceServiceDescriptor = pb.File_neoshowcase_protobuf_controller_proto.Services().ByName("ControllerSSGenService") controllerSSGenServiceConnectSSGenMethodDescriptor = controllerSSGenServiceServiceDescriptor.Methods().ByName("ConnectSSGen") controllerGiteaIntegrationServiceServiceDescriptor = pb.File_neoshowcase_protobuf_controller_proto.Services().ByName("ControllerGiteaIntegrationService") @@ -507,6 +518,103 @@ func (UnimplementedControllerBuilderServiceHandler) ConnectBuilder(context.Conte return connect.NewError(connect.CodeUnimplemented, errors.New("neoshowcase.protobuf.ControllerBuilderService.ConnectBuilder is not implemented")) } +// BuildpackHelperServiceClient is a client for the neoshowcase.protobuf.BuildpackHelperService +// service. +type BuildpackHelperServiceClient interface { + CopyFileTree(context.Context, *connect.Request[pb.CopyFileTreeRequest]) (*connect.Response[emptypb.Empty], error) + Exec(context.Context, *connect.Request[pb.HelperExecRequest]) (*connect.ServerStreamForClient[pb.HelperExecResponse], error) +} + +// NewBuildpackHelperServiceClient constructs a client for the +// neoshowcase.protobuf.BuildpackHelperService 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 NewBuildpackHelperServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) BuildpackHelperServiceClient { + baseURL = strings.TrimRight(baseURL, "/") + return &buildpackHelperServiceClient{ + copyFileTree: connect.NewClient[pb.CopyFileTreeRequest, emptypb.Empty]( + httpClient, + baseURL+BuildpackHelperServiceCopyFileTreeProcedure, + connect.WithSchema(buildpackHelperServiceCopyFileTreeMethodDescriptor), + connect.WithClientOptions(opts...), + ), + exec: connect.NewClient[pb.HelperExecRequest, pb.HelperExecResponse]( + httpClient, + baseURL+BuildpackHelperServiceExecProcedure, + connect.WithSchema(buildpackHelperServiceExecMethodDescriptor), + connect.WithClientOptions(opts...), + ), + } +} + +// buildpackHelperServiceClient implements BuildpackHelperServiceClient. +type buildpackHelperServiceClient struct { + copyFileTree *connect.Client[pb.CopyFileTreeRequest, emptypb.Empty] + exec *connect.Client[pb.HelperExecRequest, pb.HelperExecResponse] +} + +// CopyFileTree calls neoshowcase.protobuf.BuildpackHelperService.CopyFileTree. +func (c *buildpackHelperServiceClient) CopyFileTree(ctx context.Context, req *connect.Request[pb.CopyFileTreeRequest]) (*connect.Response[emptypb.Empty], error) { + return c.copyFileTree.CallUnary(ctx, req) +} + +// Exec calls neoshowcase.protobuf.BuildpackHelperService.Exec. +func (c *buildpackHelperServiceClient) Exec(ctx context.Context, req *connect.Request[pb.HelperExecRequest]) (*connect.ServerStreamForClient[pb.HelperExecResponse], error) { + return c.exec.CallServerStream(ctx, req) +} + +// BuildpackHelperServiceHandler is an implementation of the +// neoshowcase.protobuf.BuildpackHelperService service. +type BuildpackHelperServiceHandler interface { + CopyFileTree(context.Context, *connect.Request[pb.CopyFileTreeRequest]) (*connect.Response[emptypb.Empty], error) + Exec(context.Context, *connect.Request[pb.HelperExecRequest], *connect.ServerStream[pb.HelperExecResponse]) error +} + +// NewBuildpackHelperServiceHandler 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 NewBuildpackHelperServiceHandler(svc BuildpackHelperServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) { + buildpackHelperServiceCopyFileTreeHandler := connect.NewUnaryHandler( + BuildpackHelperServiceCopyFileTreeProcedure, + svc.CopyFileTree, + connect.WithSchema(buildpackHelperServiceCopyFileTreeMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + buildpackHelperServiceExecHandler := connect.NewServerStreamHandler( + BuildpackHelperServiceExecProcedure, + svc.Exec, + connect.WithSchema(buildpackHelperServiceExecMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + return "/neoshowcase.protobuf.BuildpackHelperService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case BuildpackHelperServiceCopyFileTreeProcedure: + buildpackHelperServiceCopyFileTreeHandler.ServeHTTP(w, r) + case BuildpackHelperServiceExecProcedure: + buildpackHelperServiceExecHandler.ServeHTTP(w, r) + default: + http.NotFound(w, r) + } + }) +} + +// UnimplementedBuildpackHelperServiceHandler returns CodeUnimplemented from all methods. +type UnimplementedBuildpackHelperServiceHandler struct{} + +func (UnimplementedBuildpackHelperServiceHandler) CopyFileTree(context.Context, *connect.Request[pb.CopyFileTreeRequest]) (*connect.Response[emptypb.Empty], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("neoshowcase.protobuf.BuildpackHelperService.CopyFileTree is not implemented")) +} + +func (UnimplementedBuildpackHelperServiceHandler) Exec(context.Context, *connect.Request[pb.HelperExecRequest], *connect.ServerStream[pb.HelperExecResponse]) error { + return connect.NewError(connect.CodeUnimplemented, errors.New("neoshowcase.protobuf.BuildpackHelperService.Exec is not implemented")) +} + // ControllerSSGenServiceClient is a client for the neoshowcase.protobuf.ControllerSSGenService // service. type ControllerSSGenServiceClient interface {