fix(appstore): refresh cached resources and PHP versions

Version official app package and compose downloads using the synchronized store revision. Refresh outdated local resource caches and use synchronized database parameters for official PHP version options.
This commit is contained in:
zhengkunwang223
2026-10-22 11:53:36 +08:00
parent 15283fde34
commit 1e01761ba3
4 changed files with 91 additions and 29 deletions
+36 -15
View File
@@ -258,26 +258,35 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response.
fileOp := files.NewFileOp()
versionPath := filepath.Join(app.GetAppResourcePath(), detail.Version)
if !fileOp.Stat(versionPath) || detail.Update {
if err = downloadApp(app, detail, nil, nil); err != nil && !fileOp.Stat(versionPath) {
return appDetailDTO, err
}
if err = downloadApp(app, detail, nil, nil); err != nil && !fileOp.Stat(versionPath) {
return appDetailDTO, err
}
if err == nil && app.Resource == constant.AppResourceRemote {
detail.Update = false
appDetailDTO.Update = false
}
switch app.Type {
case constant.RuntimePHP:
paramsPath := filepath.Join(versionPath, "data.yml")
if !fileOp.Stat(paramsPath) {
return appDetailDTO, buserr.WithDetail("ErrFileNotExist", paramsPath, nil)
}
param, err := fileOp.GetContent(paramsPath)
if err != nil {
return appDetailDTO, err
}
paramMap := make(map[string]interface{})
if err = yaml.Unmarshal(param, &paramMap); err != nil {
return appDetailDTO, err
if app.Resource == constant.AppResourceRemote {
if err = json.Unmarshal([]byte(detail.Params), &paramMap); err != nil {
return appDetailDTO, err
}
appDetailDTO.Params = paramMap
} else {
paramsPath := filepath.Join(versionPath, "data.yml")
if !fileOp.Stat(paramsPath) {
return appDetailDTO, buserr.WithDetail("ErrFileNotExist", paramsPath, nil)
}
param, err := fileOp.GetContent(paramsPath)
if err != nil {
return appDetailDTO, err
}
if err = yaml.Unmarshal(param, &paramMap); err != nil {
return appDetailDTO, err
}
appDetailDTO.Params = paramMap["additionalProperties"]
}
appDetailDTO.Params = paramMap["additionalProperties"]
composePath := filepath.Join(versionPath, "docker-compose.yml")
if !fileOp.Stat(composePath) {
return appDetailDTO, buserr.WithDetail("ErrFileNotExist", composePath, nil)
@@ -308,6 +317,12 @@ func (a AppService) GetAppDetail(appID uint, version, appType string) (response.
if appDetailDTO.DockerCompose == "" {
filename := filepath.Base(appDetailDTO.DownloadUrl)
dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(appDetailDTO.DownloadUrl, filename), "docker-compose.yml")
if app.Resource == constant.AppResourceRemote {
dockerComposeUrl, err = currentAppDownloadURL(dockerComposeUrl)
if err != nil {
return appDetailDTO, err
}
}
statusCode, composeRes, err := req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
if statusCode == http.StatusNotFound {
return appDetailDTO, buserr.New("ErrAppVersionUnavailable")
@@ -434,6 +449,12 @@ func (a AppService) installWithHooks(req request.AppInstallCreate, executeScript
} else {
if appDetail.DockerCompose == "" {
dockerComposeUrl := fmt.Sprintf("%s/%s/1panel/%s/%s/docker-compose.yml", global.AppRepoURL(), global.CONF.Base.Mode, app.Key, appDetail.Version)
if app.Resource == constant.AppResourceRemote {
dockerComposeUrl, err = currentAppDownloadURL(dockerComposeUrl)
if err != nil {
return
}
}
var statusCode int
statusCode, composeRes, err = req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
if statusCode == http.StatusNotFound {
+6
View File
@@ -707,6 +707,12 @@ func (a *AppInstallService) GetUpdateVersions(req request.AppUpdateVersion) ([]d
if req.UpdateVersion != "" && req.UpdateVersion == detail.Version && detail.DockerCompose == "" && !app.IsLocalApp() {
filename := filepath.Base(detail.DownloadUrl)
dockerComposeUrl := fmt.Sprintf("%s%s", strings.TrimSuffix(detail.DownloadUrl, filename), "docker-compose.yml")
if app.Resource == constant.AppResourceRemote {
dockerComposeUrl, err = currentAppDownloadURL(dockerComposeUrl)
if err != nil {
return versions, err
}
}
statusCode, composeRes, err := req_helper.HandleRequest(dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
if statusCode == http.StatusNotFound {
return versions, buserr.New("ErrAppVersionUnavailable")
+5 -1
View File
@@ -191,7 +191,11 @@ func (c *appSyncContext) processOneApp(item appWorkItem) appWorkResult {
if _, ok := InitTypes[app.Type]; ok {
dockerComposeUrl := fmt.Sprintf("%s/%s", versionUrl, "docker-compose.yml")
_, composeRes, err := req_helper.HandleRequestWithClient(&c.httpClient, dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
dockerComposeUrl, err := appDownloadURL(dockerComposeUrl, strconv.Itoa(c.list.LastModified))
var composeRes []byte
if err == nil {
_, composeRes, err = req_helper.HandleRequestWithClient(&c.httpClient, dockerComposeUrl, http.MethodGet, constant.TimeOut20s)
}
if err == nil {
detail.DockerCompose = string(composeRes)
} else {
+44 -13
View File
@@ -8,6 +8,7 @@ import (
"maps"
"math"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
@@ -891,16 +892,52 @@ func handleMap(params map[string]interface{}, envParams map[string]string) {
}
}
func appDownloadURL(rawURL, version string) (string, error) {
parsedURL, err := url.Parse(rawURL)
if err != nil {
return "", err
}
query := parsedURL.Query()
query.Set("v", version)
parsedURL.RawQuery = query.Encode()
return parsedURL.String(), nil
}
func currentAppDownloadURL(rawURL string) (string, error) {
storeVersion, err := settingRepo.GetValueByKey("AppStoreLastModified")
if err != nil {
return "", err
}
return appDownloadURL(rawURL, storeVersion)
}
func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.AppInstall, logger *logrus.Logger) (err error) {
if app.IsLocalApp() || app.IsCustomApp() {
return nil
}
defer func() {
if err != nil && appInstall != nil {
appInstall.Status = constant.StatusDownloadErr
appInstall.Message = err.Error()
}
}()
appResourceDir := path.Join(global.Dir.AppResourceDir, app.Resource)
appDownloadDir := app.GetAppResourcePath()
appVersionDir := path.Join(appDownloadDir, appDetail.Version)
fileOp := files.NewFileOp()
storeVersion, err := settingRepo.GetValueByKey("AppStoreLastModified")
if err != nil {
return err
}
cacheVersionPath := path.Join(appVersionDir, ".1panel-appstore-version")
if !appDetail.Update && fileOp.Stat(appVersionDir) {
return
if cachedVersion, readErr := os.ReadFile(cacheVersionPath); readErr == nil && string(cachedVersion) == storeVersion {
return nil
}
}
downloadURL, err := appDownloadURL(appDetail.DownloadUrl, storeVersion)
if err != nil {
return err
}
if !fileOp.Stat(appDownloadDir) {
_ = fileOp.CreateDir(appDownloadDir, constant.DirPerm)
@@ -909,23 +946,14 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
_ = fileOp.CreateDir(appVersionDir, constant.DirPerm)
}
if logger == nil {
global.LOG.Infof("download app [%s] from %s", app.Name, appDetail.DownloadUrl)
global.LOG.Infof("download app [%s] from %s", app.Name, downloadURL)
} else {
logger.Printf("download app [%s] from %s", app.Name, appDetail.DownloadUrl)
logger.Printf("download app [%s] from %s", app.Name, downloadURL)
}
filePath := path.Join(appVersionDir, app.Key+"-"+appDetail.Version+".tar.gz")
defer func() {
if err != nil {
if appInstall != nil {
appInstall.Status = constant.StatusDownloadErr
appInstall.Message = err.Error()
}
}
}()
if err = files.DownloadFileWithProxy(appDetail.DownloadUrl, filePath); err != nil {
if err = files.DownloadFileWithProxy(downloadURL, filePath); err != nil {
if logger == nil {
global.LOG.Errorf("download app [%s] error %v", app.Name, err)
} else {
@@ -942,6 +970,9 @@ func downloadApp(app model.App, appDetail model.AppDetail, appInstall *model.App
return
}
_ = fileOp.DeleteFile(filePath)
if err = os.WriteFile(cacheVersionPath, []byte(storeVersion), constant.FilePerm); err != nil {
return err
}
appDetail.Update = false
_ = appDetailRepo.Update(context.Background(), appDetail)
return