diff --git a/.envrc b/.envrc index 7e43a1c..9fdf4e8 100644 --- a/.envrc +++ b/.envrc @@ -1,2 +1,2 @@ source_up -use node v16 +use node v24 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 42a6cc4..b98610c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,17 +15,17 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: - node-version: "20.x" + node-version: "24.x" - name: Install Yarn run: npm install -g yarn - name: Get yarn cache directory path id: yarn-cache-dir-path run: echo "::set-output name=dir::$(yarn cache dir)" - - uses: actions/cache@v3 + - uses: actions/cache@v5 id: yarn-cache with: path: ${{ steps.yarn-cache-dir-path.outputs.dir }} diff --git a/.github/workflows/lookup-only.yaml b/.github/workflows/lookup-only.yaml index 9990686..4a5b515 100644 --- a/.github/workflows/lookup-only.yaml +++ b/.github/workflows/lookup-only.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Generate files in working directory shell: bash run: src/create-cache-files.sh ${{ runner.os }} test-cache @@ -46,7 +46,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Lookup cache id: lookup uses: ./ diff --git a/.github/workflows/test-env.yaml b/.github/workflows/test-env.yaml index 2b09bfc..4bfb473 100644 --- a/.github/workflows/test-env.yaml +++ b/.github/workflows/test-env.yaml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Generate files in working directory shell: bash run: src/create-cache-files.sh ${{ runner.os }} test-cache @@ -47,7 +47,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Restore cache uses: ./ env: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9967513..b30960e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Generate files in working directory shell: bash run: src/create-cache-files.sh ${{ runner.os }} test-cache @@ -44,7 +44,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Restore cache uses: ./ with: @@ -73,7 +73,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Restore cache uses: ./ with: @@ -102,7 +102,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Generate files in working directory shell: bash run: src/create-cache-files.sh ${{ runner.os }} test-cache @@ -131,7 +131,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Restore cache uses: ./restore/ with: diff --git a/README.md b/README.md index 55a679a..efef710 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This action enables caching dependencies to s3 compatible storage, e.g. minio, AWS S3 -It also has github [actions/cache@v2](https://github.com/actions/cache) fallback if s3 save & restore fails +It also has github [actions/cache@v5](https://github.com/actions/cache) fallback if s3 save & restore fails ## Usage @@ -113,9 +113,30 @@ To check if cache hits and size is not zero without downloading: ## Restore keys -`restore-keys` works similar to how github's `@actions/cache@v2` works: It search each item in `restore-keys` +`restore-keys` works similar to how github's `@actions/cache@v5` works: It search each item in `restore-keys` as prefix in object names and use the latest one +To restore from the cache using a `restore-key` prefix if the `key` restore fails: + +```yaml + - uses: tespkg/actions-cache/restore@v1 + with: + accessKey: "Q3AM3UQ867SPQQA43P2F" # required + secretKey: "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG" # required + bucket: actions-cache # required + # actions/cache compatible properties: https://github.com/actions/cache + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + ${{ runner.os }}- + path: | + node_modules +``` + +If a match is found using one of the `restore-keys` options, then `cache-hit` will be FALSE but the +`cache-matched-key` output will be set to the key that matched. See the +[actions/cache](https://github.com/actions/cache/blob/main/restore/README.md#outputs) notes. + ## Amazon S3 permissions When using this with Amazon S3, the following permissions are necessary: diff --git a/action.yml b/action.yml index 42f9a6f..bd3365d 100644 --- a/action.yml +++ b/action.yml @@ -1,6 +1,6 @@ name: "s3 cache" author: tespkg -description: "S3 actions cache with actions/cache@v2 passthrough" +description: "S3 actions cache with actions/cache@v5 passthrough" inputs: endpoint: description: "s3 / minio endpoint, see: https://docs.min.io/docs/javascript-client-api-reference.html" @@ -57,8 +57,10 @@ outputs: description: "A boolean value to indicate an exact match was found for the primary key" cache-size: description: "A integer value denoting the size of the cache object found (measured in bytes)" + cache-matched-key: + description: "The key of the cache object found, if any" runs: - using: node20 + using: node24 main: "dist/restore/index.js" post: "dist/save/index.js" post-if: "success()" diff --git a/dist/restore/index.js b/dist/restore/index.js index 31227c9..1bf58a9 100644 --- a/dist/restore/index.js +++ b/dist/restore/index.js @@ -109661,6 +109661,7 @@ function restoreCache() { const cacheHit = matchingKey === key; (0, utils_1.setCacheHitOutput)(cacheHit); (0, utils_1.setCacheSizeOutput)(obj.size); + (0, utils_1.setCacheMatchedKeyOutput)(matchingKey); if (lookupOnly) { if (cacheHit && obj.size > 0) { core.info(`Cache Hit. NOT Downloading cache from s3 because lookup-only is set. bucket: ${bucket}, object: ${obj.name}`); @@ -109692,6 +109693,7 @@ function restoreCache() { const fallbackMatchingKey = yield cache.restoreCache(paths, key, restoreKeys); if (fallbackMatchingKey) { (0, utils_1.setCacheHitOutput)(fallbackMatchingKey === key); + (0, utils_1.setCacheMatchedKeyOutput)(fallbackMatchingKey); core.info("Fallback cache restored successfully"); } else { @@ -109772,7 +109774,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.saveCache = exports.isExactKeyMatch = exports.saveMatchedKey = exports.listObjects = exports.findObject = exports.setCacheSizeOutput = exports.setCacheHitOutput = exports.formatSize = exports.getInputAsInt = exports.getInputAsArray = exports.getInputAsBoolean = exports.newMinio = exports.getInput = exports.isGhes = void 0; +exports.saveCache = exports.isExactKeyMatch = exports.saveMatchedKey = exports.listObjects = exports.findObject = exports.setCacheMatchedKeyOutput = exports.setCacheSizeOutput = exports.setCacheHitOutput = exports.formatSize = exports.getInputAsInt = exports.getInputAsArray = exports.getInputAsBoolean = exports.newMinio = exports.getInput = exports.isGhes = void 0; const utils = __importStar(__nccwpck_require__(1518)); const core = __importStar(__nccwpck_require__(2186)); const minio = __importStar(__nccwpck_require__(8308)); @@ -109846,6 +109848,10 @@ function setCacheSizeOutput(cacheSize) { core.setOutput("cache-size", cacheSize.toString()); } exports.setCacheSizeOutput = setCacheSizeOutput; +function setCacheMatchedKeyOutput(cacheMatchedKey) { + core.setOutput("cache-matched-key", cacheMatchedKey); +} +exports.setCacheMatchedKeyOutput = setCacheMatchedKeyOutput; function findObject(mc, bucket, key, restoreKeys, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { core.debug("Key: " + JSON.stringify(key)); diff --git a/dist/save/index.js b/dist/save/index.js index d3c8df2..9be2602 100644 --- a/dist/save/index.js +++ b/dist/save/index.js @@ -109687,7 +109687,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.saveCache = exports.isExactKeyMatch = exports.saveMatchedKey = exports.listObjects = exports.findObject = exports.setCacheSizeOutput = exports.setCacheHitOutput = exports.formatSize = exports.getInputAsInt = exports.getInputAsArray = exports.getInputAsBoolean = exports.newMinio = exports.getInput = exports.isGhes = void 0; +exports.saveCache = exports.isExactKeyMatch = exports.saveMatchedKey = exports.listObjects = exports.findObject = exports.setCacheMatchedKeyOutput = exports.setCacheSizeOutput = exports.setCacheHitOutput = exports.formatSize = exports.getInputAsInt = exports.getInputAsArray = exports.getInputAsBoolean = exports.newMinio = exports.getInput = exports.isGhes = void 0; const utils = __importStar(__nccwpck_require__(1518)); const core = __importStar(__nccwpck_require__(2186)); const minio = __importStar(__nccwpck_require__(8308)); @@ -109761,6 +109761,10 @@ function setCacheSizeOutput(cacheSize) { core.setOutput("cache-size", cacheSize.toString()); } exports.setCacheSizeOutput = setCacheSizeOutput; +function setCacheMatchedKeyOutput(cacheMatchedKey) { + core.setOutput("cache-matched-key", cacheMatchedKey); +} +exports.setCacheMatchedKeyOutput = setCacheMatchedKeyOutput; function findObject(mc, bucket, key, restoreKeys, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { core.debug("Key: " + JSON.stringify(key)); diff --git a/dist/saveOnly/index.js b/dist/saveOnly/index.js index d8774ba..ab2f568 100644 --- a/dist/saveOnly/index.js +++ b/dist/saveOnly/index.js @@ -109687,7 +109687,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.saveCache = exports.isExactKeyMatch = exports.saveMatchedKey = exports.listObjects = exports.findObject = exports.setCacheSizeOutput = exports.setCacheHitOutput = exports.formatSize = exports.getInputAsInt = exports.getInputAsArray = exports.getInputAsBoolean = exports.newMinio = exports.getInput = exports.isGhes = void 0; +exports.saveCache = exports.isExactKeyMatch = exports.saveMatchedKey = exports.listObjects = exports.findObject = exports.setCacheMatchedKeyOutput = exports.setCacheSizeOutput = exports.setCacheHitOutput = exports.formatSize = exports.getInputAsInt = exports.getInputAsArray = exports.getInputAsBoolean = exports.newMinio = exports.getInput = exports.isGhes = void 0; const utils = __importStar(__nccwpck_require__(1518)); const core = __importStar(__nccwpck_require__(2186)); const minio = __importStar(__nccwpck_require__(8308)); @@ -109761,6 +109761,10 @@ function setCacheSizeOutput(cacheSize) { core.setOutput("cache-size", cacheSize.toString()); } exports.setCacheSizeOutput = setCacheSizeOutput; +function setCacheMatchedKeyOutput(cacheMatchedKey) { + core.setOutput("cache-matched-key", cacheMatchedKey); +} +exports.setCacheMatchedKeyOutput = setCacheMatchedKeyOutput; function findObject(mc, bucket, key, restoreKeys, compressionMethod) { return __awaiter(this, void 0, void 0, function* () { core.debug("Key: " + JSON.stringify(key)); diff --git a/restore/action.yml b/restore/action.yml index 703bcfe..b12bf2e 100644 --- a/restore/action.yml +++ b/restore/action.yml @@ -1,6 +1,6 @@ name: "s3 cache" author: tespkg -description: "S3 actions cache with actions/cache@v2 passthrough" +description: "S3 actions cache with actions/cache@v5 passthrough" inputs: endpoint: description: "s3 / minio endpoint, see: https://docs.min.io/docs/javascript-client-api-reference.html" @@ -57,8 +57,10 @@ outputs: description: "A boolean value to indicate an exact match was found for the primary key" cache-size: description: "A integer value denoting the size of the cache object found (measured in bytes)" + cache-matched-key: + description: "The key of the cache object found, if any" runs: - using: node20 + using: node24 main: "../dist/restore/index.js" branding: icon: "archive" diff --git a/save/action.yml b/save/action.yml index 3566607..16acb32 100644 --- a/save/action.yml +++ b/save/action.yml @@ -1,6 +1,6 @@ name: "s3 cache" author: tespkg -description: "S3 actions cache with actions/cache@v2 passthrough" +description: "S3 actions cache with actions/cache@v5 passthrough" inputs: endpoint: description: "s3 / minio endpoint, see: https://docs.min.io/docs/javascript-client-api-reference.html" @@ -46,7 +46,7 @@ inputs: # required: false # default: -n runs: - using: node20 + using: node24 main: "../dist/saveOnly/index.js" branding: icon: "archive" diff --git a/src/restore.ts b/src/restore.ts index c397e8b..35dd12d 100644 --- a/src/restore.ts +++ b/src/restore.ts @@ -13,6 +13,7 @@ import { newMinio, setCacheHitOutput, setCacheSizeOutput, + setCacheMatchedKeyOutput, saveMatchedKey, getInput, } from "./utils"; @@ -66,6 +67,7 @@ async function restoreCache() { const cacheHit = matchingKey === key; setCacheHitOutput(cacheHit); setCacheSizeOutput(obj.size); + setCacheMatchedKeyOutput(matchingKey); if (lookupOnly) { if (cacheHit && obj.size > 0) { core.info( @@ -106,6 +108,7 @@ async function restoreCache() { ); if (fallbackMatchingKey) { setCacheHitOutput(fallbackMatchingKey === key); + setCacheMatchedKeyOutput(fallbackMatchingKey); core.info("Fallback cache restored successfully"); } else { core.info("Fallback cache restore failed"); diff --git a/src/utils.ts b/src/utils.ts index c7e8cd7..50fe4c2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -97,6 +97,10 @@ export function setCacheSizeOutput(cacheSize: number): void { core.setOutput("cache-size", cacheSize.toString()) } +export function setCacheMatchedKeyOutput(cacheMatchedKey: string): void { + core.setOutput("cache-matched-key", cacheMatchedKey) +} + type FindObjectResult = { item: minio.BucketItem; matchingKey: string;