Compare commits
37
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c76b5b3a03 | ||
|
|
fd47902ff8 | ||
|
|
3959b7966e | ||
|
|
c24b93f4b7 | ||
|
|
2a4f3544ad | ||
|
|
8e69225720 | ||
|
|
a20e7c1a03 | ||
|
|
c23fe4b81f | ||
|
|
034d154f88 | ||
|
|
ccfa36f304 | ||
|
|
e96dc8a69a | ||
|
|
b8c50aa82d | ||
|
|
24685611e2 | ||
|
|
e559a15ca6 | ||
|
|
816c1b3760 | ||
|
|
0ff35ed4a1 | ||
|
|
8b695c1f30 | ||
|
|
2d3c79e6fe | ||
|
|
e7e19845ca | ||
|
|
cad074ceef | ||
|
|
d7ae8cd1ef | ||
|
|
6bc5dc5a23 | ||
|
|
bbf5659dfa | ||
|
|
d175a181a0 | ||
|
|
0690c10515 | ||
|
|
0c23c38c68 | ||
|
|
7a532d03f4 | ||
|
|
d31c2dd88d | ||
|
|
27d5148f03 | ||
|
|
8e39d78020 | ||
|
|
cb3dc49fec | ||
|
|
de8fda6976 | ||
|
|
61e630822a | ||
|
|
c207fbd5db | ||
|
|
b9d1dd898e | ||
|
|
aaac0e6c98 | ||
|
|
a735d9bcd4 |
@@ -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
|
||||||
Vendored
+14
@@ -91,3 +91,17 @@
|
|||||||
|
|
||||||
### 3.0.6
|
### 3.0.6
|
||||||
- Added `@azure/abort-controller` to dependencies to fix compatibility issue with ESM [#1208](https://github.com/actions/toolkit/issues/1208)
|
- Added `@azure/abort-controller` to dependencies to fix compatibility issue with ESM [#1208](https://github.com/actions/toolkit/issues/1208)
|
||||||
|
|
||||||
|
### 3.1.0-beta.1
|
||||||
|
- Update actions/cache on windows to use gnu tar and zstd by default and fallback to bsdtar and zstd if gnu tar is not available. ([issue](https://github.com/actions/cache/issues/984))
|
||||||
|
|
||||||
|
### 3.1.0-beta.2
|
||||||
|
- Added support for fallback to gzip to restore old caches on windows.
|
||||||
|
|
||||||
|
### 3.1.0-beta.3
|
||||||
|
- Bug Fixes for fallback to gzip to restore old caches on windows and bsdtar if gnutar is not available.
|
||||||
|
|
||||||
|
### 3.1.0
|
||||||
|
- Update actions/cache on windows to use gnu tar and zstd by default
|
||||||
|
- Update actions/cache on windows to fallback to bsdtar and zstd if gnu tar is not available.
|
||||||
|
- Added support for fallback to gzip to restore old caches on windows.
|
||||||
|
|||||||
+1
-1
@@ -174,7 +174,7 @@ test('restore with zstd as default but gzip compressed cache found on windows',
|
|||||||
const getCacheMock = jest.spyOn(cacheHttpClient, 'getCacheEntry')
|
const getCacheMock = jest.spyOn(cacheHttpClient, 'getCacheEntry')
|
||||||
getCacheMock
|
getCacheMock
|
||||||
.mockImplementationOnce(async () => {
|
.mockImplementationOnce(async () => {
|
||||||
throw new Error('Cache not found.')
|
return Promise.resolve(null)
|
||||||
})
|
})
|
||||||
.mockImplementationOnce(async () => {
|
.mockImplementationOnce(async () => {
|
||||||
return Promise.resolve(cacheEntry)
|
return Promise.resolve(cacheEntry)
|
||||||
|
|||||||
Vendored
+68
-23
@@ -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,20 +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,
|
||||||
[
|
[
|
||||||
'zstd -d --long=30 -o',
|
'zstd -d --long=30 --force -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, '/')
|
||||||
].join(' ')
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -135,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}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -162,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}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -230,8 +247,10 @@ 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,
|
||||||
[
|
[
|
||||||
`"${tarPath}"`,
|
`"${tarPath}"`,
|
||||||
'--posix',
|
'--posix',
|
||||||
@@ -243,9 +262,18 @@ test('zstd create tar with windows BSDtar', async () => {
|
|||||||
'-C',
|
'-C',
|
||||||
workspace?.replace(/\\/g, '/'),
|
workspace?.replace(/\\/g, '/'),
|
||||||
'--files-from',
|
'--files-from',
|
||||||
ManifestFilename,
|
ManifestFilename
|
||||||
'&&',
|
].join(' '),
|
||||||
'zstd -T0 --long=30 -o',
|
undefined, // args
|
||||||
|
{
|
||||||
|
cwd: archiveFolder
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
[
|
||||||
|
'zstd -T0 --long=30 --force -o',
|
||||||
CacheFilename.Zstd.replace(/\\/g, '/'),
|
CacheFilename.Zstd.replace(/\\/g, '/'),
|
||||||
TarFilename.replace(/\\/g, '/')
|
TarFilename.replace(/\\/g, '/')
|
||||||
].join(' '),
|
].join(' '),
|
||||||
@@ -320,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}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -335,18 +365,29 @@ test('zstd list tar with windows BSDtar', async () => {
|
|||||||
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
||||||
|
|
||||||
const tarPath = SystemTarPathOnWindows
|
const tarPath = SystemTarPathOnWindows
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(2)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
[
|
[
|
||||||
'zstd -d --long=30 -o',
|
'zstd -d --long=30 --force -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'
|
||||||
].join(' ')
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -372,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}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -396,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}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
+8
-8
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/cache",
|
"name": "@actions/cache",
|
||||||
"version": "3.0.6",
|
"version": "3.1.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/cache",
|
"name": "@actions/cache",
|
||||||
"version": "3.0.6",
|
"version": "3.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
@@ -457,9 +457,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
},
|
},
|
||||||
@@ -998,9 +998,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"minimatch": {
|
"minimatch": {
|
||||||
"version": "3.0.4",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/cache",
|
"name": "@actions/cache",
|
||||||
"version": "3.0.6",
|
"version": "3.1.0",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"description": "Actions cache lib",
|
"description": "Actions cache lib",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|||||||
Vendored
+13
-14
@@ -91,14 +91,12 @@ export async function restoreCache(
|
|||||||
let compressionMethod = await utils.getCompressionMethod()
|
let compressionMethod = await utils.getCompressionMethod()
|
||||||
let archivePath = ''
|
let archivePath = ''
|
||||||
try {
|
try {
|
||||||
try {
|
// path are needed to compute version
|
||||||
// path are needed to compute version
|
cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
|
||||||
cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
|
compressionMethod
|
||||||
compressionMethod
|
})
|
||||||
})
|
if (!cacheEntry?.archiveLocation) {
|
||||||
} catch (error) {
|
// This is to support the old cache entry created by gzip on windows.
|
||||||
// This is to support the old cache entry created
|
|
||||||
// by the old version of the cache action on windows.
|
|
||||||
if (
|
if (
|
||||||
process.platform === 'win32' &&
|
process.platform === 'win32' &&
|
||||||
compressionMethod !== CompressionMethod.Gzip
|
compressionMethod !== CompressionMethod.Gzip
|
||||||
@@ -108,17 +106,18 @@ export async function restoreCache(
|
|||||||
compressionMethod
|
compressionMethod
|
||||||
})
|
})
|
||||||
if (!cacheEntry?.archiveLocation) {
|
if (!cacheEntry?.archiveLocation) {
|
||||||
throw error
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.info(
|
||||||
|
"Couldn't find cache entry with zstd compression, falling back to gzip compression."
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
throw error
|
// Cache not found
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cacheEntry?.archiveLocation) {
|
|
||||||
// Cache not found
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
archivePath = path.join(
|
archivePath = path.join(
|
||||||
await utils.createTempDirectory(),
|
await utils.createTempDirectory(),
|
||||||
utils.getCacheFileName(compressionMethod)
|
utils.getCacheFileName(compressionMethod)
|
||||||
|
|||||||
+33
-1
@@ -17,7 +17,8 @@ import {
|
|||||||
CommitCacheRequest,
|
CommitCacheRequest,
|
||||||
ReserveCacheRequest,
|
ReserveCacheRequest,
|
||||||
ReserveCacheResponse,
|
ReserveCacheResponse,
|
||||||
ITypedResponseWithError
|
ITypedResponseWithError,
|
||||||
|
ArtifactCacheList
|
||||||
} from './contracts'
|
} from './contracts'
|
||||||
import {downloadCacheHttpClient, downloadCacheStorageSDK} from './downloadUtils'
|
import {downloadCacheHttpClient, downloadCacheStorageSDK} from './downloadUtils'
|
||||||
import {
|
import {
|
||||||
@@ -103,7 +104,12 @@ export async function getCacheEntry(
|
|||||||
const response = await retryTypedResponse('getCacheEntry', async () =>
|
const response = await retryTypedResponse('getCacheEntry', async () =>
|
||||||
httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource))
|
httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource))
|
||||||
)
|
)
|
||||||
|
// Cache not found
|
||||||
if (response.statusCode === 204) {
|
if (response.statusCode === 204) {
|
||||||
|
// List cache for primary key only if cache miss occurs
|
||||||
|
if (core.isDebug()) {
|
||||||
|
await printCachesListForDiagnostics(keys[0], httpClient, version)
|
||||||
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (!isSuccessStatusCode(response.statusCode)) {
|
if (!isSuccessStatusCode(response.statusCode)) {
|
||||||
@@ -113,6 +119,7 @@ export async function getCacheEntry(
|
|||||||
const cacheResult = response.result
|
const cacheResult = response.result
|
||||||
const cacheDownloadUrl = cacheResult?.archiveLocation
|
const cacheDownloadUrl = cacheResult?.archiveLocation
|
||||||
if (!cacheDownloadUrl) {
|
if (!cacheDownloadUrl) {
|
||||||
|
// Cache achiveLocation not found. This should never happen, and hence bail out.
|
||||||
throw new Error('Cache not found.')
|
throw new Error('Cache not found.')
|
||||||
}
|
}
|
||||||
core.setSecret(cacheDownloadUrl)
|
core.setSecret(cacheDownloadUrl)
|
||||||
@@ -122,6 +129,31 @@ export async function getCacheEntry(
|
|||||||
return cacheResult
|
return cacheResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function printCachesListForDiagnostics(
|
||||||
|
key: string,
|
||||||
|
httpClient: HttpClient,
|
||||||
|
version: string
|
||||||
|
): Promise<void> {
|
||||||
|
const resource = `caches?key=${encodeURIComponent(key)}`
|
||||||
|
const response = await retryTypedResponse('listCache', async () =>
|
||||||
|
httpClient.getJson<ArtifactCacheList>(getCacheApiUrl(resource))
|
||||||
|
)
|
||||||
|
if (response.statusCode === 200) {
|
||||||
|
const cacheListResult = response.result
|
||||||
|
const totalCount = cacheListResult?.totalCount
|
||||||
|
if (totalCount && totalCount > 0) {
|
||||||
|
core.debug(
|
||||||
|
`No matching cache found for cache key '${key}', version '${version} and scope ${process.env['GITHUB_REF']}. There exist one or more cache(s) with similar key but they have different version or scope. See more info on cache matching here: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key \nOther caches with similar key:`
|
||||||
|
)
|
||||||
|
for (const cacheEntry of cacheListResult?.artifactCaches || []) {
|
||||||
|
core.debug(
|
||||||
|
`Cache Key: ${cacheEntry?.cacheKey}, Cache Version: ${cacheEntry?.cacheVersion}, Cache Scope: ${cacheEntry?.scope}, Cache Created: ${cacheEntry?.creationTime}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function downloadCache(
|
export async function downloadCache(
|
||||||
archiveLocation: string,
|
archiveLocation: string,
|
||||||
archivePath: string,
|
archivePath: string,
|
||||||
|
|||||||
+6
@@ -9,10 +9,16 @@ export interface ITypedResponseWithError<T> extends TypedResponse<T> {
|
|||||||
export interface ArtifactCacheEntry {
|
export interface ArtifactCacheEntry {
|
||||||
cacheKey?: string
|
cacheKey?: string
|
||||||
scope?: string
|
scope?: string
|
||||||
|
cacheVersion?: string
|
||||||
creationTime?: string
|
creationTime?: string
|
||||||
archiveLocation?: string
|
archiveLocation?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ArtifactCacheList {
|
||||||
|
totalCount: number
|
||||||
|
artifactCaches?: ArtifactCacheEntry[]
|
||||||
|
}
|
||||||
|
|
||||||
export interface CommitCacheRequest {
|
export interface CommitCacheRequest {
|
||||||
size: number
|
size: number
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+46
-33
@@ -14,7 +14,7 @@ import {
|
|||||||
|
|
||||||
const IS_WINDOWS = process.platform === 'win32'
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
|
|
||||||
// Function also mutates the args array. For non-mutation call with passing an empty array.
|
// Returns tar path and type: BSD or GNU
|
||||||
async function getTarPath(): Promise<ArchiveTool> {
|
async function getTarPath(): Promise<ArchiveTool> {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'win32': {
|
case 'win32': {
|
||||||
@@ -43,6 +43,7 @@ async function getTarPath(): Promise<ArchiveTool> {
|
|||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// Default assumption is GNU tar is present in path
|
||||||
return <ArchiveTool>{
|
return <ArchiveTool>{
|
||||||
path: await io.which('tar', true),
|
path: await io.which('tar', true),
|
||||||
type: ArchiveToolType.GNU
|
type: ArchiveToolType.GNU
|
||||||
@@ -60,6 +61,7 @@ async function getTarArgs(
|
|||||||
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
||||||
const tarFile = 'cache.tar'
|
const tarFile = 'cache.tar'
|
||||||
const workingDirectory = getWorkingDirectory()
|
const workingDirectory = getWorkingDirectory()
|
||||||
|
// Speficic args for BSD tar on windows for workaround
|
||||||
const BSD_TAR_ZSTD =
|
const BSD_TAR_ZSTD =
|
||||||
tarPath.type === ArchiveToolType.BSD &&
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
compressionMethod !== CompressionMethod.Gzip &&
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
@@ -122,11 +124,14 @@ async function getTarArgs(
|
|||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getArgs(
|
// Returns commands to run tar and compression program
|
||||||
|
async function getCommands(
|
||||||
compressionMethod: CompressionMethod,
|
compressionMethod: CompressionMethod,
|
||||||
type: string,
|
type: string,
|
||||||
archivePath = ''
|
archivePath = ''
|
||||||
): Promise<string> {
|
): Promise<string[]> {
|
||||||
|
let args
|
||||||
|
|
||||||
const tarPath = await getTarPath()
|
const tarPath = await getTarPath()
|
||||||
const tarArgs = await getTarArgs(
|
const tarArgs = await getTarArgs(
|
||||||
tarPath,
|
tarPath,
|
||||||
@@ -142,11 +147,18 @@ async function getArgs(
|
|||||||
tarPath.type === ArchiveToolType.BSD &&
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
compressionMethod !== CompressionMethod.Gzip &&
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
IS_WINDOWS
|
IS_WINDOWS
|
||||||
|
|
||||||
if (BSD_TAR_ZSTD && type !== 'create') {
|
if (BSD_TAR_ZSTD && type !== 'create') {
|
||||||
return [...compressionArgs, ...tarArgs].join(' ')
|
args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')]
|
||||||
} else {
|
} else {
|
||||||
return [...tarArgs, ...compressionArgs].join(' ')
|
args = [[...tarArgs].join(' '), [...compressionArgs].join(' ')]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (BSD_TAR_ZSTD) {
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
return [args.join(' ')]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWorkingDirectory(): string {
|
function getWorkingDirectory(): string {
|
||||||
@@ -171,10 +183,9 @@ async function getDecompressionProgram(
|
|||||||
case CompressionMethod.Zstd:
|
case CompressionMethod.Zstd:
|
||||||
return BSD_TAR_ZSTD
|
return BSD_TAR_ZSTD
|
||||||
? [
|
? [
|
||||||
'zstd -d --long=30 -o',
|
'zstd -d --long=30 --force -o',
|
||||||
TarFilename,
|
TarFilename,
|
||||||
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||||
'&&'
|
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
'--use-compress-program',
|
'--use-compress-program',
|
||||||
@@ -183,10 +194,9 @@ async function getDecompressionProgram(
|
|||||||
case CompressionMethod.ZstdWithoutLong:
|
case CompressionMethod.ZstdWithoutLong:
|
||||||
return BSD_TAR_ZSTD
|
return BSD_TAR_ZSTD
|
||||||
? [
|
? [
|
||||||
'zstd -d -o',
|
'zstd -d --force -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:
|
||||||
@@ -194,6 +204,7 @@ async function getDecompressionProgram(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used for creating the archive
|
||||||
// -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
|
// -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
|
||||||
// zstdmt is equivalent to 'zstd -T0'
|
// zstdmt is equivalent to 'zstd -T0'
|
||||||
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
||||||
@@ -212,8 +223,7 @@ async function getCompressionProgram(
|
|||||||
case CompressionMethod.Zstd:
|
case CompressionMethod.Zstd:
|
||||||
return BSD_TAR_ZSTD
|
return BSD_TAR_ZSTD
|
||||||
? [
|
? [
|
||||||
'&&',
|
'zstd -T0 --long=30 --force -o',
|
||||||
'zstd -T0 --long=30 -o',
|
|
||||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
TarFilename
|
TarFilename
|
||||||
]
|
]
|
||||||
@@ -224,8 +234,7 @@ async function getCompressionProgram(
|
|||||||
case CompressionMethod.ZstdWithoutLong:
|
case CompressionMethod.ZstdWithoutLong:
|
||||||
return BSD_TAR_ZSTD
|
return BSD_TAR_ZSTD
|
||||||
? [
|
? [
|
||||||
'&&',
|
'zstd -T0 --force -o',
|
||||||
'zstd -T0 -o',
|
|
||||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
TarFilename
|
TarFilename
|
||||||
]
|
]
|
||||||
@@ -235,18 +244,29 @@ async function getCompressionProgram(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Executes all commands as separate processes
|
||||||
|
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.split(' ')[0]} failed with error: ${error?.message}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// List the contents of a tar
|
||||||
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}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract a tar
|
||||||
export async function extractTar(
|
export async function extractTar(
|
||||||
archivePath: string,
|
archivePath: string,
|
||||||
compressionMethod: CompressionMethod
|
compressionMethod: CompressionMethod
|
||||||
@@ -254,14 +274,11 @@ 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}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a tar
|
||||||
export async function createTar(
|
export async function createTar(
|
||||||
archiveFolder: string,
|
archiveFolder: string,
|
||||||
sourceDirectories: string[],
|
sourceDirectories: string[],
|
||||||
@@ -272,10 +289,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}`)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user