Skip to content

Add render status conditions to Kptfile#4418

Open
aravindtga wants to merge 2 commits intokptdev:mainfrom
Nordix:render-status-conditions
Open

Add render status conditions to Kptfile#4418
aravindtga wants to merge 2 commits intokptdev:mainfrom
Nordix:render-status-conditions

Conversation

@aravindtga
Copy link
Contributor

@aravindtga aravindtga commented Feb 26, 2026

After every kpt fn render execution, a Rendered status condition is recorded in the root Kptfile indicating whether rendering succeeded or failed.

Note

86 of the 94 changed files are E2E test data and test scenarios. The core implementation changes are in 8 files.

What

  • Add a Rendered condition to status.conditions in the root Kptfile after render
  • On success: status: "True", reason: RenderSuccess
  • On failure: status: "False", reason: RenderFailed, message: <error details>
  • Status is recorded only in the root Kptfile, not in subpackages
  • Absolute temp/working directory paths in error messages are replaced with . (e.g. /tmp/kpt-pipeline-e2e-123/my-pkg/subpkg./subpkg) to keep messages deterministic and portable

Success Case:

status:
  conditions:
    - type: Rendered
      status: "True"
      reason: RenderSuccess

Render failure Case:

status:
  conditions:
    - type: Rendered
      status: "False"
      reason: RenderFailed
      message: |-
        pkg.render: pkg .:
        	pipeline.run: must run with `--allow-exec` option to allow running function binaries

Behaviour

  • In-place render (kpt fn render): status condition is written to the Kptfile
  • Out-of-place to directory (kpt fn render -o <dir>): status condition is not written, same as stdout/unwrap mode
  • Stdout/unwrap mode (kpt fn render -o stdout, -o unwrap): status condition is not written since there is no on-disk package to update
  • Status is recorded regardless of the kpt.dev/save-on-render-failure annotation

Changes

Core implementation:

  • pkg/api/kptfile/v1/types.go - Constants and helpers added
  • internal/util/render/executor.go - Functions to update the render status added
  • pkg/kptfile/kptfileutil/util.go - Helpers to write in a kpt file added.

Tests:

  • Updated and tested unit and e2e tests

@netlify
Copy link

netlify bot commented Feb 26, 2026

Deploy Preview for kptdocs ready!

Name Link
🔨 Latest commit 1af1873
🔍 Latest deploy log https://app.netlify.com/projects/kptdocs/deploys/69a0a1c9386247000896e2f9
😎 Deploy Preview https://deploy-preview-4418--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.

Signed-off-by: aravind.est <aravindhan.a@est.tech>
@aravindtga aravindtga force-pushed the render-status-conditions branch from 880acd5 to c94ece2 Compare February 26, 2026 18:28
@aravindtga aravindtga marked this pull request as ready for review February 26, 2026 18:45
Copilot AI review requested due to automatic review settings February 26, 2026 18:45
@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. area/fn-runtime KRM function runtime labels Feb 26, 2026
@dosubot
Copy link
Contributor

dosubot bot commented Feb 26, 2026

Related Documentation

4 document(s) may need updating based on files changed in this PR:

kpt

_index /kpt/blob/main/documentation/content/en/book/02-concepts/_index.md
View Suggested Changes
@@ -98,6 +98,37 @@
 rendering fails, instead of reverting all changes. This is particularly useful for debugging render failures and is
 essential for programmatic package rendering scenarios where preserving partial progress is valuable.
 
+### Status Conditions
+
+The Kptfile includes a `status.conditions` field that provides a declarative way to track the execution status of kpt operations. This makes package management operations observable and traceable.
+
+When `kpt fn render` executes, a `Rendered` status condition is automatically added to the root Kptfile to indicate whether the rendering operation succeeded or failed. This status is recorded only for in-place renders (the default behavior); it is not written for out-of-place modes such as stdout (`-o stdout`), unwrap (`-o unwrap`), or directory output (`-o <dir>`).
+
+**On successful render:**
+
+```yaml
+status:
+  conditions:
+    - type: Rendered
+      status: "True"
+      reason: RenderSuccess
+```
+
+**On failed render:**
+
+```yaml
+status:
+  conditions:
+    - type: Rendered
+      status: "False"
+      reason: RenderFailed
+      message: |-
+        pkg.render: pkg .:
+        	pipeline.run: must run with `--allow-exec` option to allow running function binaries
+```
+
+The status condition is recorded only in the root Kptfile, not in subpackages. The error message in failure cases provides details about what went wrong during the render operation.
+
 Just as directories can be nested, a package can contain another package, called a _subpackage_.
 
 Let's take a look at the wordpress package as an example:

[Accept] [Decline]

_index /kpt/blob/main/documentation/content/en/reference/cli/fn/render/_index.md
View Suggested Changes
@@ -95,6 +95,53 @@
 
 <!--mdtogo-->
 
