diff --git a/artifact.go b/artifact.go index c68e637..bcb7b88 100644 --- a/artifact.go +++ b/artifact.go @@ -21,6 +21,11 @@ const ( artifactsPath = ".compose/artifacts" bumpSearchText = "versions bump" dirPermissions = 0755 + retryLimit = 50 +) + +var ( + errArtifactNotFound = errors.New("artifact was not found") ) // ArtifactStorage represents a storage for artifacts. @@ -39,24 +44,54 @@ func (s *ArtifactStorage) PrepareComparisonArtifact(comparisonDir string) error } log.Info("Repository name: %s", repoName) - var comparisonRef string + var archivePath string if s.override != "" { - comparisonRef = s.override + comparisonRef := s.override log.Info("OVERRIDDEN_COMPARISON_REF has been set: %s", s.override) - } else { - comparisonRef, err = s.repo.GetComparisonRef(bumpSearchText) + artifactFile, artifactPath := s.buildArtifactPaths(repoName, comparisonRef) + err = s.downloadArtifact(s.username, s.password, artifactFile, artifactPath, repoName) if err != nil { return err } - log.Info("Last bump commit identified: %s", comparisonRef) - } - artifactFile := fmt.Sprintf("%s-%s-plasma-src.tar.gz", repoName, comparisonRef) - artifactPath := filepath.Join(artifactsPath, artifactFile) + archivePath = artifactPath + } else { + hash, errHash := s.repo.git.ResolveRevision("HEAD~1") + if errHash != nil { + return errHash + } - err = s.downloadArtifact(s.username, s.password, artifactFile, artifactPath, repoName) - if err != nil { - return err + from := hash + retryCount := 0 + for retryCount < retryLimit { + comparisonHash, errHash := s.repo.GetComparisonCommit(*from, bumpSearchText) + if errHash != nil { + return errHash + } + + commit := []rune(comparisonHash.String()) + comparisonRef := string(commit[:7]) + + log.Info("Bump commit identified: %s", comparisonRef) + artifactFile, artifactPath := s.buildArtifactPaths(repoName, comparisonRef) + errDownload := s.downloadArtifact(s.username, s.password, artifactFile, artifactPath, repoName) + if errDownload != nil { + if errors.Is(errDownload, errArtifactNotFound) { + retryCount++ + from = comparisonHash + continue + } + + return errDownload + } + + archivePath = artifactPath + break + } + + if archivePath == "" { + return errArtifactNotFound + } } cli.Println("Processing...") @@ -64,7 +99,7 @@ func (s *ArtifactStorage) PrepareComparisonArtifact(comparisonDir string) error if err != nil { return err } - _, err = s.unarchiveTar(artifactPath, comparisonDir) + _, err = s.unarchiveTar(archivePath, comparisonDir) if err != nil { return err } @@ -72,6 +107,13 @@ func (s *ArtifactStorage) PrepareComparisonArtifact(comparisonDir string) error return nil } +func (s *ArtifactStorage) buildArtifactPaths(repoName, comparisonRef string) (string, string) { + artifactFile := fmt.Sprintf("%s-%s-plasma-src.tar.gz", repoName, comparisonRef) + artifactPath := filepath.Join(artifactsPath, artifactFile) + + return artifactFile, artifactPath +} + func (s *ArtifactStorage) prepareComparisonDir(path string) error { err := os.MkdirAll(path, dirPermissions) if err != nil { @@ -92,7 +134,7 @@ func (s *ArtifactStorage) downloadArtifact(username, password, artifactFile, art return nil } - cli.Println("Local artifact not found") + cli.Println("Local artifact %s not found", artifactFile) url := fmt.Sprintf("%s/repository/%s-artifacts/%s", artifactsRepositoryDomain, repo, artifactFile) cli.Println("Attempting to download artifact: %s", url) @@ -139,7 +181,7 @@ func (s *ArtifactStorage) downloadArtifact(username, password, artifactFile, art return errors.New("invalid credentials") } if statusCode == http.StatusNotFound { - return errors.New("artifact was not found") + return errArtifactNotFound } return fmt.Errorf("unexpected status code: %d while trying to get %s", statusCode, url) diff --git a/git.go b/git.go index c1776be..62f8451 100644 --- a/git.go +++ b/git.go @@ -7,6 +7,8 @@ import ( "strings" "time" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/storer" "github.com/go-git/go-git/v5" @@ -186,24 +188,21 @@ func (r *BumperRepo) GetRepoName() (string, error) { return "", errors.New("no remote was found") } -// GetComparisonRef returns the short hash of the commit that contains the specified search message. -// If the commit is found, the function will return the short hash. Otherwise, if the commit is not found in the search, -// or if there is an error resolving the revision or fetching the commit log, an error will be returned. -func (r *BumperRepo) GetComparisonRef(searchMessage string) (string, error) { - hash, err := r.git.ResolveRevision("HEAD~1") - if err != nil { - return "", err - } - - cIter, err := r.git.Log(&git.LogOptions{From: *hash}) +// GetComparisonCommit returns the commit that contains the specified search message. +func (r *BumperRepo) GetComparisonCommit(from plumbing.Hash, searchMessage string) (*plumbing.Hash, error) { + cIter, err := r.git.Log(&git.LogOptions{From: from}) if err != nil { - return "", err + return nil, err } - var commit []rune + var commit *plumbing.Hash err = cIter.ForEach(func(c *object.Commit) error { - if strings.Contains(c.Message, searchMessage) { - commit = []rune(c.Hash.String()) + if c.Hash == from { + return nil + } + + if strings.TrimSpace(c.Message) == searchMessage { + commit = &c.Hash return storer.ErrStop } @@ -211,13 +210,12 @@ func (r *BumperRepo) GetComparisonRef(searchMessage string) (string, error) { }) if err != nil { - return "", err + return nil, err } - if len(commit) == 0 { - return "", errors.New("unable to determine comparison ref (couldn't compute it)") + if commit == nil { + return nil, errors.New("unable to determine comparison commit (couldn't compute it)") } - shortCommit := string(commit[:7]) - return shortCommit, nil + return commit, nil }