Skip to content

feat: Add CEL-based conditional function execution (#4388)#4391

Closed
SurbhiAgarwal1 wants to merge 61 commits intokptdev:mainfrom
SurbhiAgarwal1:feat/cel-conditional-execution
Closed

feat: Add CEL-based conditional function execution (#4388)#4391
SurbhiAgarwal1 wants to merge 61 commits intokptdev:mainfrom
SurbhiAgarwal1:feat/cel-conditional-execution

Conversation

@SurbhiAgarwal1
Copy link
Copy Markdown
Contributor

Implements #4388

Changes

  • Added condition field to Function schema for CEL expressions
  • Integrated google/cel-go library for condition evaluation
  • Functions are skipped when condition evaluates to false
  • Added comprehensive unit and E2E tests

Example Usage

pipeline:
  mutators:
  - image: gcr.io/kpt-fn/set-namespace:v0.4
    condition: "resources.exists(r, r.kind == 'ConfigMap' && r.metadata.name == 'env-config')"
    configMap:
      namespace: production

Copilot AI review requested due to automatic review settings February 14, 2026 17:56
@netlify
Copy link
Copy Markdown

netlify bot commented Feb 14, 2026

Deploy Preview for kptdocs ready!

Name Link
🔨 Latest commit 30d68a1
🔍 Latest deploy log https://app.netlify.com/projects/kptdocs/deploys/69d539230792db0008bbefe7
😎 Deploy Preview https://deploy-preview-4391--kptdocs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@SurbhiAgarwal1 SurbhiAgarwal1 force-pushed the feat/cel-conditional-execution branch from 32fe3c0 to 3d2bde5 Compare February 15, 2026 09:54
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Did you mean to post these files on the issue rather than on the PR? It looks like AI generated content.

Copy link
Copy Markdown
Contributor

@nagygergo nagygergo left a comment

Choose a reason for hiding this comment

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

Hey, good to see a new contributor.

Some general comments:

  1. Clean up AI instructions.
  2. Add e2e tests.
  3. Add documentation.

Some specific comments are inline.

"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/kyaml/yaml"
)

Copy link
Copy Markdown
Contributor

@nagygergo nagygergo Feb 16, 2026

Choose a reason for hiding this comment

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

Add a testcase that makes sure that the cel functions can't mutate the resourcelist that is the input. The function signature can allow for it, as it hands over the *yaml.RNode list.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hi @nagygergo! Done! I've added TestEvaluateCondition_Immutability that verifies CEL functions can't mutate the input resource list.

The test creates a ConfigMap, stores the original YAML, evaluates a CEL condition, then compares before/after to ensure no mutation. Even though the function signature accepts *yaml.RNode list (which could be mutated), CEL only receives converted map[string]interface{} copies, so the original RNodes remain unchanged.

Copilot AI review requested due to automatic review settings February 17, 2026 09:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@SurbhiAgarwal1 SurbhiAgarwal1 force-pushed the feat/cel-conditional-execution branch from 5f1dce7 to 98ac05d Compare February 18, 2026 09:55
Copilot AI review requested due to automatic review settings February 18, 2026 10:07
@SurbhiAgarwal1
Copy link
Copy Markdown
Contributor Author

Thanks @nagygergo for the detailed review! I've addressed all the feedback:

Changes Made:

1. Cleaned up AI-generated files

  • Removed the .agent/ directory

2. Added CEL protection

  • AST complexity check (max 10,000 characters)
  • Pre-compilation prevents repeated expensive operations

3. Reuse CEL environment

  • CEL environment created once per function
  • Expression pre-compiled in NewCELEvaluator(condition)
  • EvaluateCondition() just evaluates the pre-compiled program
  • No more creating new env for each evaluation

4. Added context parameter

  • Context passed to EvaluateCondition() for future timeout support

5. Removed unnecessary nil check

  • Changed from if fr.condition != "" && fr.evaluator != nil to if fr.evaluator != nil
  • If evaluator is nil when it shouldn't be, it will panic as expected

6. Added immutability test

  • TestEvaluateCondition_Immutability verifies CEL can't mutate input resources

7. Updated all tests

  • All tests use new NewCELEvaluator(condition) signature

8. Added documentation

  • Added internal/fnruntime/CEL_CONDITIONS.md with usage examples

9. Resource serialization

  • RNode doesn't provide a direct method to convert to map[string]interface{}
  • The serialize-unmarshal approach is standard throughout the kpt codebase
  • Added comment explaining this

10. fnResult/fnResults in tests

  • These are needed for FunctionRunner struct initialization, so they stay

All review comments have been addressed. Let me know if you need any other changes!

@SurbhiAgarwal1 SurbhiAgarwal1 force-pushed the feat/cel-conditional-execution branch from cce25d3 to e0c5faa Compare February 18, 2026 10:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@nagygergo
Copy link
Copy Markdown
Contributor

@SurbhiAgarwal1 please fix the build issues. I'll get back to reviewing it after the build and tests are passing.

Copilot AI review requested due to automatic review settings February 19, 2026 07:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI review requested due to automatic review settings February 19, 2026 10:57
@SurbhiAgarwal1 SurbhiAgarwal1 force-pushed the feat/cel-conditional-execution branch from 155590a to fc9326d Compare February 19, 2026 11:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@dosubot dosubot bot added the size:XXL This PR changes 1000+ lines, ignoring generated files. label Feb 20, 2026
SurbhiAgarwal1 and others added 28 commits April 7, 2026 22:07
- Run go mod tidy to drop k8s.io/apiserver (was causing docker/podman CI failure)
- Fix celeval_test.go: correct import path to github.com/kptdev/kpt/pkg/lib/runneroptions
- Update tests to use new EvaluateCondition(ctx, condition, resources) API

Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
Fix 1: ensure kind/apiVersion/metadata always present in CEL resource map
- resourceToMap now guarantees these keys exist so CEL expressions like
  r.kind == 'Deployment' return false instead of 'no such key' error

Fix 2: add .krmignore to condition test dirs
- .expected/ was being picked up by kpt fn render as a KRM resource
- .krmignore with '.expected' excludes it, matching all other test cases

Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
- Switch condition testdata from set-labels to no-op function so
  diff.patch hashes are deterministic and don't depend on container output
- Fix diff.patch files with correct git blob hashes for before/after Kptfile
- Update config.yaml expected stderr to match no-op function output
- Add comment in celenv.go explaining why k8s.io/apiserver CEL extensions
  are excluded (binary size / CI build failures) while cel-go built-ins suffice

Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
…, SemVer)

