Skip to content

Commit

Permalink
Merge pull request #1260 from actions/phantsure/cache-testing
Browse files Browse the repository at this point in the history
Fix known issues for cache
  • Loading branch information
Phantsure authored Dec 12, 2022
2 parents 27d5148 + 2d3c79e commit 8b695c1
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 64 deletions.
91 changes: 91 additions & 0 deletions .github/workflows/cache-windows-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: cache-windows-bsd-unit-tests
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'

jobs:
build:
name: Build

runs-on: windows-latest

steps:
- name: Checkout
uses: actions/checkout@v2

- shell: bash
run: |
rm "C:\Program Files\Git\usr\bin\tar.exe"
- name: Set Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: 12.x

# In order to save & restore cache from a shell script, certain env variables need to be set that are only available in the
# node context. This runs a local action that gets and sets the necessary env variables that are needed
- name: Set env variables
uses: ./packages/cache/__tests__/__fixtures__/

# Need root node_modules because certain npm packages like jest are configured for the entire repository and it won't be possible
# without these to just compile the cache package
- name: Install root npm packages
run: npm ci

- name: Compile cache package
run: |
npm ci
npm run tsc
working-directory: packages/cache

- name: Generate files in working directory
shell: bash
run: packages/cache/__tests__/create-cache-files.sh ${{ runner.os }} test-cache

- name: Generate files outside working directory
shell: bash
run: packages/cache/__tests__/create-cache-files.sh ${{ runner.os }} ~/test-cache

# We're using node -e to call the functions directly available in the @actions/cache package
- name: Save cache using saveCache()
run: |
node -e "Promise.resolve(require('./packages/cache/lib/cache').saveCache(['test-cache','~/test-cache'],'test-${{ runner.os }}-${{ github.run_id }}'))"
- name: Delete cache folders before restoring
shell: bash
run: |
rm -rf test-cache
rm -rf ~/test-cache
- name: Restore cache using restoreCache() with http-client
run: |
node -e "Promise.resolve(require('./packages/cache/lib/cache').restoreCache(['test-cache','~/test-cache'],'test-${{ runner.os }}-${{ github.run_id }}',[],{useAzureSdk: false}))"
- name: Verify cache restored with http-client
shell: bash
run: |
packages/cache/__tests__/verify-cache-files.sh ${{ runner.os }} test-cache
packages/cache/__tests__/verify-cache-files.sh ${{ runner.os }} ~/test-cache
- name: Delete cache folders before restoring
shell: bash
run: |
rm -rf test-cache
rm -rf ~/test-cache
rm -f cache.tar
- name: Restore cache using restoreCache() with Azure SDK
run: |
node -e "Promise.resolve(require('./packages/cache/lib/cache').restoreCache(['test-cache','~/test-cache'],'test-${{ runner.os }}-${{ github.run_id }}'))"
- name: Verify cache restored with Azure SDK
shell: bash
run: |
packages/cache/__tests__/verify-cache-files.sh ${{ runner.os }} test-cache
packages/cache/__tests__/verify-cache-files.sh ${{ runner.os }} ~/test-cache
2 changes: 1 addition & 1 deletion packages/cache/__tests__/restoreCache.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ test('restore with zstd as default but gzip compressed cache found on windows',
const getCacheMock = jest.spyOn(cacheHttpClient, 'getCacheEntry')
getCacheMock
.mockImplementationOnce(async () => {
throw new Error('Cache not found.')
return Promise.resolve(null)
})
.mockImplementationOnce(async () => {
return Promise.resolve(cacheEntry)
Expand Down
85 changes: 65 additions & 20 deletions packages/cache/__tests__/tar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ test('zstd extract tar', async () => {
'--use-compress-program',
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
])
.join(' ')
.join(' '),
undefined,
{cwd: undefined}
)
})

Expand All @@ -92,20 +94,31 @@ test('zstd extract tar with windows BSDtar', async () => {
await tar.extractTar(archivePath, CompressionMethod.Zstd)

expect(mkdirMock).toHaveBeenCalledWith(workspace)
expect(execMock).toHaveBeenCalledTimes(1)
expect(execMock).toHaveBeenCalledWith(
expect(execMock).toHaveBeenCalledTimes(2)

expect(execMock).toHaveBeenNthCalledWith(
1,
[
'zstd -d --long=30 -o',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'&&',
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
].join(' '),
undefined,
{cwd: undefined}
)

expect(execMock).toHaveBeenNthCalledWith(
2,
[
`"${tarPath}"`,
'-xf',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P',
'-C',
workspace?.replace(/\\/g, '/')
].join(' ')
].join(' '),
undefined,
{cwd: undefined}
)
}
})
Expand Down Expand Up @@ -135,7 +148,9 @@ test('gzip extract tar', async () => {
.concat(IS_WINDOWS ? ['--force-local'] : [])
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
.concat(['-z'])
.join(' ')
.join(' '),
undefined,
{cwd: undefined}
)
})

