diff --git a/coverage-badge.svg b/coverage-badge.svg index 0001913..00bed39 100644 --- a/coverage-badge.svg +++ b/coverage-badge.svg @@ -2,5 +2,5 @@ coverage - 57.4% + 58.5% diff --git a/internal/app/app.go b/internal/app/app.go index 6bea852..499b013 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -121,7 +121,7 @@ func (app *App) Run() { }, ) - err := app.repo.ForceUpdate() + err := app.repo.Update(false) if err != nil { panic(err) } diff --git a/internal/services/cronservice/service.go b/internal/services/cronservice/service.go index 3b85f7e..33b20d8 100644 --- a/internal/services/cronservice/service.go +++ b/internal/services/cronservice/service.go @@ -7,7 +7,7 @@ import ( ) type RepoService interface { - ForceUpdate() error + Update(bool) error } type Service struct { @@ -37,11 +37,11 @@ func (s *Service) SetupCronJobs() { gocron.CronJob("0 4 * * *", false), gocron.NewTask(func() { log.Info( - "[cron] force update is started", + "[cron] update is started", ) - err := s.repoService.ForceUpdate() + err := s.repoService.Update(false) if err != nil { - log.Error("[cron] force update error", map[string]interface{}{ + log.Error("[cron] update error", map[string]interface{}{ "err": err, }) } diff --git a/internal/services/reposervice/service.go b/internal/services/reposervice/service.go index a987dd1..10e40f1 100644 --- a/internal/services/reposervice/service.go +++ b/internal/services/reposervice/service.go @@ -48,7 +48,31 @@ func (s *Service) oldRepoPathPrefix() string { ) } -func (s *Service) ForceUpdate() error { +func (s *Service) prepareForUpdate() error { + err := os.MkdirAll(s.futureRepoPathPrefix(), os.ModePerm) + if err != nil { + return err + } + + err = os.MkdirAll(s.oldRepoPathPrefix(), os.ModePerm) + if err != nil { + return err + } + + err = os.MkdirAll(s.currentRepoPathPrefix(), os.ModePerm) + if err != nil { + return err + } + + return nil +} + +func (s *Service) cleanUpAfterUpdate() { + os.RemoveAll(s.futureRepoPathPrefix()) + os.RemoveAll(s.oldRepoPathPrefix()) +} + +func (s *Service) Update(force bool) error { const REPO_NAME = "aides" architectures := []string{ @@ -63,22 +87,7 @@ func (s *Service) ForceUpdate() error { log := logger.GetLogger() log.Info("Start repo update") - err := os.MkdirAll(s.futureRepoPathPrefix(), os.ModePerm) - if err != nil { - return err - } - defer os.RemoveAll(s.futureRepoPathPrefix()) - - err = os.MkdirAll(s.oldRepoPathPrefix(), os.ModePerm) - if err != nil { - return err - } - defer os.RemoveAll(s.oldRepoPathPrefix()) - - err = os.MkdirAll(s.currentRepoPathPrefix(), os.ModePerm) - if err != nil { - return err - } + preparedForUpdate := false for _, r := range repos { var tasks []models.Task @@ -86,9 +95,39 @@ func (s *Service) ForceUpdate() error { Name: r, } - s.db. + if err := s.db. Where(&altRepo). - First(&altRepo) + First(&altRepo).Error; err != nil { + return err + } + + var exists bool + if err := s.db. + Model(&models.GitRepoAltRepoTask{}). + Select("1"). + Where("alt_repo_id = ?", altRepo.ID). + Where("last_task_id != current_task_id"). + Limit(1). + Scan(&exists).Error; err != nil { + return err + } + + if !force && !exists { + log.Info( + "No updates found for ALTRepo, skipping.", + map[string]interface{}{ + "repo": altRepo.Name, + }) + continue + } + + if !preparedForUpdate { + if err := s.prepareForUpdate(); err != nil { + return err + } + defer s.cleanUpAfterUpdate() + } + preparedForUpdate = true s.db. Model(&models.GitRepoAltRepoTask{}). diff --git a/tests/integration/reposervice_forceupdate_test.go b/tests/integration/reposervice_forceupdate_test.go index d2e12bc..e41f0fb 100644 --- a/tests/integration/reposervice_forceupdate_test.go +++ b/tests/integration/reposervice_forceupdate_test.go @@ -13,41 +13,145 @@ import ( ) func TestRepoService_ForceUpdate(t *testing.T) { - db := prepareDb(t) - config := prepareConfig() + t.Run("Correct update (new)", func(t *testing.T) { + // PREPARE + db := prepareDb(t) + config := prepareConfig() - os.MkdirAll(config.GetUploadDir(), os.ModePerm) + os.MkdirAll(config.GetUploadDir(), os.ModePerm) - taskPath := path.Join(config.GetUploadDir(), "tasks/1") + taskPath := path.Join(config.GetUploadDir(), "tasks/1") - os.MkdirAll(taskPath, os.ModePerm) - defer os.RemoveAll(config.GetUploadDir()) + os.MkdirAll(taskPath, os.ModePerm) + defer os.RemoveAll(config.GetUploadDir()) - fileName := "example-foo-1.0.0-alt1.x86_64.rpm" + fileName := "example-foo-1.0.0-alt1.x86_64.rpm" - source, err := os.Open(path.Join("./test_rpms", fileName)) - assert.NoError(t, err) - destination, err := os.Create(path.Join(taskPath, fileName)) - assert.NoError(t, err) - defer destination.Close() - _, err = io.Copy(destination, source) - assert.NoError(t, err) + source, err := os.Open(path.Join("./test_rpms", fileName)) + assert.NoError(t, err) + destination, err := os.Create(path.Join(taskPath, fileName)) + assert.NoError(t, err) + defer destination.Close() + _, err = io.Copy(destination, source) + assert.NoError(t, err) - source.Close() - destination.Close() + source.Close() + destination.Close() - gitRepo := &models.GitRepo{ - Name: "example-foo", - } + gitRepo := &models.GitRepo{ + Name: "example-foo", + } - altRepo := &models.ALTRepo{ - Name: "Sisyphus", - } + altRepo := &models.ALTRepo{ + Name: "Sisyphus", + } - db.Create(&models.GitRepoAltRepoTask{ - Repo: gitRepo, - ALTRepo: altRepo, - CurrentTask: &models.Task{ + db.Create(&models.GitRepoAltRepoTask{ + Repo: gitRepo, + ALTRepo: altRepo, + CurrentTask: &models.Task{ + Status: models.StatusCompleted, + Files: []models.RPMFile{ + { + Filename: "---", + Name: "example-foo", + Version: "0.9.9", + Release: "1", + Arch: "x86_64", + Epoch: 0, + }, + }, + }, + LastTask: &models.Task{ + Status: models.StatusCompleted, + Files: []models.RPMFile{ + { + Filename: fileName, + Name: "example-foo", + Version: "1.0.0", + Release: "1", + Arch: "x86_64", + Epoch: 0, + }, + }, + }, + }) + + service := reposervice.New( + db, + config, + ) + + // EXECUTE + err = service.Update(false) + + // CHECK + assert.NoError(t, err) + // TODO: check db + repoBasePath := path.Join(config.GetUploadDir(), "repo", "Sisyphus") + x86_64BasePath := path.Join(repoBasePath, "x86_64", "base") + x86_64RPMSPath := path.Join(repoBasePath, "x86_64", "RPMS.aides") + noarchBasePath := path.Join(repoBasePath, "noarch", "base") + + expectedFiles := []string{ + path.Join(x86_64BasePath, "pkglist.aides"), + path.Join(x86_64BasePath, "pkglist.aides.bz2"), + path.Join(x86_64BasePath, "pkglist.aides.xz"), + path.Join(x86_64BasePath, "release"), + path.Join(x86_64BasePath, "release.aides"), + path.Join(x86_64RPMSPath, fileName), + path.Join(noarchBasePath, "pkglist.aides"), + path.Join(noarchBasePath, "pkglist.aides.bz2"), + path.Join(noarchBasePath, "pkglist.aides.xz"), + path.Join(noarchBasePath, "release"), + path.Join(noarchBasePath, "release.aides"), + } + + for _, filePath := range expectedFiles { + _, err := os.Stat(filePath) + assert.NoErrorf(t, err, "Файл %s не найден", filePath) + } + + rpmPath := path.Join(x86_64RPMSPath, fileName) + linkDest, err := os.Readlink(rpmPath) + assert.NoError(t, err) + assert.Equal(t, path.Join("../../../../tasks/1", fileName), linkDest) + }) + + t.Run("Do not do anything if no updates", func(t *testing.T) { + // PREPARE + db := prepareDb(t) + config := prepareConfig() + + os.MkdirAll(config.GetUploadDir(), os.ModePerm) + + taskPath := path.Join(config.GetUploadDir(), "tasks/1") + + os.MkdirAll(taskPath, os.ModePerm) + defer os.RemoveAll(config.GetUploadDir()) + + fileName := "example-foo-1.0.0-alt1.x86_64.rpm" + + source, err := os.Open(path.Join("./test_rpms", fileName)) + assert.NoError(t, err) + destination, err := os.Create(path.Join(taskPath, fileName)) + assert.NoError(t, err) + defer destination.Close() + _, err = io.Copy(destination, source) + assert.NoError(t, err) + + source.Close() + destination.Close() + + gitRepo := &models.GitRepo{ + Name: "example-foo", + } + + altRepo := &models.ALTRepo{ + Name: "Sisyphus", + } + + task := &models.Task{ Status: models.StatusCompleted, Files: []models.RPMFile{ { @@ -59,58 +163,27 @@ func TestRepoService_ForceUpdate(t *testing.T) { Epoch: 0, }, }, - }, - LastTask: &models.Task{ - Status: models.StatusCompleted, - Files: []models.RPMFile{ - { - Filename: fileName, - Name: "example-foo", - Version: "1.0.0", - Release: "1", - Arch: "x86_64", - Epoch: 0, - }, - }, - }, + } + + db.Create(&models.GitRepoAltRepoTask{ + Repo: gitRepo, + ALTRepo: altRepo, + CurrentTask: task, + LastTask: task, + }) + + service := reposervice.New( + db, + config, + ) + + // EXECUTE + err = service.Update(false) + + // СHECK + assert.NoError(t, err) + repoBasePath := path.Join(config.GetUploadDir(), "repo", "Sisyphus") + _, err = os.Stat(repoBasePath) + assert.True(t, os.IsNotExist(err)) }) - - service := reposervice.New( - db, - config, - ) - - // EXECUTE - err = service.ForceUpdate() - - assert.NoError(t, err) - // TODO: check db - repoBasePath := path.Join(config.GetUploadDir(), "repo", "Sisyphus") - x86_64BasePath := path.Join(repoBasePath, "x86_64", "base") - x86_64RPMSPath := path.Join(repoBasePath, "x86_64", "RPMS.aides") - noarchBasePath := path.Join(repoBasePath, "noarch", "base") - - expectedFiles := []string{ - path.Join(x86_64BasePath, "pkglist.aides"), - path.Join(x86_64BasePath, "pkglist.aides.bz2"), - path.Join(x86_64BasePath, "pkglist.aides.xz"), - path.Join(x86_64BasePath, "release"), - path.Join(x86_64BasePath, "release.aides"), - path.Join(x86_64RPMSPath, fileName), - path.Join(noarchBasePath, "pkglist.aides"), - path.Join(noarchBasePath, "pkglist.aides.bz2"), - path.Join(noarchBasePath, "pkglist.aides.xz"), - path.Join(noarchBasePath, "release"), - path.Join(noarchBasePath, "release.aides"), - } - - for _, filePath := range expectedFiles { - _, err := os.Stat(filePath) - assert.NoErrorf(t, err, "Файл %s не найден", filePath) - } - - rpmPath := path.Join(x86_64RPMSPath, fileName) - linkDest, err := os.Readlink(rpmPath) - assert.NoError(t, err) - assert.Equal(t, path.Join("../../../../tasks/1", fileName), linkDest) }