kosli evaluate commands let you evaluate Kosli trails against custom policies written in . This is useful for enforcing rules like “every artifact must have an approved pull request” or “all security scans must pass”, and for gating deployments in CI/CD pipelines based on those rules.
In this tutorial, we’ll write a policy that checks whether pull requests on a trail have been approved, then evaluate it against real trails in public Kosli orgs.
Prerequisites
To follow this tutorial, you need to:
- Install Kosli CLI.
- Get a Kosli API token.
-
Set the
KOSLI_API_TOKENenvironment variable to your token:
You don’t need OPA installed — the Kosli CLI has a built-in Rego evaluator. You just need to write a
.rego policy file.Write a policy
Create a file called Let’s break down what this policy does:
pr-approved.rego with the following content:pr-approved.rego
package policy— every evaluate policy must use thepolicypackage.import rego.v1— use Rego v1 syntax (theif/containskeywords).default allow = false— trails are denied unless explicitly allowed.violations— a set of messages describing why the policy failed. The rule iterates over trails, then over pull requests within thepull-requestattestation, looking for PRs whereapproversis empty.allow— trails are allowed only when there are no violations.
See the Rego Policy reference for the full policy contract, input data shape, and exit code behaviour.
Evaluate multiple trails
Let’s evaluate several trails from the public The cyber-dojo project doesn’t require PR approvals, so you’ll see violations:Now try the
cyber-dojo org against our policy. The kosli evaluate trails command fetches trail data from Kosli and passes it to the policy as input.trails:kosli-public org, where PRs do have approvers:Evaluate a single trail
The This policy iterates over every artifact in the trail, looks up its The trail has zero high-severity vulnerabilities, so the policy allows it.
kosli evaluate trail (singular) command evaluates facts within a single trail, which is a different use case from comparing across multiple trails. For example, you might check that a snyk container scan found no high-severity vulnerabilities.Save this as snyk-no-high-vulns.rego:snyk-container-scan attestation, and checks whether any result has a non-zero high_count.Use --attestations to enrich only the snyk data (faster than fetching all attestation details).
The value uses the format artifact-name.attestation-type. Here, dashboard is the artifact name and snyk-container-scan is the attestation name:The
input.trail / input.trails distinction and the full input data shape are documented in the Rego Policy reference.Explore the policy input with --show-input
When writing policies, it helps to see exactly what data is available. Use This outputs the evaluation result along with the complete
--show-input combined with --output json to see the full input that gets passed to the policy:input object. You can pipe it through jq to explore the structure:Use the
--attestations flag to limit which attestations are enriched with full detail. The flag filters by attestation name (not type). For example, --attestations pull-request fetches only details for attestations named pull-request, which speeds up evaluation and reduces noise when exploring the input.Use in CI/CD
The This pattern lets you enforce custom compliance rules as part of your delivery pipeline, using the same trail data that Kosli already collects.
kosli evaluate commands exit with 0 on allow and 1 on deny or error — making them straightforward to use as pipeline gates. See the Rego Policy reference for details on distinguishing denial from command failure.Record the evaluation
After evaluating a trail, you can record the result as an attestation. This creates an audit record in Kosli that captures the policy, the full evaluation report, and any violations.This step requires write access to your Kosli org. The examples below use variables you’d set in your CI/CD pipeline. In your own pipeline you’d use your own policy file — here we use This creates a generic attestation on the trail with:
my-policy.rego as a placeholder:--compliantset based on whether the policy allowed or denied — read directly from the JSON report rather than relying on the exit code, which avoids issues withset -ein CI environments like GitHub Actions--attachmentscontaining the Rego policy (for reproducibility) and the full JSON evaluation report (including the input data the policy evaluated)--user-datacontaining the violations, which appear in the Kosli UI as structured metadata on the attestation
What you’ve accomplished
You have written OPA/Rego policies and evaluated Kosli trails against them, both across multiple trails and within a single trail. You’ve also recorded evaluation results as attestations, creating a tamper-proof audit record of every policy decision linked to a specific trail. From here you can:- Explore evaluated trails in the Kosli app
- Gate deployments in CI/CD pipelines using
kosli evaluate trailexit codes - Extend your policies to check other attestation types. See
kosli evaluate trailandkosli evaluate trailsfor the full flag reference