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 }