1
0
Fork 0

Add end to end test for cache using bsd on windows

and address review comments
pull/1260/head
Sampark Sharma 2022-12-12 06:53:11 +00:00 committed by GitHub
parent 0690c10515
commit d175a181a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 182 additions and 59 deletions

View File

@ -0,0 +1,90 @@
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
- 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

View File

@ -73,7 +73,9 @@ test('zstd extract tar', async () => {
'--use-compress-program', '--use-compress-program',
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30' IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
]) ])
.join(' ') .join(' '),
undefined,
{cwd: undefined}
) )
}) })
@ -92,22 +94,31 @@ test('zstd extract tar with windows BSDtar', async () => {
await tar.extractTar(archivePath, CompressionMethod.Zstd) await tar.extractTar(archivePath, CompressionMethod.Zstd)
expect(mkdirMock).toHaveBeenCalledWith(workspace) expect(mkdirMock).toHaveBeenCalledWith(workspace)
expect(execMock).toHaveBeenCalledTimes(1) expect(execMock).toHaveBeenCalledTimes(2)
expect(execMock).toHaveBeenCalledWith(
expect(execMock).toHaveBeenNthCalledWith(
1,
[ [
'cmd /c "',
'zstd -d --long=30 -o', 'zstd -d --long=30 -o',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), 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}"`, `"${tarPath}"`,
'-xf', '-xf',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P', '-P',
'-C', '-C',
workspace?.replace(/\\/g, '/'), workspace?.replace(/\\/g, '/')
'"' // end cmd /c ].join(' '),
].join(' ') undefined,
{cwd: undefined}
) )
} }
}) })
@ -137,7 +148,9 @@ test('gzip extract tar', async () => {
.concat(IS_WINDOWS ? ['--force-local'] : []) .concat(IS_WINDOWS ? ['--force-local'] : [])
.concat(IS_MAC ? ['--delay-directory-restore'] : []) .concat(IS_MAC ? ['--delay-directory-restore'] : [])
.concat(['-z']) .concat(['-z'])
.join(' ') .join(' '),
undefined,
{cwd: undefined}
) )
}) })
@ -164,7 +177,9 @@ test('gzip extract GNU tar on windows with GNUtar in path', async () => {
workspace?.replace(/\\/g, '/'), workspace?.replace(/\\/g, '/'),
'--force-local', '--force-local',
'-z' '-z'
].join(' ') ].join(' '),
undefined,
{cwd: undefined}
) )
} }
}) })
@ -232,10 +247,11 @@ test('zstd create tar with windows BSDtar', async () => {
const tarPath = SystemTarPathOnWindows const tarPath = SystemTarPathOnWindows
expect(execMock).toHaveBeenCalledTimes(1) expect(execMock).toHaveBeenCalledTimes(2)
expect(execMock).toHaveBeenCalledWith(
expect(execMock).toHaveBeenNthCalledWith(
1,
[ [
'cmd /c "',
`"${tarPath}"`, `"${tarPath}"`,
'--posix', '--posix',
'-cf', '-cf',
@ -246,12 +262,20 @@ test('zstd create tar with windows BSDtar', async () => {
'-C', '-C',
workspace?.replace(/\\/g, '/'), workspace?.replace(/\\/g, '/'),
'--files-from', '--files-from',
ManifestFilename, ManifestFilename
'&&', ].join(' '),
undefined, // args
{
cwd: archiveFolder
}
)
expect(execMock).toHaveBeenNthCalledWith(
2,
[
'zstd -T0 --long=30 -o', 'zstd -T0 --long=30 -o',
CacheFilename.Zstd.replace(/\\/g, '/'), CacheFilename.Zstd.replace(/\\/g, '/'),
TarFilename.replace(/\\/g, '/'), TarFilename.replace(/\\/g, '/')
'"' // end cmd /c
].join(' '), ].join(' '),
undefined, // args undefined, // args
{ {
@ -324,7 +348,9 @@ test('zstd list tar', async () => {
'--use-compress-program', '--use-compress-program',
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30' IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
]) ])
.join(' ') .join(' '),
undefined,
{cwd: undefined}
) )
}) })
@ -340,19 +366,28 @@ test('zstd list tar with windows BSDtar', async () => {
const tarPath = SystemTarPathOnWindows const tarPath = SystemTarPathOnWindows
expect(execMock).toHaveBeenCalledTimes(1) expect(execMock).toHaveBeenCalledTimes(1)
expect(execMock).toHaveBeenCalledWith(
expect(execMock).toHaveBeenNthCalledWith(
1,
[ [
'cmd /c "',
'zstd -d --long=30 -o', 'zstd -d --long=30 -o',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), 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}"`, `"${tarPath}"`,
'-tf', '-tf',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
'-P', '-P'
'"' // end cmd /c ].join(' '),
].join(' ') undefined,
{cwd: undefined}
) )
} }
}) })
@ -378,7 +413,9 @@ test('zstdWithoutLong list tar', async () => {
.concat(IS_WINDOWS ? ['--force-local'] : []) .concat(IS_WINDOWS ? ['--force-local'] : [])
.concat(IS_MAC ? ['--delay-directory-restore'] : []) .concat(IS_MAC ? ['--delay-directory-restore'] : [])
.concat(['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd']) .concat(['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'])
.join(' ') .join(' '),
undefined,
{cwd: undefined}
) )
}) })
@ -402,6 +439,8 @@ test('gzip list tar', async () => {
.concat(IS_WINDOWS ? ['--force-local'] : []) .concat(IS_WINDOWS ? ['--force-local'] : [])
.concat(IS_MAC ? ['--delay-directory-restore'] : []) .concat(IS_MAC ? ['--delay-directory-restore'] : [])
.concat(['-z']) .concat(['-z'])
.join(' ') .join(' '),
undefined,
{cwd: undefined}
) )
}) })

