From 21c0493ecfd34b1217f0a90ec19a327f3cc0a048 Mon Sep 17 00:00:00 2001
From: Alexey <1337kwiz@gmail.com>
Date: Tue, 5 Apr 2022 06:57:13 -0700
Subject: [PATCH] Cache hit output (#373)

* Remove useless await in getCacheDistributor calls

* Added cache-hit output

* Build action with cache-hit output

* Remove PromiseReturnType, add matchedKey == primaryKey check

* Update cache-distributor.ts

* Fix tests and rebuild
---
 __tests__/cache-restore.test.ts              | 42 ++++++++++++++++++--
 action.yml                                   |  2 +
 dist/cache-save/index.js                     | 18 +++++----
 dist/setup/index.js                          | 18 +++++----
 src/cache-distributions/cache-distributor.ts |  5 +++
 5 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/__tests__/cache-restore.test.ts b/__tests__/cache-restore.test.ts
index 4dce56a1..99b674ef 100644
--- a/__tests__/cache-restore.test.ts
+++ b/__tests__/cache-restore.test.ts
@@ -27,6 +27,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/patrick/Library/Caches/py
   let debugSpy: jest.SpyInstance;
   let saveSatetSpy: jest.SpyInstance;
   let getStateSpy: jest.SpyInstance;
+  let setOutputSpy: jest.SpyInstance;
 
   // cache spy
   let restoreCacheSpy: jest.SpyInstance;
@@ -64,6 +65,9 @@ virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/patrick/Library/Caches/py
       return {stdout: '', stderr: 'Error occured', exitCode: 2};
     });
 
