Skip to content

Commit

Permalink
feat: source version information from debug.BuildInfo
Browse files Browse the repository at this point in the history
Signed-off-by: nscuro <nscuro@protonmail.com>
  • Loading branch information
nscuro committed Jun 28, 2022
1 parent d000aa5 commit 1c8f56f
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 19 deletions.
39 changes: 33 additions & 6 deletions internal/cli/cmd/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,53 @@ package version

import (
"context"
"fmt"
"encoding/json"
"flag"
"github.com/CycloneDX/cyclonedx-gomod/internal/version"
"io"
"os"
"text/template"

"github.com/CycloneDX/cyclonedx-gomod/internal/version"
"github.com/peterbourgon/ff/v3/ffcli"
)

func New() *ffcli.Command {
fs := flag.NewFlagSet("cyclonedx-gomod version", flag.ExitOnError)

var useJSON bool
fs.BoolVar(&useJSON, "json", false, "Output in JSON")

return &ffcli.Command{
Name: "version",
ShortHelp: "Show version information",
ShortUsage: "cyclonedx-gomod version",
FlagSet: fs,
Exec: func(_ context.Context, _ []string) error {
return execVersionCmd(os.Stdout)
return execVersionCmd(os.Stdout, useJSON)
},
}
}

func execVersionCmd(writer io.Writer) error {
fmt.Fprintln(writer, version.Version)
return nil
var outputTmpl = template.Must(template.New("").Parse(`Version:{{"\t"}}{{ .Version }}
{{ if .ModuleSum -}}
ModuleSum:{{"\t"}}{{ .ModuleSum }}
{{ end -}}
{{ if .Commit -}}
Commit:{{"\t\t"}}{{ .Commit }}
CommitDate:{{"\t"}}{{ .CommitDate }}
Modified:{{"\t"}}{{ .Modified }}
{{ end -}}
GoVersion:{{"\t"}}{{ .GoVersion }}
OS:{{"\t\t"}}{{ .OS }}
Arch:{{"\t\t"}}{{ .Arch }}
`))

func execVersionCmd(writer io.Writer, useJSON bool) error {
if useJSON {
enc := json.NewEncoder(writer)
enc.SetIndent("", " ")
return enc.Encode(version.Info)
}

return outputTmpl.Execute(writer, version.Info)
}
39 changes: 33 additions & 6 deletions internal/cli/cmd/version/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,44 @@ package version

import (
"bytes"
"fmt"
"encoding/json"
"strings"
"testing"

"github.com/CycloneDX/cyclonedx-gomod/internal/version"
"github.com/stretchr/testify/require"
)

func TestExecVersionCmd(t *testing.T) {
buf := new(bytes.Buffer)
t.Run("Plain", func(t *testing.T) {
buf := new(bytes.Buffer)

err := execVersionCmd(buf)
require.NoError(t, err)
require.Equal(t, fmt.Sprintf("%s\n", version.Version), buf.String())
err := execVersionCmd(buf, false)
require.NoError(t, err)

lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
require.Len(t, lines, 4)
require.Equal(t, "Version:\tv0.0.0-unknown", lines[0]) // Actual version is not set during tests
require.Regexp(t, `^GoVersion:\s+go.+`, lines[1])
require.Regexp(t, `^OS:\s+[a-z]+`, lines[2])
require.Regexp(t, `^Arch:\s+[a-z]+`, lines[3])
})

t.Run("JSON", func(t *testing.T) {
buf := new(bytes.Buffer)

err := execVersionCmd(buf, true)
require.NoError(t, err)

var output map[string]any
err = json.NewDecoder(buf).Decode(&output)
require.NoError(t, err)

require.Len(t, output, 4)
require.Contains(t, output, "Version")
require.Equal(t, "v0.0.0-unknown", output["Version"])
require.Contains(t, output, "GoVersion")
require.Regexp(t, `go.+`, output["GoVersion"])
require.Contains(t, output, "OS")
require.Contains(t, output, "Arch")
})
}
6 changes: 3 additions & 3 deletions internal/sbom/sbom.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@ func BuildToolMetadata(logger zerolog.Logger) (*cdx.Tool, error) {
}

return &cdx.Tool{
Vendor: version.Author,
Name: version.Name,
Version: version.Version,
Vendor: "CycloneDX",
Name: "cyclonedx-gomod",
Version: version.Info.Version,
Hashes: &toolHashes,
ExternalReferences: &[]cdx.ExternalReference{
{
Expand Down
59 changes: 55 additions & 4 deletions internal/version/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,60 @@

package version

const (
Author = "CycloneDX"
Name = "cyclonedx-gomod"
import (
"golang.org/x/mod/module"
"runtime"
"runtime/debug"
"strconv"
"time"
)

var Version = "v0.0.0-unset" // Must be a var so we can set it at build time
var Info = struct {
Version string
ModuleSum string `json:",omitempty"`
Commit string `json:",omitempty"`
CommitDate *time.Time `json:",omitempty"`
Modified *bool `json:",omitempty"`
GoVersion string
OS string
Arch string
}{
Version: "v0.0.0-unknown",
}

func init() {
bi, ok := debug.ReadBuildInfo()
if !ok {
return
}

Info.Commit = buildSetting(bi, "vcs.revision")
if vcsDate, err := time.Parse(time.RFC3339, buildSetting(bi, "vcs.time")); err == nil {
Info.CommitDate = &vcsDate
}
if vcsModified, err := strconv.ParseBool(buildSetting(bi, "vcs.modified")); err == nil {
Info.Modified = &vcsModified
}

Info.GoVersion = bi.GoVersion
Info.OS = runtime.GOOS
Info.Arch = runtime.GOARCH

if bi.Main.Version != "" && bi.Main.Version != "(devel)" {
Info.Version = bi.Main.Version
} else if Info.Commit != "" && Info.CommitDate != nil {
Info.Version = module.PseudoVersion("", "", *Info.CommitDate, Info.Commit[:12])
}
Info.ModuleSum = bi.Main.Sum
}

func buildSetting(bi *debug.BuildInfo, key string) (val string) {
for _, setting := range bi.Settings {
if setting.Key == key {
val = setting.Value
break
}
}

return
}

0 comments on commit 1c8f56f

Please sign in to comment.