Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .github/workflows/test-exact-match.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: test-exact-match

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
# Save a "decoy" cache whose key is a prefix-extension of the exact key.
# e.g. key = "test-exact-Linux-12345-decoy" which shares the prefix
# "test-exact-Linux-12345" with the key we'll try to restore later.
test-save-decoy:
strategy:
matrix:
os: [ubuntu-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Generate decoy cache files
shell: bash
run: src/create-cache-files.sh ${{ runner.os }} test-cache
- name: Save decoy cache
uses: ./
with:
endpoint: ${{ secrets.ENDPOINT }}
accessKey: ${{ secrets.ACCESS_KEY }}
secretKey: ${{ secrets.SECRET_KEY }}
bucket: ${{ secrets.BUCKET }}
use-fallback: false
key: test-exact-${{ runner.os }}-${{ github.run_id }}-decoy
path: test-cache

# Try to restore with the shorter key that is a prefix of the decoy key.
# With correct exact matching this must NOT match the decoy.
test-exact-no-false-positive:
needs: test-save-decoy
strategy:
matrix:
os: [ubuntu-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Restore cache (should miss)
id: restore
uses: ./
with:
endpoint: ${{ secrets.ENDPOINT }}
accessKey: ${{ secrets.ACCESS_KEY }}
secretKey: ${{ secrets.SECRET_KEY }}
bucket: ${{ secrets.BUCKET }}
use-fallback: false
key: test-exact-${{ runner.os }}-${{ github.run_id }}
path: test-cache
- name: Verify cache was NOT restored
shell: bash
env:
CACHE_HIT: ${{ steps.restore.outputs.cache-hit }}
run: |
echo "cache-hit=$CACHE_HIT"
if [ "$CACHE_HIT" = "true" ]; then
echo "FAIL: cache-hit should not be true — decoy was incorrectly matched"
exit 1
fi
if [ -e test-cache/test-file.txt ]; then
echo "FAIL: test-file.txt should not exist — decoy files were restored"
exit 1
fi
echo "PASS: exact match correctly rejected the decoy"
18 changes: 11 additions & 7 deletions dist/restore/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86300,14 +86300,18 @@ function findObject(mc, bucket, key, restoreKeys, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () {
core.debug("Key: " + JSON.stringify(key));
core.debug("Restore keys: " + JSON.stringify(restoreKeys));
core.debug(`Finding exact macth for: ${key}`);
const exactMatch = yield listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(exactMatch, null, 2)}`);
if (exactMatch.length) {
const result = { item: exactMatch[0], matchingKey: key };
core.debug(`Using ${JSON.stringify(result)}`);
return result;
core.debug(`Finding exact match for: ${key}`);
const keyMatches = yield listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(keyMatches, null, 2)}`);
if (keyMatches.length > 0) {
const exactMatch = keyMatches.find((obj) => { var _a; return (_a = obj.name) === null || _a === void 0 ? void 0 : _a.startsWith(key + path_1.default.sep); });
if (exactMatch) {
const result = { item: exactMatch, matchingKey: key };
core.debug(`Found an exact match; using ${JSON.stringify(result)}`);
return result;
}
}
core.debug(`Didn't find an exact match`);
for (const restoreKey of restoreKeys) {
const fn = utils.getCacheFileName(compressionMethod);
core.debug(`Finding object with prefix: ${restoreKey}`);
Expand Down
18 changes: 11 additions & 7 deletions dist/save/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86215,14 +86215,18 @@ function findObject(mc, bucket, key, restoreKeys, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () {
core.debug("Key: " + JSON.stringify(key));
core.debug("Restore keys: " + JSON.stringify(restoreKeys));
core.debug(`Finding exact macth for: ${key}`);
const exactMatch = yield listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(exactMatch, null, 2)}`);
if (exactMatch.length) {
const result = { item: exactMatch[0], matchingKey: key };
core.debug(`Using ${JSON.stringify(result)}`);
return result;
core.debug(`Finding exact match for: ${key}`);
const keyMatches = yield listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(keyMatches, null, 2)}`);
if (keyMatches.length > 0) {
const exactMatch = keyMatches.find((obj) => { var _a; return (_a = obj.name) === null || _a === void 0 ? void 0 : _a.startsWith(key + path_1.default.sep); });
if (exactMatch) {
const result = { item: exactMatch, matchingKey: key };
core.debug(`Found an exact match; using ${JSON.stringify(result)}`);
return result;
}
}
core.debug(`Didn't find an exact match`);
for (const restoreKey of restoreKeys) {
const fn = utils.getCacheFileName(compressionMethod);
core.debug(`Finding object with prefix: ${restoreKey}`);
Expand Down
18 changes: 11 additions & 7 deletions dist/saveOnly/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86215,14 +86215,18 @@ function findObject(mc, bucket, key, restoreKeys, compressionMethod) {
return __awaiter(this, void 0, void 0, function* () {
core.debug("Key: " + JSON.stringify(key));
core.debug("Restore keys: " + JSON.stringify(restoreKeys));
core.debug(`Finding exact macth for: ${key}`);
const exactMatch = yield listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(exactMatch, null, 2)}`);
if (exactMatch.length) {
const result = { item: exactMatch[0], matchingKey: key };
core.debug(`Using ${JSON.stringify(result)}`);
return result;
core.debug(`Finding exact match for: ${key}`);
const keyMatches = yield listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(keyMatches, null, 2)}`);
if (keyMatches.length > 0) {
const exactMatch = keyMatches.find((obj) => { var _a; return (_a = obj.name) === null || _a === void 0 ? void 0 : _a.startsWith(key + path_1.default.sep); });
if (exactMatch) {
const result = { item: exactMatch, matchingKey: key };
core.debug(`Found an exact match; using ${JSON.stringify(result)}`);
return result;
}
}
core.debug(`Didn't find an exact match`);
for (const restoreKey of restoreKeys) {
const fn = utils.getCacheFileName(compressionMethod);
core.debug(`Finding object with prefix: ${restoreKey}`);
Expand Down
18 changes: 11 additions & 7 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,14 +128,18 @@ export async function findObject(
core.debug("Key: " + JSON.stringify(key));
core.debug("Restore keys: " + JSON.stringify(restoreKeys));

core.debug(`Finding exact macth for: ${key}`);
const exactMatch = await listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(exactMatch, null, 2)}`);
if (exactMatch.length) {
const result = { item: exactMatch[0], matchingKey: key };
core.debug(`Using ${JSON.stringify(result)}`);
return result;
core.debug(`Finding exact match for: ${key}`);
const keyMatches = await listObjects(mc, bucket, key);
core.debug(`Found ${JSON.stringify(keyMatches, null, 2)}`);
if (keyMatches.length > 0) {
const exactMatch = keyMatches.find((obj) => obj.name?.startsWith(key + path.sep));
if (exactMatch) {
const result = { item: exactMatch, matchingKey: key };
core.debug(`Found an exact match; using ${JSON.stringify(result)}`);
return result;
}
}
core.debug(`Didn't find an exact match`);

for (const restoreKey of restoreKeys) {
const fn = utils.getCacheFileName(compressionMethod);
Expand Down
Loading