+    setOutputSpy = jest.spyOn(core, 'setOutput');
+    setOutputSpy.mockImplementation(input => undefined);
+
     restoreCacheSpy = jest.spyOn(cache, 'restoreCache');
     restoreCacheSpy.mockImplementation(
       (cachePaths: string[], primaryKey: string, restoreKey?: string) => {
@@ -100,7 +104,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/patrick/Library/Caches/py
     ])(
       'restored dependencies for %s by primaryKey',
       async (packageManager, pythonVersion, dependencyFile, fileHash) => {
-        const cacheDistributor = await getCacheDistributor(
+        const cacheDistributor = getCacheDistributor(
           packageManager,
           pythonVersion,
           dependencyFile
@@ -126,7 +130,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/patrick/Library/Caches/py
         dependencyFile,
         cacheDependencyPath
       ) => {
-        const cacheDistributor = await getCacheDistributor(
+        const cacheDistributor = getCacheDistributor(
           packageManager,
           pythonVersion,
           dependencyFile
@@ -162,7 +166,7 @@ virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/patrick/Library/Caches/py
             return primaryKey !== fileHash && restoreKey ? pipFileLockHash : '';
           }
         );
-        const cacheDistributor = await getCacheDistributor(
+        const cacheDistributor = getCacheDistributor(
           packageManager,
           pythonVersion,
           dependencyFile
@@ -187,6 +191,38 @@ virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/patrick/Library/Caches/py
     );
   });
 
+  describe('Check if handleMatchResult', () => {
+    it.each([
+      ['pip', '3.8.12', 'requirements.txt', 'someKey', 'someKey', true],
+      ['pipenv', '3.9.1', 'requirements.txt', 'someKey', 'someKey', true],
+      ['poetry', '3.8.12', 'requirements.txt', 'someKey', 'someKey', true],
+      ['pip', '3.9.2', 'requirements.txt', undefined, 'someKey', false],
+      ['pipenv', '3.8.12', 'requirements.txt', undefined, 'someKey', false],
+      ['poetry', '3.9.12', 'requirements.txt', undefined, 'someKey', false]
+    ])(
+      'sets correct outputs',
+      async (
+        packageManager,
+        pythonVersion,
+        dependencyFile,
+        matchedKey,
+        restoredKey,
+        expectedOutputValue
+      ) => {
+        const cacheDistributor = getCacheDistributor(
+          packageManager,
+          pythonVersion,
+          dependencyFile
+        );
+        cacheDistributor.handleMatchResult(matchedKey, restoredKey);
+        expect(setOutputSpy).toHaveBeenCalledWith(
+          'cache-hit',
+          expectedOutputValue
+        );
+      }
+    );
+  });
+
   afterEach(() => {
     jest.resetAllMocks();
     jest.clearAllMocks();
diff --git a/action.yml b/action.yml
index bd9ee686..bda521dd 100644
--- a/action.yml
+++ b/action.yml
@@ -19,6 +19,8 @@ inputs:
 outputs:
   python-version:
     description: "The installed python version. Useful when given a version range as input."
+  cache-hit:
+    description: 'A boolean value to indicate a cache entry was found'
 runs:
   using: 'node16'
   main: 'dist/setup/index.js'
diff --git a/dist/cache-save/index.js b/dist/cache-save/index.js
index bf48c7a6..c1c654f2 100644
--- a/dist/cache-save/index.js
+++ b/dist/cache-save/index.js
@@ -37234,15 +37234,19 @@ class CacheDistributor {
             core.saveState(State.CACHE_PATHS, cachePath);
             core.saveState(State.STATE_CACHE_PRIMARY_KEY, primaryKey);
             const matchedKey = yield cache.restoreCache(cachePath, primaryKey, restoreKey);
-            if (matchedKey) {
-                core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
-                core.info(`Cache restored from key: ${matchedKey}`);
-            }
-            else {
-                core.info(`${this.packageManager} cache is not found`);
-            }
+            this.handleMatchResult(matchedKey, primaryKey);
         });
     }
+    handleMatchResult(matchedKey, primaryKey) {
+        if (matchedKey) {
+            core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
+            core.info(`Cache restored from key: ${matchedKey}`);
+        }
+        else {
+            core.info(`${this.packageManager} cache is not found`);
+        }
+        core.setOutput('cache-hit', matchedKey === primaryKey);
+    }
 }
 exports.default = CacheDistributor;
 
diff --git a/dist/setup/index.js b/dist/setup/index.js
index d272c828..e4e67083 100644
--- a/dist/setup/index.js
+++ b/dist/setup/index.js
@@ -42579,15 +42579,19 @@ class CacheDistributor {
             core.saveState(State.CACHE_PATHS, cachePath);
             core.saveState(State.STATE_CACHE_PRIMARY_KEY, primaryKey);
             const matchedKey = yield cache.restoreCache(cachePath, primaryKey, restoreKey);
-            if (matchedKey) {
-                core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
-                core.info(`Cache restored from key: ${matchedKey}`);
-            }
-            else {
-                core.info(`${this.packageManager} cache is not found`);
-            }
+            this.handleMatchResult(matchedKey, primaryKey);
         });
     }
+    handleMatchResult(matchedKey, primaryKey) {
+        if (matchedKey) {
+            core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
+            core.info(`Cache restored from key: ${matchedKey}`);
+        }
+        else {
+            core.info(`${this.packageManager} cache is not found`);
+        }
+        core.setOutput('cache-hit', matchedKey === primaryKey);
+    }
 }
 exports.default = CacheDistributor;
 
diff --git a/src/cache-distributions/cache-distributor.ts b/src/cache-distributions/cache-distributor.ts
index ef0be0ef..f24c78da 100644
--- a/src/cache-distributions/cache-distributor.ts
+++ b/src/cache-distributions/cache-distributor.ts
@@ -41,12 +41,17 @@ abstract class CacheDistributor {
       restoreKey
     );
 
+    this.handleMatchResult(matchedKey, primaryKey);
+  }
+
+  public handleMatchResult(matchedKey: string | undefined, primaryKey: string) {
     if (matchedKey) {
       core.saveState(State.CACHE_MATCHED_KEY, matchedKey);
       core.info(`Cache restored from key: ${matchedKey}`);
     } else {
       core.info(`${this.packageManager} cache is not found`);
     }
+    core.setOutput('cache-hit', matchedKey === primaryKey);
   }
 }