Skip to content
Draft
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
18 changes: 17 additions & 1 deletion .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ if [[ -n "${__STACKPANEL_CLEAN_ENV+x}" ]]; then
exit 0
fi

# ----------------------------------------------------------------------------
# Nix
# ----------------------------------------------------------------------------
if ! has nix; then
echo "nix is required, install it: https://install.determinate.systems" >&2
exit 1
fi

# ----------------------------------------------------------------------------
# Binary cache
# ----------------------------------------------------------------------------
Expand All @@ -35,11 +43,19 @@ fi
# source_url "$NIX_DIRENV_URL" "$NIX_DIRENV_SHA"
# fi

__stack=stack
if ! has stack; then
echo "installing stackpanel..." >&2
# nix profile add github:darkmatter/stackpanel
# In stackcpanel itself we run off the local project
__stack='nix run . --'
fi


# ----------------------------------------------------------------------------
# Stackpanel preflight + pure mode
# ----------------------------------------------------------------------------
eval "$(stack envrc)"
eval "$($__stack envrc)"
# Export STACKPANEL_ROOT for preflight command
export STACKPANEL_ROOT="$GIT_ROOT"

Expand Down
3 changes: 2 additions & 1 deletion .stack/config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@
prelude = {
tagline = "Stackpanel devshell";
subtitle = "your environment is ready";
settings.motd.title.text = ./title.txt;
};

# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -932,7 +933,7 @@
ca-url = "https://ca.internal:443";
cert-name = "device";
enable = true;
prompt-on-shell = true;
prompt-on-shell = false;
provisioner = "Authentik";
};

Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion apps/docs/content/docs/reference/modules.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ Flake URL (e.g., "github:author/my-module")

## `modules.<name>.healthcheckModule`

Name of the doctor module that provides health checks for this module. This links to stackpanel.doctor.<name>.
Name of the doctor module that provides health checks for this module. This links to `stackpanel.doctor.<name>`.