Expand All @@ -162,7 +177,9 @@ test('gzip extract GNU tar on windows with GNUtar in path', async () => {
workspace?.replace(/\\/g, '/'),
'--force-local',
'-z'
].join(' ')
].join(' '),
undefined,
{cwd: undefined}
)
}
})
Expand Down Expand Up @@ -230,8 +247,10 @@ test('zstd create tar with windows BSDtar', async () => {

const tarPath = SystemTarPathOnWindows

expect(execMock).toHaveBeenCalledTimes(1)
expect(execMock).toHaveBeenCalledWith(
expect(execMock).toHaveBeenCalledTimes(2)

expect(execMock).toHaveBeenNthCalledWith(
1,
[
`"${tarPath}"`,
'--posix',
Expand All @@ -243,8 +262,17 @@ test('zstd create tar with windows BSDtar', async () => {
'-C',
workspace?.replace(/\\/g, '/'),
'--files-from',
ManifestFilename,
'&&',
ManifestFilename
].join(' '),
undefined, // args
{
cwd: archiveFolder
}
)

expect(execMock).toHaveBeenNthCalledWith(
2,
[
'zstd -T0 --long=30 -o',
CacheFilename.Zstd.replace(/\\/g, '/'),
TarFilename.replace(/\\/g, '/')
Expand Down Expand Up @@ -320,7 +348,9 @@ test('zstd list tar', async () => {
'--use-compress-program',
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
])
.join(' ')
.join(' '),
undefined,
{cwd: undefined}
)
})

Expand All @@ -335,18 +365,29 @@ test('zstd list tar with windows BSDtar', async () => {
await tar.listTar(archivePath, CompressionMethod.Zstd)

const tarPath = SystemTarPathOnWindows
expect(execMock).toHaveBeenCalledTimes(1)
expect(execMock).toHaveBeenCalledWith(
expect(execMock).toHaveBeenCalledTimes(2)

expect(execMock).toHaveBeenNthCalledWith(
1,
[
'zstd -d --long=30 -o',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'&&',
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
].join(' '),
undefined,
{cwd: undefined}
)

expect(execMock).toHaveBeenNthCalledWith(
2,
[
`"${tarPath}"`,
'-tf',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P'
].join(' ')
].join(' '),
undefined,
{cwd: undefined}
)
}
})
Expand All @@ -372,7 +413,9 @@ test('zstdWithoutLong list tar', async () => {
.concat(IS_WINDOWS ? ['--force-local'] : [])
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
.concat(['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'])
.join(' ')
.join(' '),
undefined,
{cwd: undefined}
)
})

Expand All @@ -396,6 +439,8 @@ test('gzip list tar', async () => {
.concat(IS_WINDOWS ? ['--force-local'] : [])
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
.concat(['-z'])
.join(' ')
.join(' '),
undefined,
{cwd: undefined}
)
})
27 changes: 13 additions & 14 deletions packages/cache/src/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,12 @@ export async function restoreCache(
let compressionMethod = await utils.getCompressionMethod()
let archivePath = ''
try {
try {
// path are needed to compute version
cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
compressionMethod
})
} catch (error) {
// This is to support the old cache entry created
// by the old version of the cache action on windows.
// path are needed to compute version
cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
compressionMethod
})
if (!cacheEntry?.archiveLocation) {
// This is to support the old cache entry created by gzip on windows.
if (
process.platform === 'win32' &&
compressionMethod !== CompressionMethod.Gzip
Expand All @@ -108,17 +106,18 @@ export async function restoreCache(
compressionMethod
})
if (!cacheEntry?.archiveLocation) {
throw error
return undefined
}

core.debug(
"Couldn't find cache entry with zstd compression, falling back to gzip compression."
)
} else {
throw error
// Cache not found
return undefined
}
}

if (!cacheEntry?.archiveLocation) {
// Cache not found
return undefined
}
archivePath = path.join(
await utils.createTempDirectory(),
utils.getCacheFileName(compressionMethod)
Expand Down
2 changes: 2 additions & 0 deletions packages/cache/src/internal/cacheHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export async function getCacheEntry(
httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource))
)
if (response.statusCode === 204) {
// Cache not found
return null
}
if (!isSuccessStatusCode(response.statusCode)) {
Expand All @@ -113,6 +114,7 @@ export async function getCacheEntry(
const cacheResult = response.result
const cacheDownloadUrl = cacheResult?.archiveLocation
if (!cacheDownloadUrl) {
// Cache achiveLocation not found. This should never happen, and hence bail out.
throw new Error('Cache not found.')
}
core.setSecret(cacheDownloadUrl)
Expand Down
Loading

0 comments on commit 8b695c1

Please sign in to comment.