Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .claude/skills/new-command/references/archetype-read.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Read whichever canonical file matches and adapt.
**`run` method**
- Build the base URL into a `base` variable (not `url` — `listArtifacts.go` does this so the `net/url` package stays in scope), then append query params via `url.Values{}` and `params.Encode()`.
- Same `GET` + `output.FormattedPrint` pattern as read-single.
- The `print<Noun>sAsTable` helper unmarshals to a `[]map[string]interface{}` and handles the empty-list case with `logger.Info("No <nouns> were found.")`.
- The `print<Noun>sAsTable` helper unmarshals to a `[]map[string]any` and handles the empty-list case with `logger.Info("No <nouns> were found.")`.

**`RunE` signature**
- `return o.run(out)` (no `args` needed when there are no positional args).
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ jobs:
uses: golangci/golangci-lint-action@v9
with:
version: latest
args: --timeout=5m -v

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.

How come this was removed?

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.

Is it intentional as it's not a part of the PR description?

args: -v

- name: Test the server image lookup
run: ./hack/test-get-server-image.sh
Expand Down
19 changes: 18 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
version: "2"

run:
timeout: 5m # Set the maximum time for the analysis run
Comment thread
claude[bot] marked this conversation as resolved.

linters:
enable:
- forbidigo
- forbidigo # Forbid usage of certain Go constructs

settings:
forbidigo:
analyze-types: true
Expand All @@ -11,3 +15,16 @@ linters:
msg: "binary.NativeEndian is not portable; s390x is big-endian. Use binary.BigEndian or binary.LittleEndian explicitly."
- pattern: '^unsafe\.Pointer$'
msg: "unsafe.Pointer byte reinterpretation is endian-sensitive on s390x. Prefer encoding/binary, or add //nolint:forbidigo with justification."

formatters:
enable:
- gofmt # Check code formatting

settings:
gofmt:
# Apply the rewrite rules to the source before reformatting.
# https://pkg.go.dev/cmd/gofmt
# Default: []
rewrite-rules:
- pattern: 'interface{}'
replacement: 'any'
Comment thread
claude[bot] marked this conversation as resolved.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ ldflags: ## Print ldflags
@echo $(LDFLAGS)

fmt: ## Reformat package sources
@go fmt ./...
# Mirrors the gofmt rewrite rule in .golangci.yml so fmt can fix what lint rejects.
# gofmt is used directly because golangci-lint is not available where `make build` runs (Dockerfile).
@gofmt -l -w -r 'interface{} -> any' $$(go list -f '{{.Dir}}' ./...)

ensure_golangci-lint:
@if command -v brew >/dev/null 2>&1; then \
Expand All @@ -77,7 +79,7 @@ ensure_golangci-lint:
fi

lint: deps vet ensure_golangci-lint ## Run linting
@golangci-lint run --timeout=5m --color always -v ./...
@golangci-lint run --color always -v ./...

