From c9fe6e6e1e72d038bbe98dfcf9dbdc073b8df813 Mon Sep 17 00:00:00 2001 From: Ian Littman Date: Mon, 1 Dec 2025 17:31:47 -0600 Subject: [PATCH] When IPAs are updated via GitOps, keep titles as-is (or re-hydrate from the same SW in the DB) when not downloading anew (#36532) Fixes #36523. # Checklist for submitter If some of the following don't apply, delete the relevant line. ## Testing - [x] QA'd all new/changed functionality manually For unreleased bug fixes in a release candidate, one of: - [x] Confirmed that the fix is not expected to adversely impact load test results --- ee/server/service/software_installers.go | 5 ++++- server/datastore/mysql/in_house_apps.go | 12 ++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ee/server/service/software_installers.go b/ee/server/service/software_installers.go index e793c74046..1c303350d8 100644 --- a/ee/server/service/software_installers.go +++ b/ee/server/service/software_installers.go @@ -2339,7 +2339,10 @@ func (svc *Service) softwareBatchUpload( if installer.Filename == "" { installer.Filename = fmt.Sprintf("package.%s", ext) } - if installer.Title == "" { + if installer.Title == "" && installer.Extension != "ipa" { + // If an IPA is specified via hash rather than downloaded via URL, we won't have a title populated, + // and should try to pull the title from the database if it exists. If we can't extract title name for + // some reason, filename should only be used after attempting to pull data from the database. installer.Title = installer.Filename } diff --git a/server/datastore/mysql/in_house_apps.go b/server/datastore/mysql/in_house_apps.go index a24ca7ac4a..87e4b85def 100644 --- a/server/datastore/mysql/in_house_apps.go +++ b/server/datastore/mysql/in_house_apps.go @@ -1026,9 +1026,16 @@ VALUES var args []any for _, installer := range installers { + var providedTitle *string + if installer.Title != "" { + providedTitle = &installer.Title // for IPAs downloaded via URL; IPAs referenced by hash won't have this + } + args = append( args, - strings.TrimSuffix(installer.Filename, ".ipa"), + providedTitle, // if IPA is downloaded as part of the GitOps run, we'll have this via metadata extraction + installer.StorageID, // if the IPA already exists in the DB, pull the name from an existing title if possible + strings.TrimSuffix(installer.Filename, ".ipa"), // if neither of the above turns up anything, fall back to filename installer.Source, "", func() *string { @@ -1040,7 +1047,8 @@ VALUES ) } - values := strings.TrimSuffix(strings.Repeat("(?,?,?,?),", len(installers)), ",") + values := strings.TrimSuffix(strings.Repeat( + "(COALESCE(?, (SELECT name FROM software_titles st JOIN in_house_apps iha ON iha.title_id = st.id AND iha.storage_id = ? ORDER BY st.id ASC LIMIT 1), ?),?,?,?),", len(installers)), ",") if _, err := tx.ExecContext(ctx, fmt.Sprintf(upsertSoftwareTitles, values), args...); err != nil { return ctxerr.Wrap(ctx, err, "insert new/edited software titles") }