Imported from fujiwara/jsonnet-armed (
AGENTS.md). Install upstream withnpx skills add fujiwara/jsonnet-armed. Copyright stays with the author.
AGENTS.md
This file provides guidance to AI coding agents when working with code in this repository.
Project Overview
jsonnet-armed is a Go CLI tool that extends the standard Jsonnet evaluator with native functions useful for infrastructure/DevOps configuration (env vars, hashing, HTTP, DNS, exec, regex, jq, UUID, x509, etc.). It evaluates Jsonnet files and outputs JSON.
Development Commands
make # Build binary
make test # Run all tests with -race
go test -v ./... # Run all tests (verbose)
go test -v ./functions # Run only unit tests for native functions
go test -v -run TestName # Run a single test by name
go test -v -run TestName ./functions # Run a single function test
make install # Install binary
go fmt ./... # Format code (run before every commit)
go mod tidy # Clean dependencies (run after adding deps)
Architecture
Package Structure
armed(root package): CLI lifecycle, Jsonnet VM orchestration, caching, output handling. Key types:CLI(kong-based),Cache,ArmedImporter.functionspackage: All native function implementations. No knowledge of thearmedpackage (one-way dependency).cmd/jsonnet-armed: Binary entry point with signal handling.
Execution Flow
cmd/main.go → armed.Run() → kong CLI parsing → cli.run() → cli.processRequest() → cli.evaluate() → creates jsonnet.VM, registers all native functions via functions.GenerateAllFunctions(ctx), sets ArmedImporter (provides virtual armed.libsonnet), evaluates Jsonnet.
Native Function Registration Pattern
Functions follow two patterns:
Static maps (context-independent) — most functions use this:
// In functions/<category>.go
var CategoryFunctions = map[string]*jsonnet.NativeFunction{
"func_name": {
Params: []ast.Identifier{"param1", "param2"},
Func: func(args []any) (any, error) { ... },
},
}
func init() { initializeFunctionMap(CategoryFunctions) } // sets Name from map key
Generator functions (context-dependent) — used by exec and http:
func GenerateExecFunctions(ctx context.Context) map[string]*jsonnet.NativeFunction { ... }
All function maps are aggregated in functions/armed.go:GenerateAllFunctions(). When adding a new category, add its map iteration there.
ArmedImporter
Custom Jsonnet importer that intercepts import 'armed.libsonnet' and dynamically generates a Jsonnet object mapping all function names to std.native() calls. Users can use either std.native("func") or (import 'armed.libsonnet').func.
Adding New Native Functions
- Create
functions/<category>.gowith exported map (e.g.,CategoryFunctions) - Use
init()to callinitializeFunctionMap() - Register in
functions/armed.go:GenerateAllFunctions() - All functions must return
(any, error)with JSON-compatible types (map[string]any,[]any, not typed maps/slices) - Add unit tests in
functions/<category>_test.go(packagefunctions_test, table-driven) - Add integration test case in
integration_test.go(packagearmed_test) - Create test fixtures in
testdata/if function reads files
Testing Conventions
- Table-driven tests with
[]struct{ name, args/jsonnet, expected, expectError } - Use
github.com/google/go-cmp/cmp.Difffor JSON structural comparison - Use
cli.SetWriter(&buf)to capture output in tests — never replaceos.Stdout - For non-deterministic outputs (UUIDs, timestamps): test format validity with regex, use validation placeholders like
<valid_uuid_v4>in integration tests - Unit test helpers in
functions/test_helpers_test.goprovidegetEnvFunction(),getHashFunction(), etc.
Pre-commit Checklist
go fmt ./...go mod tidygo test -v ./functions(unit tests)go test -v(integration tests)