Fix empty dts panic - #7116
Fix empty dts panic#7116
Conversation
ec6f4e4 to
56cc827
Compare
e1f0fcd to
6234b1a
Compare
|
@vishnukothakapu Nice catch, but I think instead of doing this in each plugin, this should be part of the SDK, wdyt? |
I also think this kind of validation should be part of the SDK, basically no deployment plugin has zero |
|
I belive the first place to parse and store deploy targets from piped configuration file is pipecd/pkg/plugin/sdk/plugin.go Lines 330 to 340 in 3ecbefa so just add validation after parsing deploy targets like this is ok IMO if p.deploymentPlugin != nil && len(commonFields.deployTargets) == 0 {
logger.Error("deployment plugin requires at least one deploy target to be configured", zap.String("name", cfg.Name))
return fmt.Errorf("deployment plugin requires at least one deploy target to be configured")
}Update: Livestate plugin and plan preview plugin should also check this (not only deployment plugin) |
Yes, agreed! I’ve updated the PR to handle this centrally. Added startup validation in |
Yes, exactly! I've updated the PR to add this validation during plugin startup in pkg/plugin/sdk/plugin.go. This ensures the plugin won't even start if it's missing deploy targets, which keeps the individual stage logic clean and focused on its work. |
Exactly this! I have added this exact validation check in Plugin.run right after parsing the deploy targets, including the checks for Livestate and PlanPreview plugins as you suggested. Thanks for the snippet, it made the fix very straightforward!
Exactly this! I have added this exact validation check in Plugin.run right after parsing the deploy targets, including the checks for Livestate and PlanPreview plugins as you suggested. Thanks for the snippet, it made the fix very straightforward! |
6234b1a to
2d3d839
Compare
✅ Deploy Preview for pipecd-site ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
2d3d839 to
2c51b06
Compare
Hi @rahulshendre, out of scope but why this change still trigger netlify ? |
There was a problem hiding this comment.
LGTM overall, only need to modify the test, you can have a look here: https://github.com/pipe-cd/pipecd/actions/runs/31786725487/job/94729559336?pr=7116 @vishnukothakapu
2c51b06 to
604411d
Compare
|
A little bit issue with the labeler check, still safe to merge nhe anh @khanhtc1202 |
I just merged the labeler patch, could you please help me update branch for this PR, so we can test the labeler workflow 😁 |
337bb99 to
3b32a67
Compare
|
NOTE: Release sdk after this being merged 📝 |
346e7f5 to
3ac8ff2
Compare
|
|
||
| // Get the deploy targets set on the deployment from the piped plugin config. | ||
| dtNames := request.GetInput().GetDeployment().GetDeployTargets(s.config.Name) | ||
| if len(dtNames) == 0 { |
There was a problem hiding this comment.
Still, do we need to validate it here, after validating deployTargets in the plugin?go (run function)? cc @armistcxy
There was a problem hiding this comment.
Yes, we still need this check here. The validation in plugin.go only verifies that the plugin itself has deploy targets configured.
dtNames comes from the individual app’s deployment request, so an app can still send an empty targets list. Without this check, we’d pass an empty deployTargets slice to stage execution and hit the same dts[0] panic this PR is meant to prevent.
So this check is needed to return a clean InvalidArgument error for that case.
There was a problem hiding this comment.
@khanhtc1202 yes anh, I have checked and as what @vishnukothakapu said, we need to check in both places
The first one in the plugin's Run function is for when starting the plugin
The next ones are for each application deployment (I've just checked that you can create an application without deploy target through Web UI)
Evidence: it can cause panic when you trigger new deployment for the application with no deploy target

TL,DR: Yes, we still need because validate in plugin running != validate in executing stage in application's deployment
There was a problem hiding this comment.
But there's one part I still concern @vishnukothakapu
Your fix check the dtNames, but the one we actually pass to the function executeStage is deployTargets
dtNames := request.GetInput().GetDeployment().GetDeployTargets(s.config.Name)
if len(dtNames) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "no deploy targets provided")
}
deployTargets := make([]*DeployTarget[DeployTargetConfig], 0, len(dtNames))
for _, name := range dtNames {
dt, ok := s.deployTargets[name]
if !ok {
return nil, status.Errorf(codes.Internal, "the deploy target %s is not found in the piped plugin config", name)
}
deployTargets = append(deployTargets, dt)
}
return executeStage(ctx, s.name, s.base, s.pluginConfig, deployTargets, client, request, sSo there will be a bug like this, in application configuration we specify deploy target ecs-dev
But in piped.yaml we specify deploy target as ecs-target
There will be mismatch => len(deployTargets) = 0
Maybe you should do something like if len(deployTargets) ==0 then log error like "Mismatch deploy target between plugin and application, or no specified deploy target in application configuration"
CC anh @khanhtc1202
There was a problem hiding this comment.
Thanks for checking this! @armistcxy .
Actually, if there is a mismatch (e.g., the application asks for ecs-dev but the plugin only has ecs-target), the code inside the for loop will hit the !ok condition and immediately return an error:
return nil, status.Errorf(codes.Internal, "the deploy target %s is not found in the piped plugin config", name)
Because it returns this error immediately, it never proceeds to executeStage with an empty deployTargets slice. If len(dtNames) > 0, len(deployTargets) is guaranteed to be greater than 0, otherwise it fails safely before execution. So we are completely covered for the mismatch scenario!
There was a problem hiding this comment.
@vishnukothakapu Oh I see, sorry for false alert, then I think it's all good now
3ac8ff2 to
418b992
Compare
Signed-off-by: Vishnu Kothakapu <vishnukothakapu27@gmail.com>
418b992 to
4cd65cf
Compare
great catch @armistcxy - our netlify.toml has no ignore build rule, so Netlify runs a preview on every PR regardless of what changed, even a Go-only one. |
|
@rahulshendre Yeah, I think we should ignore non-docs changes |
@harshitghagre, could you please open a PR for this? |
rahulshendre
left a comment
There was a problem hiding this comment.
LGTM
Great work @vishnukothakapu, thanks : )
|
@rahulshendre thanks for flagging this opened the fix in #7179 netlify now skips the build if there are no changes under /docs. |
that was fast @harshitghagre, thanks a lot : ) |
What this PR does:
Adds validation for empty
DeployTargetsacross multiplepipedv1stage plugins to prevent index out-of-bounds panics when accessingdts[0]. It also fixes a bug in the SDK whereStagePluginServiceServer.ExecuteStagepassednilfor deploy targets instead of correctly parsing them.Why we need it:
If a user misconfigures their application with an empty targets list, or if the SDK fails to pass the targets properly, affected plugins (Terraform deployment, ECS plan preview, and Kubernetes plan preview) would experience an unhandled panic and crash the process during the execution or plan preview stages. These checks ensure the plugins return a clean failure status with a descriptive log message instead.
Which issue(s) this PR fixes:
Fixes #7115
Does this PR introduce a user-facing change?:
No. This is purely an internal bug fix and adds protective checks to prevent unhandled panics.
Users with misconfigured deploy targets will now see a descriptive failure log in the PipeCD UI instead of the plugin crashing silently or hanging.
No.
N/A