Skip to content

Commit 196d981

Browse files
authored
feat: add /version endpoint and global Minder-Version header (#6358)
feat: add /version endpoint and global X-Minder-Version header Signed-off-by: DharunMR <maddharun56@gmail.com>
1 parent f0d4cba commit 196d981

13 files changed

Lines changed: 1699 additions & 1386 deletions

File tree

.github/workflows/image-build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ jobs:
2222
--image-label=org.opencontainers.image.source=https://github.com/mindersec/minder,org.opencontainers.image.title="Minder",org.opencontainers.image.licenses=Apache-2.0,org.opencontainers.image.vendor=OpenSSF
2323
env:
2424
KO_DOCKER_REPO: "ko.local"
25+
GOFLAGS: "-ldflags=-X=github.com/mindersec/minder/internal/constants.CLIVersion=${{ github.ref_name }}"
2526
check-helm:
2627
name: Build Helm chart
2728
# TODO: remove the 'image' build once helm build is stable, because ko resolve will build the image
@@ -47,3 +48,4 @@ jobs:
4748
env:
4849
KO_DOCKER_REPO: "ko.local"
4950
KO_PUSH_IMAGE: "false"
51+
GOFLAGS: "-ldflags=-X=github.com/mindersec/minder/internal/constants.CLIVersion=${{ github.ref_name }}"

.mk/build.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ build-minder-cli: ## build minder cli
2222
.PHONY: build-minder-server
2323
build-minder-server: ## build minder-server
2424
@echo "Building $(projectname)-server..."
25-
@CGO_ENABLED=0 go build -trimpath -tags '$(BUILDTAGS)' -o ./bin/$(projectname)-server ./cmd/server
25+
@CGO_ENABLED=0 go build -trimpath -tags '$(BUILDTAGS)' -ldflags "-X github.com/mindersec/minder/internal/constants.CLIVersion=$(shell git describe --abbrev=0 --tags)+ref.$(shell git rev-parse --short HEAD)" -o ./bin/$(projectname)-server ./cmd/server
2626

2727
.PHONY: build-reminder-server
2828
build-reminder-server: ## build reminder server

.mk/develop.mk

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ del(.services.migrate.build) | \
1212

1313
.PHONY: run-cli
1414
run-cli: ## run the CLI, needs additional arguments
15-
@go run -ldflags "-X main.version=$(shell git describe --abbrev=0 --tags)" -tags '$(BUILDTAGS)' ./cmd/cli
15+
@go run -ldflags "-X github.com/mindersec/minder/internal/constants.CLIVersion=$(shell git describe --abbrev=0 --tags)+ref.$(shell git rev-parse --short HEAD)" -tags '$(BUILDTAGS)' ./cmd/cli
1616

1717
.PHONY: run-server
1818
run-server: ## run the app
19-
@go run -ldflags "-X main.version=$(shell git describe --abbrev=0 --tags)" -tags '$(BUILDTAGS)' ./cmd/server serve
19+
@go run -ldflags "-X github.com/mindersec/minder/internal/constants.CLIVersion=$(shell git describe --abbrev=0 --tags)+ref.$(shell git rev-parse --short HEAD)" -tags '$(BUILDTAGS)' ./cmd/server serve
2020

2121
.PHONY: run-docker-teardown
2222
run-docker-teardown: ## teardown the docker compose environment
@@ -35,7 +35,7 @@ run-docker: run-docker-teardown ## run the app under docker compose
3535
@# podman (at least) doesn't seem to like multi-arch images, and sometimes picks the wrong one (e.g. amd64 on arm64)
3636
@# We also need to remove the build: directives to use ko builds
3737
@# ko resolve will fill in the image: field in the compose file, but it adds a yaml document separator
38-
@yq e $(YQ_BUILD_REPLACE_STRING) docker-compose.yaml | KO_DOCKER_REPO=$(KO_DOCKER_REPO) ko resolve --base-import-paths --platform linux/$(DOCKERARCH) -f - | sed 's/^--*$$//' > .resolved-compose.yaml
38+
@yq e $(YQ_BUILD_REPLACE_STRING) docker-compose.yaml | KO_DOCKER_REPO=$(KO_DOCKER_REPO) GOFLAGS="-ldflags=-X=github.com/mindersec/minder/internal/constants.CLIVersion=$(shell git describe --abbrev=0 --tags)+ref.$(shell git rev-parse --short HEAD)" ko resolve --base-import-paths --platform linux/$(DOCKERARCH) -f - | sed 's/^--*$$//' > .resolved-compose.yaml
3939
@$(COMPOSE) -f .resolved-compose.yaml up $(COMPOSE_ARGS) $(services)
4040
@rm .resolved-compose.yaml*
4141

docs/docs/ref/proto.mdx

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/constants/useragent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ package constants
55

66
var (
77
// ServerUserAgent is the user agent string for the server
8-
ServerUserAgent = "Minder/" + Revision
8+
ServerUserAgent = "Minder/" + CLIVersion
99
)

internal/controlplane/handlers.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"google.golang.org/grpc/codes"
1212
"google.golang.org/grpc/status"
1313

14+
"github.com/mindersec/minder/internal/constants"
1415
pb "github.com/mindersec/minder/pkg/api/protobuf/go/minder/v1"
1516
)
1617

