Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,26 @@ cfg := Config{Message: "Hello, {{ .name }}!"}

err := gomplate.Walk(map[string]any{"name": "world"}, &cfg)
// cfg.Message == "Hello, world!"

## CEL eval helper
Comment on lines +154 to +155
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Close the previous Go code fence before this new section.

The ## CEL eval helper heading is currently still inside the Go fenced block opened earlier, so the new docs will render as code instead of Markdown.

📝 Proposed fix
 err := gomplate.Walk(map[string]any{"name": "world"}, &cfg)
 // cfg.Message == "Hello, world!"
+
+```
 
 ## CEL eval helper
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@README.md` around lines 154 - 155, The README has an unclosed Go code fence
so the "## CEL eval helper" heading is rendered as code; close the open Go fence
(the ```go block started earlier) immediately before the "## CEL eval helper"
heading so the new section is treated as Markdown rather than code (i.e., insert
the matching closing triple-backtick right before the heading).


A small helper command is available at `cmd/ceval` to evaluate CEL expressions against an input YAML or JSON file.

Run it with:

```bash
go run ./cmd/ceval -f env.yaml -e "labels['a/b/c']"
```

Example input file:

```yaml
labels:
a/b/c: d
```

Output:

```text
d
```
95 changes: 95 additions & 0 deletions cmd/ceval/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package main

import (
"encoding/json"
"flag"
"fmt"
"io"
"os"

"github.com/flanksource/gomplate/v3"
"gopkg.in/yaml.v3"
)

func loadEnvironment(path string) (map[string]any, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("read env file %q: %w", path, err)
}

var env map[string]any
if err := json.Unmarshal(data, &env); err == nil && env != nil {
return env, nil
}
if err := yaml.Unmarshal(data, &env); err == nil && env != nil {
return env, nil
}

var generic any
if err := yaml.Unmarshal(data, &generic); err != nil {
return nil, fmt.Errorf("parse env file %q as yaml/json: %w", path, err)
}

return map[string]any{"data": generic}, nil
}

func printValue(w io.Writer, value any) error {
switch v := value.(type) {
case string:
_, err := fmt.Fprintln(w, v)
return err
default:
b, err := json.MarshalIndent(v, "", " ")
if err != nil {
_, err = fmt.Fprintln(w, value)
return err
}
_, err = fmt.Fprintln(w, string(b))
return err
}
}

func run(args []string, stdout, stderr io.Writer) int {
fs := flag.NewFlagSet("ceval", flag.ContinueOnError)
fs.SetOutput(stderr)

var file string
var expr string
fs.StringVar(&file, "f", "", "Path to env yaml/json file")
fs.StringVar(&file, "file", "", "Path to env yaml/json file")
fs.StringVar(&expr, "e", "", "CEL expression to evaluate")
fs.StringVar(&expr, "expr", "", "CEL expression to evaluate")

if err := fs.Parse(args); err != nil {
return 2
}

if file == "" || expr == "" {
_, _ = fmt.Fprintln(stderr, "usage: ceval -f env.yaml -e \"labels['a/b/c']\"")
fs.PrintDefaults()
return 2
}

env, err := loadEnvironment(file)
if err != nil {
_, _ = fmt.Fprintf(stderr, "error: %v\n", err)
return 1
}

out, err := gomplate.RunExpression(env, gomplate.Template{Expression: expr})
if err != nil {
_, _ = fmt.Fprintf(stderr, "error: %v\n", err)
return 1
}

if err := printValue(stdout, out); err != nil {
_, _ = fmt.Fprintf(stderr, "error: %v\n", err)
return 1
}

return 0
}

func main() {
os.Exit(run(os.Args[1:], os.Stdout, os.Stderr))
}
38 changes: 38 additions & 0 deletions cmd/ceval/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package main

import (
"bytes"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestLoadEnvironmentYAML(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "env.yaml")
require.NoError(t, os.WriteFile(path, []byte("labels:\n a/b/c: gg\n"), 0o644))

env, err := loadEnvironment(path)
require.NoError(t, err)

labels, ok := env["labels"].(map[string]any)
require.True(t, ok)
assert.Equal(t, "gg", labels["a/b/c"])
}

func TestRun(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "env.yaml")
require.NoError(t, os.WriteFile(path, []byte("labels:\n a/b/c: gg\n"), 0o644))

var stdout bytes.Buffer
var stderr bytes.Buffer
code := run([]string{"-f", path, "-e", "labels['a/b/c']"}, &stdout, &stderr)

assert.Equal(t, 0, code)
assert.Equal(t, "gg\n", stdout.String())
assert.Equal(t, "", stderr.String())
}
Loading