2025
v0.2.2 (2025-12-19)
Features
Checks can now be marked as not applicable to a component (for example, a Go-specific check on a repository with no Go code): calling the new
Check.skip(reason)method reports the check with the newskippedstatus (CheckStatus.SKIPPED) and discards any assertions recorded before the skip.
v0.2.1 (2025-11-06)
Features
CheckandNodegainget_value_or_default(path, default), which returns the given default when there is no value at the path — instead of raising an error or, while data collection is still in progress, marking the check pending.
v0.2.0 (2025-11-05)
Breaking changes
Node-based data access API
The SDK's data access layer is rebuilt around the new Node class, which represents a location in the component JSON and navigates relative to that location. Check.get_node(path) returns a Node; nodes expose get_value, get_all_values, exists, and get_node, with paths resolved relative to the node and data accessed lazily. Checks and nodes can also be iterated — lists yield child nodes, dicts yield keys — and items() yields key/child-node pairs.
Upgrading from 0.1.x requires policy changes:
ComponentDataandPathare removed. Build aNodeinstead —Node.from_bundle_file,Node.from_bundle_json,Node.from_component_json_file, orNode.from_component_json— and pass it toCheck(name, node=...). When no node is given, checks still load the component JSON automatically fromLUNAR_BUNDLE_PATH.check.get(path)is renamed tocheck.get_value(path), andcheck.get_all(path)tocheck.get_all_values(path). Both now default to., the current node's value.Paths use a strict JSON path grammar — dot segments (
.foo), bracketed keys (['foo-bar']), and array indexes ([0]) — that can be concatenated for relative navigation. General JSONPath expressions such as$roots, wildcards, and filters are no longer accepted. Because the SDK now parses paths itself, thejsonpath-ngdependency is gone andlunar-policyhas no runtime dependencies.CheckStatus.NO_DATAis renamed toCheckStatus.PENDING; policy code that references the old member must be updated. The status value reported in check results is stillno-data.
v0.1.7 (2025-10-01)
Improvements
lunar-policycan now be installed on Python 3.9 and newer; earlier releases required Python 3.13.
v0.1.6 (2025-08-20)
Breaking changes
Component data loaded with
ComponentData.from_fileorComponentData.from_jsonmust now include abundle_infokey, which carries the workflow-completion signal; Lunar-provided data includes it automatically, but hand-written fixtures used for local policy testing need to add it, andComponentData.from_component_jsonaccepts a new optionalbundle_infoargument.The
get_or_defaultandget_all_or_defaultmethods are removed; useexists()to probe for optional data, or catchNoDataErrorwhere a default value is genuinely wanted.
Features
The new
assert_exists(Path(path))assertion andexists(path)helper test whether a path is present in the component data;assert_existsrequires aPathobject, whileexistsaccepts a path string. Before all CI workflows for the commit have finished, a missing path keeps the usualno-databehavior; afterward,assert_existsfails the check andexistsreturnsFalse.
Improvements
Missing data becomes conclusive once collectors finish
Checks now distinguish data that has not been collected yet from data that is conclusively absent. Lunar records in the component data whether all CI workflows for the commit have completed, and the SDK reads that signal whenever a queried path has no data.
While workflows are still running, missing data behaves as before: the check ends early and reports no-data, and Lunar re-evaluates the policy as more data is collected. Once all workflows have finished, missing data is no longer treated as pending: assert_exists fails the check, exists returns False, and other assertions or get calls that hit a missing path report an error instead of leaving the check no-data indefinitely.
NoDataErrorcan now be imported directly from the package root (from lunar_policy import NoDataError), for policies that handle missing data themselves.
Bug fixes
Result reporting is fixed for policy scripts that define more than one check: each check's results are now emitted on a separate line, so checks after the first are no longer misread.
v0.1.5 (2025-06-27)
Features
Policy scripts can now write ordinary log output to stdout: check results are emitted with the marker Lunar provides via
LUNAR_LOG_PREFIX, so the platform can separate result reporting from anything else the script prints and capture the rest as script logs; when the marker is not set, output is unchanged.
Bug fixes
The missing-data check status is now reported as
no-datainstead ofno_data, making the value consistent with the rest of Lunar; it previously surfaced asno_datain the checks SQL view.
v0.1.4 (2025-06-03)
Breaking changes
The
submit()method onCheckis removed — results are submitted automatically when thewithblock exits — andnameis now a read-only property; the previously publicdescriptionattribute is now internal.The
SnippetDataclass is renamed toComponentData, matching what it holds — the component JSON a policy evaluates; update imports and references, thefrom_file,from_json, andfrom_component_jsonconstructors are unchanged.Check.failure_reasonsnow returns a list of failure messages instead of a single comma-separated string.
Features
New
get_or_defaultandget_all_or_defaultmethods onCheckreturn a default value instead of ending the check asno_datawhen a path has no data.
Improvements
Unexpected exceptions inside a check now produce a distinct
errorcheck status instead of being recorded as an assertion failure, separating broken policy code from genuine policy violations; the new value is available asCheckStatus.ERROR.When a check ends early because data is missing, the recorded result now includes a message naming the path that had no data (for example,
No data found for .sbom).
v0.1.3 (2025-05-28)
Breaking changes
Explicit Path objects for component-data queries
Component-data lookups in assertions are now expressed with the new Path class, and assertions no longer guess whether a string argument is a JSON path: a plain string is always treated as a literal value.
Previously, any string beginning with . was interpreted as a path, which made it impossible to assert against literal values that merely look like paths. Path replaces the former JsonPathExpression class, and paths may now be written with an explicit $ root prefix (for example Path("$.readme.exists")); either way they are evaluated from the root of the component JSON. String arguments to get and get_all are still interpreted as paths.
The
assert_existsandassert_missingassertions are removed; assert on the value itself instead.A check now ends at the first missing-data access, recording a single
no_dataresult and skipping the rest of the block, instead of every assertion reportingno_dataindividually; accordingly,getandget_allraiseNoDataErrorwhen a path has no data — handled automatically by theCheckcontext manager — instead of returningNoneor an empty list.
Features
The new
fail()method onCheckexplicitly fails a check with an optional failure message, for conditions the built-in assertions cannot express.New
statusandfailure_reasonsproperties onCheckexpose the outcome of a check — useful for unit-testing policies; statuses are values of theCheckStatusenum, which replacesOpResult.The new
SnippetData.from_component_jsonconstructor loads a plain component JSON document as both the merged view and a single delta, so a policy can be exercised against a raw component JSON.
Improvements
An unhandled exception inside a
with Check(...)block is now recorded on the check as a failed assertion carrying the error message, so the failure shows up in the check results rather than only in the script's output; the exception still propagates after the check is submitted.
Bug fixes
lunar_policy.__version__now reports the package version; it previously reported0.0.1regardless of the installed release.
v0.1.2 (2025-05-20)
Breaking changes
Package renamed to lunar-policy
The Policy Python SDK is now published on PyPI as lunar-policy, replacing the lunar-checks name; the package was originally published as lunar-snippets. Install it with pip install lunar-policy and import it as lunar_policy:
Aside from the name, the package contents are identical to lunar-checks 0.1.1. Update policy dependencies and imports to the new name; the older package names no longer receive updates.
Last updated
