Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/docs_check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,12 @@ jobs:
run: gem install mdl -v 0.13.0

- name: Run Markdown lint
# Excluded paths:
# docs/vendor — vendored third-party content.
# docs/superpowers — internal AI-assisted planning artifacts
# (specs and implementation plans). These are
# work-in-progress authoring docs, not
# user-facing documentation, and are not held
# to mdl style rules.
run: |
find docs/ -path docs/vendor -prune -false -o -name '*.md' | xargs mdl -s docs/mdl-style.rb
find docs/ \( -path docs/vendor -o -path docs/superpowers \) -prune -false -o -name '*.md' -print | xargs mdl -s docs/mdl-style.rb
32 changes: 32 additions & 0 deletions .github/workflows/homebrew-validate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
# Licensed under the Apache License, Version 2.0.

name: homebrew-validate

on:
pull_request:
paths:
- 'Formula/**'
push:
branches: [main]
paths:
- 'Formula/**'

permissions:
contents: read

jobs:
audit:
name: Audit & Style
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Audit formula
run: |
brew audit --strict --online Formula/holodeck.rb

- name: Style check
run: |
brew style Formula/holodeck.rb
49 changes: 49 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
# Licensed under the Apache License, Version 2.0.

name: release

on:
push:
tags:
- 'v*'

permissions:
contents: write # publish GitHub Release + tag artifacts

jobs:
goreleaser:
name: GoReleaser
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0 # GoReleaser needs full history for the changelog

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache: true

- name: Verify HOMEBREW_TAP_GITHUB_TOKEN secret is configured
env:
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
run: |
if [ -z "$HOMEBREW_TAP_GITHUB_TOKEN" ]; then
echo "::error::HOMEBREW_TAP_GITHUB_TOKEN repo secret is not set."
echo "::error::The release would publish but the Homebrew formula PR would not open."
echo "::error::See docs/release.md (One-time setup) for PAT creation steps."
exit 1
fi

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: '~> v2'
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
kubeconfig
bin
dist/
.DS_Store
e2e_logs
coverage.out*
Expand Down
118 changes: 118 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Copyright (c) 2026, NVIDIA CORPORATION. All rights reserved.
# Licensed under the Apache License, Version 2.0.
#
# GoReleaser config for cross-building holodeck binaries, publishing
# them as GitHub Release assets, and auto-updating the Homebrew formula
# at Formula/holodeck.rb on every v* tag.
#
# See docs/release.md for the release process.

version: 2

project_name: holodeck

before:
hooks:
- go mod tidy

builds:
- id: holodeck
main: ./cmd/cli
binary: holodeck
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64
ldflags:
- -s -w
- -X main.ProgramVersion={{ .Version }}

- id: holodeck-action
main: ./cmd/action
binary: holodeck-action
env:
- CGO_ENABLED=0
goos:
- linux
goarch:
- amd64
- arm64
ldflags:
- -s -w

archives:
- id: holodeck
ids:
- holodeck
name_template: "holodeck_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
formats:
- tar.gz
files:
- LICENSE
- README.md

- id: holodeck-action
ids:
- holodeck-action
name_template: "holodeck-action_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
formats:
- tar.gz
files:
- LICENSE

checksum:
name_template: checksums.txt
algorithm: sha256

source:
enabled: true

changelog:
use: github
sort: asc
filters:
exclude:
- '^docs:'
- '^chore:'
- '^test:'

release:
github:
owner: NVIDIA
name: holodeck
draft: false
prerelease: auto

brews:
- name: holodeck
ids:
- holodeck
repository:
owner: NVIDIA
name: holodeck
branch: main
pull_request:
enabled: true
draft: false
base:
branch: main
token: "{{ .Env.HOMEBREW_TAP_GITHUB_TOKEN }}"
directory: Formula
homepage: "https://github.com/NVIDIA/holodeck"
description: "Tool for creating and managing GPU-ready cloud test environments"
license: "Apache-2.0"
commit_author:
name: nvidia-ci
email: nvidia-ci@users.noreply.github.com
commit_msg_template: |
chore(brew): bump {{ .ProjectName }} to {{ .Tag }}