+### Render Status Conditions
+
+After every `kpt fn render` execution, a `Rendered` status condition is recorded in the root Kptfile's `status.conditions` field to track the render execution history. This helps users quickly identify whether the last render succeeded or failed.
+
+#### Behavior
+
+- **Success**: When rendering completes successfully, the Kptfile receives a condition with `type: Rendered`, `status: "True"`, and `reason: RenderSuccess`.
+- **Failure**: When rendering fails, the Kptfile receives a condition with `type: Rendered`, `status: "False"`, `reason: RenderFailed`, and a `message` field containing the error details.
+- **In-place render only**: The status condition is written only when rendering in-place (the default behavior). It is NOT written when using out-of-place modes: `-o stdout`, `-o unwrap`, or `-o <DIR>`, since these modes do not modify the on-disk package.
+- **Always recorded**: The status is recorded regardless of the `kpt.dev/save-on-render-failure` annotation setting.
+- **Root Kptfile only**: The status condition is written only to the root Kptfile, not to subpackages.
+
+#### Success Example
+
+After a successful render, the root Kptfile will contain:
+
+```yaml
+apiVersion: kpt.dev/v1
+kind: Kptfile
+metadata:
+  name: my-package
+status:
+  conditions:
+    - type: Rendered
+      status: "True"
+      reason: RenderSuccess
+```
+
+#### Failure Example
+
+After a failed render, the root Kptfile will contain:
+
+```yaml
+apiVersion: kpt.dev/v1
+kind: Kptfile
+metadata:
+  name: my-package
+status:
+  conditions:
+    - type: Rendered
+      status: "False"
+      reason: RenderFailed
+      message: |-
+        pkg.render: pkg .:
+        	pipeline.run: must run with `--allow-exec` option to allow running function binaries
+```
+
 ### Examples
 
 <!--mdtogo:Examples-->

[Accept] [Decline]

_index /kpt/blob/main/documentation/content/en/book/04-using-functions/_index.md
View Suggested Changes
@@ -123,6 +123,52 @@
    `app: wordpress`.
 3. Resources in `mysql` and `wordpress` packages are validated against their
    OpenAPI spec.
+
+### Render status tracking
+
+After each `kpt fn render` execution, kpt records the render status in the root package's `Kptfile`. This provides visibility
+into whether the most recent render succeeded or failed, which is helpful for debugging and tracking the state of your package.
+
+The render status is recorded as a `Rendered` condition in the `status.conditions` section of the root `Kptfile`:
+
+**On success:**
+
+```yaml
+apiVersion: kpt.dev/v1
+kind: Kptfile
+metadata:
+  name: wordpress
+pipeline:
+  mutators:
+    - image: ghcr.io/kptdev/krm-functions-catalog/set-labels:latest
+      configMap:
+        app: wordpress
+  validators:
+    - image: ghcr.io/kptdev/krm-functions-catalog/kubeconform:latest
+status:
+  conditions:
+    - type: Rendered
+      status: "True"
+      reason: RenderSuccess
+```
+
+**On failure:**
+
+```yaml
+status:
+  conditions:
+    - type: Rendered
+      status: "False"
+      reason: RenderFailed
+      message: |-
+        pkg.render: pkg .:
+        	pipeline.run: must run with `--allow-exec` option to allow running function binaries
+```
+
+The render status is recorded only when performing in-place rendering (the default mode). It is not recorded when using
+out-of-place modes such as `--output stdout`, `--output unwrap`, or `--output <directory>`.
+
+You can inspect the render status by examining the root `Kptfile` to understand the result of the most recent render operation.
 
 ### Debugging render failures
 

[Accept] [Decline]

_index /kpt/blob/main/documentation/content/en/book/03-packages/_index.md
View Suggested Changes
@@ -63,9 +63,14 @@
         app: wordpress
   validators:
     - image: ghcr.io/kptdev/krm-functions-catalog/kubeconform:latest
-```
-
-The `Kptfile` contains two sections to keep track of the upstream package:
+status:
+  conditions:
+    - type: Rendered
+      status: "True"
+      reason: RenderSuccess
+```
+
+The `Kptfile` contains several sections to keep track of the package and its state:
 
 1. The `upstream` section contains the user-specified Git reference to the upstream package. This contains three pieces
    of information:
@@ -76,6 +81,10 @@
      or commit SHA.
 2. The `upstreamLock` section records the upstream Git reference (exact Git SHA) that was fetched by kpt. This section
    is managed by kpt and should not be changed manually.
+3. The `status` section records the operational state of the package. This is managed by kpt and tracks the execution
+   status of operations like `render`. The `status.conditions` field contains a list of condition objects, similar to
+   how Kubernetes tracks conditions on resources. For example, after running `kpt fn render`, a `Rendered` condition
+   is automatically recorded to indicate whether the last render succeeded or failed.
 
 Now, let's look at the `Kptfile` for the `mysql` subpackage:
 
@@ -239,6 +248,14 @@
    formatting of resources, even though a function (developed by different
    people using different toolchains) may have modified the formatting in some
    way.
+4. Records the render execution status in the root `Kptfile` as a `Rendered` condition
+   under `status.conditions`. On success, the condition has `status: "True"` and
+   `reason: RenderSuccess`. On failure, it has `status: "False"`, `reason: RenderFailed`,
+   and includes error details in the `message` field.
+
+Note that status conditions are only written for in-place renders (the default behavior).
+When using out-of-place output modes like `kpt fn render -o stdout` or `kpt fn render -o <dir>`,
+no status condition is written since the package is not being updated on disk.
 
 [Chapter 4](../04-using-functions/) discusses different ways of running functions in detail.
 

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

