Skip to content

feat: add builtin runtime support#4430

Open
abdulrahman11a wants to merge 6 commits intokptdev:mainfrom
abdulrahman11a:feature/builtin-runtime
Open

feat: add builtin runtime support#4430
abdulrahman11a wants to merge 6 commits intokptdev:mainfrom
abdulrahman11a:feature/builtin-runtime

Conversation

@abdulrahman11a
Copy link
Copy Markdown

Summary

Closes #4307

This PR implements a built-in runtime for curated KRM functions inside kpt itself,
allowing apply-replacements and starlark to run without pulling images from Docker Hub.

Approach

As discussed in the issue thread, this implementation avoids reintroducing a circular
dependency between Porch and kpt by moving the built-in runtime concept into kpt directly.
The architecture is intentionally simple and extensible — new functions can be added
incrementally by registering them in the builtin registry.

How it works

A thread-safe self-registration registry (internal/builtins/registry) allows KRM function
implementations to register themselves via init(). The fnruntime runner checks this
registry before falling back to Docker or WASM, so existing behavior is fully preserved
for unregistered functions.

Priority order in fnruntime/runner.go:

  1. pkg-context builtin (existing)
  2. Builtin registry ← new, no Docker needed
  3. Docker / WASM (fallback, unchanged)

Functions included

Function Image
apply-replacements ghcr.io/kptdev/krm-functions-catalog/apply-replacements
starlark ghcr.io/kptdev/krm-functions-catalog/starlark

Files changed

File Description
internal/builtins/registry/registry.go Thread-safe self-registration registry
internal/builtins/applyreplacements/apply_replacements.go Built-in apply-replacements implementation
internal/builtins/starlark/starlark.go Built-in starlark entry point
internal/builtins/starlark/config.go Starlark config parser (accepts StarlarkRun and Run kinds)
internal/builtins/starlark/processor.go Starlark processor
internal/builtins/BuiltinRuntime.go Blank-imports all builtins to trigger init()
internal/fnruntime/runner.go Wires builtin registry lookup before Docker fallback

Verified locally

[PASS] "ghcr.io/kptdev/krm-functions-catalog/apply-replacements:v0.1.1" in 0s
[PASS] "ghcr.io/kptdev/krm-functions-catalog/starlark:v0.5.0" in 0s

Both functions execute without Docker running.
image

Next steps

  • More curated functions can be gradually inlined following the same pattern
  • WASM support remains a separate investigation track as suggested in the issue

Copilot AI review requested due to automatic review settings March 12, 2026 21:22
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 12, 2026

Deploy Preview for kptdocs ready!

Name Link
🔨 Latest commit 839d2ff
🔍 Latest deploy log https://app.netlify.com/projects/kptdocs/deploys/69d56e2fe288c400087cbdba
😎 Deploy Preview https://deploy-preview-4430--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.

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. area/fn-runtime KRM function runtime labels Mar 12, 2026
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.

Pull request overview

This PR implements a built-in runtime for curated KRM functions (apply-replacements and starlark) inside kpt itself, allowing them to run without Docker by registering them in a thread-safe in-process registry. When a function image matches a registered builtin (by normalized name, ignoring tags/digests), the builtin is used; otherwise the existing Docker/WASM fallback is preserved.

