Skip to content

Commit cc138e8

Browse files
drewmalinmistercodedorpatelspratik
authored
feat(hardware): use NVML to grab the hardware profile during the regi… (#314)
* feat(hardware): use NVML to grab the hardware profile during the register command * cgo cross compile, bugfix in fetch devplane proto, uncomment todos * also use cgo_enabled=1 iin goreleaser * lint * fix: address hardware profile PR comments * update goreleaser * makefile updates * remove unused local build * update cross version * release closer to cross * review feedback * merge conflicts --------- Co-authored-by: mistercodedor <mistercodedor@jagcrete.com> Co-authored-by: Pratik Patel <pratpatel@nvidia.com>
1 parent 08b1024 commit cc138e8

19 files changed

Lines changed: 1146 additions & 492 deletions

.github/workflows/legacy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,4 @@ jobs:
6565
go-version: '1.24.0'
6666
cache: true
6767
- name: Release test
68-
run: make build
68+
run: make build-cross

.github/workflows/release.yml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ on:
55
tags:
66
- "v*"
77

8+
env:
9+
# Go module path for Docker mount (must match go.mod module).
10+
BREV_MODULE: github.com/brevdev/brev-cli
11+
# goreleaser-cross image with cross-compilers for CGO (see https://goreleaser.com/limitations/cgo/#using-docker).
12+
GOLANG_CROSS_VERSION: v1.24.5
13+
814
jobs:
915
goreleaser:
1016
runs-on: ubuntu-22.04
@@ -17,8 +23,9 @@ jobs:
1723
with:
1824
go-version: '1.24.0'
1925
cache: true
20-
- name: Release
21-
run: make ci smoke-test release
26+
27+
- name: CI, smoke-test, and release
28+
run: make ci smoke-test release-cross
2229
env:
2330
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
2431
# disable until this until figure out tags

.goreleaser.yml

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,49 @@
1+
version: 2
12
before:
23
hooks:
34
- go mod download
5+
# Separate builds per target so CC/CXX are correct in goreleaser-cross (avoids aarch64-gcc being used for linux/amd64).
46
builds:
5-
- env:
6-
- CGO_ENABLED=0
7-
goos:
8-
- darwin
9-
- linux
10-
# - windows
11-
goarch:
12-
- amd64
13-
- arm64
7+
- id: darwin-amd64
8+
env:
9+
- CGO_ENABLED=1
10+
goos: [darwin]
11+
goarch: [amd64]
12+
binary: brev
13+
ldflags:
14+
- -X github.com/brevdev/brev-cli/pkg/cmd/version.Version={{.Tag}}
15+
- id: darwin-arm64
16+
env:
17+
- CGO_ENABLED=1
18+
goos: [darwin]
19+
goarch: [arm64]
20+
binary: brev
21+
ldflags:
22+
- -X github.com/brevdev/brev-cli/pkg/cmd/version.Version={{.Tag}}
23+
- id: linux-amd64
24+
env:
25+
- CGO_ENABLED=1
26+
- CC=x86_64-linux-gnu-gcc
27+
- CXX=x86_64-linux-gnu-g++
28+
goos: [linux]
29+
goarch: [amd64]
30+
binary: brev
31+
ldflags:
32+
- -X github.com/brevdev/brev-cli/pkg/cmd/version.Version={{.Tag}}
33+
- id: linux-arm64
34+
env:
35+
- CGO_ENABLED=1
36+
- CC=aarch64-linux-gnu-gcc
37+
- CXX=aarch64-linux-gnu-g++
38+
goos: [linux]
39+
goarch: [arm64]
1440
binary: brev
1541
ldflags:
1642
- -X github.com/brevdev/brev-cli/pkg/cmd/version.Version={{.Tag}}
1743

1844
brews:
1945
- name: brev
20-
folder: Formula
46+
directory: Formula
2147
# GitHub/GitLab repository to push the formula to
2248
repository:
2349
owner: brevdev
@@ -37,9 +63,11 @@ brews:
3763
archives:
3864
- format_overrides:
3965
- goos: windows
40-
format: zip
66+
formats: [zip]
4167
release:
4268
github:
69+
owner: brevdev
70+
name: brev-cli
4371
prerelease: auto
4472
# dockers:
4573
# - image_templates:

Makefile

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
11
.DEFAULT_GOAL := fast-build
22
VERSION := dev-$(shell git rev-parse HEAD | cut -c 1-8)
33

4+
# Cross-compilation via Docker (golang:1.24 native Linux container).
5+
# When arch=<GOOS>/<GOARCH> is provided, spin up a container that matches
6+
# the target platform so CGO uses the native Linux gcc/GNU ld toolchain
7+
_GOMODCACHE := $(shell go env GOMODCACHE)
8+
ifdef arch
9+
_CROSS_GOOS := $(word 1,$(subst /, ,$(arch)))
10+
_CROSS_GOARCH := $(word 2,$(subst /, ,$(arch)))
11+
_BUILD_PREFIX := docker run --rm \
12+
--platform $(_CROSS_GOOS)/$(_CROSS_GOARCH) \
13+
-v $(CURDIR):/app \
14+
-v $(_GOMODCACHE):/go/pkg/mod \
15+
-e CGO_ENABLED=1 \
16+
-e GOPRIVATE=github.com/brevdev/* \
17+
-e GONOSUMDB=github.com/brevdev/* \
18+
-w /app \
19+
golang:1.24
20+
else
21+
_BUILD_PREFIX := CGO_ENABLED=1
22+
endif
23+
424
.PHONY: fast-build
525
fast-build: ## go build -o brev
626
$(call print-target)
727
echo ${VERSION}
8-
CGO_ENABLED=0 go build -o brev -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
28+
CGO_ENABLED=1 go build -o brev -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
929

1030
.PHONY: local
1131
local: ## build with env wrapper (use: make local env=dev0|dev1|dev2|stg arch=linux/amd64, or make local for defaults)
1232
$(call print-target)
1333
ifdef env
1434
@echo "Building with env=$(env) wrapper..."
1535
@echo ${VERSION}
16-
$(if $(arch),GOOS=$(word 1,$(subst /, ,$(arch))) GOARCH=$(word 2,$(subst /, ,$(arch))),) CGO_ENABLED=0 go build -o brev-local -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
36+
$(_BUILD_PREFIX) go build -o brev-local -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
1737
@echo '#!/bin/sh' > brev
1838
@echo '# Auto-generated wrapper with environment overrides' >> brev
1939
@echo 'export BREV_CONSOLE_URL="https://localhost.nvidia.com:3000"' >> brev
@@ -26,7 +46,7 @@ ifdef env
2646
@chmod +x brev
2747
else
2848
@echo "Building without environment overrides (using config.go defaults)..."
29-
$(if $(arch),GOOS=$(word 1,$(subst /, ,$(arch))) GOARCH=$(word 2,$(subst /, ,$(arch))),) CGO_ENABLED=0 go build -o brev -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
49+
$(_BUILD_PREFIX) go build -o brev -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
3050
endif
3151

3252
.PHONY: install-dev
@@ -104,18 +124,42 @@ diff: ## git diff
104124
git diff --exit-code
105125
RES=$$(git status --porcelain) ; if [ -n "$$RES" ]; then echo $$RES && exit 1 ; fi
106126

107-
.PHONY: build
108-
build: ## goreleaser --snapshot --skip-publish --rm-dist
109-
build: install-tools
110-
$(call print-target)
111-
goreleaser --snapshot --skip-publish --rm-dist
112-
113127
.PHONY: release
114128
release: ## goreleaser --rm-dist
115129
release: install-tools
116130
$(call print-target)
117131
goreleaser --rm-dist
118132

133+
# Docker-based build/release using goreleaser-cross.
134+
# See: https://goreleaser.com/limitations/cgo (goreleaser needs explicit instructions for CGO builds)
135+
# See: https://github.com/goreleaser/goreleaser-cross (docker image with cross-compilers for CGO builds)
136+
# See: https://github.com/goreleaser/example-cross (example of using goreleaser-cross)
137+
GOLANG_CROSS_VERSION ?= v1.24.5
138+
BREV_MODULE ?= github.com/brevdev/brev-cli
139+
140+
# Dry-run build using goreleaser-cross
141+
.PHONY: build-cross
142+
build-cross:
143+
$(call print-target)
144+
docker run --rm \
145+
-e CGO_ENABLED=1 \
146+
-v "$$(pwd):/go/src/$(BREV_MODULE)" \
147+
-w "/go/src/$(BREV_MODULE)" \
148+
ghcr.io/goreleaser/goreleaser-cross:$(GOLANG_CROSS_VERSION) \
149+
--clean --skip=validate --skip=publish
150+
151+
# Release using goreleaser-cross. Requires GITHUB_TOKEN to be set.
152+
.PHONY: release-cross
153+
release-cross:
154+
$(call print-target)
155+
docker run --rm \
156+
-e CGO_ENABLED=1 \
157+
-e "GITHUB_TOKEN=$$GITHUB_TOKEN" \
158+
-v "$$(pwd):/go/src/$(BREV_MODULE)" \
159+
-w "/go/src/$(BREV_MODULE)" \
160+
ghcr.io/goreleaser/goreleaser-cross:$(GOLANG_CROSS_VERSION) \
161+
release --clean
162+
119163
.PHONY: run
120164
run: ## go run
121165
@go run -race .
@@ -169,7 +213,7 @@ full-smoke-test: ci fast-build
169213
build-linux-amd:
170214
$(call print-target)
171215
echo ${VERSION}
172-
GOOS=linux GOARCH=amd64 go build -o brev -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
216+
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o brev -ldflags "-X github.com/brevdev/brev-cli/pkg/cmd/version.Version=${VERSION}"
173217

174218
.PHONY: build-darwin-amd
175219
build-darwin-amd:
@@ -305,8 +349,8 @@ develop-with-nix:
305349
update-devplane-deps: ## update devplane dependencies (use: make update-devplane-deps commit=<hash-or-tag>, defaults to latest)
306350
@COMMIT=$${commit:-latest}; \
307351
echo "Updating devplane dependencies to: $$COMMIT"; \
308-
go get -u github.com/brevdev/dev-plane@$$COMMIT; \
352+
GOPRIVATE=github.com/brevdev/* go get -u github.com/brevdev/dev-plane@$$COMMIT; \
309353
go get buf.build/gen/go/brevdev/devplane/grpc/go@$$COMMIT; \
310354
go get buf.build/gen/go/brevdev/devplane/protocolbuffers/go@$$COMMIT; \
311-
go mod tidy; \
355+
GOPRIVATE=github.com/brevdev/* go mod tidy; \
312356
echo "Successfully updated to $$COMMIT"

go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ go 1.24.0
44

55
require (
66
buf.build/gen/go/brevdev/devplane/connectrpc/go v1.19.1-20260228021043-887d38e1b474.2
7-
buf.build/gen/go/brevdev/devplane/protocolbuffers/go v1.36.11-20260305005117-3cacb6388cd4.1
7+
buf.build/gen/go/brevdev/devplane/protocolbuffers/go v1.36.11-20260305201249-af5106090c8a.1
88
connectrpc.com/connect v1.19.1
9+
github.com/NVIDIA/go-nvml v0.13.0-1
910
github.com/alessio/shellescape v1.4.1
1011
github.com/brevdev/parse v0.0.11
1112
github.com/briandowns/spinner v1.16.0
@@ -150,7 +151,7 @@ require (
150151
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
151152
golang.org/x/net v0.48.0 // indirect
152153
golang.org/x/oauth2 v0.34.0 // indirect
153-
golang.org/x/sys v0.40.0 // indirect
154+
golang.org/x/sys v0.40.0
154155
golang.org/x/term v0.39.0 // indirect
155156
golang.org/x/time v0.12.0 // indirect
156157
google.golang.org/protobuf v1.36.11

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
buf.build/gen/go/brevdev/devplane/connectrpc/go v1.19.1-20260228021043-887d38e1b474.2 h1:Sq0kIa/xKzScbJcqB5EbPVhOL0QYHPr3araQaupL2lk=
22
buf.build/gen/go/brevdev/devplane/connectrpc/go v1.19.1-20260228021043-887d38e1b474.2/go.mod h1:Yh34p9aADmWsKv2umYlMpnCZuBmNBE9N+HImgRriJXM=
3-
buf.build/gen/go/brevdev/devplane/protocolbuffers/go v1.36.11-20260305005117-3cacb6388cd4.1 h1:3Y3FI5kbM4uacawy5dySjVTPSbu2BJMO42eQHf2wz+g=
4-
buf.build/gen/go/brevdev/devplane/protocolbuffers/go v1.36.11-20260305005117-3cacb6388cd4.1/go.mod h1:V/y7Wxg0QvU4XPVwqErF5NHLobUT1QEyfgrGuQIxdPo=
3+
buf.build/gen/go/brevdev/devplane/protocolbuffers/go v1.36.11-20260305201249-af5106090c8a.1 h1:d+kY4OSI/WV2eBuO5G7ezCQ8RiLtDOIrUbtmZOKi5Kw=
4+
buf.build/gen/go/brevdev/devplane/protocolbuffers/go v1.36.11-20260305201249-af5106090c8a.1/go.mod h1:V/y7Wxg0QvU4XPVwqErF5NHLobUT1QEyfgrGuQIxdPo=
55
buf.build/gen/go/brevdev/protoc-gen-gotag/protocolbuffers/go v1.36.11-20220906235457-8b4922735da5.1 h1:6amhprQmCKJ4wgJ6ngkh32d9V+dQcOLUZ/SfHdOnYgo=
66
buf.build/gen/go/brevdev/protoc-gen-gotag/protocolbuffers/go v1.36.11-20220906235457-8b4922735da5.1/go.mod h1:O+pnSHMru/naTMrm4tmpBoH3wz6PHa+R75HR7Mv8X2g=
77
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
@@ -53,6 +53,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
5353
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
5454
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
5555
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
56+
github.com/NVIDIA/go-nvml v0.13.0-1 h1:OLX8Jq3dONuPOQPC7rndB6+iDmDakw0XTYgzMxObkEw=
57+
github.com/NVIDIA/go-nvml v0.13.0-1/go.mod h1:+KNA7c7gIBH7SKSJ1ntlwkfN80zdx8ovl4hrK3LmPt4=
5658
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
5759
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
5860
github.com/alessio/shellescape v1.4.1 h1:V7yhSDDn8LP4lc4jS8pFkt0zCnzVJlG5JXy9BVKJUX0=

pkg/cmd/register/device_registration_store.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ const (
2323
// DeviceRegistration is the persistent identity file for a registered device.
2424
// Fields align with the AddNodeResponse from dev-plane.
2525
type DeviceRegistration struct {
26-
ExternalNodeID string `json:"external_node_id"`
27-
DisplayName string `json:"display_name"`
28-
OrgID string `json:"org_id"`
29-
DeviceID string `json:"device_id"`
30-
RegisteredAt string `json:"registered_at"`
31-
NodeSpec NodeSpec `json:"node_spec"`
26+
ExternalNodeID string `json:"external_node_id"`
27+
DisplayName string `json:"display_name"`
28+
OrgID string `json:"org_id"`
29+
DeviceID string `json:"device_id"`
30+
RegisteredAt string `json:"registered_at"`
31+
HardwareProfile HardwareProfile `json:"hardware_profile"`
3232
}
3333

3434
// RegistrationStore defines the contract for persisting device registration data.

pkg/cmd/register/device_registration_store_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func Test_SaveAndLoadRegistration_RoundTrip(t *testing.T) {
3131
OrgID: "org_xyz",
3232
DeviceID: "device-uuid-123",
3333
RegisteredAt: "2026-02-25T00:00:00Z",
34-
NodeSpec: NodeSpec{
34+
HardwareProfile: HardwareProfile{
3535
CPUCount: &cpuCount,
3636
RAMBytes: &ramBytes,
3737
Architecture: "arm64",
@@ -59,11 +59,11 @@ func Test_SaveAndLoadRegistration_RoundTrip(t *testing.T) {
5959
if loaded.DeviceID != reg.DeviceID {
6060
t.Errorf("DeviceID mismatch: got %s, want %s", loaded.DeviceID, reg.DeviceID)
6161
}
62-
if loaded.NodeSpec.Architecture != "arm64" {
63-
t.Errorf("Architecture mismatch: got %s", loaded.NodeSpec.Architecture)
62+
if loaded.HardwareProfile.Architecture != "arm64" {
63+
t.Errorf("Architecture mismatch: got %s", loaded.HardwareProfile.Architecture)
6464
}
65-
if loaded.NodeSpec.CPUCount == nil || *loaded.NodeSpec.CPUCount != 12 {
66-
t.Errorf("CPUCount mismatch: got %v", loaded.NodeSpec.CPUCount)
65+
if loaded.HardwareProfile.CPUCount == nil || *loaded.HardwareProfile.CPUCount != 12 {
66+
t.Errorf("CPUCount mismatch: got %v", loaded.HardwareProfile.CPUCount)
6767
}
6868
}
6969

0 commit comments

Comments
 (0)