diff --git a/.bingo/.gitignore b/.bingo/.gitignore deleted file mode 100644 index 4428593c..00000000 --- a/.bingo/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ - -# Ignore everything -* - -# But not these files: -!.gitignore -!*.mod -!*.sum -!README.md -!Variables.mk -!variables.env - -*tmp.mod -*tmp.sum diff --git a/.bingo/README.md b/.bingo/README.md deleted file mode 100644 index 74705b9f..00000000 --- a/.bingo/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Project Development Dependencies. - -This is directory which stores Go modules with pinned buildable package that is used within this repository, managed by . - -* Run `bingo get` to install all tools having each own module file in this directory. -* Run `bingo get ` to install `` that have own module file in this directory. -* For Makefile: Make sure to put `include .bingo/Variables.mk` in your Makefile, then use `\$()` variable where `` is the .bingo/`.mod`. -* For shell: Run `source .bingo/variables.env` to source all environment variable for each tool. -* See or -h on how to add, remove or change binaries dependencies. - -## Requirements - -* Go 1.25.x diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk deleted file mode 100644 index fc89112c..00000000 --- a/.bingo/Variables.mk +++ /dev/null @@ -1,37 +0,0 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.10. DO NOT EDIT. -# All tools are designed to be build inside $GOBIN. -BINGO_DIR := $(dir $(lastword $(MAKEFILE_LIST))) -GOPATH ?= $(shell go env GOPATH) -GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin -GO ?= $(shell which go) - -# Ensure bingo-managed tools are always built for the host platform, -# even when GOOS/GOARCH are set for cross-compilation of other targets. -GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) -GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) -GOHOSTARM ?= $(shell $(GO) env GOHOSTARM) - -# Below generated variables ensure that every time a tool under each variable is invoked, the correct version -# will be used; reinstalling only if needed. -# For example for golangci-lint variable: -# -# In your main Makefile (for non array binaries): -# -#include .bingo/Variables.mk # Assuming -dir was set to .bingo . -# -#command: $(GOLANGCI_LINT) -# @echo "Running golangci-lint" -# @$(GOLANGCI_LINT) -# -GOLANGCI_LINT := $(GOBIN)/golangci-lint-v2.7.0 -$(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod - @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. - @echo "(re)installing $(GOBIN)/golangci-lint-v2.7.0" - @cd $(BINGO_DIR) && GOWORK=off GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) GOARM=$(GOHOSTARM) $(GO) build -mod=mod -modfile=golangci-lint.mod -o=$(GOBIN)/golangci-lint-v2.7.0 "github.com/golangci/golangci-lint/v2/cmd/golangci-lint" - -OAPI_CODEGEN := $(GOBIN)/oapi-codegen-v2.5.1 -$(OAPI_CODEGEN): $(BINGO_DIR)/oapi-codegen.mod - @# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies. - @echo "(re)installing $(GOBIN)/oapi-codegen-v2.5.1" - @cd $(BINGO_DIR) && GOWORK=off GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) GOARM=$(GOHOSTARM) $(GO) build -mod=mod -modfile=oapi-codegen.mod -o=$(GOBIN)/oapi-codegen-v2.5.1 "github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen" - diff --git a/.bingo/go.mod b/.bingo/go.mod deleted file mode 100644 index 610249af..00000000 --- a/.bingo/go.mod +++ /dev/null @@ -1 +0,0 @@ -module _ // Fake go.mod auto-created by 'bingo' for go -moddir compatibility with non-Go projects. Commit this file, together with other .mod files. \ No newline at end of file diff --git a/.bingo/golangci-lint.mod b/.bingo/golangci-lint.mod deleted file mode 100644 index 48627661..00000000 --- a/.bingo/golangci-lint.mod +++ /dev/null @@ -1,5 +0,0 @@ -module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT - -go 1.25.3 - -require github.com/golangci/golangci-lint/v2 v2.7.0 // cmd/golangci-lint diff --git a/.bingo/oapi-codegen.mod b/.bingo/oapi-codegen.mod deleted file mode 100644 index 8d0b140e..00000000 --- a/.bingo/oapi-codegen.mod +++ /dev/null @@ -1,5 +0,0 @@ -module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT - -go 1.25 - -require github.com/oapi-codegen/oapi-codegen/v2 v2.5.1 // cmd/oapi-codegen diff --git a/.bingo/oapi-codegen.sum b/.bingo/oapi-codegen.sum deleted file mode 100644 index e4d15a85..00000000 --- a/.bingo/oapi-codegen.sum +++ /dev/null @@ -1,147 +0,0 @@ -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 h1:PRxIJD8XjimM5aTknUK9w6DHLDox2r2M3DI4i2pnd3w= -github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936/go.mod h1:ttYvX5qlB+mlV1okblJqcSMtR4c52UKxDiX9GRBS8+Q= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= -github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/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/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/oapi-codegen/oapi-codegen/v2 v2.5.1 h1:5vHNY1uuPBRBWqB2Dp0G7YB03phxLQZupZTIZaeorjc= -github.com/oapi-codegen/oapi-codegen/v2 v2.5.1/go.mod h1:ro0npU1BWkcGpCgGD9QwPp44l5OIZ94tB3eabnT7DjQ= -github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= -github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= -github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= -github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= -github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/speakeasy-api/jsonpath v0.6.0 h1:IhtFOV9EbXplhyRqsVhHoBmmYjblIRh5D1/g8DHMXJ8= -github.com/speakeasy-api/jsonpath v0.6.0/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw= -github.com/speakeasy-api/openapi-overlay v0.10.2 h1:VOdQ03eGKeiHnpb1boZCGm7x8Haj6gST0P3SGTX95GU= -github.com/speakeasy-api/openapi-overlay v0.10.2/go.mod h1:n0iOU7AqKpNFfEt6tq7qYITC4f0yzVVdFw0S7hukemg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk= -github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ= -github.com/woodsbury/decimal128 v1.3.0 h1:8pffMNWIlC0O5vbyHWFZAt5yWvWcrHA+3ovIIjVWss0= -github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4ZKOB5I6Zjb+ds= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= -golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -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.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= -golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.25.1 h1:YeIyhd0M7gStYR9jb2IFXVVT+QJhgXu1ZECOuRwofh4= -golang.org/x/tools v0.25.1/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg= -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/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -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= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= diff --git a/.bingo/variables.env b/.bingo/variables.env deleted file mode 100644 index c224b2dd..00000000 --- a/.bingo/variables.env +++ /dev/null @@ -1,14 +0,0 @@ -# Auto generated binary variables helper managed by https://github.com/bwplotka/bingo v0.10. DO NOT EDIT. -# All tools are designed to be build inside $GOBIN. -# Those variables will work only until 'bingo get' was invoked, or if tools were installed via Makefile's Variables.mk. -GOBIN=${GOBIN:=$(go env GOBIN)} - -if [ -z "$GOBIN" ]; then - GOBIN="$(go env GOPATH)/bin" -fi - - -GOLANGCI_LINT="${GOBIN}/golangci-lint-v2.7.0" - -OAPI_CODEGEN="${GOBIN}/oapi-codegen-v2.5.1" - diff --git a/.dockerignore b/.dockerignore index 2b579b9b..93aa2ed6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -33,9 +33,6 @@ dist/ output/ out/ -# Generated code (will be regenerated in container) -pkg/api/openapi/openapi.gen.go -openapi/openapi.yaml # Test results *.xml diff --git a/.gitignore b/.gitignore index 949e4ab4..6a8f70d7 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ vendor/ *.bak *.log .deploy-work/ +.test-work/ # Environment files .env @@ -47,11 +48,9 @@ vendor/ .env.*.local deploy-scripts/.env +# Perf test results +perf/results/ + # Claude Code files .claude/ -# Generated code -pkg/api/openapi/ - -# Downloaded from hyperfleet-api during make generate -openapi/openapi.yaml diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..cd8bc090 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,173 @@ +# HyperFleet E2E — Agent Instructions + +Black-box E2E testing framework for HyperFleet cluster lifecycle management. Tests hit the HyperFleet API, create ephemeral clusters, verify adapter execution and K8s resource creation, then clean up. Built with Go 1.26, Ginkgo v2, Gomega, and a hand-written generic HTTP client. + +Test suites: `e2e/cluster/`, `e2e/nodepool/`, `e2e/adapter/`. + +## Verification + +Run `make check` before declaring work done. It runs everything in order: + +| Target | What it does | +|---|---| +| `make check` | `generate` → `fmt-check` → `vet` → `lint` → `test` (all-in-one) | +| `make build` | `generate` → compile binary to `bin/hyperfleet-e2e` | +| `make fmt` | Format code and imports (`golangci-lint fmt`) | +| `make test` | Unit tests only (`./pkg/...`) | +| `make lint` | `golangci-lint` (pinned in `tools/go.mod`, config: `.golangci.yml`) | +| `make generate` | No-op (reserved for future code generation) | + +Pre-flight order: `make check` then `make build`. + +## Source of Truth + +| Topic | Location | +|---|---| +| Getting started | `docs/getting-started.md` | +| Architecture | `docs/architecture.md` | +| Test placement strategy | [architecture repo](https://github.com/openshift-hyperfleet/architecture/blob/main/hyperfleet/docs/e2e-testing/test-placement-strategy.md) — which layer a test belongs in (unit / integration / E2E) | +| Test writing guide | `docs/development.md` | +| Debugging | `docs/debugging.md` (prow job mapping, CI troubleshooting, log locations) | +| Local kind setup | `docs/local-kind-setup.md` | +| Runbook | `docs/runbook.md` (prow job schedules, label-to-CI mapping, test execution) | +| Contributing | `CONTRIBUTING.md` | +| Test case templates | `test-design/templates/` | +| Test case documents | `test-design/testcases/` | +| User journey maps | `test-design/user-journeys/` | +| Config defaults | `pkg/config/defaults.go` | +| Config struct & validation | `pkg/config/config.go` | +| Pollers | `pkg/helper/pollers.go` | +| Custom matchers | `pkg/helper/matchers.go` | +| Helper core (New, TestDataPath, CleanupTestCluster) | `pkg/helper/helper.go` + `pkg/helper/suite.go` | +| Synchronous validators (HasResourceCondition, AdapterNameToConditionType) | `pkg/helper/validation.go` | +| Payload template vars | `pkg/client/payload.go` (`templateVars` struct) | +| Labels | `pkg/labels/labels.go` | +| Condition type constants | `pkg/client/constants.go` | +| Config file | `configs/config.yaml` | +| Identity config & transport | `pkg/config/config.go` (`IdentityConfig`), `pkg/helper/suite.go` (WithBearerToken wiring) | + +## Test Conventions + +### File naming and structure + +- **IMPORTANT:** Test files use `.go` extension, NOT `_test.go`. E2E tests are compiled into the binary, not run via `go test`. The single exception is `e2e/e2e_suite_test.go` — the ginkgo CLI entry point for parallel execution (`make e2e-ginkgo`); never add spec code there. +- Location: `e2e/{suite}/descriptive-name.go` (package matches directory name) +- Test name format: `[Suite: component][category] Description` (e.g., `[Suite: cluster][baseline] Cluster Resource Type Lifecycle`). Known categories: `baseline`, `update`, `delete`, `concurrent`, `negative`, `perf`. +- Test suites auto-register via blank import in `e2e/e2e.go` + +### Labels + +Every test MUST have exactly one severity label from `pkg/labels`: + +- `labels.Tier0` — critical path, blocks release +- `labels.Tier1` — important features +- `labels.Tier2` — edge cases, can defer + +Optional: `labels.Negative`, `labels.Performance`, `labels.Upgrade`, `labels.Disruptive`, `labels.Slow` + +### Async operations — pollers + custom matchers + +**IMPORTANT:** Use pollers with custom matchers. Do NOT create `WaitFor*` wrapper functions that hide `Eventually` inside helpers. + +```go +// Wait for resource condition +Eventually(h.PollCluster(ctx, clusterID), h.Cfg.Timeouts.Cluster.Reconciled, h.Cfg.Polling.Interval). + Should(helper.HaveResourceCondition(client.ConditionTypeReconciled, client.ResourceConditionStatusTrue)) + +// Wait for all adapters at generation +Eventually(h.PollClusterAdapterStatuses(ctx, clusterID), h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval). + Should(helper.HaveAllAdaptersAtGeneration(h.Cfg.Adapters.Cluster, expectedGen)) + +// Wait for hard-delete (404) +Eventually(h.PollClusterHTTPStatus(ctx, clusterID), timeout, h.Cfg.Polling.Interval). + Should(Equal(http.StatusNotFound)) + +// Wait for namespace cleanup +Eventually(h.PollNamespacesByPrefix(ctx, clusterID), timeout, h.Cfg.Polling.Interval). + Should(BeEmpty()) +``` + +Available pollers: `PollCluster`, `PollNodePool`, `PollClusterAdapterStatuses`, `PollNodePoolAdapterStatuses`, `PollClusterHTTPStatus`, `PollNodePoolHTTPStatus`, `PollNamespacesByPrefix`. + +Available matchers: `HaveResourceCondition`, `HaveAllAdaptersWithCondition`, `HaveAllAdaptersAtGeneration`, `HaveAuditIdentity`. + +For one-off complex assertions, use `Eventually(func(g Gomega) { ... }).Should(Succeed())` with `g.Expect()` (not bare `Expect()`). + +### Cleanup + +Every test MUST clean up resources with `ginkgo.DeferCleanup` inline right after resource creation. + +### Payload templates + +Resolve payload paths via `h.TestDataPath()` — never hardcode `testdata/` as a prefix (breaks when `TESTDATA_DIR` is overridden, e.g., in CI): + +```go +h.Client.CreateClusterFromPayload(ctx, h.TestDataPath("payloads/clusters/cluster-request.json")) +``` + +Payloads in `testdata/payloads/` support Go templates. Available variables (defined in `pkg/client/payload.go`): + +- `.Random` — 8-char random hex +- `.UUID` — full UUID v4 +- `.Timestamp` — Unix seconds +- `.TimestampMs` — Unix milliseconds + +### Step markers + +Use `ginkgo.By()` for major steps. **IMPORTANT:** Never use `ginkgo.By()` inside `Eventually` closures. + +### Timeouts and intervals + +Always use config values: `h.Cfg.Timeouts.Cluster.Reconciled`, `h.Cfg.Timeouts.NodePool.Reconciled`, `h.Cfg.Timeouts.Adapter.Processing`, `h.Cfg.Polling.Interval`. Never hardcode durations. + +### JWT authentication (caller identity) + +When `server.jwt.enabled=true`, the API authenticates requests via JWT. The E2E framework acquires a token from K8s using the TokenRequest API — no static tokens or secrets to manage. + +```yaml +# configs/config.yaml +identity: + expectedIdentity: "system:serviceaccount:hyperfleet:hyperfleet-e2e-sa" + tokenRequest: + serviceAccountName: "hyperfleet-e2e-sa" + namespace: "hyperfleet" +``` + +Or via env vars: +```bash +HYPERFLEET_IDENTITY_TOKENREQUEST_SERVICEACCOUNTNAME=hyperfleet-e2e-sa \ +HYPERFLEET_IDENTITY_TOKENREQUEST_NAMESPACE=hyperfleet \ +HYPERFLEET_IDENTITY_EXPECTEDIDENTITY=system:serviceaccount:hyperfleet:hyperfleet-e2e-sa \ +./bin/hyperfleet-e2e test +``` + +The acquired token is injected as `Authorization: Bearer` on every API request via `client.WithBearerToken`. + +The `expectedIdentity` field is the audit identity the API resolves from the JWT claim. It's used by test assertions to verify `created_by` / `deleted_by` fields: + +```go +if expected := h.ExpectedIdentity(); expected != "" { + Expect(cluster).To(helper.HaveAuditIdentity(expected)) +} +``` + +When `expectedIdentity` is empty, audit assertions are skipped. +## Boundaries + +### DON'T + +- Use `_test.go` suffix for E2E test files (sole exception: `e2e/e2e_suite_test.go`, the ginkgo CLI entry point) +- Hardcode timeout durations — use `h.Cfg.Timeouts.*` +- Skip cleanup (`DeferCleanup`) +- Use `ginkgo.By()` inside `Eventually` closures +- Import `e2e/*` packages from `pkg/` code + +## Gotchas + +- `Validate()` in `pkg/config/config.go` returns `error`, does not panic — only checks that `API.URL` is non-empty +- `helper.New()` calls `log.Fatalf` if config is nil — tests must call `SetSuiteConfig` before running +- Config priority: CLI flags > env vars (`HYPERFLEET_*` prefix) > `configs/config.yaml` > built-in defaults (see `pkg/config/defaults.go`) +- Config file path priority: `--config` flag > `HYPERFLEET_CONFIG` env > `./configs/config.yaml` auto-detect +- Adapter names come from `h.Cfg.Adapters.Cluster` and `h.Cfg.Adapters.NodePool` at runtime — never hardcode adapter names. Values in `configs/config.yaml` (e.g., `cl-namespace`) override compiled defaults in `pkg/config/defaults.go` (e.g., `clusters-namespace`) +- `e2e-ci` Makefile target sets `TESTDATA_DIR` to absolute path and writes JUnit XML to `output/` +- JWT auth is required when the API has `server.jwt.enabled=true` (production default). Set `identity.tokenRequest.serviceAccountName` and `.namespace` — the framework acquires a token via the K8s TokenRequest API at startup. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..e98ea521 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,60 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- CONTRIBUTING.md with development setup and contribution guidelines +- CHANGELOG.md following Keep a Changelog format +- CLAUDE.md with AI agent instructions and validation checklist + +### Changed +- Documentation structure to align with HyperFleet architecture standards + +## [0.2.0] - 2024-XX-XX + +### Added +- NodePool lifecycle tests +- Support for multiple test suites (cluster, nodepool) +- Label-based test filtering (tier0, tier1, tier2, slow, negative) +- JUnit report generation for CI integration +- Container image builds with multi-platform support + +### Changed +- Improved test isolation with ephemeral resources +- Enhanced logging with structured output +- Updated OpenAPI client generation workflow + +### Fixed +- Cleanup reliability for test resources +- Timeout handling in adapter status checks + +## [0.1.0] - 2024-XX-XX + +### Added +- Initial release of HyperFleet E2E testing framework +- Ginkgo-based test execution engine +- Cluster lifecycle tests +- OpenAPI-generated HyperFleet API client +- Configuration system with CLI flags, env vars, and config files +- Helper utilities for common test operations +- Payload template system with dynamic variable substitution +- Makefile with development, testing, and image build targets +- Comprehensive documentation (README, getting-started, architecture, development) +- CI/CD integration support + +### Features +- Black-box testing approach +- Ephemeral test cluster creation +- Parallel test execution support +- Flexible test filtering by labels and patterns +- Structured logging (JSON and text formats) +- Automatic resource cleanup + +[Unreleased]: https://github.com/openshift-hyperfleet/hyperfleet-e2e/compare/v0.2.0...HEAD +[0.2.0]: https://github.com/openshift-hyperfleet/hyperfleet-e2e/compare/v0.1.0...v0.2.0 +[0.1.0]: https://github.com/openshift-hyperfleet/hyperfleet-e2e/releases/tag/v0.1.0 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..43c994c2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..7c64a4b4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,310 @@ +# Contributing to HyperFleet E2E + +Thank you for contributing to HyperFleet E2E! This document provides guidelines for developing and contributing to the project. + +## Development Setup + +### Prerequisites + +- **Go 1.26+** - [Install Go](https://go.dev/doc/install) +- **Make** - Build automation tool +- **Container tool** - Docker or Podman for building images +- **Git** - Version control + +### Initial Setup + +1. Fork and clone the repository: + ```bash + git clone https://github.com/YOUR_USERNAME/hyperfleet-e2e.git + cd hyperfleet-e2e + ``` + +2. Add upstream remote: + ```bash + git remote add upstream https://github.com/openshift-hyperfleet/hyperfleet-e2e.git + ``` + +3. Run checks: + ```bash + make check + ``` + +4. Build the binary: + ```bash + make build + ``` + +## Repository Structure + +```text +hyperfleet-e2e/ +├── cmd/ - CLI entry point +│ └── hyperfleet-e2e/ +├── pkg/ - Core packages +│ ├── client/ - HyperFleet API client (generic HTTP) +│ ├── config/ - Configuration loading and validation +│ ├── e2e/ - Test execution engine (Ginkgo) +│ ├── helper/ - Test helper utilities +│ ├── labels/ - Test label definitions +│ └── util/ - Pointer and utility helpers +├── e2e/ - Test suites +│ ├── adapter/ - Adapter lifecycle tests +│ ├── channel/ - Channel management tests +│ ├── cluster/ - Cluster lifecycle tests +│ ├── nodepool/ - NodePool management tests +│ └── version/ - Version management tests +├── testdata/ - Test payloads and fixtures +│ ├── adapter-configs/ - Adapter configuration files +│ └── payloads/ +│ ├── clusters/ - Cluster creation payloads +│ └── nodepools/ - NodePool creation payloads +├── test-design/ - Test design documentation +│ ├── templates/ - Test case templates +│ ├── testcases/ - Test case documents +│ └── user-journeys/ - User journey maps +├── configs/ - Configuration files +│ └── config.yaml - Default configuration +├── docs/ - Documentation +├── env/ - Environment configuration files +├── hack/ - Build and development scripts +├── images/ - Container image definitions +└── scripts/ - Utility scripts +``` + +## Testing + +### Unit Tests + +Run unit tests for all packages: + +```bash +make test +``` + +Generate coverage report: + +```bash +make test-coverage +``` + +View coverage in browser: + +```bash +open coverage.html +``` + +### E2E Tests + +Run all E2E tests (requires HyperFleet API): + +```bash +export HYPERFLEET_API_URL=https://api.hyperfleet.example.com +make e2e +``` + +Run specific test suites: + +```bash +./bin/hyperfleet-e2e test --label-filter=tier0 +./bin/hyperfleet-e2e test --focus "\[Suite: cluster\]" +``` + +### Writing Tests + +See [Development Guide](docs/development.md) for detailed instructions on writing E2E tests. + +Key points: +- Test files use `.go` extension (NOT `_test.go`) +- All tests must have labels (Tier0, Tier1, or Tier2) +- Use `ginkgo.By()` to mark major test steps +- Clean up resources with `DeferCleanup` +- Use helper functions from `pkg/helper` + +## Common Tasks + +### Build and Test Workflow + + +Standard development workflow: + +```bash +# 1. Make changes to code +# 2. Format code +make fmt + +# 3. Run all checks +make check + +# 4. Build binary +make build + +# 5. Run E2E tests locally (optional) +./bin/hyperfleet-e2e test --label-filter=tier0 +``` + +### Build Container Image + +Build for local testing: + +```bash +make image +``` + +Build and push to personal Quay registry: + +```bash +QUAY_USER=myusername make image-dev +``` + +### Add a New Test + +1. Create test file in appropriate suite directory: + ```bash + touch e2e/cluster/my-new-test.go + ``` + +2. Follow the test template structure (see existing tests) + +3. Add appropriate labels + +4. Test your changes: + ```bash + make build + ./bin/hyperfleet-e2e test --focus "My New Test" + ``` + +## Code Quality + +### Formatting + +Format all Go code: + +```bash +make fmt +``` + +Check if code is formatted: + +```bash +make fmt-check +``` + +### Linting + +Run golangci-lint: + +```bash +make lint +``` + +Run all verification checks: + +```bash +make verify +``` + +### Pre-commit Checklist + +Before committing, ensure: + +- [ ] Code is formatted (`make fmt`) +- [ ] All checks pass (`make check`) +- [ ] New tests added for new functionality +- [ ] Documentation updated if needed + +## Commit Standards + +We follow [Conventional Commits](https://www.conventionalcommits.org/) standards: + +``` +(): + + + +