vet: fmt ## Run Go vet
@go vet ./...
Expand Down
2 changes: 1 addition & 1 deletion cmd/kosli/apiKey.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func printApiKeyMetadataAsTable(raw string, out io.Writer, page int) error {

// optionalTimestamp formats an epoch timestamp, returning "N/A" when it is
// unset (nil, or a zero value meaning "never"/"not set").
func optionalTimestamp(epoch interface{}) (string, error) {
func optionalTimestamp(epoch any) (string, error) {
switch v := epoch.(type) {
case nil:
return "N/A", nil
Expand Down
32 changes: 16 additions & 16 deletions cmd/kosli/assertArtifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func (o *assertArtifactOptions) run(out io.Writer, args []string) error {
return err
}

var evaluationResult map[string]interface{}
var evaluationResult map[string]any
err = json.Unmarshal([]byte(response.Body), &evaluationResult)
if err != nil {
return err
Expand All @@ -182,7 +182,7 @@ func (o *assertArtifactOptions) run(out io.Writer, args []string) error {
}

func printAssertAsTable(raw string, out io.Writer, page int) error {
var evaluationResult map[string]interface{}
var evaluationResult map[string]any
err := json.Unmarshal([]byte(raw), &evaluationResult)
if err != nil {
return err
Expand All @@ -201,29 +201,29 @@ func printAssertAsTable(raw string, out io.Writer, page int) error {
logger.Info("Environment: %v", evaluationResult["environment"].(string))
}
logger.Info("%-32v %-30v", "Policy-name", "status")
policyEvaluations := evaluationResult["policy_evaluations"].([]interface{})
policyEvaluations := evaluationResult["policy_evaluations"].([]any)
for _, item := range policyEvaluations {
policyEvaluation := item.(map[string]interface{})
policyEvaluation := item.(map[string]any)
policyName := policyEvaluation["policy_name"]
policyStatus := policyEvaluation["status"]
logger.Info(" %-32v %-30v", policyName, policyStatus)
if policyStatus != "COMPLIANT" {
ruleEvaluations := policyEvaluation["rule_evaluations"].([]interface{})
ruleEvaluations := policyEvaluation["rule_evaluations"].([]any)
var failures []string
for _, item2 := range ruleEvaluations {
ruleEvaluation := item2.(map[string]interface{})
ruleEvaluation := item2.(map[string]any)
ignored := ruleEvaluation["ignored"].(bool)
satisfied, _ := ruleEvaluation["satisfied"].(bool)
if !ignored && !satisfied {
rule := ruleEvaluation["rule"].(map[string]interface{})
resolutions := ruleEvaluation["resolutions"].([]interface{})
rule := ruleEvaluation["rule"].(map[string]any)
resolutions := ruleEvaluation["resolutions"].([]any)
for _, item3 := range resolutions {
resolution := item3.(map[string]interface{})
resolution := item3.(map[string]any)
resolutionType := resolution["type"].(string)
ruleDefinition := rule["definition"].(map[string]interface{})
ruleDefinition := rule["definition"].(map[string]any)
attestationName := ruleDefinition["name"]
attestationType := ruleDefinition["type"]
context, _ := resolution["context"].(map[string]interface{})
context, _ := resolution["context"].(map[string]any)
forControl, _ := context["for_control"].(string)
switch resolutionType {
case "legacy_flow":
Expand Down Expand Up @@ -254,19 +254,19 @@ func printAssertAsTable(raw string, out io.Writer, page int) error {
logger.Info("")
}

flows := evaluationResult["flows"].([]interface{})
flows := evaluationResult["flows"].([]any)
for _, item := range flows {
item := item.(map[string]interface{})
item := item.(map[string]any)
flow := item["flow"].(string)
trail, _ := item["trail"].(string)
complianceStatus, _ := item["compliance_status"].(map[string]interface{})
attestationsStatuses, _ := complianceStatus["attestations_statuses"].([]interface{})
complianceStatus, _ := item["compliance_status"].(map[string]any)
attestationsStatuses, _ := complianceStatus["attestations_statuses"].([]any)

logger.Info("Flow: %v\n Trail: %v", flow, trail)
logger.Info(" %-32v %-30v %-15v %-10v", "Attestation-name", "type", "status", "compliant")

for _, item := range attestationsStatuses {
attestation := item.(map[string]interface{})
attestation := item.(map[string]any)
name := attestation["attestation_name"]
attType := attestation["attestation_type"]
status := attestation["status"]
Expand Down
2 changes: 1 addition & 1 deletion cmd/kosli/assertSnapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func run(out io.Writer, args []string) error {
return err
}

var environmentData map[string]interface{}
var environmentData map[string]any
err = json.Unmarshal([]byte(response.Body), &environmentData)
if err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions cmd/kosli/attestCustom.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (

type CustomAttestationPayload struct {
*CommonAttestationPayload
TypeName string `json:"type_name"`
AttestationData interface{} `json:"attestation_data"`
TypeName string `json:"type_name"`
AttestationData any `json:"attestation_data"`
}

type attestCustomOptions struct {
Expand Down
10 changes: 5 additions & 5 deletions cmd/kosli/attestation.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type CommonAttestationPayload struct {
TargetArtifacts []string `json:"target_artifacts,omitempty"`
ExternalURLs map[string]*URLInfo `json:"external_urls,omitempty"`
OriginURL string `json:"origin_url,omitempty"`
UserData interface{} `json:"user_data,omitempty"`
UserData any `json:"user_data,omitempty"`
Description string `json:"description,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
}
Expand Down Expand Up @@ -212,7 +212,7 @@ func processExternalURLs(externalURLs, externalFingerprints map[string]string) (
return processedExternalURLs, nil
}

func prepareAttestationForm(payload interface{}, evidencePaths []string) ([]requests.FormItem, bool, string, error) {
func prepareAttestationForm(payload any, evidencePaths []string) ([]requests.FormItem, bool, string, error) {
form, cleanupNeeded, evidencePath, err := newAttestationForm(payload, evidencePaths)
if err != nil {
return []requests.FormItem{}, cleanupNeeded, evidencePath, err
Expand All @@ -235,7 +235,7 @@ func parseAttestationNameTemplate(template string) (string, string, error) {

// newAttestationForm constructs a list of FormItems for an attestation
// form submission.
func newAttestationForm(payload interface{}, attachments []string) (
func newAttestationForm(payload any, attachments []string) (
[]requests.FormItem, bool, string, error,
) {
form := []requests.FormItem{
Expand Down Expand Up @@ -314,9 +314,9 @@ func getGitRepoInfoFromBitbucket() *gitview.GitRepoInfo {
workspace = ""
}

var additionalInfo map[string]interface{}
var additionalInfo map[string]any
if projectKey := os.Getenv("BITBUCKET_PROJECT_KEY"); projectKey != "" {
additionalInfo = map[string]interface{}{"project_key": projectKey}
additionalInfo = map[string]any{"project_key": projectKey}
}

return &gitview.GitRepoInfo{
Expand Down
12 changes: 6 additions & 6 deletions cmd/kosli/attestation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestMergeGitRepoInfo(t *testing.T) {
wantURL string
wantProvider string
wantNamespacePath []string
wantAdditionalInfo map[string]interface{}
wantAdditionalInfo map[string]any
}{
{
name: "nil when both ID and Name are empty",
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestMergeGitRepoInfo(t *testing.T) {
name: "explicit --repository override clears stale CI-detected NamespacePath/AdditionalInfo",
base: &gitview.GitRepoInfo{
ID: "repo-id", Name: "MyOrg/Payment/my-repo", URL: "https://dev.azure.com/MyOrg/Payment/_git/my-repo",
NamespacePath: []string{"MyOrg", "Payment"}, AdditionalInfo: map[string]interface{}{"project_key": "PAY"},
NamespacePath: []string{"MyOrg", "Payment"}, AdditionalInfo: map[string]any{"project_key": "PAY"},
},
repoName: "my-fork/repo",
repoProvider: "github",
Expand All @@ -130,15 +130,15 @@ func TestMergeGitRepoInfo(t *testing.T) {
name: "CI-detected NamespacePath/AdditionalInfo are preserved when --repository is not set explicitly",
base: &gitview.GitRepoInfo{
ID: "repo-id", Name: "MyOrg/Payment/my-repo", URL: "https://dev.azure.com/MyOrg/Payment/_git/my-repo",
NamespacePath: []string{"MyOrg", "Payment"}, AdditionalInfo: map[string]interface{}{"project_key": "PAY"},
NamespacePath: []string{"MyOrg", "Payment"}, AdditionalInfo: map[string]any{"project_key": "PAY"},
},
repoNameExplicit: false,
wantNil: false,
wantID: "repo-id",
wantName: "MyOrg/Payment/my-repo",
wantURL: "https://dev.azure.com/MyOrg/Payment/_git/my-repo",
wantNamespacePath: []string{"MyOrg", "Payment"},
wantAdditionalInfo: map[string]interface{}{"project_key": "PAY"},
wantAdditionalInfo: map[string]any{"project_key": "PAY"},
},
{
name: "flag name applied when base has no name even if not explicit",
Expand Down Expand Up @@ -440,14 +440,14 @@ func TestGetGitRepoInfoFromBitbucket(t *testing.T) {
bitbucketRepoFullName string
bitbucketProjectKey string
wantNamespacePath []string
wantAdditionalInfo map[string]interface{}
wantAdditionalInfo map[string]any
}{
{
name: "with project key",
bitbucketRepoFullName: "myteam/my-repo",
bitbucketProjectKey: "PROJ",
wantNamespacePath: []string{"myteam"},
wantAdditionalInfo: map[string]interface{}{"project_key": "PROJ"},
wantAdditionalInfo: map[string]any{"project_key": "PROJ"},
},
{
name: "without project key",
Expand Down
2 changes: 1 addition & 1 deletion cmd/kosli/beginTrail.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type beginTrailOptions struct {
type TrailPayload struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
UserData interface{} `json:"user_data,omitempty"`
UserData any `json:"user_data,omitempty"`
Commit *gitview.BasicCommitInfo `json:"git_commit_info,omitempty"`
GitRepoInfo *gitview.GitRepoInfo `json:"repo_info,omitempty"`
ExternalURLs map[string]*URLInfo `json:"external_urls,omitempty"`
Expand Down
14 changes: 7 additions & 7 deletions cmd/kosli/beginTrailPayload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestTrailPayloadOmitsUnsetDescription(t *testing.T) {
body, err := json.Marshal(TrailPayload{Name: "test-123"})
require.NoError(t, err)

var got map[string]interface{}
var got map[string]any
require.NoError(t, json.Unmarshal(body, &got))
require.NotContains(t, got, "description")
}
Expand All @@ -24,7 +24,7 @@ func TestTrailPayloadOmitsUnsetUserData(t *testing.T) {
body, err := json.Marshal(TrailPayload{Name: "test-123"})
require.NoError(t, err)

var got map[string]interface{}
var got map[string]any
require.NoError(t, json.Unmarshal(body, &got))
require.NotContains(t, got, "user_data")
}
Expand All @@ -40,9 +40,9 @@ func TestTrailPayloadKeepsAnExplicitlyEmptyUserData(t *testing.T) {
body, err := json.Marshal(TrailPayload{Name: "test-123", UserData: userData})
require.NoError(t, err)

var got map[string]interface{}
var got map[string]any
require.NoError(t, json.Unmarshal(body, &got))
require.Equal(t, map[string]interface{}{}, got["user_data"])
require.Equal(t, map[string]any{}, got["user_data"])
}

// omitempty must not swallow a value the user did give, so a payload carrying
Expand All @@ -51,14 +51,14 @@ func TestTrailPayloadKeepsSetDescriptionAndUserData(t *testing.T) {
payload := TrailPayload{
Name: "test-123",
Description: "the release trail",
UserData: map[string]interface{}{"release": "2.11.21"},
UserData: map[string]any{"release": "2.11.21"},
}

body, err := json.Marshal(payload)
require.NoError(t, err)

var got map[string]interface{}
var got map[string]any
require.NoError(t, json.Unmarshal(body, &got))
require.Equal(t, "the release trail", got["description"])
require.Equal(t, map[string]interface{}{"release": "2.11.21"}, got["user_data"])
require.Equal(t, map[string]any{"release": "2.11.21"}, got["user_data"])
}
8 changes: 4 additions & 4 deletions cmd/kosli/cli_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,9 +436,9 @@ func GetSha256Digest(artifactName string, o *fingerprintOptions, logger *log.Log
}

// LoadJsonData loads json data from a file
func LoadJsonData(filepath string) (interface{}, error) {
func LoadJsonData(filepath string) (any, error) {
var err error
var result interface{}
var result any
content := `{}`
if filepath != "" {
content, err = utils.LoadFileContent(filepath)
Expand All @@ -459,7 +459,7 @@ func LoadJsonData(filepath string) (interface{}, error) {

// LoadOptionalJsonData loads json data from a file, and returns nil when no
// file was given so that an omitempty field stays out of the payload.
func LoadOptionalJsonData(filepath string) (interface{}, error) {
func LoadOptionalJsonData(filepath string) (any, error) {
if filepath == "" {
return nil, nil
}
Expand Down Expand Up @@ -578,7 +578,7 @@ func tabFormattedPrint(out io.Writer, header []string, rows []string) {

// formattedTimestamp formats a float timestamp into something like "Mon, 22 Aug 2022 11:34:59 CEST • 10 days ago"
// time is formatted using RFC1123
func formattedTimestamp(timestamp interface{}, short bool) (string, error) {
func formattedTimestamp(timestamp any, short bool) (string, error) {
var intTimestamp int64
var shortFormat string
var unixTime time.Time
Expand Down
2 changes: 1 addition & 1 deletion cmd/kosli/cli_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ func (suite *CliUtilsTestSuite) TestConditionallyRequiredFlags() {
func (suite *CliUtilsTestSuite) TestFormattedTimestamp() {
tests := []struct {
name string
timestamp interface{}
timestamp any
short bool
expected string
wantErr bool
Expand Down
4 changes: 2 additions & 2 deletions cmd/kosli/createAttestationType.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ func (o *createAttestationTypeOptions) run(args []string) error {
return err
}

func prepareAttestationTypeForm(payload interface{}, schemaFilePath string) ([]requests.FormItem, error) {
func prepareAttestationTypeForm(payload any, schemaFilePath string) ([]requests.FormItem, error) {
form, err := newAttestationTypeForm(payload, schemaFilePath)
if err != nil {
return []requests.FormItem{}, err
Expand All @@ -253,7 +253,7 @@ func prepareAttestationTypeForm(payload interface{}, schemaFilePath string) ([]r

// newAttestationTypeForm constructs a list of FormItems for an attestation-type
// form submission.
func newAttestationTypeForm(payload interface{}, schemaFilePath string) (
func newAttestationTypeForm(payload any, schemaFilePath string) (
[]requests.FormItem, error,
) {
form := []requests.FormItem{
Expand Down
2 changes: 1 addition & 1 deletion cmd/kosli/createFlow.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ func injectArtifactIntoTemplateIfNotExisting(template []string) []string {

// newFlowForm constructs a list of FormItems for a flow with a template file
// form submission.
func newFlowForm(payload interface{}, templateFile string, templateRequired bool) ([]requests.FormItem, error) {
func newFlowForm(payload any, templateFile string, templateRequired bool) ([]requests.FormItem, error) {
if templateFile == "" && templateRequired {
return []requests.FormItem{}, fmt.Errorf("cannot create a flow form without a template file")
}
Expand Down
Loading
Loading