View File

@ -122,12 +122,12 @@ async function getTarArgs(
return args return args
} }
async function getArgs( async function getCommands(
compressionMethod: CompressionMethod, compressionMethod: CompressionMethod,
type: string, type: string,
archivePath = '' archivePath = ''
): Promise<string> { ): Promise<string[]> {
let args: string let args
const tarPath = await getTarPath() const tarPath = await getTarPath()
const tarArgs = await getTarArgs( const tarArgs = await getTarArgs(
@ -146,16 +146,16 @@ async function getArgs(
IS_WINDOWS IS_WINDOWS
if (BSD_TAR_ZSTD && type !== 'create') { if (BSD_TAR_ZSTD && type !== 'create') {
args = [...compressionArgs, ...tarArgs].join(' ') args = [...compressionArgs, ...tarArgs]
} else { } else {
args = [...tarArgs, ...compressionArgs].join(' ') args = [...tarArgs, ...compressionArgs]
} }
if (BSD_TAR_ZSTD) { if (BSD_TAR_ZSTD) {
args = ['cmd /c "', args, '"'].join(' ') return args
} }
return args return [args.join(' ')]
} }
function getWorkingDirectory(): string { function getWorkingDirectory(): string {
@ -182,8 +182,7 @@ async function getDecompressionProgram(
? [ ? [
'zstd -d --long=30 -o', 'zstd -d --long=30 -o',
TarFilename, TarFilename,
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
'&&'
] ]
: [ : [
'--use-compress-program', '--use-compress-program',
@ -194,8 +193,7 @@ async function getDecompressionProgram(
? [ ? [
'zstd -d -o', 'zstd -d -o',
TarFilename, TarFilename,
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
'&&'
] ]
: ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'] : ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd']
default: default:
@ -221,7 +219,6 @@ async function getCompressionProgram(
case CompressionMethod.Zstd: case CompressionMethod.Zstd:
return BSD_TAR_ZSTD return BSD_TAR_ZSTD
? [ ? [
'&&',
'zstd -T0 --long=30 -o', 'zstd -T0 --long=30 -o',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
TarFilename TarFilename
@ -233,7 +230,6 @@ async function getCompressionProgram(
case CompressionMethod.ZstdWithoutLong: case CompressionMethod.ZstdWithoutLong:
return BSD_TAR_ZSTD return BSD_TAR_ZSTD
? [ ? [
'&&',
'zstd -T0 -o', 'zstd -T0 -o',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
TarFilename TarFilename
@ -244,16 +240,22 @@ async function getCompressionProgram(
} }
} }
async function execCommands(commands: string[], cwd?: string): Promise<void> {
for (const command of commands) {
try {
await exec(command, undefined, {cwd})
} catch (error) {
throw new Error(`${command[0]} failed with error: ${error?.message}`)
}
}
}
export async function listTar( export async function listTar(
archivePath: string, archivePath: string,
compressionMethod: CompressionMethod compressionMethod: CompressionMethod
): Promise<void> { ): Promise<void> {
const args = await getArgs(compressionMethod, 'list', archivePath) const commands = await getCommands(compressionMethod, 'list', archivePath)
try { await execCommands(commands)
await exec(args)
} catch (error) {
throw new Error(`Tar failed with error: ${error?.message}`)
}
} }
export async function extractTar( export async function extractTar(
@ -263,12 +265,8 @@ export async function extractTar(
// Create directory to extract tar into // Create directory to extract tar into
const workingDirectory = getWorkingDirectory() const workingDirectory = getWorkingDirectory()
await io.mkdirP(workingDirectory) await io.mkdirP(workingDirectory)
const args = await getArgs(compressionMethod, 'extract', archivePath) const commands = await getCommands(compressionMethod, 'extract', archivePath)
try { await execCommands(commands)
await exec(args)
} catch (error) {
throw new Error(`Tar failed with error: ${error?.message}`)
}
} }
export async function createTar( export async function createTar(
@ -281,10 +279,6 @@ export async function createTar(
path.join(archiveFolder, ManifestFilename), path.join(archiveFolder, ManifestFilename),
sourceDirectories.join('\n') sourceDirectories.join('\n')
) )
const args = await getArgs(compressionMethod, 'create') const commands = await getCommands(compressionMethod, 'create')
try { await execCommands(commands, archiveFolder)
await exec(args, undefined, {cwd: archiveFolder})
} catch (error) {
throw new Error(`Tar failed with error: ${error?.message}`)
}
} }