Skip to content

Commit 6b1bf3c

Browse files
committed
merge: resolve conflicts with main
2 parents 4613639 + 05297c1 commit 6b1bf3c

60 files changed

Lines changed: 1830 additions & 1067 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docker.yml

Lines changed: 294 additions & 158 deletions
Large diffs are not rendered by default.

.github/workflows/install-script-tests.yml

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@ on:
77
- '.github/workflows/install-script-tests.yml'
88
- 'bin/test_install_script.sh'
99
- 'bin/test_install_script_over_homebrew.sh'
10+
- 'npm/**'
11+
- '.goreleaser.yml'
12+
- 'scripts/npm-publish.sh'
1013
pull_request:
1114
paths:
1215
- 'install-cli.sh'
1316
- '.github/workflows/install-script-tests.yml'
1417
- 'bin/test_install_script.sh'
1518
- 'bin/test_install_script_over_homebrew.sh'
19+
- 'npm/**'
20+
- '.goreleaser.yml'
21+
- 'scripts/npm-publish.sh'
1622
workflow_dispatch:
23+
release:
24+
types: [published]
1725

1826
jobs:
1927
test-script:
@@ -63,4 +71,34 @@ jobs:
6371
shell: bash
6472
run: |
6573
chmod +x install-cli.sh
66-
bash bin/test_install_script_over_homebrew.sh --token ${{ secrets.GITHUB_TOKEN }}
74+
bash bin/test_install_script_over_homebrew.sh --token ${{ secrets.GITHUB_TOKEN }}
75+
76+
# Note: this job installs from the public npm registry, so on push/PR
77+
# it tests the currently published version — not the code being changed.
78+
# That still catches regressions. The release trigger is what tests new releases.
79+
test-npm:
80+
name: Test npm install on ${{ matrix.os }}
81+
runs-on: ${{ matrix.os }}
82+
strategy:
83+
matrix:
84+
os:
85+
- ubuntu-latest # linux/x64
86+
- ubuntu-24.04-arm # linux/arm64
87+
- macos-latest # darwin/arm64
88+
- windows-latest # win32/x64
89+
- windows-11-arm # win32/arm64
90+
91+
steps:
92+
- name: Install @kosli/cli via npm
93+
shell: bash
94+
run: |
95+
TAG="${{ github.event.release.tag_name }}"
96+
if [[ "${{ github.event_name }}" == "release" && "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
97+
npm install -g @kosli/cli@latest
98+
else
99+
npm install -g @kosli/cli@snapshot
100+
fi
101+
102+
- name: Verify kosli binary works
103+
shell: bash
104+
run: kosli version

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ jobs:
109109
uses: ./.github/workflows/docker.yml
110110
with:
111111
tag: ${{ needs.pre-build.outputs.tag }}
112-
platforms: linux/amd64
112+
platforms: linux/amd64,linux/arm64
113113
flow_name: cli
114114
trail_name: ${{ needs.pre-build.outputs.trail_name }}
115115
kosli_org: kosli-public
@@ -144,4 +144,4 @@ jobs:
144144
uses: kosli-dev/reusable-actions/.github/actions/send-ci-failure-slack-message@main
145145
with:
146146
slack_url: ${{ secrets.MERKELY_SLACK_CI_FAILURES_WEBHOOK }}
147-
github_token: ${{ secrets.GITHUB_TOKEN }}
147+
github_token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/release.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,17 @@ jobs:
149149
- name: Run GoReleaser
150150
uses: goreleaser/goreleaser-action@v7
151151
with:
152+
distribution: goreleaser-pro
152153
version: '~> v2' # latest
153154
args: release --clean ${{ steps.get-tag-notes.outputs.args }}
154155
env:
155156
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
156157
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
158+
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
159+
GORELEASER_KEY: ${{ secrets.KOSLI_GORELEASERPRO }}
160+
161+
- name: Copy npm packages into dist for provenance
162+
run: find npm -name "*.tgz" -exec cp {} dist/ \;
157163

158164
- uses: actions/upload-artifact@v7
159165
with:
@@ -164,7 +170,7 @@ jobs:
164170
- name: Prepare artifacts list
165171
id: prepare-artifacts-list
166172
run: |
167-
ARTIFACTS=$(jq '[reduce .[] as $item (
173+
GORELEASER_ARTIFACTS=$(jq '[reduce .[] as $item (
168174
[];
169175
if ($item.type == "Archive") then
170176
. + [{ template_name: ($item.goos + "-" + $item.goarch), path: $item.path }]
@@ -175,6 +181,18 @@ jobs:
175181
end
176182
)][]' dist/artifacts.json)
177183
184+
NPM_ARTIFACTS=$(find dist -maxdepth 1 -name "*.tgz" -printf '%f\n' \
185+
| jq -R '{
186+
template_name: ("npm-" + sub("-[0-9]+\\.[0-9]+\\.[0-9]+.*\\.tgz$"; "")),
187+
path: ("dist/" + .)
188+
}' \
189+
| jq -s '.')
190+
191+
ARTIFACTS=$(jq -n \
192+
--argjson g "$GORELEASER_ARTIFACTS" \
193+
--argjson n "$NPM_ARTIFACTS" \
194+
'$g + $n')
195+
178196
echo "artifacts<<nEOFn" >> $GITHUB_OUTPUT
179197
echo "${ARTIFACTS}" >> $GITHUB_OUTPUT
180198
echo "nEOFn" >> $GITHUB_OUTPUT

.github/workflows/test.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ jobs:
163163
INTEGRATION_TEST_AZURE_CLIENT_SECRET: ${{ secrets.azure_client_secret }}
164164
INTEGRATION_TEST_AZURE_CLIENT_ID: ${{ secrets.azure_client_id }}
165165
KOSLI_SONAR_API_TOKEN: ${{ secrets.sonarqube_token }}
166-
DOCKER_API_VERSION: "1.45"
167166
KOSLI_API_TOKEN_PROD: ${{ secrets.kosli_querying_api_token }}
168167
run: |
169168
# some tests use git operations, therefore the git author on the CI VM needs to be set
@@ -273,4 +272,3 @@ jobs:
273272
--trail ${{ inputs.TRAIL_NAME }}
274273
--scan-results snyk-dependency.json
275274
--org ${{ inputs.KOSLI_ORG }}
276-

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ docs.kosli.com/resources/_gen/*
1717
docs.kosli.com/content/client_reference/kosli*
1818
docs.kosli.com/public/
1919
docs.kosli.com/.netlify
20+
npm/cli*/bin/*
21+
npm/*/kosli*.tgz
2022
*.tar.gz
2123
*~
2224
/.idea

.goreleaser.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ project_name: kosli
33
before:
44
hooks:
55
- go mod tidy
6+
- rm -rf npm/cli-*/bin
7+
- find npm -name "*.tgz" -delete
68
builds:
79
- id: kosli
810
binary: kosli
@@ -27,6 +29,19 @@ builds:
2729
- goos: windows
2830
goarch: arm
2931
main: ./cmd/kosli/
32+
hooks:
33+
post:
34+
- cmd: >-
35+
bash -c '
36+
OS="{{ .Os }}";
37+
ARCH="{{ .Arch }}";
38+
[ "$OS" = "windows" ] && OS="win32";
39+
[ "$ARCH" = "amd64" ] && ARCH="x64";
40+
EXT="";
41+
[ "{{ .Os }}" = "windows" ] && EXT=".exe";
42+
mkdir -p npm/cli-${OS}-${ARCH}/bin &&
43+
cp "{{ .Path }}" npm/cli-${OS}-${ARCH}/bin/kosli${EXT} &&
44+
chmod +x npm/cli-${OS}-${ARCH}/bin/kosli${EXT}'
3045
3146
archives:
3247
-
@@ -37,11 +52,9 @@ archives:
3752
- goos: windows
3853
formats: [zip]
3954

40-
4155
# docs for nfpm can be found here: https://goreleaser.com/customization/nfpm/
4256
nfpms:
4357
- id: kosli
44-
4558
# You can change the file name of the package.
4659
#
4760
# Default:`{{ .PackageName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}`
@@ -83,6 +96,12 @@ nfpms:
8396
- src: dist/{{ .ProjectName }}_{{ .Os }}_{{ if .Amd64 }}{{ .Arch }}_v1{{ else if .Arm }}{{ .Arch }}_6{{ else if eq .Arch "arm64" }}{{ .Arch }}_v8.0{{ else }}{{ .Arch }}{{ end }}/kosli
8497
dst: /usr/local/bin/kosli
8598

99+
after:
100+
hooks:
101+
- cmd: bash scripts/npm-publish.sh "{{ .Version }}"{{ if or .IsSnapshot (not .IsRelease) }} --dry-run{{ end }}
102+
# after hooks suppresses output by default. You need to add output: true to the hook to see the script's messages.
103+
output: true
104+
86105
publishers:
87106
- name: fury.io
88107
# by specifying `packages` id here goreleaser will only use this publisher

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ setup_test_to_use_staging_server_image:
121121

122122
test_integration: deps vet ensure_network test_setup ## Run tests except the too slow ones
123123
@[ -e ~/.kosli.yml ] && mv ~/.kosli.yml ~/.kosli-renamed.yml || true
124-
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) -- --short -p=6 -coverprofile=cover.out ./...
124+
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) -- --short -p=8 -coverprofile=cover.out ./...
125125
@go tool cover -func=cover.out | grep total:
126126
@go tool cover -html=cover.out
127127
@[ -e ~/.kosli-renamed.yml ] && mv ~/.kosli-renamed.yml ~/.kosli.yml || true
@@ -130,14 +130,14 @@ test_integration: deps vet ensure_network test_setup ## Run tests except the too
130130
test_integration_full: deps vet ensure_network test_setup ## Run all tests
131131
@[ -e ~/.kosli.yml ] && mv ~/.kosli.yml ~/.kosli-renamed.yml || true
132132
@mkdir -p junit-test-results
133-
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) --junitfile junit-test-results/junit.xml -- -p=6 -coverprofile=cover.out ./...
133+
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) --junitfile junit-test-results/junit.xml -- -p=8 -coverprofile=cover.out ./...
134134
@go tool cover -func=cover.out
135135
@[ -e ~/.kosli-renamed.yml ] && mv ~/.kosli-renamed.yml ~/.kosli.yml || true
136136