| Property | Value |
|----------|-------|
Expand Down
2 changes: 1 addition & 1 deletion apps/stackpanel-go/cmd/cli/envrc.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ _nix_argsum_suffix() {

nix_direnv_watch_file() {
# shellcheck disable=2016
log_error '` + `"` + `nix_direnv_watch_file` + "`" + `is deprecated - use ` + "`" + `watch_file` + "`" + `''
log_error '` + "`" + `nix_direnv_watch_file` + "`" + ` is deprecated - use ` + "`" + `watch_file` + "`" + `'
watch_file "$@"
}

Expand Down
7 changes: 5 additions & 2 deletions apps/stackpanel-go/cmd/cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,12 @@ import (
)

var (
// Version and BuildDate are set at build time via -ldflags.
// The "dev" default lets you identify local/untagged builds.
// Version, GitCommit, and BuildDate are set at build time via -ldflags.
// The "dev"/"unknown" defaults let you identify local/untagged builds.
// When ldflags are omitted (go run, air), applyEmbeddedBuildInfo fills
// GitCommit and BuildDate from Go's embedded VCS data.
Version = "dev"
GitCommit = "unknown"
BuildDate = "unknown"
)

Expand Down
71 changes: 67 additions & 4 deletions apps/stackpanel-go/cmd/cli/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package cmd

import (
"fmt"
"io"
"runtime/debug"
"strings"

"github.com/spf13/cobra"
)
Expand All @@ -12,13 +15,73 @@ var versionCmd = &cobra.Command{
Short: "Show version information",
Long: `Display the version and build information for Stackpanel.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Stackpanel %s\n", Version)
if BuildDate != "unknown" {
fmt.Printf("Built: %s\n", BuildDate)
}
fmt.Fprint(cmd.OutOrStdout(), formatVersion(rootCmd.Name(), Version, GitCommit, BuildDate))
},
}

func init() {
applyEmbeddedBuildInfo()
rootCmd.SetVersionTemplate(versionCobraTemplate(GitCommit, BuildDate))
rootCmd.AddCommand(versionCmd)
}

func isSetBuildMeta(s string) bool {
return s != "" && s != "unknown"
}

// formatVersion is the human-readable version block used by `stack version`
// and (via versionCobraTemplate) by `stack --version`.
func formatVersion(name, version, commit, date string) string {
var b strings.Builder
fmt.Fprintf(&b, "%s version %s\n", name, version)
writeBuildMeta(&b, commit, date)
return b.String()
}

func versionCobraTemplate(commit, date string) string {
var b strings.Builder
// Keep cobra v1.9's default first line, then append build metadata.
b.WriteString(`{{with .DisplayName}}{{printf "%s " .}}{{end}}{{printf "version %s" .Version}}`)
b.WriteByte('\n')
writeBuildMeta(&b, commit, date)
return b.String()
}

func writeBuildMeta(w io.StringWriter, commit, date string) {
if isSetBuildMeta(commit) {
_, _ = w.WriteString(fmt.Sprintf("commit: %s\n", commit))
}
if isSetBuildMeta(date) {
_, _ = w.WriteString(fmt.Sprintf("built: %s\n", date))
}
}

// applyEmbeddedBuildInfo fills GitCommit and BuildDate from Go's embedded
// VCS settings when they were not injected via -ldflags (local go build).
func applyEmbeddedBuildInfo() {
info, ok := debug.ReadBuildInfo()
if !ok {
return
}
vcsRevision := ""
modified := false
for _, s := range info.Settings {
switch s.Key {
case "vcs.revision":
vcsRevision = s.Value
case "vcs.time":
if !isSetBuildMeta(BuildDate) {
BuildDate = s.Value
}
case "vcs.modified":
modified = s.Value == "true"
}
}
if isSetBuildMeta(GitCommit) || vcsRevision == "" {
return
}
GitCommit = vcsRevision
if modified {
GitCommit += "-dirty"
}
}
118 changes: 118 additions & 0 deletions apps/stackpanel-go/cmd/cli/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package cmd

import (
"bytes"
"strings"
"testing"
)

func TestFormatVersion(t *testing.T) {
t.Parallel()

tests := []struct {
name string
cmd string
version string
commit string
date string
want []string
hide []string
}{
{
name: "version only",
cmd: "stack",
version: "0.1.0",
commit: "unknown",
date: "unknown",
want: []string{"stack version 0.1.0\n"},
hide: []string{"commit:", "built:"},
},
{
name: "commit and date",
cmd: "stack",
version: "0.1.0",
commit: "abc123def",
date: "2026-09-08T05:23:00Z",
want: []string{
"stack version 0.1.0\n",
"commit: abc123def\n",
"built: 2026-09-08T05:23:00Z\n",
},
},
{
name: "empty meta omitted",
cmd: "stack",
version: "dev",
commit: "",
date: "",
want: []string{"stack version dev\n"},
hide: []string{"commit:", "built:"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := formatVersion(tt.cmd, tt.version, tt.commit, tt.date)
for _, want := range tt.want {
if !strings.Contains(got, want) {
t.Errorf("formatVersion() = %q, want to contain %q", got, want)
}
}
for _, hide := range tt.hide {
if strings.Contains(got, hide) {
t.Errorf("formatVersion() = %q, should omit %q", got, hide)
}
}
})
}
}

func resetRootFlags() {
rootCmd.SetArgs(nil)
rootCmd.SetOut(nil)
rootCmd.SetErr(nil)
for _, name := range []string{"version", "help"} {
if f := rootCmd.Flags().Lookup(name); f != nil {
_ = f.Value.Set("false")
f.Changed = false
}
}
}

func TestVersionFlagIncludesBuildMetadata(t *testing.T) {
prevVersion, prevCommit, prevDate := Version, GitCommit, BuildDate
t.Cleanup(func() {
Version, GitCommit, BuildDate = prevVersion, prevCommit, prevDate
rootCmd.Version = Version
rootCmd.SetVersionTemplate(versionCobraTemplate(GitCommit, BuildDate))
resetRootFlags()
})

Version = "0.1.0"
GitCommit = "deadbeefcafebabe"
BuildDate = "2026-09-08T05:23:00Z"
rootCmd.Version = Version
rootCmd.SetVersionTemplate(versionCobraTemplate(GitCommit, BuildDate))
resetRootFlags()

buf := &bytes.Buffer{}
rootCmd.SetOut(buf)
rootCmd.SetErr(buf)
rootCmd.SetArgs([]string{"--version"})

if err := rootCmd.Execute(); err != nil {
t.Fatalf("stack --version should succeed: %v", err)
}

got := buf.String()
for _, want := range []string{
"stack version 0.1.0",
"commit: deadbeefcafebabe",
"built: 2026-09-08T05:23:00Z",
} {
if !strings.Contains(got, want) {
t.Errorf("--version output %q, want to contain %q", got, want)
}
}
}
Loading