github.com/bitrise-io/go-steputils/v2@v2.0.0-alpha.30/cache/save_skip.go (about)

     1  package cache
     2  
     3  import (
     4  	"strings"
     5  )
     6  
     7  type skipReason int
     8  
     9  const (
    10  	reasonKeyNotDynamic skipReason = iota
    11  	reasonNoRestore
    12  	reasonRestoreSameUniqueKey
    13  	reasonRestoreSameKeyNotUnique
    14  	reasonNoRestoreThisKey
    15  	reasonNewArchiveChecksumMatch
    16  	reasonNewArchiveChecksumMismatch
    17  )
    18  
    19  func (r skipReason) String() string {
    20  	switch r {
    21  	case reasonKeyNotDynamic:
    22  		return "key_not_dynamic"
    23  	case reasonNoRestore:
    24  		return "no_restore_found"
    25  	case reasonRestoreSameUniqueKey:
    26  		return "restore_same_unique_key"
    27  	case reasonRestoreSameKeyNotUnique:
    28  		return "restore_same_key_not_unique"
    29  	case reasonNoRestoreThisKey:
    30  		return "no_restore_with_this_key"
    31  	case reasonNewArchiveChecksumMatch:
    32  		return "new_archive_checksum_match"
    33  	case reasonNewArchiveChecksumMismatch:
    34  		return "new_archive_checksum_mismatch"
    35  	default:
    36  		return "unknown"
    37  	}
    38  }
    39  
    40  func (r skipReason) description() string {
    41  	switch r {
    42  	case reasonKeyNotDynamic:
    43  		return "key is not dynamic; the expectation is that the same key is used for saving different cache contents over and over"
    44  	case reasonNoRestore:
    45  		return "no cache was restored in the workflow, creating a new cache entry"
    46  	case reasonRestoreSameUniqueKey:
    47  		return "a cache with the same key was restored in the workflow, new cache would have the same content"
    48  	case reasonRestoreSameKeyNotUnique:
    49  		return "a cache with the same key was restored in the workflow, but contents might have changed since then"
    50  	case reasonNoRestoreThisKey:
    51  		return "there was no cache restore in the workflow with this key, but was for other(s)"
    52  	case reasonNewArchiveChecksumMatch:
    53  		return "new cache archive is the same as the restored one"
    54  	case reasonNewArchiveChecksumMismatch:
    55  		return "new cache archive contains changed files"
    56  	default:
    57  		return "unrecognized skipReason"
    58  	}
    59  }
    60  
    61  func (s *saver) canSkipSave(keyTemplate, evaluatedKey string, isKeyUnique bool) (bool, skipReason) {
    62  	if keyTemplate == evaluatedKey {
    63  		return false, reasonKeyNotDynamic
    64  	}
    65  
    66  	cacheHits := s.getCacheHits()
    67  	if len(cacheHits) == 0 {
    68  		return false, reasonNoRestore
    69  	}
    70  
    71  	if _, ok := cacheHits[evaluatedKey]; ok {
    72  		if isKeyUnique {
    73  			return true, reasonRestoreSameUniqueKey
    74  		} else {
    75  			return false, reasonRestoreSameKeyNotUnique
    76  		}
    77  	}
    78  
    79  	return false, reasonNoRestoreThisKey
    80  }
    81  
    82  func (s *saver) canSkipUpload(newCacheKey, newCacheChecksum string) (bool, skipReason) {
    83  	cacheHits := s.getCacheHits()
    84  
    85  	if len(cacheHits) == 0 {
    86  		return false, reasonNoRestore
    87  	}
    88  
    89  	checksumForNewKey, ok := cacheHits[newCacheKey]
    90  	if !ok {
    91  		return false, reasonNoRestoreThisKey
    92  	}
    93  	if checksumForNewKey == newCacheChecksum {
    94  		return true, reasonNewArchiveChecksumMatch
    95  	}
    96  
    97  	return false, reasonNewArchiveChecksumMismatch
    98  }
    99  
   100  // Returns cache hit information exposed by previous restore cache steps.
   101  // The returned map's key is the restored cache key, and the value is the checksum of the cache archive
   102  func (s *saver) getCacheHits() map[string]string {
   103  	cacheHits := map[string]string{}
   104  	for _, e := range s.envRepo.List() {
   105  		envParts := strings.SplitN(e, "=", 2)
   106  		if len(envParts) < 2 {
   107  			continue
   108  		}
   109  		envKey := envParts[0]
   110  		envValue := envParts[1]
   111  
   112  		if strings.HasPrefix(envKey, cacheHitUniqueEnvVarPrefix) {
   113  			cacheKey := strings.TrimPrefix(envKey, cacheHitUniqueEnvVarPrefix)
   114  			cacheHits[cacheKey] = envValue
   115  		}
   116  	}
   117  	return cacheHits
   118  }
   119  
   120  func (s *saver) logOtherHits() {
   121  	otherKeys := []string{}
   122  	for k := range s.getCacheHits() {
   123  		otherKeys = append(otherKeys, k)
   124  	}
   125  	if len(otherKeys) == 0 {
   126  		return
   127  	}
   128  	s.logger.Printf("Other restored cache keys:")
   129  	s.logger.Printf(strings.Join(otherKeys, "\n"))
   130  }