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
4 changes: 3 additions & 1 deletion .rules/.golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
run:
timeout: 5m
modules-download-mode: readonly
go: "1.22"
go: "1.23.2"
concurrency: 2
memory-limit: 1024

# output configuration options
output:
Expand Down
23 changes: 12 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ env:

tools:
@go install github.com/daixiang0/gci@v0.13.4
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8
@go install github.com/google/addlicense@v1.1.1
@go install github.com/nikolaydubina/go-cover-treemap@v1.4.2
@go install github.com/onsi/ginkgo/v2/ginkgo@v2.19.0
Expand Down Expand Up @@ -108,13 +108,11 @@ format-go: fmt fumpt imports gci formattag

fmt:
@find . -name "*.go" -type f -not -path '*/vendor/*' \
| sed 's/^\.\///g' \
| xargs -I {} -S 5000 sh -c 'echo "formatting {}.." && gofmt -w -s {}'
-exec sh -c 'echo "formatting $$1.." && gofmt -w -s "$$1"' sh {} \;

fumpt:
@find . -name "*.go" -type f -not -path '*/vendor/*' \
| sed 's/^\.\///g' \
| xargs -I {} -S 5000 sh -c 'echo "formatting {}.." && gofumpt -w -extra {}'
-exec sh -c 'echo "formatting $$1.." && gofumpt -w -extra "$$1"' sh {} \;

imports:
@goimports -v -w -e -local github.com/sighupio main.go
Expand All @@ -123,22 +121,25 @@ imports:

gci:
@find . -name "*.go" -type f -not -path '*/vendor/*' \
| sed 's/^\.\///g' \
| xargs -I {} -S 5000 sh -c 'echo "formatting imports for {}.." && \
gci write --skip-generated -s standard -s default -s "Prefix(github.com/sighupio)" {}'
-exec sh -c 'echo "formatting imports for $$1.." && \
gci write --skip-generated -s standard -s default -s "Prefix(github.com/sighupio)" "$$1"' sh {} \;

formattag:
@find . -name "*.go" -type f -not -path '*/vendor/*' \
| sed 's/^\.\///g' \
| xargs -I {} -S 5000 sh -c 'formattag -file {}'
-exec sh -c 'formattag -file "$$1"' sh {} \;

.PHONY: lint lint-go
.PHONY: lint lint-go lint-go-common lint-common

lint: lint-go

lint-go:
@GOFLAGS=-mod=mod golangci-lint -v run --color=always --max-same-issues 25 --config=${_PROJECT_DIRECTORY}/.rules/.golangci.yml ./...

lint-go-common:
@GOFLAGS=-mod=mod golangci-lint run --no-config -E godot -E wsl -E nlreturn -E grouper --color=always --max-same-issues 25 ./...

lint-common: lint-go-common

.PHONY: test-unit test-integration test-e2e test-all show-coverage

test-unit:
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,30 @@ Once you've ensured the above dependencies are installed, you can proceed with t

For basic and advanced usage instructions, please refer to furyctl's [official documentation](https://docs.sighup.io/furyctl/) and the [SIGHUP Distribution getting started guides](https://docs.sighup.io/docs/getting-started/).

### Quick Start: Using Tool Aliases

After downloading dependencies with `furyctl download dependencies`, you can easily access the downloaded CLI tools (kubectl, helm, etc.) using bash aliases:

```bash
# Generate and view aliases
furyctl get aliases

# Set aliases in your current session
eval "$(furyctl get aliases)"

# Add aliases to your shell profile for persistence
furyctl get aliases >> ~/.bashrc
# or for zsh users
furyctl get aliases >> ~/.zshrc

# Now you can use the tools directly
kubectl get nodes
helm list
terraform --version
```

The aliases point to the exact versions of tools specified in your distribution configuration, ensuring consistency across your team and environments.

<!-- </SD-DOCS> -->
<!-- <FOOTER> -->

Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ furyctl is a command line interface tool to manage the full lifecycle of SIGHUP
rootCmd.AddCommand(NewDumpCmd())
rootCmd.AddCommand(NewGetCmd())
rootCmd.AddCommand(NewLegacyCmd())
rootCmd.AddCommand(NewToolsCmd())
rootCmd.AddCommand(NewValidateCmd())
rootCmd.AddCommand(NewVersionCmd())
rootCmd.AddCommand(NewRenewCmd())
Expand Down
33 changes: 33 additions & 0 deletions cmd/tools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2017-present SIGHUP s.r.l All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package cmd

import (
"github.com/spf13/cobra"

"github.com/sighupio/furyctl/cmd/tools"
)

func NewToolsCmd() *cobra.Command {
toolsCmd := &cobra.Command{
Use: "tools",
Short: "Manage tool integrations for downloaded binaries",
Long: `Manage tool integrations for downloaded binaries.

Generate various output formats for integrating furyctl-downloaded tools
with your shell environment. Choose the format that works best with your
development setup:

- aliases: Traditional bash aliases (default)
- functions: Bash functions that override version managers like mise/asdf
- mise: Native mise integration via mise.toml file`,
}

toolsCmd.AddCommand(tools.NewAliasesCmd())
toolsCmd.AddCommand(tools.NewFunctionsCmd())
toolsCmd.AddCommand(tools.NewMiseCmd())

return toolsCmd
}
34 changes: 34 additions & 0 deletions cmd/tools/aliases.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2017-present SIGHUP s.r.l All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tools

