Skip porter-state for modifies: false custom actions#3582
Skip porter-state for modifies: false custom actions#3582kichristensen wants to merge 8 commits into
modifies: false custom actions#3582Conversation
modifies: false custom actions
When a custom action has modifies: false, Finalize() now skips packStateBag(), preventing porter-state from being written back to the installation. Run records and user-defined outputs are still persisted as expected. Fixes getporter#3579 Signed-off-by: Kim Christensen <kimworking@gmail.com>
Add test case for stateful, modifies:false action with an applyTo output to document that recording runs/outputs is correct behavior per Porter docs. State isolation is enforced in Finalize(), not ShouldRecord(). Signed-off-by: Kim Christensen <kimworking@gmail.com>
Add test bundle and TestInvoke_ModifiesFalse_DoesNotPersistState to assert that invoking a modifies:false action leaves porter-state unchanged, while still recording the run and saving user outputs. Signed-off-by: Kim Christensen <kimworking@gmail.com>
The previous fix skipped packStateBag() inside the invocation image, but the CNAB driver requires all outputs with no default to be present — so it failed with "required output porter-state is missing and has no default". Move the guard to SaveOperationResult on the host side: when the action has modifies:false, skip persisting internal outputs (porter-state) to the installation's output record while still allowing packStateBag() to write the file for the driver. Signed-off-by: Kim Christensen <kimworking@gmail.com>
f537da9 to
06b0b84
Compare
|
I feel like we should be modifying "ShouldRecord()" to execute properly in this area by having a bool checked here, what do you think? |
@schristoff If I understand you correctly. I don't think there is anything wrong in |
|
Yeah, I agree with that. I believe we should be leveraging that bool more to disregard writing the state, if that makes sense. |
Signed-off-by: Kim Christensen <kimworking@gmail.com>
Remove duplicate GetAction().Modifies lookup in SaveOperationResult by adding ActionModifies() on Run. ShouldRecord() and SaveOperationResult now use the same bool source. Signed-off-by: Kim Christensen <kimworking@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR prevents modifies:false custom actions from overwriting persisted Porter state while still allowing their run records and user-defined outputs to be saved.
Changes:
- Adds
Run.ActionModifies()and reuses it inShouldRecord(). - Filters internal outputs such as
porter-stateduringSaveOperationResult()for non-modifying actions. - Adds unit and integration coverage plus a test bundle for the
modifies:falsestate-isolation scenario.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
pkg/cnab/provider/action.go |
Skips persisting internal outputs for non-modifying actions. |
pkg/cnab/provider/action_test.go |
Adds tests for saving/skipping porter-state based on action modification behavior. |
pkg/storage/run.go |
Adds reusable action modification helper and applies it to run recording logic. |
pkg/storage/run_test.go |
Adds tests for ActionModifies() and output-driven run recording. |
pkg/runtime/runtime_manifest_test.go |
Adds tests documenting that finalization still writes the state output file. |
tests/integration/invoke_test.go |
Adds an end-to-end regression test for modifies:false state persistence. |
tests/integration/testdata/bundles/bundle-with-modifies-false-action/porter.yaml |
Adds a fixture bundle with state, a modifies:false action, and an action-scoped output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Point to SaveOperationResult(), not Finalize(), which was never modified. Signed-off-by: Kim Christensen <kimworking@gmail.com>
What does this change
Custom actions declared with `modifies: false` (e.g. `dry-run`) would silently overwrite the installation's `porter-state` whenever they produced outputs. This happened because `SaveOperationResult()` persisted all outputs unconditionally, regardless of the action's `modifies` flag.
This change adds a guard in `SaveOperationResult()`: if the action has `Modifies: false`, internal outputs such as `porter-state` are skipped during persistence. `Finalize()` still packs the state bag unconditionally so the runtime output file is produced, but the persistence layer discards it for non-modifying actions. For built-in actions (`install`, `upgrade`, `uninstall`) and `modifies: true` actions the existing behavior is preserved.
Run records and user-defined outputs for `modifies: false` actions continue to be persisted — this is correct per the Porter docs, which state that outputs are recorded when they explicitly apply to an action via `applyTo`.
What issue does it fix
Closes #3579
Notes for the reviewer
Checklist