@@ -274,6 +274,10 @@ func checkForKotsAppUpdates(opts types.CheckForUpdatesOpts, finishedChan chan<-
274274 return nil , errors .Errorf ("no app versions found for app %s in downstream %s" , opts .AppID , d .ClusterID )
275275 }
276276
277+ if err := maybeUpdatePendingVersionsMetadata (a .ID , getUpdatesOptions , appVersions .CurrentVersion ); err != nil {
278+ logger .Error (errors .Wrap (err , "failed to update app version metadata" ))
279+ }
280+
277281 filteredUpdates := removeOldUpdates (updates .Updates , appVersions , licenseChan .IsSemverRequired )
278282
279283 var availableReleases []types.UpdateCheckRelease
@@ -333,6 +337,40 @@ func checkForKotsAppUpdates(opts types.CheckForUpdatesOpts, finishedChan chan<-
333337 return & ucr , nil
334338}
335339
340+ // maybeUpdatePendingVersionsMetadata updates metadata for pending versions since the currently deployed version.
341+ //
342+ // Limitations:
343+ // - Only gets pending releases for the channel of the currently deployed version, even if channel changed in later versions
344+ // - Does not rerender the application archive, so the Installation object in the archive can become out of sync
345+ // - This is not in the critical path - errors are logged but don't fail the overall update check
346+ func maybeUpdatePendingVersionsMetadata (appID string , getUpdatesOptions kotspull.GetUpdatesOptions , currentVersion * downstreamtypes.DownstreamVersion ) error {
347+ if currentVersion == nil {
348+ return nil
349+ }
350+
351+ // update options to use info from the currently deployed version
352+ getUpdatesOptions .CurrentCursor = currentVersion .UpdateCursor
353+ getUpdatesOptions .CurrentChannelID = currentVersion .ChannelID
354+ getUpdatesOptions .ChannelChanged = false // we want the api to return pending updates after the currently deployed version even if channel changed in later versions
355+ if currentVersion .KOTSKinds != nil {
356+ getUpdatesOptions .CurrentChannelName = currentVersion .KOTSKinds .Installation .Spec .ChannelName
357+ } else {
358+ getUpdatesOptions .CurrentChannelName = ""
359+ }
360+
361+ updates , err := kotspull .GetUpdates (fmt .Sprintf ("replicated://%s" , getUpdatesOptions .License .Spec .AppSlug ), getUpdatesOptions )
362+ if err != nil {
363+ return errors .Wrap (err , "get updates for metadata refresh" )
364+ }
365+
366+ for _ , update := range updates .Updates {
367+ if err := store .UpdateAppVersionMetadata (appID , update ); err != nil {
368+ logger .Error (errors .Wrapf (err , "failed to update app version metadata for %s" , update .VersionLabel ))
369+ }
370+ }
371+ return nil
372+ }
373+
336374func downloadAppUpdates (opts types.CheckForUpdatesOpts , appID string , clusterID string , updates []upstreamtypes.Update , updateCheckTime time.Time ) error {
337375 for index , update := range updates {
338376 appSequence , err := upstream .DownloadUpdate (appID , update , opts .SkipPreflights , opts .SkipCompatibilityCheck )
0 commit comments