feat: Add status check functions for scaffolder steps (#32890)

* feat: Add status check functions for scaffolder steps

- Introduced `always()` and `failure()` functions to control step execution after failures.
- Updated documentation to explain usage of new status check functions.
- Enhanced NunjucksWorkflowRunner to process these functions in step conditions.
- Added tests to verify behavior of steps using `always()` and `failure()`.

Signed-off-by: ferin79 <ferinpatel79@gmail.com>

* feat: Enhance status check functions in scaffolder steps

- Updated documentation to clarify usage of status check functions with template expressions.
- Modified tests to reflect changes in syntax for status checks.
- Refactored NunjucksWorkflowRunner to ensure proper handling of status check functions in step conditions.

Signed-off-by: ferin79 <ferinpatel79@gmail.com>

* docs: Clarify usage of status check functions in writing templates

- Removed redundant explanation about truthy conditions after step failure.
- Streamlined the description for better clarity on status check functions.

Signed-off-by: ferin79 <ferinpatel79@gmail.com>

---------

Signed-off-by: ferin79 <ferinpatel79@gmail.com>
This commit is contained in:
Ferin Patel
2026-04-28 06:16:59 -03:00
committed by GitHub
parent ffae2d437c
commit 07e08beac1
4 changed files with 508 additions and 10 deletions
@@ -746,6 +746,75 @@ input:
When `each` is used, the outputs of a repeated step are returned as an array of outputs from each iteration.
### Status Check Functions - `always()` and `failure()`
By default, when a step fails during a scaffolder run, all subsequent steps are skipped and the task is marked as failed. This can be problematic when your template creates external resources (repositories, cloud infrastructure, deployments) that need to be cleaned up if a later step fails.
Status check functions give you control over which steps run even after a failure. You use them inside a `${{ ... }}` template expression in the `if` field of a step.
| Function | Description |
| ----------- | ---------------------------------------------------------------------------- |
| `always()` | Always runs the step, regardless of whether previous steps passed or failed. |
| `failure()` | Runs the step only when a previous step has failed. |
These functions must be used as template expressions such as `${{ always() }}` or `${{ failure() }}`.
After a step has failed, the scaffolder only attempts later steps whose `if` expression invokes one of these status check functions.
#### Usage
```yaml
steps:
- id: cleanup
name: Cleanup Resources
action: my:cleanup:action
if: ${{ always() }}
```
#### Example: Cleanup on failure
A common pattern is to create resources in early steps and add cleanup steps
that only run if something goes wrong:
```yaml
steps:
- id: create-repo
name: Create Repository
action: publish:github
input:
repoUrl: ${{ parameters.repoUrl }}
- id: deploy
name: Deploy to Kubernetes
action: deploy:kubernetes
input:
manifest: ./k8s/deployment.yaml
# Only runs when a previous step failed — cleans up the repository
- id: cleanup-repo
name: Delete Repository
action: github:repo:delete
if: ${{ failure() }}
input:
repoUrl: ${{ parameters.repoUrl }}
# Always runs — post an audit event regardless of outcome
- id: audit
name: Post Audit Event
action: debug:log
if: ${{ always() }}
input:
message: 'Scaffolder run completed for ${{ parameters.repoUrl }}'
# Does not run after a failure, because it does not invoke a status check function
- id: plain-truthy-condition
name: Plain Truthy Condition
action: debug:log
if: ${{ true }}
input:
message: 'This step is skipped after a previous failure'
```
## Outputs
Each individual step can output some variables that can be used in the