Update golangci-lint to v2.12.2 with canonical config
All checks were successful
check / check (push) Successful in 1m8s
All checks were successful
check / check (push) Successful in 1m8s
- Replace .golangci.yml with the canonical strict config (all linters enabled except the standard disable list; lll 88, funlen 80/50, cyclop 15, dupl 100; test files now linted) - Pin the Dockerfile lint stage to golangci/golangci-lint:v2.12.2 by tag and digest (Debian-based) - Fix all ~1550 findings surfaced by the new config: line wrapping, wsl_v5/nlreturn blank lines, noinlineerr splits, err113 sentinel errors, perfsprint/modernize rewrites, goconst constants, thelper, testifylint, noctx CommandContext, testpackage conversions, t.Parallel() where safe, and complexity/dupl helper extraction - Record the change and follow-up items in TODO.md
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
// - setupTestVault(): CLI test helper for vault initialization
|
||||
// - Uses consistent test mnemonic for reproducible testing
|
||||
|
||||
//nolint:testpackage // white-box test of unexported internals
|
||||
package cli
|
||||
|
||||
import (
|
||||
@@ -32,29 +33,41 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Helper function to add a secret to vault with proper buffer protection
|
||||
func addTestSecret(t *testing.T, vlt *vault.Vault, name string, value []byte, force bool) {
|
||||
const (
|
||||
// testMnemonic is the standard BIP39 mnemonic used for CLI tests.
|
||||
//nolint:dupword // BIP39 test mnemonic intentionally repeats a word
|
||||
testMnemonic = "abandon abandon abandon abandon abandon abandon " +
|
||||
"abandon abandon abandon abandon abandon about"
|
||||
|
||||
// testStateDir is the in-memory state directory used by CLI tests.
|
||||
testStateDir = "/test/state"
|
||||
)
|
||||
|
||||
// Helper function to add a version of the "test/secret" secret to the
|
||||
// vault with proper buffer protection
|
||||
func addTestSecret(t *testing.T, vlt *vault.Vault, value []byte, force bool) {
|
||||
t.Helper()
|
||||
|
||||
buffer := memguard.NewBufferFromBytes(value)
|
||||
defer buffer.Destroy()
|
||||
err := vlt.AddSecret(name, buffer, force)
|
||||
|
||||
err := vlt.AddSecret("test/secret", buffer, force)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Helper function to set up a vault with long-term key
|
||||
func setupTestVault(t *testing.T, fs afero.Fs, stateDir string) {
|
||||
// Helper function to set up a vault with long-term key in testStateDir
|
||||
func setupTestVault(t *testing.T, fs afero.Fs) {
|
||||
t.Helper()
|
||||
|
||||
// Set mnemonic for testing
|
||||
testMnemonic := "abandon abandon abandon abandon abandon abandon " +
|
||||
"abandon abandon abandon abandon abandon about"
|
||||
t.Setenv(secret.EnvMnemonic, testMnemonic)
|
||||
|
||||
// Create vault
|
||||
vlt, err := vault.CreateVault(fs, stateDir, "default")
|
||||
vlt, err := vault.CreateVault(fs, testStateDir, "default")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Derive and store long-term key from mnemonic
|
||||
mnemonic := "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
|
||||
ltIdentity, err := agehd.DeriveIdentity(mnemonic, 0)
|
||||
ltIdentity, err := agehd.DeriveIdentity(testMnemonic, 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Store long-term public key in vault
|
||||
@@ -64,30 +77,32 @@ func setupTestVault(t *testing.T, fs afero.Fs, stateDir string) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// Select vault
|
||||
err = vault.SelectVault(fs, stateDir, "default")
|
||||
err = vault.SelectVault(fs, testStateDir, "default")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
//nolint:paralleltest // uses t.Setenv via setupTestVault
|
||||
func TestListVersionsCommand(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
stateDir := "/test/state"
|
||||
stateDir := testStateDir
|
||||
cli := NewCLIInstanceWithStateDir(fs, stateDir)
|
||||
|
||||
// Set up vault with long-term key
|
||||
setupTestVault(t, fs, stateDir)
|
||||
setupTestVault(t, fs)
|
||||
|
||||
// Add a secret with multiple versions
|
||||
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("version-1"), false)
|
||||
addTestSecret(t, vlt, []byte("version-1"), false)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("version-2"), true)
|
||||
addTestSecret(t, vlt, []byte("version-2"), true)
|
||||
|
||||
// Create a command for output capture
|
||||
cmd := newRootCmd()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetErr(&buf)
|
||||
@@ -112,24 +127,28 @@ func TestListVersionsCommand(t *testing.T) {
|
||||
// Should have two version entries
|
||||
lines := strings.Split(outputStr, "\n")
|
||||
versionLines := 0
|
||||
|
||||
for _, line := range lines {
|
||||
if strings.Contains(line, ".001") || strings.Contains(line, ".002") {
|
||||
versionLines++
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, 2, versionLines)
|
||||
}
|
||||
|
||||
//nolint:paralleltest // uses t.Setenv via setupTestVault
|
||||
func TestListVersionsNonExistentSecret(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
stateDir := "/test/state"
|
||||
stateDir := testStateDir
|
||||
cli := NewCLIInstanceWithStateDir(fs, stateDir)
|
||||
|
||||
// Set up vault with long-term key
|
||||
setupTestVault(t, fs, stateDir)
|
||||
setupTestVault(t, fs)
|
||||
|
||||
// Create a command for output capture
|
||||
cmd := newRootCmd()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetErr(&buf)
|
||||
@@ -140,23 +159,24 @@ func TestListVersionsNonExistentSecret(t *testing.T) {
|
||||
assert.Contains(t, err.Error(), "not found")
|
||||
}
|
||||
|
||||
//nolint:paralleltest // uses t.Setenv via setupTestVault
|
||||
func TestPromoteVersionCommand(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
stateDir := "/test/state"
|
||||
stateDir := testStateDir
|
||||
cli := NewCLIInstanceWithStateDir(fs, stateDir)
|
||||
|
||||
// Set up vault with long-term key
|
||||
setupTestVault(t, fs, stateDir)
|
||||
setupTestVault(t, fs)
|
||||
|
||||
// Add a secret with multiple versions
|
||||
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("version-1"), false)
|
||||
addTestSecret(t, vlt, []byte("version-1"), false)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("version-2"), true)
|
||||
addTestSecret(t, vlt, []byte("version-2"), true)
|
||||
|
||||
// Get versions
|
||||
vaultDir, _ := vlt.GetDirectory()
|
||||
@@ -175,6 +195,7 @@ func TestPromoteVersionCommand(t *testing.T) {
|
||||
|
||||
// Create a command for output capture
|
||||
cmd := newRootCmd()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetErr(&buf)
|
||||
@@ -195,22 +216,24 @@ func TestPromoteVersionCommand(t *testing.T) {
|
||||
assert.Equal(t, []byte("version-1"), value)
|
||||
}
|
||||
|
||||
//nolint:paralleltest // uses t.Setenv via setupTestVault
|
||||
func TestPromoteNonExistentVersion(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
stateDir := "/test/state"
|
||||
stateDir := testStateDir
|
||||
cli := NewCLIInstanceWithStateDir(fs, stateDir)
|
||||
|
||||
// Set up vault with long-term key
|
||||
setupTestVault(t, fs, stateDir)
|
||||
setupTestVault(t, fs)
|
||||
|
||||
// Add a secret
|
||||
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("value"), false)
|
||||
addTestSecret(t, vlt, []byte("value"), false)
|
||||
|
||||
// Create a command for output capture
|
||||
cmd := newRootCmd()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetErr(&buf)
|
||||
@@ -221,23 +244,24 @@ func TestPromoteNonExistentVersion(t *testing.T) {
|
||||
assert.Contains(t, err.Error(), "not found")
|
||||
}
|
||||
|
||||
//nolint:paralleltest // uses t.Setenv via setupTestVault
|
||||
func TestGetSecretWithVersion(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
stateDir := "/test/state"
|
||||
stateDir := testStateDir
|
||||
cli := NewCLIInstanceWithStateDir(fs, stateDir)
|
||||
|
||||
// Set up vault with long-term key
|
||||
setupTestVault(t, fs, stateDir)
|
||||
setupTestVault(t, fs)
|
||||
|
||||
// Add a secret with multiple versions
|
||||
vlt, err := vault.GetCurrentVault(fs, stateDir)
|
||||
require.NoError(t, err)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("version-1"), false)
|
||||
addTestSecret(t, vlt, []byte("version-1"), false)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
addTestSecret(t, vlt, "test/secret", []byte("version-2"), true)
|
||||
addTestSecret(t, vlt, []byte("version-2"), true)
|
||||
|
||||
// Get versions
|
||||
vaultDir, _ := vlt.GetDirectory()
|
||||
@@ -248,6 +272,7 @@ func TestGetSecretWithVersion(t *testing.T) {
|
||||
|
||||
// Create a command for output capture
|
||||
cmd := newRootCmd()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
|
||||
@@ -258,18 +283,21 @@ func TestGetSecretWithVersion(t *testing.T) {
|
||||
|
||||
// Test getting specific version
|
||||
buf.Reset()
|
||||
|
||||
firstVersion := versions[1] // Older version
|
||||
err = cli.GetSecretWithVersion(cmd, "test/secret", firstVersion)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "version-1", buf.String())
|
||||
}
|
||||
|
||||
//nolint:paralleltest // reads process environment to determine the state dir
|
||||
func TestVersionCommandStructure(t *testing.T) {
|
||||
// Test that version commands are properly structured
|
||||
cli, err := NewCLIInstance()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to initialize CLI: %v", err)
|
||||
}
|
||||
|
||||
cmd := VersionCommands(cli)
|
||||
|
||||
assert.Equal(t, "version", cmd.Use)
|
||||
@@ -285,13 +313,14 @@ func TestVersionCommandStructure(t *testing.T) {
|
||||
assert.Equal(t, "Promote a specific version to current", promoteCmd.Short)
|
||||
}
|
||||
|
||||
//nolint:paralleltest // uses t.Setenv via setupTestVault
|
||||
func TestListVersionsEmptyOutput(t *testing.T) {
|
||||
fs := afero.NewMemMapFs()
|
||||
stateDir := "/test/state"
|
||||
stateDir := testStateDir
|
||||
cli := NewCLIInstanceWithStateDir(fs, stateDir)
|
||||
|
||||
// Set up vault with long-term key
|
||||
setupTestVault(t, fs, stateDir)
|
||||
setupTestVault(t, fs)
|
||||
|
||||
// Create a secret directory without versions (edge case)
|
||||
vaultDir := stateDir + "/vaults.d/default"
|
||||
@@ -301,6 +330,7 @@ func TestListVersionsEmptyOutput(t *testing.T) {
|
||||
|
||||
// Create a command for output capture
|
||||
cmd := newRootCmd()
|
||||
|
||||
var buf bytes.Buffer
|
||||
cmd.SetOut(&buf)
|
||||
cmd.SetErr(&buf)
|
||||
|
||||
Reference in New Issue
Block a user