From 59c46b44d40072ddb3ec0db425f25aba7336f516 Mon Sep 17 00:00:00 2001 From: Shushank Ranjan Date: Fri, 28 Aug 2026 15:53:49 +0530 Subject: [PATCH] fix(bundle/direct): construct UpdateApp update_mask dynamically based on changed fields (#6400) --- .nextchanges/bundles/app_update_mask.md | 1 + .../apps/update/out.requests.direct.json | 2 +- bundle/direct/dresources/app.go | 38 ++++++++++--------- 3 files changed, 23 insertions(+), 18 deletions(-) create mode 100644 .nextchanges/bundles/app_update_mask.md diff --git a/.nextchanges/bundles/app_update_mask.md b/.nextchanges/bundles/app_update_mask.md new file mode 100644 index 0000000000..7f4d63ab0b --- /dev/null +++ b/.nextchanges/bundles/app_update_mask.md @@ -0,0 +1 @@ +Construct `UpdateApp` `update_mask` dynamically based on changed fields (#6400). diff --git a/acceptance/bundle/resources/apps/update/out.requests.direct.json b/acceptance/bundle/resources/apps/update/out.requests.direct.json index faf9c2bbca..b62940fd3b 100644 --- a/acceptance/bundle/resources/apps/update/out.requests.direct.json +++ b/acceptance/bundle/resources/apps/update/out.requests.direct.json @@ -17,7 +17,7 @@ "description": "MY_APP_DESCRIPTION", "name": "myappname" }, - "update_mask": "description,budget_policy_id,usage_policy_id,resources,user_api_scopes,forward_user_access_token,compute_size,compute_min_instances,compute_max_instances,git_repository,telemetry_export_destinations" + "update_mask": "description" } } { diff --git a/bundle/direct/dresources/app.go b/bundle/direct/dresources/app.go index c7108f8799..1bdacb8a26 100644 --- a/bundle/direct/dresources/app.go +++ b/bundle/direct/dresources/app.go @@ -171,30 +171,34 @@ var UpdateMaskFields = []string{ "telemetry_export_destinations", } -var updateMask = strings.Join(UpdateMaskFields, ",") - func (r *ResourceApp) DoUpdate(ctx context.Context, id string, config *AppState, entry *PlanEntry) (*AppRemote, error) { // Deploy-only fields (source_code_path, config, git_source, lifecycle) are excluded // from the request body; see appRequestBody. if hasAppChanges(entry) { app := appRequestBody(config) - request := apps.AsyncUpdateAppRequest{ - App: &app, - AppName: id, - UpdateMask: updateMask, - } - updateWaiter, err := r.client.Apps.CreateUpdate(ctx, request) - if err != nil { - return nil, err - } + fieldPaths := collectUpdatePathsWithPrefix(entry.Changes, "") + fieldPaths = slices.DeleteFunc(fieldPaths, func(p string) bool { + return p == "source_code_path" || p == "config" || p == "git_source" || p == "lifecycle" || strings.HasPrefix(p, "lifecycle.") + }) + if len(fieldPaths) > 0 { + request := apps.AsyncUpdateAppRequest{ + App: &app, + AppName: id, + UpdateMask: strings.Join(fieldPaths, ","), + } + updateWaiter, err := r.client.Apps.CreateUpdate(ctx, request) + if err != nil { + return nil, err + } - response, err := updateWaiter.Get() - if err != nil { - return nil, err - } + response, err := updateWaiter.Get() + if err != nil { + return nil, err + } - if response.Status.State != apps.AppUpdateUpdateStatusUpdateStateSucceeded { - return nil, fmt.Errorf("update status: %s: %s", response.Status.State, response.Status.Message) + if response.Status.State != apps.AppUpdateUpdateStatusUpdateStateSucceeded { + return nil, fmt.Errorf("update status: %s: %s", response.Status.State, response.Status.Message) + } } }