137137

138138
test_integration_restart_server: test_setup_restart_server
139139
@[ -e ~/.kosli.yml ] && mv ~/.kosli.yml ~/.kosli-renamed.yml || true
140-
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) -- --short -p=6 -coverprofile=cover.out ./...
140+
@export KOSLI_TESTS=true $(FAKE_CI_ENV) && $(GOTESTSUM) -- --short -p=8 -coverprofile=cover.out ./...
141141
@go tool cover -html=cover.out
142142
@[ -e ~/.kosli-renamed.yml ] && mv ~/.kosli-renamed.yml ~/.kosli.yml || true
143143

TODO.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,23 @@
4444
- [x] Slice 5: Expression builder wizard
4545
- [x] Slice 6: API lookups for flows and custom attestation types
4646
- [x] Slice 7: Preview screen + polish
47+
48+
## kosli evaluate input
49+
50+
- [x] Slice 1: `evaluate input --input-file` with a file path
51+
- [x] Slice 2: stdin support (omit --input-file to read stdin; `-` not supported by cobra)
52+
- [x] Slice 3: help text and examples
53+
- [x] Slice 4: PR review feedback
54+
- [x] Remove "using OPA" from all evaluate command long descriptions
55+
- [x] Add test cases for policy validation errors (missing package policy, missing allow rule, deny without violations)
56+
- [x] Update help text examples with fixture-capture workflow
57+
- [x] Refactor: use `cmd.InOrStdin()` for testable stdin
58+
- [x] Refactor: embed `commonEvaluateOptions` to remove flag duplication
59+
- [x] Slice 5: Detect terminal stdin and error when no input is piped
60+
61+
## Add `--params` flag to `kosli evaluate` commands
62+
63+
- [x] Slice 1: `evaluate.Evaluate()` accepts params, passes via OPA data store
64+
- [x] Slice 2: Add `--params` flag across all three commands
65+
- [x] Slice 3: Show params in `--show-input` output
66+
- [x] Slice 4: Update help text and examples