Changes:

  • New self-registration registry (internal/builtins/registry/) with thread-safe Register/Lookup using image name normalization
  • Built-in implementations for apply-replacements and starlark functions, wired via init() blank imports
  • Integration into fnruntime/runner.go to check the builtin registry before falling back to Docker/WASM

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/builtins/registry/registry.go Thread-safe builtin function registry with image name normalization
internal/builtins/applyreplacements/apply_replacements.go Built-in apply-replacements KRM function implementation
internal/builtins/starlark/starlark.go Built-in starlark KRM function entry point
internal/builtins/starlark/config.go Starlark config parser supporting StarlarkRun, Run, and ConfigMap kinds
internal/builtins/starlark/processor.go Starlark processing logic
internal/builtins/starlark/config_test.go Tests for starlark config parsing
internal/builtins/BuiltinRuntime.go Blank-imports all builtins to trigger init() registration
internal/fnruntime/runner.go Wires builtin registry lookup between pkg-context and Docker/WASM
go.mod / go.sum Adds starlark catalog dependency and upgrades fn SDK to v1.0.2

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@abdulrahman11a abdulrahman11a force-pushed the feature/builtin-runtime branch from 446b055 to 4bdb97c Compare March 12, 2026 21:33
Copilot AI review requested due to automatic review settings March 24, 2026 14:26
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.

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@abdulrahman11a abdulrahman11a force-pushed the feature/builtin-runtime branch from d83136d to 267c21e Compare March 31, 2026 22:31
Copilot AI review requested due to automatic review settings April 1, 2026 18:44
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.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +87 to +96
func (r *Replacements) Process(rl *fn.ResourceList) (bool, error) {
if err := r.Config(rl.FunctionConfig); err != nil {
rl.LogResult(err)
return false, nil
}
transformedItems, err := r.Transform(rl.Items)
if err != nil {
rl.LogResult(err)
return false, nil
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Replacements.Process logs errors to the ResourceList but then returns (false, nil) on both config and transform failures. That makes the builtin appear successful to fnruntime (exit code 0 / [PASS]) even when the function reports an error result. To match container/WASM behavior and the starlark builtin, propagate the error (while still logging/writing the ResourceList) so fn render fails appropriately.

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +22
import (
"io"
"log"
"strings"
"sync"
)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Lookup uses the standard library log package for warnings. The rest of this repo typically uses k8s.io/klog/v2 for warnings/info, which supports verbosity levels and integrates with existing logging flags. Consider switching this to klog.Warningf (and possibly gating behind a V-level) to keep logging consistent and avoid unexpected stdout/stderr output.

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +48
if fn != nil && imageName != normalized {
log.Printf("WARNING: builtin function %q is being used instead of the requested image %q. "+
"The built-in implementation may differ from the pinned version.", normalized, imageName)
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This warning currently triggers for any tag/digest mismatch but is emitted unconditionally once a builtin is found. If you keep the warning, consider downgrading it to a verbose log level (or only warning when the request was explicitly pinned with a tag/digest) to avoid noisy logs for users who intentionally rely on the builtin fallback.

Copilot uses AI. Check for mistakes.
Comment on lines +49 to +53
func (sr *Run) Config(fnCfg *fn.KubeObject) error {
switch {
case fnCfg.IsEmpty():
return fmt.Errorf("FunctionConfig is missing. Expect `ConfigMap` or `StarlarkRun`")
case fnCfg.IsGVK("", configMapAPIVersion, configMapKind):
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The empty-functionConfig error message is now inaccurate: this builtin accepts ConfigMap, StarlarkRun, and Run kinds, but the message only mentions ConfigMap/StarlarkRun. Please update the message so users know Run is supported (or remove mention of specific kinds and point to docs).

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +78
case fnCfg.IsGVK(starlarkRunGroup, starlarkRunVersion, starlarkRunKind),
fnCfg.IsGVK(starlarkRunGroup, starlarkRunVersion, "Run"):
if err := fnCfg.As(sr); err != nil {
return err
}
default:
return fmt.Errorf("`functionConfig` must be either %v or %v, but we got: %v",
schema.FromAPIVersionAndKind(configMapAPIVersion, configMapKind).String(),
schema.FromAPIVersionAndKind(starlarkRunAPIVersion, starlarkRunKind).String(),
schema.FromAPIVersionAndKind(fnCfg.GetAPIVersion(), fnCfg.GetKind()).String())
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The type-mismatch error message only lists ConfigMap and StarlarkRun as supported, but Run is also accepted (see the IsGVK(..., "Run") branch). Please include Run in the allowed kinds so the error output matches actual behavior.

Copilot uses AI. Check for mistakes.
import (
"fmt"

starlarkruntime "github.com/kptdev/krm-functions-catalog/functions/go/starlark/third_party/sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

This file imports a third_party/.../fn/runtime/starlark package from krm-functions-catalog, which forces kpt to take a fairly large new direct dependency (github.com/kptdev/krm-functions-catalog/functions/go/starlark). If possible, prefer importing the upstream kyaml runtime directly (sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark) to reduce transitive deps and avoid relying on a third_party path that may not be API-stable.

Suggested change
starlarkruntime "github.com/kptdev/krm-functions-catalog/functions/go/starlark/third_party/sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"
starlarkruntime "sigs.k8s.io/kustomize/kyaml/fn/runtime/starlark"

Copilot uses AI. Check for mistakes.
Signed-off-by: Abdulrahman Fikry <abdulrahmanfikry1@gmail.com>
Signed-off-by: Abdulrahman Fikry <abdulrahmanfikry1@gmail.com>
Signed-off-by: abdulrahman11a <abdulrahmanfikry1@gmail.com>
Signed-off-by: abdulrahman11a <abdulrahmanfikry1@gmail.com>
@abdulrahman11a abdulrahman11a force-pushed the feature/builtin-runtime branch from 9abb21d to c4f465b Compare April 2, 2026 20:45
@nagygergo
Copy link
Copy Markdown
Contributor

Do you need to duplicate function code here because otherwise there would be a circular dependency (kpt -> kpt-fn-sdk-> apply-replacements->kpt)?
If that's true, we need to think through how to implement it.

@abdulrahman11a
Copy link
Copy Markdown
Author

Do you need to duplicate function code here because otherwise there would be a circular dependency (kpt -> kpt-fn-sdk-> apply-replacements->kpt)? If that's true, we need to think through how to implement it.

After reviewing the go mod graph, the current dependency chain is:
kpt → krm-functions-catalog/starlark → kpt@v1.0.0-beta.61.
This is a transitive dependency on an older kpt version, which works correctly for now, so the build succeeds.
However, relying on an older version isn’t ideal for long-term maintainability.
A cleaner solution would be to use kyaml or another shared runtime, which avoids depending on older kpt versions and prevents potential circular dependency issues in the future.

Copilot AI review requested due to automatic review settings April 7, 2026 19:13
@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels Apr 7, 2026
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.

Pull request overview

Copilot reviewed 17 out of 19 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +94 to +102
} else if builtinFn := builtinsregistry.Lookup(f.Image); builtinFn != nil {
fltr.Run = func(r io.Reader, w io.Writer) error {
var stderrBuf strings.Builder
err := builtinFn.Run(r, w, &stderrBuf)
if stderrBuf.Len() > 0 {
fnResult.Stderr = stderrBuf.String()
}
return err
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Builtin functions are executed in-process here, but the runner currently doesn’t apply RunnerOptions permissions (notably AllowNetwork) that are enforced for container execution. This means the starlark builtin can still fetch URL scripts and use starlib’s http module even when AllowNetwork is false, which is a behavior + security regression versus the Docker runtime. Consider enforcing the same permission model for builtins (e.g., reject URL/http usage when AllowNetwork is false, or plumb permissions into builtin runners).

Copilot uses AI. Check for mistakes.
Comment on lines +235 to +240
// for builtin functions, print stderr from fnResult if available
if fr.fnResult.Stderr != "" {
printFnStderr(fr.ctx, fr.fnResult.Stderr)
pr.Printf(" Exit code: %d\n\n", fr.fnResult.ExitCode)
return nil, errors.ErrAlreadyHandled
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

This error path treats any non-empty fr.fnResult.Stderr as a builtin-function failure and returns errors.ErrAlreadyHandled. fnResult.Stderr can also be populated on successful execution (warnings) or left over when a later post-processing step fails (e.g., pkg-path annotation / path invariants), which would cause the real error to be masked and reported as already-handled. Gate this on a more reliable signal (e.g., a dedicated error type/flag for builtin execution failures, or only when err came from the builtin runner wrapper).

Copilot uses AI. Check for mistakes.
Comment on lines +297 to +298
// builtin functions don't return ExecError, populate stderr from error message
fnResult.Stderr = err.Error()
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

In the builtin runner wrapper, stderr is captured into fnResult.Stderr, but on error this block overwrites fnResult.Stderr with err.Error(), losing the function’s actual stderr output. Preserve the captured stderr (e.g., only set fnResult.Stderr = err.Error() if it is still empty, or append the message) so builtin failures surface useful diagnostics.

Suggested change
// builtin functions don't return ExecError, populate stderr from error message
fnResult.Stderr = err.Error()
// builtin functions don't return ExecError, preserve any captured stderr and
// fall back to the error message only when stderr is empty.
if fnResult.Stderr == "" {
fnResult.Stderr = err.Error()
} else if !strings.Contains(fnResult.Stderr, err.Error()) {
if strings.HasSuffix(fnResult.Stderr, "\n") {
fnResult.Stderr += err.Error()
} else {
fnResult.Stderr += "\n" + err.Error()
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +87
if sf.URL != "" {
err := func() error {
resp, err := http.Get(sf.URL)
if err != nil {
return err
}

defer func() {
_ = resp.Body.Close()
}()

b, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
sf.Program = string(b)
return nil
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

When loading a starlark program from URL, the code doesn’t check resp.StatusCode (so 404/500 bodies will be treated as valid programs) and uses http.Get with the default client (no timeout / no context). Handle non-2xx responses explicitly and use an http.Client with a reasonable timeout (and ideally context) to avoid hangs and improve error messages.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +31
// The resources are provided to the starlark program through the global variable "resourceList".
// "resourceList" is a dictionary containing an "items" field with a list of resources.
// The starlark modified "resourceList" is the Filter output.
//
// After being run through the starlark program, the filter will copy the comments from the input
// resources to restore them -- due to them being dropped as a result of serializing the resources
// as starlark values.
//
// "resourceList" may also contain a "functionConfig" entry to configure the starlark script itself.
// Changes made by the starlark program to the "functionConfig" will be reflected in the
// Filter.FunctionConfig value.
//
// The Filter will also format the output so that output has the preferred field ordering
// rather than an alphabetical field ordering.
//
// The resourceList variable adheres to the kustomize function spec as specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
//
// All items in the resourceList are resources represented as starlark dictionaries/
// The items in the resourceList respect the io spec specified by:
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Package docs describe a global variable resourceList, but the runtime actually exposes ctx.resource_list (see Context.predeclared). Please update the doc to match the real API so users don’t write scripts against a non-existent global.

Suggested change
// The resources are provided to the starlark program through the global variable "resourceList".
// "resourceList" is a dictionary containing an "items" field with a list of resources.
// The starlark modified "resourceList" is the Filter output.
//
// After being run through the starlark program, the filter will copy the comments from the input
// resources to restore them -- due to them being dropped as a result of serializing the resources
// as starlark values.
//
// "resourceList" may also contain a "functionConfig" entry to configure the starlark script itself.
// Changes made by the starlark program to the "functionConfig" will be reflected in the
// Filter.FunctionConfig value.
//
// The Filter will also format the output so that output has the preferred field ordering
// rather than an alphabetical field ordering.
//
// The resourceList variable adheres to the kustomize function spec as specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
//
// All items in the resourceList are resources represented as starlark dictionaries/
// The items in the resourceList respect the io spec specified by:
// The resources are provided to the starlark program through ctx.resource_list.
// ctx.resource_list is a dictionary containing an "items" field with a list of resources.
// The starlark-modified ctx.resource_list is the Filter output.
//
// After being run through the starlark program, the filter will copy the comments from the input
// resources to restore them -- due to them being dropped as a result of serializing the resources
// as starlark values.
//
// ctx.resource_list may also contain a "functionConfig" entry to configure the starlark script
// itself. Changes made by the starlark program to the "functionConfig" will be reflected in the
// Filter.FunctionConfig value.
//
// The Filter will also format the output so that output has the preferred field ordering
// rather than an alphabetical field ordering.
//
// The ctx.resource_list value adheres to the kustomize function spec as specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
//
// All items in ctx.resource_list are resources represented as starlark dictionaries/
// The items in ctx.resource_list respect the io spec specified by:

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +44
"sigs.k8s.io/kustomize/kyaml/yaml"
)

func parseResourceList(t *testing.T, input string) *framework.ResourceList {
t.Helper()
rw := &kio.ByteReader{Reader: strings.NewReader(input)}
nodes, err := rw.Read()
assert.NoError(t, err)

rl := &framework.ResourceList{Items: nodes}
// استخرج الـ functionConfig من الـ ResourceList YAML
node, err := yaml.Parse(input)
if err == nil {
fc := node.Field("functionConfig")
if fc != nil && fc.Value != nil {
rl.FunctionConfig = fc.Value
}
}
return rl
}

Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

parseResourceList is never used in this test file, and it includes a non-English inline comment. Since it’s dead code, it should be removed to keep the test suite maintainable and consistent.

Suggested change
"sigs.k8s.io/kustomize/kyaml/yaml"
)
func parseResourceList(t *testing.T, input string) *framework.ResourceList {
t.Helper()
rw := &kio.ByteReader{Reader: strings.NewReader(input)}
nodes, err := rw.Read()
assert.NoError(t, err)
rl := &framework.ResourceList{Items: nodes}
// استخرج الـ functionConfig من الـ ResourceList YAML
node, err := yaml.Parse(input)
if err == nil {
fc := node.Field("functionConfig")
if fc != nil && fc.Value != nil {
rl.FunctionConfig = fc.Value
}
}
return rl
}
)

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +57
func env() (starlark.Value, error) {
env := map[string]interface{}{}
for _, e := range os.Environ() {
pair := strings.SplitN(e, "=", 2)
if len(pair) < 2 {
continue
}
env[pair[0]] = pair[1]
}
value, err := util.Marshal(env)
if err != nil {
return nil, errors.Wrap(err)
}
return value, nil
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

ctx.environment is built from os.Environ(), which (with the new in-process builtin runtime) exposes the full kpt process environment to arbitrary starlark scripts. This is a significant privilege increase compared to container execution (where only the container env is visible). Consider gating this behind an explicit option, exposing only a safe allowlist, or omitting environment entirely to avoid accidental secret leakage (e.g., cloud credentials in env vars).

Copilot uses AI. Check for mistakes.
…ptdev#4307)

Closes kptdev#4307

Implements a built-in runtime for curated KRM functions inside kpt,

allowing apply-replacements and starlark to run without pulling images

from Docker Hub, eliminating the external SDK dependency.

## Approach

Avoids circular dependency between Porch and kpt by moving the built-in

runtime concept into kpt directly using kyaml/fn/framework instead of

krm-functions-sdk.

## Architecture

A thread-safe self-registration registry (internal/builtins/registry)

allows KRM function implementations to register themselves via init().

The fnruntime runner checks this registry before falling back to Docker

or WASM, preserving existing behavior for unregistered functions.

Priority order in fnruntime/runner.go:

1. pkg-context builtin (existing)

2. Builtin registry (new, no Docker needed)

3. Docker / WASM (fallback, unchanged)

## Functions included

- apply-replacements: ghcr.io/kptdev/krm-functions-catalog/apply-replacements

- starlark: ghcr.io/kptdev/krm-functions-catalog/starlark

## Implementation notes

- Removed dependency on krm-functions-sdk/go/fn and krm-functions-catalog/starlark

- Vendored starlark runtime locally using kyaml/yaml instead of SDK

## Verified locally

[PASS] apply-replacements in 0s (no Docker)

[PASS] starlark in 0s (no Docker)

Signed-off-by: abdulrahman11a <abdulrahmanfikry1@gmail.com>
@abdulrahman11a abdulrahman11a force-pushed the feature/builtin-runtime branch from 70f474c to a1fce5e Compare April 7, 2026 19:24
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 7, 2026 19:35
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.

Pull request overview

Copilot reviewed 17 out of 19 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +54 to +58
case krmfn.ModuleName:
return starlark.StringDict{"krmfn": krmfn.Module}, nil
}
return nil, nil
}
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

load returns (nil, nil) for unknown modules. Starlark’s Thread.Load is expected to return a non-nil error when a module can’t be resolved; returning nil without error can lead to confusing failures (or panics) when a script tries to load() an unsupported module. Please return a descriptive error for the default case.

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +34
// Package starlark contains a kio.Filter which can be applied to resources to transform
// them through starlark program.
//
// Starlark has become a popular runtime embedding in go programs, especially for Kubernetes
// and data processing.
// Examples: https://github.com/cruise-automation/isopod, https://qri.io/docs/starlark/starlib,
// https://github.com/stripe/skycfg, https://github.com/k14s/ytt
//
// The resources are provided to the starlark program through the global variable "resourceList".
// "resourceList" is a dictionary containing an "items" field with a list of resources.
// The starlark modified "resourceList" is the Filter output.
//
// After being run through the starlark program, the filter will copy the comments from the input
// resources to restore them -- due to them being dropped as a result of serializing the resources
// as starlark values.
//
// "resourceList" may also contain a "functionConfig" entry to configure the starlark script itself.
// Changes made by the starlark program to the "functionConfig" will be reflected in the
// Filter.FunctionConfig value.
//
// The Filter will also format the output so that output has the preferred field ordering
// rather than an alphabetical field ordering.
//
// The resourceList variable adheres to the kustomize function spec as specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
//
// All items in the resourceList are resources represented as starlark dictionaries/
// The items in the resourceList respect the io spec specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/config-io.md
//
// The starlark language spec can be found here:
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

Package doc is inconsistent with the actual runtime API: it says the package is starlark and that scripts receive a global resourceList, but the implementation exposes ctx.resource_list (see Context.predeclared) and the package name is starlarkruntime. Please update the doc comment to match the actual symbols users should reference.

Suggested change
// Package starlark contains a kio.Filter which can be applied to resources to transform
// them through starlark program.
//
// Starlark has become a popular runtime embedding in go programs, especially for Kubernetes
// and data processing.
// Examples: https://github.com/cruise-automation/isopod, https://qri.io/docs/starlark/starlib,
// https://github.com/stripe/skycfg, https://github.com/k14s/ytt
//
// The resources are provided to the starlark program through the global variable "resourceList".
// "resourceList" is a dictionary containing an "items" field with a list of resources.
// The starlark modified "resourceList" is the Filter output.
//
// After being run through the starlark program, the filter will copy the comments from the input
// resources to restore them -- due to them being dropped as a result of serializing the resources
// as starlark values.
//
// "resourceList" may also contain a "functionConfig" entry to configure the starlark script itself.
// Changes made by the starlark program to the "functionConfig" will be reflected in the
// Filter.FunctionConfig value.
//
// The Filter will also format the output so that output has the preferred field ordering
// rather than an alphabetical field ordering.
//
// The resourceList variable adheres to the kustomize function spec as specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
//
// All items in the resourceList are resources represented as starlark dictionaries/
// The items in the resourceList respect the io spec specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/config-io.md
//
// The starlark language spec can be found here:
// Package starlarkruntime contains a kio.Filter which can be applied to resources to transform
// them through a Starlark program.
//
// Starlark has become a popular runtime embedding in Go programs, especially for Kubernetes
// and data processing.
// Examples: https://github.com/cruise-automation/isopod, https://qri.io/docs/starlark/starlib,
// https://github.com/stripe/skycfg, https://github.com/k14s/ytt
//
// The resources are provided to the Starlark program through ctx.resource_list.
// ctx.resource_list is a dictionary containing an "items" field with a list of resources.
// The Starlark-modified ctx.resource_list is the Filter output.
//
// After being run through the Starlark program, the filter will copy the comments from the input
// resources to restore them -- due to them being dropped as a result of serializing the resources
// as Starlark values.
//
// ctx.resource_list may also contain a "functionConfig" entry to configure the Starlark script
// itself. Changes made by the Starlark program to the "functionConfig" will be reflected in the
// Filter.FunctionConfig value.
//
// The Filter will also format the output so that output has the preferred field ordering
// rather than an alphabetical field ordering.
//
// The ctx.resource_list value adheres to the kustomize function spec as specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/functions-spec.md
//
// All items in ctx.resource_list are resources represented as Starlark dictionaries/
// The items in ctx.resource_list respect the io spec specified by:
// https://github.com/kubernetes-sigs/kustomize/blob/master/cmd/config/docs/api-conventions/config-io.md
//
// The Starlark language spec can be found here:

Copilot uses AI. Check for mistakes.
@abdulrahman11a abdulrahman11a force-pushed the feature/builtin-runtime branch 2 times, most recently from f745a1a to df6c9ee Compare April 7, 2026 20:47
…ptdev#4307)

Closes kptdev#4307

Implements a built-in runtime for curated KRM functions inside kpt,

allowing apply-replacements and starlark to run without pulling images

from Docker Hub, eliminating the external SDK dependency.

Avoids circular dependency between Porch and kpt by moving the built-in

runtime concept into kpt directly using kyaml/fn/framework instead of

krm-functions-sdk.

A thread-safe self-registration registry (internal/builtins/registry)

allows KRM function implementations to register themselves via init().

The fnruntime runner checks this registry before falling back to Docker

or WASM, preserving existing behavior for unregistered functions.

Priority order in fnruntime/runner.go:

1. pkg-context builtin (existing)

2. Builtin registry (new, no Docker needed)

3. Docker / WASM (fallback, unchanged)

- apply-replacements: ghcr.io/kptdev/krm-functions-catalog/apply-replacements

- starlark: ghcr.io/kptdev/krm-functions-catalog/starlark

- Removed dependency on krm-functions-sdk/go/fn and krm-functions-catalog/starlark

- Vendored starlark runtime locally using kyaml/yaml instead of SDK

[PASS] apply-replacements in 0s (no Docker)

[PASS] starlark in 0s (no Docker)

Signed-off-by: abdulrahman11a <abdulrahmanfikry1@gmail.com>
@abdulrahman11a abdulrahman11a force-pushed the feature/builtin-runtime branch from df6c9ee to 839d2ff Compare April 7, 2026 20:50
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:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

maintain a set of curated kpt functions which can be run without pulling stuff from docker hub

3 participants