Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
6 changes: 4 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import (
"knative.dev/func/pkg/config"
fn "knative.dev/func/pkg/functions"
"knative.dev/func/pkg/k8s"
"knative.dev/func/pkg/version"
)

// DefaultVersion when building source directly (bypassing the Makefile)
const DefaultVersion = "v0.0.0+source"
// DefaultVersion when building source directly (bypassing the Makefile).
// Delegates to version.DefaultVers so the fallback is defined in one place.
const DefaultVersion = version.DefaultVers

// DefaultNamespace is the global static default namespace, and is equivalent
// to the Kubernetes default namespace.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/BurntSushi/toml v1.6.0
github.com/Masterminds/semver v1.5.0
github.com/Masterminds/semver/v3 v3.4.0
Comment thread
Ankitsinghsisodya marked this conversation as resolved.
Outdated
github.com/Microsoft/go-winio v0.6.2
github.com/Netflix/go-expect v0.0.0-20220104043353-73e0943537d2
github.com/alecthomas/jsonschema v0.0.0-20220216202328-9eeeec9d044b
Expand Down Expand Up @@ -90,7 +91,6 @@ require (
github.com/Azure/go-autorest/autorest/date v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.2 // indirect
github.com/Azure/go-autorest/tracing v0.6.1 // indirect
github.com/Masterminds/semver/v3 v3.4.0 // indirect
github.com/OneOfOne/xxhash v1.2.8 // indirect
github.com/ProtonMail/go-crypto v1.4.0 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func Main() {
cfg := cmd.RootCommandConfig{
Name: "func",
Version: cmd.Version{
Vers: version.Vers,
Vers: version.Get().Original(),
Kver: version.Kver,
Hash: version.Hash,
}}
Expand Down
8 changes: 4 additions & 4 deletions pkg/mcp/mcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import (
"sync/atomic"

"github.com/modelcontextprotocol/go-sdk/mcp"
"knative.dev/func/pkg/version"
)

const (
name = "func"
title = "func"
version = "0.1.0"
name = "func"
title = "func"
)

// NOTE: Invoking prompts in some interfaces (such as Claude Code) when all
Expand Down Expand Up @@ -91,7 +91,7 @@ func New(options ...Option) *Server {
&mcp.Implementation{
Name: name,
Title: title,
Version: version},
Version: version.Get().String()},
Comment thread
Ankitsinghsisodya marked this conversation as resolved.
Outdated
&mcp.ServerOptions{
Instructions: instructions(s.readonly.Load()),
HasPrompts: true,
Expand Down
3 changes: 2 additions & 1 deletion pkg/mcp/tools_healthcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"github.com/modelcontextprotocol/go-sdk/mcp"
"knative.dev/func/pkg/version"
)

var healthCheckTool = &mcp.Tool{
Expand All @@ -21,7 +22,7 @@ func (s *Server) healthcheckHandler(ctx context.Context, r *mcp.CallToolRequest,
output = HealthcheckOutput{
Status: "ok",
Message: "The MCP server is running!",
Version: version,
Version: version.Get().String(),
Comment thread
Ankitsinghsisodya marked this conversation as resolved.
Outdated
}
return
}
Expand Down
25 changes: 25 additions & 0 deletions pkg/version/version.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
package version

import "github.com/Masterminds/semver/v3"

var Vers, Kver, Hash string

// DefaultVers is the fallback version used when no build-time version was
// injected (e.g. source builds that bypass the Makefile).
const DefaultVers = "v0.0.0+source"

// Get returns the parsed semver for this binary. When no build-time version
// was injected via ldflags, DefaultVers is used. If the injected string is
// unparseable, DefaultVers is used as a safe fallback.
// String() returns a clean semver without the leading "v" (e.g. "0.0.0+source"),
// suitable for machine-readable consumers such as the MCP server.
// Original() round-trips the injected string verbatim, preserving the leading
// "v" preferred by human-readable output.
func Get() *semver.Version {
s := Vers
if s == "" {
s = DefaultVers
}
v, err := semver.NewVersion(s) // permissive: accepts leading 'v'
if err != nil {
v, _ = semver.NewVersion(DefaultVers)
}
Comment thread
Ankitsinghsisodya marked this conversation as resolved.
Outdated
return v
}
63 changes: 63 additions & 0 deletions pkg/version/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package version_test

import (
"testing"

"knative.dev/func/pkg/version"
)

// TestGet_Empty verifies that Get returns the DefaultVers fallback when no
// build-time version has been injected (Vers == "").
func TestGet_Empty(t *testing.T) {
orig := version.Vers
version.Vers = ""
defer func() { version.Vers = orig }()

v := version.Get()
if v == nil {
t.Fatal("expected non-nil *semver.Version")
}
// String() must be clean semver without a leading 'v'
if got := v.String(); got != "0.0.0+source" {
t.Errorf("String() = %q; want %q", got, "0.0.0+source")
}
// Original() must round-trip the full default string including 'v'
if got := v.Original(); got != "v0.0.0+source" {
t.Errorf("Original() = %q; want %q", got, "v0.0.0+source")
}
}

// TestGet_InjectedVersion verifies that a build-time version is parsed and
// exposed correctly.
func TestGet_InjectedVersion(t *testing.T) {
orig := version.Vers
version.Vers = "v1.2.3"
defer func() { version.Vers = orig }()

v := version.Get()
if v == nil {
t.Fatal("expected non-nil *semver.Version")
}
if got := v.String(); got != "1.2.3" {
t.Errorf("String() = %q; want %q", got, "1.2.3")
}
if got := v.Original(); got != "v1.2.3" {
t.Errorf("Original() = %q; want %q", got, "v1.2.3")
}
}

// TestGet_InvalidFallsBack verifies that an unparseable injected version does
// not panic and falls back to DefaultVers.
func TestGet_InvalidFallsBack(t *testing.T) {
orig := version.Vers
version.Vers = "not-a-semver!!!"
defer func() { version.Vers = orig }()

v := version.Get()
if v == nil {
t.Fatal("expected non-nil *semver.Version even for invalid input")
}
if got := v.String(); got != "0.0.0+source" {
t.Errorf("String() = %q; want %q on invalid input", got, "0.0.0+source")
}
}
Loading