cmd/kosli/evaluate.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,23 @@ import (
66
"github.com/spf13/cobra"
77
)
88

9-
const evaluateShortDesc = `Evaluate Kosli trail data against OPA/Rego policies.`
9+
const evaluateShortDesc = `Evaluate data against Rego policies.`
1010

1111
// Backtick breaks (`"` + "`x`" + `"`) are needed to embed markdown
1212
// inline code spans inside raw string literals.
1313
const evaluateLongDesc = evaluateShortDesc + `
14-
Fetch trail data from Kosli and evaluate it against custom policies written
15-
in Rego, the policy language used by Open Policy Agent (OPA).
14+
Evaluate trail data or local JSON input against custom Rego policies.
15+
16+
Use ` + "`evaluate trail`" + ` or ` + "`evaluate trails`" + ` to fetch data from Kosli and evaluate it.
17+
Use ` + "`evaluate input`" + ` to evaluate a local JSON file or stdin without any API calls.
18+
1619
The policy must use ` + "`package policy`" + ` and define an ` + "`allow`" + ` rule.
1720
An optional ` + "`violations`" + ` rule (a set of strings) can provide human-readable denial reasons.
18-
The command exits with code 0 when allowed and code 1 when denied.`
21+
The command exits with code 0 when allowed and code 1 when denied.
22+
23+
Use ` + "`--params`" + ` to pass configuration data (thresholds, expected counts, etc.)
24+
to your policy. Params are available as ` + "`data.params`" + ` in Rego, keeping policy
25+
logic reusable across environments with different tolerances.`
1926

2027
func newEvaluateCmd(out io.Writer) *cobra.Command {
2128
cmd := &cobra.Command{
@@ -28,6 +35,7 @@ func newEvaluateCmd(out io.Writer) *cobra.Command {
2835
cmd.AddCommand(
2936
newEvaluateTrailCmd(out),
3037
newEvaluateTrailsCmd(out),
38+
newEvaluateInputCmd(out),
3139
)
3240

3341
return cmd

0 commit comments

Comments
 (0)