diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 2d719a9..3da0ba4 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -32,6 +32,11 @@ builds: ignore: - goos: windows goarch: arm + ldflags: + - -s -w + - -X github.com/devbytes-cloud/freight/internal/commands.Version={{.Version}} + - -X github.com/devbytes-cloud/freight/internal/commands.Commit={{.Commit}} + - -X github.com/devbytes-cloud/freight/internal/commands.Date={{.Date}} archives: - formats: ['tar.gz'] # this name template makes the OS and Arch compatible with the results of `uname`. diff --git a/internal/commands/root.go b/internal/commands/root.go index 0ae821d..81ba164 100644 --- a/internal/commands/root.go +++ b/internal/commands/root.go @@ -41,6 +41,7 @@ func NewRootCmd() *cobra.Command { } if err := setupHooks(); err != nil { cmd.PrintErrln(err) + os.Exit(1) } configForce, err := cmd.Flags().GetBool("config-force") @@ -59,6 +60,7 @@ func NewRootCmd() *cobra.Command { initCmd.Flags().BoolP("config-force", "c", false, "If you wish to force write the config") rootCmd.AddCommand(initCmd) + rootCmd.AddCommand(versionCommand()) return rootCmd } diff --git a/internal/commands/version.go b/internal/commands/version.go new file mode 100644 index 0000000..fa9d33f --- /dev/null +++ b/internal/commands/version.go @@ -0,0 +1,43 @@ +package commands + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var ( + // Version holds the version number of the application, defaulting to "dev" for development builds. + Version = "dev" + + // Commit represents the Git commit hash of the build, defaulting to "none" for untracked or local builds. + Commit = "none" + + // Date represents the build date, defaulting to "unknown" for untracked or local builds. + Date = "unknown" +) + +// versionCommand creates a cobra command for displaying the version of freight. +func versionCommand() *cobra.Command { + vCmd := &cobra.Command{ + Use: "version", + Short: "Print the version number of freight", + Run: func(cmd *cobra.Command, args []string) { + cmd.Println(fmt.Sprintf("Freight version: %s", Version)) + + verbose, err := cmd.Flags().GetBool("verbose") + if err != nil { + cmd.PrintErrf("Failed to get verbose flag: %v", err) + } + + if verbose { + cmd.Println(fmt.Sprintf("Commit: %s", Commit)) + cmd.Println(fmt.Sprintf("Date: %s", Date)) + } + }, + } + + vCmd.Flags().BoolP("verbose", "v", false, "Print verbose version information about freight") + + return vCmd +} diff --git a/internal/commands/version_test.go b/internal/commands/version_test.go new file mode 100644 index 0000000..002b587 --- /dev/null +++ b/internal/commands/version_test.go @@ -0,0 +1,96 @@ +package commands + +import ( + "bytes" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +type testStruct struct { + isVerbose bool + setVersion string + setDate string + setCommit string + expectedVersion string + expectedDate string + expectedCommit string +} + +func TestVersionCommand(t *testing.T) { + testMap := map[string]testStruct{ + "default build": { + isVerbose: false, + expectedVersion: "dev", + }, + "set version": { + isVerbose: false, + setVersion: "test-a", + expectedVersion: "test-a", + }, + "verbose: set version": { + isVerbose: true, + setVersion: "test-a", + expectedVersion: "test-a", + }, + "verbose: set date, commit, version": { + isVerbose: true, + setVersion: "test-b", + expectedVersion: "test-b", + setCommit: "test-c", + expectedCommit: "test-c", + setDate: "2020-04-06T00:00:00Z", + expectedDate: "2020-04-06T00:00:00Z", + }, + "verbose: set date, commit": { + isVerbose: true, + setCommit: "test-c", + expectedCommit: "test-c", + setDate: "2020-04-06T00:00:00Z", + expectedDate: "2020-04-06T00:00:00Z", + }, + } + + for name, td := range testMap { + t.Run(name, func(t *testing.T) { + origVersion, origCommit, origDate := Version, Commit, Date + defer func() { + Version, Commit, Date = origVersion, origCommit, origDate + }() + + if td.setVersion != "" { + Version = td.setVersion + } + if td.setDate != "" { + Date = td.setDate + } + if td.setCommit != "" { + Commit = td.setCommit + } + + cmd := versionCommand() + buf := new(bytes.Buffer) + cmd.SetOut(buf) + cmd.SetErr(buf) + + if td.isVerbose { + cmd.SetArgs([]string{"--verbose"}) + } + + err := cmd.Execute() + + assert.NoError(t, err) + fmt.Println(buf.String()) + assert.Contains(t, buf.String(), td.expectedVersion) + + if td.isVerbose { + assert.Contains(t, buf.String(), td.expectedCommit) + assert.Contains(t, buf.String(), td.expectedDate) + } else { + assert.NotContains(t, buf.String(), "Commit:") + assert.NotContains(t, buf.String(), "Date:") + } + }) + } +} diff --git a/website/docs/cli/_category_.json b/website/docs/cli/_category_.json new file mode 100644 index 0000000..70c605c --- /dev/null +++ b/website/docs/cli/_category_.json @@ -0,0 +1,5 @@ +{ + "label": "CLI Reference", + "position": 3, + "collapsed": false +} diff --git a/website/docs/cli/index.md b/website/docs/cli/index.md new file mode 100644 index 0000000..1635643 --- /dev/null +++ b/website/docs/cli/index.md @@ -0,0 +1,17 @@ +# CLI Overview + +Brief overview of the Freight CLI. Freight is a blazing-fast Git hooks manager designed for speed and simplicity. + +## Available Commands + +| Command | Description | +| :--- | :--- | +| [`init`](./init.md) | Bootstrap Freight in the current repository. | +| [`version`](./version.md) | Print version information. | +| `help` | Show help for any command. | + +## Global Flags + +The following flags are available for all commands: + +* `-h, --help`: Show help for the command. diff --git a/website/docs/cli/init.md b/website/docs/cli/init.md new file mode 100644 index 0000000..41daced --- /dev/null +++ b/website/docs/cli/init.md @@ -0,0 +1,30 @@ +# freight init + +Bootstrap Freight in the current repository. + +## Description + +The `init` command sets up Freight in your local repository. It ensures all necessary components are in place for managing your Git hooks. + +**What it does:** +- Extracts the **Conductor** binary to your repository root. +- Generates a starter **Railcar** manifest (`railcar.json`). +- Rewires your `.git/hooks` to point to the Conductor. + +## Flags + +- `-c, --config-force`: Overwrite an existing `railcar.json` file if it already exists. + +## Examples + +```bash +freight init +``` + +**Output:** +```text +✔ Extracting conductor binary... +✔ Generating railcar.json... +✔ Rewiring git hooks... +Freight initialized successfully! +``` diff --git a/website/docs/cli/version.md b/website/docs/cli/version.md new file mode 100644 index 0000000..08ff180 --- /dev/null +++ b/website/docs/cli/version.md @@ -0,0 +1,39 @@ +# freight version + +Print the version information for the Freight CLI. + +## Description + +The `version` command displays the current version of the Freight CLI tool. This is useful for troubleshooting and ensuring you are running the expected version. + +## Flags + +- `-v, --verbose`: Show additional build details (commit hash and build date). + +## Examples + +### Normal mode +```bash +freight version +``` + +**Output:** +```text +Freight version: 0.1.0 +``` + +### Verbose mode +```bash +freight version --verbose +``` + +**Output:** +```text +Freight version: 0.1.0 +Commit: abc123 +Date: 2026-01-18T12:00:00Z +``` + +:::info Note about development builds +When running Freight from source or a non-release build, the version will show as `dev`, the commit will be `none`, and the date will be `unknown`. +::: diff --git a/website/docs/configuration.md b/website/docs/configuration.md index 808e795..7fe4875 100644 --- a/website/docs/configuration.md +++ b/website/docs/configuration.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 --- # Configuration (Railcar Manifest) diff --git a/website/docs/installation.md b/website/docs/installation.md index a31a32d..4fd56db 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -54,14 +54,4 @@ git commit -m "Testing Freight" --- -## Command-line Reference - -| Command | Description | -|----------------|---------------------------------------------| -| `freight init` | Bootstrap Freight in the current repository | -| `freight help` | Show global or command-specific help | - -### Global flags: - -* `-c, --config-force` – overwrite an existing `railcar.json` -* `-h, --help` – display help +For the complete CLI reference, see [CLI Reference](./cli/index.md). diff --git a/website/sidebars.ts b/website/sidebars.ts index 230cd0f..7965cf8 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -16,6 +16,18 @@ const sidebars: SidebarsConfig = { tutorialSidebar: [ 'introduction', 'installation', + { + type: 'category', + label: 'CLI Reference', + link: { + type: 'doc', + id: 'cli/index', + }, + items: [ + 'cli/init', + 'cli/version', + ], + }, 'configuration', 'advanced', 'best-practices',