@@ -25,3 +26,11 @@ func (s *Server) CheckHealth(ctx context.Context, _ *pb.CheckHealthRequest) (*pb
2526
}
2627
return &pb.CheckHealthResponse{Status: "OK"}, nil
2728
}
29+
30+
// GetVersion returns the build and version info of the Minder server
31+
func (*Server) GetVersion(_ context.Context, _ *pb.GetVersionRequest) (*pb.GetVersionResponse, error) {
32+
return &pb.GetVersionResponse{
33+
Version: constants.CLIVersion,
34+
Commit: constants.Revision,
35+
}, nil
36+
}

internal/controlplane/server.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"google.golang.org/grpc"
3636
"google.golang.org/grpc/codes"
3737
"google.golang.org/grpc/credentials/insecure"
38+
"google.golang.org/grpc/metadata"
3839
"google.golang.org/grpc/reflection"
3940
"google.golang.org/grpc/status"
4041

@@ -43,6 +44,7 @@ import (
4344
"github.com/mindersec/minder/internal/auth"
4445
"github.com/mindersec/minder/internal/auth/jwt"
4546
"github.com/mindersec/minder/internal/authz"
47+
"github.com/mindersec/minder/internal/constants"
4648
"github.com/mindersec/minder/internal/controlplane/metrics"
4749
"github.com/mindersec/minder/internal/crypto"
4850
datasourcessvc "github.com/mindersec/minder/internal/datasources/service"
@@ -218,8 +220,7 @@ func initMetrics(r sdkmetric.Reader) *sdkmetric.MeterProvider {
218220
res := resource.NewWithAttributes(
219221
semconv.SchemaURL,
220222
semconv.ServiceName("minder"),
221-
// TODO: Make this auto-generated
222-
semconv.ServiceVersion("v0.1.0"),
223+
semconv.ServiceVersion(constants.CLIVersion),
223224
)
224225
// By default/spec (?!), otel includes net.sock.peer.{addr,port}.
225226
// See https://github.com/open-telemetry/opentelemetry-go-contrib/issues/3071
@@ -268,6 +269,7 @@ func (s *Server) StartGRPCServer(ctx context.Context) error {
268269
s.TokenValidationInterceptor,
269270
EntityContextProjectInterceptor,
270271
ProjectAuthorizationInterceptor,
272+
VersionHeaderInterceptor(),
271273
recovery.UnaryServerInterceptor(recovery.WithRecoveryHandlerContext(recoveryHandler)),
272274
}
273275

@@ -545,3 +547,12 @@ func withMaxSizeMiddleware(h http.Handler) http.Handler {
545547
h.ServeHTTP(w, r)
546548
})
547549
}
550+
551+
// VersionHeaderInterceptor injects the Minder version into the HTTP response headers
552+
func VersionHeaderInterceptor() grpc.UnaryServerInterceptor {
553+
return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
554+
// SetHeader tells gRPC-Gateway to add this to the HTTP response
555+
_ = grpc.SetHeader(ctx, metadata.Pairs("minder-version", constants.ServerUserAgent))
556+
return handler(ctx, req)
557+
}
558+
}

internal/controlplane/server_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/mindersec/minder/internal/auth"
2929
mockjwt "github.com/mindersec/minder/internal/auth/jwt/mock"
3030
mockauthz "github.com/mindersec/minder/internal/authz/mock"
31+
"github.com/mindersec/minder/internal/constants"
3132
"github.com/mindersec/minder/internal/controlplane/metrics"
3233
"github.com/mindersec/minder/internal/crypto"
3334
mock_service "github.com/mindersec/minder/internal/entities/properties/service/mock"
@@ -220,3 +221,30 @@ func httpDoWithRetry(client *http.Client, createRequest func() (*http.Request, e
220221

221222
return resp, err
222223
}
224+
225+
func TestGetVersion(t *testing.T) {
226+
t.Parallel()
227+
228+
server := &Server{}
229+
230+
resp, err := server.GetVersion(context.Background(), &pb.GetVersionRequest{})
231+
232+
require.NoError(t, err)
233+
require.NotNil(t, resp)
234+
require.Equal(t, constants.CLIVersion, resp.Version)
235+
require.Equal(t, constants.Revision, resp.Commit)
236+
}
237+
238+
func TestVersionHeaderInterceptor(t *testing.T) {
239+
t.Parallel()
240+
241+
interceptor := VersionHeaderInterceptor()
242+
243+
handler := func(_ context.Context, _ interface{}) (interface{}, error) {
244+
return "success", nil
245+
}
246+
247+
_, err := interceptor(context.Background(), nil, &grpc.UnaryServerInfo{}, handler)
248+
249+
require.NoError(t, err)
250+
}

pkg/api/openapi/minder/v1/minder.swagger.json

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)