Skip to content

fix: populate optional artifacts with empty data. #14267 #14494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

isubasinghe
Copy link
Member

@isubasinghe isubasinghe commented May 23, 2025

Fixes #14267

Motivation

The current code allows for artifacts to be absent but allows for optional variables to be referenced on certain occasions. This code change adds all optional outputs to the scope if they do not exist.

Modifications

This change modifies the buildLocalScope to obtain the template, if an output fails to appear in the node outputs, we will populate these keys with empty artifacts.

Verification

Tested manually using a debugger.

Documentation

While this does change how variables work, there isn't any documentation changes in this PR.

Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
@isubasinghe isubasinghe force-pushed the fix-optional-artifact branch from 6deae94 to 4a059e3 Compare May 23, 2025 03:08
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
@isubasinghe isubasinghe changed the title fix: populate optional artifacts with empty data fix: populate optional artifacts with empty data. #14267 May 23, 2025
@isubasinghe
Copy link
Member Author

I was wondering if there should also be a exists variable as well such that the expression logic can deal with missing output artifacts with more precision.

@isubasinghe isubasinghe marked this pull request as ready for review May 23, 2025 06:17
@Joibel Joibel requested a review from Copilot May 23, 2025 07:31
Copy link
Contributor

@Copilot 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 fixes an issue where missing optional artifacts are now populated with empty data to ensure they can always be referenced.

  • Modify the buildLocalScope logic to include default empty artifacts based on the template outputs.
  • Update calls to addOutputsToLocalScope in both steps and DAG contexts with the new parameter for template artifacts.

Reviewed Changes

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

File Description
workflow/controller/steps.go Updates call to addOutputsToLocalScope with an empty artifact parameter.
workflow/controller/scope.go Adds hasArtifact helper to check for artifact presence in the scope.
workflow/controller/operator.go Extends buildLocalScope and addOutputsToLocalScope to process template artifacts.
workflow/controller/dag.go Modifies addOutputsToLocalScope call for DAG tasks by passing a nil tmplArts.
Comments suppressed due to low confidence (1)

workflow/controller/operator.go:3294

  • The loop resets several fields of tmplArts artifacts; please verify that this mutation is intended and does not inadvertently discard critical artifact data.
for _, art := range tmplArts {

@@ -657,7 +657,7 @@ func (woc *wfOperationCtx) executeDAGTask(ctx context.Context, dagCtx *dagContex
func (woc *wfOperationCtx) buildLocalScopeFromTask(dagCtx *dagContext, task *wfv1.DAGTask) (*wfScope, error) {
// build up the scope
scope := createScope(dagCtx.tmpl)
woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, scope)
woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, scope, nil)
Copy link
Preview

Copilot AI May 23, 2025

Choose a reason for hiding this comment

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

[nitpick] Passing nil for tmplArts is valid, but consider using an empty artifact container (e.g., wfv1.Artifacts{}) for improved clarity and consistency with other calls.

Suggested change
woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, scope, nil)
woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, scope, wfv1.Artifacts{})

Copilot uses AI. Check for mistakes.

Copy link
Member

@Joibel Joibel left a comment

Choose a reason for hiding this comment

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

This whole thing still feels like it's the wrong fix. It's fixing outputs, which are fine, to mask a problem in inputs, which are broken.

We have a problem with input artifacts, marked as optional, causing the processing of those to cause an error. They're optional, so they shouldn't cause an error, and this doesn't fix that.

This feels like a hack, undoing some of #13678 which made sure that optional output artifacts which didn't exist really didn't exist.

You've suggested a flag exists on the artifact rather than an empty value as you've implemented here - but that's pretty much already determinable with the code prior to this - it just doesn't exist.

If you'd implemented exists where would you check and use that information - that's where I think this fix should be applied?

We're missing the test case as a regression test too.

@@ -657,7 +657,7 @@ func (woc *wfOperationCtx) executeDAGTask(ctx context.Context, dagCtx *dagContex
func (woc *wfOperationCtx) buildLocalScopeFromTask(dagCtx *dagContext, task *wfv1.DAGTask) (*wfScope, error) {
// build up the scope
scope := createScope(dagCtx.tmpl)
woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, scope)
woc.addOutputsToLocalScope("workflow", woc.wf.Status.Outputs, scope, nil)
Copy link
Member

Choose a reason for hiding this comment

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

nit (edit): wot copilot said

@@ -3222,12 +3223,22 @@ func (woc *wfOperationCtx) requeueIfTransientErr(err error, nodeName string) (*w
// buildLocalScope adds all of a nodes outputs to the local scope with the given prefix, as well
// as the global scope, if specified with a globalName
func (woc *wfOperationCtx) buildLocalScope(scope *wfScope, prefix string, node *wfv1.NodeStatus) {

Copy link
Member

Choose a reason for hiding this comment

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

nit: Remove leading new line

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Optional artifact yielding failed to resolve when not passed alongside withParams or withItems
2 participants