Re-add k8s.io/apiserver dependency to include k8s-specific CEL validators.
Maintainer confirmed these should be included despite the build time increase.

Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
- celeval.go: fix type alias comment (no import cycle, just convenience)
- celenv.go: default metadata.name and metadata.namespace to empty string
  so CEL expressions like r.metadata.name never error on missing keys
- runner.go: return error when condition is set but CELEnvironment is nil
- types.go: clarify Condition doc - evaluated against selected resources
  (after Selectors/Exclude), not the full package resource list
- celeval_test.go: add TestEvaluateCondition_MissingMetadata to verify
  conditions don't error on resources with missing metadata fields

Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
- Remove unnecessary type alias file (internal/fnruntime/celeval.go)
  Use *runneroptions.CELEnvironment directly in runner.go

- Group CEL constants in const() block in celenv.go

- Replace interface{} with any throughout celenv.go for modern Go style

- Remove panic from InitDefaults, add separate InitCELEnvironment() method
  Callers can now handle CEL initialization errors gracefully

- Fix error message for exec-based functions when condition is set
  Now uses f.Exec as fallback when f.Image is empty

- Fix go.mod: mark k8s.io/apiserver as direct dependency (not indirect)

- Add InitCELEnvironment() calls after all InitDefaults() calls:
  * commands/fn/render/cmdrender.go
  * thirdparty/cmdconfig/commands/cmdeval/cmdeval.go
  * internal/util/get/get.go
  * pkg/lib/kptops/fs_test.go
  * pkg/lib/kptops/render_test.go

Addresses review comments from:
- mozesl-nokia (type alias, const grouping, panic removal, any vs interface{})
- Copilot (error messages, go.mod dependency marking)

Signed-off-by: Surbhi <agarwalsurbhi1807@gmail.com>
… specified

When users explicitly pass '.' as the destination directory, kpt pkg get
now places files directly in the current directory, matching the behavior
of 'git clone' and 'kpt cfg set'.

