diff --git a/common/constants.go b/common/constants.go index 15ef4c10..fdbd1b6b 100644 --- a/common/constants.go +++ b/common/constants.go @@ -30,3 +30,6 @@ const ( CategoryListFileName = "category-list.json" RecommendListFileName = "recommend-list.json" ) + +// the tags can add more. like "latest", "stable", "edge", "beta", "alpha" +var NeedCheckDigestTags = []string{"latest"} diff --git a/route/v2/appstore.go b/route/v2/appstore.go index 0b0068c7..118bb0ed 100644 --- a/route/v2/appstore.go +++ b/route/v2/appstore.go @@ -338,7 +338,7 @@ func FilterCatalogByCategory(catalog map[string]*service.ComposeApp, category st return false } - return strings.ToLower(storeInfo.Category) == strings.ToLower(category) + return strings.EqualFold(storeInfo.Category, category) }) } @@ -352,13 +352,13 @@ func FilterCatalogByAuthorType(catalog map[string]*service.ComposeApp, authorTyp return map[string]*service.ComposeApp{} } - return lo.PickBy(catalog, func(storeAppID string, composeApp *service.ComposeApp) bool { + return lo.PickBy(catalog, func(_ string, composeApp *service.ComposeApp) bool { return composeApp.AuthorType() == authorType }) } func FilterCatalogByAppStoreID(catalog map[string]*service.ComposeApp, appStoreIDs []string) map[string]*service.ComposeApp { - return lo.PickBy(catalog, func(storeAppID string, composeApp *service.ComposeApp) bool { + return lo.PickBy(catalog, func(storeAppID string, _ *service.ComposeApp) bool { return lo.Contains(appStoreIDs, storeAppID) }) } @@ -404,10 +404,22 @@ func (a *AppManagement) UpgradableAppList(ctx echo.Context) error { status = codegen.Updating } + // not change the main tag + mainTag, err := composeApp.MainTag() + if err != nil { + logger.Error("failed to get main tag", zap.Error(err), zap.String("name", composeApp.Name)) + continue + } + + targetTag := tag + if lo.Contains(common.NeedCheckDigestTags, mainTag) { + targetTag = mainTag + } + if service.MyService.AppStoreManagement().IsUpdateAvailable(composeApp) { upgradableAppList = append(upgradableAppList, codegen.UpgradableAppInfo{ Title: string(title), - Version: tag, + Version: targetTag, StoreAppID: lo.ToPtr(id), Status: status, Icon: storeInfo.Icon, diff --git a/route/v2/compose_app.go b/route/v2/compose_app.go index ae71bf4b..75dd67d6 100644 --- a/route/v2/compose_app.go +++ b/route/v2/compose_app.go @@ -84,18 +84,27 @@ func (a *AppManagement) MyComposeApp(ctx echo.Context, id codegen.ComposeAppID) logger.Error("failed to get compose app status", zap.Error(err), zap.String("composeAppID", id)) } + // disable the because performance issue + // check update is hard and cost a lot of time. specially when the tag is latest + // such as Stable Diffusion. the check by ZimaOS GPU Application by @LinkLeong + // Alought @LinkLeong Didn't need the field. + // We should add a new API to get app info without update info + // and restore the following code + // check if updateAvailable - updateAvailable := service.MyService.AppStoreManagement().IsUpdateAvailable(composeApp) + // updateAvailable := service.MyService.AppStoreManagement().IsUpdateAvailable(composeApp) message := fmt.Sprintf("!! JSON format is for debugging purpose only - use `Accept: %s` HTTP header to get YAML instead !!", common.MIMEApplicationYAML) return ctx.JSON(http.StatusOK, codegen.ComposeAppOK{ // extension properties aren't marshalled - https://github.com/golang/go/issues/6213 Message: &message, Data: &codegen.ComposeAppWithStoreInfo{ - StoreInfo: storeInfo, - Compose: (*types.Project)(composeApp), - Status: &status, - UpdateAvailable: &updateAvailable, + StoreInfo: storeInfo, + Compose: (*types.Project)(composeApp), + Status: &status, + + // see above comment + UpdateAvailable: nil, }, }) } @@ -108,7 +117,7 @@ func (a *AppManagement) IsNewComposeUncontrolled(newComposeApp *service.ComposeA } // TODO refactor this. because if user not update. the status will be uncontrolled. - if newTag == "latest" { + if lo.Contains(common.NeedCheckDigestTags, newTag) { return false, nil } diff --git a/service/appstore_management.go b/service/appstore_management.go index 5c70755d..02b2691f 100644 --- a/service/appstore_management.go +++ b/service/appstore_management.go @@ -15,18 +15,16 @@ import ( "github.com/IceWhaleTech/CasaOS-Common/utils/file" "github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/bluele/gcache" - "github.com/docker/docker/client" "github.com/samber/lo" "go.uber.org/zap" ) type AppStoreManagement struct { + isAppUpgradable gcache.Cache + defaultAppStore AppStore + isAppUpgrading sync.Map onAppStoreRegister []func(string) error onAppStoreUnregister []func(string) error - - isAppUpgradable gcache.Cache - isAppUpgrading sync.Map - defaultAppStore AppStore } func (a *AppStoreManagement) AppStoreList() []codegen.AppStoreMetadata { @@ -481,29 +479,13 @@ func (a *AppStoreManagement) IsUpdateAvailableWith(composeApp *ComposeApp, store logger.Error("failed to get main service", zap.Error(err)) return false, err } - if currentTag == "latest" { - ctx := context.Background() - cli, clientErr := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if clientErr != nil { - logger.Error("failed to create docker client", zap.Error(clientErr)) - return false, clientErr - } - defer cli.Close() - - image, _ := docker.ExtractImageAndTag(mainService.Image) + if lo.Contains(common.NeedCheckDigestTags, currentTag) { - imageInfo, _, clientErr := cli.ImageInspectWithRaw(ctx, image) - if clientErr != nil { - logger.Error("failed to inspect image", zap.Error(clientErr)) - return false, clientErr - } - match, clientErr := docker.CompareDigest(mainService.Image, imageInfo.RepoDigests) - if clientErr != nil { - logger.Error("failed to compare digest", zap.Error(clientErr)) - return false, clientErr - } - // match means no update available - return !match, nil + _, _ = docker.ExtractImageAndTag(mainService.Image) + // TODO: refactor this. + // need to check the digest of the image + // to see if the image is updated + return false, nil } storeTag, err := storeComposeApp.MainTag() return currentTag != storeTag, err