import "github.com/spf13/cobra"

// NewAliasesCmd creates the aliases command.
func NewAliasesCmd() *cobra.Command {
return CreateShellIntegrationCommand(
"aliases",
"Generate bash aliases for downloaded tools",
`Generate bash aliases for tools downloaded by furyctl.

This command outputs bash aliases that point to the downloaded tool binaries
with versions that are compatible with your SIGHUP Distribution configuration.

Examples:
# View aliases
furyctl tools aliases

# Set aliases in current session
eval "$(furyctl tools aliases)"

# Add to your shell profile
furyctl tools aliases >> ~/.bashrc

# Use the tools natively
kubectl --help
helm list --help`,
AliasFormat,
)
}
113 changes: 113 additions & 0 deletions cmd/tools/aliases_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) 2017-present SIGHUP s.r.l All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tools_test

import (
"strings"
"testing"

"github.com/stretchr/testify/assert"

"github.com/sighupio/furyctl/cmd/tools"
)

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

cmd := tools.NewAliasesCmd()

assert.Equal(t, "aliases", cmd.Use)
assert.Equal(t, "Generate bash aliases for downloaded tools", cmd.Short)
assert.Contains(t, cmd.Long, "Generate bash aliases for tools downloaded by furyctl")
assert.Contains(t, cmd.Long, "eval \"$(furyctl tools aliases)\"")
}

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

cmd := tools.NewAliasesCmd()

// Test that command can be created and has expected flags.
assert.NotNil(t, cmd)

// Verify required flags exist.
configFlag := cmd.Flags().Lookup("config")
assert.NotNil(t, configFlag)
assert.Equal(t, "furyctl.yaml", configFlag.DefValue)

binPathFlag := cmd.Flags().Lookup("bin-path")
assert.NotNil(t, binPathFlag)

skipDepsFlag := cmd.Flags().Lookup("skip-deps-download")
assert.NotNil(t, skipDepsFlag)
assert.Equal(t, "false", skipDepsFlag.DefValue)
}
Comment on lines +27 to +46

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure how much this kind of test makes sense. it's testing more cobra than our actual code, a better test would be to actually use test the flags in the actual code


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

cmd := tools.NewAliasesCmd()

// Verify the command is properly structured.
assert.NotNil(t, cmd.PreRun)
assert.NotNil(t, cmd.RunE)

// Check flags are properly defined.
binPathFlag := cmd.Flags().Lookup("bin-path")
assert.NotNil(t, binPathFlag)
assert.Equal(t, "b", binPathFlag.Shorthand)

configFlag := cmd.Flags().Lookup("config")
assert.NotNil(t, configFlag)
assert.Equal(t, "c", configFlag.Shorthand)
assert.Equal(t, "furyctl.yaml", configFlag.DefValue)

skipDepsFlag := cmd.Flags().Lookup("skip-deps-download")
assert.NotNil(t, skipDepsFlag)
assert.Equal(t, "false", skipDepsFlag.DefValue)
}

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

// Test the expected alias format.
toolName := "kubectl"
toolPath := "/path/to/.furyctl/bin/kubectl/1.25.8/kubectl"

expectedAlias := `alias kubectl="/path/to/.furyctl/bin/kubectl/1.25.8/kubectl"`

// Simulate the alias generation format.
actualAlias := "alias " + toolName + "=\"" + toolPath + "\""

assert.Equal(t, expectedAlias, actualAlias)
}

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

// Test multiple aliases format.
tools := []struct {
name string
path string
}{
{"kubectl", "/path/to/.furyctl/bin/kubectl/1.25.8/kubectl"},
{"helm", "/path/to/.furyctl/bin/helm/3.10.0/helm"},
{"terraform", "/path/to/.furyctl/bin/terraform/1.5.7/terraform"},
}

aliases := make([]string, 0, len(tools))

for _, tool := range tools {
alias := "alias " + tool.name + "=\"" + tool.path + "\""
aliases = append(aliases, alias)
}

output := strings.Join(aliases, "\n")

assert.Contains(t, output, "alias kubectl=")
assert.Contains(t, output, "alias helm=")
assert.Contains(t, output, "alias terraform=")
assert.Len(t, strings.Split(output, "\n"), 3)
}
34 changes: 34 additions & 0 deletions cmd/tools/functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2017-present SIGHUP s.r.l All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package tools

import "github.com/spf13/cobra"

// NewFunctionsCmd creates the functions command.
func NewFunctionsCmd() *cobra.Command {
return CreateShellIntegrationCommand(
"functions",
"Generate bash functions for downloaded tools",
`Generate bash functions for tools downloaded by furyctl.

This command generates bash functions instead of aliases. Functions have higher
precedence than aliases and will override version managers like mise, asdf, or
other tools that create aliases.

Use this when you have version managers installed but want furyctl-downloaded
tools to take precedence.

Examples:
# View functions
furyctl tools functions

# Set functions in current session (overrides mise/asdf)
eval "$(furyctl tools functions)"

# Add to your shell profile
furyctl tools functions >> ~/.bashrc`,
FunctionFormat,
)
}
Loading