Signed-off-by: nvidia-ci <nvidia-ci@users.noreply.github.com>
install: |
bin.install "holodeck"
test: |
system "#{bin}/holodeck", "--version"
23 changes: 7 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
.PHONY: build fmt verify release lint vendor mod-tidy mod-vendor mod-verify check-vendor mdlint
.PHONY: build fmt verify snapshot lint vendor mod-tidy mod-vendor mod-verify check-vendor mdlint

CONTAINER_RUN_CMD ?= docker run
GO_CMD ?= go
Expand Down Expand Up @@ -96,21 +96,12 @@ mdlint:
ruby:slim \
/workdir/scripts/mdlint.sh

release:
@rm -rf bin
@mkdir -p bin
@for os in linux darwin; do \
for arch in amd64 arm64; do \
echo "Building $$os-$$arch"; \
GOOS=$$os GOARCH=$$arch $(GO_CMD) build -o bin/$(BINARY_NAME)-action-$$os-$$arch cmd/action/main.go; \
done; \
done
@for os in linux darwin; do \
for arch in amd64 arm64; do \
echo "Building $$os-$$arch"; \
GOOS=$$os GOARCH=$$arch $(GO_CMD) build -o bin/$(BINARY_NAME)-$$os-$$arch cmd/cli/main.go; \
done; \
done
# snapshot runs GoReleaser in dry-run mode: cross-builds binaries,
# produces archives + a draft Formula/holodeck.rb under ./dist, but
# does NOT publish to GitHub or push the formula. Use this before
# tagging a release to validate the build matrix and formula shape.
snapshot:
goreleaser release --snapshot --clean --skip=publish

.PHONY: generate
generate: controller-gen
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@ A tool for creating and managing GPU-ready Cloud test environments.

See [docs/quick-start.md](docs/quick-start.md) for a full walkthrough.

### Install via Homebrew (macOS, Linux)

```bash
brew tap nvidia/holodeck https://github.com/NVIDIA/holodeck
brew install nvidia/holodeck/holodeck
holodeck --help
```

Pre-built binaries for macOS (arm64, amd64) and Linux (arm64, amd64) are
downloaded from the [GitHub Releases page](https://github.com/NVIDIA/holodeck/releases/latest).
Run `brew upgrade nvidia/holodeck/holodeck` to update.

### Install from source

```bash
make build
sudo mv ./bin/holodeck /usr/local/bin/holodeck
Expand Down
6 changes: 4 additions & 2 deletions cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ import (
const (
// ProgramName is the canonical name of this program
ProgramName = "holodeck"
// ProgramVersion is the current version of the program
ProgramVersion = "0.3.2"
)

// ProgramVersion is the program version. It is set at build time via
// -ldflags "-X main.ProgramVersion=..." (see .goreleaser.yaml).
var ProgramVersion = "dev"

type config struct {
Debug bool
Verbose bool
Expand Down
8 changes: 6 additions & 2 deletions cmd/cli/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ func TestNewApp(t *testing.T) {
log := logger.NewLogger()
app := NewApp(log)

if app.Version != "0.3.2" {
t.Errorf("expected app version %q, got %q", "0.3.2", app.Version)
// ProgramVersion is injected at build time via -ldflags (see .goreleaser.yaml).
// `go test` builds without that flag, so app.Version falls back to the
// package default "dev". Assert non-emptiness rather than a literal so
// the test doesn't need bumping on every release tag.
if app.Version == "" {
t.Errorf("expected app version to be non-empty, got %q", app.Version)
}
if app.Name != "holodeck" {
t.Errorf("expected app name %q, got %q", "holodeck", app.Name)
Expand Down
Loading