Compare commits
209
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d3c79e6fe | ||
|
|
e7e19845ca | ||
|
|
cad074ceef | ||
|
|
d7ae8cd1ef | ||
|
|
6bc5dc5a23 | ||
|
|
bbf5659dfa | ||
|
|
d175a181a0 | ||
|
|
0690c10515 | ||
|
|
0c23c38c68 | ||
|
|
7a532d03f4 | ||
|
|
d31c2dd88d | ||
|
|
cb3dc49fec | ||
|
|
27f9a7d461 | ||
|
|
d79a09bc0e | ||
|
|
d1094e1523 | ||
|
|
c0085d7739 | ||
|
|
1dae855746 | ||
|
|
de8fda6976 | ||
|
|
61e630822a | ||
|
|
c207fbd5db | ||
|
|
785599dd2e | ||
|
|
8595831452 | ||
|
|
afbc5c0a9e | ||
|
|
424ae62ee7 | ||
|
|
2e5a517460 | ||
|
|
34f0143be2 | ||
|
|
0fd856d0a0 | ||
|
|
0822441ee0 | ||
|
|
187781e273 | ||
|
|
1f3371766a | ||
|
|
39b7a86b23 | ||
|
|
2f73afa843 | ||
|
|
ffde3e4bd5 | ||
|
|
32f538163d | ||
|
|
32b95825ba | ||
|
|
54eb9b8055 | ||
|
|
f9dfb05bd2 | ||
|
|
b3bd482c0f | ||
|
|
4fa5b7d133 | ||
|
|
ea9856079f | ||
|
|
caadeee090 | ||
|
|
964682b5d4 | ||
|
|
6f7397feb6 | ||
|
|
819157bf87 | ||
|
|
86102e88e9 | ||
|
|
5f89653f1b | ||
|
|
e9e146bbf8 | ||
|
|
27bf8304ea | ||
|
|
db3517fe3b | ||
|
|
6349c3ca3a | ||
|
|
e4c071ba19 | ||
|
|
9443e26349 | ||
|
|
5a0405df4e | ||
|
|
0e707aeabc | ||
|
|
7441dc5e59 | ||
|
|
1ddac5e02f | ||
|
|
55484166d8 | ||
|
|
7181b913f5 | ||
|
|
81cd5a5c2e | ||
|
|
4b348086a9 | ||
|
|
436cf8d6ea | ||
|
|
e0aadb573c | ||
|
|
62a66a8ce9 | ||
|
|
0c58e4113e | ||
|
|
9366237c90 | ||
|
|
b36e70495f | ||
|
|
8423354d7d | ||
|
|
abcca5a0b2 | ||
|
|
b2e1c39c92 | ||
|
|
8e8a93deae | ||
|
|
738c849e89 | ||
|
|
9b58167dc9 | ||
|
|
ffb7e3e14e | ||
|
|
ce378c4cec | ||
|
|
3e257b0745 | ||
|
|
e5e4491ac5 | ||
|
|
1bc93f3cdf | ||
|
|
4fbc5c941a | ||
|
|
ac778acad2 | ||
|
|
192c26f865 | ||
|
|
295cbcc4da | ||
|
|
b00a9fd033 | ||
|
|
4df45177e4 | ||
|
|
33f1d64363 | ||
|
|
ebe4ac336f | ||
|
|
94de2cf6d4 | ||
|
|
64c334f0e5 | ||
|
|
e1bb04bace | ||
|
|
0388e62759 | ||
|
|
e6257f1117 | ||
|
|
b7db7552c9 | ||
|
|
2c50af36e2 | ||
|
|
aac665d186 | ||
|
|
bc4be50597 | ||
|
|
0982f1da89 | ||
|
|
ed96e21792 | ||
|
|
2ae31879b7 | ||
|
|
14d8f65f10 | ||
|
|
f47a9aff5e | ||
|
|
ce68daa10e | ||
|
|
a57a4fe011 | ||
|
|
6c9b023c1b | ||
|
|
0be752bc46 | ||
|
|
5c5e91f040 | ||
|
|
846a0af6ec | ||
|
|
4b6b45fe18 | ||
|
|
98a4069558 | ||
|
|
6e888c882e | ||
|
|
c202c38407 | ||
|
|
d543359fab | ||
|
|
8bd9e29d3c | ||
|
|
63c66cf07e | ||
|
|
556b1c57e7 | ||
|
|
a4276ac40f | ||
|
|
c7340e91af | ||
|
|
d714ea08d6 | ||
|
|
3fd7f664a6 | ||
|
|
30995490f2 | ||
|
|
4beda9cbc0 | ||
|
|
ba462956ea | ||
|
|
cf5d2b8fac | ||
|
|
f9d38b0015 | ||
|
|
23cfbb3484 | ||
|
|
83becb7900 | ||
|
|
ef888588c1 | ||
|
|
f05c04b173 | ||
|
|
518f480528 | ||
|
|
90be12a59c | ||
|
|
fe1ee8b6b4 | ||
|
|
c89375df9f | ||
|
|
7cb82599d4 | ||
|
|
8be69a26ed | ||
|
|
970264135a | ||
|
|
e5e69a3171 | ||
|
|
567598fdd7 | ||
|
|
d8b119ca22 | ||
|
|
a438f61f94 | ||
|
|
388d774221 | ||
|
|
9b309c5a32 | ||
|
|
01e1ff7bc0 | ||
|
|
74ff60c561 | ||
|
|
e98bae803b | ||
|
|
dd553d68ce | ||
|
|
74dd6f6817 | ||
|
|
83bca5cb13 | ||
|
|
2a37ee752b | ||
|
|
ec95a9b114 | ||
|
|
67cb82d99b | ||
|
|
da6701aea9 | ||
|
|
593bc7061c | ||
|
|
120202a68c | ||
|
|
c5278cdd08 | ||
|
|
46231a7da3 | ||
|
|
9b7bcb1567 | ||
|
|
00282d6145 | ||
|
|
b5f31bb5a2 | ||
|
|
41c667327d | ||
|
|
2fd9a80bc1 | ||
|
|
ebfda315a5 | ||
|
|
fe93288f85 | ||
|
|
2d6e5ecd7c | ||
|
|
49cd1ccc3f | ||
|
|
3cf35dbd46 | ||
|
|
845770f824 | ||
|
|
c1bb3fb679 | ||
|
|
347d2e2a35 | ||
|
|
a78bb30ca0 | ||
|
|
1fc4ec3274 | ||
|
|
91842768bd | ||
|
|
1d5b16aa38 | ||
|
|
197f5a13a9 | ||
|
|
8263c4d15d | ||
|
|
4ee0048304 | ||
|
|
d618dc457e | ||
|
|
558edc0a3b | ||
|
|
92b210aced | ||
|
|
6f6f4e7588 | ||
|
|
10a3934663 | ||
|
|
6421989639 | ||
|
|
07b91eafe5 | ||
|
|
b9fefecf57 | ||
|
|
9aecf41d21 | ||
|
|
da52b35800 | ||
|
|
1e0f6285e5 | ||
|
|
dd4e856a4e | ||
|
|
a70804595b | ||
|
|
eb7ed88d77 | ||
|
|
500d0b42fe | ||
|
|
82efa3d285 | ||
|
|
2abc7c46f8 | ||
|
|
e48f1d0c54 | ||
|
|
aa676f3cc7 | ||
|
|
925ae6978b | ||
|
|
e73063a93c | ||
|
|
c4ae214c26 | ||
|
|
07242b37a4 | ||
|
|
01aceeaad6 | ||
|
|
35e5aac523 | ||
|
|
a3c696e88e | ||
|
|
b68735e060 | ||
|
|
d5c547c19f | ||
|
|
9e285cc3fa | ||
|
|
3f95e2ea4f | ||
|
|
fccc5ee6e6 | ||
|
|
3d61fe8000 | ||
|
|
9387bd7ded | ||
|
|
e3549a9c58 | ||
|
|
c5d1911357 | ||
|
|
8b45e1e356 |
@@ -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
|
||||||
@@ -4,7 +4,7 @@ Self-hosted runners [can be configured](https://help.github.com/en/actions/hosti
|
|||||||
|
|
||||||
For actions to **just work** behind a proxy server:
|
For actions to **just work** behind a proxy server:
|
||||||
|
|
||||||
1. Use [tool-cache] version >= 1.3.1
|
1. Use [tool-cache](/packages/tool-cache) version >= 1.3.1
|
||||||
2. Optionally use [actions/http-client](https://github.com/actions/http-client)
|
2. Optionally use [actions/http-client](/packages/http-client)
|
||||||
|
|
||||||
If you are using other http clients, refer to the [environment variables set by the runner](https://help.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners).
|
If you are using other http clients, refer to the [environment variables set by the runner](https://help.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners).
|
||||||
Generated
+6445
-6670
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -24,7 +24,7 @@
|
|||||||
"eslint-plugin-jest": "^22.21.0",
|
"eslint-plugin-jest": "^22.21.0",
|
||||||
"flow-bin": "^0.115.0",
|
"flow-bin": "^0.115.0",
|
||||||
"jest": "^27.2.5",
|
"jest": "^27.2.5",
|
||||||
"lerna": "^4.0.0",
|
"lerna": "^5.4.0",
|
||||||
"prettier": "^1.19.1",
|
"prettier": "^1.19.1",
|
||||||
"ts-jest": "^27.0.5",
|
"ts-jest": "^27.0.5",
|
||||||
"typescript": "^3.9.9"
|
"typescript": "^3.9.9"
|
||||||
|
|||||||
@@ -77,4 +77,16 @@
|
|||||||
|
|
||||||
### 1.0.0
|
### 1.0.0
|
||||||
|
|
||||||
- Update `lockfileVersion` to `v2` in `package-lock.json [#1009](https://github.com/actions/toolkit/pull/1009)
|
- Update `lockfileVersion` to `v2` in `package-lock.json` [#1009](https://github.com/actions/toolkit/pull/1009)
|
||||||
|
|
||||||
|
### 1.0.1
|
||||||
|
|
||||||
|
- Update to v2.0.0 of `@actions/http-client`
|
||||||
|
|
||||||
|
### 1.0.2
|
||||||
|
|
||||||
|
- Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
|
||||||
|
|
||||||
|
### 1.1.0
|
||||||
|
|
||||||
|
- Add `x-actions-results-crc64` and `x-actions-results-md5` checksum headers on upload [#1063](https://github.com/actions/toolkit/pull/1063)
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import CRC64, {CRC64DigestEncoding} from '../src/internal/crc64'
|
||||||
|
|
||||||
|
const fixtures = {
|
||||||
|
data:
|
||||||
|
'🚀 👉😎👉 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\nUt enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\nExcepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n',
|
||||||
|
expected: {
|
||||||
|
hex: '846CE4ADAD6223ED',
|
||||||
|
base64: '7SNira3kbIQ=',
|
||||||
|
buffer: Buffer.from([0xed, 0x23, 0x62, 0xad, 0xad, 0xe4, 0x6c, 0x84])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertEncodings(crc: CRC64): void {
|
||||||
|
const encodings = Object.keys(fixtures.expected) as CRC64DigestEncoding[]
|
||||||
|
for (const encoding of encodings) {
|
||||||
|
expect(crc.digest(encoding)).toEqual(fixtures.expected[encoding])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('@actions/artifact/src/internal/crc64', () => {
|
||||||
|
it('CRC64 from string', async () => {
|
||||||
|
const crc = new CRC64()
|
||||||
|
crc.update(fixtures.data)
|
||||||
|
|
||||||
|
assertEncodings(crc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('CRC64 from buffer', async () => {
|
||||||
|
const crc = new CRC64()
|
||||||
|
const buf = Buffer.from(fixtures.data)
|
||||||
|
crc.update(buf)
|
||||||
|
|
||||||
|
assertEncodings(crc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('CRC64 from split data', async () => {
|
||||||
|
const crc = new CRC64()
|
||||||
|
const splits = fixtures.data.split('\n').slice(0, -1)
|
||||||
|
for (const split of splits) {
|
||||||
|
crc.update(`${split}\n`)
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEncodings(crc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('flips 64 bits', async () => {
|
||||||
|
const tests = [
|
||||||
|
[BigInt(0), BigInt('0xffffffffffffffff')],
|
||||||
|
[BigInt('0xffffffffffffffff'), BigInt(0)],
|
||||||
|
[BigInt('0xdeadbeef'), BigInt('0xffffffff21524110')]
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const [input, expected] of tests) {
|
||||||
|
expect(CRC64.flip64Bits(input)).toEqual(expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -3,7 +3,6 @@ import * as net from 'net'
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as configVariables from '../src/internal/config-variables'
|
import * as configVariables from '../src/internal/config-variables'
|
||||||
import {retry} from '../src/internal/requestUtils'
|
import {retry} from '../src/internal/requestUtils'
|
||||||
import {IHttpClientResponse} from '@actions/http-client/interfaces'
|
|
||||||
import {HttpClientResponse} from '@actions/http-client'
|
import {HttpClientResponse} from '@actions/http-client'
|
||||||
|
|
||||||
jest.mock('../src/internal/config-variables')
|
jest.mock('../src/internal/config-variables')
|
||||||
@@ -42,7 +41,7 @@ async function testRetry(
|
|||||||
|
|
||||||
async function handleResponse(
|
async function handleResponse(
|
||||||
testResponseCode: number | undefined
|
testResponseCode: number | undefined
|
||||||
): Promise<IHttpClientResponse> {
|
): Promise<HttpClientResponse> {
|
||||||
if (!testResponseCode) {
|
if (!testResponseCode) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Test incorrectly set up. reverse.pop() was called too many times so not enough test response codes were supplied'
|
'Test incorrectly set up. reverse.pop() was called too many times so not enough test response codes were supplied'
|
||||||
@@ -72,7 +71,7 @@ async function emptyMockReadBody(): Promise<string> {
|
|||||||
|
|
||||||
async function setupSingleMockResponse(
|
async function setupSingleMockResponse(
|
||||||
statusCode: number
|
statusCode: number
|
||||||
): Promise<IHttpClientResponse> {
|
): Promise<HttpClientResponse> {
|
||||||
const mockMessage = new http.IncomingMessage(new net.Socket())
|
const mockMessage = new http.IncomingMessage(new net.Socket())
|
||||||
const mockReadBody = emptyMockReadBody
|
const mockReadBody = emptyMockReadBody
|
||||||
mockMessage.statusCode = statusCode
|
mockMessage.statusCode = statusCode
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
getInitialRetryIntervalInMilliseconds,
|
getInitialRetryIntervalInMilliseconds,
|
||||||
getRetryMultiplier
|
getRetryMultiplier
|
||||||
} from '../src/internal/config-variables'
|
} from '../src/internal/config-variables'
|
||||||
|
import {Readable} from 'stream'
|
||||||
|
|
||||||
jest.mock('../src/internal/config-variables')
|
jest.mock('../src/internal/config-variables')
|
||||||
|
|
||||||
@@ -74,15 +75,20 @@ describe('Utils', () => {
|
|||||||
const size = 24
|
const size = 24
|
||||||
const uncompressedLength = 100
|
const uncompressedLength = 100
|
||||||
const range = 'bytes 0-199/200'
|
const range = 'bytes 0-199/200'
|
||||||
|
const digest = {
|
||||||
|
crc64: 'bSzITYnW/P8=',
|
||||||
|
md5: 'Xiv1fT9AxLbfadrxk2y3ZvgyN0tPwCWafL/wbi9w8mk='
|
||||||
|
}
|
||||||
const headers = utils.getUploadHeaders(
|
const headers = utils.getUploadHeaders(
|
||||||
contentType,
|
contentType,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
uncompressedLength,
|
uncompressedLength,
|
||||||
size,
|
size,
|
||||||
range
|
range,
|
||||||
|
digest
|
||||||
)
|
)
|
||||||
expect(Object.keys(headers).length).toEqual(8)
|
expect(Object.keys(headers).length).toEqual(10)
|
||||||
expect(headers['Accept']).toEqual(
|
expect(headers['Accept']).toEqual(
|
||||||
`application/json;api-version=${utils.getApiVersion()}`
|
`application/json;api-version=${utils.getApiVersion()}`
|
||||||
)
|
)
|
||||||
@@ -93,6 +99,8 @@ describe('Utils', () => {
|
|||||||
expect(headers['x-tfs-filelength']).toEqual(uncompressedLength)
|
expect(headers['x-tfs-filelength']).toEqual(uncompressedLength)
|
||||||
expect(headers['Content-Length']).toEqual(size)
|
expect(headers['Content-Length']).toEqual(size)
|
||||||
expect(headers['Content-Range']).toEqual(range)
|
expect(headers['Content-Range']).toEqual(range)
|
||||||
|
expect(headers['x-actions-results-crc64']).toEqual(digest.crc64)
|
||||||
|
expect(headers['x-actions-results-md5']).toEqual(digest.md5)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Test constructing upload headers with only required parameter', () => {
|
it('Test constructing upload headers with only required parameter', () => {
|
||||||
@@ -219,4 +227,13 @@ describe('Utils', () => {
|
|||||||
const size2 = (await fs.promises.stat(emptyFile2)).size
|
const size2 = (await fs.promises.stat(emptyFile2)).size
|
||||||
expect(size2).toEqual(0)
|
expect(size2).toEqual(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Creates a digest from a readable stream', async () => {
|
||||||
|
const data = 'lorem ipsum'
|
||||||
|
const stream = Readable.from(data)
|
||||||
|
const digest = await utils.digestForStream(stream)
|
||||||
|
|
||||||
|
expect(digest.crc64).toBe('bSzITYnW/P8=')
|
||||||
|
expect(digest.md5).toBe('gKdR/eV3AoZAxBkADjPrpg==')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Generated
+35
-20
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/artifact",
|
"name": "@actions/artifact",
|
||||||
"version": "0.6.1",
|
"version": "1.1.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/artifact",
|
"name": "@actions/artifact",
|
||||||
"version": "0.6.1",
|
"version": "1.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.9.1",
|
||||||
"@actions/http-client": "^1.0.11",
|
"@actions/http-client": "^2.0.1",
|
||||||
"tmp": "^0.2.1",
|
"tmp": "^0.2.1",
|
||||||
"tmp-promise": "^3.0.2"
|
"tmp-promise": "^3.0.2"
|
||||||
},
|
},
|
||||||
@@ -20,19 +20,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/core": {
|
"node_modules/@actions/core": {
|
||||||
"version": "1.6.0",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||||
"integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
|
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^1.0.11"
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/http-client": {
|
"node_modules/@actions/http-client": {
|
||||||
"version": "1.0.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/tmp": {
|
"node_modules/@types/tmp": {
|
||||||
@@ -179,6 +180,14 @@
|
|||||||
"node": ">=4.2.0"
|
"node": ">=4.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/wrappy": {
|
"node_modules/wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
@@ -187,19 +196,20 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": {
|
"@actions/core": {
|
||||||
"version": "1.6.0",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||||
"integrity": "sha512-NB1UAZomZlCV/LmJqkLhNTqtKfFXJZAUPcfl/zqG7EfsQdeUJtaWO98SGbuQ3pydJ3fHl2CvI/51OKYlCYYcaw==",
|
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/http-client": "^1.0.11"
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/tmp": {
|
"@types/tmp": {
|
||||||
@@ -315,6 +325,11 @@
|
|||||||
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
|
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
|
},
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/artifact",
|
"name": "@actions/artifact",
|
||||||
"version": "1.0.0",
|
"version": "1.1.0",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"description": "Actions artifact lib",
|
"description": "Actions artifact lib",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -37,8 +37,8 @@
|
|||||||
"url": "https://github.com/actions/toolkit/issues"
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.9.1",
|
||||||
"@actions/http-client": "^1.0.11",
|
"@actions/http-client": "^2.0.1",
|
||||||
"tmp": "^0.2.1",
|
"tmp": "^0.2.1",
|
||||||
"tmp-promise": "^3.0.2"
|
"tmp-promise": "^3.0.2"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,317 @@
|
|||||||
|
/**
|
||||||
|
* CRC64: cyclic redundancy check, 64-bits
|
||||||
|
*
|
||||||
|
* In order to validate that artifacts are not being corrupted over the wire, this redundancy check allows us to
|
||||||
|
* validate that there was no corruption during transmission. The implementation here is based on Go's hash/crc64 pkg,
|
||||||
|
* but without the slicing-by-8 optimization: https://cs.opensource.google/go/go/+/master:src/hash/crc64/crc64.go
|
||||||
|
*
|
||||||
|
* This implementation uses a pregenerated table based on 0x9A6C9329AC4BC9B5 as the polynomial, the same polynomial that
|
||||||
|
* is used for Azure Storage: https://github.com/Azure/azure-storage-net/blob/cbe605f9faa01bfc3003d75fc5a16b2eaccfe102/Lib/Common/Core/Util/Crc64.cs#L27
|
||||||
|
*/
|
||||||
|
|
||||||
|
// when transpile target is >= ES2020 (after dropping node 12) these can be changed to bigint literals - ts(2737)
|
||||||
|
const PREGEN_POLY_TABLE = [
|
||||||
|
BigInt('0x0000000000000000'),
|
||||||
|
BigInt('0x7F6EF0C830358979'),
|
||||||
|
BigInt('0xFEDDE190606B12F2'),
|
||||||
|
BigInt('0x81B31158505E9B8B'),
|
||||||
|
BigInt('0xC962E5739841B68F'),
|
||||||
|
BigInt('0xB60C15BBA8743FF6'),
|
||||||
|
BigInt('0x37BF04E3F82AA47D'),
|
||||||
|
BigInt('0x48D1F42BC81F2D04'),
|
||||||
|
BigInt('0xA61CECB46814FE75'),
|
||||||
|
BigInt('0xD9721C7C5821770C'),
|
||||||
|
BigInt('0x58C10D24087FEC87'),
|
||||||
|
BigInt('0x27AFFDEC384A65FE'),
|
||||||
|
BigInt('0x6F7E09C7F05548FA'),
|
||||||
|
BigInt('0x1010F90FC060C183'),
|
||||||
|
BigInt('0x91A3E857903E5A08'),
|
||||||
|
BigInt('0xEECD189FA00BD371'),
|
||||||
|
BigInt('0x78E0FF3B88BE6F81'),
|
||||||
|
BigInt('0x078E0FF3B88BE6F8'),
|
||||||
|
BigInt('0x863D1EABE8D57D73'),
|
||||||
|
BigInt('0xF953EE63D8E0F40A'),
|
||||||
|
BigInt('0xB1821A4810FFD90E'),
|
||||||
|
BigInt('0xCEECEA8020CA5077'),
|
||||||
|
BigInt('0x4F5FFBD87094CBFC'),
|
||||||
|
BigInt('0x30310B1040A14285'),
|
||||||
|
BigInt('0xDEFC138FE0AA91F4'),
|
||||||
|
BigInt('0xA192E347D09F188D'),
|
||||||
|
BigInt('0x2021F21F80C18306'),
|
||||||
|
BigInt('0x5F4F02D7B0F40A7F'),
|
||||||
|
BigInt('0x179EF6FC78EB277B'),
|
||||||
|
BigInt('0x68F0063448DEAE02'),
|
||||||
|
BigInt('0xE943176C18803589'),
|
||||||
|
BigInt('0x962DE7A428B5BCF0'),
|
||||||
|
BigInt('0xF1C1FE77117CDF02'),
|
||||||
|
BigInt('0x8EAF0EBF2149567B'),
|
||||||
|
BigInt('0x0F1C1FE77117CDF0'),
|
||||||
|
BigInt('0x7072EF2F41224489'),
|
||||||
|
BigInt('0x38A31B04893D698D'),
|
||||||
|
BigInt('0x47CDEBCCB908E0F4'),
|
||||||
|
BigInt('0xC67EFA94E9567B7F'),
|
||||||
|
BigInt('0xB9100A5CD963F206'),
|
||||||
|
BigInt('0x57DD12C379682177'),
|
||||||
|
BigInt('0x28B3E20B495DA80E'),
|
||||||
|
BigInt('0xA900F35319033385'),
|
||||||
|
BigInt('0xD66E039B2936BAFC'),
|
||||||
|
BigInt('0x9EBFF7B0E12997F8'),
|
||||||
|
BigInt('0xE1D10778D11C1E81'),
|
||||||
|
BigInt('0x606216208142850A'),
|
||||||
|
BigInt('0x1F0CE6E8B1770C73'),
|
||||||
|
BigInt('0x8921014C99C2B083'),
|
||||||
|
BigInt('0xF64FF184A9F739FA'),
|
||||||
|
BigInt('0x77FCE0DCF9A9A271'),
|
||||||
|
BigInt('0x08921014C99C2B08'),
|
||||||
|
BigInt('0x4043E43F0183060C'),
|
||||||
|
BigInt('0x3F2D14F731B68F75'),
|
||||||
|
BigInt('0xBE9E05AF61E814FE'),
|
||||||
|
BigInt('0xC1F0F56751DD9D87'),
|
||||||
|
BigInt('0x2F3DEDF8F1D64EF6'),
|
||||||
|
BigInt('0x50531D30C1E3C78F'),
|
||||||
|
BigInt('0xD1E00C6891BD5C04'),
|
||||||
|
BigInt('0xAE8EFCA0A188D57D'),
|
||||||
|
BigInt('0xE65F088B6997F879'),
|
||||||
|
BigInt('0x9931F84359A27100'),
|
||||||
|
BigInt('0x1882E91B09FCEA8B'),
|
||||||
|
BigInt('0x67EC19D339C963F2'),
|
||||||
|
BigInt('0xD75ADABD7A6E2D6F'),
|
||||||
|
BigInt('0xA8342A754A5BA416'),
|
||||||
|
BigInt('0x29873B2D1A053F9D'),
|
||||||
|
BigInt('0x56E9CBE52A30B6E4'),
|
||||||
|
BigInt('0x1E383FCEE22F9BE0'),
|
||||||
|
BigInt('0x6156CF06D21A1299'),
|
||||||
|
BigInt('0xE0E5DE5E82448912'),
|
||||||
|
BigInt('0x9F8B2E96B271006B'),
|
||||||
|
BigInt('0x71463609127AD31A'),
|
||||||
|
BigInt('0x0E28C6C1224F5A63'),
|
||||||
|
BigInt('0x8F9BD7997211C1E8'),
|
||||||
|
BigInt('0xF0F5275142244891'),
|
||||||
|
BigInt('0xB824D37A8A3B6595'),
|
||||||
|
BigInt('0xC74A23B2BA0EECEC'),
|
||||||
|
BigInt('0x46F932EAEA507767'),
|
||||||
|
BigInt('0x3997C222DA65FE1E'),
|
||||||
|
BigInt('0xAFBA2586F2D042EE'),
|
||||||
|
BigInt('0xD0D4D54EC2E5CB97'),
|
||||||
|
BigInt('0x5167C41692BB501C'),
|
||||||
|
BigInt('0x2E0934DEA28ED965'),
|
||||||
|
BigInt('0x66D8C0F56A91F461'),
|
||||||
|
BigInt('0x19B6303D5AA47D18'),
|
||||||
|
BigInt('0x980521650AFAE693'),
|
||||||
|
BigInt('0xE76BD1AD3ACF6FEA'),
|
||||||
|
BigInt('0x09A6C9329AC4BC9B'),
|
||||||
|
BigInt('0x76C839FAAAF135E2'),
|
||||||
|
BigInt('0xF77B28A2FAAFAE69'),
|
||||||
|
BigInt('0x8815D86ACA9A2710'),
|
||||||
|
BigInt('0xC0C42C4102850A14'),
|
||||||
|
BigInt('0xBFAADC8932B0836D'),
|
||||||
|
BigInt('0x3E19CDD162EE18E6'),
|
||||||
|
BigInt('0x41773D1952DB919F'),
|
||||||
|
BigInt('0x269B24CA6B12F26D'),
|
||||||
|
BigInt('0x59F5D4025B277B14'),
|
||||||
|
BigInt('0xD846C55A0B79E09F'),
|
||||||
|
BigInt('0xA72835923B4C69E6'),
|
||||||
|
BigInt('0xEFF9C1B9F35344E2'),
|
||||||
|
BigInt('0x90973171C366CD9B'),
|
||||||
|
BigInt('0x1124202993385610'),
|
||||||
|
BigInt('0x6E4AD0E1A30DDF69'),
|
||||||
|
BigInt('0x8087C87E03060C18'),
|
||||||
|
BigInt('0xFFE938B633338561'),
|
||||||
|
BigInt('0x7E5A29EE636D1EEA'),
|
||||||
|
BigInt('0x0134D92653589793'),
|
||||||
|
BigInt('0x49E52D0D9B47BA97'),
|
||||||
|
BigInt('0x368BDDC5AB7233EE'),
|
||||||
|
BigInt('0xB738CC9DFB2CA865'),
|
||||||
|
BigInt('0xC8563C55CB19211C'),
|
||||||
|
BigInt('0x5E7BDBF1E3AC9DEC'),
|
||||||
|
BigInt('0x21152B39D3991495'),
|
||||||
|
BigInt('0xA0A63A6183C78F1E'),
|
||||||
|
BigInt('0xDFC8CAA9B3F20667'),
|
||||||
|
BigInt('0x97193E827BED2B63'),
|
||||||
|
BigInt('0xE877CE4A4BD8A21A'),
|
||||||
|
BigInt('0x69C4DF121B863991'),
|
||||||
|
BigInt('0x16AA2FDA2BB3B0E8'),
|
||||||
|
BigInt('0xF86737458BB86399'),
|
||||||
|
BigInt('0x8709C78DBB8DEAE0'),
|
||||||
|
BigInt('0x06BAD6D5EBD3716B'),
|
||||||
|
BigInt('0x79D4261DDBE6F812'),
|
||||||
|
BigInt('0x3105D23613F9D516'),
|
||||||
|
BigInt('0x4E6B22FE23CC5C6F'),
|
||||||
|
BigInt('0xCFD833A67392C7E4'),
|
||||||
|
BigInt('0xB0B6C36E43A74E9D'),
|
||||||
|
BigInt('0x9A6C9329AC4BC9B5'),
|
||||||
|
BigInt('0xE50263E19C7E40CC'),
|
||||||
|
BigInt('0x64B172B9CC20DB47'),
|
||||||
|
BigInt('0x1BDF8271FC15523E'),
|
||||||
|
BigInt('0x530E765A340A7F3A'),
|
||||||
|
BigInt('0x2C608692043FF643'),
|
||||||
|
BigInt('0xADD397CA54616DC8'),
|
||||||
|
BigInt('0xD2BD67026454E4B1'),
|
||||||
|
BigInt('0x3C707F9DC45F37C0'),
|
||||||
|
BigInt('0x431E8F55F46ABEB9'),
|
||||||
|
BigInt('0xC2AD9E0DA4342532'),
|
||||||
|
BigInt('0xBDC36EC59401AC4B'),
|
||||||
|
BigInt('0xF5129AEE5C1E814F'),
|
||||||
|
BigInt('0x8A7C6A266C2B0836'),
|
||||||
|
BigInt('0x0BCF7B7E3C7593BD'),
|
||||||
|
BigInt('0x74A18BB60C401AC4'),
|
||||||
|
BigInt('0xE28C6C1224F5A634'),
|
||||||
|
BigInt('0x9DE29CDA14C02F4D'),
|
||||||
|
BigInt('0x1C518D82449EB4C6'),
|
||||||
|
BigInt('0x633F7D4A74AB3DBF'),
|
||||||
|
BigInt('0x2BEE8961BCB410BB'),
|
||||||
|
BigInt('0x548079A98C8199C2'),
|
||||||
|
BigInt('0xD53368F1DCDF0249'),
|
||||||
|
BigInt('0xAA5D9839ECEA8B30'),
|
||||||
|
BigInt('0x449080A64CE15841'),
|
||||||
|
BigInt('0x3BFE706E7CD4D138'),
|
||||||
|
BigInt('0xBA4D61362C8A4AB3'),
|
||||||
|
BigInt('0xC52391FE1CBFC3CA'),
|
||||||
|
BigInt('0x8DF265D5D4A0EECE'),
|
||||||
|
BigInt('0xF29C951DE49567B7'),
|
||||||
|
BigInt('0x732F8445B4CBFC3C'),
|
||||||
|
BigInt('0x0C41748D84FE7545'),
|
||||||
|
BigInt('0x6BAD6D5EBD3716B7'),
|
||||||
|
BigInt('0x14C39D968D029FCE'),
|
||||||
|
BigInt('0x95708CCEDD5C0445'),
|
||||||
|
BigInt('0xEA1E7C06ED698D3C'),
|
||||||
|
BigInt('0xA2CF882D2576A038'),
|
||||||
|
BigInt('0xDDA178E515432941'),
|
||||||
|
BigInt('0x5C1269BD451DB2CA'),
|
||||||
|
BigInt('0x237C997575283BB3'),
|
||||||
|
BigInt('0xCDB181EAD523E8C2'),
|
||||||
|
BigInt('0xB2DF7122E51661BB'),
|
||||||
|
BigInt('0x336C607AB548FA30'),
|
||||||
|
BigInt('0x4C0290B2857D7349'),
|
||||||
|
BigInt('0x04D364994D625E4D'),
|
||||||
|
BigInt('0x7BBD94517D57D734'),
|
||||||
|
BigInt('0xFA0E85092D094CBF'),
|
||||||
|
BigInt('0x856075C11D3CC5C6'),
|
||||||
|
BigInt('0x134D926535897936'),
|
||||||
|
BigInt('0x6C2362AD05BCF04F'),
|
||||||
|
BigInt('0xED9073F555E26BC4'),
|
||||||
|
BigInt('0x92FE833D65D7E2BD'),
|
||||||
|
BigInt('0xDA2F7716ADC8CFB9'),
|
||||||
|
BigInt('0xA54187DE9DFD46C0'),
|
||||||
|
BigInt('0x24F29686CDA3DD4B'),
|
||||||
|
BigInt('0x5B9C664EFD965432'),
|
||||||
|
BigInt('0xB5517ED15D9D8743'),
|
||||||
|
BigInt('0xCA3F8E196DA80E3A'),
|
||||||
|
BigInt('0x4B8C9F413DF695B1'),
|
||||||
|
BigInt('0x34E26F890DC31CC8'),
|
||||||
|
BigInt('0x7C339BA2C5DC31CC'),
|
||||||
|
BigInt('0x035D6B6AF5E9B8B5'),
|
||||||
|
BigInt('0x82EE7A32A5B7233E'),
|
||||||
|
BigInt('0xFD808AFA9582AA47'),
|
||||||
|
BigInt('0x4D364994D625E4DA'),
|
||||||
|
BigInt('0x3258B95CE6106DA3'),
|
||||||
|
BigInt('0xB3EBA804B64EF628'),
|
||||||
|
BigInt('0xCC8558CC867B7F51'),
|
||||||
|
BigInt('0x8454ACE74E645255'),
|
||||||
|
BigInt('0xFB3A5C2F7E51DB2C'),
|
||||||
|
BigInt('0x7A894D772E0F40A7'),
|
||||||
|
BigInt('0x05E7BDBF1E3AC9DE'),
|
||||||
|
BigInt('0xEB2AA520BE311AAF'),
|
||||||
|
BigInt('0x944455E88E0493D6'),
|
||||||
|
BigInt('0x15F744B0DE5A085D'),
|
||||||
|
BigInt('0x6A99B478EE6F8124'),
|
||||||
|
BigInt('0x224840532670AC20'),
|
||||||
|
BigInt('0x5D26B09B16452559'),
|
||||||
|
BigInt('0xDC95A1C3461BBED2'),
|
||||||
|
BigInt('0xA3FB510B762E37AB'),
|
||||||
|
BigInt('0x35D6B6AF5E9B8B5B'),
|
||||||
|
BigInt('0x4AB846676EAE0222'),
|
||||||
|
BigInt('0xCB0B573F3EF099A9'),
|
||||||
|
BigInt('0xB465A7F70EC510D0'),
|
||||||
|
BigInt('0xFCB453DCC6DA3DD4'),
|
||||||
|
BigInt('0x83DAA314F6EFB4AD'),
|
||||||
|
BigInt('0x0269B24CA6B12F26'),
|
||||||
|
BigInt('0x7D0742849684A65F'),
|
||||||
|
BigInt('0x93CA5A1B368F752E'),
|
||||||
|
BigInt('0xECA4AAD306BAFC57'),
|
||||||
|
BigInt('0x6D17BB8B56E467DC'),
|
||||||
|
BigInt('0x12794B4366D1EEA5'),
|
||||||
|
BigInt('0x5AA8BF68AECEC3A1'),
|
||||||
|
BigInt('0x25C64FA09EFB4AD8'),
|
||||||
|
BigInt('0xA4755EF8CEA5D153'),
|
||||||
|
BigInt('0xDB1BAE30FE90582A'),
|
||||||
|
BigInt('0xBCF7B7E3C7593BD8'),
|
||||||
|
BigInt('0xC399472BF76CB2A1'),
|
||||||
|
BigInt('0x422A5673A732292A'),
|
||||||
|
BigInt('0x3D44A6BB9707A053'),
|
||||||
|
BigInt('0x759552905F188D57'),
|
||||||
|
BigInt('0x0AFBA2586F2D042E'),
|
||||||
|
BigInt('0x8B48B3003F739FA5'),
|
||||||
|
BigInt('0xF42643C80F4616DC'),
|
||||||
|
BigInt('0x1AEB5B57AF4DC5AD'),
|
||||||
|
BigInt('0x6585AB9F9F784CD4'),
|
||||||
|
BigInt('0xE436BAC7CF26D75F'),
|
||||||
|
BigInt('0x9B584A0FFF135E26'),
|
||||||
|
BigInt('0xD389BE24370C7322'),
|
||||||
|
BigInt('0xACE74EEC0739FA5B'),
|
||||||
|
BigInt('0x2D545FB4576761D0'),
|
||||||
|
BigInt('0x523AAF7C6752E8A9'),
|
||||||
|
BigInt('0xC41748D84FE75459'),
|
||||||
|
BigInt('0xBB79B8107FD2DD20'),
|
||||||
|
BigInt('0x3ACAA9482F8C46AB'),
|
||||||
|
BigInt('0x45A459801FB9CFD2'),
|
||||||
|
BigInt('0x0D75ADABD7A6E2D6'),
|
||||||
|
BigInt('0x721B5D63E7936BAF'),
|
||||||
|
BigInt('0xF3A84C3BB7CDF024'),
|
||||||
|
BigInt('0x8CC6BCF387F8795D'),
|
||||||
|
BigInt('0x620BA46C27F3AA2C'),
|
||||||
|
BigInt('0x1D6554A417C62355'),
|
||||||
|
BigInt('0x9CD645FC4798B8DE'),
|
||||||
|
BigInt('0xE3B8B53477AD31A7'),
|
||||||
|
BigInt('0xAB69411FBFB21CA3'),
|
||||||
|
BigInt('0xD407B1D78F8795DA'),
|
||||||
|
BigInt('0x55B4A08FDFD90E51'),
|
||||||
|
BigInt('0x2ADA5047EFEC8728')
|
||||||
|
]
|
||||||
|
|
||||||
|
export type CRC64DigestEncoding = 'hex' | 'base64' | 'buffer'
|
||||||
|
|
||||||
|
class CRC64 {
|
||||||
|
private _crc: bigint
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this._crc = BigInt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
update(data: Buffer | string): void {
|
||||||
|
const buffer = typeof data === 'string' ? Buffer.from(data) : data
|
||||||
|
let crc = CRC64.flip64Bits(this._crc)
|
||||||
|
|
||||||
|
for (const dataByte of buffer) {
|
||||||
|
const crcByte = Number(crc & BigInt(0xff))
|
||||||
|
crc = PREGEN_POLY_TABLE[crcByte ^ dataByte] ^ (crc >> BigInt(8))
|
||||||
|
}
|
||||||
|
|
||||||
|
this._crc = CRC64.flip64Bits(crc)
|
||||||
|
}
|
||||||
|
|
||||||
|
digest(encoding?: CRC64DigestEncoding): string | Buffer {
|
||||||
|
switch (encoding) {
|
||||||
|
case 'hex':
|
||||||
|
return this._crc.toString(16).toUpperCase()
|
||||||
|
case 'base64':
|
||||||
|
return this.toBuffer().toString('base64')
|
||||||
|
default:
|
||||||
|
return this.toBuffer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private toBuffer(): Buffer {
|
||||||
|
return Buffer.from(
|
||||||
|
[0, 8, 16, 24, 32, 40, 48, 56].map(s =>
|
||||||
|
Number((this._crc >> BigInt(s)) & BigInt(0xff))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
static flip64Bits(n: bigint): bigint {
|
||||||
|
return (BigInt(1) << BigInt(64)) - BigInt(1) - n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CRC64
|
||||||
@@ -18,7 +18,7 @@ import {URL} from 'url'
|
|||||||
import {StatusReporter} from './status-reporter'
|
import {StatusReporter} from './status-reporter'
|
||||||
import {performance} from 'perf_hooks'
|
import {performance} from 'perf_hooks'
|
||||||
import {ListArtifactsResponse, QueryArtifactResponse} from './contracts'
|
import {ListArtifactsResponse, QueryArtifactResponse} from './contracts'
|
||||||
import {IHttpClientResponse} from '@actions/http-client/interfaces'
|
import {HttpClientResponse} from '@actions/http-client'
|
||||||
import {HttpManager} from './http-manager'
|
import {HttpManager} from './http-manager'
|
||||||
import {DownloadItem} from './download-specification'
|
import {DownloadItem} from './download-specification'
|
||||||
import {getDownloadFileConcurrency, getRetryLimit} from './config-variables'
|
import {getDownloadFileConcurrency, getRetryLimit} from './config-variables'
|
||||||
@@ -152,7 +152,7 @@ export class DownloadHttpClient {
|
|||||||
const headers = getDownloadHeaders('application/json', true, true)
|
const headers = getDownloadHeaders('application/json', true, true)
|
||||||
|
|
||||||
// a single GET request is used to download a file
|
// a single GET request is used to download a file
|
||||||
const makeDownloadRequest = async (): Promise<IHttpClientResponse> => {
|
const makeDownloadRequest = async (): Promise<HttpClientResponse> => {
|
||||||
const client = this.downloadHttpManager.getClient(httpClientIndex)
|
const client = this.downloadHttpManager.getClient(httpClientIndex)
|
||||||
return await client.get(artifactLocation, headers)
|
return await client.get(artifactLocation, headers)
|
||||||
}
|
}
|
||||||
@@ -225,7 +225,7 @@ export class DownloadHttpClient {
|
|||||||
|
|
||||||
// keep trying to download a file until a retry limit has been reached
|
// keep trying to download a file until a retry limit has been reached
|
||||||
while (retryCount <= retryLimit) {
|
while (retryCount <= retryLimit) {
|
||||||
let response: IHttpClientResponse
|
let response: HttpClientResponse
|
||||||
try {
|
try {
|
||||||
response = await makeDownloadRequest()
|
response = await makeDownloadRequest()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -295,7 +295,7 @@ export class DownloadHttpClient {
|
|||||||
* @param isGzip a boolean denoting if the content is compressed using gzip and if we need to decode it
|
* @param isGzip a boolean denoting if the content is compressed using gzip and if we need to decode it
|
||||||
*/
|
*/
|
||||||
async pipeResponseToFile(
|
async pipeResponseToFile(
|
||||||
response: IHttpClientResponse,
|
response: HttpClientResponse,
|
||||||
destinationStream: fs.WriteStream,
|
destinationStream: fs.WriteStream,
|
||||||
isGzip: boolean
|
isGzip: boolean
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {HttpClient} from '@actions/http-client/index'
|
import {HttpClient} from '@actions/http-client'
|
||||||
import {createHttpClient} from './utils'
|
import {createHttpClient} from './utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {IHttpClientResponse} from '@actions/http-client/interfaces'
|
import {HttpClientResponse} from '@actions/http-client'
|
||||||
import {
|
import {
|
||||||
isRetryableStatusCode,
|
isRetryableStatusCode,
|
||||||
isSuccessStatusCode,
|
isSuccessStatusCode,
|
||||||
@@ -11,11 +11,11 @@ import {getRetryLimit} from './config-variables'
|
|||||||
|
|
||||||
export async function retry(
|
export async function retry(
|
||||||
name: string,
|
name: string,
|
||||||
operation: () => Promise<IHttpClientResponse>,
|
operation: () => Promise<HttpClientResponse>,
|
||||||
customErrorMessages: Map<number, string>,
|
customErrorMessages: Map<number, string>,
|
||||||
maxAttempts: number
|
maxAttempts: number
|
||||||
): Promise<IHttpClientResponse> {
|
): Promise<HttpClientResponse> {
|
||||||
let response: IHttpClientResponse | undefined = undefined
|
let response: HttpClientResponse | undefined = undefined
|
||||||
let statusCode: number | undefined = undefined
|
let statusCode: number | undefined = undefined
|
||||||
let isRetryable = false
|
let isRetryable = false
|
||||||
let errorMessage = ''
|
let errorMessage = ''
|
||||||
@@ -71,9 +71,9 @@ export async function retry(
|
|||||||
|
|
||||||
export async function retryHttpClientRequest(
|
export async function retryHttpClientRequest(
|
||||||
name: string,
|
name: string,
|
||||||
method: () => Promise<IHttpClientResponse>,
|
method: () => Promise<HttpClientResponse>,
|
||||||
customErrorMessages: Map<number, string> = new Map(),
|
customErrorMessages: Map<number, string> = new Map(),
|
||||||
maxAttempts = getRetryLimit()
|
maxAttempts = getRetryLimit()
|
||||||
): Promise<IHttpClientResponse> {
|
): Promise<HttpClientResponse> {
|
||||||
return await retry(name, method, customErrorMessages, maxAttempts)
|
return await retry(name, method, customErrorMessages, maxAttempts)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
UploadResults
|
UploadResults
|
||||||
} from './contracts'
|
} from './contracts'
|
||||||
import {
|
import {
|
||||||
|
digestForStream,
|
||||||
getArtifactUrl,
|
getArtifactUrl,
|
||||||
getContentRange,
|
getContentRange,
|
||||||
getUploadHeaders,
|
getUploadHeaders,
|
||||||
@@ -31,8 +32,7 @@ import {promisify} from 'util'
|
|||||||
import {URL} from 'url'
|
import {URL} from 'url'
|
||||||
import {performance} from 'perf_hooks'
|
import {performance} from 'perf_hooks'
|
||||||
import {StatusReporter} from './status-reporter'
|
import {StatusReporter} from './status-reporter'
|
||||||
import {HttpCodes} from '@actions/http-client'
|
import {HttpCodes, HttpClientResponse} from '@actions/http-client'
|
||||||
import {IHttpClientResponse} from '@actions/http-client/interfaces'
|
|
||||||
import {HttpManager} from './http-manager'
|
import {HttpManager} from './http-manager'
|
||||||
import {UploadSpecification} from './upload-specification'
|
import {UploadSpecification} from './upload-specification'
|
||||||
import {UploadOptions} from './upload-options'
|
import {UploadOptions} from './upload-options'
|
||||||
@@ -406,6 +406,9 @@ export class UploadHttpClient {
|
|||||||
isGzip: boolean,
|
isGzip: boolean,
|
||||||
totalFileSize: number
|
totalFileSize: number
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
|
// open a new stream and read it to compute the digest
|
||||||
|
const digest = await digestForStream(openStream())
|
||||||
|
|
||||||
// prepare all the necessary headers before making any http call
|
// prepare all the necessary headers before making any http call
|
||||||
const headers = getUploadHeaders(
|
const headers = getUploadHeaders(
|
||||||
'application/octet-stream',
|
'application/octet-stream',
|
||||||
@@ -413,10 +416,11 @@ export class UploadHttpClient {
|
|||||||
isGzip,
|
isGzip,
|
||||||
totalFileSize,
|
totalFileSize,
|
||||||
end - start + 1,
|
end - start + 1,
|
||||||
getContentRange(start, end, uploadFileSize)
|
getContentRange(start, end, uploadFileSize),
|
||||||
|
digest
|
||||||
)
|
)
|
||||||
|
|
||||||
const uploadChunkRequest = async (): Promise<IHttpClientResponse> => {
|
const uploadChunkRequest = async (): Promise<HttpClientResponse> => {
|
||||||
const client = this.uploadHttpManager.getClient(httpClientIndex)
|
const client = this.uploadHttpManager.getClient(httpClientIndex)
|
||||||
return await client.sendStream('PUT', resourceUrl, openStream(), headers)
|
return await client.sendStream('PUT', resourceUrl, openStream(), headers)
|
||||||
}
|
}
|
||||||
@@ -427,7 +431,7 @@ export class UploadHttpClient {
|
|||||||
// Increments the current retry count and then checks if the retry limit has been reached
|
// Increments the current retry count and then checks if the retry limit has been reached
|
||||||
// If there have been too many retries, fail so the download stops
|
// If there have been too many retries, fail so the download stops
|
||||||
const incrementAndCheckRetryLimit = (
|
const incrementAndCheckRetryLimit = (
|
||||||
response?: IHttpClientResponse
|
response?: HttpClientResponse
|
||||||
): boolean => {
|
): boolean => {
|
||||||
retryCount++
|
retryCount++
|
||||||
if (retryCount > retryLimit) {
|
if (retryCount > retryLimit) {
|
||||||
@@ -464,7 +468,7 @@ export class UploadHttpClient {
|
|||||||
|
|
||||||
// allow for failed chunks to be retried multiple times
|
// allow for failed chunks to be retried multiple times
|
||||||
while (retryCount <= retryLimit) {
|
while (retryCount <= retryLimit) {
|
||||||
let response: IHttpClientResponse
|
let response: HttpClientResponse
|
||||||
|
|
||||||
try {
|
try {
|
||||||
response = await uploadChunkRequest()
|
response = await uploadChunkRequest()
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import {debug, info, warning} from '@actions/core'
|
import crypto from 'crypto'
|
||||||
import {promises as fs} from 'fs'
|
import {promises as fs} from 'fs'
|
||||||
import {HttpCodes, HttpClient} from '@actions/http-client'
|
import {IncomingHttpHeaders, OutgoingHttpHeaders} from 'http'
|
||||||
import {BearerCredentialHandler} from '@actions/http-client/auth'
|
import {debug, info, warning} from '@actions/core'
|
||||||
import {IHeaders, IHttpClientResponse} from '@actions/http-client/interfaces'
|
import {HttpCodes, HttpClient, HttpClientResponse} from '@actions/http-client'
|
||||||
import {IncomingHttpHeaders} from 'http'
|
import {BearerCredentialHandler} from '@actions/http-client/lib/auth'
|
||||||
import {
|
import {
|
||||||
getRuntimeToken,
|
getRuntimeToken,
|
||||||
getRuntimeUrl,
|
getRuntimeUrl,
|
||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
getRetryMultiplier,
|
getRetryMultiplier,
|
||||||
getInitialRetryIntervalInMilliseconds
|
getInitialRetryIntervalInMilliseconds
|
||||||
} from './config-variables'
|
} from './config-variables'
|
||||||
|
import CRC64 from './crc64'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a retry time in milliseconds that exponentially gets larger
|
* Returns a retry time in milliseconds that exponentially gets larger
|
||||||
@@ -139,8 +140,8 @@ export function getDownloadHeaders(
|
|||||||
contentType: string,
|
contentType: string,
|
||||||
isKeepAlive?: boolean,
|
isKeepAlive?: boolean,
|
||||||
acceptGzip?: boolean
|
acceptGzip?: boolean
|
||||||
): IHeaders {
|
): OutgoingHttpHeaders {
|
||||||
const requestOptions: IHeaders = {}
|
const requestOptions: OutgoingHttpHeaders = {}
|
||||||
|
|
||||||
if (contentType) {
|
if (contentType) {
|
||||||
requestOptions['Content-Type'] = contentType
|
requestOptions['Content-Type'] = contentType
|
||||||
@@ -180,9 +181,10 @@ export function getUploadHeaders(
|
|||||||
isGzip?: boolean,
|
isGzip?: boolean,
|
||||||
uncompressedLength?: number,
|
uncompressedLength?: number,
|
||||||
contentLength?: number,
|
contentLength?: number,
|
||||||
contentRange?: string
|
contentRange?: string,
|
||||||
): IHeaders {
|
digest?: StreamDigest
|
||||||
const requestOptions: IHeaders = {}
|
): OutgoingHttpHeaders {
|
||||||
|
const requestOptions: OutgoingHttpHeaders = {}
|
||||||
requestOptions['Accept'] = `application/json;api-version=${getApiVersion()}`
|
requestOptions['Accept'] = `application/json;api-version=${getApiVersion()}`
|
||||||
if (contentType) {
|
if (contentType) {
|
||||||
requestOptions['Content-Type'] = contentType
|
requestOptions['Content-Type'] = contentType
|
||||||
@@ -202,6 +204,10 @@ export function getUploadHeaders(
|
|||||||
if (contentRange) {
|
if (contentRange) {
|
||||||
requestOptions['Content-Range'] = contentRange
|
requestOptions['Content-Range'] = contentRange
|
||||||
}
|
}
|
||||||
|
if (digest) {
|
||||||
|
requestOptions['x-actions-results-crc64'] = digest.crc64
|
||||||
|
requestOptions['x-actions-results-md5'] = digest.md5
|
||||||
|
}
|
||||||
|
|
||||||
return requestOptions
|
return requestOptions
|
||||||
}
|
}
|
||||||
@@ -227,7 +233,7 @@ export function getArtifactUrl(): string {
|
|||||||
* Certain information such as the TLSSocket and the Readable state are not really useful for diagnostic purposes so they can be avoided.
|
* Certain information such as the TLSSocket and the Readable state are not really useful for diagnostic purposes so they can be avoided.
|
||||||
* Other information such as the headers, the response code and message might be useful, so this is displayed.
|
* Other information such as the headers, the response code and message might be useful, so this is displayed.
|
||||||
*/
|
*/
|
||||||
export function displayHttpDiagnostics(response: IHttpClientResponse): void {
|
export function displayHttpDiagnostics(response: HttpClientResponse): void {
|
||||||
info(
|
info(
|
||||||
`##### Begin Diagnostic HTTP information #####
|
`##### Begin Diagnostic HTTP information #####
|
||||||
Status Code: ${response.message.statusCode}
|
Status Code: ${response.message.statusCode}
|
||||||
@@ -291,3 +297,29 @@ export function getProperRetention(
|
|||||||
export async function sleep(milliseconds: number): Promise<void> {
|
export async function sleep(milliseconds: number): Promise<void> {
|
||||||
return new Promise(resolve => setTimeout(resolve, milliseconds))
|
return new Promise(resolve => setTimeout(resolve, milliseconds))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface StreamDigest {
|
||||||
|
crc64: string
|
||||||
|
md5: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function digestForStream(
|
||||||
|
stream: NodeJS.ReadableStream
|
||||||
|
): Promise<StreamDigest> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const crc64 = new CRC64()
|
||||||
|
const md5 = crypto.createHash('md5')
|
||||||
|
stream
|
||||||
|
.on('data', data => {
|
||||||
|
crc64.update(data)
|
||||||
|
md5.update(data)
|
||||||
|
})
|
||||||
|
.on('end', () =>
|
||||||
|
resolve({
|
||||||
|
crc64: crc64.digest('base64') as string,
|
||||||
|
md5: md5.digest('base64')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.on('error', reject)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+6
-1
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> Functions necessary for caching dependencies and build outputs to improve workflow execution time.
|
> Functions necessary for caching dependencies and build outputs to improve workflow execution time.
|
||||||
|
|
||||||
See ["Caching dependencies to speed up workflows"](https://help.github.com/github/automating-your-workflow-with-github-actions/caching-dependencies-to-speed-up-workflows) for how caching works.
|
See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows) for how caching works.
|
||||||
|
|
||||||
Note that GitHub will remove any cache entries that have not been accessed in over 7 days. There is no limit on the number of caches you can store, but the total size of all caches in a repository is limited to 10 GB. If you exceed this limit, GitHub will save your cache but will begin evicting caches until the total size is less than 10 GB.
|
Note that GitHub will remove any cache entries that have not been accessed in over 7 days. There is no limit on the number of caches you can store, but the total size of all caches in a repository is limited to 10 GB. If you exceed this limit, GitHub will save your cache but will begin evicting caches until the total size is less than 10 GB.
|
||||||
|
|
||||||
@@ -42,3 +42,8 @@ const restoreKeys = [
|
|||||||
const cacheKey = await cache.restoreCache(paths, key, restoreKeys)
|
const cacheKey = await cache.restoreCache(paths, key, restoreKeys)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### Cache segment restore timeout
|
||||||
|
|
||||||
|
A cache gets downloaded in multiple segments of fixed sizes (`1GB` for a `32-bit` runner and `2GB` for a `64-bit` runner). Sometimes, a segment download gets stuck which causes the workflow job to be stuck forever and fail. Version `v3.0.4` of cache package introduces a segment download timeout. The segment download timeout will allow the segment download to get aborted and hence allow the job to proceed with a cache miss.
|
||||||
|
|
||||||
|
Default value of this timeout is 60 minutes and can be customized by specifying an [environment variable](https://docs.github.com/en/actions/learn-github-actions/environment-variables) named `SEGMENT_DOWNLOAD_TIMEOUT_MINS` with timeout value in minutes.
|
||||||
|
|||||||
Vendored
+38
@@ -56,3 +56,41 @@
|
|||||||
|
|
||||||
### 2.0.0
|
### 2.0.0
|
||||||
- Added support to check if Actions cache service feature is available or not [#1028](https://github.com/actions/toolkit/pull/1028)
|
- Added support to check if Actions cache service feature is available or not [#1028](https://github.com/actions/toolkit/pull/1028)
|
||||||
|
|
||||||
|
### 2.0.3
|
||||||
|
- Update to v2.0.0 of `@actions/http-client`
|
||||||
|
|
||||||
|
### 2.0.4
|
||||||
|
- Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
|
||||||
|
|
||||||
|
### 2.0.5
|
||||||
|
- Fix to avoid saving empty cache when no files are available for caching. ([issue](https://github.com/actions/cache/issues/624))
|
||||||
|
|
||||||
|
### 2.0.6
|
||||||
|
- Fix `Tar failed with error: The process '/usr/bin/tar' failed with exit code 1` issue when temp directory where tar is getting created is actually the subdirectory of the path mentioned by the user for caching. ([issue](https://github.com/actions/cache/issues/689))
|
||||||
|
|
||||||
|
### 3.0.0
|
||||||
|
- Updated actions/cache to suppress Actions cache server error and log warning for those error [#1122](https://github.com/actions/toolkit/pull/1122)
|
||||||
|
|
||||||
|
### 3.0.1
|
||||||
|
- Fix [#833](https://github.com/actions/cache/issues/833) - cache doesn't work with github workspace directory.
|
||||||
|
- Fix [#809](https://github.com/actions/cache/issues/809) `zstd -d: no such file or directory` error on AWS self-hosted runners.
|
||||||
|
|
||||||
|
### 3.0.2
|
||||||
|
- Added 1 hour timeout for the download stuck issue [#810](https://github.com/actions/cache/issues/810).
|
||||||
|
|
||||||
|
### 3.0.3
|
||||||
|
- Bug fixes for download stuck issue [#810](https://github.com/actions/cache/issues/810).
|
||||||
|
|
||||||
|
### 3.0.4
|
||||||
|
- Fix zstd not working for windows on gnu tar in issues [#888](https://github.com/actions/cache/issues/888) and [#891](https://github.com/actions/cache/issues/891).
|
||||||
|
- Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MINS`. Default is 60 minutes.
|
||||||
|
|
||||||
|
### 3.0.5
|
||||||
|
- Update `@actions/cache` to use `@actions/core@^1.10.0`
|
||||||
|
|
||||||
|
### 3.0.6
|
||||||
|
- 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))
|
||||||
+6
@@ -32,3 +32,9 @@ test('assertDefined throws if undefined', () => {
|
|||||||
test('assertDefined returns value', () => {
|
test('assertDefined returns value', () => {
|
||||||
expect(cacheUtils.assertDefined('test', 5)).toBe(5)
|
expect(cacheUtils.assertDefined('test', 5)).toBe(5)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('resolvePaths works on github workspace directory', async () => {
|
||||||
|
const workspace = process.env['GITHUB_WORKSPACE'] ?? '.'
|
||||||
|
const paths = await cacheUtils.resolvePaths([workspace])
|
||||||
|
expect(paths.length).toBeGreaterThan(0)
|
||||||
|
})
|
||||||
|
|||||||
+23
-2
@@ -8,6 +8,7 @@ import {
|
|||||||
const useAzureSdk = true
|
const useAzureSdk = true
|
||||||
const downloadConcurrency = 8
|
const downloadConcurrency = 8
|
||||||
const timeoutInMs = 30000
|
const timeoutInMs = 30000
|
||||||
|
const segmentTimeoutInMs = 3600000
|
||||||
const uploadConcurrency = 4
|
const uploadConcurrency = 4
|
||||||
const uploadChunkSize = 32 * 1024 * 1024
|
const uploadChunkSize = 32 * 1024 * 1024
|
||||||
|
|
||||||
@@ -17,7 +18,8 @@ test('getDownloadOptions sets defaults', async () => {
|
|||||||
expect(actualOptions).toEqual({
|
expect(actualOptions).toEqual({
|
||||||
useAzureSdk,
|
useAzureSdk,
|
||||||
downloadConcurrency,
|
downloadConcurrency,
|
||||||
timeoutInMs
|
timeoutInMs,
|
||||||
|
segmentTimeoutInMs
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -25,7 +27,8 @@ test('getDownloadOptions overrides all settings', async () => {
|
|||||||
const expectedOptions: DownloadOptions = {
|
const expectedOptions: DownloadOptions = {
|
||||||
useAzureSdk: false,
|
useAzureSdk: false,
|
||||||
downloadConcurrency: 14,
|
downloadConcurrency: 14,
|
||||||
timeoutInMs: 20000
|
timeoutInMs: 20000,
|
||||||
|
segmentTimeoutInMs: 3600000
|
||||||
}
|
}
|
||||||
|
|
||||||
const actualOptions = getDownloadOptions(expectedOptions)
|
const actualOptions = getDownloadOptions(expectedOptions)
|
||||||
@@ -52,3 +55,21 @@ test('getUploadOptions overrides all settings', async () => {
|
|||||||
|
|
||||||
expect(actualOptions).toEqual(expectedOptions)
|
expect(actualOptions).toEqual(expectedOptions)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('getDownloadOptions overrides download timeout minutes', async () => {
|
||||||
|
const expectedOptions: DownloadOptions = {
|
||||||
|
useAzureSdk: false,
|
||||||
|
downloadConcurrency: 14,
|
||||||
|
timeoutInMs: 20000,
|
||||||
|
segmentTimeoutInMs: 3600000
|
||||||
|
}
|
||||||
|
process.env.SEGMENT_DOWNLOAD_TIMEOUT_MINS = '10'
|
||||||
|
const actualOptions = getDownloadOptions(expectedOptions)
|
||||||
|
|
||||||
|
expect(actualOptions.useAzureSdk).toEqual(expectedOptions.useAzureSdk)
|
||||||
|
expect(actualOptions.downloadConcurrency).toEqual(
|
||||||
|
expectedOptions.downloadConcurrency
|
||||||
|
)
|
||||||
|
expect(actualOptions.timeoutInMs).toEqual(expectedOptions.timeoutInMs)
|
||||||
|
expect(actualOptions.segmentTimeoutInMs).toEqual(600000)
|
||||||
|
})
|
||||||
|
|||||||
+81
-2
@@ -73,13 +73,17 @@ test('restore with no cache found', async () => {
|
|||||||
test('restore with server error should fail', async () => {
|
test('restore with server error should fail', async () => {
|
||||||
const paths = ['node_modules']
|
const paths = ['node_modules']
|
||||||
const key = 'node-test'
|
const key = 'node-test'
|
||||||
|
const logWarningMock = jest.spyOn(core, 'warning')
|
||||||
|
|
||||||
jest.spyOn(cacheHttpClient, 'getCacheEntry').mockImplementation(() => {
|
jest.spyOn(cacheHttpClient, 'getCacheEntry').mockImplementation(() => {
|
||||||
throw new Error('HTTP Error Occurred')
|
throw new Error('HTTP Error Occurred')
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(restoreCache(paths, key)).rejects.toThrowError(
|
const cacheKey = await restoreCache(paths, key)
|
||||||
'HTTP Error Occurred'
|
expect(cacheKey).toBe(undefined)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
'Failed to restore: HTTP Error Occurred'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -157,6 +161,81 @@ test('restore with gzip compressed cache found', async () => {
|
|||||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('restore with zstd as default but gzip compressed cache found on windows', async () => {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
const paths = ['node_modules']
|
||||||
|
const key = 'node-test'
|
||||||
|
|
||||||
|
const cacheEntry: ArtifactCacheEntry = {
|
||||||
|
cacheKey: key,
|
||||||
|
scope: 'refs/heads/main',
|
||||||
|
archiveLocation: 'www.actionscache.test/download'
|
||||||
|
}
|
||||||
|
const getCacheMock = jest.spyOn(cacheHttpClient, 'getCacheEntry')
|
||||||
|
getCacheMock
|
||||||
|
.mockImplementationOnce(async () => {
|
||||||
|
return Promise.resolve(null)
|
||||||
|
})
|
||||||
|
.mockImplementationOnce(async () => {
|
||||||
|
return Promise.resolve(cacheEntry)
|
||||||
|
})
|
||||||
|
|
||||||
|
const tempPath = '/foo/bar'
|
||||||
|
|
||||||
|
const createTempDirectoryMock = jest.spyOn(
|
||||||
|
cacheUtils,
|
||||||
|
'createTempDirectory'
|
||||||
|
)
|
||||||
|
createTempDirectoryMock.mockImplementation(async () => {
|
||||||
|
return Promise.resolve(tempPath)
|
||||||
|
})
|
||||||
|
|
||||||
|
const archivePath = path.join(tempPath, CacheFilename.Gzip)
|
||||||
|
const downloadCacheMock = jest.spyOn(cacheHttpClient, 'downloadCache')
|
||||||
|
|
||||||
|
const fileSize = 142
|
||||||
|
const getArchiveFileSizeInBytesMock = jest
|
||||||
|
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
|
||||||
|
.mockReturnValue(fileSize)
|
||||||
|
|
||||||
|
const extractTarMock = jest.spyOn(tar, 'extractTar')
|
||||||
|
const unlinkFileMock = jest.spyOn(cacheUtils, 'unlinkFile')
|
||||||
|
|
||||||
|
const compression = CompressionMethod.Zstd
|
||||||
|
const getCompressionMock = jest
|
||||||
|
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||||
|
.mockReturnValue(Promise.resolve(compression))
|
||||||
|
|
||||||
|
const cacheKey = await restoreCache(paths, key)
|
||||||
|
|
||||||
|
expect(cacheKey).toBe(key)
|
||||||
|
expect(getCacheMock).toHaveBeenNthCalledWith(1, [key], paths, {
|
||||||
|
compressionMethod: compression
|
||||||
|
})
|
||||||
|
expect(getCacheMock).toHaveBeenNthCalledWith(2, [key], paths, {
|
||||||
|
compressionMethod: CompressionMethod.Gzip
|
||||||
|
})
|
||||||
|
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(downloadCacheMock).toHaveBeenCalledWith(
|
||||||
|
cacheEntry.archiveLocation,
|
||||||
|
archivePath,
|
||||||
|
undefined
|
||||||
|
)
|
||||||
|
expect(getArchiveFileSizeInBytesMock).toHaveBeenCalledWith(archivePath)
|
||||||
|
|
||||||
|
expect(extractTarMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(extractTarMock).toHaveBeenCalledWith(
|
||||||
|
archivePath,
|
||||||
|
CompressionMethod.Gzip
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(unlinkFileMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(unlinkFileMock).toHaveBeenCalledWith(archivePath)
|
||||||
|
|
||||||
|
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('restore with zstd compressed cache found', async () => {
|
test('restore with zstd compressed cache found', async () => {
|
||||||
const paths = ['node_modules']
|
const paths = ['node_modules']
|
||||||
const key = 'node-test'
|
const key = 'node-test'
|
||||||
|
|||||||
+46
-15
@@ -5,7 +5,7 @@ import * as cacheHttpClient from '../src/internal/cacheHttpClient'
|
|||||||
import * as cacheUtils from '../src/internal/cacheUtils'
|
import * as cacheUtils from '../src/internal/cacheUtils'
|
||||||
import {CacheFilename, CompressionMethod} from '../src/internal/constants'
|
import {CacheFilename, CompressionMethod} from '../src/internal/constants'
|
||||||
import * as tar from '../src/internal/tar'
|
import * as tar from '../src/internal/tar'
|
||||||
import {ITypedResponse} from '@actions/http-client/interfaces'
|
import {TypedResponse} from '@actions/http-client/lib/interfaces'
|
||||||
import {
|
import {
|
||||||
ReserveCacheResponse,
|
ReserveCacheResponse,
|
||||||
ITypedResponseWithError
|
ITypedResponseWithError
|
||||||
@@ -48,6 +48,7 @@ test('save with large cache outputs should fail', async () => {
|
|||||||
const cachePaths = [path.resolve(filePath)]
|
const cachePaths = [path.resolve(filePath)]
|
||||||
|
|
||||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||||
|
const logWarningMock = jest.spyOn(core, 'warning')
|
||||||
|
|
||||||
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
||||||
jest
|
jest
|
||||||
@@ -58,8 +59,11 @@ test('save with large cache outputs should fail', async () => {
|
|||||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||||
.mockReturnValueOnce(Promise.resolve(compression))
|
.mockReturnValueOnce(Promise.resolve(compression))
|
||||||
|
|
||||||
await expect(saveCache([filePath], primaryKey)).rejects.toThrowError(
|
const cacheId = await saveCache([filePath], primaryKey)
|
||||||
'Cache size of ~11264 MB (11811160064 B) is over the 10GB limit, not saving cache.'
|
expect(cacheId).toBe(-1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
'Failed to save: Cache size of ~11264 MB (11811160064 B) is over the 10GB limit, not saving cache.'
|
||||||
)
|
)
|
||||||
|
|
||||||
const archiveFolder = '/foo/bar'
|
const archiveFolder = '/foo/bar'
|
||||||
@@ -79,6 +83,7 @@ test('save with large cache outputs should fail in GHES with error message', asy
|
|||||||
const cachePaths = [path.resolve(filePath)]
|
const cachePaths = [path.resolve(filePath)]
|
||||||
|
|
||||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||||
|
const logWarningMock = jest.spyOn(core, 'warning')
|
||||||
|
|
||||||
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
||||||
jest
|
jest
|
||||||
@@ -106,8 +111,11 @@ test('save with large cache outputs should fail in GHES with error message', asy
|
|||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(saveCache([filePath], primaryKey)).rejects.toThrowError(
|
const cacheId = await saveCache([filePath], primaryKey)
|
||||||
'The cache filesize must be between 0 and 1073741824 bytes'
|
expect(cacheId).toBe(-1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
'Failed to save: The cache filesize must be between 0 and 1073741824 bytes'
|
||||||
)
|
)
|
||||||
|
|
||||||
const archiveFolder = '/foo/bar'
|
const archiveFolder = '/foo/bar'
|
||||||
@@ -127,6 +135,7 @@ test('save with large cache outputs should fail in GHES without error message',
|
|||||||
const cachePaths = [path.resolve(filePath)]
|
const cachePaths = [path.resolve(filePath)]
|
||||||
|
|
||||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||||
|
const logWarningMock = jest.spyOn(core, 'warning')
|
||||||
|
|
||||||
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
||||||
jest
|
jest
|
||||||
@@ -150,8 +159,11 @@ test('save with large cache outputs should fail in GHES without error message',
|
|||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
|
|
||||||
await expect(saveCache([filePath], primaryKey)).rejects.toThrowError(
|
const cacheId = await saveCache([filePath], primaryKey)
|
||||||
'Cache size of ~11264 MB (11811160064 B) is over the data cap limit, not saving cache.'
|
expect(cacheId).toBe(-1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
'Failed to save: Cache size of ~11264 MB (11811160064 B) is over the data cap limit, not saving cache.'
|
||||||
)
|
)
|
||||||
|
|
||||||
const archiveFolder = '/foo/bar'
|
const archiveFolder = '/foo/bar'
|
||||||
@@ -168,11 +180,12 @@ test('save with large cache outputs should fail in GHES without error message',
|
|||||||
test('save with reserve cache failure should fail', async () => {
|
test('save with reserve cache failure should fail', async () => {
|
||||||
const paths = ['node_modules']
|
const paths = ['node_modules']
|
||||||
const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||||
|
const logInfoMock = jest.spyOn(core, 'info')
|
||||||
|
|
||||||
const reserveCacheMock = jest
|
const reserveCacheMock = jest
|
||||||
.spyOn(cacheHttpClient, 'reserveCache')
|
.spyOn(cacheHttpClient, 'reserveCache')
|
||||||
.mockImplementation(async () => {
|
.mockImplementation(async () => {
|
||||||
const response: ITypedResponse<ReserveCacheResponse> = {
|
const response: TypedResponse<ReserveCacheResponse> = {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
result: null,
|
result: null,
|
||||||
headers: {}
|
headers: {}
|
||||||
@@ -187,9 +200,13 @@ test('save with reserve cache failure should fail', async () => {
|
|||||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||||
.mockReturnValueOnce(Promise.resolve(compression))
|
.mockReturnValueOnce(Promise.resolve(compression))
|
||||||
|
|
||||||
await expect(saveCache(paths, primaryKey)).rejects.toThrowError(
|
const cacheId = await saveCache(paths, primaryKey)
|
||||||
`Unable to reserve cache with key ${primaryKey}, another job may be creating this cache.`
|
expect(cacheId).toBe(-1)
|
||||||
|
expect(logInfoMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(logInfoMock).toHaveBeenCalledWith(
|
||||||
|
`Failed to save: Unable to reserve cache with key ${primaryKey}, another job may be creating this cache. More details: undefined`
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(reserveCacheMock).toHaveBeenCalledTimes(1)
|
expect(reserveCacheMock).toHaveBeenCalledTimes(1)
|
||||||
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, paths, {
|
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, paths, {
|
||||||
compressionMethod: compression
|
compressionMethod: compression
|
||||||
@@ -203,12 +220,12 @@ test('save with server error should fail', async () => {
|
|||||||
const filePath = 'node_modules'
|
const filePath = 'node_modules'
|
||||||
const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||||
const cachePaths = [path.resolve(filePath)]
|
const cachePaths = [path.resolve(filePath)]
|
||||||
|
const logWarningMock = jest.spyOn(core, 'warning')
|
||||||
const cacheId = 4
|
const cacheId = 4
|
||||||
const reserveCacheMock = jest
|
const reserveCacheMock = jest
|
||||||
.spyOn(cacheHttpClient, 'reserveCache')
|
.spyOn(cacheHttpClient, 'reserveCache')
|
||||||
.mockImplementation(async () => {
|
.mockImplementation(async () => {
|
||||||
const response: ITypedResponse<ReserveCacheResponse> = {
|
const response: TypedResponse<ReserveCacheResponse> = {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
result: {cacheId},
|
result: {cacheId},
|
||||||
headers: {}
|
headers: {}
|
||||||
@@ -228,9 +245,12 @@ test('save with server error should fail', async () => {
|
|||||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||||
.mockReturnValueOnce(Promise.resolve(compression))
|
.mockReturnValueOnce(Promise.resolve(compression))
|
||||||
|
|
||||||
await expect(saveCache([filePath], primaryKey)).rejects.toThrowError(
|
await saveCache([filePath], primaryKey)
|
||||||
'HTTP Error Occurred'
|
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||||
|
expect(logWarningMock).toHaveBeenCalledWith(
|
||||||
|
'Failed to save: HTTP Error Occurred'
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(reserveCacheMock).toHaveBeenCalledTimes(1)
|
expect(reserveCacheMock).toHaveBeenCalledTimes(1)
|
||||||
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], {
|
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], {
|
||||||
compressionMethod: compression
|
compressionMethod: compression
|
||||||
@@ -257,7 +277,7 @@ test('save with valid inputs uploads a cache', async () => {
|
|||||||
const reserveCacheMock = jest
|
const reserveCacheMock = jest
|
||||||
.spyOn(cacheHttpClient, 'reserveCache')
|
.spyOn(cacheHttpClient, 'reserveCache')
|
||||||
.mockImplementation(async () => {
|
.mockImplementation(async () => {
|
||||||
const response: ITypedResponse<ReserveCacheResponse> = {
|
const response: TypedResponse<ReserveCacheResponse> = {
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
result: {cacheId},
|
result: {cacheId},
|
||||||
headers: {}
|
headers: {}
|
||||||
@@ -290,3 +310,14 @@ test('save with valid inputs uploads a cache', async () => {
|
|||||||
expect(saveCacheMock).toHaveBeenCalledWith(cacheId, archiveFile, undefined)
|
expect(saveCacheMock).toHaveBeenCalledWith(cacheId, archiveFile, undefined)
|
||||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('save with non existing path should not save cache', async () => {
|
||||||
|
const path = 'node_modules'
|
||||||
|
const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||||
|
jest.spyOn(cacheUtils, 'resolvePaths').mockImplementation(async () => {
|
||||||
|
return []
|
||||||
|
})
|
||||||
|
await expect(saveCache([path], primaryKey)).rejects.toThrowError(
|
||||||
|
`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|||||||
Vendored
+228
-49
@@ -1,7 +1,14 @@
|
|||||||
import * as exec from '@actions/exec'
|
import * as exec from '@actions/exec'
|
||||||
import * as io from '@actions/io'
|
import * as io from '@actions/io'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import {CacheFilename, CompressionMethod} from '../src/internal/constants'
|
import {
|
||||||
|
CacheFilename,
|
||||||
|
CompressionMethod,
|
||||||
|
GnuTarPathOnWindows,
|
||||||
|
ManifestFilename,
|
||||||
|
SystemTarPathOnWindows,
|
||||||
|
TarFilename
|
||||||
|
} from '../src/internal/constants'
|
||||||
import * as tar from '../src/internal/tar'
|
import * as tar from '../src/internal/tar'
|
||||||
import * as utils from '../src/internal/cacheUtils'
|
import * as utils from '../src/internal/cacheUtils'
|
||||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||||
@@ -13,7 +20,7 @@ jest.mock('@actions/io')
|
|||||||
const IS_WINDOWS = process.platform === 'win32'
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
const IS_MAC = process.platform === 'darwin'
|
const IS_MAC = process.platform === 'darwin'
|
||||||
|
|
||||||
const defaultTarPath = process.platform === 'darwin' ? 'gtar' : 'tar'
|
const defaultTarPath = IS_MAC ? 'gtar' : 'tar'
|
||||||
|
|
||||||
function getTempDir(): string {
|
function getTempDir(): string {
|
||||||
return path.join(__dirname, '_temp', 'tar')
|
return path.join(__dirname, '_temp', 'tar')
|
||||||
@@ -28,6 +35,10 @@ beforeAll(async () => {
|
|||||||
await jest.requireActual('@actions/io').rmRF(getTempDir())
|
await jest.requireActual('@actions/io').rmRF(getTempDir())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
delete process.env['GITHUB_WORKSPACE']
|
delete process.env['GITHUB_WORKSPACE']
|
||||||
await jest.requireActual('@actions/io').rmRF(getTempDir())
|
await jest.requireActual('@actions/io').rmRF(getTempDir())
|
||||||
@@ -41,16 +52,15 @@ test('zstd extract tar', async () => {
|
|||||||
? `${process.env['windir']}\\fakepath\\cache.tar`
|
? `${process.env['windir']}\\fakepath\\cache.tar`
|
||||||
: 'cache.tar'
|
: 'cache.tar'
|
||||||
const workspace = process.env['GITHUB_WORKSPACE']
|
const workspace = process.env['GITHUB_WORKSPACE']
|
||||||
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
|
|
||||||
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(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${defaultTarPath}"`,
|
|
||||||
[
|
[
|
||||||
'--use-compress-program',
|
`"${tarPath}"`,
|
||||||
'zstd -d --long=30',
|
|
||||||
'-xf',
|
'-xf',
|
||||||
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
||||||
'-P',
|
'-P',
|
||||||
@@ -58,11 +68,61 @@ test('zstd extract tar', async () => {
|
|||||||
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace
|
||||||
]
|
]
|
||||||
.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 --long=30"' : 'unzstd --long=30'
|
||||||
|
])
|
||||||
|
.join(' '),
|
||||||
|
undefined,
|
||||||
{cwd: undefined}
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('zstd extract tar with windows BSDtar', async () => {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
||||||
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
jest
|
||||||
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
||||||
|
.mockReturnValue(Promise.resolve(''))
|
||||||
|
|
||||||
|
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
||||||
|
const workspace = process.env['GITHUB_WORKSPACE']
|
||||||
|
const tarPath = SystemTarPathOnWindows
|
||||||
|
|
||||||
|
await tar.extractTar(archivePath, CompressionMethod.Zstd)
|
||||||
|
|
||||||
|
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
||||||
|
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'), '/')
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{cwd: undefined}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
|
'-xf',
|
||||||
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P',
|
||||||
|
'-C',
|
||||||
|
workspace?.replace(/\\/g, '/')
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{cwd: undefined}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('gzip extract tar', async () => {
|
test('gzip extract tar', async () => {
|
||||||
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
const mkdirMock = jest.spyOn(io, 'mkdirP')
|
||||||
const execMock = jest.spyOn(exec, 'exec')
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
@@ -74,50 +134,51 @@ test('gzip extract tar', async () => {
|
|||||||
await tar.extractTar(archivePath, CompressionMethod.Gzip)
|
await tar.extractTar(archivePath, CompressionMethod.Gzip)
|
||||||
|
|
||||||
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
expect(mkdirMock).toHaveBeenCalledWith(workspace)
|
||||||
const tarPath = IS_WINDOWS
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
? `${process.env['windir']}\\System32\\tar.exe`
|
|
||||||
: defaultTarPath
|
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${tarPath}"`,
|
|
||||||
[
|
[
|
||||||
'-z',
|
`"${tarPath}"`,
|
||||||
'-xf',
|
'-xf',
|
||||||
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
||||||
'-P',
|
'-P',
|
||||||
'-C',
|
'-C',
|
||||||
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace
|
||||||
].concat(IS_MAC ? ['--delay-directory-restore'] : []),
|
]
|
||||||
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
||||||
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
||||||
|
.concat(['-z'])
|
||||||
|
.join(' '),
|
||||||
|
undefined,
|
||||||
{cwd: undefined}
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('gzip extract GNU tar on windows', async () => {
|
test('gzip extract GNU tar on windows with GNUtar in path', async () => {
|
||||||
if (IS_WINDOWS) {
|
if (IS_WINDOWS) {
|
||||||
jest.spyOn(fs, 'existsSync').mockReturnValueOnce(false)
|
// GNU tar present in path but not at default location
|
||||||
|
jest
|
||||||
const isGnuMock = jest
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
||||||
.spyOn(utils, 'isGnuTarInstalled')
|
.mockReturnValue(Promise.resolve('tar'))
|
||||||
.mockReturnValue(Promise.resolve(true))
|
|
||||||
const execMock = jest.spyOn(exec, 'exec')
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
||||||
const workspace = process.env['GITHUB_WORKSPACE']
|
const workspace = process.env['GITHUB_WORKSPACE']
|
||||||
|
|
||||||
await tar.extractTar(archivePath, CompressionMethod.Gzip)
|
await tar.extractTar(archivePath, CompressionMethod.Gzip)
|
||||||
|
|
||||||
expect(isGnuMock).toHaveBeenCalledTimes(1)
|
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"tar"`,
|
|
||||||
[
|
[
|
||||||
'-z',
|
`"tar"`,
|
||||||
'-xf',
|
'-xf',
|
||||||
archivePath.replace(/\\/g, '/'),
|
archivePath.replace(/\\/g, '/'),
|
||||||
'-P',
|
'-P',
|
||||||
'-C',
|
'-C',
|
||||||
workspace?.replace(/\\/g, '/'),
|
workspace?.replace(/\\/g, '/'),
|
||||||
'--force-local'
|
'--force-local',
|
||||||
],
|
'-z'
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
{cwd: undefined}
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -134,29 +195,96 @@ test('zstd create tar', async () => {
|
|||||||
|
|
||||||
await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.Zstd)
|
await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.Zstd)
|
||||||
|
|
||||||
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
|
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${defaultTarPath}"`,
|
|
||||||
[
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
'--posix',
|
'--posix',
|
||||||
'--use-compress-program',
|
|
||||||
'zstd -T0 --long=30',
|
|
||||||
'-cf',
|
'-cf',
|
||||||
IS_WINDOWS ? CacheFilename.Zstd.replace(/\\/g, '/') : CacheFilename.Zstd,
|
IS_WINDOWS ? CacheFilename.Zstd.replace(/\\/g, '/') : CacheFilename.Zstd,
|
||||||
|
'--exclude',
|
||||||
|
IS_WINDOWS ? CacheFilename.Zstd.replace(/\\/g, '/') : CacheFilename.Zstd,
|
||||||
'-P',
|
'-P',
|
||||||
'-C',
|
'-C',
|
||||||
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace,
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace,
|
||||||
'--files-from',
|
'--files-from',
|
||||||
'manifest.txt'
|
ManifestFilename
|
||||||
]
|
]
|
||||||
.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 -T0 --long=30"' : 'zstdmt --long=30'
|
||||||
|
])
|
||||||
|
.join(' '),
|
||||||
|
undefined, // args
|
||||||
{
|
{
|
||||||
cwd: archiveFolder
|
cwd: archiveFolder
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('zstd create tar with windows BSDtar', async () => {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
jest
|
||||||
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
||||||
|
.mockReturnValue(Promise.resolve(''))
|
||||||
|
|
||||||
|
const archiveFolder = getTempDir()
|
||||||
|
const workspace = process.env['GITHUB_WORKSPACE']
|
||||||
|
const sourceDirectories = ['~/.npm/cache', `${workspace}/dist`]
|
||||||
|
|
||||||
|
await fs.promises.mkdir(archiveFolder, {recursive: true})
|
||||||
|
|
||||||
|
await tar.createTar(
|
||||||
|
archiveFolder,
|
||||||
|
sourceDirectories,
|
||||||
|
CompressionMethod.Zstd
|
||||||
|
)
|
||||||
|
|
||||||
|
const tarPath = SystemTarPathOnWindows
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenCalledTimes(2)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
1,
|
||||||
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
|
'--posix',
|
||||||
|
'-cf',
|
||||||
|
TarFilename.replace(/\\/g, '/'),
|
||||||
|
'--exclude',
|
||||||
|
TarFilename.replace(/\\/g, '/'),
|
||||||
|
'-P',
|
||||||
|
'-C',
|
||||||
|
workspace?.replace(/\\/g, '/'),
|
||||||
|
'--files-from',
|
||||||
|
ManifestFilename
|
||||||
|
].join(' '),
|
||||||
|
undefined, // args
|
||||||
|
{
|
||||||
|
cwd: archiveFolder
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
[
|
||||||
|
'zstd -T0 --long=30 -o',
|
||||||
|
CacheFilename.Zstd.replace(/\\/g, '/'),
|
||||||
|
TarFilename.replace(/\\/g, '/')
|
||||||
|
].join(' '),
|
||||||
|
undefined, // args
|
||||||
|
{
|
||||||
|
cwd: archiveFolder
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('gzip create tar', async () => {
|
test('gzip create tar', async () => {
|
||||||
const execMock = jest.spyOn(exec, 'exec')
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
|
||||||
@@ -168,24 +296,28 @@ test('gzip create tar', async () => {
|
|||||||
|
|
||||||
await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.Gzip)
|
await tar.createTar(archiveFolder, sourceDirectories, CompressionMethod.Gzip)
|
||||||
|
|
||||||
const tarPath = IS_WINDOWS
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
? `${process.env['windir']}\\System32\\tar.exe`
|
|
||||||
: defaultTarPath
|
|
||||||
|
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${tarPath}"`,
|
|
||||||
[
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
'--posix',
|
'--posix',
|
||||||
'-z',
|
|
||||||
'-cf',
|
'-cf',
|
||||||
IS_WINDOWS ? CacheFilename.Gzip.replace(/\\/g, '/') : CacheFilename.Gzip,
|
IS_WINDOWS ? CacheFilename.Gzip.replace(/\\/g, '/') : CacheFilename.Gzip,
|
||||||
|
'--exclude',
|
||||||
|
IS_WINDOWS ? CacheFilename.Gzip.replace(/\\/g, '/') : CacheFilename.Gzip,
|
||||||
'-P',
|
'-P',
|
||||||
'-C',
|
'-C',
|
||||||
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace,
|
IS_WINDOWS ? workspace?.replace(/\\/g, '/') : workspace,
|
||||||
'--files-from',
|
'--files-from',
|
||||||
'manifest.txt'
|
ManifestFilename
|
||||||
].concat(IS_MAC ? ['--delay-directory-restore'] : []),
|
]
|
||||||
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
||||||
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
||||||
|
.concat(['-z'])
|
||||||
|
.join(' '),
|
||||||
|
undefined, // args
|
||||||
{
|
{
|
||||||
cwd: archiveFolder
|
cwd: archiveFolder
|
||||||
}
|
}
|
||||||
@@ -201,22 +333,65 @@ test('zstd list tar', async () => {
|
|||||||
|
|
||||||
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
||||||
|
|
||||||
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${defaultTarPath}"`,
|
|
||||||
[
|
[
|
||||||
'--use-compress-program',
|
`"${tarPath}"`,
|
||||||
'zstd -d --long=30',
|
|
||||||
'-tf',
|
'-tf',
|
||||||
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
||||||
'-P'
|
'-P'
|
||||||
]
|
]
|
||||||
.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 --long=30"' : 'unzstd --long=30'
|
||||||
|
])
|
||||||
|
.join(' '),
|
||||||
|
undefined,
|
||||||
{cwd: undefined}
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('zstd list tar with windows BSDtar', async () => {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
jest
|
||||||
|
.spyOn(utils, 'getGnuTarPathOnWindows')
|
||||||
|
.mockReturnValue(Promise.resolve(''))
|
||||||
|
const archivePath = `${process.env['windir']}\\fakepath\\cache.tar`
|
||||||
|
|
||||||
|
await tar.listTar(archivePath, CompressionMethod.Zstd)
|
||||||
|
|
||||||
|
const tarPath = SystemTarPathOnWindows
|
||||||
|
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'), '/')
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{cwd: undefined}
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(execMock).toHaveBeenNthCalledWith(
|
||||||
|
2,
|
||||||
|
[
|
||||||
|
`"${tarPath}"`,
|
||||||
|
'-tf',
|
||||||
|
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P'
|
||||||
|
].join(' '),
|
||||||
|
undefined,
|
||||||
|
{cwd: undefined}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('zstdWithoutLong list tar', async () => {
|
test('zstdWithoutLong list tar', async () => {
|
||||||
const execMock = jest.spyOn(exec, 'exec')
|
const execMock = jest.spyOn(exec, 'exec')
|
||||||
|
|
||||||
@@ -226,18 +401,20 @@ test('zstdWithoutLong list tar', async () => {
|
|||||||
|
|
||||||
await tar.listTar(archivePath, CompressionMethod.ZstdWithoutLong)
|
await tar.listTar(archivePath, CompressionMethod.ZstdWithoutLong)
|
||||||
|
|
||||||
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${defaultTarPath}"`,
|
|
||||||
[
|
[
|
||||||
'--use-compress-program',
|
`"${tarPath}"`,
|
||||||
'zstd -d',
|
|
||||||
'-tf',
|
'-tf',
|
||||||
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
||||||
'-P'
|
'-P'
|
||||||
]
|
]
|
||||||
.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'])
|
||||||
|
.join(' '),
|
||||||
|
undefined,
|
||||||
{cwd: undefined}
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -250,18 +427,20 @@ test('gzip list tar', async () => {
|
|||||||
|
|
||||||
await tar.listTar(archivePath, CompressionMethod.Gzip)
|
await tar.listTar(archivePath, CompressionMethod.Gzip)
|
||||||
|
|
||||||
const tarPath = IS_WINDOWS
|
const tarPath = IS_WINDOWS ? GnuTarPathOnWindows : defaultTarPath
|
||||||
? `${process.env['windir']}\\System32\\tar.exe`
|
|
||||||
: defaultTarPath
|
|
||||||
expect(execMock).toHaveBeenCalledTimes(1)
|
expect(execMock).toHaveBeenCalledTimes(1)
|
||||||
expect(execMock).toHaveBeenCalledWith(
|
expect(execMock).toHaveBeenCalledWith(
|
||||||
`"${tarPath}"`,
|
|
||||||
[
|
[
|
||||||
'-z',
|
`"${tarPath}"`,
|
||||||
'-tf',
|
'-tf',
|
||||||
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
IS_WINDOWS ? archivePath.replace(/\\/g, '/') : archivePath,
|
||||||
'-P'
|
'-P'
|
||||||
].concat(IS_MAC ? ['--delay-directory-restore'] : []),
|
]
|
||||||
|
.concat(IS_WINDOWS ? ['--force-local'] : [])
|
||||||
|
.concat(IS_MAC ? ['--delay-directory-restore'] : [])
|
||||||
|
.concat(['-z'])
|
||||||
|
.join(' '),
|
||||||
|
undefined,
|
||||||
{cwd: undefined}
|
{cwd: undefined}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
+69
-60
@@ -1,19 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/cache",
|
"name": "@actions/cache",
|
||||||
"version": "2.0.2",
|
"version": "3.1.0-beta.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/cache",
|
"name": "@actions/cache",
|
||||||
"version": "2.0.0",
|
"version": "3.1.0-beta.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
"@actions/glob": "^0.1.0",
|
"@actions/glob": "^0.1.0",
|
||||||
"@actions/http-client": "^1.0.9",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@actions/io": "^1.0.1",
|
"@actions/io": "^1.0.1",
|
||||||
|
"@azure/abort-controller": "^1.1.0",
|
||||||
"@azure/ms-rest-js": "^2.6.0",
|
"@azure/ms-rest-js": "^2.6.0",
|
||||||
"@azure/storage-blob": "^12.8.0",
|
"@azure/storage-blob": "^12.8.0",
|
||||||
"semver": "^6.1.0",
|
"semver": "^6.1.0",
|
||||||
@@ -26,14 +27,26 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/core": {
|
"node_modules/@actions/core": {
|
||||||
"version": "1.2.6",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
|
||||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/core/node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/exec": {
|
"node_modules/@actions/exec": {
|
||||||
"version": "1.0.4",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
"integrity": "sha512-4DPChWow9yc9W3WqEbUj8Nr86xkpyE29ZzWjXucHItclLbEW6jr80Zx4nqv18QL6KK65+cifiQZXvnqgTV6oHw==",
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/io": "^1.0.1"
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
@@ -48,35 +61,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/http-client": {
|
"node_modules/@actions/http-client": {
|
||||||
"version": "1.0.9",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-0O4SsJ7q+MK0ycvXPl2e6bMXV7dxAXOGjrXS1eTF9s2S401Tp6c/P3c3Joz04QefC1J6Gt942Wl2jbm3f4mLcg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@actions/http-client/node_modules/tunnel": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
|
||||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/io": {
|
"node_modules/@actions/io": {
|
||||||
"version": "1.0.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.2.tgz",
|
||||||
"integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg=="
|
"integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw=="
|
||||||
},
|
},
|
||||||
"node_modules/@azure/abort-controller": {
|
"node_modules/@azure/abort-controller": {
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
|
||||||
"integrity": "sha512-lNUmDRVGpanCsiUN3NWxFTdwmdFI53xwhkTFfHDGTYk46ca7Ind3nanJc+U6Zj9Tv+9nTCWRBscWEW1DyKOpTw==",
|
"integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/abort-controller/node_modules/tslib": {
|
"node_modules/@azure/abort-controller/node_modules/tslib": {
|
||||||
@@ -452,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"
|
||||||
},
|
},
|
||||||
@@ -613,14 +618,25 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": {
|
"@actions/core": {
|
||||||
"version": "1.2.6",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
|
||||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
|
||||||
|
"requires": {
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"@actions/exec": {
|
"@actions/exec": {
|
||||||
"version": "1.0.4",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
"integrity": "sha512-4DPChWow9yc9W3WqEbUj8Nr86xkpyE29ZzWjXucHItclLbEW6jr80Zx4nqv18QL6KK65+cifiQZXvnqgTV6oHw==",
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/io": "^1.0.1"
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
@@ -635,31 +651,24 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.9",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-0O4SsJ7q+MK0ycvXPl2e6bMXV7dxAXOGjrXS1eTF9s2S401Tp6c/P3c3Joz04QefC1J6Gt942Wl2jbm3f4mLcg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"tunnel": {
|
|
||||||
"version": "0.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
|
||||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/io": {
|
"@actions/io": {
|
||||||
"version": "1.0.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.2.tgz",
|
||||||
"integrity": "sha512-J8KuFqVPr3p6U8W93DOXlXW6zFvrQAJANdS+vw0YhusLIq+bszW8zmK2Fh1C2kDPX8FMvwIl1OUcFgvJoXLbAg=="
|
"integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw=="
|
||||||
},
|
},
|
||||||
"@azure/abort-controller": {
|
"@azure/abort-controller": {
|
||||||
"version": "1.0.4",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz",
|
||||||
"integrity": "sha512-lNUmDRVGpanCsiUN3NWxFTdwmdFI53xwhkTFfHDGTYk46ca7Ind3nanJc+U6Zj9Tv+9nTCWRBscWEW1DyKOpTw==",
|
"integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^2.0.0"
|
"tslib": "^2.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": {
|
"tslib": {
|
||||||
@@ -989,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
+6
-5
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/cache",
|
"name": "@actions/cache",
|
||||||
"version": "2.0.2",
|
"version": "3.1.0-beta.1",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"description": "Actions cache lib",
|
"description": "Actions cache lib",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
@@ -37,19 +37,20 @@
|
|||||||
"url": "https://github.com/actions/toolkit/issues"
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
"@actions/glob": "^0.1.0",
|
"@actions/glob": "^0.1.0",
|
||||||
"@actions/http-client": "^1.0.9",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@actions/io": "^1.0.1",
|
"@actions/io": "^1.0.1",
|
||||||
|
"@azure/abort-controller": "^1.1.0",
|
||||||
"@azure/ms-rest-js": "^2.6.0",
|
"@azure/ms-rest-js": "^2.6.0",
|
||||||
"@azure/storage-blob": "^12.8.0",
|
"@azure/storage-blob": "^12.8.0",
|
||||||
"semver": "^6.1.0",
|
"semver": "^6.1.0",
|
||||||
"uuid": "^3.3.3"
|
"uuid": "^3.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^3.8.3",
|
|
||||||
"@types/semver": "^6.0.0",
|
"@types/semver": "^6.0.0",
|
||||||
"@types/uuid": "^3.4.5"
|
"@types/uuid": "^3.4.5",
|
||||||
|
"typescript": "^3.8.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+65
-19
@@ -4,6 +4,8 @@ import * as utils from './internal/cacheUtils'
|
|||||||
import * as cacheHttpClient from './internal/cacheHttpClient'
|
import * as cacheHttpClient from './internal/cacheHttpClient'
|
||||||
import {createTar, extractTar, listTar} from './internal/tar'
|
import {createTar, extractTar, listTar} from './internal/tar'
|
||||||
import {DownloadOptions, UploadOptions} from './options'
|
import {DownloadOptions, UploadOptions} from './options'
|
||||||
|
import {CompressionMethod} from './internal/constants'
|
||||||
|
import {ArtifactCacheEntry} from './internal/contracts'
|
||||||
|
|
||||||
export class ValidationError extends Error {
|
export class ValidationError extends Error {
|
||||||
constructor(message: string) {
|
constructor(message: string) {
|
||||||
@@ -85,24 +87,43 @@ export async function restoreCache(
|
|||||||
checkKey(key)
|
checkKey(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
const compressionMethod = await utils.getCompressionMethod()
|
let cacheEntry: ArtifactCacheEntry | null
|
||||||
|
let compressionMethod = await utils.getCompressionMethod()
|
||||||
// path are needed to compute version
|
let archivePath = ''
|
||||||
const cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
|
|
||||||
compressionMethod
|
|
||||||
})
|
|
||||||
if (!cacheEntry?.archiveLocation) {
|
|
||||||
// Cache not found
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
const archivePath = path.join(
|
|
||||||
await utils.createTempDirectory(),
|
|
||||||
utils.getCacheFileName(compressionMethod)
|
|
||||||
)
|
|
||||||
core.debug(`Archive Path: ${archivePath}`)
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// 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
|
||||||
|
) {
|
||||||
|
compressionMethod = CompressionMethod.Gzip
|
||||||
|
cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
|
||||||
|
compressionMethod
|
||||||
|
})
|
||||||
|
if (!cacheEntry?.archiveLocation) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
core.debug(
|
||||||
|
"Couldn't find cache entry with zstd compression, falling back to gzip compression."
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Cache not found
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
archivePath = path.join(
|
||||||
|
await utils.createTempDirectory(),
|
||||||
|
utils.getCacheFileName(compressionMethod)
|
||||||
|
)
|
||||||
|
core.debug(`Archive Path: ${archivePath}`)
|
||||||
|
|
||||||
// Download the cache from the cache entry
|
// Download the cache from the cache entry
|
||||||
await cacheHttpClient.downloadCache(
|
await cacheHttpClient.downloadCache(
|
||||||
cacheEntry.archiveLocation,
|
cacheEntry.archiveLocation,
|
||||||
@@ -123,6 +144,16 @@ export async function restoreCache(
|
|||||||
|
|
||||||
await extractTar(archivePath, compressionMethod)
|
await extractTar(archivePath, compressionMethod)
|
||||||
core.info('Cache restored successfully')
|
core.info('Cache restored successfully')
|
||||||
|
|
||||||
|
return cacheEntry.cacheKey
|
||||||
|
} catch (error) {
|
||||||
|
const typedError = error as Error
|
||||||
|
if (typedError.name === ValidationError.name) {
|
||||||
|
throw error
|
||||||
|
} else {
|
||||||
|
// Supress all non-validation cache related errors because caching should be optional
|
||||||
|
core.warning(`Failed to restore: ${(error as Error).message}`)
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// Try to delete the archive to save space
|
// Try to delete the archive to save space
|
||||||
try {
|
try {
|
||||||
@@ -132,7 +163,7 @@ export async function restoreCache(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return cacheEntry.cacheKey
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,12 +183,18 @@ export async function saveCache(
|
|||||||
checkKey(key)
|
checkKey(key)
|
||||||
|
|
||||||
const compressionMethod = await utils.getCompressionMethod()
|
const compressionMethod = await utils.getCompressionMethod()
|
||||||
let cacheId = null
|
let cacheId = -1
|
||||||
|
|
||||||
const cachePaths = await utils.resolvePaths(paths)
|
const cachePaths = await utils.resolvePaths(paths)
|
||||||
core.debug('Cache Paths:')
|
core.debug('Cache Paths:')
|
||||||
core.debug(`${JSON.stringify(cachePaths)}`)
|
core.debug(`${JSON.stringify(cachePaths)}`)
|
||||||
|
|
||||||
|
if (cachePaths.length === 0) {
|
||||||
|
throw new Error(
|
||||||
|
`Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const archiveFolder = await utils.createTempDirectory()
|
const archiveFolder = await utils.createTempDirectory()
|
||||||
const archivePath = path.join(
|
const archivePath = path.join(
|
||||||
archiveFolder,
|
archiveFolder,
|
||||||
@@ -211,6 +248,15 @@ export async function saveCache(
|
|||||||
|
|
||||||
core.debug(`Saving Cache (ID: ${cacheId})`)
|
core.debug(`Saving Cache (ID: ${cacheId})`)
|
||||||
await cacheHttpClient.saveCache(cacheId, archivePath, options)
|
await cacheHttpClient.saveCache(cacheId, archivePath, options)
|
||||||
|
} catch (error) {
|
||||||
|
const typedError = error as Error
|
||||||
|
if (typedError.name === ValidationError.name) {
|
||||||
|
throw error
|
||||||
|
} else if (typedError.name === ReserveCacheError.name) {
|
||||||
|
core.info(`Failed to save: ${typedError.message}`)
|
||||||
|
} else {
|
||||||
|
core.warning(`Failed to save: ${typedError.message}`)
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// Try to delete the archive to save space
|
// Try to delete the archive to save space
|
||||||
try {
|
try {
|
||||||
|
|||||||
+10
-5
@@ -1,7 +1,10 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {HttpClient} from '@actions/http-client'
|
import {HttpClient} from '@actions/http-client'
|
||||||
import {BearerCredentialHandler} from '@actions/http-client/auth'
|
import {BearerCredentialHandler} from '@actions/http-client/lib/auth'
|
||||||
import {IRequestOptions, ITypedResponse} from '@actions/http-client/interfaces'
|
import {
|
||||||
|
RequestOptions,
|
||||||
|
TypedResponse
|
||||||
|
} from '@actions/http-client/lib/interfaces'
|
||||||
import * as crypto from 'crypto'
|
import * as crypto from 'crypto'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import {URL} from 'url'
|
import {URL} from 'url'
|
||||||
@@ -46,8 +49,8 @@ function createAcceptHeader(type: string, apiVersion: string): string {
|
|||||||
return `${type};api-version=${apiVersion}`
|
return `${type};api-version=${apiVersion}`
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRequestOptions(): IRequestOptions {
|
function getRequestOptions(): RequestOptions {
|
||||||
const requestOptions: IRequestOptions = {
|
const requestOptions: RequestOptions = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: createAcceptHeader('application/json', '6.0-preview.1')
|
Accept: createAcceptHeader('application/json', '6.0-preview.1')
|
||||||
}
|
}
|
||||||
@@ -101,6 +104,7 @@ export async function getCacheEntry(
|
|||||||
httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource))
|
httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource))
|
||||||
)
|
)
|
||||||
if (response.statusCode === 204) {
|
if (response.statusCode === 204) {
|
||||||
|
// Cache not found
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
if (!isSuccessStatusCode(response.statusCode)) {
|
if (!isSuccessStatusCode(response.statusCode)) {
|
||||||
@@ -110,6 +114,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)
|
||||||
@@ -275,7 +280,7 @@ async function commitCache(
|
|||||||
httpClient: HttpClient,
|
httpClient: HttpClient,
|
||||||
cacheId: number,
|
cacheId: number,
|
||||||
filesize: number
|
filesize: number
|
||||||
): Promise<ITypedResponse<null>> {
|
): Promise<TypedResponse<null>> {
|
||||||
const commitCacheRequest: CommitCacheRequest = {size: filesize}
|
const commitCacheRequest: CommitCacheRequest = {size: filesize}
|
||||||
return await retryTypedResponse('commitCache', async () =>
|
return await retryTypedResponse('commitCache', async () =>
|
||||||
httpClient.postJson<null>(
|
httpClient.postJson<null>(
|
||||||
|
|||||||
+16
-9
@@ -7,7 +7,11 @@ import * as path from 'path'
|
|||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
import * as util from 'util'
|
import * as util from 'util'
|
||||||
import {v4 as uuidV4} from 'uuid'
|
import {v4 as uuidV4} from 'uuid'
|
||||||
import {CacheFilename, CompressionMethod} from './constants'
|
import {
|
||||||
|
CacheFilename,
|
||||||
|
CompressionMethod,
|
||||||
|
GnuTarPathOnWindows
|
||||||
|
} from './constants'
|
||||||
|
|
||||||
// From https://github.com/actions/toolkit/blob/main/packages/tool-cache/src/tool-cache.ts#L23
|
// From https://github.com/actions/toolkit/blob/main/packages/tool-cache/src/tool-cache.ts#L23
|
||||||
export async function createTempDirectory(): Promise<string> {
|
export async function createTempDirectory(): Promise<string> {
|
||||||
@@ -52,7 +56,12 @@ export async function resolvePaths(patterns: string[]): Promise<string[]> {
|
|||||||
.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||||
core.debug(`Matched: ${relativeFile}`)
|
core.debug(`Matched: ${relativeFile}`)
|
||||||
// Paths are made relative so the tar entries are all relative to the root of the workspace.
|
// Paths are made relative so the tar entries are all relative to the root of the workspace.
|
||||||
paths.push(`${relativeFile}`)
|
if (relativeFile === '') {
|
||||||
|
// path.relative returns empty string if workspace and file are equal
|
||||||
|
paths.push('.')
|
||||||
|
} else {
|
||||||
|
paths.push(`${relativeFile}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
@@ -85,11 +94,6 @@ async function getVersion(app: string): Promise<string> {
|
|||||||
|
|
||||||
// Use zstandard if possible to maximize cache performance
|
// Use zstandard if possible to maximize cache performance
|
||||||
export async function getCompressionMethod(): Promise<CompressionMethod> {
|
export async function getCompressionMethod(): Promise<CompressionMethod> {
|
||||||
if (process.platform === 'win32' && !(await isGnuTarInstalled())) {
|
|
||||||
// Disable zstd due to bug https://github.com/actions/cache/issues/301
|
|
||||||
return CompressionMethod.Gzip
|
|
||||||
}
|
|
||||||
|
|
||||||
const versionOutput = await getVersion('zstd')
|
const versionOutput = await getVersion('zstd')
|
||||||
const version = semver.clean(versionOutput)
|
const version = semver.clean(versionOutput)
|
||||||
|
|
||||||
@@ -111,9 +115,12 @@ export function getCacheFileName(compressionMethod: CompressionMethod): string {
|
|||||||
: CacheFilename.Zstd
|
: CacheFilename.Zstd
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function isGnuTarInstalled(): Promise<boolean> {
|
export async function getGnuTarPathOnWindows(): Promise<string> {
|
||||||
|
if (fs.existsSync(GnuTarPathOnWindows)) {
|
||||||
|
return GnuTarPathOnWindows
|
||||||
|
}
|
||||||
const versionOutput = await getVersion('tar')
|
const versionOutput = await getVersion('tar')
|
||||||
return versionOutput.toLowerCase().includes('gnu tar')
|
return versionOutput.toLowerCase().includes('gnu tar') ? io.which('tar') : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
export function assertDefined<T>(name: string, value?: T): T {
|
export function assertDefined<T>(name: string, value?: T): T {
|
||||||
|
|||||||
+15
@@ -11,6 +11,11 @@ export enum CompressionMethod {
|
|||||||
Zstd = 'zstd'
|
Zstd = 'zstd'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ArchiveToolType {
|
||||||
|
GNU = 'gnu',
|
||||||
|
BSD = 'bsd'
|
||||||
|
}
|
||||||
|
|
||||||
// The default number of retry attempts.
|
// The default number of retry attempts.
|
||||||
export const DefaultRetryAttempts = 2
|
export const DefaultRetryAttempts = 2
|
||||||
|
|
||||||
@@ -21,3 +26,13 @@ export const DefaultRetryDelay = 5000
|
|||||||
// over the socket during this period, the socket is destroyed and the download
|
// over the socket during this period, the socket is destroyed and the download
|
||||||
// is aborted.
|
// is aborted.
|
||||||
export const SocketTimeout = 5000
|
export const SocketTimeout = 5000
|
||||||
|
|
||||||
|
// The default path of GNUtar on hosted Windows runners
|
||||||
|
export const GnuTarPathOnWindows = `${process.env['PROGRAMFILES']}\\Git\\usr\\bin\\tar.exe`
|
||||||
|
|
||||||
|
// The default path of BSDtar on hosted Windows runners
|
||||||
|
export const SystemTarPathOnWindows = `${process.env['SYSTEMDRIVE']}\\Windows\\System32\\tar.exe`
|
||||||
|
|
||||||
|
export const TarFilename = 'cache.tar'
|
||||||
|
|
||||||
|
export const ManifestFilename = 'manifest.txt'
|
||||||
|
|||||||
+7
-2
@@ -1,8 +1,8 @@
|
|||||||
import {CompressionMethod} from './constants'
|
import {CompressionMethod} from './constants'
|
||||||
import {ITypedResponse} from '@actions/http-client/interfaces'
|
import {TypedResponse} from '@actions/http-client/lib/interfaces'
|
||||||
import {HttpClientError} from '@actions/http-client'
|
import {HttpClientError} from '@actions/http-client'
|
||||||
|
|
||||||
export interface ITypedResponseWithError<T> extends ITypedResponse<T> {
|
export interface ITypedResponseWithError<T> extends TypedResponse<T> {
|
||||||
error?: HttpClientError
|
error?: HttpClientError
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,3 +31,8 @@ export interface InternalCacheOptions {
|
|||||||
compressionMethod?: CompressionMethod
|
compressionMethod?: CompressionMethod
|
||||||
cacheSize?: number
|
cacheSize?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ArchiveTool {
|
||||||
|
path: string
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
|||||||
+34
-12
@@ -1,6 +1,5 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {HttpClient} from '@actions/http-client'
|
import {HttpClient, HttpClientResponse} from '@actions/http-client'
|
||||||
import {IHttpClientResponse} from '@actions/http-client/interfaces'
|
|
||||||
import {BlockBlobClient} from '@azure/storage-blob'
|
import {BlockBlobClient} from '@azure/storage-blob'
|
||||||
import {TransferProgressEvent} from '@azure/ms-rest-js'
|
import {TransferProgressEvent} from '@azure/ms-rest-js'
|
||||||
import * as buffer from 'buffer'
|
import * as buffer from 'buffer'
|
||||||
@@ -13,6 +12,8 @@ import {SocketTimeout} from './constants'
|
|||||||
import {DownloadOptions} from '../options'
|
import {DownloadOptions} from '../options'
|
||||||
import {retryHttpClientResponse} from './requestUtils'
|
import {retryHttpClientResponse} from './requestUtils'
|
||||||
|
|
||||||
|
import {AbortController} from '@azure/abort-controller'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pipes the body of a HTTP response to a stream
|
* Pipes the body of a HTTP response to a stream
|
||||||
*
|
*
|
||||||
@@ -20,7 +21,7 @@ import {retryHttpClientResponse} from './requestUtils'
|
|||||||
* @param output the writable stream
|
* @param output the writable stream
|
||||||
*/
|
*/
|
||||||
async function pipeResponseToStream(
|
async function pipeResponseToStream(
|
||||||
response: IHttpClientResponse,
|
response: HttpClientResponse,
|
||||||
output: NodeJS.WritableStream
|
output: NodeJS.WritableStream
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const pipeline = util.promisify(stream.pipeline)
|
const pipeline = util.promisify(stream.pipeline)
|
||||||
@@ -248,7 +249,8 @@ export async function downloadCacheStorageSDK(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
downloadProgress.startDisplayTimer()
|
downloadProgress.startDisplayTimer()
|
||||||
|
const controller = new AbortController()
|
||||||
|
const abortSignal = controller.signal
|
||||||
while (!downloadProgress.isDone()) {
|
while (!downloadProgress.isDone()) {
|
||||||
const segmentStart =
|
const segmentStart =
|
||||||
downloadProgress.segmentOffset + downloadProgress.segmentSize
|
downloadProgress.segmentOffset + downloadProgress.segmentSize
|
||||||
@@ -259,17 +261,22 @@ export async function downloadCacheStorageSDK(
|
|||||||
)
|
)
|
||||||
|
|
||||||
downloadProgress.nextSegment(segmentSize)
|
downloadProgress.nextSegment(segmentSize)
|
||||||
|
const result = await promiseWithTimeout(
|
||||||
const result = await client.downloadToBuffer(
|
options.segmentTimeoutInMs || 3600000,
|
||||||
segmentStart,
|
client.downloadToBuffer(segmentStart, segmentSize, {
|
||||||
segmentSize,
|
abortSignal,
|
||||||
{
|
|
||||||
concurrency: options.downloadConcurrency,
|
concurrency: options.downloadConcurrency,
|
||||||
onProgress: downloadProgress.onProgress()
|
onProgress: downloadProgress.onProgress()
|
||||||
}
|
})
|
||||||
)
|
)
|
||||||
|
if (result === 'timeout') {
|
||||||
fs.writeFileSync(fd, result)
|
controller.abort()
|
||||||
|
throw new Error(
|
||||||
|
'Aborting cache download as the download time exceeded the timeout.'
|
||||||
|
)
|
||||||
|
} else if (Buffer.isBuffer(result)) {
|
||||||
|
fs.writeFileSync(fd, result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
downloadProgress.stopDisplayTimer()
|
downloadProgress.stopDisplayTimer()
|
||||||
@@ -277,3 +284,18 @@ export async function downloadCacheStorageSDK(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const promiseWithTimeout = async (
|
||||||
|
timeoutMs: number,
|
||||||
|
promise: Promise<Buffer>
|
||||||
|
): Promise<unknown> => {
|
||||||
|
let timeoutHandle: NodeJS.Timeout
|
||||||
|
const timeoutPromise = new Promise(resolve => {
|
||||||
|
timeoutHandle = setTimeout(() => resolve('timeout'), timeoutMs)
|
||||||
|
})
|
||||||
|
|
||||||
|
return Promise.race([promise, timeoutPromise]).then(result => {
|
||||||
|
clearTimeout(timeoutHandle)
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
+9
-6
@@ -1,6 +1,9 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import {HttpCodes, HttpClientError} from '@actions/http-client'
|
import {
|
||||||
import {IHttpClientResponse} from '@actions/http-client/interfaces'
|
HttpCodes,
|
||||||
|
HttpClientError,
|
||||||
|
HttpClientResponse
|
||||||
|
} from '@actions/http-client'
|
||||||
import {DefaultRetryDelay, DefaultRetryAttempts} from './constants'
|
import {DefaultRetryDelay, DefaultRetryAttempts} from './constants'
|
||||||
import {ITypedResponseWithError} from './contracts'
|
import {ITypedResponseWithError} from './contracts'
|
||||||
|
|
||||||
@@ -103,7 +106,7 @@ export async function retryTypedResponse<T>(
|
|||||||
maxAttempts,
|
maxAttempts,
|
||||||
delay,
|
delay,
|
||||||
// If the error object contains the statusCode property, extract it and return
|
// If the error object contains the statusCode property, extract it and return
|
||||||
// an ITypedResponse<T> so it can be processed by the retry logic.
|
// an TypedResponse<T> so it can be processed by the retry logic.
|
||||||
(error: Error) => {
|
(error: Error) => {
|
||||||
if (error instanceof HttpClientError) {
|
if (error instanceof HttpClientError) {
|
||||||
return {
|
return {
|
||||||
@@ -121,14 +124,14 @@ export async function retryTypedResponse<T>(
|
|||||||
|
|
||||||
export async function retryHttpClientResponse(
|
export async function retryHttpClientResponse(
|
||||||
name: string,
|
name: string,
|
||||||
method: () => Promise<IHttpClientResponse>,
|
method: () => Promise<HttpClientResponse>,
|
||||||
maxAttempts = DefaultRetryAttempts,
|
maxAttempts = DefaultRetryAttempts,
|
||||||
delay = DefaultRetryDelay
|
delay = DefaultRetryDelay
|
||||||
): Promise<IHttpClientResponse> {
|
): Promise<HttpClientResponse> {
|
||||||
return await retry(
|
return await retry(
|
||||||
name,
|
name,
|
||||||
method,
|
method,
|
||||||
(response: IHttpClientResponse) => response.message.statusCode,
|
(response: HttpClientResponse) => response.message.statusCode,
|
||||||
maxAttempts,
|
maxAttempts,
|
||||||
delay
|
delay
|
||||||
)
|
)
|
||||||
|
|||||||
Vendored
+244
-105
@@ -3,23 +3,28 @@ import * as io from '@actions/io'
|
|||||||
import {existsSync, writeFileSync} from 'fs'
|
import {existsSync, writeFileSync} from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as utils from './cacheUtils'
|
import * as utils from './cacheUtils'
|
||||||
import {CompressionMethod} from './constants'
|
import {ArchiveTool} from './contracts'
|
||||||
|
import {
|
||||||
|
CompressionMethod,
|
||||||
|
SystemTarPathOnWindows,
|
||||||
|
ArchiveToolType,
|
||||||
|
TarFilename,
|
||||||
|
ManifestFilename
|
||||||
|
} from './constants'
|
||||||
|
|
||||||
async function getTarPath(
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
args: string[],
|
|
||||||
compressionMethod: CompressionMethod
|
// Returns tar path and type: BSD or GNU
|
||||||
): Promise<string> {
|
async function getTarPath(): Promise<ArchiveTool> {
|
||||||
switch (process.platform) {
|
switch (process.platform) {
|
||||||
case 'win32': {
|
case 'win32': {
|
||||||
const systemTar = `${process.env['windir']}\\System32\\tar.exe`
|
const gnuTar = await utils.getGnuTarPathOnWindows()
|
||||||
if (compressionMethod !== CompressionMethod.Gzip) {
|
const systemTar = SystemTarPathOnWindows
|
||||||
// We only use zstandard compression on windows when gnu tar is installed due to
|
if (gnuTar) {
|
||||||
// a bug with compressing large files with bsdtar + zstd
|
// Use GNUtar as default on windows
|
||||||
args.push('--force-local')
|
return <ArchiveTool>{path: gnuTar, type: ArchiveToolType.GNU}
|
||||||
} else if (existsSync(systemTar)) {
|
} else if (existsSync(systemTar)) {
|
||||||
return systemTar
|
return <ArchiveTool>{path: systemTar, type: ArchiveToolType.BSD}
|
||||||
} else if (await utils.isGnuTarInstalled()) {
|
|
||||||
args.push('--force-local')
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -27,33 +32,241 @@ async function getTarPath(
|
|||||||
const gnuTar = await io.which('gtar', false)
|
const gnuTar = await io.which('gtar', false)
|
||||||
if (gnuTar) {
|
if (gnuTar) {
|
||||||
// fix permission denied errors when extracting BSD tar archive with GNU tar - https://github.com/actions/cache/issues/527
|
// fix permission denied errors when extracting BSD tar archive with GNU tar - https://github.com/actions/cache/issues/527
|
||||||
args.push('--delay-directory-restore')
|
return <ArchiveTool>{path: gnuTar, type: ArchiveToolType.GNU}
|
||||||
return gnuTar
|
} else {
|
||||||
|
return <ArchiveTool>{
|
||||||
|
path: await io.which('tar', true),
|
||||||
|
type: ArchiveToolType.BSD
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return await io.which('tar', true)
|
// Default assumption is GNU tar is present in path
|
||||||
|
return <ArchiveTool>{
|
||||||
|
path: await io.which('tar', true),
|
||||||
|
type: ArchiveToolType.GNU
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function execTar(
|
// Return arguments for tar as per tarPath, compressionMethod, method type and os
|
||||||
args: string[],
|
async function getTarArgs(
|
||||||
|
tarPath: ArchiveTool,
|
||||||
compressionMethod: CompressionMethod,
|
compressionMethod: CompressionMethod,
|
||||||
cwd?: string
|
type: string,
|
||||||
): Promise<void> {
|
archivePath = ''
|
||||||
try {
|
): Promise<string[]> {
|
||||||
await exec(`"${await getTarPath(args, compressionMethod)}"`, args, {cwd})
|
const args = [`"${tarPath.path}"`]
|
||||||
} catch (error) {
|
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
||||||
throw new Error(`Tar failed with error: ${error?.message}`)
|
const tarFile = 'cache.tar'
|
||||||
|
const workingDirectory = getWorkingDirectory()
|
||||||
|
// Speficic args for BSD tar on windows for workaround
|
||||||
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
|
|
||||||
|
// Method specific args
|
||||||
|
switch (type) {
|
||||||
|
case 'create':
|
||||||
|
args.push(
|
||||||
|
'--posix',
|
||||||
|
'-cf',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'--exclude',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P',
|
||||||
|
'-C',
|
||||||
|
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'--files-from',
|
||||||
|
ManifestFilename
|
||||||
|
)
|
||||||
|
break
|
||||||
|
case 'extract':
|
||||||
|
args.push(
|
||||||
|
'-xf',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P',
|
||||||
|
'-C',
|
||||||
|
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||||
|
)
|
||||||
|
break
|
||||||
|
case 'list':
|
||||||
|
args.push(
|
||||||
|
'-tf',
|
||||||
|
BSD_TAR_ZSTD
|
||||||
|
? tarFile
|
||||||
|
: archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
'-P'
|
||||||
|
)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Platform specific args
|
||||||
|
if (tarPath.type === ArchiveToolType.GNU) {
|
||||||
|
switch (process.platform) {
|
||||||
|
case 'win32':
|
||||||
|
args.push('--force-local')
|
||||||
|
break
|
||||||
|
case 'darwin':
|
||||||
|
args.push('--delay-directory-restore')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns commands to run tar and compression program
|
||||||
|
async function getCommands(
|
||||||
|
compressionMethod: CompressionMethod,
|
||||||
|
type: string,
|
||||||
|
archivePath = ''
|
||||||
|
): Promise<string[]> {
|
||||||
|
let args
|
||||||
|
|
||||||
|
const tarPath = await getTarPath()
|
||||||
|
const tarArgs = await getTarArgs(
|
||||||
|
tarPath,
|
||||||
|
compressionMethod,
|
||||||
|
type,
|
||||||
|
archivePath
|
||||||
|
)
|
||||||
|
const compressionArgs =
|
||||||
|
type !== 'create'
|
||||||
|
? await getDecompressionProgram(tarPath, compressionMethod, archivePath)
|
||||||
|
: await getCompressionProgram(tarPath, compressionMethod)
|
||||||
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
|
|
||||||
|
if (BSD_TAR_ZSTD && type !== 'create') {
|
||||||
|
args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')]
|
||||||
|
} else {
|
||||||
|
args = [[...tarArgs].join(' '), [...compressionArgs].join(' ')]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BSD_TAR_ZSTD) {
|
||||||
|
return args
|
||||||
|
}
|
||||||
|
|
||||||
|
return [args.join(' ')]
|
||||||
}
|
}
|
||||||
|
|
||||||
function getWorkingDirectory(): string {
|
function getWorkingDirectory(): string {
|
||||||
return process.env['GITHUB_WORKSPACE'] ?? process.cwd()
|
return process.env['GITHUB_WORKSPACE'] ?? process.cwd()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common function for extractTar and listTar to get the compression method
|
||||||
|
async function getDecompressionProgram(
|
||||||
|
tarPath: ArchiveTool,
|
||||||
|
compressionMethod: CompressionMethod,
|
||||||
|
archivePath: string
|
||||||
|
): Promise<string[]> {
|
||||||
|
// -d: Decompress.
|
||||||
|
// unzstd is equivalent to 'zstd -d'
|
||||||
|
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
||||||
|
// Using 30 here because we also support 32-bit self-hosted runners.
|
||||||
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
|
switch (compressionMethod) {
|
||||||
|
case CompressionMethod.Zstd:
|
||||||
|
return BSD_TAR_ZSTD
|
||||||
|
? [
|
||||||
|
'zstd -d --long=30 -o',
|
||||||
|
TarFilename,
|
||||||
|
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
'--use-compress-program',
|
||||||
|
IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
|
||||||
|
]
|
||||||
|
case CompressionMethod.ZstdWithoutLong:
|
||||||
|
return BSD_TAR_ZSTD
|
||||||
|
? [
|
||||||
|
'zstd -d -o',
|
||||||
|
TarFilename,
|
||||||
|
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
||||||
|
]
|
||||||
|
: ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd']
|
||||||
|
default:
|
||||||
|
return ['-z']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used for creating the archive
|
||||||
|
// -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'
|
||||||
|
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
||||||
|
// Using 30 here because we also support 32-bit self-hosted runners.
|
||||||
|
// Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd.
|
||||||
|
async function getCompressionProgram(
|
||||||
|
tarPath: ArchiveTool,
|
||||||
|
compressionMethod: CompressionMethod
|
||||||
|
): Promise<string[]> {
|
||||||
|
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
||||||
|
const BSD_TAR_ZSTD =
|
||||||
|
tarPath.type === ArchiveToolType.BSD &&
|
||||||
|
compressionMethod !== CompressionMethod.Gzip &&
|
||||||
|
IS_WINDOWS
|
||||||
|
switch (compressionMethod) {
|
||||||
|
case CompressionMethod.Zstd:
|
||||||
|
return BSD_TAR_ZSTD
|
||||||
|
? [
|
||||||
|
'zstd -T0 --long=30 -o',
|
||||||
|
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
TarFilename
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
'--use-compress-program',
|
||||||
|
IS_WINDOWS ? '"zstd -T0 --long=30"' : 'zstdmt --long=30'
|
||||||
|
]
|
||||||
|
case CompressionMethod.ZstdWithoutLong:
|
||||||
|
return BSD_TAR_ZSTD
|
||||||
|
? [
|
||||||
|
'zstd -T0 -o',
|
||||||
|
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
||||||
|
TarFilename
|
||||||
|
]
|
||||||
|
: ['--use-compress-program', IS_WINDOWS ? '"zstd -T0"' : 'zstdmt']
|
||||||
|
default:
|
||||||
|
return ['-z']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
archivePath: string,
|
||||||
|
compressionMethod: CompressionMethod
|
||||||
|
): Promise<void> {
|
||||||
|
const commands = await getCommands(compressionMethod, 'list', archivePath)
|
||||||
|
await execCommands(commands)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract a tar
|
||||||
export async function extractTar(
|
export async function extractTar(
|
||||||
archivePath: string,
|
archivePath: string,
|
||||||
compressionMethod: CompressionMethod
|
compressionMethod: CompressionMethod
|
||||||
@@ -61,95 +274,21 @@ 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)
|
||||||
// --d: Decompress.
|
const commands = await getCommands(compressionMethod, 'extract', archivePath)
|
||||||
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
await execCommands(commands)
|
||||||
// Using 30 here because we also support 32-bit self-hosted runners.
|
|
||||||
function getCompressionProgram(): string[] {
|
|
||||||
switch (compressionMethod) {
|
|
||||||
case CompressionMethod.Zstd:
|
|
||||||
return ['--use-compress-program', 'zstd -d --long=30']
|
|
||||||
case CompressionMethod.ZstdWithoutLong:
|
|
||||||
return ['--use-compress-program', 'zstd -d']
|
|
||||||
default:
|
|
||||||
return ['-z']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const args = [
|
|
||||||
...getCompressionProgram(),
|
|
||||||
'-xf',
|
|
||||||
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
|
||||||
'-P',
|
|
||||||
'-C',
|
|
||||||
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
|
|
||||||
]
|
|
||||||
await execTar(args, compressionMethod)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a tar
|
||||||
export async function createTar(
|
export async function createTar(
|
||||||
archiveFolder: string,
|
archiveFolder: string,
|
||||||
sourceDirectories: string[],
|
sourceDirectories: string[],
|
||||||
compressionMethod: CompressionMethod
|
compressionMethod: CompressionMethod
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// Write source directories to manifest.txt to avoid command length limits
|
// Write source directories to manifest.txt to avoid command length limits
|
||||||
const manifestFilename = 'manifest.txt'
|
|
||||||
const cacheFileName = utils.getCacheFileName(compressionMethod)
|
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
path.join(archiveFolder, manifestFilename),
|
path.join(archiveFolder, ManifestFilename),
|
||||||
sourceDirectories.join('\n')
|
sourceDirectories.join('\n')
|
||||||
)
|
)
|
||||||
const workingDirectory = getWorkingDirectory()
|
const commands = await getCommands(compressionMethod, 'create')
|
||||||
|
await execCommands(commands, archiveFolder)
|
||||||
// -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
|
|
||||||
// --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
|
||||||
// Using 30 here because we also support 32-bit self-hosted runners.
|
|
||||||
// Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd.
|
|
||||||
function getCompressionProgram(): string[] {
|
|
||||||
switch (compressionMethod) {
|
|
||||||
case CompressionMethod.Zstd:
|
|
||||||
return ['--use-compress-program', 'zstd -T0 --long=30']
|
|
||||||
case CompressionMethod.ZstdWithoutLong:
|
|
||||||
return ['--use-compress-program', 'zstd -T0']
|
|
||||||
default:
|
|
||||||
return ['-z']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const args = [
|
|
||||||
'--posix',
|
|
||||||
...getCompressionProgram(),
|
|
||||||
'-cf',
|
|
||||||
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
|
||||||
'-P',
|
|
||||||
'-C',
|
|
||||||
workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
|
||||||
'--files-from',
|
|
||||||
manifestFilename
|
|
||||||
]
|
|
||||||
await execTar(args, compressionMethod, archiveFolder)
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function listTar(
|
|
||||||
archivePath: string,
|
|
||||||
compressionMethod: CompressionMethod
|
|
||||||
): Promise<void> {
|
|
||||||
// --d: Decompress.
|
|
||||||
// --long=#: Enables long distance matching with # bits.
|
|
||||||
// Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
|
|
||||||
// Using 30 here because we also support 32-bit self-hosted runners.
|
|
||||||
function getCompressionProgram(): string[] {
|
|
||||||
switch (compressionMethod) {
|
|
||||||
case CompressionMethod.Zstd:
|
|
||||||
return ['--use-compress-program', 'zstd -d --long=30']
|
|
||||||
case CompressionMethod.ZstdWithoutLong:
|
|
||||||
return ['--use-compress-program', 'zstd -d']
|
|
||||||
default:
|
|
||||||
return ['-z']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const args = [
|
|
||||||
...getCompressionProgram(),
|
|
||||||
'-tf',
|
|
||||||
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
|
|
||||||
'-P'
|
|
||||||
]
|
|
||||||
await execTar(args, compressionMethod)
|
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+27
-2
@@ -46,6 +46,13 @@ export interface DownloadOptions {
|
|||||||
* @default 30000
|
* @default 30000
|
||||||
*/
|
*/
|
||||||
timeoutInMs?: number
|
timeoutInMs?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time after which a segment download should be aborted if stuck
|
||||||
|
*
|
||||||
|
* @default 3600000
|
||||||
|
*/
|
||||||
|
segmentTimeoutInMs?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -84,7 +91,8 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
|
|||||||
const result: DownloadOptions = {
|
const result: DownloadOptions = {
|
||||||
useAzureSdk: true,
|
useAzureSdk: true,
|
||||||
downloadConcurrency: 8,
|
downloadConcurrency: 8,
|
||||||
timeoutInMs: 30000
|
timeoutInMs: 30000,
|
||||||
|
segmentTimeoutInMs: 3600000
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copy) {
|
if (copy) {
|
||||||
@@ -99,11 +107,28 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
|
|||||||
if (typeof copy.timeoutInMs === 'number') {
|
if (typeof copy.timeoutInMs === 'number') {
|
||||||
result.timeoutInMs = copy.timeoutInMs
|
result.timeoutInMs = copy.timeoutInMs
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if (typeof copy.segmentTimeoutInMs === 'number') {
|
||||||
|
result.segmentTimeoutInMs = copy.segmentTimeoutInMs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const segmentDownloadTimeoutMins =
|
||||||
|
process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']
|
||||||
|
|
||||||
|
if (
|
||||||
|
segmentDownloadTimeoutMins &&
|
||||||
|
!isNaN(Number(segmentDownloadTimeoutMins)) &&
|
||||||
|
isFinite(Number(segmentDownloadTimeoutMins))
|
||||||
|
) {
|
||||||
|
result.segmentTimeoutInMs = Number(segmentDownloadTimeoutMins) * 60 * 1000
|
||||||
|
}
|
||||||
core.debug(`Use Azure SDK: ${result.useAzureSdk}`)
|
core.debug(`Use Azure SDK: ${result.useAzureSdk}`)
|
||||||
core.debug(`Download concurrency: ${result.downloadConcurrency}`)
|
core.debug(`Download concurrency: ${result.downloadConcurrency}`)
|
||||||
core.debug(`Request timeout (ms): ${result.timeoutInMs}`)
|
core.debug(`Request timeout (ms): ${result.timeoutInMs}`)
|
||||||
|
core.debug(
|
||||||
|
`Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}`
|
||||||
|
)
|
||||||
|
core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-1
@@ -163,7 +163,7 @@ export interface AnnotationProperties {
|
|||||||
startColumn?: number
|
startColumn?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The start column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
* The end column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
||||||
* Defaults to `startColumn` when `startColumn` is provided.
|
* Defaults to `startColumn` when `startColumn` is provided.
|
||||||
*/
|
*/
|
||||||
endColumn?: number
|
endColumn?: number
|
||||||
@@ -310,3 +310,26 @@ runs:
|
|||||||
using: 'node12'
|
using: 'node12'
|
||||||
main: 'dist/index.js'
|
main: 'dist/index.js'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Filesystem path helpers
|
||||||
|
|
||||||
|
You can use these methods to manipulate file paths across operating systems.
|
||||||
|
|
||||||
|
The `toPosixPath` function converts input paths to Posix-style (Linux) paths.
|
||||||
|
The `toWin32Path` function converts input paths to Windows-style paths. These
|
||||||
|
functions work independently of the underlying runner operating system.
|
||||||
|
|
||||||
|
```js
|
||||||
|
toPosixPath('\\foo\\bar') // => /foo/bar
|
||||||
|
toWin32Path('/foo/bar') // => \foo\bar
|
||||||
|
```
|
||||||
|
|
||||||
|
The `toPlatformPath` function converts input paths to the expected value on the runner's operating system.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// On a Windows runner.
|
||||||
|
toPlatformPath('/foo/bar') // => \foo\bar
|
||||||
|
|
||||||
|
// On a Linux runner.
|
||||||
|
toPlatformPath('\\foo\\bar') // => /foo/bar
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,5 +1,26 @@
|
|||||||
# @actions/core Releases
|
# @actions/core Releases
|
||||||
|
|
||||||
|
### 1.10.0
|
||||||
|
- `saveState` and `setOutput` now use environment files if available [#1178](https://github.com/actions/toolkit/pull/1178)
|
||||||
|
- `getMultilineInput` now correctly trims whitespace by default [#1185](https://github.com/actions/toolkit/pull/1185)
|
||||||
|
|
||||||
|
### 1.9.1
|
||||||
|
- Randomize delimiter when calling `core.exportVariable`
|
||||||
|
|
||||||
|
### 1.9.0
|
||||||
|
- Added `toPosixPath`, `toWin32Path` and `toPlatformPath` utilities [#1102](https://github.com/actions/toolkit/pull/1102)
|
||||||
|
|
||||||
|
### 1.8.2
|
||||||
|
- Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
|
||||||
|
|
||||||
|
### 1.8.1
|
||||||
|
- Update to v2.0.0 of `@actions/http-client`
|
||||||
|
|
||||||
|
### 1.8.0
|
||||||
|
- Deprecate `markdownSummary` extension export in favor of `summary`
|
||||||
|
- https://github.com/actions/toolkit/pull/1072
|
||||||
|
- https://github.com/actions/toolkit/pull/1073
|
||||||
|
|
||||||
### 1.7.0
|
### 1.7.0
|
||||||
- [Added `markdownSummary` extension](https://github.com/actions/toolkit/pull/1014)
|
- [Added `markdownSummary` extension](https://github.com/actions/toolkit/pull/1014)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import * as path from 'path'
|
|||||||
import * as core from '../src/core'
|
import * as core from '../src/core'
|
||||||
import {HttpClient} from '@actions/http-client'
|
import {HttpClient} from '@actions/http-client'
|
||||||
import {toCommandProperties} from '../src/utils'
|
import {toCommandProperties} from '../src/utils'
|
||||||
|
import * as uuid from 'uuid'
|
||||||
|
|
||||||
|
jest.mock('uuid')
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/unbound-method */
|
/* eslint-disable @typescript-eslint/unbound-method */
|
||||||
|
|
||||||
@@ -30,17 +33,22 @@ const testEnvVars = {
|
|||||||
INPUT_BOOLEAN_INPUT_FALSE3: 'FALSE',
|
INPUT_BOOLEAN_INPUT_FALSE3: 'FALSE',
|
||||||
INPUT_WRONG_BOOLEAN_INPUT: 'wrong',
|
INPUT_WRONG_BOOLEAN_INPUT: 'wrong',
|
||||||
INPUT_WITH_TRAILING_WHITESPACE: ' some val ',
|
INPUT_WITH_TRAILING_WHITESPACE: ' some val ',
|
||||||
|
|
||||||
INPUT_MY_INPUT_LIST: 'val1\nval2\nval3',
|
INPUT_MY_INPUT_LIST: 'val1\nval2\nval3',
|
||||||
|
INPUT_LIST_WITH_TRAILING_WHITESPACE: ' val1 \n val2 \n ',
|
||||||
|
|
||||||
// Save inputs
|
// Save inputs
|
||||||
STATE_TEST_1: 'state_val',
|
STATE_TEST_1: 'state_val',
|
||||||
|
|
||||||
// File Commands
|
// File Commands
|
||||||
GITHUB_PATH: '',
|
GITHUB_PATH: '',
|
||||||
GITHUB_ENV: ''
|
GITHUB_ENV: '',
|
||||||
|
GITHUB_OUTPUT: '',
|
||||||
|
GITHUB_STATE: ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const UUID = '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'
|
||||||
|
const DELIMITER = `ghadelimiter_${UUID}`
|
||||||
|
|
||||||
describe('@actions/core', () => {
|
describe('@actions/core', () => {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
const filePath = path.join(__dirname, `test`)
|
const filePath = path.join(__dirname, `test`)
|
||||||
@@ -54,6 +62,14 @@ describe('@actions/core', () => {
|
|||||||
process.env[key] = testEnvVars[key as keyof typeof testEnvVars]
|
process.env[key] = testEnvVars[key as keyof typeof testEnvVars]
|
||||||
}
|
}
|
||||||
process.stdout.write = jest.fn()
|
process.stdout.write = jest.fn()
|
||||||
|
|
||||||
|
jest.spyOn(uuid, 'v4').mockImplementation(() => {
|
||||||
|
return UUID
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
jest.restoreAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('legacy exportVariable produces the correct command and sets the env', () => {
|
it('legacy exportVariable produces the correct command and sets the env', () => {
|
||||||
@@ -91,7 +107,7 @@ describe('@actions/core', () => {
|
|||||||
core.exportVariable('my var', 'var val')
|
core.exportVariable('my var', 'var val')
|
||||||
verifyFileCommand(
|
verifyFileCommand(
|
||||||
command,
|
command,
|
||||||
`my var<<_GitHubActionsFileCommandDelimeter_${os.EOL}var val${os.EOL}_GitHubActionsFileCommandDelimeter_${os.EOL}`
|
`my var<<${DELIMITER}${os.EOL}var val${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -101,7 +117,7 @@ describe('@actions/core', () => {
|
|||||||
core.exportVariable('my var', true)
|
core.exportVariable('my var', true)
|
||||||
verifyFileCommand(
|
verifyFileCommand(
|
||||||
command,
|
command,
|
||||||
`my var<<_GitHubActionsFileCommandDelimeter_${os.EOL}true${os.EOL}_GitHubActionsFileCommandDelimeter_${os.EOL}`
|
`my var<<${DELIMITER}${os.EOL}true${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -111,10 +127,38 @@ describe('@actions/core', () => {
|
|||||||
core.exportVariable('my var', 5)
|
core.exportVariable('my var', 5)
|
||||||
verifyFileCommand(
|
verifyFileCommand(
|
||||||
command,
|
command,
|
||||||
`my var<<_GitHubActionsFileCommandDelimeter_${os.EOL}5${os.EOL}_GitHubActionsFileCommandDelimeter_${os.EOL}`
|
`my var<<${DELIMITER}${os.EOL}5${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('exportVariable does not allow delimiter as value', () => {
|
||||||
|
const command = 'ENV'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
core.exportVariable('my var', `good stuff ${DELIMITER} bad stuff`)
|
||||||
|
}).toThrow(
|
||||||
|
`Unexpected input: value should not contain the delimiter "${DELIMITER}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = path.join(__dirname, `test/${command}`)
|
||||||
|
fs.unlinkSync(filePath)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('exportVariable does not allow delimiter as name', () => {
|
||||||
|
const command = 'ENV'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
core.exportVariable(`good stuff ${DELIMITER} bad stuff`, 'test')
|
||||||
|
}).toThrow(
|
||||||
|
`Unexpected input: name should not contain the delimiter "${DELIMITER}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = path.join(__dirname, `test/${command}`)
|
||||||
|
fs.unlinkSync(filePath)
|
||||||
|
})
|
||||||
|
|
||||||
it('setSecret produces the correct command', () => {
|
it('setSecret produces the correct command', () => {
|
||||||
core.setSecret('secret val')
|
core.setSecret('secret val')
|
||||||
assertWriteCalls([`::add-mask::secret val${os.EOL}`])
|
assertWriteCalls([`::add-mask::secret val${os.EOL}`])
|
||||||
@@ -170,14 +214,6 @@ describe('@actions/core', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('getMultilineInput works', () => {
|
|
||||||
expect(core.getMultilineInput('my input list')).toEqual([
|
|
||||||
'val1',
|
|
||||||
'val2',
|
|
||||||
'val3'
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('getInput trims whitespace by default', () => {
|
it('getInput trims whitespace by default', () => {
|
||||||
expect(core.getInput('with trailing whitespace')).toBe('some val')
|
expect(core.getInput('with trailing whitespace')).toBe('some val')
|
||||||
})
|
})
|
||||||
@@ -218,7 +254,38 @@ describe('@actions/core', () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('setOutput produces the correct command', () => {
|
it('getMultilineInput works', () => {
|
||||||
|
expect(core.getMultilineInput('my input list')).toEqual([
|
||||||
|
'val1',
|
||||||
|
'val2',
|
||||||
|
'val3'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getMultilineInput trims whitespace by default', () => {
|
||||||
|
expect(core.getMultilineInput('list with trailing whitespace')).toEqual([
|
||||||
|
'val1',
|
||||||
|
'val2'
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getMultilineInput trims whitespace when option is explicitly true', () => {
|
||||||
|
expect(
|
||||||
|
core.getMultilineInput('list with trailing whitespace', {
|
||||||
|
trimWhitespace: true
|
||||||
|
})
|
||||||
|
).toEqual(['val1', 'val2'])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('getMultilineInput does not trim whitespace when option is false', () => {
|
||||||
|
expect(
|
||||||
|
core.getMultilineInput('list with trailing whitespace', {
|
||||||
|
trimWhitespace: false
|
||||||
|
})
|
||||||
|
).toEqual([' val1 ', ' val2 ', ' '])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('legacy setOutput produces the correct command', () => {
|
||||||
core.setOutput('some output', 'some value')
|
core.setOutput('some output', 'some value')
|
||||||
assertWriteCalls([
|
assertWriteCalls([
|
||||||
os.EOL,
|
os.EOL,
|
||||||
@@ -226,16 +293,74 @@ describe('@actions/core', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('setOutput handles bools', () => {
|
it('legacy setOutput handles bools', () => {
|
||||||
core.setOutput('some output', false)
|
core.setOutput('some output', false)
|
||||||
assertWriteCalls([os.EOL, `::set-output name=some output::false${os.EOL}`])
|
assertWriteCalls([os.EOL, `::set-output name=some output::false${os.EOL}`])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('setOutput handles numbers', () => {
|
it('legacy setOutput handles numbers', () => {
|
||||||
core.setOutput('some output', 1.01)
|
core.setOutput('some output', 1.01)
|
||||||
assertWriteCalls([os.EOL, `::set-output name=some output::1.01${os.EOL}`])
|
assertWriteCalls([os.EOL, `::set-output name=some output::1.01${os.EOL}`])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('setOutput produces the correct command and sets the output', () => {
|
||||||
|
const command = 'OUTPUT'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
core.setOutput('my out', 'out val')
|
||||||
|
verifyFileCommand(
|
||||||
|
command,
|
||||||
|
`my out<<${DELIMITER}${os.EOL}out val${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('setOutput handles boolean inputs', () => {
|
||||||
|
const command = 'OUTPUT'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
core.setOutput('my out', true)
|
||||||
|
verifyFileCommand(
|
||||||
|
command,
|
||||||
|
`my out<<${DELIMITER}${os.EOL}true${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('setOutput handles number inputs', () => {
|
||||||
|
const command = 'OUTPUT'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
core.setOutput('my out', 5)
|
||||||
|
verifyFileCommand(
|
||||||
|
command,
|
||||||
|
`my out<<${DELIMITER}${os.EOL}5${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('setOutput does not allow delimiter as value', () => {
|
||||||
|
const command = 'OUTPUT'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
core.setOutput('my out', `good stuff ${DELIMITER} bad stuff`)
|
||||||
|
}).toThrow(
|
||||||
|
`Unexpected input: value should not contain the delimiter "${DELIMITER}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = path.join(__dirname, `test/${command}`)
|
||||||
|
fs.unlinkSync(filePath)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('setOutput does not allow delimiter as name', () => {
|
||||||
|
const command = 'OUTPUT'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
core.setOutput(`good stuff ${DELIMITER} bad stuff`, 'test')
|
||||||
|
}).toThrow(
|
||||||
|
`Unexpected input: name should not contain the delimiter "${DELIMITER}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = path.join(__dirname, `test/${command}`)
|
||||||
|
fs.unlinkSync(filePath)
|
||||||
|
})
|
||||||
|
|
||||||
it('setFailed sets the correct exit code and failure message', () => {
|
it('setFailed sets the correct exit code and failure message', () => {
|
||||||
core.setFailed('Failure message')
|
core.setFailed('Failure message')
|
||||||
expect(process.exitCode).toBe(core.ExitCode.Failure)
|
expect(process.exitCode).toBe(core.ExitCode.Failure)
|
||||||
@@ -401,21 +526,79 @@ describe('@actions/core', () => {
|
|||||||
assertWriteCalls([`::debug::%0D%0Adebug%0A${os.EOL}`])
|
assertWriteCalls([`::debug::%0D%0Adebug%0A${os.EOL}`])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('saveState produces the correct command', () => {
|
it('legacy saveState produces the correct command', () => {
|
||||||
core.saveState('state_1', 'some value')
|
core.saveState('state_1', 'some value')
|
||||||
assertWriteCalls([`::save-state name=state_1::some value${os.EOL}`])
|
assertWriteCalls([`::save-state name=state_1::some value${os.EOL}`])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('saveState handles numbers', () => {
|
it('legacy saveState handles numbers', () => {
|
||||||
core.saveState('state_1', 1)
|
core.saveState('state_1', 1)
|
||||||
assertWriteCalls([`::save-state name=state_1::1${os.EOL}`])
|
assertWriteCalls([`::save-state name=state_1::1${os.EOL}`])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('saveState handles bools', () => {
|
it('legacy saveState handles bools', () => {
|
||||||
core.saveState('state_1', true)
|
core.saveState('state_1', true)
|
||||||
assertWriteCalls([`::save-state name=state_1::true${os.EOL}`])
|
assertWriteCalls([`::save-state name=state_1::true${os.EOL}`])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('saveState produces the correct command and saves the state', () => {
|
||||||
|
const command = 'STATE'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
core.saveState('my state', 'out val')
|
||||||
|
verifyFileCommand(
|
||||||
|
command,
|
||||||
|
`my state<<${DELIMITER}${os.EOL}out val${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('saveState handles boolean inputs', () => {
|
||||||
|
const command = 'STATE'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
core.saveState('my state', true)
|
||||||
|
verifyFileCommand(
|
||||||
|
command,
|
||||||
|
`my state<<${DELIMITER}${os.EOL}true${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('saveState handles number inputs', () => {
|
||||||
|
const command = 'STATE'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
core.saveState('my state', 5)
|
||||||
|
verifyFileCommand(
|
||||||
|
command,
|
||||||
|
`my state<<${DELIMITER}${os.EOL}5${os.EOL}${DELIMITER}${os.EOL}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('saveState does not allow delimiter as value', () => {
|
||||||
|
const command = 'STATE'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
core.saveState('my state', `good stuff ${DELIMITER} bad stuff`)
|
||||||
|
}).toThrow(
|
||||||
|
`Unexpected input: value should not contain the delimiter "${DELIMITER}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = path.join(__dirname, `test/${command}`)
|
||||||
|
fs.unlinkSync(filePath)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('saveState does not allow delimiter as name', () => {
|
||||||
|
const command = 'STATE'
|
||||||
|
createFileCommandFile(command)
|
||||||
|
|
||||||
|
expect(() => {
|
||||||
|
core.saveState(`good stuff ${DELIMITER} bad stuff`, 'test')
|
||||||
|
}).toThrow(
|
||||||
|
`Unexpected input: name should not contain the delimiter "${DELIMITER}"`
|
||||||
|
)
|
||||||
|
|
||||||
|
const filePath = path.join(__dirname, `test/${command}`)
|
||||||
|
fs.unlinkSync(filePath)
|
||||||
|
})
|
||||||
|
|
||||||
it('getState gets wrapper action state', () => {
|
it('getState gets wrapper action state', () => {
|
||||||
expect(core.getState('TEST_1')).toBe('state_val')
|
expect(core.getState('TEST_1')).toBe('state_val')
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
import {toPlatformPath, toPosixPath, toWin32Path} from '../src/path-utils'
|
||||||
|
|
||||||
|
describe('#toPosixPath', () => {
|
||||||
|
const cases: {
|
||||||
|
only?: boolean
|
||||||
|
name: string
|
||||||
|
input: string
|
||||||
|
expected: string
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
name: 'empty string',
|
||||||
|
input: '',
|
||||||
|
expected: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'single value',
|
||||||
|
input: 'foo',
|
||||||
|
expected: 'foo'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with posix relative',
|
||||||
|
input: 'foo/bar/baz',
|
||||||
|
expected: 'foo/bar/baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with posix absolute',
|
||||||
|
input: '/foo/bar/baz',
|
||||||
|
expected: '/foo/bar/baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with win32 relative',
|
||||||
|
input: 'foo\\bar\\baz',
|
||||||
|
expected: 'foo/bar/baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with win32 absolute',
|
||||||
|
input: '\\foo\\bar\\baz',
|
||||||
|
expected: '/foo/bar/baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with a mix',
|
||||||
|
input: '\\foo/bar/baz',
|
||||||
|
expected: '/foo/bar/baz'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const tc of cases) {
|
||||||
|
const fn = tc.only ? it.only : it
|
||||||
|
fn(tc.name, () => {
|
||||||
|
const result = toPosixPath(tc.input)
|
||||||
|
expect(result).toEqual(tc.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#toWin32Path', () => {
|
||||||
|
const cases: {
|
||||||
|
only?: boolean
|
||||||
|
name: string
|
||||||
|
input: string
|
||||||
|
expected: string
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
name: 'empty string',
|
||||||
|
input: '',
|
||||||
|
expected: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'single value',
|
||||||
|
input: 'foo',
|
||||||
|
expected: 'foo'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with posix relative',
|
||||||
|
input: 'foo/bar/baz',
|
||||||
|
expected: 'foo\\bar\\baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with posix absolute',
|
||||||
|
input: '/foo/bar/baz',
|
||||||
|
expected: '\\foo\\bar\\baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with win32 relative',
|
||||||
|
input: 'foo\\bar\\baz',
|
||||||
|
expected: 'foo\\bar\\baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with win32 absolute',
|
||||||
|
input: '\\foo\\bar\\baz',
|
||||||
|
expected: '\\foo\\bar\\baz'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with a mix',
|
||||||
|
input: '\\foo/bar\\baz',
|
||||||
|
expected: '\\foo\\bar\\baz'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const tc of cases) {
|
||||||
|
const fn = tc.only ? it.only : it
|
||||||
|
fn(tc.name, () => {
|
||||||
|
const result = toWin32Path(tc.input)
|
||||||
|
expect(result).toEqual(tc.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('#toPlatformPath', () => {
|
||||||
|
const cases: {
|
||||||
|
only?: boolean
|
||||||
|
name: string
|
||||||
|
input: string
|
||||||
|
expected: string
|
||||||
|
}[] = [
|
||||||
|
{
|
||||||
|
name: 'empty string',
|
||||||
|
input: '',
|
||||||
|
expected: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'single value',
|
||||||
|
input: 'foo',
|
||||||
|
expected: 'foo'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with posix relative',
|
||||||
|
input: 'foo/bar/baz',
|
||||||
|
expected: path.join('foo', 'bar', 'baz')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with posix absolute',
|
||||||
|
input: '/foo/bar/baz',
|
||||||
|
expected: path.join(path.sep, 'foo', 'bar', 'baz')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with win32 relative',
|
||||||
|
input: 'foo\\bar\\baz',
|
||||||
|
expected: path.join('foo', 'bar', 'baz')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with win32 absolute',
|
||||||
|
input: '\\foo\\bar\\baz',
|
||||||
|
expected: path.join(path.sep, 'foo', 'bar', 'baz')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'with a mix',
|
||||||
|
input: '\\foo/bar\\baz',
|
||||||
|
expected: path.join(path.sep, 'foo', 'bar', 'baz')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
for (const tc of cases) {
|
||||||
|
const fn = tc.only ? it.only : it
|
||||||
|
fn(tc.name, () => {
|
||||||
|
const result = toPlatformPath(tc.input)
|
||||||
|
expect(result).toEqual(tc.expected)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
Generated
+39
-12
@@ -1,26 +1,28 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/core",
|
"name": "@actions/core",
|
||||||
"version": "1.7.0",
|
"version": "1.10.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/core",
|
"name": "@actions/core",
|
||||||
"version": "1.6.0",
|
"version": "1.10.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^1.0.11"
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^12.0.2"
|
"@types/node": "^12.0.2",
|
||||||
|
"@types/uuid": "^8.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/http-client": {
|
"node_modules/@actions/http-client": {
|
||||||
"version": "1.0.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
@@ -29,6 +31,12 @@
|
|||||||
"integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
|
"integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/tunnel": {
|
"node_modules/tunnel": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
@@ -36,15 +44,23 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@types/node": {
|
"@types/node": {
|
||||||
@@ -53,10 +69,21 @@
|
|||||||
"integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
|
"integrity": "sha512-5tabW/i+9mhrfEOUcLDu2xBPsHJ+X5Orqy9FKpale3SjDA17j5AEpYq5vfy3oAeAHGcvANRCO3NV3d2D6q3NiA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "8.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
|
||||||
|
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"tunnel": {
|
"tunnel": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/core",
|
"name": "@actions/core",
|
||||||
"version": "1.7.0",
|
"version": "1.10.0",
|
||||||
"description": "Actions core lib",
|
"description": "Actions core lib",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"github",
|
"github",
|
||||||
@@ -36,9 +36,11 @@
|
|||||||
"url": "https://github.com/actions/toolkit/issues"
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^1.0.11"
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^12.0.2"
|
"@types/node": "^12.0.2",
|
||||||
|
"@types/uuid": "^8.3.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-10
@@ -1,5 +1,5 @@
|
|||||||
import {issue, issueCommand} from './command'
|
import {issue, issueCommand} from './command'
|
||||||
import {issueCommand as issueFileCommand} from './file-command'
|
import {issueFileCommand, prepareKeyValueMessage} from './file-command'
|
||||||
import {toCommandProperties, toCommandValue} from './utils'
|
import {toCommandProperties, toCommandValue} from './utils'
|
||||||
|
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
@@ -64,7 +64,7 @@ export interface AnnotationProperties {
|
|||||||
startColumn?: number
|
startColumn?: number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The start column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
* The end column for the annotation. Cannot be sent when `startLine` and `endLine` are different values.
|
||||||
* Defaults to `startColumn` when `startColumn` is provided.
|
* Defaults to `startColumn` when `startColumn` is provided.
|
||||||
*/
|
*/
|
||||||
endColumn?: number
|
endColumn?: number
|
||||||
@@ -86,12 +86,10 @@ export function exportVariable(name: string, val: any): void {
|
|||||||
|
|
||||||
const filePath = process.env['GITHUB_ENV'] || ''
|
const filePath = process.env['GITHUB_ENV'] || ''
|
||||||
if (filePath) {
|
if (filePath) {
|
||||||
const delimiter = '_GitHubActionsFileCommandDelimeter_'
|
return issueFileCommand('ENV', prepareKeyValueMessage(name, val))
|
||||||
const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`
|
|
||||||
issueFileCommand('ENV', commandValue)
|
|
||||||
} else {
|
|
||||||
issueCommand('set-env', {name}, convertedVal)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issueCommand('set-env', {name}, convertedVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,7 +153,11 @@ export function getMultilineInput(
|
|||||||
.split('\n')
|
.split('\n')
|
||||||
.filter(x => x !== '')
|
.filter(x => x !== '')
|
||||||
|
|
||||||
return inputs
|
if (options && options.trimWhitespace === false) {
|
||||||
|
return inputs
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputs.map(input => input.trim())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,8 +190,13 @@ export function getBooleanInput(name: string, options?: InputOptions): boolean {
|
|||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export function setOutput(name: string, value: any): void {
|
export function setOutput(name: string, value: any): void {
|
||||||
|
const filePath = process.env['GITHUB_OUTPUT'] || ''
|
||||||
|
if (filePath) {
|
||||||
|
return issueFileCommand('OUTPUT', prepareKeyValueMessage(name, value))
|
||||||
|
}
|
||||||
|
|
||||||
process.stdout.write(os.EOL)
|
process.stdout.write(os.EOL)
|
||||||
issueCommand('set-output', {name}, value)
|
issueCommand('set-output', {name}, toCommandValue(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,7 +350,12 @@ export async function group<T>(name: string, fn: () => Promise<T>): Promise<T> {
|
|||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export function saveState(name: string, value: any): void {
|
export function saveState(name: string, value: any): void {
|
||||||
issueCommand('save-state', {name}, value)
|
const filePath = process.env['GITHUB_STATE'] || ''
|
||||||
|
if (filePath) {
|
||||||
|
return issueFileCommand('STATE', prepareKeyValueMessage(name, value))
|
||||||
|
}
|
||||||
|
|
||||||
|
issueCommand('save-state', {name}, toCommandValue(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -364,3 +376,13 @@ export async function getIDToken(aud?: string): Promise<string> {
|
|||||||
* Summary exports
|
* Summary exports
|
||||||
*/
|
*/
|
||||||
export {summary} from './summary'
|
export {summary} from './summary'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use core.summary
|
||||||
|
*/
|
||||||
|
export {markdownSummary} from './summary'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Path exports
|
||||||
|
*/
|
||||||
|
export {toPosixPath, toWin32Path, toPlatformPath} from './path-utils'
|
||||||
|
|||||||
@@ -5,9 +5,10 @@
|
|||||||
|
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as os from 'os'
|
import * as os from 'os'
|
||||||
|
import {v4 as uuidv4} from 'uuid'
|
||||||
import {toCommandValue} from './utils'
|
import {toCommandValue} from './utils'
|
||||||
|
|
||||||
export function issueCommand(command: string, message: any): void {
|
export function issueFileCommand(command: string, message: any): void {
|
||||||
const filePath = process.env[`GITHUB_${command}`]
|
const filePath = process.env[`GITHUB_${command}`]
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -22,3 +23,25 @@ export function issueCommand(command: string, message: any): void {
|
|||||||
encoding: 'utf8'
|
encoding: 'utf8'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function prepareKeyValueMessage(key: string, value: any): string {
|
||||||
|
const delimiter = `ghadelimiter_${uuidv4()}`
|
||||||
|
const convertedValue = toCommandValue(value)
|
||||||
|
|
||||||
|
// These should realistically never happen, but just in case someone finds a
|
||||||
|
// way to exploit uuid generation let's not allow keys or values that contain
|
||||||
|
// the delimiter.
|
||||||
|
if (key.includes(delimiter)) {
|
||||||
|
throw new Error(
|
||||||
|
`Unexpected input: name should not contain the delimiter "${delimiter}"`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (convertedValue.includes(delimiter)) {
|
||||||
|
throw new Error(
|
||||||
|
`Unexpected input: value should not contain the delimiter "${delimiter}"`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
/* eslint-disable @typescript-eslint/no-extraneous-class */
|
||||||
import * as actions_http_client from '@actions/http-client'
|
import * as actions_http_client from '@actions/http-client'
|
||||||
import {IRequestOptions} from '@actions/http-client/interfaces'
|
import {RequestOptions} from '@actions/http-client/lib/interfaces'
|
||||||
import {HttpClient} from '@actions/http-client'
|
import {HttpClient} from '@actions/http-client'
|
||||||
import {BearerCredentialHandler} from '@actions/http-client/auth'
|
import {BearerCredentialHandler} from '@actions/http-client/lib/auth'
|
||||||
import {debug, setSecret} from './core'
|
import {debug, setSecret} from './core'
|
||||||
interface TokenResponse {
|
interface TokenResponse {
|
||||||
value?: string
|
value?: string
|
||||||
@@ -13,7 +13,7 @@ export class OidcClient {
|
|||||||
allowRetry = true,
|
allowRetry = true,
|
||||||
maxRetry = 10
|
maxRetry = 10
|
||||||
): actions_http_client.HttpClient {
|
): actions_http_client.HttpClient {
|
||||||
const requestOptions: IRequestOptions = {
|
const requestOptions: RequestOptions = {
|
||||||
allowRetries: allowRetry,
|
allowRetries: allowRetry,
|
||||||
maxRetries: maxRetry
|
maxRetries: maxRetry
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toPosixPath converts the given path to the posix form. On Windows, \\ will be
|
||||||
|
* replaced with /.
|
||||||
|
*
|
||||||
|
* @param pth. Path to transform.
|
||||||
|
* @return string Posix path.
|
||||||
|
*/
|
||||||
|
export function toPosixPath(pth: string): string {
|
||||||
|
return pth.replace(/[\\]/g, '/')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toWin32Path converts the given path to the win32 form. On Linux, / will be
|
||||||
|
* replaced with \\.
|
||||||
|
*
|
||||||
|
* @param pth. Path to transform.
|
||||||
|
* @return string Win32 path.
|
||||||
|
*/
|
||||||
|
export function toWin32Path(pth: string): string {
|
||||||
|
return pth.replace(/[/]/g, '\\')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toPlatformPath converts the given path to a platform-specific path. It does
|
||||||
|
* this by replacing instances of / and \ with the platform-specific path
|
||||||
|
* separator.
|
||||||
|
*
|
||||||
|
* @param pth The path to platformize.
|
||||||
|
* @return string The platform-specific path.
|
||||||
|
*/
|
||||||
|
export function toPlatformPath(pth: string): string {
|
||||||
|
return pth.replace(/[/\\]/g, path.sep)
|
||||||
|
}
|
||||||
@@ -354,5 +354,10 @@ class Summary {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// singleton export
|
const _summary = new Summary()
|
||||||
export const summary = new Summary()
|
|
||||||
|
/**
|
||||||
|
* @deprecated use `core.summary`
|
||||||
|
*/
|
||||||
|
export const markdownSummary = _summary
|
||||||
|
export const summary = _summary
|
||||||
|
|||||||
@@ -1,5 +1,19 @@
|
|||||||
# @actions/github Releases
|
# @actions/github Releases
|
||||||
|
|
||||||
|
### 5.1.1
|
||||||
|
- Export default octokit options [#1188](https://github.com/actions/toolkit/pull/1188)
|
||||||
|
|
||||||
|
### 5.1.0
|
||||||
|
- Add additionalPlugins parameter to getOctokit method [#1181](https://github.com/actions/toolkit/pull/1181)
|
||||||
|
- Dependency updates [#1180](https://github.com/actions/toolkit/pull/1180)
|
||||||
|
|
||||||
|
|
||||||
|
### 5.0.3
|
||||||
|
- - Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
|
||||||
|
|
||||||
|
### 5.0.2
|
||||||
|
- Update to v2.0.0 of `@actions/http-client`
|
||||||
|
|
||||||
### 5.0.1
|
### 5.0.1
|
||||||
- [Update Octokit Dependencies](https://github.com/actions/toolkit/pull/1037)
|
- [Update Octokit Dependencies](https://github.com/actions/toolkit/pull/1037)
|
||||||
### 5.0.0
|
### 5.0.0
|
||||||
|
|||||||
Generated
+11
-11
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/github",
|
"name": "@actions/github",
|
||||||
"version": "5.0.1",
|
"version": "5.1.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/github",
|
"name": "@actions/github",
|
||||||
"version": "5.0.1",
|
"version": "5.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^1.0.11",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@octokit/core": "^3.6.0",
|
"@octokit/core": "^3.6.0",
|
||||||
"@octokit/plugin-paginate-rest": "^2.17.0",
|
"@octokit/plugin-paginate-rest": "^2.17.0",
|
||||||
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
||||||
@@ -19,11 +19,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/http-client": {
|
"node_modules/@actions/http-client": {
|
||||||
"version": "1.0.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/auth-token": {
|
"node_modules/@octokit/auth-token": {
|
||||||
@@ -361,11 +361,11 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.11",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-VRYHGQV1rqnROJqdMvGUbY/Kn8vriQe/F9HR2AlYHzmKuM/p3kjNuXhmdBfcVgsvRWTz5C5XW5xvndZrVBuAYg==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@octokit/auth-token": {
|
"@octokit/auth-token": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/github",
|
"name": "@actions/github",
|
||||||
"version": "5.0.1",
|
"version": "5.1.1",
|
||||||
"description": "Actions github lib",
|
"description": "Actions github lib",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"github",
|
"github",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"url": "https://github.com/actions/toolkit/issues"
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/http-client": "^1.0.11",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@octokit/core": "^3.6.0",
|
"@octokit/core": "^3.6.0",
|
||||||
"@octokit/plugin-paginate-rest": "^2.17.0",
|
"@octokit/plugin-paginate-rest": "^2.17.0",
|
||||||
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
"@octokit/plugin-rest-endpoint-methods": "^5.13.0"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as Context from './context'
|
|||||||
import {GitHub, getOctokitOptions} from './utils'
|
import {GitHub, getOctokitOptions} from './utils'
|
||||||
|
|
||||||
// octokit + plugins
|
// octokit + plugins
|
||||||
import {OctokitOptions} from '@octokit/core/dist-types/types'
|
import {OctokitOptions, OctokitPlugin} from '@octokit/core/dist-types/types'
|
||||||
|
|
||||||
export const context = new Context.Context()
|
export const context = new Context.Context()
|
||||||
|
|
||||||
@@ -14,7 +14,9 @@ export const context = new Context.Context()
|
|||||||
*/
|
*/
|
||||||
export function getOctokit(
|
export function getOctokit(
|
||||||
token: string,
|
token: string,
|
||||||
options?: OctokitOptions
|
options?: OctokitOptions,
|
||||||
|
...additionalPlugins: OctokitPlugin[]
|
||||||
): InstanceType<typeof GitHub> {
|
): InstanceType<typeof GitHub> {
|
||||||
return new GitHub(getOctokitOptions(token, options))
|
const GitHubWithPlugins = GitHub.plugin(...additionalPlugins)
|
||||||
|
return new GitHubWithPlugins(getOctokitOptions(token, options))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {paginateRest} from '@octokit/plugin-paginate-rest'
|
|||||||
export const context = new Context.Context()
|
export const context = new Context.Context()
|
||||||
|
|
||||||
const baseUrl = Utils.getApiBaseUrl()
|
const baseUrl = Utils.getApiBaseUrl()
|
||||||
const defaults = {
|
export const defaults: OctokitOptions = {
|
||||||
baseUrl,
|
baseUrl,
|
||||||
request: {
|
request: {
|
||||||
agent: Utils.getProxyAgent(baseUrl)
|
agent: Utils.getProxyAgent(baseUrl)
|
||||||
|
|||||||
Generated
+58
-8
@@ -6,17 +6,29 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/glob",
|
"name": "@actions/glob",
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.9.1",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/core": {
|
"node_modules/@actions/core": {
|
||||||
"version": "1.2.6",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/http-client": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tunnel": "^0.0.6"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -47,13 +59,41 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/tunnel": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": {
|
"@actions/core": {
|
||||||
"version": "1.2.6",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||||
|
"requires": {
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@actions/http-client": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
|
"requires": {
|
||||||
|
"tunnel": "^0.0.6"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -81,6 +121,16 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"tunnel": {
|
||||||
|
"version": "0.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"url": "https://github.com/actions/toolkit/issues"
|
"url": "https://github.com/actions/toolkit/issues"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.9.1",
|
||||||
"minimatch": "^3.0.4"
|
"minimatch": "^3.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
## Releases
|
## Releases
|
||||||
|
|
||||||
|
## 2.0.1
|
||||||
|
- Fix an issue with missing `tunnel` dependency [#1085](https://github.com/actions/toolkit/pull/1085)
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
- The package is now compiled with TypeScript's [`strict` compiler setting](https://www.typescriptlang.org/tsconfig#strict). To comply with stricter rules:
|
- The package is now compiled with TypeScript's [`strict` compiler setting](https://www.typescriptlang.org/tsconfig#strict). To comply with stricter rules:
|
||||||
- Some exported types now include `| null` or `| undefined`, matching their actual behavior.
|
- Some exported types now include `| null` or `| undefined`, matching their actual behavior.
|
||||||
|
|||||||
Generated
+7
-7
@@ -1,17 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/http-client",
|
"name": "@actions/http-client",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/http-client",
|
"name": "@actions/http-client",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tunnel": "^0.0.6"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/tunnel": "0.0.3",
|
"@types/tunnel": "0.0.3",
|
||||||
"proxy": "^1.0.1",
|
"proxy": "^1.0.1"
|
||||||
"tunnel": "0.0.6"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
@@ -182,7 +184,6 @@
|
|||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||||
}
|
}
|
||||||
@@ -325,8 +326,7 @@
|
|||||||
"tunnel": {
|
"tunnel": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/http-client",
|
"name": "@actions/http-client",
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"description": "Actions Http Client",
|
"description": "Actions Http Client",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"github",
|
"github",
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/actions/toolkit.git",
|
"url": "git+https://github.com/actions/toolkit.git",
|
||||||
"directory": "packages/github"
|
"directory": "packages/http-client"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json",
|
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json",
|
||||||
@@ -40,7 +40,9 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/tunnel": "0.0.3",
|
"@types/tunnel": "0.0.3",
|
||||||
"proxy": "^1.0.1",
|
"proxy": "^1.0.1"
|
||||||
"tunnel": "0.0.6"
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
# @actions/tool-cache Releases
|
# @actions/tool-cache Releases
|
||||||
|
|
||||||
|
### 2.0.1
|
||||||
|
- Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
|
||||||
|
|
||||||
|
### 2.0.0
|
||||||
|
- Update to v2.0.0 of `@actions/http-client`
|
||||||
|
- The type of the `headers` parameter in the exported function `downloadTool` has been narrowed from `{ [header: string]: any }` to `{ [header: string]: number | string | string[] | undefined; }` (that is, `http.OutgoingHttpHeaders`).
|
||||||
|
This is strictly a compile-time change for TypeScript consumers. Previous attempts to use a header value of a type other than those now accepted would have resulted in an error at run time.
|
||||||
|
|
||||||
### 1.7.2
|
### 1.7.2
|
||||||
- Update `lockfileVersion` to `v2` in `package-lock.json [#1025](https://github.com/actions/toolkit/pull/1025)
|
- Update `lockfileVersion` to `v2` in `package-lock.json [#1025](https://github.com/actions/toolkit/pull/1025)
|
||||||
|
|
||||||
|
|||||||
Generated
+52
-29
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/tool-cache",
|
"name": "@actions/tool-cache",
|
||||||
"version": "1.7.2",
|
"version": "2.0.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@actions/tool-cache",
|
"name": "@actions/tool-cache",
|
||||||
"version": "1.7.2",
|
"version": "2.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.0",
|
"@actions/exec": "^1.0.0",
|
||||||
"@actions/http-client": "^1.0.8",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@actions/io": "^1.1.1",
|
"@actions/io": "^1.1.1",
|
||||||
"semver": "^6.1.0",
|
"semver": "^6.1.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
@@ -24,30 +24,42 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/core": {
|
"node_modules/@actions/core": {
|
||||||
"version": "1.2.6",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@actions/core/node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/exec": {
|
"node_modules/@actions/exec": {
|
||||||
"version": "1.0.3",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
"integrity": "sha512-TogJGnueOmM7ntCi0ASTUj4LapRRtDfj57Ja4IhPmg2fls28uVOPbAn8N+JifaOumN2UG3oEO/Ixek2A4NcYSA==",
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/io": "^1.0.1"
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/http-client": {
|
"node_modules/@actions/http-client": {
|
||||||
"version": "1.0.8",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@actions/io": {
|
"node_modules/@actions/io": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.2.tgz",
|
||||||
"integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA=="
|
"integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw=="
|
||||||
},
|
},
|
||||||
"node_modules/@types/nock": {
|
"node_modules/@types/nock": {
|
||||||
"version": "10.0.3",
|
"version": "10.0.3",
|
||||||
@@ -280,30 +292,41 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": {
|
"@actions/core": {
|
||||||
"version": "1.2.6",
|
"version": "1.9.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
|
||||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
|
||||||
|
"requires": {
|
||||||
|
"@actions/http-client": "^2.0.1",
|
||||||
|
"uuid": "^8.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"@actions/exec": {
|
"@actions/exec": {
|
||||||
"version": "1.0.3",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||||
"integrity": "sha512-TogJGnueOmM7ntCi0ASTUj4LapRRtDfj57Ja4IhPmg2fls28uVOPbAn8N+JifaOumN2UG3oEO/Ixek2A4NcYSA==",
|
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@actions/io": "^1.0.1"
|
"@actions/io": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/http-client": {
|
"@actions/http-client": {
|
||||||
"version": "1.0.8",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
|
||||||
"integrity": "sha512-G4JjJ6f9Hb3Zvejj+ewLLKLf99ZC+9v+yCxoYf9vSyH+WkzPLB2LuUtRMGNkooMqdugGBFStIKXOuvH1W+EctA==",
|
"integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tunnel": "0.0.6"
|
"tunnel": "^0.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@actions/io": {
|
"@actions/io": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.2.tgz",
|
||||||
"integrity": "sha512-Qi4JoKXjmE0O67wAOH6y0n26QXhMKMFo7GD/4IXNVcrtLjUlGjGuVys6pQgwF3ArfGTQu0XpqaNr0YhED2RaRA=="
|
"integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw=="
|
||||||
},
|
},
|
||||||
"@types/nock": {
|
"@types/nock": {
|
||||||
"version": "10.0.3",
|
"version": "10.0.3",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@actions/tool-cache",
|
"name": "@actions/tool-cache",
|
||||||
"version": "1.7.2",
|
"version": "2.0.1",
|
||||||
"description": "Actions tool-cache lib",
|
"description": "Actions tool-cache lib",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"github",
|
"github",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.2.6",
|
"@actions/core": "^1.2.6",
|
||||||
"@actions/exec": "^1.0.0",
|
"@actions/exec": "^1.0.0",
|
||||||
"@actions/http-client": "^1.0.8",
|
"@actions/http-client": "^2.0.1",
|
||||||
"@actions/io": "^1.1.1",
|
"@actions/io": "^1.1.1",
|
||||||
"semver": "^6.1.0",
|
"semver": "^6.1.0",
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
|
|||||||
@@ -8,12 +8,12 @@ import * as httpm from '@actions/http-client'
|
|||||||
import * as semver from 'semver'
|
import * as semver from 'semver'
|
||||||
import * as stream from 'stream'
|
import * as stream from 'stream'
|
||||||
import * as util from 'util'
|
import * as util from 'util'
|
||||||
|
import {ok} from 'assert'
|
||||||
|
import {OutgoingHttpHeaders} from 'http'
|
||||||
import uuidV4 from 'uuid/v4'
|
import uuidV4 from 'uuid/v4'
|
||||||
import {exec} from '@actions/exec/lib/exec'
|
import {exec} from '@actions/exec/lib/exec'
|
||||||
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
import {ExecOptions} from '@actions/exec/lib/interfaces'
|
||||||
import {ok} from 'assert'
|
|
||||||
import {RetryHelper} from './retry-helper'
|
import {RetryHelper} from './retry-helper'
|
||||||
import {IHeaders} from '@actions/http-client/interfaces'
|
|
||||||
|
|
||||||
export class HTTPError extends Error {
|
export class HTTPError extends Error {
|
||||||
constructor(readonly httpStatusCode: number | undefined) {
|
constructor(readonly httpStatusCode: number | undefined) {
|
||||||
@@ -39,7 +39,7 @@ export async function downloadTool(
|
|||||||
url: string,
|
url: string,
|
||||||
dest?: string,
|
dest?: string,
|
||||||
auth?: string,
|
auth?: string,
|
||||||
headers?: IHeaders
|
headers?: OutgoingHttpHeaders
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
dest = dest || path.join(_getTempDirectory(), uuidV4())
|
dest = dest || path.join(_getTempDirectory(), uuidV4())
|
||||||
await io.mkdirP(path.dirname(dest))
|
await io.mkdirP(path.dirname(dest))
|
||||||
@@ -82,7 +82,7 @@ async function downloadToolAttempt(
|
|||||||
url: string,
|
url: string,
|
||||||
dest: string,
|
dest: string,
|
||||||
auth?: string,
|
auth?: string,
|
||||||
headers?: IHeaders
|
headers?: OutgoingHttpHeaders
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
if (fs.existsSync(dest)) {
|
if (fs.existsSync(dest)) {
|
||||||
throw new Error(`Destination file path ${dest} already exists`)
|
throw new Error(`Destination file path ${dest} already exists`)
|
||||||
@@ -596,7 +596,7 @@ export async function getManifestFromRepo(
|
|||||||
const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}`
|
const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${branch}`
|
||||||
|
|
||||||
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache')
|
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache')
|
||||||
const headers: IHeaders = {}
|
const headers: OutgoingHttpHeaders = {}
|
||||||
if (auth) {
|
if (auth) {
|
||||||
core.debug('set auth')
|
core.debug('set auth')
|
||||||
headers.authorization = auth
|
headers.authorization = auth
|
||||||
|
|||||||
@@ -54,6 +54,16 @@ const AUDIT_ALLOW_LIST = [
|
|||||||
path: "lerna>@lerna/version>@lerna/conventional-commits>conventional-changelog-core>get-pkg-repo>meow>trim-newlines",
|
path: "lerna>@lerna/version>@lerna/conventional-commits>conventional-changelog-core>get-pkg-repo>meow>trim-newlines",
|
||||||
advisoryUrl: "https://www.npmjs.com/advisories/1753",
|
advisoryUrl: "https://www.npmjs.com/advisories/1753",
|
||||||
justification: "dependency of lerna (dev only); low severity"
|
justification: "dependency of lerna (dev only); low severity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "lerna>@lerna/version>@lerna/github-client>git-url-parse>git-up>parse-url",
|
||||||
|
advisoryUrl: "https://github.com/advisories/GHSA-j9fq-vwqv-2fm2",
|
||||||
|
justification: "dependency of lerna; moderate severity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "lerna>@lerna/publish>@lerna/version>@lerna/github-client>git-url-parse>git-up>parse-url",
|
||||||
|
advisoryUrl: "https://github.com/advisories/GHSA-j9fq-vwqv-2fm2",
|
||||||
|
justification: "dependency of lerna; moderate severity"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user