Copy link

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 records the outcome of kpt fn render by writing a Rendered condition into status.conditions of the root Kptfile after render, capturing success (RenderSuccess) or failure (RenderFailed, with an error message). It also updates extensive E2E fixtures to expect the new status output and to keep failure messages deterministic by rewriting absolute root paths to ..

Changes:

  • Add Rendered condition constants and a helper constructor in the Kptfile API.
  • Update the render executor to write/update the root Kptfile status.conditions on success/failure (in-place only).
  • Update unit tests and E2E expected outputs to include the new Rendered condition behavior.

Reviewed changes

Copilot reviewed 83 out of 90 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
pkg/api/kptfile/v1/types.go Adds Rendered condition constants and NewRenderedCondition helper.
internal/util/render/executor.go Writes the Rendered condition to the root Kptfile after render (in-place only) and normalizes root paths in error messages.
pkg/kptfile/kptfileutil/util.go Adds WriteKptfileToFS and refactors marshaling into marshalKptfile.
internal/util/render/executor_test.go Adds unit tests covering render status updates (success/failure/replace/root-only) and updates constants.
e2e/testdata/fn-render/validate-resource-failure/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False on failure.
e2e/testdata/fn-render/validate-generated-resource/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True on success.
e2e/testdata/fn-render/success-stdout/.expected/diff.patch Updates expected outputs (note: stdout mode should not write status to disk).
e2e/testdata/fn-render/subpkgs/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True on success.
e2e/testdata/fn-render/subpkgs-with-krmignore/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True on success.
e2e/testdata/fn-render/subpkg-resource-deletion/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True on success.
e2e/testdata/fn-render/subpkg-has-samename-subdir/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True on success.
e2e/testdata/fn-render/subpkg-has-invalid-kptfile/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False with normalized path in message.
e2e/testdata/fn-render/subpkg-fn-failure/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/structured-results-from-muiltiple-fns/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/short-image-path/.expected/results.yaml Updates expected results formatting.
e2e/testdata/fn-render/short-image-path/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/selectors/selectors-with-exclude/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/selectors/generator/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/selectors/exclude/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/selectors/basicpipeline/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/save-on-render-failure/no-save-on-render-failure/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-subpkg-validator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-subpkg-mutator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-parent-validator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-parent-mutator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-parent-and-subpkg-both-fail/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-multiple-subpkgs-one-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-deep-nested-middle-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/dfs-basicpipeline/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-subpkg-validator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-subpkg-mutator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-parent-validator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-parent-mutator-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-parent-and-subpkg-both-fail/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-multiple-subpkgs-one-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-deep-nested-middle-fails/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/save-on-render-failure/bfs-basicpipeline/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/resource-has-pkgname-prefix/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/resource-deletion/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/preserve-order-null-values/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/preserve-comments/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/path-index-outofpackage/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/path-index-duplicate/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/path-index-descendent/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/path-index-current/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/path-index-ancestor/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/non-krm-resource/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/non-krm-resource-no-pipeline/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/no-resources/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/no-pipeline-in-subpackage/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/no-op/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/no-fnconfig/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/mutate-path-index/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/mutate-legacy-path-index/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/modify-path-annotation/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/modify-legacy-path-annotation/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/missing-fn-image/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/kubeval-failure/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/krm-check-exclude-kustomize/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/image-pull-policy-never/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/generator/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/generator-absolute-path/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/format-on-success/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fnresult-fn-success/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fnresult-fn-failure/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/fnconfig/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fnconfig-updated-in-render/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fnconfig-pkgfn-refers-subdir/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fnconfig-in-subdir/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fnconfig-cannot-refer-subpkgs/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/fnconfig-ancestorfn-not-mutate-subpkg-config/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fn-success-with-stderr/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/fn-failure/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/fn-failure-output-no-truncate/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/exec-without-permissions/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=False.
e2e/testdata/fn-render/exec-function-with-args/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/exec-function-stderr/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/default-runtime/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/basicpipeline/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/basicpipeline-wasm/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/basicpipeline-symlink/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/basicpipeline-semver/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-render/all-resource-deletion/.expected/diff.patch Updates expected root Kptfile diff to include Rendered=True.
e2e/testdata/fn-eval/simple-function-with-tag/.expected/diff.patch Updates expected diff formatting (unrelated fixture normalization).
e2e/testdata/fn-eval/save-fn/preserve-kptfile-comments/.expected/diff.patch Updates expected diff formatting (fixture normalization).

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

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Feb 26, 2026
Signed-off-by: aravind.est <aravindhan.a@est.tech>
@aravindtga aravindtga force-pushed the render-status-conditions branch from 7e87f5c to 1af1873 Compare February 26, 2026 19:40
Copilot AI review requested due to automatic review settings February 26, 2026 19:40
Copy link

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 87 out of 94 changed files in this pull request and generated no new comments.


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

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.

2 participants