Skip to content

Commit efcf325

Browse files
committed
green: evaluate trail/trails policy denial exits with code 1 (ErrCompliance)
- printEvaluateResultAsJson and printEvaluateResultAsTable now return ErrCompliance on policy denial so the process exits with code 1 - Add exitCodesEvaluate set (code 1: "Policy denied.") and register kosli evaluate trail and kosli evaluate trails in commandExitCodes - Add TestPolicyDenialIsErrCompliance covering both formatters for allow and deny cases
1 parent 30f5bc8 commit efcf325

3 files changed

Lines changed: 52 additions & 3 deletions

File tree

cmd/kosli/docs.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ var (
4747
{Code: 2, Meaning: "Kosli server is unreachable or down."},
4848
}
4949

50+
// exitCodesEvaluate applies to evaluate commands that run a policy and can signal policy denial.
51+
exitCodesEvaluate = []docgen.ExitCodeEntry{
52+
{Code: 0, Meaning: "No error (policy allowed)."},
53+
{Code: 1, Meaning: "Policy denied."},
54+
{Code: 2, Meaning: "Kosli server is unreachable or returned a server error."},
55+
{Code: 3, Meaning: "Invalid API token or unauthorized access."},
56+
{Code: 4, Meaning: "CLI usage error (e.g. missing or invalid flags)."},
57+
}
58+
5059
// exitCodesNoAPI applies to commands that do not call the Kosli API (version, completion, docs).
5160
exitCodesNoAPI = []docgen.ExitCodeEntry{
5261
{Code: 0, Meaning: "No error."},
@@ -72,6 +81,9 @@ var commandExitCodes = map[string][]docgen.ExitCodeEntry{
7281
"kosli attest pullrequest azure": exitCodesAttest,
7382
"kosli attest pullrequest bitbucket": exitCodesAttest,
7483
"kosli attest jira": exitCodesAttest,
84+
// evaluate commands — policy denial exits with code 1
85+
"kosli evaluate trail": exitCodesEvaluate,
86+
"kosli evaluate trails": exitCodesEvaluate,
7587
// non-API commands
7688
"kosli version": exitCodesNoAPI,
7789
"kosli completion": exitCodesNoAPI,

cmd/kosli/evaluateHelpers.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010

1111
"github.com/kosli-dev/cli/internal/evaluate"
12+
kosliErrors "github.com/kosli-dev/cli/internal/errors"
1213
"github.com/kosli-dev/cli/internal/output"
1314
"github.com/kosli-dev/cli/internal/requests"
1415
"github.com/spf13/cobra"
@@ -136,7 +137,7 @@ func printEvaluateResultAsJson(raw string, out io.Writer, _ int) error {
136137
return err
137138
}
138139
if allow, ok := result["allow"].(bool); ok && !allow {
139-
return fmt.Errorf("policy denied")
140+
return kosliErrors.NewErrCompliance("policy denied")
140141
}
141142
return nil
142143
}
@@ -167,8 +168,8 @@ func printEvaluateResultAsTable(raw string, out io.Writer, _ int) error {
167168
}
168169
}
169170
tabFormattedPrint(out, []string{}, rows)
170-
return fmt.Errorf("policy denied: %v", violations)
171+
return kosliErrors.NewErrCompliance(fmt.Sprintf("policy denied: %v", violations))
171172
}
172173
tabFormattedPrint(out, []string{}, rows)
173-
return fmt.Errorf("policy denied")
174+
return kosliErrors.NewErrCompliance("policy denied")
174175
}

cmd/kosli/evaluateHelpers_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"testing"
7+
8+
kosliErrors "github.com/kosli-dev/cli/internal/errors"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
func TestPolicyDenialIsErrCompliance(t *testing.T) {
13+
deniedJSON := `{"allow":false,"violations":["missing approval"]}`
14+
15+
t.Run("printEvaluateResultAsJson returns ErrCompliance on policy denial", func(t *testing.T) {
16+
err := printEvaluateResultAsJson(deniedJSON, &bytes.Buffer{}, 0)
17+
var ec *kosliErrors.ErrCompliance
18+
assert.True(t, errors.As(err, &ec), "expected ErrCompliance, got %T: %v", err, err)
19+
})
20+
21+
t.Run("printEvaluateResultAsTable returns ErrCompliance on policy denial", func(t *testing.T) {
22+
err := printEvaluateResultAsTable(deniedJSON, &bytes.Buffer{}, 0)
23+
var ec *kosliErrors.ErrCompliance
24+
assert.True(t, errors.As(err, &ec), "expected ErrCompliance, got %T: %v", err, err)
25+
})
26+
27+
t.Run("printEvaluateResultAsJson returns nil on policy allow", func(t *testing.T) {
28+
err := printEvaluateResultAsJson(`{"allow":true,"violations":[]}`, &bytes.Buffer{}, 0)
29+
assert.NoError(t, err)
30+
})
31+
32+
t.Run("printEvaluateResultAsTable returns nil on policy allow", func(t *testing.T) {
33+
err := printEvaluateResultAsTable(`{"allow":true,"violations":[]}`, &bytes.Buffer{}, 0)
34+
assert.NoError(t, err)
35+
})
36+
}

0 commit comments

Comments
 (0)