Changes:
- Modified parse.GitParseArgs() to track if destination was explicitly provided
- Updated getDest() to use current directory directly when explicitly specified
- Modified get.Run() to allow using existing empty directories
- Preserved default behavior: when no destination is provided, still creates
  a subdirectory with the package name

Fixes kptdev#1407

Signed-off-by: Ciaran Johnston <ciaran.johnston@ericsson.com>
Signed-off-by: Ciaran Johnston <ciaran.johnston@ericsson.com>
…tions

- Changed getDest() to check cleaned path (v) instead of originalV for '.' comparison
- Updated tests to expect current directory when './' or '.' is explicitly passed
- Fixed TestCmdMainBranch_execute to not pass './' explicitly
- Fixed TestCmd_fail to use non-existent destination directory

Signed-off-by: Ciaran Johnston <ciaran.johnston@ericsson.com>
Signed-off-by: Ciaran Johnston <ciaran.johnston@ericsson.com>
Signed-off-by: Ciaran Johnston <ciaran.johnston@ericsson.com>
* Replace the image registry from gcr.io to ghcr.io

Signed-off-by: aravind.est <aravindhan.a@est.tech>

* Fix the wasm build failure

New WASM images published.
It's a manual process now.
Fix Go 1.21+ wasm compatibility by renaming the import module from go to gojs in the nodejs JS glue code. The wasmexec library used by the wasmtime runtime has the same issue but requires
a separate upstream fix.

Signed-off-by: aravind.est <aravindhan.a@est.tech>

---------

Signed-off-by: aravind.est <aravindhan.a@est.tech>
Signed-off-by: Michael Greaves <michael.greaves@nokia.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Michael Greaves <michael.greaves@nokia.com>
Signed-off-by: Michael Greaves <michael.greaves@nokia.com>
CI failure due to renderstatus merge fixed.
Env variable to use nodejs as wasm env moved to Makefile from Github workflow

Signed-off-by: aravind.est <aravindhan.a@est.tech>
…king (kptdev#4437)

* Add renderstatus to the kptfile

Signed-off-by: aravind.est <aravindhan.a@est.tech>

* Address copilot review comments

Signed-off-by: Aravindhan Ayyanathan <aravindhan.a@est.tech>

---------

Signed-off-by: aravind.est <aravindhan.a@est.tech>
Signed-off-by: Aravindhan Ayyanathan <aravindhan.a@est.tech>
Signed-off-by: Mózes László Máté <laszlo.mozes@nokia.com>
Signed-off-by: Mózes László Máté <laszlo.mozes@nokia.com>
Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
- Remove krm-functions-catalog submodule (causing netlify docs build failure)
- Remove temporary files: output.txt, e2e_output.txt, PR_REVIEW_SUMMARY.md
- Update test expectations to include renderStatus field in Kptfile API
  - condition-not-met: empty mutationSteps array (function skipped)
  - condition-met: mutationSteps with exitCode 0 (function executed)

Addresses review feedback from efiacor

Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
When condition is not met and function is skipped, mutationSteps is
empty so renderStatus is omitted entirely (omitempty). Remove the
empty mutationSteps from the expected diff.patch.

Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
Replace unused parameters r and w with _ in filter.Run mock function
to satisfy revive linter unused-parameter rule.

Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
Filter() calls printer.FromContextOrDie() which panics if printer
is not set in context. Add printer.WithContext() to test setup.

Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
@SurbhiAgarwal1
Copy link
Copy Markdown
Contributor Author

Closing this PR in favor of a clean rebase. The branch had accumulated 61 commits including upstream commits from other contributors, making it messy to review.

All the feedback from this review has been addressed in the new PR which has a single clean commit:

  • Removed unnecessary type alias file (celeval.go)
  • Grouped constants in const() block
  • Replaced interface{} with any
  • Removed panic from InitDefaults, added InitCELEnvironment() error method
  • Added e2e tests for condition-met and condition-not-met
  • Added immutability test
  • Added documentation (kptfile schema + book/04-using-functions)
  • Removed all unwanted files (krm-functions-catalog, output.txt, etc.)
  • Fixed diff.patch for renderStatus field

Thank you all for the thorough review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/fn-runtime KRM function runtime size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants