refactor: use connect-go instead of regular Google gRPC
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone/tag Build is failing

- support binary name for plugins
- register plugins for container jobs
This commit is contained in:
Peter 2023-09-12 18:43:34 +02:00
parent b7e11c8992
commit 34c431790e
Signed by: prskr
GPG key ID: C1DB5D2E8DB512F9
54 changed files with 751 additions and 938 deletions

View file

@ -4,7 +4,7 @@ buildr {
logs_dir = ".buildr/logs"
plugin "golang" {
url = "https://code.icb4dc0.de/api/packages/buildr/generic/golang_plugin/0.0.1/golang.wasm"
checksum = "2a183eb9c2c55b8ab678e9f176c60a477a2d0a67e3e8d25f42bc2113e0cdab8e"
url = "https://code.icb4dc0.de/api/packages/buildr/generic/golang_plugin/0.0.2/golang.wasm"
checksum = "d82de8973447e036d4cc26a76f7b6ac8bc78afc3abdf49fcc31553ba5e119e46"
}
}

View file

@ -1,69 +1,63 @@
task "script" "go_fmt" {
inline = [
"go fmt ${join(" ", toset([for s in vcs.staged_files : "code.icb4dc0.de/buildr/buildr/${dirname(s)}" if ext(s) == ".go"]))}"
]
inline = [
"go fmt ${join(" ", toset([for s in vcs.staged_files : "code.icb4dc0.de/buildr/buildr/${dirname(s)}" if ext(s) == ".go"]))}"
]
}
task "script" "go_generate" {
inline = [
"go generate -x ./..."
]
inline = [
"go generate -x ./..."
]
depends_on = [
tools.mockery.id
]
depends_on = [
tools.mockery.id
]
}
task "script" "go_test" {
inline = [
"apt update && apt install -y fuse",
"gotestsum --junitfile results.xml --format pkgname-and-test-fails -- -race -shuffle=on ./..."
]
inline = [
"apt update && apt install -y fuse",
"gotestsum --junitfile results.xml --format pkgname-and-test-fails -- -shuffle=on ./..."
]
depends_on = [
tasks.go_generate.id,
tools.gotestsum.id
]
depends_on = [
tasks.go_generate.id,
tools.gotestsum.id
]
environment = {
CGO_ENABLED = "1"
}
input_mapping = {
"${repo.root}" = "."
}
container {
image = "docker.io/golang:1.20"
capabilities {
add = ["SYS_ADMIN"]
input_mapping = {
"${repo.root}" = "."
}
volume_mount "/go/pkg/mod" {
name = "go_cache"
}
container {
image = "docker.io/golang:1.21"
privileged = true
bind_mount "/dev/fuse" {
source = "/dev/fuse"
volume_mount "/go/pkg/mod" {
name = "go_cache"
}
bind_mount "/dev/fuse" {
source = "/dev/fuse"
}
}
}
}
task "script" "golangci_lint" {
inline = [
"golangci-lint run -v"
]
inline = [
"golangci-lint run -v"
]
container {
image = "golangci/golangci-lint"
}
container {
image = "golangci/golangci-lint"
}
depends_on = [
tasks.go_fmt.id,
tasks.go_generate.id,
]
depends_on = [
tasks.go_fmt.id,
tasks.go_generate.id,
]
input_mapping = {
"${repo.root}" = "."
}
input_mapping = {
"${repo.root}" = "."
}
}

View file

@ -1,34 +1,38 @@
locals {
tool_versions {
mockery = gh_latest_release("vektra", "mockery", from_vault("github_token"))
gotestsum = gh_latest_release("gotestyourself", "gotestsum", from_vault("github_token"))
golangci_lint = gh_latest_release("golangci", "golangci-lint", from_vault("github_token"))
}
tool_versions {
mockery = gh_latest_release("vektra", "mockery", from_vault("github_token"))
gotestsum = gh_latest_release("gotestyourself", "gotestsum", from_vault("github_token"))
golangci_lint = gh_latest_release("golangci", "golangci-lint", from_vault("github_token"))
}
}
tool "go_tool" "mockery" {
binary_name = "mockery"
repository = "github.com/vektra/mockery/v2"
version = local.tool_versions.mockery
build_args = [
"-v",
"-trimpath",
"-a",
"-installsuffix=cgo"
]
binary_name = "mockery"
repository = "github.com/vektra/mockery/v2"
version = local.tool_versions.mockery
build_args = [
"-v",
"-trimpath",
"-a",
"-installsuffix=cgo"
]
environment = {
CGO_ENABLED = "0"
}
}
tool "go_tool" "gotestsum" {
binary_name = "gotestsum"
repository = "gotest.tools/gotestsum"
version = local.tool_versions.gotestsum
build_args = [
"-v",
"-trimpath",
"-a",
"-installsuffix=cgo"
]
environment = {
CGO_ENABLED = "0"
binary_name = "gotestsum"
repository = "gotest.tools/gotestsum"
version = local.tool_versions.gotestsum
build_args = [
"-v",
"-trimpath",
"-a",
"-installsuffix=cgo"
]
environment = {
CGO_ENABLED = "0"
}
}

View file

@ -61,7 +61,7 @@ linters-settings:
importas:
no-unaliased: true
alias:
- pkg: code.icb4dc0.de/buildr/buildr/generated/rpc/(v[\w\d]+)
- pkg: code.icb4dc0.de/buildr/buildr/generated/remote/(v[\w\d]+)
alias: $1$2
lll:
line-length: 140

View file

@ -1,9 +1,12 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="task buf_generate" type="GoApplicationRunConfiguration" factoryName="Go Application">
<configuration default="false" name="task go_test" type="GoApplicationRunConfiguration" factoryName="Go Application">
<module name="buildr" />
<working_directory value="$PROJECT_DIR$/buildr" />
<go_parameters value="-a -installsuffix=cgo" />
<parameters value="--pprof.cpu-profile --pprof.out-file /tmp/cpu.profile task buf_generate" />
<parameters value="--pprof.cpu-profile --pprof.out-file /tmp/cpu.profile task go_test" />
<envs>
<env name="DOCKER_HOST" value="unix:///var/run/docker.sock" />
</envs>
<EXTENSION ID="net.ashald.envfile">
<option name="IS_ENABLED" value="false" />
<option name="IS_SUBST" value="false" />

61
go.mod
View file

@ -3,26 +3,28 @@ module code.icb4dc0.de/buildr/buildr
go 1.21
require (
code.icb4dc0.de/buildr/api v0.0.0-20230824061008-9729e3ce7ec3
code.icb4dc0.de/buildr/common v0.0.0-20230823164419-5a757074eaa3
buf.build/gen/go/grpc/grpc/connectrpc/go v1.11.1-20230911202230-334e348dc585.1
buf.build/gen/go/grpc/grpc/protocolbuffers/go v1.31.0-20230911202230-334e348dc585.1
code.icb4dc0.de/buildr/api v0.0.0-20230912160519-4b705a6732bc
code.icb4dc0.de/buildr/common v0.0.0-20230912160755-da17cbfde028
code.icb4dc0.de/prskr/go-pwgen v0.0.0-20230427131724-8ef26fd9749e
connectrpc.com/connect v1.11.1
connectrpc.com/grpcreflect v1.2.0
entgo.io/ent v0.12.3
github.com/Masterminds/sprig/v3 v3.2.3
github.com/charmbracelet/bubbles v0.16.1
github.com/charmbracelet/bubbletea v0.24.2
github.com/charmbracelet/glamour v0.6.0
github.com/charmbracelet/lipgloss v0.8.0
github.com/docker/docker v24.0.5+incompatible
github.com/docker/docker v24.0.6+incompatible
github.com/docker/go-connections v0.4.0
github.com/fsnotify/fsnotify v1.6.0
github.com/go-git/go-git/v5 v5.8.1
github.com/google/go-containerregistry v0.16.1
github.com/google/go-github/v53 v53.2.0
github.com/google/uuid v1.3.1
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/hanwen/go-fuse/v2 v2.3.0
github.com/hashicorp/hcl/v2 v2.17.0
github.com/hanwen/go-fuse/v2 v2.4.0
github.com/hashicorp/hcl/v2 v2.18.0
github.com/jinzhu/copier v0.4.0
github.com/klauspost/compress v1.16.7
github.com/klauspost/pgzip v1.2.6
@ -31,11 +33,12 @@ require (
github.com/opencontainers/image-spec v1.1.0-rc4
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
github.com/tetratelabs/wazero v1.4.0
github.com/zclconf/go-cty v1.13.2
golang.org/x/crypto v0.12.0
github.com/tetratelabs/wazero v1.5.0
github.com/zclconf/go-cty v1.14.0
golang.org/x/crypto v0.13.0
golang.org/x/net v0.15.0
golang.org/x/sync v0.3.0
google.golang.org/grpc v1.57.0
google.golang.org/grpc v1.58.0
google.golang.org/protobuf v1.31.0
modernc.org/sqlite v1.25.0
)
@ -43,34 +46,33 @@ require (
replace golang.org/x/net => golang.org/x/net v0.14.0
require (
ariga.io/atlas v0.13.1 // indirect
ariga.io/atlas v0.14.0 // indirect
dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/docker/cli v24.0.5+incompatible // indirect
github.com/docker/cli v24.0.6+incompatible // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.4.1 // indirect
github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@ -88,7 +90,6 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/microcosm-cc/bluemonday v1.0.25 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
@ -101,12 +102,9 @@ require (
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/sergi/go-diff v1.3.1 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
@ -118,15 +116,14 @@ require (
github.com/yuin/goldmark v1.5.6 // indirect
github.com/yuin/goldmark-emoji v1.0.2 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.11.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sys v0.12.0 // indirect
golang.org/x/term v0.12.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/uint128 v1.3.0 // indirect
@ -134,7 +131,7 @@ require (
modernc.org/ccgo/v3 v3.16.15 // indirect
modernc.org/libc v1.24.1 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.0 // indirect
modernc.org/memory v1.7.1 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect

184
go.sum
View file

@ -1,19 +1,41 @@
ariga.io/atlas v0.13.1 h1:oSkEYgI3qUnQZ6b6+teAEiIuizjBvkZ4YDbz0XWfCdQ=
ariga.io/atlas v0.13.1/go.mod h1:+TR129FJZ5Lvzms6dvCeGWh1yR6hMvmXBhug4hrNIGk=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
code.icb4dc0.de/buildr/api v0.0.0-20230824061008-9729e3ce7ec3 h1:CXt7gnJOMzk3lxXdYokRzwTeX6w7ZeceSBayvz8AfAw=
code.icb4dc0.de/buildr/api v0.0.0-20230824061008-9729e3ce7ec3/go.mod h1:eCeIvmMgYp/04nar7GnBDORMdO4jHYQl/RMiNJhyGf8=
code.icb4dc0.de/buildr/common v0.0.0-20230823164419-5a757074eaa3 h1:jWQCCE56vhfNoOuJj4JlCEcfXUB/40iR8L59j5xeh+s=
code.icb4dc0.de/buildr/common v0.0.0-20230823164419-5a757074eaa3/go.mod h1:u0PEZjq0l3ICCUgARZObM6Hc0ZlqkcjK0PBEozhAdNQ=
ariga.io/atlas v0.14.0 h1:2gpshFCwvlbXxRJHahUbIpDVdsbJtZVVeuqL410LSTY=
ariga.io/atlas v0.14.0/go.mod h1:+TR129FJZ5Lvzms6dvCeGWh1yR6hMvmXBhug4hrNIGk=
buf.build/gen/go/cncf/xds/protocolbuffers/go v1.31.0-20230607214312-0d869d8e763c.1/go.mod h1:UmNsX/9X7uCdAHlus9dv+pEV65jvhDP9IIECLXbgOtA=
buf.build/gen/go/envoyproxy/envoy/protocolbuffers/go v1.31.0-20230830152833-1ec8ea8729b6.1/go.mod h1:7BMBAxv7wnfvzSKS5jPEzS/PNAlEWLPgnMN4R0UytEY=
buf.build/gen/go/envoyproxy/envoy/protocolbuffers/go v1.31.0-20230911202228-79f095667852.1/go.mod h1:7BMBAxv7wnfvzSKS5jPEzS/PNAlEWLPgnMN4R0UytEY=
buf.build/gen/go/envoyproxy/protoc-gen-validate/protocolbuffers/go v1.31.0-20221025150516-6607b10f00ed.1/go.mod h1:Piak8t898VnXArmyLTXHwiVis+pdk9Yxsu5TwwmFnsA=
buf.build/gen/go/envoyproxy/protoc-gen-validate/protocolbuffers/go v1.31.0-20230814203303-eac44469a7af.1/go.mod h1:Piak8t898VnXArmyLTXHwiVis+pdk9Yxsu5TwwmFnsA=
buf.build/gen/go/grpc/grpc/connectrpc/go v1.11.1-20230830152835-a5b3a068eb8c.1 h1:Ud2hdR21ANar5UzstlASqYYpUg1ce9l2FVwN5I0uYTU=
buf.build/gen/go/grpc/grpc/connectrpc/go v1.11.1-20230830152835-a5b3a068eb8c.1/go.mod h1:toR4cis/X7aq2z+Bk8rVarKiLMa3TqOKHPRbtgsaXoQ=
buf.build/gen/go/grpc/grpc/connectrpc/go v1.11.1-20230911202230-334e348dc585.1 h1:Fuwims/p7aNyBp47T0OwHH6hfw0nNi2/EaOohCSnEUk=
buf.build/gen/go/grpc/grpc/connectrpc/go v1.11.1-20230911202230-334e348dc585.1/go.mod h1:O/8BbgiOiWwNj0yTvW7BX74CQhPc1Dn31qWZT06YeXw=
buf.build/gen/go/grpc/grpc/protocolbuffers/go v1.31.0-20230830152835-a5b3a068eb8c.1 h1:pFPEaE/nohP3uB/fqtrx8/Vd0j58Rurx9gGjSQjRyOw=
buf.build/gen/go/grpc/grpc/protocolbuffers/go v1.31.0-20230830152835-a5b3a068eb8c.1/go.mod h1:l/3NXaZu35rzlUb+BCEg1i+lFyKUg1rk7p1KRCWawgU=
buf.build/gen/go/grpc/grpc/protocolbuffers/go v1.31.0-20230911202230-334e348dc585.1 h1:7O3N3OfEaRLizUSvaZwPygEJIbSy+ac+YilMGM2JT7Y=
buf.build/gen/go/grpc/grpc/protocolbuffers/go v1.31.0-20230911202230-334e348dc585.1/go.mod h1:DR/7WARbY7PZHgO660Wg3IexK3tM+lr/OnH28yIItPQ=
buf.build/gen/go/opencensus/opencensus/protocolbuffers/go v1.31.0-20230503204408-7e4755513505.1/go.mod h1:v274lhTHlm2pFzzjZTWNyZ/DqSTLpowVbsfoCB2/xDw=
buf.build/gen/go/opentelemetry/opentelemetry/protocolbuffers/go v1.31.0-20230823200321-2ad07e196ee7.1/go.mod h1:Z8vHgcMy12BQ89FTPKtYuX6U8UgU5/LMlV6MVq7BBlE=
buf.build/gen/go/prometheus/client-model/protocolbuffers/go v1.31.0-20230727201446-741a6a7bbc76.1/go.mod h1:JN4TkluIEzvuA3no7YE9Hx53OddciaeLJGNLNCetkwU=
code.icb4dc0.de/buildr/api v0.0.0-20230905195458-e4d230e5c7fd h1:N4WkVoqphjFXfFwfKpLcEtS5lBCfd9NVytUutiszQ90=
code.icb4dc0.de/buildr/api v0.0.0-20230905195458-e4d230e5c7fd/go.mod h1:eWSjeX25XbbNGKlxVoOf2a8V6xOCIaQh5W65T7nNcL8=
code.icb4dc0.de/buildr/api v0.0.0-20230912160519-4b705a6732bc h1:NpOz5K0Oo/WFWBRsBKf92MTX9iW+sqaImwMuU33z6/s=
code.icb4dc0.de/buildr/api v0.0.0-20230912160519-4b705a6732bc/go.mod h1:eWSjeX25XbbNGKlxVoOf2a8V6xOCIaQh5W65T7nNcL8=
code.icb4dc0.de/buildr/common v0.0.0-20230905195627-a3d5bb4f1ee7 h1:sqBO2IFI0Gs+FiM4kkQjj7QkC0p+AhJKqhCQqCEwlM4=
code.icb4dc0.de/buildr/common v0.0.0-20230905195627-a3d5bb4f1ee7/go.mod h1:biIRy/mBiVPAR/okWN5DFmB3Hnnxt2FP1Qswa4GBMeE=
code.icb4dc0.de/buildr/common v0.0.0-20230912160755-da17cbfde028 h1:12xr1rT8faxqY7QqI7Z4nlKw1UdQZNfAtv4FybTPtwk=
code.icb4dc0.de/buildr/common v0.0.0-20230912160755-da17cbfde028/go.mod h1:GMFttKFr14bCsjGHbq1tUCOuru7AqBkELvsk2Xhn0Bw=
code.icb4dc0.de/prskr/go-pwgen v0.0.0-20230427131724-8ef26fd9749e h1:N+3hdfeHRf/ndLjiZoet6h+9eZ2Zr5O/Ia5G7b3oQXU=
code.icb4dc0.de/prskr/go-pwgen v0.0.0-20230427131724-8ef26fd9749e/go.mod h1:1MCCxqZsOgfQzV8AR2ZAVRI36MEGF+teFium6Pf2HHU=
connectrpc.com/connect v1.11.1 h1:dqRwblixqkVh+OFBOOL1yIf1jS/yP0MSJLijRj29bFg=
connectrpc.com/connect v1.11.1/go.mod h1:3AGaO6RRGMx5IKFfqbe3hvK1NqLosFNP2BxDYTPmNPo=
connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U=
connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
entgo.io/ent v0.12.3 h1:N5lO2EOrHpCH5HYfiMOCHYbo+oh5M8GjT0/cx5x6xkk=
entgo.io/ent v0.12.3/go.mod h1:AigGGx+tbrBBYHAzGOg8ND661E5cxx1Uiu5o/otJ6Yg=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
@ -26,8 +48,8 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ=
github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
@ -36,8 +58,8 @@ github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbf
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
@ -45,13 +67,7 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY=
github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc=
github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06RaW2cx/SY=
@ -60,16 +76,16 @@ github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM2
github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc=
github.com/charmbracelet/lipgloss v0.8.0 h1:IS00fk4XAHcf8uZKc3eHeMUTCxUH6NkaTrdyCQk84RU=
github.com/charmbracelet/lipgloss v0.8.0/go.mod h1:p4eYUZZJ/0oXTuCQKFF8mqyKCz0ja6y+7DniDDw5KKU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -78,10 +94,14 @@ github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc=
github.com/docker/cli v24.0.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY=
github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.5+incompatible h1:WmgcE4fxyI6EEXxBRxsHnZXrO1pQ3smi0k/jho4HLeY=
github.com/docker/docker v24.0.5+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.6+incompatible h1:hceabKCtUgDqPu+qm0NgsaXf28Ljf4/pWFL7xjWWDgE=
github.com/docker/docker v24.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8=
github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@ -94,10 +114,6 @@ github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3O
github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
@ -108,31 +124,25 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo=
github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A=
github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
@ -150,14 +160,10 @@ github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/hanwen/go-fuse/v2 v2.3.0 h1:t5ivNIH2PK+zw4OBul/iJjsoG9K6kXo4nMDoBpciC8A=
github.com/hanwen/go-fuse/v2 v2.3.0/go.mod h1:xKwi1cF7nXAOBCXujD5ie0ZKsxc8GGSA1rlMJc+8IJs=
github.com/hashicorp/hcl/v2 v2.17.0 h1:z1XvSUyXd1HP10U4lrLg5e0JMVz6CPaJvAgxM0KNZVY=
github.com/hashicorp/hcl/v2 v2.17.0/go.mod h1:gJyW2PTShkJqQBKpAmPO3yxMxIuoXkOF2TpqXzrQyx4=
github.com/hanwen/go-fuse/v2 v2.4.0 h1:12OhD7CkXXQdvxG2osIdBQLdXh+nmLXY9unkUIe/xaU=
github.com/hanwen/go-fuse/v2 v2.4.0/go.mod h1:xKwi1cF7nXAOBCXujD5ie0ZKsxc8GGSA1rlMJc+8IJs=
github.com/hashicorp/hcl/v2 v2.18.0 h1:wYnG7Lt31t2zYkcquwgKo6MWXzRUDIeIVU5naZwHLl8=
github.com/hashicorp/hcl/v2 v2.18.0/go.mod h1:ThLC89FV4p9MPW804KVbe/cEXoQ8NZEh+JtMeeGErHE=
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@ -180,7 +186,6 @@ github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGC
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
@ -208,8 +213,6 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
@ -245,23 +248,12 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0=
github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI=
github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@ -270,13 +262,14 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@ -290,16 +283,14 @@ github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRM
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tetratelabs/wazero v1.4.0 h1:9/MirYvmkJ/zSUOygKY/ia3t+e+RqIZXKbylIby1WYk=
github.com/tetratelabs/wazero v1.4.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
github.com/tetratelabs/wazero v1.5.0 h1:Yz3fZHivfDiZFUXnWMPUoiW7s8tC1sjdBtlJn08qYa0=
github.com/tetratelabs/wazero v1.5.0/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts=
github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
@ -314,25 +305,17 @@ github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5ta
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s=
github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY=
github.com/zclconf/go-cty v1.13.2 h1:4GvrUxe/QUDYuJKAav4EYqdM47/kZa672LwmXFmEKT0=
github.com/zclconf/go-cty v1.13.2/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
github.com/zclconf/go-cty v1.14.0 h1:/Xrd39K7DXbHzlisFP9c4pHao4yyf+/Ug9LEz+Y/yhc=
github.com/zclconf/go-cty v1.14.0/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@ -341,12 +324,8 @@ golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU=
golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -355,16 +334,12 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -375,80 +350,69 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832 h1:o4LtQxebKIJ4vkzyhtD2rfUNZ20Zf0ik5YVP5E7G7VE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230911183012-2d3300fd4832/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw=
google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o=
google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q=
@ -463,8 +427,8 @@ modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=
modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.0 h1:2pXdbgdP5hIyDp2JqIwkHNZ1sAjEbh8GnRpcqFWBf7E=
modernc.org/memory v1.7.0/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/memory v1.7.1 h1:9J+2/GKTlV503mk3yv8QJ6oEpRCUrRy0ad8TXEPoV8M=
modernc.org/memory v1.7.1/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA=

View file

@ -8,7 +8,6 @@ import (
"log/slog"
"os"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/internal/slices"
"code.icb4dc0.de/buildr/buildr/internal/config"
@ -33,11 +32,9 @@ import (
"code.icb4dc0.de/buildr/buildr/internal/services"
"code.icb4dc0.de/buildr/buildr/internal/vault"
"code.icb4dc0.de/buildr/buildr/modules"
"code.icb4dc0.de/buildr/buildr/modules/build"
"code.icb4dc0.de/buildr/buildr/modules/packaging"
"code.icb4dc0.de/buildr/buildr/modules/repo"
"code.icb4dc0.de/buildr/buildr/modules/task"
"code.icb4dc0.de/buildr/buildr/modules/tool"
hcl2 "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
@ -97,7 +94,7 @@ func NewApp() *App {
c,
app,
TasksArgsProviderFor(app, app, c),
WithShort(fmt.Sprintf("Run a %s by its name", v1.CategoryName(c))),
WithShort(fmt.Sprintf("Run a %s by its name", modules.CategoryName(c))),
)
})...,
)
@ -172,8 +169,6 @@ func (a *App) Init(ctx context.Context) (err error) {
}
registry := modules.NewRegistry(
build.Registration,
tool.Registration,
task.Registration,
packaging.Registration,
)

View file

@ -10,7 +10,6 @@ import (
"github.com/Masterminds/sprig/v3"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/internal/tmpl"
"code.icb4dc0.de/buildr/buildr/internal/services"
@ -60,7 +59,7 @@ func (m ManApp) DisplayModuleManual(ctx context.Context, pager Pager, cat module
if h, ok := mod.Unwrap().(modules.Helper); !ok {
slog.Info(
"Module has no help",
slog.String("category", v1.CategoryName(cat)),
slog.String("category", modules.CategoryName(cat)),
slog.String("name", name),
)
return nil

View file

@ -34,7 +34,7 @@ func (s *ServerApp) ServeAPI(ctx context.Context, cfg *rpc.GrpcConfig) error {
grpcServer := rpc.NewServer(logger, s.accessor)
go func() {
if err := grpcServer.Start(cfg.Host.Address); err != nil {
if err := grpcServer.Start(ctx, cfg.Host.Address); err != nil {
slog.Error("Error occurred while serving gRPC API", slog.String("err", err.Error()))
}
}()

View file

@ -3,7 +3,6 @@ package cmd
import (
"github.com/spf13/cobra"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules"
)
@ -22,7 +21,7 @@ func ExecuteModuleCommand(
opts ...ModuleCommandOption,
) *cobra.Command {
cmd := &cobra.Command{
Use: v1.CategoryName(category),
Use: modules.CategoryName(category),
Args: cobra.ExactArgs(1),
SilenceUsage: true,
SilenceErrors: true,

View file

@ -5,7 +5,6 @@ import (
"flag"
"fmt"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/internal/slices"
"code.icb4dc0.de/buildr/buildr/modules"
@ -80,8 +79,8 @@ func ModuleManCommand(
manCfg *ManConfig,
) *cobra.Command {
return &cobra.Command{
Use: v1.CategoryName(category),
Short: fmt.Sprintf("Show manual pages for %s modules", v1.CategoryName(category)),
Use: modules.CategoryName(category),
Short: fmt.Sprintf("Show manual pages for %s modules", modules.CategoryName(category)),
SilenceUsage: true,
SilenceErrors: true,
Args: cobra.ExactArgs(1),
@ -91,7 +90,7 @@ func ModuleManCommand(
return err
}
p, err := manCfg.Pager(cmd.Context(), fmt.Sprintf("Manual - %s/%s", v1.CategoryName(category), args[0]))
p, err := manCfg.Pager(cmd.Context(), fmt.Sprintf("Manual - %s/%s", modules.CategoryName(category), args[0]))
if err != nil {
return err
}

View file

@ -4,7 +4,6 @@ import (
"fmt"
"os"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/internal/slices"
"code.icb4dc0.de/buildr/buildr/modules"
@ -34,7 +33,7 @@ func ModulesCommand(
c,
moduleCmder,
ModulesArgsProviderFor(initializer, registryAcc, c),
WithShort(fmt.Sprintf("Bootstrap %s module", v1.CategoryName(c))),
WithShort(fmt.Sprintf("Bootstrap %s module", modules.CategoryName(c))),
)
})...,
),

View file

@ -3,7 +3,6 @@ package cmd
import (
"github.com/spf13/cobra"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules"
)
@ -26,7 +25,7 @@ func BootstrapModuleCmd(
) *cobra.Command {
const argsWithModuleName = 2
cmd := &cobra.Command{
Use: v1.CategoryName(category),
Use: modules.CategoryName(category),
SilenceUsage: true,
SilenceErrors: true,
ValidArgsFunction: argsProvider.ValidModulesArgs,

View file

@ -2,30 +2,26 @@ package containers
import (
"context"
"errors"
"time"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
"google.golang.org/grpc"
v1 "google.golang.org/grpc/health/grpc_health_v1"
)
"buf.build/gen/go/grpc/grpc/connectrpc/go/grpc/health/v1/healthv1connect"
v1 "buf.build/gen/go/grpc/grpc/protocolbuffers/go/grpc/health/v1"
"connectrpc.com/connect"
const DefaultBackoffDuration = 100 * time.Millisecond
"code.icb4dc0.de/buildr/buildr/internal/rpc"
)
var _ Probe = (*GrpcHealthProbe)(nil)
func NewGRPCHealthProbe(conn *grpc.ClientConn, backoffDuration time.Duration) GrpcHealthProbe {
if backoffDuration == 0 {
backoffDuration = DefaultBackoffDuration
}
func NewGRPCHealthProbe(baseUrl string) GrpcHealthProbe {
return GrpcHealthProbe{
backoffDuration: backoffDuration,
client: v1.NewHealthClient(conn),
client: healthv1connect.NewHealthClient(rpc.NewH2cHTTPClient(), baseUrl),
}
}
type GrpcHealthProbe struct {
client v1.HealthClient
client healthv1connect.HealthClient
backoffDuration time.Duration
}
@ -35,16 +31,17 @@ func (g GrpcHealthProbe) Execute(ctx context.Context) (ready chan bool, errs cha
go func() {
for ctx.Err() == nil {
resp, err := g.client.Check(
ctx,
&v1.HealthCheckRequest{},
grpc_retry.WithBackoff(grpc_retry.BackoffExponential(g.backoffDuration)),
)
resp, err := g.client.Check(ctx, connect.NewRequest(new(v1.HealthCheckRequest)))
if err != nil {
var conErr *connect.Error
if errors.As(err, &conErr) && conErr.Code() == connect.CodeUnavailable {
continue
}
errs <- err
continue
}
if resp.Status == v1.HealthCheckResponse_SERVING {
if resp.Msg.Status == v1.HealthCheckResponse_SERVING {
ready <- true
return
}

View file

@ -17,9 +17,6 @@ import (
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"
"google.golang.org/grpc"
"google.golang.org/grpc/backoff"
"google.golang.org/grpc/credentials/insecure"
"code.icb4dc0.de/buildr/buildr/internal/archive"
"code.icb4dc0.de/buildr/buildr/internal/ignore"
@ -67,8 +64,8 @@ type Orchestrator struct {
dockerHostArch string
}
func (o *Orchestrator) BuildRContainer(ctx context.Context, spec *BuildRContainerSpec) (Container, *grpc.ClientConn, error) {
con := &containerRef{
func (o *Orchestrator) BuildRContainer(ctx context.Context, spec *BuildRContainerSpec) (con Container, baseUrl string, err error) {
conRef := &containerRef{
shutdowner: o,
client: o.client,
resourceName: fmt.Sprintf("buildr-%s-%s", spec.ModuleName, spec.ID),
@ -78,16 +75,16 @@ func (o *Orchestrator) BuildRContainer(ctx context.Context, spec *BuildRContaine
defer cancel()
if err := o.pullImage(containerSetupCtx, spec.Image); err != nil {
return nil, nil, err
return nil, "", err
}
if err := o.createContainerNetwork(containerSetupCtx, con); err != nil {
return nil, nil, err
if err := o.createContainerNetwork(containerSetupCtx, conRef); err != nil {
return nil, "", err
}
var buildrExecutablePath string
if e, err := os.Executable(); err != nil {
return nil, nil, fmt.Errorf("failed to determine buildr executable: %w", err)
return nil, "", fmt.Errorf("failed to determine buildr executable: %w", err)
} else {
buildrExecutablePath = e
}
@ -96,8 +93,8 @@ func (o *Orchestrator) BuildRContainer(ctx context.Context, spec *BuildRContaine
containerRepoRoot, conSpec := spec.containerSpec(buildrExecutableName)
if err := o.createContainer(containerSetupCtx, conSpec, con); err != nil {
return nil, nil, err
if err := o.createContainer(containerSetupCtx, conSpec, conRef); err != nil {
return nil, "", err
}
for i := range spec.ExtraBinaries {
@ -107,50 +104,39 @@ func (o *Orchestrator) BuildRContainer(ctx context.Context, spec *BuildRContaine
spec.Content[buildrExecutablePath] = path.Join("/", "opt", "buildr", "bin", buildrExecutableName)
if err := o.copyFilesToContainer(containerSetupCtx, spec.RepoRoot, con, spec.Content, containerRepoRoot); err != nil {
return nil, nil, err
if err := o.copyFilesToContainer(containerSetupCtx, spec.RepoRoot, conRef, spec.Content, containerRepoRoot); err != nil {
return nil, "", err
}
if err := o.client.ContainerStart(containerSetupCtx, con.containerID, types.ContainerStartOptions{}); err != nil {
return nil, nil, err
if err := o.client.ContainerStart(containerSetupCtx, conRef.containerID, types.ContainerStartOptions{}); err != nil {
return nil, "", err
}
if status, err := o.client.ContainerInspect(containerSetupCtx, con.containerID); err != nil {
return nil, nil, err
if status, err := o.client.ContainerInspect(containerSetupCtx, conRef.containerID); err != nil {
return nil, "", err
} else if !status.State.Running {
return nil, nil, fmt.Errorf("container %s is not running: %d - %s", con.containerID, status.State.ExitCode, status.State.Error)
return nil, "", fmt.Errorf("container %s is not running: %d - %s", conRef.containerID, status.State.ExitCode, status.State.Error)
}
_, port, err := con.MappedPort(containerSetupCtx, "3000/tcp")
_, port, err := conRef.MappedPort(containerSetupCtx, "3000/tcp")
if err != nil {
return nil, nil, err
return nil, "", err
}
conn, err := grpc.DialContext(
containerSetupCtx,
fmt.Sprintf("localhost:%s", port),
grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithConnectParams(grpc.ConnectParams{
Backoff: backoff.DefaultConfig,
MinConnectTimeout: defaultGRPCDialTimeout,
}),
)
if err != nil {
return nil, nil, fmt.Errorf("failed to connect gRPC connection: %w", err)
}
baseUrl = fmt.Sprintf("http://localhost:%s", port)
prober := NewContainerProbe(
slog.Default(),
con.containerID,
NewGRPCHealthProbe(conn, 0),
conRef.containerID,
NewGRPCHealthProbe(baseUrl),
o.client,
)
if err = prober.WaitReady(containerSetupCtx); err != nil {
return nil, nil, fmt.Errorf("error occurred while waiting for container to be ready: %w", err)
return nil, "", fmt.Errorf("error occurred while waiting for container to be ready: %w", err)
}
return con, conn, nil
return conRef, baseUrl, nil
}
func (o *Orchestrator) ShutdownContainer(ctx context.Context, con Container) error {

View file

@ -13,15 +13,22 @@ import (
"sync"
"time"
"connectrpc.com/connect"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/common/protocol"
"code.icb4dc0.de/buildr/buildr/modules/plugin"
"code.icb4dc0.de/buildr/buildr/internal/rpc"
"code.icb4dc0.de/buildr/buildr/internal/errs"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules/state"
"github.com/klauspost/compress/s2"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
"code.icb4dc0.de/buildr/api/generated/remote/v1/rpcv1connect"
"code.icb4dc0.de/buildr/buildr/internal/containers"
"code.icb4dc0.de/buildr/buildr/internal/execution"
@ -68,7 +75,7 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
Default().
With(
slog.String("module_name", c.moduleWithMeta.Name()),
slog.String("module_type", v1.CategoryName(c.moduleWithMeta.Category())),
slog.String("module_type", modules.CategoryName(c.moduleWithMeta.Category())),
)
if c.moduleWithMeta.ShouldSkip() {
@ -84,7 +91,7 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
continue
}
if binNamer, ok := depMod.Unwrap().(modules.BinaryNamer); ok {
if extraBin := binNamer.BinaryName(); extraBin != "" {
if extraBin, err := binNamer.BinaryName(ctx); err == nil && extraBin != "" {
extraBinaries = append(extraBinaries, extraBin)
}
}
@ -124,31 +131,39 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
}
logger.Debug("Preparing container")
con, grpcConn, err := c.orchestrator.BuildRContainer(ctx, &buildrContainerSpec)
con, baseURL, err := c.orchestrator.BuildRContainer(ctx, &buildrContainerSpec)
if err != nil {
return fmt.Errorf("failed to create container for task %s/%s: %w", c.moduleWithMeta.Type(), c.moduleWithMeta.Name(), err)
}
var keepContainer bool
defer func() {
if keepContainer {
err = errors.Join(err, grpcConn.Close())
return
}
err = errors.Join(err, grpcConn.Close(), con.Shutdown(context.Background()))
}()
executorClient := rpcv1.NewExecutorServiceClient(grpcConn)
logger.Debug("Start remote task execution")
streamClient, err := executorClient.ExecuteStream(ctx)
if err != nil {
return fmt.Errorf("failed to start remote task execution: %w", err)
client := rpc.NewH2cHTTPClient()
moduleReference := &commonv1.ModuleReference{
ModuleCategory: c.moduleWithMeta.Category(),
ModuleType: c.moduleWithMeta.Type(),
}
if pluginModule, ok := c.moduleWithMeta.Unwrap().(plugin.Module); ok {
payload, err := pluginModule.PluginPayload.Bytes()
if err != nil {
return err
}
pluginMgrClient := rpcv1connect.NewPluginManagerServiceClient(client, baseURL)
registerPluginRequest := &remotev1.RegisterPluginModuleRequest{
ModuleRef: moduleReference,
PluginPayload: payload,
}
if _, err := pluginMgrClient.RegisterPluginModule(ctx, connect.NewRequest(registerPluginRequest)); err != nil {
return err
}
}
executorClient := rpcv1connect.NewExecutorServiceClient(client, baseURL)
logger.Debug("Start remote task execution")
streamClient := executorClient.ExecuteStream(ctx)
defer func() {
err = errors.Join(err, streamClient.CloseSend())
err = errors.Join(err, streamClient.CloseRequest())
}()
rawModule, err := protocol.Marshal(c.moduleWithMeta.Unwrap())
@ -158,21 +173,18 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
rawModule.Category = c.moduleWithMeta.Category()
startTaskReq := &rpcv1.ExecutionClientMessage{
Envelope: &rpcv1.ExecutionClientMessage_StartTask{
StartTask: &rpcv1.StartTaskRequest{
Buildr: &rpcv1.Buildr{
Repo: &rpcv1.Buildr_Repo{
startTaskReq := &remotev1.ExecutionClientMessage{
Envelope: &remotev1.ExecutionClientMessage_StartTask{
StartTask: &remotev1.StartTaskRequest{
Buildr: &remotev1.Buildr{
Repo: &remotev1.Buildr_Repo{
Root: fmt.Sprintf("/work/%s", c.moduleWithMeta.ID()),
},
},
Reference: &rpcv1.TaskReference{
Id: c.moduleWithMeta.ID(),
Name: c.moduleWithMeta.Name(),
Module: &rpcv1.ModuleReference{
ModuleCategory: c.moduleWithMeta.Category(),
ModuleType: c.moduleWithMeta.Type(),
},
Reference: &remotev1.TaskReference{
Id: c.moduleWithMeta.ID(),
Name: c.moduleWithMeta.Name(),
Module: moduleReference,
},
Spec: rawModule,
},
@ -185,21 +197,20 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
}
for {
ev, err := streamClient.Recv()
ev, err := streamClient.Receive()
if err != nil {
keepContainer = true
return fmt.Errorf("failed to receive remote executor event: %w", err)
}
switch msg := ev.GetEnvelope().(type) {
case *rpcv1.ExecutionServerMessage_TaskLog:
case *remotev1.ExecutionServerMessage_TaskLog:
c.handleTaskLog(ctx, msg.TaskLog, logger)
case *rpcv1.ExecutionServerMessage_TaskOutput:
case *remotev1.ExecutionServerMessage_TaskOutput:
logger.Debug("Handle task output")
if err = c.handleTaskOutput(outputSink, msg.TaskOutput); err != nil {
logger.Error("Failed to process task output", slog.String("err", err.Error()))
}
case *rpcv1.ExecutionServerMessage_TaskResult:
case *remotev1.ExecutionServerMessage_TaskResult:
logger.Debug("Received task result")
if errMsg := msg.TaskResult.Error; errMsg != "" {
return fmt.Errorf("failed to execute task: %s", msg.TaskResult.Error)
@ -216,16 +227,16 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
}
return nil
case *rpcv1.ExecutionServerMessage_SetState:
msgIDMeta, ok := ev.Meta.(*rpcv1.ExecutionServerMessage_MessageId)
case *remotev1.ExecutionServerMessage_SetState:
msgIDMeta, ok := ev.Meta.(*remotev1.ExecutionServerMessage_MessageId)
if !ok {
continue
}
result := &rpcv1.ExecutionClientMessage_Error{
Error: new(rpcv1.Result),
result := &remotev1.ExecutionClientMessage_Error{
Error: new(remotev1.Result),
}
respMsg := &rpcv1.ExecutionClientMessage{
Meta: &rpcv1.ExecutionClientMessage_RepliesTo{
respMsg := &remotev1.ExecutionClientMessage{
Meta: &remotev1.ExecutionClientMessage_RepliesTo{
RepliesTo: msgIDMeta.MessageId,
},
Envelope: result,
@ -240,30 +251,30 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
if err = streamClient.Send(respMsg); err != nil {
logger.Error("Failed to send set status response", errs.Attr(err))
}
case *rpcv1.ExecutionServerMessage_GetState:
case *remotev1.ExecutionServerMessage_GetState:
k := state.PlainKey(msg.GetState.Key)
msgIDMeta, ok := ev.Meta.(*rpcv1.ExecutionServerMessage_MessageId)
msgIDMeta, ok := ev.Meta.(*remotev1.ExecutionServerMessage_MessageId)
if !ok {
continue
}
respMsg := &rpcv1.ExecutionClientMessage{
Meta: &rpcv1.ExecutionClientMessage_RepliesTo{
respMsg := &remotev1.ExecutionClientMessage{
Meta: &remotev1.ExecutionClientMessage_RepliesTo{
RepliesTo: msgIDMeta.MessageId,
},
}
data, _, err := c.stateStore.Get(ctx, k)
if err == nil {
respMsg.Envelope = &rpcv1.ExecutionClientMessage_GetState{
GetState: &rpcv1.GetStateResponse{
respMsg.Envelope = &remotev1.ExecutionClientMessage_GetState{
GetState: &remotev1.GetStateResponse{
Key: msg.GetState.Key,
Data: data,
},
}
} else {
respMsg.Envelope = &rpcv1.ExecutionClientMessage_Error{
Error: &rpcv1.Result{
respMsg.Envelope = &remotev1.ExecutionClientMessage_Error{
Error: &remotev1.Result{
Error: err.Error(),
},
}
@ -276,16 +287,16 @@ func (c *containerTask) doExecute(ctx context.Context, spec execution.Spec) (err
}
}
func (c *containerTask) handleTaskOutput(sink logging.TaskOutputSink, req *rpcv1.TaskOutput) (err error) {
func (c *containerTask) handleTaskOutput(sink logging.TaskOutputSink, req *remotev1.TaskOutput) (err error) {
//nolint:exhaustive // not necessary here
switch req.Source {
case rpcv1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDOUT:
case remotev1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDOUT:
writer := sink.StdOut()
_, err = writer.Write(req.Payload)
if syncer, ok := writer.(interface{ Sync() error }); ok {
err = errors.Join(err, syncer.Sync())
}
case rpcv1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDERR:
case remotev1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDERR:
writer := sink.StdErr()
_, err = writer.Write(req.Payload)
if syncer, ok := writer.(interface{ Sync() error }); ok {
@ -296,7 +307,7 @@ func (c *containerTask) handleTaskOutput(sink logging.TaskOutputSink, req *rpcv1
return err
}
func (c *containerTask) handleTaskLog(ctx context.Context, taskLog *rpcv1.TaskLog, logger *slog.Logger) {
func (c *containerTask) handleTaskLog(ctx context.Context, taskLog *remotev1.TaskLog, logger *slog.Logger) {
handler := logger.Handler()
level := slog.Level(taskLog.Level)
if !handler.Enabled(ctx, level) {

View file

@ -9,7 +9,6 @@ import (
"path/filepath"
"sync"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules/state"
"golang.org/x/sync/errgroup"
@ -80,7 +79,7 @@ func (t *localTask) doExecute(ctx context.Context, spec execution.Spec) error {
}
if err := t.module.Execute(execCtx); err != nil {
return fmt.Errorf("failed to execute module %s/%s: %w", v1.CategoryName(t.module.Category()), t.module.Name(), err)
return fmt.Errorf("failed to execute module %s/%s: %w", modules.CategoryName(t.module.Category()), t.module.Name(), err)
}
return nil
@ -159,7 +158,7 @@ func (t *localTask) executeIsolated(ctx context.Context, spec execution.Spec) er
}()
if err = t.module.Execute(execCtx); err != nil {
return fmt.Errorf("failed to execute module %s/%s: %w", v1.CategoryName(t.module.Category()), t.module.Name(), err)
return fmt.Errorf("failed to execute module %s/%s: %w", modules.CategoryName(t.module.Category()), t.module.Name(), err)
}
return nil
@ -186,7 +185,7 @@ func (t *localTask) executionContextFor(
WithLoggerFactory(func() *slog.Logger {
return slog.Default().With(
slog.String("module_name", m.Name()),
slog.String("module_type", v1.CategoryName(m.Category())),
slog.String("module_type", modules.CategoryName(m.Category())),
)
}),
)

View file

@ -4,7 +4,6 @@ import (
"context"
"fmt"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules"
)
@ -16,7 +15,7 @@ func NewPlanFor(
) (*Plan, error) {
target := repo.Module(moduleType, moduleName)
if target == nil {
return nil, fmt.Errorf("%w: %s/%s", modules.ErrNoSuchModule, v1.CategoryName(moduleType), moduleName)
return nil, fmt.Errorf("%w: %s/%s", modules.ErrNoSuchModule, modules.CategoryName(moduleType), moduleName)
}
entryPoint, err := factory.TaskForModule(target.ID(), repo)

View file

@ -9,7 +9,6 @@ import (
"github.com/hashicorp/hcl/v2/hclsyntax"
"github.com/zclconf/go-cty/cty"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules"
)
@ -85,7 +84,7 @@ func initBlock(body *hclsyntax.Body, moduleType modules.Category, moduleName, ou
body.Attributes["out_dir"] = &hclsyntax.Attribute{
Name: "out_dir",
Expr: &hclsyntax.LiteralValueExpr{
Val: cty.StringVal(filepath.Join(outDir, v1.CategoryName(moduleType), moduleName)),
Val: cty.StringVal(filepath.Join(outDir, modules.CategoryName(moduleType), moduleName)),
},
}
}

View file

@ -6,7 +6,6 @@ import (
"github.com/hashicorp/hcl/v2/hclwrite"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules"
)
@ -40,7 +39,7 @@ type Writer[T modules.ModuleWithMeta] struct {
func (w *Writer[T]) Write(in T) error {
f := hclwrite.NewEmptyFile()
block := hclwrite.NewBlock(v1.CategoryName(in.Category()), []string{in.Type(), in.Name()})
block := hclwrite.NewBlock(modules.CategoryName(in.Category()), []string{in.Type(), in.Name()})
if err := w.marshalInto(reflect.ValueOf(in), block); err != nil {
return err
}

View file

@ -70,13 +70,18 @@ func (h HTTPDownloader) Download(ctx context.Context, target string, src *url.UR
return err
}
type FileDownloader struct {
}
type FileDownloader struct{}
func (f FileDownloader) Download(_ context.Context, target string, src *url.URL) error {
if src.Scheme != "file" {
return fmt.Errorf("%w: %s", ErrUnsupportedProtocol, src.Scheme)
}
if _, err := os.Stat(target); err == nil {
if err = os.Remove(target); err != nil {
return err
}
}
return os.Link(src.Path, target)
}

View file

@ -13,6 +13,9 @@ import (
"os"
"path/filepath"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/buildr/internal/config"
"code.icb4dc0.de/buildr/buildr/internal/slices"
@ -24,8 +27,6 @@ import (
"code.icb4dc0.de/buildr/buildr/modules"
"code.icb4dc0.de/buildr/buildr/modules/plugin"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
"code.icb4dc0.de/buildr/buildr/modules/state"
)
@ -59,7 +60,7 @@ func (p *Manager) Register(ctx context.Context, registry *modules.TypeRegistry)
module := module
registry.RegisterModule(modules.ModuleFactoryFunc(func() modules.ModuleWithMeta {
var (
defaultSpec = new(rpcv1.ModuleSpec)
defaultSpec = new(commonv1.ModuleSpec)
mod = plugin.Module{
PluginPayload: &plugin.PayloadFile{
Path: registeredPlugin.LocalPath,
@ -119,7 +120,7 @@ func (p *Manager) UpdatePlugins(ctx context.Context, refs ...config.PluginRefere
} else if inventory, err := plugin.DiscoverInventory(ctx, payload); err != nil {
return err
} else {
pluginModules := slices.Map(inventory.Specs, func(in *rpcv1.PluginInventory_InventorySpec) state.PluginModule {
pluginModules := slices.Map(inventory.Specs, func(in *wasiv1.PluginInventoryResponse_InventorySpec) state.PluginModule {
return moduleReferenceToPluginModule(pluginID, in)
})
if err := p.plugins.UpsertModules(ctx, pluginModules); err != nil {
@ -253,7 +254,7 @@ func hashFile(filePath string, h hash.Hash) (computedHash, payload []byte, err e
return h.Sum(nil), buf.Bytes(), nil
}
func moduleReferenceToPluginModule(pluginID uuid.UUID, in *rpcv1.PluginInventory_InventorySpec) state.PluginModule {
func moduleReferenceToPluginModule(pluginID uuid.UUID, in *wasiv1.PluginInventoryResponse_InventorySpec) state.PluginModule {
return state.PluginModule{
PluginID: pluginID,
Type: in.ModuleRef.ModuleType,

25
internal/rpc/client.go Normal file
View file

@ -0,0 +1,25 @@
package rpc
import (
"context"
"crypto/tls"
"net"
"net/http"
"golang.org/x/net/http2"
)
func NewH2cHTTPClient() *http.Client {
return &http.Client{
Transport: &http2.Transport{
AllowHTTP: true,
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
// If you're also using this client for non-h2c traffic, you may want
// to delegate to tls.Dial if the network isn't TCP or the addr isn't
// in an allowlist.
return net.Dial(network, addr)
},
},
}
}

View file

@ -1,28 +0,0 @@
package middleware
import (
"context"
"errors"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var ContextErrorConverter grpc.UnaryServerInterceptor = func(
ctx context.Context,
req any,
_ *grpc.UnaryServerInfo,
handler grpc.UnaryHandler,
) (resp any, err error) {
resp, err = handler(ctx, req)
switch {
case errors.Is(err, context.DeadlineExceeded):
err = status.Error(codes.DeadlineExceeded, err.Error())
case errors.Is(err, context.Canceled):
err = status.Errorf(codes.Canceled, err.Error())
default:
}
return
}

View file

@ -1,85 +0,0 @@
package middleware_test
import (
"context"
"errors"
"testing"
"time"
"code.icb4dc0.de/buildr/buildr/internal/rpc/middleware"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestContextErrorConverter(t *testing.T) {
t.Parallel()
type args struct {
handler grpc.UnaryHandler
}
tests := []struct {
want error
args args
name string
wantError bool
}{
{
name: "Not a context error",
args: args{
handler: func(context.Context, any) (any, error) {
return nil, errors.New("there's something strange in the neighborhood")
},
},
wantError: true,
want: errors.New("there's something strange in the neighborhood"),
},
{
name: "Not an error at all",
args: args{
handler: func(context.Context, any) (any, error) {
//nolint:nilnil // on purpose
return nil, nil
},
},
wantError: false,
},
{
name: "Context canceled error",
args: args{
handler: func(context.Context, any) (any, error) {
return nil, context.Canceled
},
},
wantError: true,
want: status.Error(codes.Canceled, context.Canceled.Error()),
},
{
name: "Context DeadlineExceeded error",
args: args{
handler: func(context.Context, any) (any, error) {
return nil, context.DeadlineExceeded
},
},
wantError: true,
want: status.Error(codes.Canceled, context.DeadlineExceeded.Error()),
},
}
for _, tc := range tests {
tt := tc
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
ctx, cancel := context.WithTimeout(context.Background(), 50*time.Millisecond)
t.Cleanup(cancel)
if _, err := middleware.ContextErrorConverter(ctx, nil, new(grpc.UnaryServerInfo), tt.args.handler); err != nil {
if !tt.wantError && !errors.Is(err, tt.want) {
t.Errorf("Got error but type was not expected - error = %v", err)
}
return
}
if tt.wantError {
t.Error("Expected error but didn't get one")
}
})
}
}

View file

@ -1,27 +1,29 @@
package rpc
import (
"context"
"log/slog"
"net"
"net/http"
"sync"
"time"
grpcmiddleware "github.com/grpc-ecosystem/go-grpc-middleware"
recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
v1Health "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/reflection"
"buf.build/gen/go/grpc/grpc/connectrpc/go/grpc/health/v1/healthv1connect"
"connectrpc.com/grpcreflect"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
"code.icb4dc0.de/buildr/api/generated/remote/v1/rpcv1connect"
"code.icb4dc0.de/buildr/buildr/internal/rpc/middleware"
v1 "code.icb4dc0.de/buildr/buildr/internal/rpc/v1"
"code.icb4dc0.de/buildr/buildr/internal/services"
"google.golang.org/grpc"
)
const serverShutdownTimeout = 5 * time.Second
const (
serverShutdownTimeout = 5 * time.Second
defaultReadWriteTimeout = 200 * time.Millisecond
defaultIdleTimeout = 30 * time.Second
)
func NewServer(
logger *slog.Logger,
@ -40,12 +42,12 @@ func NewServer(
type BuildrAPI struct {
typeRegistryAccess services.TypeRegistryAccessor
logger *slog.Logger
server *grpc.Server
server *http.Server
serverRunning chan struct{}
lock sync.Mutex
}
func (a *BuildrAPI) Start(address string) (err error) {
func (a *BuildrAPI) Start(ctx context.Context, address string) (err error) {
a.lock.Lock()
a.serverRunning = make(chan struct{})
a.lock.Unlock()
@ -55,24 +57,27 @@ func (a *BuildrAPI) Start(address string) (err error) {
return err
}
a.server = grpc.NewServer(
grpc.StreamInterceptor(
grpcmiddleware.ChainStreamServer(
recovery.StreamServerInterceptor(),
prometheus.StreamServerInterceptor,
)),
grpc.UnaryInterceptor(grpcmiddleware.ChainUnaryServer(
recovery.UnaryServerInterceptor(),
middleware.ContextErrorConverter,
prometheus.UnaryServerInterceptor,
)),
mux := http.NewServeMux()
a.server = &http.Server{
Handler: h2c.NewHandler(mux, &http2.Server{}),
ReadHeaderTimeout: defaultReadWriteTimeout,
IdleTimeout: defaultIdleTimeout,
BaseContext: func(net.Listener) context.Context {
return ctx
},
}
reflector := grpcreflect.NewStaticReflector(
"grpc.health.v1.Health",
"buildr.rpc.v1.ExecutorService",
// "buildr.rpc.v1.buildr.rpc.v1.PluginManagerService",
)
v1Health.RegisterHealthServer(a.server, v1.NewHealthServer(a.logger))
rpcv1.RegisterExecutorServiceServer(a.server, v1.NewExecutorServiceServer(a.typeRegistryAccess.TypeRegistry()))
reflection.Register(a.server)
mux.Handle(grpcreflect.NewHandlerV1Alpha(reflector))
mux.Handle(grpcreflect.NewHandlerV1(reflector))
mux.Handle(healthv1connect.NewHealthHandler(v1.NewHealthServer(a.logger)))
mux.Handle(rpcv1connect.NewExecutorServiceHandler(v1.NewExecutorServiceServer(a.typeRegistryAccess.TypeRegistry())))
defer func() {
a.lock.Lock()
@ -90,14 +95,16 @@ func (a *BuildrAPI) Close() {
}
gracefulStopChan := make(chan struct{})
go func() {
a.server.GracefulStop()
ctx, cancel := context.WithTimeout(context.Background(), serverShutdownTimeout)
defer cancel()
_ = a.server.Shutdown(ctx)
close(gracefulStopChan)
}()
select {
case <-gracefulStopChan:
case <-time.After(serverShutdownTimeout):
a.server.Stop()
_ = a.server.Close()
}
}

View file

@ -9,5 +9,5 @@ type StreamSender[T proto.Message] interface {
}
type StreamReceiver[T proto.Message] interface {
Recv() (msg T, err error)
Receive() (msg T, err error)
}

View file

@ -1,11 +0,0 @@
package v1
import (
"strings"
"code.icb4dc0.de/buildr/buildr/modules"
)
func CategoryName(c modules.Category) string {
return strings.Replace(strings.ToLower(c.String()), "category", "", -1)
}

View file

@ -8,7 +8,7 @@ import (
"code.icb4dc0.de/buildr/buildr/modules/state"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/buildr/modules"
)
@ -20,7 +20,7 @@ func NewContainerExecutionContext(
logger *slog.Logger,
name,
workingDir string,
sender StreamSender[*rpcv1.ExecutionServerMessage],
sender StreamSender[*remotev1.ExecutionServerMessage],
remoteState *RemoteStateClient,
) *ContainerExecutionContext {
return &ContainerExecutionContext{
@ -30,11 +30,11 @@ func NewContainerExecutionContext(
logger: logger,
workingDir: workingDir,
stdOutWriter: io.MultiWriter(newTaskOutputWriter(
rpcv1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDOUT,
remotev1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDOUT,
sender,
), os.Stdout),
stdErrWriter: io.MultiWriter(newTaskOutputWriter(
rpcv1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDERR,
remotev1.TaskOutputSource_TASK_OUTPUT_SOURCE_STDERR,
sender,
), os.Stderr),
}

View file

@ -8,7 +8,7 @@ import (
"os"
"time"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/common/protocol"
"code.icb4dc0.de/buildr/buildr/internal/archive"
@ -27,14 +27,14 @@ type RemoteTaskExecutor struct {
logger *slog.Logger
registry *modules.TypeRegistry
requestClient *RequestResponseClient
sender StreamSender[*rpcv1.ExecutionServerMessage]
sender StreamSender[*remotev1.ExecutionServerMessage]
}
func (e *RemoteTaskExecutor) Execute(
ctx context.Context,
startTask *rpcv1.StartTaskRequest,
) (resp chan *rpcv1.TaskResult, errs chan error) {
resp = make(chan *rpcv1.TaskResult)
startTask *remotev1.StartTaskRequest,
) (resp chan *remotev1.TaskResult, errs chan error) {
resp = make(chan *remotev1.TaskResult)
errs = make(chan error)
ctx, cancel := context.WithCancelCause(ctx)
@ -81,10 +81,10 @@ func (e *RemoteTaskExecutor) Execute(
)
err = mod.Execute(executionContext)
result := new(rpcv1.TaskResult)
result := new(remotev1.TaskResult)
if err != nil {
result.Error = fmt.Sprintf("failed to execute module %s/%s: %s", CategoryName(mod.Category()), mod.Name(), err.Error())
result.Error = fmt.Sprintf("failed to execute module %s/%s: %s", modules.CategoryName(mod.Category()), mod.Name(), err.Error())
}
e.logger.Debug("Waiting for file change events to propagate before canceling watcher")
@ -104,7 +104,7 @@ func (e *RemoteTaskExecutor) Execute(
return resp, errs
}
func (e *RemoteTaskExecutor) addModifiedFilesToResult(result *rpcv1.TaskResult, watcher *fsWatcher) error {
func (e *RemoteTaskExecutor) addModifiedFilesToResult(result *remotev1.TaskResult, watcher *fsWatcher) error {
tmpFile, err := os.CreateTemp(os.TempDir(), "buildr-modified-files-*.tar.s2")
if err != nil {
e.logger.Error("Failed to create temporary file", slog.String("err", err.Error()))

View file

@ -7,7 +7,10 @@ import (
"io"
"log/slog"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
"connectrpc.com/connect"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/api/generated/remote/v1/rpcv1connect"
"code.icb4dc0.de/buildr/buildr/internal/errs"
"code.icb4dc0.de/buildr/buildr/modules"
@ -17,11 +20,11 @@ import (
)
var (
_ rpcv1.ExecutorServiceServer = (*ExecutorServiceServer)(nil)
ErrExecutionCompleted = errors.New("execution completed")
_ rpcv1connect.ExecutorServiceHandler = (*ExecutorServiceServer)(nil)
ErrExecutionCompleted = errors.New("execution completed")
)
func NewExecutorServiceServer(registry *modules.TypeRegistry) rpcv1.ExecutorServiceServer {
func NewExecutorServiceServer(registry *modules.TypeRegistry) rpcv1connect.ExecutorServiceHandler {
return &ExecutorServiceServer{
registry: registry,
}
@ -31,8 +34,8 @@ type ExecutorServiceServer struct {
registry *modules.TypeRegistry
}
func (e *ExecutorServiceServer) ExecuteStream(server rpcv1.ExecutorService_ExecuteStreamServer) (err error) {
ctx, cancel := context.WithCancelCause(server.Context())
func (e *ExecutorServiceServer) ExecuteStream(ctx context.Context, stream *connect.BidiStream[remotev1.ExecutionClientMessage, remotev1.ExecutionServerMessage]) (err error) {
ctx, cancel := context.WithCancelCause(ctx)
defer cancel(errors.New("stream closed"))
defer func() {
@ -41,10 +44,10 @@ func (e *ExecutorServiceServer) ExecuteStream(server rpcv1.ExecutorService_Execu
}
}()
logger := slog.New(NewGrpcExecutorHandler(server))
requestClient := NewRequestResponseClient(logger, server)
logger := slog.New(NewGrpcExecutorHandler(stream))
requestClient := NewRequestResponseClient(logger, stream)
request, err := server.Recv()
request, err := stream.Receive()
if err != nil {
if errors.Is(err, io.EOF) {
return nil
@ -53,7 +56,7 @@ func (e *ExecutorServiceServer) ExecuteStream(server rpcv1.ExecutorService_Execu
}
}
unwrapped, ok := request.GetEnvelope().(*rpcv1.ExecutionClientMessage_StartTask)
unwrapped, ok := request.GetEnvelope().(*remotev1.ExecutionClientMessage_StartTask)
if !ok {
return status.Error(codes.InvalidArgument, "expected StartTask as first message in stream")
}
@ -62,10 +65,10 @@ func (e *ExecutorServiceServer) ExecuteStream(server rpcv1.ExecutorService_Execu
logger: logger,
registry: e.registry,
requestClient: requestClient,
sender: server,
sender: stream,
}
clientErrs := requestClient.DispatchMessages(server)
clientErrs := requestClient.DispatchMessages(stream)
resp, execErrs := executor.Execute(ctx, unwrapped.StartTask)
select {
@ -77,8 +80,8 @@ func (e *ExecutorServiceServer) ExecuteStream(server rpcv1.ExecutorService_Execu
logger.Error("Error occurred while executing module", errs.Attr(e))
return status.Error(codes.Internal, e.Error())
case r := <-resp:
_ = server.Send(&rpcv1.ExecutionServerMessage{
Envelope: &rpcv1.ExecutionServerMessage_TaskResult{
_ = stream.Send(&remotev1.ExecutionServerMessage{
Envelope: &remotev1.ExecutionServerMessage_TaskResult{
TaskResult: r,
},
})

View file

@ -4,12 +4,12 @@ import (
"context"
"log/slog"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
)
var _ slog.Handler = (*GrpcExecutorHandler)(nil)
func NewGrpcExecutorHandler(sender StreamSender[*rpcv1.ExecutionServerMessage]) *GrpcExecutorHandler {
func NewGrpcExecutorHandler(sender StreamSender[*remotev1.ExecutionServerMessage]) *GrpcExecutorHandler {
return &GrpcExecutorHandler{
Level: slog.LevelDebug,
sender: sender,
@ -17,7 +17,7 @@ func NewGrpcExecutorHandler(sender StreamSender[*rpcv1.ExecutionServerMessage])
}
type GrpcExecutorHandler struct {
sender StreamSender[*rpcv1.ExecutionServerMessage]
sender StreamSender[*remotev1.ExecutionServerMessage]
group string
attributes []slog.Attr
Level slog.Level
@ -29,15 +29,15 @@ func (g GrpcExecutorHandler) Enabled(_ context.Context, level slog.Level) bool {
//nolint:gocritic // can't pass by reference due to interface constraints
func (g GrpcExecutorHandler) Handle(_ context.Context, record slog.Record) error {
taskLog := rpcv1.TaskLog{
taskLog := remotev1.TaskLog{
Time: record.Time.UnixMicro(),
Message: record.Message,
Level: int32(record.Level),
Attributes: make([]*rpcv1.TaskLog_LogAttribute, 0, record.NumAttrs()),
Attributes: make([]*remotev1.TaskLog_LogAttribute, 0, record.NumAttrs()),
}
record.Attrs(func(attr slog.Attr) bool {
taskLog.Attributes = append(taskLog.Attributes, &rpcv1.TaskLog_LogAttribute{
taskLog.Attributes = append(taskLog.Attributes, &remotev1.TaskLog_LogAttribute{
Key: attr.Key,
Value: attr.Value.String(),
})
@ -45,8 +45,8 @@ func (g GrpcExecutorHandler) Handle(_ context.Context, record slog.Record) error
return true
})
resp := rpcv1.ExecutionServerMessage{
Envelope: &rpcv1.ExecutionServerMessage_TaskLog{
resp := remotev1.ExecutionServerMessage{
Envelope: &remotev1.ExecutionServerMessage_TaskLog{
TaskLog: &taskLog,
},
}

View file

@ -5,47 +5,48 @@ import (
"log/slog"
"time"
v1 "google.golang.org/grpc/health/grpc_health_v1"
"buf.build/gen/go/grpc/grpc/connectrpc/go/grpc/health/v1/healthv1connect"
v1 "buf.build/gen/go/grpc/grpc/protocolbuffers/go/grpc/health/v1"
"connectrpc.com/connect"
)
const healthCheckInterval = 100 * time.Millisecond
var _ v1.HealthServer = (*healthServer)(nil)
var _ healthv1connect.HealthHandler = (*healthServer)(nil)
func NewHealthServer(logger *slog.Logger) v1.HealthServer {
func NewHealthServer(logger *slog.Logger) healthv1connect.HealthHandler {
return &healthServer{
logger: logger,
}
}
type healthServer struct {
v1.UnimplementedHealthServer
logger *slog.Logger
}
func (h *healthServer) Check(context.Context, *v1.HealthCheckRequest) (resp *v1.HealthCheckResponse, err error) {
resp = &v1.HealthCheckResponse{
func (h *healthServer) Check(context.Context, *connect.Request[v1.HealthCheckRequest]) (*connect.Response[v1.HealthCheckResponse], error) {
resp := &v1.HealthCheckResponse{
Status: v1.HealthCheckResponse_SERVING,
}
return resp, nil
return connect.NewResponse(resp), nil
}
func (h *healthServer) Watch(_ *v1.HealthCheckRequest, server v1.Health_WatchServer) error {
func (h *healthServer) Watch(ctx context.Context, _ *connect.Request[v1.HealthCheckRequest], stream *connect.ServerStream[v1.HealthCheckResponse]) error {
ticker := time.NewTicker(healthCheckInterval)
defer ticker.Stop()
select {
case <-ticker.C:
err := server.Send(&v1.HealthCheckResponse{
err := stream.Send(&v1.HealthCheckResponse{
Status: v1.HealthCheckResponse_SERVING,
})
if err != nil {
h.logger.Error("Failed to send response", slog.String("err", err.Error()))
}
return nil
case <-server.Context().Done():
case <-ctx.Done():
return nil
}
}

View file

@ -0,0 +1,34 @@
package v1
import (
"context"
"connectrpc.com/connect"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/api/generated/remote/v1/rpcv1connect"
"code.icb4dc0.de/buildr/buildr/modules"
"code.icb4dc0.de/buildr/buildr/modules/plugin"
)
var _ rpcv1connect.PluginManagerServiceHandler = (*PluginManagerServiceServer)(nil)
type PluginManagerServiceServer struct {
registry *modules.TypeRegistry
}
func (p PluginManagerServiceServer) RegisterPluginModule(_ context.Context, request *connect.Request[remotev1.RegisterPluginModuleRequest]) (*connect.Response[remotev1.RegisterPluginModuleResponse], error) {
p.registry.RegisterModule(modules.ModuleFactoryFunc(func() modules.ModuleWithMeta {
return &modules.Metadata[plugin.Module]{
Module: plugin.Module{
PluginPayload: plugin.MemoryPayload(request.Msg.GetPluginPayload()),
ModuleSpec: make(map[string]any),
PluginType: request.Msg.ModuleRef.ModuleType,
PluginCategory: request.Msg.ModuleRef.ModuleCategory,
},
}
}))
return connect.NewResponse(new(remotev1.RegisterPluginModuleResponse)), nil
}

View file

@ -8,7 +8,7 @@ import (
"log/slog"
"sync"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"github.com/google/uuid"
)
@ -18,30 +18,30 @@ var (
ErrNoMatchingRequest = errors.New("no matching request for given message id")
)
func NewRequestResponseClient(logger *slog.Logger, sender StreamSender[*rpcv1.ExecutionServerMessage]) *RequestResponseClient {
func NewRequestResponseClient(logger *slog.Logger, sender StreamSender[*remotev1.ExecutionServerMessage]) *RequestResponseClient {
return &RequestResponseClient{
logger: logger,
sender: sender,
requests: make(map[uuid.UUID]chan *rpcv1.ExecutionClientMessage),
requests: make(map[uuid.UUID]chan *remotev1.ExecutionClientMessage),
}
}
type RequestResponseClient struct {
sender StreamSender[*rpcv1.ExecutionServerMessage]
sender StreamSender[*remotev1.ExecutionServerMessage]
logger *slog.Logger
requests map[uuid.UUID]chan *rpcv1.ExecutionClientMessage
requests map[uuid.UUID]chan *remotev1.ExecutionClientMessage
lock sync.Mutex
}
func (rrc *RequestResponseClient) DispatchMessages(receiver StreamReceiver[*rpcv1.ExecutionClientMessage]) (errs chan error) {
func (rrc *RequestResponseClient) DispatchMessages(receiver StreamReceiver[*remotev1.ExecutionClientMessage]) (errs chan error) {
errs = make(chan error)
go func() {
for {
msg, err := receiver.Recv()
msg, err := receiver.Receive()
if err != nil {
if errors.Is(err, io.EOF) {
rrc.logger.Info("Closing request response client")
slog.Default().Info("Closing request response client")
return
}
errs <- err
@ -49,7 +49,7 @@ func (rrc *RequestResponseClient) DispatchMessages(receiver StreamReceiver[*rpcv
}
rrc.logger.Debug("Dispatching message")
repliesTo, ok := msg.Meta.(*rpcv1.ExecutionClientMessage_RepliesTo)
repliesTo, ok := msg.Meta.(*remotev1.ExecutionClientMessage_RepliesTo)
if !ok {
errs <- ErrNoReplyMsgID
continue
@ -83,14 +83,14 @@ func (rrc *RequestResponseClient) DispatchMessages(receiver StreamReceiver[*rpcv
func (rrc *RequestResponseClient) Send(
ctx context.Context,
req *rpcv1.ExecutionServerMessage,
) (resp *rpcv1.ExecutionClientMessage, err error) {
req *remotev1.ExecutionServerMessage,
) (resp *remotev1.ExecutionClientMessage, err error) {
var (
msgID = uuid.New()
respChan = make(chan *rpcv1.ExecutionClientMessage)
respChan = make(chan *remotev1.ExecutionClientMessage)
)
req.Meta = &rpcv1.ExecutionServerMessage_MessageId{
req.Meta = &remotev1.ExecutionServerMessage_MessageId{
MessageId: uuidBytes(msgID),
}
rrc.lock.Lock()
@ -108,7 +108,7 @@ func (rrc *RequestResponseClient) Send(
return nil, ctx.Err()
case resp := <-respChan:
switch unwrap := resp.Envelope.(type) {
case *rpcv1.ExecutionClientMessage_Error:
case *remotev1.ExecutionClientMessage_Error:
if errMsg := unwrap.Error.Error; errMsg != "" {
return nil, errors.New(unwrap.Error.Error)
}

View file

@ -5,7 +5,7 @@ import (
"errors"
"log/slog"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
rpcv1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/buildr/internal/errs"
"code.icb4dc0.de/buildr/buildr/modules"

View file

@ -3,12 +3,12 @@ package v1
import (
"io"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
)
var _ io.Writer = (*taskOutputWriter)(nil)
func newTaskOutputWriter(source rpcv1.TaskOutputSource, sender StreamSender[*rpcv1.ExecutionServerMessage]) taskOutputWriter {
func newTaskOutputWriter(source remotev1.TaskOutputSource, sender StreamSender[*remotev1.ExecutionServerMessage]) taskOutputWriter {
return taskOutputWriter{
source: source,
sender: sender,
@ -16,14 +16,14 @@ func newTaskOutputWriter(source rpcv1.TaskOutputSource, sender StreamSender[*rpc
}
type taskOutputWriter struct {
sender StreamSender[*rpcv1.ExecutionServerMessage]
source rpcv1.TaskOutputSource
sender StreamSender[*remotev1.ExecutionServerMessage]
source remotev1.TaskOutputSource
}
func (t taskOutputWriter) Write(p []byte) (n int, err error) {
err = t.sender.Send(&rpcv1.ExecutionServerMessage{
Envelope: &rpcv1.ExecutionServerMessage_TaskOutput{
TaskOutput: &rpcv1.TaskOutput{
err = t.sender.Send(&remotev1.ExecutionServerMessage{
Envelope: &remotev1.ExecutionServerMessage_TaskOutput{
TaskOutput: &remotev1.TaskOutput{
Source: t.source,
Payload: p,
},

View file

@ -57,12 +57,8 @@ type Module interface {
Type() string
}
type Validatable interface {
Validate() error
}
type BinaryNamer interface {
BinaryName() string
BinaryName(ctx context.Context) (binaryName string, err error)
}
type ToolModule interface {

View file

@ -9,7 +9,7 @@ import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
"code.icb4dc0.de/buildr/common/protocol"
)
@ -109,7 +109,7 @@ type Metadata[T Module] struct {
Deps []string `hcl:"depends_on,optional"`
}
func (m *Metadata[T]) UnmarshalModuleSpec(val *rpcv1.ModuleSpec) error {
func (m *Metadata[T]) UnmarshalModuleSpec(val *commonv1.ModuleSpec) error {
v := reflect.ValueOf(m.Module)
if v.Kind() == reflect.Ptr {
return protocol.Unmarshal(val, m.Module)

View file

@ -1,8 +0,0 @@
package build
import (
"code.icb4dc0.de/buildr/buildr/modules"
)
var Registration = modules.RegistrationFunc(func(registry *modules.TypeRegistry) {
})

9
modules/category.go Normal file
View file

@ -0,0 +1,9 @@
package modules
import (
"strings"
)
func CategoryName(c Category) string {
return strings.Replace(strings.ToLower(c.String()), "category", "", -1)
}

View file

@ -4,35 +4,33 @@ import (
"context"
"errors"
"fmt"
"time"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
"connectrpc.com/connect"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"google.golang.org/protobuf/proto"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/api/generated/wasi/v1/rpcv1connect"
"code.icb4dc0.de/buildr/common/wasirpc"
)
var (
dummyWithoutResult = func(ctx context.Context, m api.Module, offset, byteCount uint32) {}
dummyWithResult = func(ctx context.Context, m api.Module, offset, byteCount uint32) (result uint64) { return 0 }
)
var dummyWithResult = func(ctx context.Context, m api.Module, offset, byteCount uint32) (result uint64) { return 0 }
func DiscoverInventory(ctx context.Context, payload []byte) (inventory *rpcv1.PluginInventory, err error) {
func DiscoverInventory(ctx context.Context, payload []byte) (inventory *wasiv1.PluginInventoryResponse, err error) {
runtimeConfig := wazero.
NewRuntimeConfig().
WithCloseOnContextDone(true)
r := wazero.NewRuntimeWithConfig(ctx, runtimeConfig)
defer func() {
closeCtx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
closeCtx, cancel := context.WithTimeout(context.Background(), runtimeClosingTimeout)
defer cancel()
err = errors.Join(err, r.Close(closeCtx))
}()
_, err = r.NewHostModuleBuilder("buildr").
NewFunctionBuilder().WithFunc(dummyWithoutResult).Export("log_msg").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("log_msg").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("get_state").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("set_state").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("exec").
@ -57,31 +55,16 @@ func DiscoverInventory(ctx context.Context, payload []byte) (inventory *rpcv1.Pl
return nil, fmt.Errorf("failed to instantiate WASI plugin: %w", err)
}
memMgr := newMemoryManager(mod)
result, err := mod.ExportedFunction("inventory").Call(ctx)
moduleClient, err := wasirpc.NewModuleClient(mod)
if err != nil {
return nil, fmt.Errorf("failed to call inventory function: %w", err)
return nil, fmt.Errorf("failed to create module client: %w", err)
}
ptr, size := uint32(result[0]>>defaultIntegerSize), uint32(result[0])
if ptr == 0 {
return nil, errors.New("failed to get inventory - 0 pointer")
wasiClient := rpcv1connect.NewWasiExecutorServiceClient(moduleClient, "wasi://pluginToBeDiscovered")
resp, err := wasiClient.PluginInventory(ctx, connect.NewRequest(new(wasiv1.PluginInventoryRequest)))
if err != nil {
return nil, fmt.Errorf("failed to call plugin inventory: %w", err)
}
defer func() {
err = errors.Join(err, memMgr.Deallocate(ctx, uint64(ptr)))
}()
data, ok := mod.Memory().Read(ptr, size)
if !ok {
return nil, errors.New("failed to get inventory")
}
inventory = new(rpcv1.PluginInventory)
if err = proto.Unmarshal(data, inventory); err != nil {
return nil, fmt.Errorf("failed to unmarshal inventory: %w", err)
}
return inventory, nil
return resp.Msg, nil
}

View file

@ -6,42 +6,85 @@ import (
"errors"
"log/slog"
"os/exec"
"reflect"
"time"
"github.com/tetratelabs/wazero/api"
"google.golang.org/protobuf/proto"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
bapi "code.icb4dc0.de/buildr/api"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/buildr/internal/sh"
"code.icb4dc0.de/buildr/buildr/modules"
)
type wasiPluginExecContext struct {
ctx modules.ExecutionContext
memMgr *memoryManager
const defaultIntegerSize = 32
func NewHostFuncExport[TRequest bapi.ProtoMessage, TResponse bapi.ProtoMessage](f func(ctx context.Context, req TRequest) (TResponse, error)) HostFuncExportWrapper[TRequest, TResponse] {
return f
}
func (c *wasiPluginExecContext) lookPath(ctx context.Context, m api.Module, offset, byteCount uint32) uint64 {
type HostFuncExportWrapper[TRequest bapi.ProtoMessage, TResponse bapi.ProtoMessage] func(ctx context.Context, req TRequest) (TResponse, error)
func (w HostFuncExportWrapper[TRequest, TResponse]) Call(ctx context.Context, m api.Module, offset, byteCount uint32) uint64 {
buf, ok := m.Memory().Read(offset, byteCount)
if !ok {
return 0
}
lookupPathReq := new(rpcv1.LookupPathRequest)
if err := proto.Unmarshal(buf, lookupPathReq); err != nil {
c.ctx.Logger().Error("failed to unmarshal LookupPathRequest", slog.String("err", err.Error()))
return 0
var req TRequest
if reflect.TypeOf(req).Kind() == reflect.Ptr {
req = reflect.New(reflect.TypeOf(req).Elem()).Interface().(TRequest)
}
if err := req.UnmarshalVT(buf); err != nil {
panic(err)
}
resp, err := w(ctx, req)
if err != nil {
panic(err)
}
data, err := resp.MarshalVT()
if err != nil {
panic(err)
}
ptr, err := w.allocate(ctx, m, uint64(len(data)))
if err != nil {
panic(err)
}
if !m.Memory().Write(uint32(ptr), data) {
panic("failed to write message to memory")
}
return (ptr << uint64(defaultIntegerSize)) | uint64(len(data))
}
func (w HostFuncExportWrapper[TRequest, TResponse]) allocate(ctx context.Context, m api.Module, size uint64) (ptr uint64, err error) {
results, err := m.ExportedFunction("allocate").Call(ctx, size)
if err != nil {
return 0, err
}
return results[0], nil
}
type wasiPluginExecContext struct {
ctx modules.ExecutionContext
}
func (c *wasiPluginExecContext) lookPath(_ context.Context, lookupPathReq *wasiv1.LookupPathRequest) (*wasiv1.LookupPathResponse, error) {
if lookupPathReq.Command == "" {
c.ctx.Logger().Error("cannot lookup empty command")
return 0
return nil, errors.New("cannot lookup empty command")
}
foundPath, err := exec.LookPath(lookupPathReq.Command)
lookupPathResp := &rpcv1.LookupPathResponse{
lookupPathResp := &wasiv1.LookupPathResponse{
Path: foundPath,
}
@ -49,33 +92,17 @@ func (c *wasiPluginExecContext) lookPath(ctx context.Context, m api.Module, offs
lookupPathResp.Error = err.Error()
}
if ptrSize, err := c.memMgr.WriteMessage(ctx, m, lookupPathResp); err != nil {
c.ctx.Logger().Error("Failed to write message", slog.String("err", err.Error()))
return 0
} else {
return ptrSize
}
return lookupPathResp, nil
}
func (c *wasiPluginExecContext) exec(ctx context.Context, m api.Module, offset, byteCount uint32) uint64 {
buf, ok := m.Memory().Read(offset, byteCount)
if !ok {
return 0
}
execReq := new(rpcv1.ProcessStartRequest)
if err := proto.Unmarshal(buf, execReq); err != nil {
c.ctx.Logger().Error("failed to unmarshal ProcessStartRequest", slog.String("err", err.Error()))
return 0
}
execResp := new(rpcv1.ProcessStartResponse)
func (c *wasiPluginExecContext) exec(_ context.Context, execReq *wasiv1.ProcessStartRequest) (*wasiv1.ProcessStartResponse, error) {
execResp := new(wasiv1.ProcessStartResponse)
//nolint:contextcheck // that ain't a context.Context
cmd, err := sh.PrepareCommand(c.ctx, execReq.Command, execReq.Args...)
if err != nil {
c.ctx.Logger().Error("failed to prepare command", slog.String("err", err.Error()))
return 0
return nil, err
}
cmd.AddEnv(execReq.Environment)
@ -98,27 +125,10 @@ func (c *wasiPluginExecContext) exec(ctx context.Context, m api.Module, offset,
execResp.Error = err.Error()
}
if ptrSize, err := c.memMgr.WriteMessage(ctx, m, execResp); err != nil {
c.ctx.Logger().Error("Failed to write message", slog.String("err", err.Error()))
return 0
} else {
return ptrSize
}
return execResp, nil
}
func (c *wasiPluginExecContext) log(ctx context.Context, m api.Module, offset, byteCount uint32) {
buf, ok := m.Memory().Read(offset, byteCount)
if !ok {
return
}
logger := c.ctx.Logger()
taskLog := new(rpcv1.TaskLog)
if err := proto.Unmarshal(buf, taskLog); err != nil {
logger.Warn("failed to unmarshal task log", slog.String("err", err.Error()))
return
}
func (c *wasiPluginExecContext) log(ctx context.Context, taskLog *remotev1.TaskLog) (*remotev1.Result, error) {
rec := slog.NewRecord(time.UnixMicro(taskLog.Time), slog.Level(taskLog.Level), taskLog.Message, 0)
for i := range taskLog.Attributes {
@ -126,62 +136,32 @@ func (c *wasiPluginExecContext) log(ctx context.Context, m api.Module, offset, b
rec.AddAttrs(slog.String(attr.Key, attr.Value))
}
_ = logger.Handler().Handle(ctx, rec)
if err := c.ctx.Logger().Handler().Handle(ctx, rec); err != nil {
return &remotev1.Result{Error: err.Error()}, nil
}
return new(remotev1.Result), nil
}
func (c *wasiPluginExecContext) getState(ctx context.Context, m api.Module, offset, byteCount uint32) uint64 {
buf, ok := m.Memory().Read(offset, byteCount)
if !ok {
return 0
}
getStateReq := new(rpcv1.GetStateRequest)
if err := proto.Unmarshal(buf, getStateReq); err != nil {
c.ctx.Logger().Error("failed to unmarshal getStateRequest", slog.String("err", err.Error()))
return 0
}
resp := new(rpcv1.GetStateResponse)
func (c *wasiPluginExecContext) getState(ctx context.Context, getStateReq *remotev1.GetStateRequest) (*remotev1.GetStateResponse, error) {
resp := new(remotev1.GetStateResponse)
val, _, err := c.ctx.GetState(ctx, string(getStateReq.Key))
if err != nil {
c.ctx.Logger().Error("failed to get state", slog.String("err", err.Error()))
return 0
return nil, err
}
resp.Data = val
if ptrSize, err := c.memMgr.WriteMessage(ctx, m, resp); err != nil {
c.ctx.Logger().Error("Failed to write message", slog.String("err", err.Error()))
return 0
} else {
return ptrSize
}
return resp, nil
}
func (c *wasiPluginExecContext) setState(ctx context.Context, m api.Module, offset, byteCount uint32) (result uint64) {
buf, ok := m.Memory().Read(offset, byteCount)
if !ok {
return 0
}
setState := new(rpcv1.SetState)
if err := proto.Unmarshal(buf, setState); err != nil {
c.ctx.Logger().Error("failed to unmarshal SetState", slog.String("err", err.Error()))
return 0
}
var resp rpcv1.Result
func (c *wasiPluginExecContext) setState(ctx context.Context, setState *remotev1.SetState) (*remotev1.Result, error) {
var resp remotev1.Result
if err := c.ctx.SetState(ctx, string(setState.Key), setState.Data); err != nil {
c.ctx.Logger().Error("failed to set state", slog.String("err", err.Error()))
resp.Error = err.Error()
} else {
resp.Success = true
}
if ptrSize, err := c.memMgr.WriteMessage(ctx, m, &resp); err != nil {
c.ctx.Logger().Error("Failed to write message", slog.String("err", err.Error()))
return 0
} else {
return ptrSize
}
return &resp, nil
}

View file

@ -1,76 +0,0 @@
package plugin
import (
"context"
"errors"
"github.com/tetratelabs/wazero/api"
"google.golang.org/protobuf/proto"
)
const defaultIntegerSize = 32
func newMemoryManager(mod api.Module) (mgr *memoryManager) {
funcs := mod.ExportedFunctionDefinitions()
mgr = new(memoryManager)
if _, ok := funcs["allocate"]; ok {
mgr.allocate = mod.ExportedFunction("allocate")
}
if _, ok := funcs["deallocate"]; ok {
mgr.deallocate = mod.ExportedFunction("deallocate")
}
return
}
type memoryManager struct {
allocate api.Function
deallocate api.Function
}
func (m *memoryManager) Deallocate(ctx context.Context, ptr uint64) error {
_, err := m.deallocate.Call(ctx, ptr)
return err
}
func (m *memoryManager) WriteMessage(ctx context.Context, mod api.Module, msg proto.Message) (uint64, error) {
data, err := proto.Marshal(msg)
if err != nil {
return 0, err
}
ptr, err := m.Allocate(ctx, uint64(len(data)))
if err != nil {
return 0, err
}
if !mod.Memory().Write(uint32(ptr), data) {
return 0, errors.New("failed to write message to memory")
}
return (ptr << uint64(defaultIntegerSize)) | uint64(len(data)), nil
}
func (m *memoryManager) Allocate(ctx context.Context, size uint64) (ptr uint64, err error) {
results, err := m.allocate.Call(ctx, size)
if err != nil {
return 0, err
}
return results[0], nil
}
func (m *memoryManager) WithMem(ctx context.Context, size uint64, delegate func(ptr uint64) error) (err error) {
results, err := m.allocate.Call(ctx, size)
if err != nil {
return err
}
defer func() {
_, deallocateErr := m.deallocate.Call(ctx, results[0])
err = errors.Join(err, deallocateErr)
}()
return delegate(results[0])
}

View file

@ -6,6 +6,13 @@ import (
"fmt"
"time"
"connectrpc.com/connect"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
remotev1 "code.icb4dc0.de/buildr/api/generated/remote/v1"
"code.icb4dc0.de/buildr/api/generated/wasi/v1/rpcv1connect"
"code.icb4dc0.de/buildr/common/wasirpc"
"code.icb4dc0.de/buildr/buildr/internal/hcl"
"code.icb4dc0.de/buildr/buildr/modules"
@ -13,9 +20,6 @@ import (
hcl2 "github.com/hashicorp/hcl/v2"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"google.golang.org/protobuf/proto"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
)
var (
@ -23,12 +27,15 @@ var (
_ hcl.Marshaler = (*Module)(nil)
_ modules.Helper = (*Module)(nil)
_ modules.Initializer = (*Module)(nil)
_ modules.BinaryNamer = (*Module)(nil)
)
const runtimeClosingTimeout = 1 * time.Second
type Module struct {
PluginPayload PayloadReader
ModuleSpec map[string]any `hcl:",remain"`
modSpec *rpcv1.ModuleSpec
modSpec *commonv1.ModuleSpec
PluginType string
PluginCategory modules.Category
}
@ -37,7 +44,7 @@ func (m Module) Execute(ctx modules.ExecutionContext) (err error) {
runtime := m.prepareWASIRuntime(ctx)
defer func() {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), runtimeClosingTimeout)
defer cancel()
if closeErr := runtime.Close(ctx); closeErr != nil {
err = errors.Join(err, fmt.Errorf("failed to close runtime: %w", closeErr))
@ -49,11 +56,11 @@ func (m Module) Execute(ctx modules.ExecutionContext) (err error) {
}
_, err = runtime.NewHostModuleBuilder("buildr").
NewFunctionBuilder().WithFunc(wasiCtx.log).Export("log_msg").
NewFunctionBuilder().WithFunc(wasiCtx.getState).Export("get_state").
NewFunctionBuilder().WithFunc(wasiCtx.setState).Export("set_state").
NewFunctionBuilder().WithFunc(wasiCtx.exec).Export("exec").
NewFunctionBuilder().WithFunc(wasiCtx.lookPath).Export("lookPath").
NewFunctionBuilder().WithFunc(NewHostFuncExport(wasiCtx.log).Call).Export("log_msg").
NewFunctionBuilder().WithFunc(NewHostFuncExport(wasiCtx.getState).Call).Export("get_state").
NewFunctionBuilder().WithFunc(NewHostFuncExport(wasiCtx.setState).Call).Export("set_state").
NewFunctionBuilder().WithFunc(NewHostFuncExport(wasiCtx.exec).Call).Export("exec").
NewFunctionBuilder().WithFunc(NewHostFuncExport(wasiCtx.lookPath).Call).Export("lookPath").
Instantiate(ctx)
if err != nil {
@ -86,20 +93,24 @@ func (m Module) Execute(ctx modules.ExecutionContext) (err error) {
return fmt.Errorf("failed to instantiate WASI module: %w", err)
}
memMgr := newMemoryManager(mod)
wasiCtx.memMgr = memMgr
moduleClient, err := wasirpc.NewModuleClient(mod)
if err != nil {
return fmt.Errorf("failed to create module client: %w", err)
}
startTask := &rpcv1.StartTaskRequest{
Reference: &rpcv1.TaskReference{
wasiClient := rpcv1connect.NewWasiExecutorServiceClient(moduleClient, fmt.Sprintf("wasi://%s", m.PluginType))
startTask := &remotev1.StartTaskRequest{
Reference: &remotev1.TaskReference{
Id: uuid.NewString(),
Module: &rpcv1.ModuleReference{
Module: &commonv1.ModuleReference{
ModuleCategory: m.PluginCategory,
ModuleType: m.PluginType,
},
Name: ctx.Name(),
},
Buildr: &rpcv1.Buildr{
Repo: &rpcv1.Buildr_Repo{
Buildr: &remotev1.Buildr{
Repo: &remotev1.Buildr_Repo{
Root: ctx.WorkingDir(),
},
OutDir: ctx.OutDir(),
@ -108,26 +119,7 @@ func (m Module) Execute(ctx modules.ExecutionContext) (err error) {
Spec: m.modSpec,
}
data, err := proto.Marshal(startTask)
if err != nil {
return fmt.Errorf("failed to marshal task spec as protobuf: %w", err)
}
run := mod.ExportedFunction("run")
err = memMgr.WithMem(ctx, uint64(len(data)), func(ptr uint64) error {
if !mod.Memory().Write(uint32(ptr), data) {
return errors.New("failed to write to memory")
}
_, err = run.Call(ctx, ptr, uint64(len(data)))
if err != nil {
return fmt.Errorf("failed to run WASI module: %w", err)
}
return nil
})
_, err = wasiClient.StartTask(ctx, connect.NewRequest(startTask))
return err
}
@ -140,15 +132,15 @@ func (m Module) Type() string {
return m.PluginType
}
func (m *Module) SetModuleSpec(spec *rpcv1.ModuleSpec) {
func (m *Module) SetModuleSpec(spec *commonv1.ModuleSpec) {
m.modSpec = spec
}
func (m Module) Init(hclCtx *hcl2.EvalContext) (modules.Module, error) {
m.modSpec = &rpcv1.ModuleSpec{
m.modSpec = &commonv1.ModuleSpec{
Category: m.PluginCategory,
Type: m.PluginType,
Values: make(map[string]*rpcv1.ModuleSpec_Value),
Values: make(map[string]*commonv1.ModuleSpec_Value),
}
for k, v := range m.ModuleSpec {

View file

@ -0,0 +1,82 @@
package plugin
import (
"context"
"errors"
"fmt"
"connectrpc.com/connect"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/api/generated/wasi/v1/rpcv1connect"
"code.icb4dc0.de/buildr/common/wasirpc"
)
func (m Module) BinaryName(ctx context.Context) (binaryName string, err error) {
runtimeConfig := wazero.
NewRuntimeConfig().
WithCloseOnContextDone(true)
r := wazero.NewRuntimeWithConfig(ctx, runtimeConfig)
defer func() {
closeCtx, cancel := context.WithTimeout(context.Background(), runtimeClosingTimeout)
defer cancel()
err = errors.Join(err, r.Close(closeCtx))
}()
_, err = r.NewHostModuleBuilder("buildr").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("log_msg").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("get_state").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("set_state").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("exec").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("lookPath").
Instantiate(ctx)
if err != nil {
return "", fmt.Errorf("failed to instantiate host module builder: %w", err)
}
closer, err := wasi_snapshot_preview1.Instantiate(ctx, r)
if err != nil {
return "", fmt.Errorf("failed to instantiate wasi snapshot preview1: %w", err)
}
defer func() {
err = errors.Join(err, closer.Close(context.Background()))
}()
pluginPayload, err := m.PluginPayload.Bytes()
if err != nil {
return "", err
}
mod, err := r.Instantiate(ctx, pluginPayload)
if err != nil {
return "", fmt.Errorf("failed to instantiate WASI plugin: %w", err)
}
moduleClient, err := wasirpc.NewModuleClient(mod)
if err != nil {
return "", fmt.Errorf("failed to create module client: %w", err)
}
wasiClient := rpcv1connect.NewWasiExecutorServiceClient(moduleClient, fmt.Sprintf("wasi://%s", m.PluginType))
req := &wasiv1.BinaryNameRequest{
ModuleReference: &commonv1.ModuleReference{
ModuleCategory: m.PluginCategory,
ModuleType: m.PluginType,
},
Spec: m.modSpec,
}
resp, err := wasiClient.BinaryName(ctx, connect.NewRequest(req))
if err != nil {
return "", fmt.Errorf("failed to get plugin binary name: %w", err)
}
return resp.Msg.Name, nil
}

View file

@ -7,16 +7,18 @@ import (
"io"
"time"
"connectrpc.com/connect"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"google.golang.org/protobuf/proto"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
wasiv1 "code.icb4dc0.de/buildr/api/generated/wasi/v1"
"code.icb4dc0.de/buildr/api/generated/wasi/v1/rpcv1connect"
"code.icb4dc0.de/buildr/common/wasirpc"
"code.icb4dc0.de/buildr/buildr/modules"
)
//nolint:funlen // not much value in splitting hereG22
func (m Module) Help(ctx context.Context) (help modules.Help, err error) {
runtime := m.prepareWASIRuntime(ctx)
@ -27,7 +29,7 @@ func (m Module) Help(ctx context.Context) (help modules.Help, err error) {
}()
_, err = runtime.NewHostModuleBuilder("buildr").
NewFunctionBuilder().WithFunc(dummyWithoutResult).Export("log_msg").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("log_msg").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("get_state").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("set_state").
NewFunctionBuilder().WithFunc(dummyWithResult).Export("exec").
@ -63,68 +65,35 @@ func (m Module) Help(ctx context.Context) (help modules.Help, err error) {
return modules.Help{}, err
}
memMgr := newMemoryManager(mod)
moduleClient, err := wasirpc.NewModuleClient(mod)
if err != nil {
return modules.Help{}, fmt.Errorf("failed to create module client: %w", err)
}
helpRequest := &rpcv1.HelpRequest{
ModuleReference: &rpcv1.ModuleReference{
wasiClient := rpcv1connect.NewWasiExecutorServiceClient(moduleClient, fmt.Sprintf("wasi://%s", m.PluginType))
helpRequest := &wasiv1.HelpRequest{
ModuleReference: &commonv1.ModuleReference{
ModuleCategory: m.PluginCategory,
ModuleType: m.PluginType,
},
}
data, err := proto.Marshal(helpRequest)
if err != nil {
return modules.Help{}, err
}
helpFunc := mod.ExportedFunction("help")
var helpResult rpcv1.HelpResponse
err = memMgr.WithMem(ctx, uint64(len(data)), func(ptr uint64) error {
if !mod.Memory().Write(uint32(ptr), data) {
return errors.New("failed to write to memory")
}
result, err := helpFunc.Call(ctx, ptr, uint64(len(data)))
if err != nil {
return fmt.Errorf("failed to run WASI module: %w", err)
}
resultPtr, resultSize := uint32(result[0]>>defaultIntegerSize), uint32(result[0])
if ptr == 0 {
return errors.New("failed to get inventory - 0 pointer")
}
defer func() {
err = errors.Join(err, memMgr.Deallocate(ctx, ptr))
}()
data, ok := mod.Memory().Read(resultPtr, resultSize)
if !ok {
return errors.New("failed to get inventory")
}
if err = proto.Unmarshal(data, &helpResult); err != nil {
return fmt.Errorf("failed to unmarshal inventory: %w", err)
}
return nil
})
resp, err := wasiClient.Help(ctx, connect.NewRequest(helpRequest))
if err != nil {
return modules.Help{}, err
}
moduleHelp := modules.Help{
Name: helpResult.Name,
Description: helpResult.Description,
Examples: m.mapToExamples(helpResult.Examples),
Name: resp.Msg.Name,
Description: resp.Msg.Description,
Examples: m.mapToExamples(resp.Msg.Examples),
}
return moduleHelp, nil
}
func (m Module) mapToExamples(raw []*rpcv1.TaskExample) []modules.Example {
func (m Module) mapToExamples(raw []*wasiv1.TaskExample) []modules.Example {
examples := make([]modules.Example, 0, len(raw))
for _, example := range raw {

View file

@ -7,7 +7,7 @@ import (
"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/zclconf/go-cty/cty"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
rpcv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
"code.icb4dc0.de/buildr/buildr/internal/hcl"
)

View file

@ -3,31 +3,31 @@ package plugin
import (
"github.com/zclconf/go-cty/cty"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
)
func unwrap(val cty.Value) *rpcv1.ModuleSpec_Value {
func unwrap(val cty.Value) *commonv1.ModuleSpec_Value {
switch {
case val.Type().Equals(cty.String):
return &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeSingle,
SingleValue: &rpcv1.ModuleSpec_Value_StringValue{
return &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeSingle,
SingleValue: &commonv1.ModuleSpec_Value_StringValue{
StringValue: val.AsString(),
},
}
case val.Type().Equals(cty.Bool):
return &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeSingle,
SingleValue: &rpcv1.ModuleSpec_Value_BoolValue{
return &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeSingle,
SingleValue: &commonv1.ModuleSpec_Value_BoolValue{
BoolValue: val.True(),
},
}
case val.Type().Equals(cty.Number):
f, _ := val.AsBigFloat().Float64()
return &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeSingle,
SingleValue: &rpcv1.ModuleSpec_Value_DoubleValue{
return &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeSingle,
SingleValue: &commonv1.ModuleSpec_Value_DoubleValue{
DoubleValue: f,
},
}
@ -35,8 +35,8 @@ func unwrap(val cty.Value) *rpcv1.ModuleSpec_Value {
//nolint:gocritic // eventually, there will be more cases
switch {
case val.Type().TupleElementTypes()[0].Equals(cty.String):
specVal := &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeStringSlice,
specVal := &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeStringSlice,
}
for _, v := range val.AsValueSlice() {
specVal.StringValues = append(specVal.StringValues, v.AsString())
@ -45,17 +45,17 @@ func unwrap(val cty.Value) *rpcv1.ModuleSpec_Value {
}
case val.Type().IsMapType():
valueMap := val.AsValueMap()
specVal := &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeMap,
ComplexValue: make(map[string]*rpcv1.ModuleSpec_Value, len(valueMap)),
specVal := &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeMap,
ComplexValue: make(map[string]*commonv1.ModuleSpec_Value, len(valueMap)),
}
//nolint:gocritic // eventually, there will be more cases
switch {
case val.Type().MapElementType().Equals(cty.String):
for k, v := range valueMap {
specVal.ComplexValue[k] = &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeSingle,
SingleValue: &rpcv1.ModuleSpec_Value_StringValue{
specVal.ComplexValue[k] = &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeSingle,
SingleValue: &commonv1.ModuleSpec_Value_StringValue{
StringValue: v.AsString(),
},
}
@ -64,9 +64,9 @@ func unwrap(val cty.Value) *rpcv1.ModuleSpec_Value {
return specVal
case val.Type().IsObjectType():
valueMap := val.AsValueMap()
specVal := &rpcv1.ModuleSpec_Value{
Type: rpcv1.ModuleSpec_ValueTypeObject,
ComplexValue: make(map[string]*rpcv1.ModuleSpec_Value, len(valueMap)),
specVal := &commonv1.ModuleSpec_Value{
Type: commonv1.ModuleSpec_ValueTypeObject,
ComplexValue: make(map[string]*commonv1.ModuleSpec_Value, len(valueMap)),
}
for k, v := range valueMap {

View file

@ -3,7 +3,7 @@ package state
import (
"net/url"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
"code.icb4dc0.de/buildr/buildr/modules/state/ent"
@ -22,7 +22,7 @@ type PluginModule struct {
ID *uuid.UUID
Type string
DefaultSpec []byte
Category rpcv1.Category
Category commonv1.Category
PluginID uuid.UUID
}

View file

@ -3,7 +3,7 @@ package state
import (
"context"
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
"code.icb4dc0.de/buildr/buildr/modules/state/ent"
"code.icb4dc0.de/buildr/buildr/modules/state/ent/plugin"
@ -44,7 +44,7 @@ func (e EntPluginsRepo) ModulesForPlugin(ctx context.Context, id uuid.UUID) ([]P
ID: &module.ID,
PluginID: id,
Type: module.Type,
Category: rpcv1.Category(module.Category),
Category: commonv1.Category(module.Category),
DefaultSpec: module.DefaultSpec,
})
}

View file

@ -1,8 +0,0 @@
package tool
import (
"code.icb4dc0.de/buildr/buildr/modules"
)
var Registration = modules.RegistrationFunc(func(registry *modules.TypeRegistry) {
})

View file

@ -1,16 +1,16 @@
package modules
import (
rpcv1 "code.icb4dc0.de/buildr/api/generated/rpc/v1"
commonv1 "code.icb4dc0.de/buildr/api/generated/common/v1"
)
type Category = rpcv1.Category
type Category = commonv1.Category
const (
CategoryTool = rpcv1.Category_CategoryTool
CategoryTask = rpcv1.Category_CategoryTask
CategoryBuild = rpcv1.Category_CategoryBuild
CategoryPackage = rpcv1.Category_CategoryPackage
CategoryTool = commonv1.Category_CategoryTool
CategoryTask = commonv1.Category_CategoryTask
CategoryBuild = commonv1.Category_CategoryBuild
CategoryPackage = commonv1.Category_CategoryPackage
)
func Categories() []Category {