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
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 {
Comment thread
Phantsure marked this conversation as resolved.
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