Compare commits

..

48 Commits

Author SHA1 Message Date
Sampark Sharma 2d3c79e6fe Address review comments 2022-12-12 12:18:07 +00:00
Sampark Sharma e7e19845ca Update packages/cache/src/internal/cacheHttpClient.ts
Co-authored-by: Bishal Prasad <bishal-pdmsft@github.com>
2022-12-12 17:44:34 +05:30
Sampark Sharma cad074ceef Add better comments 2022-12-12 10:58:58 +00:00
Sampark Sharma d7ae8cd1ef Fix tests 2022-12-12 07:51:54 +00:00
Sampark Sharma 6bc5dc5a23 Fix test 2022-12-12 07:25:36 +00:00
Sampark Sharma bbf5659dfa Fix test 2022-12-12 07:04:15 +00:00
Sampark Sharma d175a181a0 Add end to end test for cache using bsd on windows
and address review comments
2022-12-12 06:53:11 +00:00
Sampark Sharma 0690c10515 Fix test 2022-12-09 11:47:00 +00:00
Sampark Sharma 0c23c38c68 Add debug logging for gzip fall back 2022-12-09 11:10:28 +00:00
Sampark Sharma 7a532d03f4 Reconfigure catch block 2022-12-09 11:10:18 +00:00
Sampark Sharma d31c2dd88d Fix issues 2022-12-09 11:09:54 +00:00
Sampark Sharma cb3dc49fec Merge pull request #1249 from actions/phantsure/gzip-fallback
Add fallback to gzip compression if cache not found
2022-12-08 10:59:17 +05:30
Sampark Sharma 27f9a7d461 Revert Address review comments 2022-12-07 08:41:56 +00:00
Sampark Sharma d79a09bc0e Address review comments 2022-12-07 08:27:08 +00:00
Sampark Sharma d1094e1523 Add test 2022-12-07 07:39:41 +00:00
Sampark Sharma c0085d7739 Fix test 2022-12-06 11:52:46 +00:00
Sampark Sharma 1dae855746 Add fallback to gzip compression if cache not found 2022-12-06 11:38:17 +00:00
Sampark Sharma de8fda6976 Merge pull request #1244 from actions/phantsure/release-beta-1
Update for beta release of cache package
2022-12-05 13:01:30 +05:30
Sampark Sharma 61e630822a Fix audit issues 2022-12-05 06:09:05 +00:00
Sampark Sharma c207fbd5db Update for beta release 2022-12-01 10:08:48 +00:00
Sampark Sharma 785599dd2e Merge pull request #1237 from actions/pdotl/win-bsdtar-zstd
Bsdtar + zstd fallback to prevent zstd hanging issue on windows
2022-12-01 12:14:55 +05:30
Sampark Sharma 8595831452 Fix test 2022-11-30 10:37:32 +00:00
Sampark Sharma afbc5c0a9e Add await to async function calls 2022-11-30 06:16:19 +00:00
Sampark Sharma 424ae62ee7 Fix tar test 2022-11-30 06:05:34 +00:00
Sampark Sharma 2e5a517460 Fix test 2022-11-29 12:16:17 +00:00
Sampark Sharma 34f0143be2 Address review comments 2022-11-29 10:35:22 +00:00
Sampark Sharma 0fd856d0a0 Refactor code 2022-11-28 10:24:40 +00:00
Sampark Sharma 0822441ee0 Fix lint test 2022-11-23 11:51:46 +00:00
Sampark Sharma 187781e273 Fix tests 2022-11-23 11:40:11 +00:00
Sampark Sharma 1f3371766a Add new tests 2022-11-23 11:20:24 +00:00
Sampark Sharma 39b7a86b23 Fix old tests 2022-11-23 07:58:46 +00:00
Sampark Sharma 2f73afa843 Separate args 2022-11-23 07:39:15 +00:00
Sampark Sharma ffde3e4bd5 Fix test 2022-11-22 07:33:01 +00:00
Sampark Sharma 32f538163d Fix windows test 2022-11-21 12:51:07 +00:00
Sampark Sharma 32b95825ba Add windows bsdtar test 2022-11-21 12:19:44 +00:00
Sampark Sharma 54eb9b8055 Address some comments and correct compression commands 2022-11-21 12:05:03 +00:00
Lovepreet Singh f9dfb05bd2 Temporarily remove thhe condition that prevents zstd usage on windows unless with GNUtar 2022-11-17 12:13:49 +00:00
Lovepreet Singh b3bd482c0f Fix windows gnutar test case 2022-11-17 09:46:01 +00:00
Lovepreet Singh 4fa5b7d133 Fix lint issues 2022-11-17 09:12:53 +00:00
Lovepreet Singh ea9856079f Fix tar tests 2022-11-17 08:53:46 +00:00
Sampark Sharma caadeee090 Merge pull request #1239 from actions/phantsure/gnutar_windows
Add GNUtar as default on windows
2022-11-17 13:12:02 +05:30
Sampark Sharma 964682b5d4 Fix test 2022-11-17 07:34:07 +00:00
Sampark Sharma 6f7397feb6 Add GNUtar as default on windows 2022-11-17 07:26:52 +00:00
Lovepreet Singh 5f89653f1b Fix order of args for tar 2022-11-17 06:22:13 +00:00
Lovepreet Singh e9e146bbf8 Add -v option for testing 2022-11-16 21:04:25 +00:00
Lovepreet Singh 27bf8304ea Fix tar operations 2022-11-16 20:50:04 +00:00
Lovepreet Singh db3517fe3b bsd + zstd fallback implementation 2022-11-16 20:21:40 +00:00
Lovepreet Singh 6349c3ca3a bsd + zstd fallback implementation 2022-11-16 20:18:31 +00:00
66 changed files with 2544 additions and 3805 deletions
+9 -9
View File
@@ -22,12 +22,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 12.x
uses: actions/setup-node@v3 uses: actions/setup-node@v1
with: with:
node-version: 16.x node-version: 12.x
# In order to upload & download artifacts from a shell script, certain env variables need to be set that are only available in the # In order to upload & download artifacts 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 # node context. This runs a local action that gets and sets the necessary env variables that are needed
@@ -55,16 +55,16 @@ jobs:
- name: Create files that will be uploaded - name: Create files that will be uploaded
run: | run: |
mkdir artifact-path mkdir artifact-path
echo '${{ env.non-gzip-artifact-content }}' > artifact-path/world.txt echo ${{ env.non-gzip-artifact-content }} > artifact-path/world.txt
echo '${{ env.gzip-artifact-content }}' > artifact-path/gzip.txt echo ${{ env.gzip-artifact-content }} > artifact-path/gzip.txt
touch artifact-path/empty.txt touch artifact-path/empty.txt
# We're using node -e to call the functions directly available in the @actions/artifact package # We're using node -e to call the functions directly available in the @actions/artifact package
- name: Upload artifacts using uploadArtifact() - name: Upload artifacts using uploadArtifact()
run: | run: |
node -e "Promise.resolve(require('./packages/artifact/lib/artifact-client').create().uploadArtifact('my-artifact-1',['artifact-path/world.txt'], process.argv[1]))" "${{ github.workspace }}" node -e "Promise.resolve(require('./packages/artifact/lib/artifact-client').create().uploadArtifact('my-artifact-1',['artifact-path/world.txt'], '${{ github.workspace }}'))"
node -e "Promise.resolve(require('./packages/artifact/lib/artifact-client').create().uploadArtifact('my-artifact-2',['artifact-path/gzip.txt'], process.argv[1]))" "${{ github.workspace }}" node -e "Promise.resolve(require('./packages/artifact/lib/artifact-client').create().uploadArtifact('my-artifact-2',['artifact-path/gzip.txt'], '${{ github.workspace }}'))"
node -e "Promise.resolve(require('./packages/artifact/lib/artifact-client').create().uploadArtifact('my-artifact-3',['artifact-path/empty.txt'], process.argv[1]))" "${{ github.workspace }}" node -e "Promise.resolve(require('./packages/artifact/lib/artifact-client').create().uploadArtifact('my-artifact-3',['artifact-path/empty.txt'], '${{ github.workspace }}'))"
- name: Download artifacts using downloadArtifact() - name: Download artifacts using downloadArtifact()
run: | run: |
+7 -6
View File
@@ -18,12 +18,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 12.x
uses: actions/setup-node@v3 uses: actions/setup-node@v1
with: with:
node-version: 16.x node-version: 12.x
- name: npm install - name: npm install
run: npm install run: npm install
@@ -31,8 +31,9 @@ jobs:
- name: Bootstrap - name: Bootstrap
run: npm run bootstrap run: npm run bootstrap
- name: audit tools (without allow-list) - name: audit tools
run: npm audit --audit-level=moderate # `|| npm audit` to pretty-print the output if vulnerabilies are found after filtering.
run: npm audit --audit-level=moderate --json | scripts/audit-allow-list || npm audit --audit-level=moderate
- name: audit packages - name: audit packages
run: npm run audit-all run: npm run audit-all
+4 -4
View File
@@ -22,12 +22,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 12.x
uses: actions/setup-node@v3 uses: actions/setup-node@v1
with: with:
node-version: 16.x 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 # 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 # node context. This runs a local action that gets and sets the necessary env variables that are needed
+1
View File
@@ -78,6 +78,7 @@ jobs:
run: | run: |
rm -rf test-cache rm -rf test-cache
rm -rf ~/test-cache rm -rf ~/test-cache
rm -f cache.tar
- name: Restore cache using restoreCache() with Azure SDK - name: Restore cache using restoreCache() with Azure SDK
run: | run: |
+1 -1
View File
@@ -20,7 +20,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
+6 -6
View File
@@ -13,15 +13,15 @@ jobs:
steps: steps:
- name: setup repo - name: setup repo
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: verify package exists - name: verify package exists
run: ls packages/${{ github.event.inputs.package }} run: ls packages/${{ github.event.inputs.package }}
- name: Set Node.js 16.x - name: Set Node.js 12.x
uses: actions/setup-node@v3 uses: actions/setup-node@v1
with: with:
node-version: 16.x node-version: 12.x
- name: npm install - name: npm install
run: npm install run: npm install
@@ -40,7 +40,7 @@ jobs:
working-directory: packages/${{ github.event.inputs.package }} working-directory: packages/${{ github.event.inputs.package }}
- name: upload artifact - name: upload artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v2
with: with:
name: ${{ github.event.inputs.package }} name: ${{ github.event.inputs.package }}
path: packages/${{ github.event.inputs.package }}/*.tgz path: packages/${{ github.event.inputs.package }}/*.tgz
@@ -52,7 +52,7 @@ jobs:
steps: steps:
- name: download artifact - name: download artifact
uses: actions/download-artifact@v3 uses: actions/download-artifact@v2
with: with:
name: ${{ github.event.inputs.package }} name: ${{ github.event.inputs.package }}
+5 -5
View File
@@ -23,12 +23,12 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Set Node.js 16.x - name: Set Node.js 12.x
uses: actions/setup-node@v3 uses: actions/setup-node@v1
with: with:
node-version: 16.x node-version: 12.x
- name: npm install - name: npm install
run: npm install run: npm install
@@ -40,7 +40,7 @@ jobs:
run: npm run build run: npm run build
- name: npm test - name: npm test
run: npm test -- --runInBand run: npm test
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
+2 -2
View File
@@ -9,7 +9,7 @@ jobs:
if: ${{ github.repository_owner == 'actions' }} if: ${{ github.repository_owner == 'actions' }}
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Update Octokit - name: Update Octokit
working-directory: packages/github working-directory: packages/github
run: | run: |
@@ -30,7 +30,7 @@ jobs:
fi fi
- name: Create PR - name: Create PR
if: ${{steps.status.outputs.createPR}} if: ${{steps.status.outputs.createPR}}
uses: actions/github-script@v6 uses: actions/github-script@v2
with: with:
github-token: ${{secrets.GITHUB_TOKEN}} github-token: ${{secrets.GITHUB_TOKEN}}
script: | script: |
+1 -1
View File
@@ -32,7 +32,7 @@ jobs:
os: [ubuntu-16.04, windows-2019] os: [ubuntu-16.04, windows-2019]
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
actions: actions:
- uses: actions/setup-node@v3 - uses: actions/setup-node@v1
with: with:
version: ${{matrix.node}} version: ${{matrix.node}}
- run: | - run: |
+1 -15
View File
@@ -50,18 +50,7 @@ function setSecret(secret: string): void {}
Now, future logs containing BAR will be masked. E.g. running `echo "Hello FOO BAR World"` will now print `Hello FOO **** World`. Now, future logs containing BAR will be masked. E.g. running `echo "Hello FOO BAR World"` will now print `Hello FOO **** World`.
**WARNING** The add-mask and setSecret commands only support single-line **WARNING** The add-mask and setSecret commands only support single line secrets. To register a multiline secrets you must register each line individually otherwise it will not be masked.
secrets or multi-line secrets that have been escaped. `@actions/core`
`setSecret` will escape the string you provide by default. When an escaped
multi-line string is provided the whole string and each of its lines
individually will be masked. For example you can mask `first\nsecond\r\nthird`
using:
```sh
echo "::add-mask::first%0Asecond%0D%0Athird"
```
This will mask `first%0Asecond%0D%0Athird`, `first`, `second` and `third`.
**WARNING** Do **not** mask short values if you can avoid it, it could render your output unreadable (and future steps' output as well). **WARNING** Do **not** mask short values if you can avoid it, it could render your output unreadable (and future steps' output as well).
For example, if you mask the letter `l`, running `echo "Hello FOO BAR World"` will now print `He*********o FOO BAR Wor****d` For example, if you mask the letter `l`, running `echo "Hello FOO BAR World"` will now print `He*********o FOO BAR Wor****d`
@@ -111,12 +100,9 @@ There are several commands to emit different levels of log output:
| log level | example usage | | log level | example usage |
|---|---| |---|---|
| [debug](action-debugging.md) | `echo "::debug::My debug message"` | | [debug](action-debugging.md) | `echo "::debug::My debug message"` |
| notice | `echo "::notice::My notice message"` |
| warning | `echo "::warning::My warning message"` | | warning | `echo "::warning::My warning message"` |
| error | `echo "::error::My error message"` | | error | `echo "::error::My error message"` |
Additional syntax options are described at [the workflow command documentation](https://docs.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message).
### Command Echoing ### Command Echoing
By default, the echoing of commands to stdout only occurs if [Step Debugging is enabled](./action-debugging.md#How-to-Access-Step-Debug-Logs) By default, the echoing of commands to stdout only occurs if [Step Debugging is enabled](./action-debugging.md#How-to-Access-Step-Debug-Logs)
+1 -1
View File
@@ -18,7 +18,7 @@ e.g. To use https://github.com/actions/setup-node, users will author:
```yaml ```yaml
steps: steps:
using: actions/setup-node@v3 using: actions/setup-node@v1
``` ```
# Define Metadata # Define Metadata
+1646 -2808
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -15,7 +15,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"@types/node": "^16.18.1", "@types/node": "^12.20.13",
"@types/signale": "^1.4.1", "@types/signale": "^1.4.1",
"@typescript-eslint/parser": "^4.0.0", "@typescript-eslint/parser": "^4.0.0",
"concurrently": "^6.1.0", "concurrently": "^6.1.0",
-4
View File
@@ -90,7 +90,3 @@
### 1.1.0 ### 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) - Add `x-actions-results-crc64` and `x-actions-results-md5` checksum headers on upload [#1063](https://github.com/actions/toolkit/pull/1063)
### 1.1.1
- Fixed a bug in Node16 where if an HTTP download finished too quickly (<1ms, e.g. when it's mocked) we attempt to delete a temp file that has not been created yet [#1278](https://github.com/actions/toolkit/pull/1278/commits/b9de68a590daf37c6747e38d3cb4f1dd2cfb791c)
+13 -88
View File
@@ -6,28 +6,13 @@ import {promises as fs} from 'fs'
import {createGZipFileOnDisk} from '../src/internal/upload-gzip' import {createGZipFileOnDisk} from '../src/internal/upload-gzip'
const root = path.join(__dirname, '_temp', 'upload-gzip') const root = path.join(__dirname, '_temp', 'upload-gzip')
const tempGzFilePath = path.join(root, 'file.gz') const tempGzipFilePath = path.join(root, 'file1.gzip')
const tempGzipFilePath = path.join(root, 'file.gzip') const tempZipFilePath = path.join(root, 'file2.zip')
const tempTgzFilePath = path.join(root, 'file.tgz') const tempTarlzFilePath = path.join(root, 'file3.tar.lz')
const tempTazFilePath = path.join(root, 'file.taz') const tempGzFilePath = path.join(root, 'file4.tar.gz')
const tempZFilePath = path.join(root, 'file.Z') const tempBz2FilePath = path.join(root, 'file5.tar.bz2')
const tempTaZFilePath = path.join(root, 'file.taZ') const temp7zFilePath = path.join(root, 'file6.7z')
const tempBz2FilePath = path.join(root, 'file.bz2') const tempNormalFilePath = path.join(root, 'file6.txt')
const tempTbzFilePath = path.join(root, 'file.tbz')
const tempTbz2FilePath = path.join(root, 'file.tbz2')
const tempTz2FilePath = path.join(root, 'file.tz2')
const tempLzFilePath = path.join(root, 'file.lz')
const tempLzmaFilePath = path.join(root, 'file.lzma')
const tempTlzFilePath = path.join(root, 'file.tlz')
const tempLzoFilePath = path.join(root, 'file.lzo')
const tempXzFilePath = path.join(root, 'file.xz')
const tempTxzFilePath = path.join(root, 'file.txz')
const tempZstFilePath = path.join(root, 'file.zst')
const tempZstdFilePath = path.join(root, 'file.zstd')
const tempTzstFilePath = path.join(root, 'file.tzst')
const tempZipFilePath = path.join(root, 'file.zip')
const temp7zFilePath = path.join(root, 'file.7z')
const tempNormalFilePath = path.join(root, 'file.txt')
jest.mock('../src/internal/config-variables') jest.mock('../src/internal/config-variables')
@@ -42,26 +27,11 @@ beforeAll(async () => {
// clear temp directory and create files that will be "uploaded" // clear temp directory and create files that will be "uploaded"
await io.rmRF(root) await io.rmRF(root)
await fs.mkdir(path.join(root)) await fs.mkdir(path.join(root))
await fs.writeFile(tempGzFilePath, 'a file with a .gz file extension')
await fs.writeFile(tempGzipFilePath, 'a file with a .gzip file extension') await fs.writeFile(tempGzipFilePath, 'a file with a .gzip file extension')
await fs.writeFile(tempTgzFilePath, 'a file with a .tgz file extension')
await fs.writeFile(tempTazFilePath, 'a file with a .taz file extension')
await fs.writeFile(tempZFilePath, 'a file with a .Z file extension')
await fs.writeFile(tempTaZFilePath, 'a file with a .taZ file extension')
await fs.writeFile(tempBz2FilePath, 'a file with a .bz2 file extension')
await fs.writeFile(tempTbzFilePath, 'a file with a .tbz file extension')
await fs.writeFile(tempTbz2FilePath, 'a file with a .tbz2 file extension')
await fs.writeFile(tempTz2FilePath, 'a file with a .tz2 file extension')
await fs.writeFile(tempLzFilePath, 'a file with a .lz file extension')
await fs.writeFile(tempLzmaFilePath, 'a file with a .lzma file extension')
await fs.writeFile(tempTlzFilePath, 'a file with a .tlz file extension')
await fs.writeFile(tempLzoFilePath, 'a file with a .lzo file extension')
await fs.writeFile(tempXzFilePath, 'a file with a .xz file extension')
await fs.writeFile(tempTxzFilePath, 'a file with a .txz file extension')
await fs.writeFile(tempZstFilePath, 'a file with a .zst file extension')
await fs.writeFile(tempZstdFilePath, 'a file with a .zstd file extension')
await fs.writeFile(tempTzstFilePath, 'a file with a .tzst file extension')
await fs.writeFile(tempZipFilePath, 'a file with a .zip file extension') await fs.writeFile(tempZipFilePath, 'a file with a .zip file extension')
await fs.writeFile(tempTarlzFilePath, 'a file with a tar.lz file extension')
await fs.writeFile(tempGzFilePath, 'a file with a gz file file extension')
await fs.writeFile(tempBz2FilePath, 'a file with a .bz2 file extension')
await fs.writeFile(temp7zFilePath, 'a file with a .7z file extension') await fs.writeFile(temp7zFilePath, 'a file with a .7z file extension')
await fs.writeFile(tempNormalFilePath, 'a file with a .txt file extension') await fs.writeFile(tempNormalFilePath, 'a file with a .txt file extension')
}) })
@@ -70,66 +40,21 @@ test('Number.MAX_SAFE_INTEGER is returned when an existing compressed file is us
// create temporary file // create temporary file
const tempFile = await tmp.file() const tempFile = await tmp.file()
expect(await createGZipFileOnDisk(tempGzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempGzipFilePath, tempFile.path)).toEqual( expect(await createGZipFileOnDisk(tempGzipFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER Number.MAX_SAFE_INTEGER
) )
expect(await createGZipFileOnDisk(tempTgzFilePath, tempFile.path)).toEqual( expect(await createGZipFileOnDisk(tempZipFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER Number.MAX_SAFE_INTEGER
) )
expect(await createGZipFileOnDisk(tempTazFilePath, tempFile.path)).toEqual( expect(await createGZipFileOnDisk(tempTarlzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER Number.MAX_SAFE_INTEGER
) )
expect(await createGZipFileOnDisk(tempZFilePath, tempFile.path)).toEqual( expect(await createGZipFileOnDisk(tempGzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempTaZFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER Number.MAX_SAFE_INTEGER
) )
expect(await createGZipFileOnDisk(tempBz2FilePath, tempFile.path)).toEqual( expect(await createGZipFileOnDisk(tempBz2FilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER Number.MAX_SAFE_INTEGER
) )
expect(await createGZipFileOnDisk(tempTbzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempTbz2FilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempTz2FilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempLzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempLzmaFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempTlzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempLzoFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempXzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempTxzFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempZstFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempZstdFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempTzstFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(tempZipFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER
)
expect(await createGZipFileOnDisk(temp7zFilePath, tempFile.path)).toEqual( expect(await createGZipFileOnDisk(temp7zFilePath, tempFile.path)).toEqual(
Number.MAX_SAFE_INTEGER Number.MAX_SAFE_INTEGER
) )
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "@actions/artifact", "name": "@actions/artifact",
"version": "1.1.1", "version": "1.1.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/artifact", "name": "@actions/artifact",
"version": "1.1.1", "version": "1.1.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.9.1", "@actions/core": "^1.9.1",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/artifact", "name": "@actions/artifact",
"version": "1.1.1", "version": "1.1.0",
"preview": true, "preview": true,
"description": "Actions artifact lib", "description": "Actions artifact lib",
"keywords": [ "keywords": [
@@ -203,7 +203,7 @@ Note: The size of downloaded zips can differ significantly from the reported siz
await createDirectoriesForArtifact( await createDirectoriesForArtifact(
downloadSpecification.directoryStructure downloadSpecification.directoryStructure
) )
core.info('Directory structure has been set up for the artifact') core.info('Directory structure has been setup for the artifact')
await createEmptyFilesForArtifact( await createEmptyFilesForArtifact(
downloadSpecification.emptyFilesToCreate downloadSpecification.emptyFilesToCreate
) )
@@ -219,13 +219,6 @@ export class DownloadHttpClient {
fileDownloadPath: string fileDownloadPath: string
): Promise<void> => { ): Promise<void> => {
destinationStream.close() destinationStream.close()
// await until file is created at downloadpath; node15 and up fs.createWriteStream had not created a file yet
await new Promise<void>(resolve => {
destinationStream.on('close', resolve)
if (destinationStream.writableFinished) {
resolve()
}
})
await rmFile(fileDownloadPath) await rmFile(fileDownloadPath)
destinationStream = fs.createWriteStream(fileDownloadPath) destinationStream = fs.createWriteStream(fileDownloadPath)
} }
@@ -311,7 +304,7 @@ export class DownloadHttpClient {
const gunzip = zlib.createGunzip() const gunzip = zlib.createGunzip()
response.message response.message
.on('error', error => { .on('error', error => {
core.info( core.error(
`An error occurred while attempting to read the response stream` `An error occurred while attempting to read the response stream`
) )
gunzip.close() gunzip.close()
@@ -320,7 +313,7 @@ export class DownloadHttpClient {
}) })
.pipe(gunzip) .pipe(gunzip)
.on('error', error => { .on('error', error => {
core.info( core.error(
`An error occurred while attempting to decompress the response stream` `An error occurred while attempting to decompress the response stream`
) )
destinationStream.close() destinationStream.close()
@@ -331,7 +324,7 @@ export class DownloadHttpClient {
resolve() resolve()
}) })
.on('error', error => { .on('error', error => {
core.info( core.error(
`An error occurred while writing a downloaded file to ${destinationStream.path}` `An error occurred while writing a downloaded file to ${destinationStream.path}`
) )
reject(error) reject(error)
@@ -339,7 +332,7 @@ export class DownloadHttpClient {
} else { } else {
response.message response.message
.on('error', error => { .on('error', error => {
core.info( core.error(
`An error occurred while attempting to read the response stream` `An error occurred while attempting to read the response stream`
) )
destinationStream.close() destinationStream.close()
@@ -350,7 +343,7 @@ export class DownloadHttpClient {
resolve() resolve()
}) })
.on('error', error => { .on('error', error => {
core.info( core.error(
`An error occurred while writing a downloaded file to ${destinationStream.path}` `An error occurred while writing a downloaded file to ${destinationStream.path}`
) )
reject(error) reject(error)
+7 -22
View File
@@ -9,27 +9,12 @@ const stat = promisify(fs.stat)
* If any of these types of files are encountered then on-disk gzip creation will be skipped and the original file will be uploaded as-is * If any of these types of files are encountered then on-disk gzip creation will be skipped and the original file will be uploaded as-is
*/ */
const gzipExemptFileExtensions = [ const gzipExemptFileExtensions = [
'.gz', // GZIP '.gzip',
'.gzip', // GZIP '.zip',
'.tgz', // GZIP '.tar.lz',
'.taz', // GZIP '.tar.gz',
'.Z', // COMPRESS '.tar.bz2',
'.taZ', // COMPRESS '.7z'
'.bz2', // BZIP2
'.tbz', // BZIP2
'.tbz2', // BZIP2
'.tz2', // BZIP2
'.lz', // LZIP
'.lzma', // LZMA
'.tlz', // LZMA
'.lzo', // LZOP
'.xz', // XZ
'.txz', // XZ
'.zst', // ZSTD
'.zstd', // ZSTD
'.tzst', // ZSTD
'.zip', // ZIP
'.7z' // 7ZIP
] ]
/** /**
@@ -62,7 +47,7 @@ export async function createGZipFileOnDisk(
outputStream.on('error', error => { outputStream.on('error', error => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(error) console.log(error)
reject(error) reject
}) })
}) })
} }
@@ -25,7 +25,7 @@ export function getUploadSpecification(
if (!fs.existsSync(rootDirectory)) { if (!fs.existsSync(rootDirectory)) {
throw new Error(`Provided rootDirectory ${rootDirectory} does not exist`) throw new Error(`Provided rootDirectory ${rootDirectory} does not exist`)
} }
if (!fs.statSync(rootDirectory).isDirectory()) { if (!fs.lstatSync(rootDirectory).isDirectory()) {
throw new Error( throw new Error(
`Provided rootDirectory ${rootDirectory} is not a valid directory` `Provided rootDirectory ${rootDirectory} is not a valid directory`
) )
@@ -57,7 +57,7 @@ export function getUploadSpecification(
if (!fs.existsSync(file)) { if (!fs.existsSync(file)) {
throw new Error(`File ${file} does not exist`) throw new Error(`File ${file} does not exist`)
} }
if (!fs.statSync(file).isDirectory()) { if (!fs.lstatSync(file).isDirectory()) {
// Normalize and resolve, this allows for either absolute or relative paths to be used // Normalize and resolve, this allows for either absolute or relative paths to be used
file = normalize(file) file = normalize(file)
file = resolve(file) file = resolve(file)
+2 -4
View File
@@ -44,8 +44,6 @@ const cacheKey = await cache.restoreCache(paths, key, restoreKeys)
##### Cache segment restore timeout ##### Cache segment restore timeout
A cache gets downloaded in multiple segments of fixed sizes (now `128MB` to fail-fast, previously `1GB` for a `32-bit` runner and `2GB` for a `64-bit` runner were used). 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. 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 10 minutes (starting `v3.2.1` and higher, previously 60 minutes in versions between `v.3.0.4` and `v3.2.0`, both included) 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.
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.
+2 -68
View File
@@ -5,158 +5,92 @@
- Initial release - Initial release
### 0.2.0 ### 0.2.0
- Fixes issues with the zstd compression algorithm on Windows and Ubuntu 16.04 [#469](https://github.com/actions/toolkit/pull/469) - Fixes issues with the zstd compression algorithm on Windows and Ubuntu 16.04 [#469](https://github.com/actions/toolkit/pull/469)
### 0.2.1 ### 0.2.1
- Fix to await async function getCompressionMethod - Fix to await async function getCompressionMethod
### 1.0.0 ### 1.0.0
- Downloads Azure-hosted caches using the Azure SDK for speed and reliability - Downloads Azure-hosted caches using the Azure SDK for speed and reliability
- Displays download progress - Displays download progress
- Includes changes that break compatibility with earlier versions, including: - Includes changes that break compatibility with earlier versions, including:
- `retry`, `retryTypedResponse`, and `retryHttpClientResponse` moved from `cacheHttpClient` to `requestUtils` - `retry`, `retryTypedResponse`, and `retryHttpClientResponse` moved from `cacheHttpClient` to `requestUtils`
### 1.0.1 ### 1.0.1
- Fix bug in downloading large files (> 2 GBs) with the Azure SDK - Fix bug in downloading large files (> 2 GBs) with the Azure SDK
### 1.0.2 ### 1.0.2
- Use posix archive format to add support for some tools - Use posix archive format to add support for some tools
### 1.0.3 ### 1.0.3
- Use http-client v1.0.9 - Use http-client v1.0.9
- Fixes error handling so retries are not attempted on non-retryable errors (409 Conflict, for example) - Fixes error handling so retries are not attempted on non-retryable errors (409 Conflict, for example)
- Adds 5 second delay between retry attempts - Adds 5 second delay between retry attempts
### 1.0.4 ### 1.0.4
- Use @actions/core v1.2.6 - Use @actions/core v1.2.6
- Fixes uploadChunk to throw an error if any unsuccessful response code is received - Fixes uploadChunk to throw an error if any unsuccessful response code is received
### 1.0.5 ### 1.0.5
- Fix to ensure Windows cache paths get resolved correctly - Fix to ensure Windows cache paths get resolved correctly
### 1.0.6 ### 1.0.6
- Make caching more verbose [#650](https://github.com/actions/toolkit/pull/650) - Make caching more verbose [#650](https://github.com/actions/toolkit/pull/650)
- Use GNU tar on macOS if available [#701](https://github.com/actions/toolkit/pull/701) - Use GNU tar on macOS if available [#701](https://github.com/actions/toolkit/pull/701)
### 1.0.7 ### 1.0.7
- Fixes permissions issue extracting archives with GNU tar on macOS ([issue](https://github.com/actions/cache/issues/527)) - Fixes permissions issue extracting archives with GNU tar on macOS ([issue](https://github.com/actions/cache/issues/527))
### 1.0.8 ### 1.0.8
- Increase the allowed artifact cache size from 5GB to 10GB ([issue](https://github.com/actions/cache/discussions/497)) - Increase the allowed artifact cache size from 5GB to 10GB ([issue](https://github.com/actions/cache/discussions/497))
### 1.0.9 ### 1.0.9
- Use @azure/ms-rest-js v2.6.0
- Use @azure/ms-rest-js v2.6.0 - Use @azure/storage-blob v12.8.0
- Use @azure/storage-blob v12.8.0
### 1.0.10 ### 1.0.10
- Update `lockfileVersion` to `v2` in `package-lock.json [#1022](https://github.com/actions/toolkit/pull/1022) - Update `lockfileVersion` to `v2` in `package-lock.json [#1022](https://github.com/actions/toolkit/pull/1022)
### 1.0.11 ### 1.0.11
- Fix file downloads > 2GB([issue](https://github.com/actions/cache/issues/773)) - Fix file downloads > 2GB([issue](https://github.com/actions/cache/issues/773))
### 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 ### 2.0.3
- Update to v2.0.0 of `@actions/http-client` - Update to v2.0.0 of `@actions/http-client`
### 2.0.4 ### 2.0.4
- Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087) - Update to v2.0.1 of `@actions/http-client` [#1087](https://github.com/actions/toolkit/pull/1087)
### 2.0.5 ### 2.0.5
- Fix to avoid saving empty cache when no files are available for caching. ([issue](https://github.com/actions/cache/issues/624)) - Fix to avoid saving empty cache when no files are available for caching. ([issue](https://github.com/actions/cache/issues/624))
### 2.0.6 ### 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)) - 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 ### 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) - 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 ### 3.0.1
- Fix [#833](https://github.com/actions/cache/issues/833) - cache doesn't work with github workspace directory. - 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. - 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 ### 3.0.2
- Added 1 hour timeout for the download stuck issue [#810](https://github.com/actions/cache/issues/810). - Added 1 hour timeout for the download stuck issue [#810](https://github.com/actions/cache/issues/810).
### 3.0.3 ### 3.0.3
- Bug fixes for download stuck issue [#810](https://github.com/actions/cache/issues/810). - Bug fixes for download stuck issue [#810](https://github.com/actions/cache/issues/810).
### 3.0.4 ### 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). - 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. - 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 ### 3.0.5
- Update `@actions/cache` to use `@actions/core@^1.10.0` - Update `@actions/cache` to use `@actions/core@^1.10.0`
### 3.0.6 ### 3.0.6
- Added `@azure/abort-controller` to dependencies to fix compatibility issue with ESM [#1208](https://github.com/actions/toolkit/issues/1208) - Added `@azure/abort-controller` to dependencies to fix compatibility issue with ESM [#1208](https://github.com/actions/toolkit/issues/1208)
### 3.1.0-beta.1 ### 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)) - Update actions/cache on windows to use gnu tar and zstd by default and fallback to bsdtar and zstd if gnu tar is not available. ([issue](https://github.com/actions/cache/issues/984))
### 3.1.0-beta.2
- Added support for fallback to gzip to restore old caches on windows.
### 3.1.0-beta.3
- Bug Fixes for fallback to gzip to restore old caches on windows and bsdtar if gnutar is not available.
### 3.1.0
- Update actions/cache on windows to use gnu tar and zstd by default
- Update actions/cache on windows to fallback to bsdtar and zstd if gnu tar is not available.
- Added support for fallback to gzip to restore old caches on windows.
### 3.1.1
- Reverted changes in 3.1.0 to fix issue with symlink restoration on windows.
- Added support for verbose logging about cache version during cache miss.
### 3.1.2
- Fix issue with symlink restoration on windows.
### 3.1.3
- Fix to prevent from setting MYSYS environement variable globally [#1329](https://github.com/actions/toolkit/pull/1329).
### 3.1.4
- Fix zstd not being used due to `zstd --version` output change in zstd 1.5.4 release. See [#1353](https://github.com/actions/toolkit/pull/1353).
### 3.2.0
- Add `lookupOnly` to cache restore `DownloadOptions`.
### 3.2.1
- Updated @azure/storage-blob to `v12.13.0`
+6 -17
View File
@@ -7,7 +7,7 @@ jest.mock('../src/internal/downloadUtils')
test('getCacheVersion with one path returns version', async () => { test('getCacheVersion with one path returns version', async () => {
const paths = ['node_modules'] const paths = ['node_modules']
const result = getCacheVersion(paths, undefined, true) const result = getCacheVersion(paths)
expect(result).toEqual( expect(result).toEqual(
'b3e0c6cb5ecf32614eeb2997d905b9c297046d7cbf69062698f25b14b4cb0985' 'b3e0c6cb5ecf32614eeb2997d905b9c297046d7cbf69062698f25b14b4cb0985'
) )
@@ -15,7 +15,7 @@ test('getCacheVersion with one path returns version', async () => {
test('getCacheVersion with multiple paths returns version', async () => { test('getCacheVersion with multiple paths returns version', async () => {
const paths = ['node_modules', 'dist'] const paths = ['node_modules', 'dist']
const result = getCacheVersion(paths, undefined, true) const result = getCacheVersion(paths)
expect(result).toEqual( expect(result).toEqual(
'165c3053bc646bf0d4fac17b1f5731caca6fe38e0e464715c0c3c6b6318bf436' '165c3053bc646bf0d4fac17b1f5731caca6fe38e0e464715c0c3c6b6318bf436'
) )
@@ -23,33 +23,22 @@ test('getCacheVersion with multiple paths returns version', async () => {
test('getCacheVersion with zstd compression returns version', async () => { test('getCacheVersion with zstd compression returns version', async () => {
const paths = ['node_modules'] const paths = ['node_modules']
const result = getCacheVersion(paths, CompressionMethod.Zstd, true) const result = getCacheVersion(paths, CompressionMethod.Zstd)
expect(result).toEqual( expect(result).toEqual(
'273877e14fd65d270b87a198edbfa2db5a43de567c9a548d2a2505b408befe24' '273877e14fd65d270b87a198edbfa2db5a43de567c9a548d2a2505b408befe24'
) )
}) })
test('getCacheVersion with gzip compression returns version', async () => { test('getCacheVersion with gzip compression does not change vesion', async () => {
const paths = ['node_modules'] const paths = ['node_modules']
const result = getCacheVersion(paths, CompressionMethod.Gzip, true) const result = getCacheVersion(paths, CompressionMethod.Gzip)
expect(result).toEqual( expect(result).toEqual(
'470e252814dbffc9524891b17cf4e5749b26c1b5026e63dd3f00972db2393117' 'b3e0c6cb5ecf32614eeb2997d905b9c297046d7cbf69062698f25b14b4cb0985'
) )
}) })
test('getCacheVersion with enableCrossOsArchive as false returns version on windows', async () => {
if (process.platform === 'win32') {
const paths = ['node_modules']
const result = getCacheVersion(paths)
expect(result).toEqual(
'2db19d6596dc34f51f0043120148827a264863f5c6ac857569c2af7119bad14e'
)
}
})
test('downloadCache uses http-client for non-Azure URLs', async () => { test('downloadCache uses http-client for non-Azure URLs', async () => {
const downloadCacheHttpClientMock = jest.spyOn( const downloadCacheHttpClientMock = jest.spyOn(
downloadUtils, downloadUtils,
+4 -9
View File
@@ -8,8 +8,7 @@ import {
const useAzureSdk = true const useAzureSdk = true
const downloadConcurrency = 8 const downloadConcurrency = 8
const timeoutInMs = 30000 const timeoutInMs = 30000
const segmentTimeoutInMs = 600000 const segmentTimeoutInMs = 3600000
const lookupOnly = false
const uploadConcurrency = 4 const uploadConcurrency = 4
const uploadChunkSize = 32 * 1024 * 1024 const uploadChunkSize = 32 * 1024 * 1024
@@ -20,8 +19,7 @@ test('getDownloadOptions sets defaults', async () => {
useAzureSdk, useAzureSdk,
downloadConcurrency, downloadConcurrency,
timeoutInMs, timeoutInMs,
segmentTimeoutInMs, segmentTimeoutInMs
lookupOnly
}) })
}) })
@@ -30,8 +28,7 @@ test('getDownloadOptions overrides all settings', async () => {
useAzureSdk: false, useAzureSdk: false,
downloadConcurrency: 14, downloadConcurrency: 14,
timeoutInMs: 20000, timeoutInMs: 20000,
segmentTimeoutInMs: 3600000, segmentTimeoutInMs: 3600000
lookupOnly: true
} }
const actualOptions = getDownloadOptions(expectedOptions) const actualOptions = getDownloadOptions(expectedOptions)
@@ -64,8 +61,7 @@ test('getDownloadOptions overrides download timeout minutes', async () => {
useAzureSdk: false, useAzureSdk: false,
downloadConcurrency: 14, downloadConcurrency: 14,
timeoutInMs: 20000, timeoutInMs: 20000,
segmentTimeoutInMs: 3600000, segmentTimeoutInMs: 3600000
lookupOnly: true
} }
process.env.SEGMENT_DOWNLOAD_TIMEOUT_MINS = '10' process.env.SEGMENT_DOWNLOAD_TIMEOUT_MINS = '10'
const actualOptions = getDownloadOptions(expectedOptions) const actualOptions = getDownloadOptions(expectedOptions)
@@ -76,5 +72,4 @@ test('getDownloadOptions overrides download timeout minutes', async () => {
) )
expect(actualOptions.timeoutInMs).toEqual(expectedOptions.timeoutInMs) expect(actualOptions.timeoutInMs).toEqual(expectedOptions.timeoutInMs)
expect(actualOptions.segmentTimeoutInMs).toEqual(600000) expect(actualOptions.segmentTimeoutInMs).toEqual(600000)
expect(actualOptions.lookupOnly).toEqual(expectedOptions.lookupOnly)
}) })
+78 -42
View File
@@ -142,8 +142,7 @@ test('restore with gzip compressed cache found', async () => {
expect(cacheKey).toBe(key) expect(cacheKey).toBe(key)
expect(getCacheMock).toHaveBeenCalledWith([key], paths, { expect(getCacheMock).toHaveBeenCalledWith([key], paths, {
compressionMethod: compression, compressionMethod: compression
enableCrossOsArchive: false
}) })
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1) expect(createTempDirectoryMock).toHaveBeenCalledTimes(1)
expect(downloadCacheMock).toHaveBeenCalledWith( expect(downloadCacheMock).toHaveBeenCalledWith(
@@ -162,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'
@@ -202,8 +276,7 @@ test('restore with zstd compressed cache found', async () => {
expect(cacheKey).toBe(key) expect(cacheKey).toBe(key)
expect(getCacheMock).toHaveBeenCalledWith([key], paths, { expect(getCacheMock).toHaveBeenCalledWith([key], paths, {
compressionMethod: compression, compressionMethod: compression
enableCrossOsArchive: false
}) })
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1) expect(createTempDirectoryMock).toHaveBeenCalledTimes(1)
expect(downloadCacheMock).toHaveBeenCalledWith( expect(downloadCacheMock).toHaveBeenCalledWith(
@@ -260,8 +333,7 @@ test('restore with cache found for restore key', async () => {
expect(cacheKey).toBe(restoreKey) expect(cacheKey).toBe(restoreKey)
expect(getCacheMock).toHaveBeenCalledWith([key, restoreKey], paths, { expect(getCacheMock).toHaveBeenCalledWith([key, restoreKey], paths, {
compressionMethod: compression, compressionMethod: compression
enableCrossOsArchive: false
}) })
expect(createTempDirectoryMock).toHaveBeenCalledTimes(1) expect(createTempDirectoryMock).toHaveBeenCalledTimes(1)
expect(downloadCacheMock).toHaveBeenCalledWith( expect(downloadCacheMock).toHaveBeenCalledWith(
@@ -276,39 +348,3 @@ test('restore with cache found for restore key', async () => {
expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression) expect(extractTarMock).toHaveBeenCalledWith(archivePath, compression)
expect(getCompressionMock).toHaveBeenCalledTimes(1) expect(getCompressionMock).toHaveBeenCalledTimes(1)
}) })
test('restore with dry run', async () => {
const paths = ['node_modules']
const key = 'node-test'
const options = {lookupOnly: true}
const cacheEntry: ArtifactCacheEntry = {
cacheKey: key,
scope: 'refs/heads/main',
archiveLocation: 'www.actionscache.test/download'
}
const getCacheMock = jest.spyOn(cacheHttpClient, 'getCacheEntry')
getCacheMock.mockImplementation(async () => {
return Promise.resolve(cacheEntry)
})
const createTempDirectoryMock = jest.spyOn(cacheUtils, 'createTempDirectory')
const downloadCacheMock = jest.spyOn(cacheHttpClient, 'downloadCache')
const compression = CompressionMethod.Gzip
const getCompressionMock = jest
.spyOn(cacheUtils, 'getCompressionMethod')
.mockReturnValue(Promise.resolve(compression))
const cacheKey = await restoreCache(paths, key, undefined, options)
expect(cacheKey).toBe(key)
expect(getCompressionMock).toHaveBeenCalledTimes(1)
expect(getCacheMock).toHaveBeenCalledWith([key], paths, {
compressionMethod: compression,
enableCrossOsArchive: false
})
// creating a tempDir and downloading the cache are skipped
expect(createTempDirectoryMock).toHaveBeenCalledTimes(0)
expect(downloadCacheMock).toHaveBeenCalledTimes(0)
})
+3 -9
View File
@@ -209,9 +209,7 @@ test('save with reserve cache failure should fail', async () => {
expect(reserveCacheMock).toHaveBeenCalledTimes(1) expect(reserveCacheMock).toHaveBeenCalledTimes(1)
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, paths, { expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, paths, {
cacheSize: undefined, compressionMethod: compression
compressionMethod: compression,
enableCrossOsArchive: false
}) })
expect(createTarMock).toHaveBeenCalledTimes(1) expect(createTarMock).toHaveBeenCalledTimes(1)
expect(saveCacheMock).toHaveBeenCalledTimes(0) expect(saveCacheMock).toHaveBeenCalledTimes(0)
@@ -255,9 +253,7 @@ test('save with server error should fail', async () => {
expect(reserveCacheMock).toHaveBeenCalledTimes(1) expect(reserveCacheMock).toHaveBeenCalledTimes(1)
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], { expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], {
cacheSize: undefined, compressionMethod: compression
compressionMethod: compression,
enableCrossOsArchive: false
}) })
const archiveFolder = '/foo/bar' const archiveFolder = '/foo/bar'
const archiveFile = path.join(archiveFolder, CacheFilename.Zstd) const archiveFile = path.join(archiveFolder, CacheFilename.Zstd)
@@ -300,9 +296,7 @@ test('save with valid inputs uploads a cache', async () => {
expect(reserveCacheMock).toHaveBeenCalledTimes(1) expect(reserveCacheMock).toHaveBeenCalledTimes(1)
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], { expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], {
cacheSize: undefined, compressionMethod: compression
compressionMethod: compression,
enableCrossOsArchive: false
}) })
const archiveFolder = '/foo/bar' const archiveFolder = '/foo/bar'
const archiveFile = path.join(archiveFolder, CacheFilename.Zstd) const archiveFile = path.join(archiveFolder, CacheFilename.Zstd)
+17 -53
View File
@@ -22,8 +22,6 @@ const IS_MAC = process.platform === 'darwin'
const defaultTarPath = IS_MAC ? 'gtar' : 'tar' const defaultTarPath = IS_MAC ? 'gtar' : 'tar'
const defaultEnv = {MSYS: 'winsymlinks:nativestrict'}
function getTempDir(): string { function getTempDir(): string {
return path.join(__dirname, '_temp', 'tar') return path.join(__dirname, '_temp', 'tar')
} }
@@ -77,10 +75,7 @@ test('zstd extract tar', async () => {
]) ])
.join(' '), .join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
}) })
@@ -104,15 +99,12 @@ test('zstd extract tar with windows BSDtar', async () => {
expect(execMock).toHaveBeenNthCalledWith( expect(execMock).toHaveBeenNthCalledWith(
1, 1,
[ [
'zstd -d --long=30 --force -o', 'zstd -d --long=30 -o',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/') archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
].join(' '), ].join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
expect(execMock).toHaveBeenNthCalledWith( expect(execMock).toHaveBeenNthCalledWith(
@@ -126,10 +118,7 @@ test('zstd extract tar with windows BSDtar', async () => {
workspace?.replace(/\\/g, '/') workspace?.replace(/\\/g, '/')
].join(' '), ].join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
} }
}) })
@@ -161,10 +150,7 @@ test('gzip extract tar', async () => {
.concat(['-z']) .concat(['-z'])
.join(' '), .join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
}) })
@@ -193,10 +179,7 @@ test('gzip extract GNU tar on windows with GNUtar in path', async () => {
'-z' '-z'
].join(' '), ].join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
} }
}) })
@@ -238,8 +221,7 @@ test('zstd create tar', async () => {
.join(' '), .join(' '),
undefined, // args undefined, // args
{ {
cwd: archiveFolder, cwd: archiveFolder
env: expect.objectContaining(defaultEnv)
} }
) )
}) })
@@ -284,22 +266,20 @@ test('zstd create tar with windows BSDtar', async () => {
].join(' '), ].join(' '),
undefined, // args undefined, // args
{ {
cwd: archiveFolder, cwd: archiveFolder
env: expect.objectContaining(defaultEnv)
} }
) )
expect(execMock).toHaveBeenNthCalledWith( expect(execMock).toHaveBeenNthCalledWith(
2, 2,
[ [
'zstd -T0 --long=30 --force -o', 'zstd -T0 --long=30 -o',
CacheFilename.Zstd.replace(/\\/g, '/'), CacheFilename.Zstd.replace(/\\/g, '/'),
TarFilename.replace(/\\/g, '/') TarFilename.replace(/\\/g, '/')
].join(' '), ].join(' '),
undefined, // args undefined, // args
{ {
cwd: archiveFolder, cwd: archiveFolder
env: expect.objectContaining(defaultEnv)
} }
) )
} }
@@ -339,8 +319,7 @@ test('gzip create tar', async () => {
.join(' '), .join(' '),
undefined, // args undefined, // args
{ {
cwd: archiveFolder, cwd: archiveFolder
env: expect.objectContaining(defaultEnv)
} }
) )
}) })
@@ -371,10 +350,7 @@ test('zstd list tar', async () => {
]) ])
.join(' '), .join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
}) })
@@ -394,15 +370,12 @@ test('zstd list tar with windows BSDtar', async () => {
expect(execMock).toHaveBeenNthCalledWith( expect(execMock).toHaveBeenNthCalledWith(
1, 1,
[ [
'zstd -d --long=30 --force -o', 'zstd -d --long=30 -o',
TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), TarFilename.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/') archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
].join(' '), ].join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
expect(execMock).toHaveBeenNthCalledWith( expect(execMock).toHaveBeenNthCalledWith(
@@ -414,10 +387,7 @@ test('zstd list tar with windows BSDtar', async () => {
'-P' '-P'
].join(' '), ].join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
} }
}) })
@@ -445,10 +415,7 @@ test('zstdWithoutLong list tar', async () => {
.concat(['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd']) .concat(['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd'])
.join(' '), .join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
}) })
@@ -474,9 +441,6 @@ test('gzip list tar', async () => {
.concat(['-z']) .concat(['-z'])
.join(' '), .join(' '),
undefined, undefined,
{ {cwd: undefined}
cwd: undefined,
env: expect.objectContaining(defaultEnv)
}
) )
}) })
+106 -101
View File
@@ -1,12 +1,12 @@
{ {
"name": "@actions/cache", "name": "@actions/cache",
"version": "3.2.1", "version": "3.1.0-beta.1",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/cache", "name": "@actions/cache",
"version": "3.2.1", "version": "3.1.0-beta.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.10.0", "@actions/core": "^1.10.0",
@@ -16,14 +16,14 @@
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
"@azure/abort-controller": "^1.1.0", "@azure/abort-controller": "^1.1.0",
"@azure/ms-rest-js": "^2.6.0", "@azure/ms-rest-js": "^2.6.0",
"@azure/storage-blob": "^12.13.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": {
"@types/semver": "^6.0.0", "@types/semver": "^6.0.0",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",
"typescript": "^4.8.0" "typescript": "^3.8.3"
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
@@ -112,27 +112,28 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}, },
"node_modules/@azure/core-http": { "node_modules/@azure/core-http": {
"version": "3.0.1", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-2.2.3.tgz",
"integrity": "sha512-A3x+um3cAPgQe42Lu7Iv/x8/fNjhL/nIoEfqFxfn30EyxK6zC13n+OUxzZBRC0IzQqssqIbt4INf5YG7lYYFtw==", "integrity": "sha512-xr8AeszxP418rI//W38NfJDDr0kbVAPZkURZnZ+Fle+lLWeURjDE5zNIuocA1wUPoKSP8iXc0ApW6nPtbLGswA==",
"dependencies": { "dependencies": {
"@azure/abort-controller": "^1.0.0", "@azure/abort-controller": "^1.0.0",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@azure/core-auth": "^1.3.0", "@azure/core-auth": "^1.3.0",
"@azure/core-tracing": "1.0.0-preview.13", "@azure/core-tracing": "1.0.0-preview.13",
"@azure/core-util": "^1.1.1",
"@azure/logger": "^1.0.0", "@azure/logger": "^1.0.0",
"@types/node-fetch": "^2.5.0", "@types/node-fetch": "^2.5.0",
"@types/tunnel": "^0.0.3", "@types/tunnel": "^0.0.3",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.6",
"process": "^0.11.10", "process": "^0.11.10",
"tough-cookie": "^4.0.0",
"tslib": "^2.2.0", "tslib": "^2.2.0",
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
"uuid": "^8.3.0", "uuid": "^8.3.0",
"xml2js": "^0.5.0" "xml2js": "^0.4.19"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/@azure/core-http/node_modules/form-data": { "node_modules/@azure/core-http/node_modules/form-data": {
@@ -148,10 +149,23 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/@azure/core-http/node_modules/tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
"dependencies": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.1.2"
},
"engines": {
"node": ">=6"
}
},
"node_modules/@azure/core-http/node_modules/tslib": { "node_modules/@azure/core-http/node_modules/tslib": {
"version": "2.5.0", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}, },
"node_modules/@azure/core-http/node_modules/uuid": { "node_modules/@azure/core-http/node_modules/uuid": {
"version": "8.3.2", "version": "8.3.2",
@@ -214,23 +228,6 @@
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}, },
"node_modules/@azure/core-util": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.2.0.tgz",
"integrity": "sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng==",
"dependencies": {
"@azure/abort-controller": "^1.0.0",
"tslib": "^2.2.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@azure/core-util/node_modules/tslib": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
},
"node_modules/@azure/logger": { "node_modules/@azure/logger": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz",
@@ -248,19 +245,19 @@
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}, },
"node_modules/@azure/ms-rest-js": { "node_modules/@azure/ms-rest-js": {
"version": "2.6.6", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.6.6.tgz", "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.6.0.tgz",
"integrity": "sha512-WYIda8VvrkZE68xHgOxUXvjThxNf1nnGPPe0rAljqK5HJHIZ12Pi3YhEDOn3Ge7UnwaaM3eFO0VtAy4nGVI27Q==", "integrity": "sha512-4C5FCtvEzWudblB+h92/TYYPiq7tuElX8icVYToxOdggnYqeec4Se14mjse5miInKtZahiFHdl8lZA/jziEc5g==",
"dependencies": { "dependencies": {
"@azure/core-auth": "^1.1.4", "@azure/core-auth": "^1.1.4",
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"form-data": "^2.5.0", "form-data": "^2.5.0",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.0",
"tough-cookie": "^3.0.1", "tough-cookie": "^3.0.1",
"tslib": "^1.10.0", "tslib": "^1.10.0",
"tunnel": "0.0.6", "tunnel": "0.0.6",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"xml2js": "^0.5.0" "xml2js": "^0.4.19"
} }
}, },
"node_modules/@azure/ms-rest-js/node_modules/uuid": { "node_modules/@azure/ms-rest-js/node_modules/uuid": {
@@ -272,12 +269,12 @@
} }
}, },
"node_modules/@azure/storage-blob": { "node_modules/@azure/storage-blob": {
"version": "12.13.0", "version": "12.8.0",
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.13.0.tgz", "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.8.0.tgz",
"integrity": "sha512-t3Q2lvBMJucgTjQcP5+hvEJMAsJSk0qmAnjDLie2td017IiduZbbC9BOcFfmwzR6y6cJdZOuewLCNFmEx9IrXA==", "integrity": "sha512-c8+Wz19xauW0bGkTCoqZH4dYfbtBniPiGiRQOn1ca6G5jsjr4azwaTk9gwjVY8r3vY2Taf95eivLzipfIfiS4A==",
"dependencies": { "dependencies": {
"@azure/abort-controller": "^1.0.0", "@azure/abort-controller": "^1.0.0",
"@azure/core-http": "^3.0.0", "@azure/core-http": "^2.0.0",
"@azure/core-lro": "^2.2.0", "@azure/core-lro": "^2.2.0",
"@azure/core-paging": "^1.1.1", "@azure/core-paging": "^1.1.1",
"@azure/core-tracing": "1.0.0-preview.13", "@azure/core-tracing": "1.0.0-preview.13",
@@ -286,7 +283,7 @@
"tslib": "^2.2.0" "tslib": "^2.2.0"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/@azure/storage-blob/node_modules/tslib": { "node_modules/@azure/storage-blob/node_modules/tslib": {
@@ -303,14 +300,14 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.14.6", "version": "17.0.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.14.tgz",
"integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==" "integrity": "sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng=="
}, },
"node_modules/@types/node-fetch": { "node_modules/@types/node-fetch": {
"version": "2.6.2", "version": "2.5.12",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz",
"integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==",
"dependencies": { "dependencies": {
"@types/node": "*", "@types/node": "*",
"form-data": "^3.0.0" "form-data": "^3.0.0"
@@ -492,7 +489,7 @@
"node_modules/process": { "node_modules/process": {
"version": "0.11.10", "version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
"engines": { "engines": {
"node": ">= 0.6.0" "node": ">= 0.6.0"
} }
@@ -555,9 +552,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.8.4", "version": "3.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
"dev": true, "dev": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
@@ -567,6 +564,14 @@
"node": ">=4.2.0" "node": ">=4.2.0"
} }
}, },
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/uuid": { "node_modules/uuid": {
"version": "3.4.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
@@ -591,9 +596,9 @@
} }
}, },
"node_modules/xml2js": { "node_modules/xml2js": {
"version": "0.5.0", "version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
"dependencies": { "dependencies": {
"sax": ">=0.6.0", "sax": ">=0.6.0",
"xmlbuilder": "~11.0.0" "xmlbuilder": "~11.0.0"
@@ -695,24 +700,25 @@
} }
}, },
"@azure/core-http": { "@azure/core-http": {
"version": "3.0.1", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@azure/core-http/-/core-http-2.2.3.tgz",
"integrity": "sha512-A3x+um3cAPgQe42Lu7Iv/x8/fNjhL/nIoEfqFxfn30EyxK6zC13n+OUxzZBRC0IzQqssqIbt4INf5YG7lYYFtw==", "integrity": "sha512-xr8AeszxP418rI//W38NfJDDr0kbVAPZkURZnZ+Fle+lLWeURjDE5zNIuocA1wUPoKSP8iXc0ApW6nPtbLGswA==",
"requires": { "requires": {
"@azure/abort-controller": "^1.0.0", "@azure/abort-controller": "^1.0.0",
"@azure/core-asynciterator-polyfill": "^1.0.0",
"@azure/core-auth": "^1.3.0", "@azure/core-auth": "^1.3.0",
"@azure/core-tracing": "1.0.0-preview.13", "@azure/core-tracing": "1.0.0-preview.13",
"@azure/core-util": "^1.1.1",
"@azure/logger": "^1.0.0", "@azure/logger": "^1.0.0",
"@types/node-fetch": "^2.5.0", "@types/node-fetch": "^2.5.0",
"@types/tunnel": "^0.0.3", "@types/tunnel": "^0.0.3",
"form-data": "^4.0.0", "form-data": "^4.0.0",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.6",
"process": "^0.11.10", "process": "^0.11.10",
"tough-cookie": "^4.0.0",
"tslib": "^2.2.0", "tslib": "^2.2.0",
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
"uuid": "^8.3.0", "uuid": "^8.3.0",
"xml2js": "^0.5.0" "xml2js": "^0.4.19"
}, },
"dependencies": { "dependencies": {
"form-data": { "form-data": {
@@ -725,10 +731,20 @@
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
} }
}, },
"tough-cookie": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz",
"integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==",
"requires": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.1.2"
}
},
"tslib": { "tslib": {
"version": "2.5.0", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
}, },
"uuid": { "uuid": {
"version": "8.3.2", "version": "8.3.2",
@@ -787,22 +803,6 @@
} }
} }
}, },
"@azure/core-util": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.2.0.tgz",
"integrity": "sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng==",
"requires": {
"@azure/abort-controller": "^1.0.0",
"tslib": "^2.2.0"
},
"dependencies": {
"tslib": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
}
}
},
"@azure/logger": { "@azure/logger": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz",
@@ -819,19 +819,19 @@
} }
}, },
"@azure/ms-rest-js": { "@azure/ms-rest-js": {
"version": "2.6.6", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.6.6.tgz", "resolved": "https://registry.npmjs.org/@azure/ms-rest-js/-/ms-rest-js-2.6.0.tgz",
"integrity": "sha512-WYIda8VvrkZE68xHgOxUXvjThxNf1nnGPPe0rAljqK5HJHIZ12Pi3YhEDOn3Ge7UnwaaM3eFO0VtAy4nGVI27Q==", "integrity": "sha512-4C5FCtvEzWudblB+h92/TYYPiq7tuElX8icVYToxOdggnYqeec4Se14mjse5miInKtZahiFHdl8lZA/jziEc5g==",
"requires": { "requires": {
"@azure/core-auth": "^1.1.4", "@azure/core-auth": "^1.1.4",
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"form-data": "^2.5.0", "form-data": "^2.5.0",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.0",
"tough-cookie": "^3.0.1", "tough-cookie": "^3.0.1",
"tslib": "^1.10.0", "tslib": "^1.10.0",
"tunnel": "0.0.6", "tunnel": "0.0.6",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"xml2js": "^0.5.0" "xml2js": "^0.4.19"
}, },
"dependencies": { "dependencies": {
"uuid": { "uuid": {
@@ -842,12 +842,12 @@
} }
}, },
"@azure/storage-blob": { "@azure/storage-blob": {
"version": "12.13.0", "version": "12.8.0",
"resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.13.0.tgz", "resolved": "https://registry.npmjs.org/@azure/storage-blob/-/storage-blob-12.8.0.tgz",
"integrity": "sha512-t3Q2lvBMJucgTjQcP5+hvEJMAsJSk0qmAnjDLie2td017IiduZbbC9BOcFfmwzR6y6cJdZOuewLCNFmEx9IrXA==", "integrity": "sha512-c8+Wz19xauW0bGkTCoqZH4dYfbtBniPiGiRQOn1ca6G5jsjr4azwaTk9gwjVY8r3vY2Taf95eivLzipfIfiS4A==",
"requires": { "requires": {
"@azure/abort-controller": "^1.0.0", "@azure/abort-controller": "^1.0.0",
"@azure/core-http": "^3.0.0", "@azure/core-http": "^2.0.0",
"@azure/core-lro": "^2.2.0", "@azure/core-lro": "^2.2.0",
"@azure/core-paging": "^1.1.1", "@azure/core-paging": "^1.1.1",
"@azure/core-tracing": "1.0.0-preview.13", "@azure/core-tracing": "1.0.0-preview.13",
@@ -869,14 +869,14 @@
"integrity": "sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog==" "integrity": "sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog=="
}, },
"@types/node": { "@types/node": {
"version": "18.14.6", "version": "17.0.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.14.tgz",
"integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==" "integrity": "sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng=="
}, },
"@types/node-fetch": { "@types/node-fetch": {
"version": "2.6.2", "version": "2.5.12",
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.12.tgz",
"integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", "integrity": "sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw==",
"requires": { "requires": {
"@types/node": "*", "@types/node": "*",
"form-data": "^3.0.0" "form-data": "^3.0.0"
@@ -1016,7 +1016,7 @@
"process": { "process": {
"version": "0.11.10", "version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
}, },
"psl": { "psl": {
"version": "1.8.0", "version": "1.8.0",
@@ -1064,11 +1064,16 @@
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
}, },
"typescript": { "typescript": {
"version": "4.8.4", "version": "3.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
"dev": true "dev": true
}, },
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"uuid": { "uuid": {
"version": "3.4.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
@@ -1089,9 +1094,9 @@
} }
}, },
"xml2js": { "xml2js": {
"version": "0.5.0", "version": "0.4.23",
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
"integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
"requires": { "requires": {
"sax": ">=0.6.0", "sax": ">=0.6.0",
"xmlbuilder": "~11.0.0" "xmlbuilder": "~11.0.0"
+3 -3
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/cache", "name": "@actions/cache",
"version": "3.2.1", "version": "3.1.0-beta.1",
"preview": true, "preview": true,
"description": "Actions cache lib", "description": "Actions cache lib",
"keywords": [ "keywords": [
@@ -44,13 +44,13 @@
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
"@azure/abort-controller": "^1.1.0", "@azure/abort-controller": "^1.1.0",
"@azure/ms-rest-js": "^2.6.0", "@azure/ms-rest-js": "^2.6.0",
"@azure/storage-blob": "^12.13.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": {
"@types/semver": "^6.0.0", "@types/semver": "^6.0.0",
"@types/uuid": "^3.4.5", "@types/uuid": "^3.4.5",
"typescript": "^4.8.0" "typescript": "^3.8.3"
} }
} }
+27 -17
View File
@@ -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) {
@@ -60,15 +62,13 @@ export function isFeatureAvailable(): boolean {
* @param primaryKey an explicit key for restoring the cache * @param primaryKey an explicit key for restoring the cache
* @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for key * @param restoreKeys an optional ordered list of keys to use for restoring the cache if no cache hit occurred for key
* @param downloadOptions cache download options * @param downloadOptions cache download options
* @param enableCrossOsArchive an optional boolean enabled to restore on windows any cache created on any platform
* @returns string returns the key for the cache hit, otherwise returns undefined * @returns string returns the key for the cache hit, otherwise returns undefined
*/ */
export async function restoreCache( export async function restoreCache(
paths: string[], paths: string[],
primaryKey: string, primaryKey: string,
restoreKeys?: string[], restoreKeys?: string[],
options?: DownloadOptions, options?: DownloadOptions
enableCrossOsArchive = false
): Promise<string | undefined> { ): Promise<string | undefined> {
checkPaths(paths) checkPaths(paths)
@@ -87,22 +87,35 @@ export async function restoreCache(
checkKey(key) checkKey(key)
} }
const compressionMethod = await utils.getCompressionMethod() let cacheEntry: ArtifactCacheEntry | null
let compressionMethod = await utils.getCompressionMethod()
let archivePath = '' let archivePath = ''
try { try {
// path are needed to compute version // path are needed to compute version
const cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, { cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
compressionMethod, compressionMethod
enableCrossOsArchive
}) })
if (!cacheEntry?.archiveLocation) { if (!cacheEntry?.archiveLocation) {
// Cache not found // This is to support the old cache entry created by gzip on windows.
return undefined if (
} process.platform === 'win32' &&
compressionMethod !== CompressionMethod.Gzip
) {
compressionMethod = CompressionMethod.Gzip
cacheEntry = await cacheHttpClient.getCacheEntry(keys, paths, {
compressionMethod
})
if (!cacheEntry?.archiveLocation) {
return undefined
}
if (options?.lookupOnly) { core.debug(
core.info('Lookup only - skipping download') "Couldn't find cache entry with zstd compression, falling back to gzip compression."
return cacheEntry.cacheKey )
} else {
// Cache not found
return undefined
}
} }
archivePath = path.join( archivePath = path.join(
@@ -158,15 +171,13 @@ export async function restoreCache(
* *
* @param paths a list of file paths to be cached * @param paths a list of file paths to be cached
* @param key an explicit key for restoring the cache * @param key an explicit key for restoring the cache
* @param enableCrossOsArchive an optional boolean enabled to save cache on windows which could be restored on any platform
* @param options cache upload options * @param options cache upload options
* @returns number returns cacheId if the cache was saved successfully and throws an error if save fails * @returns number returns cacheId if the cache was saved successfully and throws an error if save fails
*/ */
export async function saveCache( export async function saveCache(
paths: string[], paths: string[],
key: string, key: string,
options?: UploadOptions, options?: UploadOptions
enableCrossOsArchive = false
): Promise<number> { ): Promise<number> {
checkPaths(paths) checkPaths(paths)
checkKey(key) checkKey(key)
@@ -216,7 +227,6 @@ export async function saveCache(
paths, paths,
{ {
compressionMethod, compressionMethod,
enableCrossOsArchive,
cacheSize: archiveFileSize cacheSize: archiveFileSize
} }
) )
+10 -56
View File
@@ -17,8 +17,7 @@ import {
CommitCacheRequest, CommitCacheRequest,
ReserveCacheRequest, ReserveCacheRequest,
ReserveCacheResponse, ReserveCacheResponse,
ITypedResponseWithError, ITypedResponseWithError
ArtifactCacheList
} from './contracts' } from './contracts'
import {downloadCacheHttpClient, downloadCacheStorageSDK} from './downloadUtils' import {downloadCacheHttpClient, downloadCacheStorageSDK} from './downloadUtils'
import { import {
@@ -73,21 +72,13 @@ function createHttpClient(): HttpClient {
export function getCacheVersion( export function getCacheVersion(
paths: string[], paths: string[],
compressionMethod?: CompressionMethod, compressionMethod?: CompressionMethod
enableCrossOsArchive = false
): string { ): string {
const components = paths const components = paths.concat(
!compressionMethod || compressionMethod === CompressionMethod.Gzip
// Add compression method to cache version to restore ? []
// compressed cache as per compression method : [compressionMethod]
if (compressionMethod) { )
components.push(compressionMethod)
}
// Only check for windows platforms if enableCrossOsArchive is false
if (process.platform === 'win32' && !enableCrossOsArchive) {
components.push('windows-only')
}
// Add salt to cache version to support breaking changes in cache entry // Add salt to cache version to support breaking changes in cache entry
components.push(versionSalt) components.push(versionSalt)
@@ -104,11 +95,7 @@ export async function getCacheEntry(
options?: InternalCacheOptions options?: InternalCacheOptions
): Promise<ArtifactCacheEntry | null> { ): Promise<ArtifactCacheEntry | null> {
const httpClient = createHttpClient() const httpClient = createHttpClient()
const version = getCacheVersion( const version = getCacheVersion(paths, options?.compressionMethod)
paths,
options?.compressionMethod,
options?.enableCrossOsArchive
)
const resource = `cache?keys=${encodeURIComponent( const resource = `cache?keys=${encodeURIComponent(
keys.join(',') keys.join(',')
)}&version=${version}` )}&version=${version}`
@@ -116,12 +103,8 @@ export async function getCacheEntry(
const response = await retryTypedResponse('getCacheEntry', async () => const response = await retryTypedResponse('getCacheEntry', async () =>
httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource)) httpClient.getJson<ArtifactCacheEntry>(getCacheApiUrl(resource))
) )
// Cache not found
if (response.statusCode === 204) { if (response.statusCode === 204) {
// List cache for primary key only if cache miss occurs // Cache not found
if (core.isDebug()) {
await printCachesListForDiagnostics(keys[0], httpClient, version)
}
return null return null
} }
if (!isSuccessStatusCode(response.statusCode)) { if (!isSuccessStatusCode(response.statusCode)) {
@@ -141,31 +124,6 @@ export async function getCacheEntry(
return cacheResult return cacheResult
} }
async function printCachesListForDiagnostics(
key: string,
httpClient: HttpClient,
version: string
): Promise<void> {
const resource = `caches?key=${encodeURIComponent(key)}`
const response = await retryTypedResponse('listCache', async () =>
httpClient.getJson<ArtifactCacheList>(getCacheApiUrl(resource))
)
if (response.statusCode === 200) {
const cacheListResult = response.result
const totalCount = cacheListResult?.totalCount
if (totalCount && totalCount > 0) {
core.debug(
`No matching cache found for cache key '${key}', version '${version} and scope ${process.env['GITHUB_REF']}. There exist one or more cache(s) with similar key but they have different version or scope. See more info on cache matching here: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key \nOther caches with similar key:`
)
for (const cacheEntry of cacheListResult?.artifactCaches || []) {
core.debug(
`Cache Key: ${cacheEntry?.cacheKey}, Cache Version: ${cacheEntry?.cacheVersion}, Cache Scope: ${cacheEntry?.scope}, Cache Created: ${cacheEntry?.creationTime}`
)
}
}
}
}
export async function downloadCache( export async function downloadCache(
archiveLocation: string, archiveLocation: string,
archivePath: string, archivePath: string,
@@ -193,11 +151,7 @@ export async function reserveCache(
options?: InternalCacheOptions options?: InternalCacheOptions
): Promise<ITypedResponseWithError<ReserveCacheResponse>> { ): Promise<ITypedResponseWithError<ReserveCacheResponse>> {
const httpClient = createHttpClient() const httpClient = createHttpClient()
const version = getCacheVersion( const version = getCacheVersion(paths, options?.compressionMethod)
paths,
options?.compressionMethod,
options?.enableCrossOsArchive
)
const reserveCacheRequest: ReserveCacheRequest = { const reserveCacheRequest: ReserveCacheRequest = {
key, key,
+11 -11
View File
@@ -71,15 +71,11 @@ export async function unlinkFile(filePath: fs.PathLike): Promise<void> {
return util.promisify(fs.unlink)(filePath) return util.promisify(fs.unlink)(filePath)
} }
async function getVersion( async function getVersion(app: string): Promise<string> {
app: string, core.debug(`Checking ${app} --version`)
additionalArgs: string[] = []
): Promise<string> {
let versionOutput = '' let versionOutput = ''
additionalArgs.push('--version')
core.debug(`Checking ${app} ${additionalArgs.join(' ')}`)
try { try {
await exec.exec(`${app}`, additionalArgs, { await exec.exec(`${app} --version`, [], {
ignoreReturnCode: true, ignoreReturnCode: true,
silent: true, silent: true,
listeners: { listeners: {
@@ -98,14 +94,18 @@ async function getVersion(
// 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> {
const versionOutput = await getVersion('zstd', ['--quiet']) const versionOutput = await getVersion('zstd')
const version = semver.clean(versionOutput) const version = semver.clean(versionOutput)
core.debug(`zstd version: ${version}`)
if (versionOutput === '') { if (!versionOutput.toLowerCase().includes('zstd command line interface')) {
// zstd is not installed
return CompressionMethod.Gzip return CompressionMethod.Gzip
} else { } else if (!version || semver.lt(version, 'v1.3.2')) {
// zstd is installed but using a version earlier than v1.3.2
// v1.3.2 is required to use the `--long` options in zstd
return CompressionMethod.ZstdWithoutLong return CompressionMethod.ZstdWithoutLong
} else {
return CompressionMethod.Zstd
} }
} }
-7
View File
@@ -9,16 +9,10 @@ export interface ITypedResponseWithError<T> extends TypedResponse<T> {
export interface ArtifactCacheEntry { export interface ArtifactCacheEntry {
cacheKey?: string cacheKey?: string
scope?: string scope?: string
cacheVersion?: string
creationTime?: string creationTime?: string
archiveLocation?: string archiveLocation?: string
} }
export interface ArtifactCacheList {
totalCount: number
artifactCaches?: ArtifactCacheEntry[]
}
export interface CommitCacheRequest { export interface CommitCacheRequest {
size: number size: number
} }
@@ -35,7 +29,6 @@ export interface ReserveCacheResponse {
export interface InternalCacheOptions { export interface InternalCacheOptions {
compressionMethod?: CompressionMethod compressionMethod?: CompressionMethod
enableCrossOsArchive?: boolean
cacheSize?: number cacheSize?: number
} }
+1 -3
View File
@@ -242,9 +242,7 @@ export async function downloadCacheStorageSDK(
// If the file exceeds the buffer maximum length (~1 GB on 32-bit systems and ~2 GB // If the file exceeds the buffer maximum length (~1 GB on 32-bit systems and ~2 GB
// on 64-bit systems), split the download into multiple segments // on 64-bit systems), split the download into multiple segments
// ~2 GB = 2147483647, beyond this, we start getting out of range error. So, capping it accordingly. // ~2 GB = 2147483647, beyond this, we start getting out of range error. So, capping it accordingly.
const maxSegmentSize = Math.min(2147483647, buffer.constants.MAX_LENGTH)
// Updated segment size to 128MB = 134217728 bytes, to complete a segment faster and fail fast
const maxSegmentSize = Math.min(134217728, buffer.constants.MAX_LENGTH)
const downloadProgress = new DownloadProgress(contentLength) const downloadProgress = new DownloadProgress(contentLength)
const fd = fs.openSync(archivePath, 'w') const fd = fs.openSync(archivePath, 'w')
+5 -8
View File
@@ -183,7 +183,7 @@ async function getDecompressionProgram(
case CompressionMethod.Zstd: case CompressionMethod.Zstd:
return BSD_TAR_ZSTD return BSD_TAR_ZSTD
? [ ? [
'zstd -d --long=30 --force -o', 'zstd -d --long=30 -o',
TarFilename, TarFilename,
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/') archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
] ]
@@ -194,7 +194,7 @@ async function getDecompressionProgram(
case CompressionMethod.ZstdWithoutLong: case CompressionMethod.ZstdWithoutLong:
return BSD_TAR_ZSTD return BSD_TAR_ZSTD
? [ ? [
'zstd -d --force -o', 'zstd -d -o',
TarFilename, TarFilename,
archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/') archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
] ]
@@ -223,7 +223,7 @@ async function getCompressionProgram(
case CompressionMethod.Zstd: case CompressionMethod.Zstd:
return BSD_TAR_ZSTD return BSD_TAR_ZSTD
? [ ? [
'zstd -T0 --long=30 --force -o', 'zstd -T0 --long=30 -o',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
TarFilename TarFilename
] ]
@@ -234,7 +234,7 @@ async function getCompressionProgram(
case CompressionMethod.ZstdWithoutLong: case CompressionMethod.ZstdWithoutLong:
return BSD_TAR_ZSTD return BSD_TAR_ZSTD
? [ ? [
'zstd -T0 --force -o', 'zstd -T0 -o',
cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'), cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
TarFilename TarFilename
] ]
@@ -248,10 +248,7 @@ async function getCompressionProgram(
async function execCommands(commands: string[], cwd?: string): Promise<void> { async function execCommands(commands: string[], cwd?: string): Promise<void> {
for (const command of commands) { for (const command of commands) {
try { try {
await exec(command, undefined, { await exec(command, undefined, {cwd})
cwd,
env: {...(process.env as object), MSYS: 'winsymlinks:nativestrict'}
})
} catch (error) { } catch (error) {
throw new Error( throw new Error(
`${command.split(' ')[0]} failed with error: ${error?.message}` `${command.split(' ')[0]} failed with error: ${error?.message}`
+1 -16
View File
@@ -53,15 +53,6 @@ export interface DownloadOptions {
* @default 3600000 * @default 3600000
*/ */
segmentTimeoutInMs?: number segmentTimeoutInMs?: number
/**
* Weather to skip downloading the cache entry.
* If lookupOnly is set to true, the restore function will only check if
* a matching cache entry exists and return the cache key if it does.
*
* @default false
*/
lookupOnly?: boolean
} }
/** /**
@@ -101,8 +92,7 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
useAzureSdk: true, useAzureSdk: true,
downloadConcurrency: 8, downloadConcurrency: 8,
timeoutInMs: 30000, timeoutInMs: 30000,
segmentTimeoutInMs: 600000, segmentTimeoutInMs: 3600000
lookupOnly: false
} }
if (copy) { if (copy) {
@@ -121,10 +111,6 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
if (typeof copy.segmentTimeoutInMs === 'number') { if (typeof copy.segmentTimeoutInMs === 'number') {
result.segmentTimeoutInMs = copy.segmentTimeoutInMs result.segmentTimeoutInMs = copy.segmentTimeoutInMs
} }
if (typeof copy.lookupOnly === 'boolean') {
result.lookupOnly = copy.lookupOnly
}
} }
const segmentDownloadTimeoutMins = const segmentDownloadTimeoutMins =
process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS'] process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']
@@ -143,7 +129,6 @@ export function getDownloadOptions(copy?: DownloadOptions): DownloadOptions {
`Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}` `Cache segment download timeout mins env var: ${process.env['SEGMENT_DOWNLOAD_TIMEOUT_MINS']}`
) )
core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`) core.debug(`Segment download timeout (ms): ${result.segmentTimeoutInMs}`)
core.debug(`Lookup only: ${result.lookupOnly}`)
return result return result
} }
+1 -2
View File
@@ -4,8 +4,7 @@
"baseUrl": "./", "baseUrl": "./",
"outDir": "./lib", "outDir": "./lib",
"rootDir": "./src", "rootDir": "./src",
"lib": ["es6", "dom"], "lib": ["es6", "dom"]
"useUnknownInCatchVariables": false
}, },
"include": [ "include": [
"./src" "./src"
+1 -1
View File
@@ -121,7 +121,7 @@ const result = await core.group('Do something async', async () => {
This library has 3 methods that will produce [annotations](https://docs.github.com/en/rest/reference/checks#create-a-check-run). This library has 3 methods that will produce [annotations](https://docs.github.com/en/rest/reference/checks#create-a-check-run).
```js ```js
core.error('This is a bad error, action may still succeed though.') core.error('This is a bad error. This will also fail the build.')
core.warning('Something went wrong, but it\'s not bad enough to fail the build.') core.warning('Something went wrong, but it\'s not bad enough to fail the build.')
+1 -5
View File
@@ -161,11 +161,7 @@ describe('@actions/core', () => {
it('setSecret produces the correct command', () => { it('setSecret produces the correct command', () => {
core.setSecret('secret val') core.setSecret('secret val')
core.setSecret('multi\nline\r\nsecret') assertWriteCalls([`::add-mask::secret val${os.EOL}`])
assertWriteCalls([
`::add-mask::secret val${os.EOL}`,
`::add-mask::multi%0Aline%0D%0Asecret${os.EOL}`
])
}) })
it('prependPath produces the correct commands and sets the env', () => { it('prependPath produces the correct commands and sets the env', () => {
+1 -1
View File
@@ -34,7 +34,7 @@ export enum ExitCode {
} }
/** /**
* Optional properties that can be sent with annotation commands (notice, error, and warning) * Optional properties that can be sent with annotatation commands (notice, error, and warning)
* See: https://docs.github.com/en/rest/reference/checks#create-a-check-run for more information about annotations. * See: https://docs.github.com/en/rest/reference/checks#create-a-check-run for more information about annotations.
*/ */
export interface AnnotationProperties { export interface AnnotationProperties {
@@ -22,7 +22,7 @@ describe('@actions/github', () => {
proxyServer.listen(port, () => resolve()) proxyServer.listen(port, () => resolve())
}) })
proxyServer.on('connect', req => { proxyServer.on('connect', req => {
proxyConnects.push(req.url ?? '') proxyConnects.push(req.url)
}) })
}) })
+1 -1
View File
@@ -18,7 +18,7 @@ describe('@actions/github', () => {
proxyServer.listen(port, () => resolve(null)) proxyServer.listen(port, () => resolve(null))
}) })
proxyServer.on('connect', req => { proxyServer.on('connect', req => {
proxyConnects.push(req.url ?? '') proxyConnects.push(req.url)
}) })
}) })
-3
View File
@@ -1,8 +1,5 @@
# @actions/glob Releases # @actions/glob Releases
### 0.4.0
- Pass in the current workspace as a parameter to HashFiles [#1318](https://github.com/actions/toolkit/pull/1318)
### 0.3.0 ### 0.3.0
- Added a `verbose` option to HashFiles [#1052](https://github.com/actions/toolkit/pull/1052/files) - Added a `verbose` option to HashFiles [#1052](https://github.com/actions/toolkit/pull/1052/files)
+2 -7
View File
@@ -51,7 +51,6 @@ describe('globber', () => {
) )
}) })
const emptyDirectory = ''
it('followSymbolicLinks set to true', async () => { it('followSymbolicLinks set to true', async () => {
const root = path.join(getTestTemp(), 'set-to-true') const root = path.join(getTestTemp(), 'set-to-true')
await fs.mkdir(path.join(root, 'realdir'), {recursive: true}) await fs.mkdir(path.join(root, 'realdir'), {recursive: true})
@@ -61,9 +60,7 @@ describe('globber', () => {
path.join(root, 'symDir') path.join(root, 'symDir')
) )
const testPath = path.join(root, `symDir`) const testPath = path.join(root, `symDir`)
const hash = await hashFiles(testPath, emptyDirectory, { const hash = await hashFiles(testPath, {followSymbolicLinks: true})
followSymbolicLinks: true
})
expect(hash).toEqual( expect(hash).toEqual(
'd8a411e8f8643821bed189e627ff57151918aa554c00c10b31c693ab2dded273' 'd8a411e8f8643821bed189e627ff57151918aa554c00c10b31c693ab2dded273'
) )
@@ -83,9 +80,7 @@ describe('globber', () => {
path.join(root, 'symDir') path.join(root, 'symDir')
) )
const testPath = path.join(root, 'symdir') const testPath = path.join(root, 'symdir')
const hash = await hashFiles(testPath, emptyDirectory, { const hash = await hashFiles(testPath, {followSymbolicLinks: false})
followSymbolicLinks: false
})
expect(hash).toEqual('') expect(hash).toEqual('')
}) })
+92 -46
View File
@@ -1,27 +1,12 @@
{ {
"name": "@actions/glob", "name": "@actions/glob",
"version": "0.4.0", "version": "0.3.0",
"lockfileVersion": 3, "lockfileVersion": 2,
"requires": true, "requires": true,
"description": "Actions glob lib",
"files": [
"lib",
"!.DS_Store"
],
"homepage": "https://github.com/actions/toolkit/tree/main/packages/glob",
"keywords": [
"github",
"actions",
"glob"
],
"license": "MIT",
"main": "lib/glob.js",
"preview": true,
"types": "lib/glob.d.ts",
"packages": { "packages": {
"": { "": {
"name": "@actions/glob", "name": "@actions/glob",
"version": "0.4.0", "version": "0.3.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.9.1", "@actions/core": "^1.9.1",
@@ -29,17 +14,26 @@
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
"version": "1.10.0", "version": "1.9.1",
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"dependencies": { "dependencies": {
"@actions/http-client": "^2.0.1", "@actions/http-client": "^2.0.1",
"uuid": "^8.3.2" "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.2", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
@@ -53,38 +47,90 @@
"node_modules/concat-map": { "node_modules/concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.2", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
}, },
"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"
}
} }
}, },
"bugs": { "dependencies": {
"url": "https://github.com/actions/toolkit/issues" "@actions/core": {
}, "version": "1.9.1",
"directories": { "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz",
"lib": "lib", "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==",
"test": "__tests__" "requires": {
}, "@actions/http-client": "^2.0.1",
"publishConfig": { "uuid": "^8.3.2"
"access": "public" }
}, },
"repository": { "@actions/http-client": {
"directory": "packages/glob", "version": "2.0.1",
"type": "git", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz",
"url": "git+https://github.com/actions/toolkit.git" "integrity": "sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw==",
}, "requires": {
"scripts": { "tunnel": "^0.0.6"
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json", }
"test": "echo \"Error: run tests from root\" && exit 1", },
"tsc": "tsc" "balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"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=="
}
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/glob", "name": "@actions/glob",
"version": "0.4.0", "version": "0.3.0",
"preview": true, "preview": true,
"description": "Actions glob lib", "description": "Actions glob lib",
"keywords": [ "keywords": [
+1 -4
View File
@@ -22,13 +22,10 @@ export async function create(
* Computes the sha256 hash of a glob * Computes the sha256 hash of a glob
* *
* @param patterns Patterns separated by newlines * @param patterns Patterns separated by newlines
* @param currentWorkspace Workspace used when matching files
* @param options Glob options * @param options Glob options
* @param verbose Enables verbose logging
*/ */
export async function hashFiles( export async function hashFiles(
patterns: string, patterns: string,
currentWorkspace = '',
options?: HashFileOptions, options?: HashFileOptions,
verbose: Boolean = false verbose: Boolean = false
): Promise<string> { ): Promise<string> {
@@ -37,5 +34,5 @@ export async function hashFiles(
followSymbolicLinks = options.followSymbolicLinks followSymbolicLinks = options.followSymbolicLinks
} }
const globber = await create(patterns, {followSymbolicLinks}) const globber = await create(patterns, {followSymbolicLinks})
return _hashFiles(globber, currentWorkspace, verbose) return _hashFiles(globber, verbose)
} }
+1 -4
View File
@@ -8,14 +8,11 @@ import {Globber} from './glob'
export async function hashFiles( export async function hashFiles(
globber: Globber, globber: Globber,
currentWorkspace: string,
verbose: Boolean = false verbose: Boolean = false
): Promise<string> { ): Promise<string> {
const writeDelegate = verbose ? core.info : core.debug const writeDelegate = verbose ? core.info : core.debug
let hasMatch = false let hasMatch = false
const githubWorkspace = currentWorkspace const githubWorkspace = process.env['GITHUB_WORKSPACE'] ?? process.cwd()
? currentWorkspace
: process.env['GITHUB_WORKSPACE'] ?? process.cwd()
const result = crypto.createHash('sha256') const result = crypto.createHash('sha256')
let count = 0 let count = 0
for await (const file of globber.globGenerator()) { for await (const file of globber.globGenerator()) {
-4
View File
@@ -1,9 +1,5 @@
## Releases ## Releases
## 2.1.0
- Add support for `*` and subdomains in `no_proxy` [#1355](https://github.com/actions/toolkit/pull/1355) [#1223](https://github.com/actions/toolkit/pull/1223)
- Bypass proxy for loopback IP adresses [#1360](https://github.com/actions/toolkit/pull/1360))
## 2.0.1 ## 2.0.1
- Fix an issue with missing `tunnel` dependency [#1085](https://github.com/actions/toolkit/pull/1085) - Fix an issue with missing `tunnel` dependency [#1085](https://github.com/actions/toolkit/pull/1085)
+9 -9
View File
@@ -15,18 +15,18 @@ describe('auth', () => {
bh bh
]) ])
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
const auth: string = obj.headers.authorization const auth: string = obj.headers.Authorization
const creds: string = Buffer.from( const creds: string = Buffer.from(
auth.substring('Basic '.length), auth.substring('Basic '.length),
'base64' 'base64'
).toString() ).toString()
expect(creds).toBe('johndoe:password') expect(creds).toBe('johndoe:password')
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
}) })
it('does basic http get request with pat token auth', async () => { it('does basic http get request with pat token auth', async () => {
@@ -39,18 +39,18 @@ describe('auth', () => {
ph ph
]) ])
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
const auth: string = obj.headers.authorization const auth: string = obj.headers.Authorization
const creds: string = Buffer.from( const creds: string = Buffer.from(
auth.substring('Basic '.length), auth.substring('Basic '.length),
'base64' 'base64'
).toString() ).toString()
expect(creds).toBe(`PAT:${token}`) expect(creds).toBe(`PAT:${token}`)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
}) })
it('does basic http get request with pat token auth', async () => { it('does basic http get request with pat token auth', async () => {
@@ -61,13 +61,13 @@ describe('auth', () => {
ph ph
]) ])
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
const auth: string = obj.headers.authorization const auth: string = obj.headers.Authorization
expect(auth).toBe(`Bearer ${token}`) expect(auth).toBe(`Bearer ${token}`)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
}) })
}) })
+67 -69
View File
@@ -33,44 +33,44 @@ describe('basics', () => {
// "args": {}, // "args": {},
// "headers": { // "headers": {
// "Connection": "close", // "Connection": "close",
// "Host": "postman-echo.com", // "Host": "httpbin.org",
// "user-agent": "typed-test-client-tests" // "User-Agent": "typed-test-client-tests"
// }, // },
// "origin": "173.95.152.44", // "origin": "173.95.152.44",
// "url": "https://postman-echo.com/get" // "url": "https://httpbin.org/get"
// } // }
it('does basic http get request', async () => { it('does basic http get request', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
expect(obj.headers['user-agent']).toBeTruthy() expect(obj.headers['User-Agent']).toBeTruthy()
}) })
it('does basic http get request with no user agent', async () => { it('does basic http get request with no user agent', async () => {
const http: httpm.HttpClient = new httpm.HttpClient() const http: httpm.HttpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
expect(obj.headers['user-agent']).toBeFalsy() expect(obj.headers['User-Agent']).toBeFalsy()
}) })
it('does basic https get request', async () => { it('does basic https get request', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
'https://postman-echo.com/get' 'https://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('https://postman-echo.com/get') expect(obj.url).toBe('https://httpbin.org/get')
}) })
it('does basic http get request with default headers', async () => { it('does basic http get request with default headers', async () => {
@@ -85,14 +85,14 @@ describe('basics', () => {
} }
) )
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.headers.accept).toBe('application/json') expect(obj.headers.Accept).toBe('application/json')
expect(obj.headers['content-type']).toBe('application/json') expect(obj.headers['Content-Type']).toBe('application/json')
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
}) })
it('does basic http get request with merged headers', async () => { it('does basic http get request with merged headers', async () => {
@@ -107,7 +107,7 @@ describe('basics', () => {
} }
) )
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
'http://postman-echo.com/get', 'http://httpbin.org/get',
{ {
'content-type': 'application/x-www-form-urlencoded' 'content-type': 'application/x-www-form-urlencoded'
} }
@@ -115,22 +115,22 @@ describe('basics', () => {
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.headers.accept).toBe('application/json') expect(obj.headers.Accept).toBe('application/json')
expect(obj.headers['content-type']).toBe( expect(obj.headers['Content-Type']).toBe(
'application/x-www-form-urlencoded' 'application/x-www-form-urlencoded'
) )
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
}) })
it('pipes a get request', async () => { it('pipes a get request', async () => {
return new Promise<void>(async resolve => { return new Promise<void>(async resolve => {
const file = fs.createWriteStream(sampleFilePath) const file = fs.createWriteStream(sampleFilePath)
;(await _http.get('https://postman-echo.com/get')).message ;(await _http.get('https://httpbin.org/get')).message
.pipe(file) .pipe(file)
.on('close', () => { .on('close', () => {
const body: string = fs.readFileSync(sampleFilePath).toString() const body: string = fs.readFileSync(sampleFilePath).toString()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('https://postman-echo.com/get') expect(obj.url).toBe('https://httpbin.org/get')
resolve() resolve()
}) })
}) })
@@ -138,32 +138,32 @@ describe('basics', () => {
it('does basic get request with redirects', async () => { it('does basic get request with redirects', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
`https://postman-echo.com/redirect-to?url=${encodeURIComponent( `https://httpbin.org/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/get' 'https://httpbin.org/get'
)}` )}`
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('https://postman-echo.com/get') expect(obj.url).toBe('https://httpbin.org/get')
}) })
it('does basic get request with redirects (303)', async () => { it('does basic get request with redirects (303)', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
`https://postman-echo.com/redirect-to?url=${encodeURIComponent( `https://httpbin.org/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/get' 'https://httpbin.org/get'
)}&status_code=303` )}&status_code=303`
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('https://postman-echo.com/get') expect(obj.url).toBe('https://httpbin.org/get')
}) })
it('returns 404 for not found get request on redirect', async () => { it('returns 404 for not found get request on redirect', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
`https://postman-echo.com/redirect-to?url=${encodeURIComponent( `https://httpbin.org/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/status/404' 'https://httpbin.org/status/404'
)}&status_code=303` )}&status_code=303`
) )
expect(res.message.statusCode).toBe(404) expect(res.message.statusCode).toBe(404)
@@ -177,8 +177,8 @@ describe('basics', () => {
{allowRedirects: false} {allowRedirects: false}
) )
const res: httpm.HttpClientResponse = await http.get( const res: httpm.HttpClientResponse = await http.get(
`https://postman-echo.com/redirect-to?url=${encodeURIComponent( `https://httpbin.org/redirect-to?url=${encodeURIComponent(
'https://postman-echo.com/get' 'https://httpbin.org/get'
)}` )}`
) )
expect(res.message.statusCode).toBe(302) expect(res.message.statusCode).toBe(302)
@@ -191,8 +191,8 @@ describe('basics', () => {
authorization: 'shhh' authorization: 'shhh'
} }
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
`https://postman-echo.com/redirect-to?url=${encodeURIComponent( `https://httpbin.org/redirect-to?url=${encodeURIComponent(
'https://www.postman-echo.com/get' 'https://www.httpbin.org/get'
)}`, )}`,
headers headers
) )
@@ -201,10 +201,10 @@ describe('basics', () => {
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
// httpbin "fixes" the casing // httpbin "fixes" the casing
expect(obj.headers[httpm.Headers.Accept]).toBe('application/json') expect(obj.headers['Accept']).toBe('application/json')
expect(obj.headers['Authorization']).toBeUndefined() expect(obj.headers['Authorization']).toBeUndefined()
expect(obj.headers['authorization']).toBeUndefined() expect(obj.headers['authorization']).toBeUndefined()
expect(obj.url).toBe('https://www.postman-echo.com/get') expect(obj.url).toBe('https://www.httpbin.org/get')
}) })
it('does not pass Auth with diff hostname redirects', async () => { it('does not pass Auth with diff hostname redirects', async () => {
@@ -213,8 +213,8 @@ describe('basics', () => {
Authorization: 'shhh' Authorization: 'shhh'
} }
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
`https://postman-echo.com/redirect-to?url=${encodeURIComponent( `https://httpbin.org/redirect-to?url=${encodeURIComponent(
'https://www.postman-echo.com/get' 'https://www.httpbin.org/get'
)}`, )}`,
headers headers
) )
@@ -223,22 +223,22 @@ describe('basics', () => {
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
// httpbin "fixes" the casing // httpbin "fixes" the casing
expect(obj.headers[httpm.Headers.Accept]).toBe('application/json') expect(obj.headers['Accept']).toBe('application/json')
expect(obj.headers['Authorization']).toBeUndefined() expect(obj.headers['Authorization']).toBeUndefined()
expect(obj.headers['authorization']).toBeUndefined() expect(obj.headers['authorization']).toBeUndefined()
expect(obj.url).toBe('https://www.postman-echo.com/get') expect(obj.url).toBe('https://www.httpbin.org/get')
}) })
it('does basic head request', async () => { it('does basic head request', async () => {
const res: httpm.HttpClientResponse = await _http.head( const res: httpm.HttpClientResponse = await _http.head(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
}) })
it('does basic http delete request', async () => { it('does basic http delete request', async () => {
const res: httpm.HttpClientResponse = await _http.del( const res: httpm.HttpClientResponse = await _http.del(
'http://postman-echo.com/delete' 'http://httpbin.org/delete'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
@@ -248,32 +248,32 @@ describe('basics', () => {
it('does basic http post request', async () => { it('does basic http post request', async () => {
const b = 'Hello World!' const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.post( const res: httpm.HttpClientResponse = await _http.post(
'http://postman-echo.com/post', 'http://httpbin.org/post',
b b
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.data).toBe(b) expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/post') expect(obj.url).toBe('http://httpbin.org/post')
}) })
it('does basic http patch request', async () => { it('does basic http patch request', async () => {
const b = 'Hello World!' const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.patch( const res: httpm.HttpClientResponse = await _http.patch(
'http://postman-echo.com/patch', 'http://httpbin.org/patch',
b b
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.data).toBe(b) expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/patch') expect(obj.url).toBe('http://httpbin.org/patch')
}) })
it('does basic http options request', async () => { it('does basic http options request', async () => {
const res: httpm.HttpClientResponse = await _http.options( const res: httpm.HttpClientResponse = await _http.options(
'http://postman-echo.com' 'http://httpbin.org'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
await res.readBody() await res.readBody()
@@ -281,30 +281,28 @@ describe('basics', () => {
it('returns 404 for not found get request', async () => { it('returns 404 for not found get request', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/status/404' 'http://httpbin.org/status/404'
) )
expect(res.message.statusCode).toBe(404) expect(res.message.statusCode).toBe(404)
await res.readBody() await res.readBody()
}) })
it('gets a json object', async () => { it('gets a json object', async () => {
const jsonObj = await _http.getJson<HttpBinData>( const jsonObj = await _http.getJson<HttpBinData>('https://httpbin.org/get')
'https://postman-echo.com/get'
)
expect(jsonObj.statusCode).toBe(200) expect(jsonObj.statusCode).toBe(200)
expect(jsonObj.result).toBeDefined() expect(jsonObj.result).toBeDefined()
expect(jsonObj.result?.url).toBe('https://postman-echo.com/get') expect(jsonObj.result?.url).toBe('https://httpbin.org/get')
expect(jsonObj.result?.headers[httpm.Headers.Accept]).toBe( expect(jsonObj.result?.headers['Accept']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(jsonObj.headers['content-type']).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
it('getting a non existent json object returns null', async () => { it('getting a non existent json object returns null', async () => {
const jsonObj = await _http.getJson<HttpBinData>( const jsonObj = await _http.getJson<HttpBinData>(
'https://postman-echo.com/status/404' 'https://httpbin.org/status/404'
) )
expect(jsonObj.statusCode).toBe(404) expect(jsonObj.statusCode).toBe(404)
expect(jsonObj.result).toBeNull() expect(jsonObj.result).toBeNull()
@@ -313,20 +311,20 @@ describe('basics', () => {
it('posts a json object', async () => { it('posts a json object', async () => {
const res = {name: 'foo'} const res = {name: 'foo'}
const restRes = await _http.postJson<HttpBinData>( const restRes = await _http.postJson<HttpBinData>(
'https://postman-echo.com/post', 'https://httpbin.org/post',
res res
) )
expect(restRes.statusCode).toBe(200) expect(restRes.statusCode).toBe(200)
expect(restRes.result).toBeDefined() expect(restRes.result).toBeDefined()
expect(restRes.result?.url).toBe('https://postman-echo.com/post') expect(restRes.result?.url).toBe('https://httpbin.org/post')
expect(restRes.result?.json.name).toBe('foo') expect(restRes.result?.json.name).toBe('foo')
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe( expect(restRes.result?.headers['Accept']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(restRes.result?.headers['content-type']).toBe( expect(restRes.result?.headers['Content-Type']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(restRes.headers['content-type']).toContain( expect(restRes.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
@@ -334,21 +332,21 @@ describe('basics', () => {
it('puts a json object', async () => { it('puts a json object', async () => {
const res = {name: 'foo'} const res = {name: 'foo'}
const restRes = await _http.putJson<HttpBinData>( const restRes = await _http.putJson<HttpBinData>(
'https://postman-echo.com/put', 'https://httpbin.org/put',
res res
) )
expect(restRes.statusCode).toBe(200) expect(restRes.statusCode).toBe(200)
expect(restRes.result).toBeDefined() expect(restRes.result).toBeDefined()
expect(restRes.result?.url).toBe('https://postman-echo.com/put') expect(restRes.result?.url).toBe('https://httpbin.org/put')
expect(restRes.result?.json.name).toBe('foo') expect(restRes.result?.json.name).toBe('foo')
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe( expect(restRes.result?.headers['Accept']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(restRes.result?.headers['content-type']).toBe( expect(restRes.result?.headers['Content-Type']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(restRes.headers['content-type']).toContain( expect(restRes.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
@@ -356,20 +354,20 @@ describe('basics', () => {
it('patch a json object', async () => { it('patch a json object', async () => {
const res = {name: 'foo'} const res = {name: 'foo'}
const restRes = await _http.patchJson<HttpBinData>( const restRes = await _http.patchJson<HttpBinData>(
'https://postman-echo.com/patch', 'https://httpbin.org/patch',
res res
) )
expect(restRes.statusCode).toBe(200) expect(restRes.statusCode).toBe(200)
expect(restRes.result).toBeDefined() expect(restRes.result).toBeDefined()
expect(restRes.result?.url).toBe('https://postman-echo.com/patch') expect(restRes.result?.url).toBe('https://httpbin.org/patch')
expect(restRes.result?.json.name).toBe('foo') expect(restRes.result?.json.name).toBe('foo')
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe( expect(restRes.result?.headers['Accept']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(restRes.result?.headers['content-type']).toBe( expect(restRes.result?.headers['Content-Type']).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
expect(restRes.headers['content-type']).toContain( expect(restRes.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
+24 -27
View File
@@ -12,11 +12,11 @@ describe('headers', () => {
it('preserves existing headers on getJson', async () => { it('preserves existing headers on getJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'} const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.getJson<any>( let jsonObj = await _http.getJson<any>(
'https://postman-echo.com/get', 'https://httpbin.org/get',
additionalHeaders additionalHeaders
) )
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('foo') expect(jsonObj.result.headers['Accept']).toBe('foo')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
@@ -26,9 +26,9 @@ describe('headers', () => {
[httpm.Headers.Accept]: 'baz' [httpm.Headers.Accept]: 'baz'
} }
} }
jsonObj = await httpWithHeaders.getJson<any>('https://postman-echo.com/get') jsonObj = await httpWithHeaders.getJson<any>('https://httpbin.org/get')
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz') expect(jsonObj.result.headers['Accept']).toBe('baz')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
@@ -36,12 +36,12 @@ describe('headers', () => {
it('preserves existing headers on postJson', async () => { it('preserves existing headers on postJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'} const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.postJson<any>( let jsonObj = await _http.postJson<any>(
'https://postman-echo.com/post', 'https://httpbin.org/post',
{}, {},
additionalHeaders additionalHeaders
) )
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('foo') expect(jsonObj.result.headers['Accept']).toBe('foo')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
@@ -52,11 +52,11 @@ describe('headers', () => {
} }
} }
jsonObj = await httpWithHeaders.postJson<any>( jsonObj = await httpWithHeaders.postJson<any>(
'https://postman-echo.com/post', 'https://httpbin.org/post',
{} {}
) )
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz') expect(jsonObj.result.headers['Accept']).toBe('baz')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
@@ -64,12 +64,12 @@ describe('headers', () => {
it('preserves existing headers on putJson', async () => { it('preserves existing headers on putJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'} const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.putJson<any>( let jsonObj = await _http.putJson<any>(
'https://postman-echo.com/put', 'https://httpbin.org/put',
{}, {},
additionalHeaders additionalHeaders
) )
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('foo') expect(jsonObj.result.headers['Accept']).toBe('foo')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
@@ -79,12 +79,9 @@ describe('headers', () => {
[httpm.Headers.Accept]: 'baz' [httpm.Headers.Accept]: 'baz'
} }
} }
jsonObj = await httpWithHeaders.putJson<any>( jsonObj = await httpWithHeaders.putJson<any>('https://httpbin.org/put', {})
'https://postman-echo.com/put', expect(jsonObj.result.headers['Accept']).toBe('baz')
{} expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
)
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
@@ -92,12 +89,12 @@ describe('headers', () => {
it('preserves existing headers on patchJson', async () => { it('preserves existing headers on patchJson', async () => {
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'} const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
let jsonObj = await _http.patchJson<any>( let jsonObj = await _http.patchJson<any>(
'https://postman-echo.com/patch', 'https://httpbin.org/patch',
{}, {},
additionalHeaders additionalHeaders
) )
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('foo') expect(jsonObj.result.headers['Accept']).toBe('foo')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
@@ -108,11 +105,11 @@ describe('headers', () => {
} }
} }
jsonObj = await httpWithHeaders.patchJson<any>( jsonObj = await httpWithHeaders.patchJson<any>(
'https://postman-echo.com/patch', 'https://httpbin.org/patch',
{} {}
) )
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz') expect(jsonObj.result.headers['Accept']).toBe('baz')
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain( expect(jsonObj.headers[httpm.Headers.ContentType]).toBe(
httpm.MediaTypes.ApplicationJson httpm.MediaTypes.ApplicationJson
) )
}) })
@@ -13,24 +13,24 @@ describe('basics', () => {
it('does basic http get request with keepAlive true', async () => { it('does basic http get request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.get( const res: httpm.HttpClientResponse = await _http.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
}) })
it('does basic head request with keepAlive true', async () => { it('does basic head request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.head( const res: httpm.HttpClientResponse = await _http.head(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
}) })
it('does basic http delete request with keepAlive true', async () => { it('does basic http delete request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.del( const res: httpm.HttpClientResponse = await _http.del(
'http://postman-echo.com/delete' 'http://httpbin.org/delete'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
@@ -40,32 +40,32 @@ describe('basics', () => {
it('does basic http post request with keepAlive true', async () => { it('does basic http post request with keepAlive true', async () => {
const b = 'Hello World!' const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.post( const res: httpm.HttpClientResponse = await _http.post(
'http://postman-echo.com/post', 'http://httpbin.org/post',
b b
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.data).toBe(b) expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/post') expect(obj.url).toBe('http://httpbin.org/post')
}) })
it('does basic http patch request with keepAlive true', async () => { it('does basic http patch request with keepAlive true', async () => {
const b = 'Hello World!' const b = 'Hello World!'
const res: httpm.HttpClientResponse = await _http.patch( const res: httpm.HttpClientResponse = await _http.patch(
'http://postman-echo.com/patch', 'http://httpbin.org/patch',
b b
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.data).toBe(b) expect(obj.data).toBe(b)
expect(obj.url).toBe('http://postman-echo.com/patch') expect(obj.url).toBe('http://httpbin.org/patch')
}) })
it('does basic http options request with keepAlive true', async () => { it('does basic http options request with keepAlive true', async () => {
const res: httpm.HttpClientResponse = await _http.options( const res: httpm.HttpClientResponse = await _http.options(
'http://postman-echo.com' 'http://httpbin.org'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
await res.readBody() await res.readBody()
+14 -88
View File
@@ -19,7 +19,7 @@ describe('proxy', () => {
_proxyServer.listen(port, () => resolve()) _proxyServer.listen(port, () => resolve())
}) })
_proxyServer.on('connect', req => { _proxyServer.on('connect', req => {
_proxyConnects.push(req.url ?? '') _proxyConnects.push(req.url)
}) })
}) })
@@ -91,12 +91,6 @@ describe('proxy', () => {
expect(proxyUrl).toBeDefined() expect(proxyUrl).toBeDefined()
}) })
it('getProxyUrl returns proxyUrl if http_proxy has no protocol', () => {
process.env['http_proxy'] = 'myproxysvr'
const proxyUrl = pm.getProxyUrl(new URL('http://github.com'))
expect(proxyUrl?.toString()).toBe('http://myproxysvr/')
})
it('checkBypass returns true if host as no_proxy list', () => { it('checkBypass returns true if host as no_proxy list', () => {
process.env['no_proxy'] = 'myserver' process.env['no_proxy'] = 'myserver'
const bypass = pm.checkBypass(new URL('https://myserver')) const bypass = pm.checkBypass(new URL('https://myserver'))
@@ -151,73 +145,30 @@ describe('proxy', () => {
expect(bypass).toBeFalsy() expect(bypass).toBeFalsy()
}) })
it('checkBypass returns true if host with subdomain in no_proxy', () => {
process.env['no_proxy'] = 'myserver.com'
const bypass = pm.checkBypass(new URL('https://sub.myserver.com'))
expect(bypass).toBeTruthy()
})
it('checkBypass returns false if no_proxy is subdomain', () => {
process.env['no_proxy'] = 'myserver.com'
const bypass = pm.checkBypass(new URL('https://myserver.com.evil.org'))
expect(bypass).toBeFalsy()
})
it('checkBypass returns false if no_proxy is part of domain', () => {
process.env['no_proxy'] = 'myserver.com'
const bypass = pm.checkBypass(new URL('https://evilmyserver.com'))
expect(bypass).toBeFalsy()
})
// Do not strip leading dots as per https://github.com/actions/runner/blob/97195bad5870e2ad0915ebfef1616083aacf5818/docs/adrs/0263-proxy-support.md
it('checkBypass returns false if host with leading dot in no_proxy', () => {
process.env['no_proxy'] = '.myserver.com'
const bypass = pm.checkBypass(new URL('https://myserver.com'))
expect(bypass).toBeFalsy()
})
it('checkBypass returns true if host with subdomain in no_proxy defined with leading "."', () => {
process.env['no_proxy'] = '.myserver.com'
const bypass = pm.checkBypass(new URL('https://sub.myserver.com'))
expect(bypass).toBeTruthy()
})
it('checkBypass returns true if no_proxy is "*"', () => {
process.env['no_proxy'] = '*'
const bypass = pm.checkBypass(new URL('https://anything.whatsoever.com'))
expect(bypass).toBeTruthy()
})
it('checkBypass returns true if no_proxy contains comma separated "*"', () => {
process.env['no_proxy'] = 'domain.com,* , example.com'
const bypass = pm.checkBypass(new URL('https://anything.whatsoever.com'))
expect(bypass).toBeTruthy()
})
it('HttpClient does basic http get request through proxy', async () => { it('HttpClient does basic http get request through proxy', async () => {
process.env['http_proxy'] = _proxyUrl process.env['http_proxy'] = _proxyUrl
const httpClient = new httpm.HttpClient() const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get( const res: httpm.HttpClientResponse = await httpClient.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
expect(_proxyConnects).toEqual(['postman-echo.com:80']) expect(_proxyConnects).toEqual(['httpbin.org:80'])
}) })
it('HttpClient does basic http get request when bypass proxy', async () => { it('HttoClient does basic http get request when bypass proxy', async () => {
process.env['http_proxy'] = _proxyUrl process.env['http_proxy'] = _proxyUrl
process.env['no_proxy'] = 'postman-echo.com' process.env['no_proxy'] = 'httpbin.org'
const httpClient = new httpm.HttpClient() const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get( const res: httpm.HttpClientResponse = await httpClient.get(
'http://postman-echo.com/get' 'http://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('http://postman-echo.com/get') expect(obj.url).toBe('http://httpbin.org/get')
expect(_proxyConnects).toHaveLength(0) expect(_proxyConnects).toHaveLength(0)
}) })
@@ -225,54 +176,29 @@ describe('proxy', () => {
process.env['https_proxy'] = _proxyUrl process.env['https_proxy'] = _proxyUrl
const httpClient = new httpm.HttpClient() const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get( const res: httpm.HttpClientResponse = await httpClient.get(
'https://postman-echo.com/get' 'https://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('https://postman-echo.com/get') expect(obj.url).toBe('https://httpbin.org/get')
expect(_proxyConnects).toEqual(['postman-echo.com:443']) expect(_proxyConnects).toEqual(['httpbin.org:443'])
}) })
it('HttpClient does basic https get request when bypass proxy', async () => { it('HttpClient does basic https get request when bypass proxy', async () => {
process.env['https_proxy'] = _proxyUrl process.env['https_proxy'] = _proxyUrl
process.env['no_proxy'] = 'postman-echo.com' process.env['no_proxy'] = 'httpbin.org'
const httpClient = new httpm.HttpClient() const httpClient = new httpm.HttpClient()
const res: httpm.HttpClientResponse = await httpClient.get( const res: httpm.HttpClientResponse = await httpClient.get(
'https://postman-echo.com/get' 'https://httpbin.org/get'
) )
expect(res.message.statusCode).toBe(200) expect(res.message.statusCode).toBe(200)
const body: string = await res.readBody() const body: string = await res.readBody()
const obj = JSON.parse(body) const obj = JSON.parse(body)
expect(obj.url).toBe('https://postman-echo.com/get') expect(obj.url).toBe('https://httpbin.org/get')
expect(_proxyConnects).toHaveLength(0) expect(_proxyConnects).toHaveLength(0)
}) })
it('HttpClient bypasses proxy for loopback addresses (localhost, ::1, 127.*)', async () => {
// setup a server listening on localhost:8091
const server = http.createServer((request, response) => {
response.writeHead(200)
request.pipe(response)
})
server.listen(8091)
try {
process.env['http_proxy'] = _proxyUrl
const httpClient = new httpm.HttpClient()
let res = await httpClient.get('http://localhost:8091')
expect(res.message.statusCode).toBe(200)
res = await httpClient.get('http://127.0.0.1:8091')
expect(res.message.statusCode).toBe(200)
// no support for ipv6 for now
expect(httpClient.get('http://[::1]:8091')).rejects.toThrow()
// proxy at _proxyUrl was ignored
expect(_proxyConnects).toEqual([])
} finally {
server.close()
}
})
it('proxyAuth not set in tunnel agent when authentication is not provided', async () => { it('proxyAuth not set in tunnel agent when authentication is not provided', async () => {
process.env['https_proxy'] = 'http://127.0.0.1:8080' process.env['https_proxy'] = 'http://127.0.0.1:8080'
const httpClient = new httpm.HttpClient() const httpClient = new httpm.HttpClient()
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/http-client", "name": "@actions/http-client",
"version": "2.1.0", "version": "2.0.1",
"description": "Actions Http Client", "description": "Actions Http Client",
"keywords": [ "keywords": [
"github", "github",
+2 -31
View File
@@ -14,12 +14,7 @@ export function getProxyUrl(reqUrl: URL): URL | undefined {
})() })()
if (proxyVar) { if (proxyVar) {
try { return new URL(proxyVar)
return new URL(proxyVar)
} catch {
if (!proxyVar.startsWith('http://') && !proxyVar.startsWith('https://'))
return new URL(`http://${proxyVar}`)
}
} else { } else {
return undefined return undefined
} }
@@ -30,11 +25,6 @@ export function checkBypass(reqUrl: URL): boolean {
return false return false
} }
const reqHost = reqUrl.hostname
if (isLoopbackAddress(reqHost)) {
return true
}
const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || '' const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''
if (!noProxy) { if (!noProxy) {
return false return false
@@ -61,29 +51,10 @@ export function checkBypass(reqUrl: URL): boolean {
.split(',') .split(',')
.map(x => x.trim().toUpperCase()) .map(x => x.trim().toUpperCase())
.filter(x => x)) { .filter(x => x)) {
if ( if (upperReqHosts.some(x => x === upperNoProxyItem)) {
upperNoProxyItem === '*' ||
upperReqHosts.some(
x =>
x === upperNoProxyItem ||
x.endsWith(`.${upperNoProxyItem}`) ||
(upperNoProxyItem.startsWith('.') &&
x.endsWith(`${upperNoProxyItem}`))
)
) {
return true return true
} }
} }
return false return false
} }
function isLoopbackAddress(host: string): boolean {
const hostLower = host.toLowerCase()
return (
hostLower === 'localhost' ||
hostLower.startsWith('127.') ||
hostLower.startsWith('[::1]') ||
hostLower.startsWith('[0:0:0:0:0:0:0:1]')
)
}
-3
View File
@@ -1,8 +1,5 @@
# @actions/io Releases # @actions/io Releases
### 1.1.3
- Replace `child_process.exec` with `fs.rm` in `rmRF` for all OS implementations [#1373](https://github.com/actions/toolkit/pull/1373)
### 1.1.2 ### 1.1.2
- Update `lockfileVersion` to `v2` in `package-lock.json [#1020](https://github.com/actions/toolkit/pull/1020) - Update `lockfileVersion` to `v2` in `package-lock.json [#1020](https://github.com/actions/toolkit/pull/1020)
+24 -16
View File
@@ -3,7 +3,6 @@ import {promises as fs} from 'fs'
import * as os from 'os' import * as os from 'os'
import * as path from 'path' import * as path from 'path'
import * as io from '../src/io' import * as io from '../src/io'
import * as ioUtil from '../src/io-util'
describe('cp', () => { describe('cp', () => {
beforeAll(async () => { beforeAll(async () => {
@@ -332,22 +331,11 @@ describe('rmRF', () => {
await fs.appendFile(filePath, 'some data') await fs.appendFile(filePath, 'some data')
await assertExists(filePath) await assertExists(filePath)
// For windows we need to explicitly set an exclusive lock flag, because by default Node will open the file with the 'Delete' FileShare flag. const fd = await fs.open(filePath, 'r')
// See the exclusive lock windows flag definition: await io.rmRF(testPath)
// https://github.com/nodejs/node/blob/c2e4b1fa9ad0b744616c4e4c13a5017772a630c4/deps/uv/src/win/fs.c#L499-L513
const fd = await fs.open( await assertNotExists(testPath)
filePath,
fs.constants.O_RDONLY | ioUtil.UV_FS_O_EXLOCK
)
if (ioUtil.IS_WINDOWS) {
// On Windows, we expect an error due to an lstat call implementation in the underlying libuv code.
// See https://github.com/libuv/libuv/issues/3267 is resolved
await expect(async () => io.rmRF(testPath)).rejects.toThrow('EBUSY')
} else {
await io.rmRF(testPath)
await assertNotExists(testPath)
}
await fd.close() await fd.close()
await io.rmRF(testPath) await io.rmRF(testPath)
await assertNotExists(testPath) await assertNotExists(testPath)
@@ -385,6 +373,26 @@ describe('rmRF', () => {
await assertNotExists(file) await assertNotExists(file)
}) })
it('removes symlink folder with rmRF', async () => {
// create the following layout:
// real_directory
// real_directory/real_file
// symlink_directory -> real_directory
const root: string = path.join(getTestTemp(), 'rmRF_sym_dir_test')
const realDirectory: string = path.join(root, 'real_directory')
const realFile: string = path.join(root, 'real_directory', 'real_file')
const symlinkDirectory: string = path.join(root, 'symlink_directory')
await io.mkdirP(realDirectory)
await fs.writeFile(realFile, 'test file content')
await createSymlinkDir(realDirectory, symlinkDirectory)
await assertExists(path.join(symlinkDirectory, 'real_file'))
await io.rmRF(symlinkDirectory)
await assertExists(realDirectory)
await assertExists(realFile)
await assertNotExists(symlinkDirectory)
})
// creating a symlink to a file on Windows requires elevated // creating a symlink to a file on Windows requires elevated
if (os.platform() !== 'win32') { if (os.platform() !== 'win32') {
it('removes symlink file with rmRF', async () => { it('removes symlink file with rmRF', async () => {
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "@actions/io", "name": "@actions/io",
"version": "1.1.3", "version": "1.1.2",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@actions/io", "name": "@actions/io",
"version": "1.1.3", "version": "1.1.2",
"license": "MIT" "license": "MIT"
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@actions/io", "name": "@actions/io",
"version": "1.1.3", "version": "1.1.2",
"description": "Actions io lib", "description": "Actions io lib",
"keywords": [ "keywords": [
"github", "github",
+1 -6
View File
@@ -6,21 +6,16 @@ export const {
copyFile, copyFile,
lstat, lstat,
mkdir, mkdir,
open,
readdir, readdir,
readlink, readlink,
rename, rename,
rm,
rmdir, rmdir,
stat, stat,
symlink, symlink,
unlink unlink
} = fs.promises } = fs.promises
// export const {open} = 'fs'
export const IS_WINDOWS = process.platform === 'win32' export const IS_WINDOWS = process.platform === 'win32'
// See https://github.com/nodejs/node/blob/d0153aee367422d0858105abec186da4dff0a0c5/deps/uv/include/uv/win.h#L691
export const UV_FS_O_EXLOCK = 0x10000000
export const READONLY = fs.constants.O_RDONLY
export async function exists(fsPath: string): Promise<boolean> { export async function exists(fsPath: string): Promise<boolean> {
try { try {
+49 -11
View File
@@ -1,7 +1,12 @@
import {ok} from 'assert' import {ok} from 'assert'
import * as childProcess from 'child_process'
import * as path from 'path' import * as path from 'path'
import {promisify} from 'util'
import * as ioUtil from './io-util' import * as ioUtil from './io-util'
const exec = promisify(childProcess.exec)
const execFile = promisify(childProcess.execFile)
/** /**
* Interface for cp/mv options * Interface for cp/mv options
*/ */
@@ -111,6 +116,9 @@ export async function mv(
*/ */
export async function rmRF(inputPath: string): Promise<void> { export async function rmRF(inputPath: string): Promise<void> {
if (ioUtil.IS_WINDOWS) { if (ioUtil.IS_WINDOWS) {
// Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another
// program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del.
// Check for invalid characters // Check for invalid characters
// https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file // https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
if (/[*"<>|]/.test(inputPath)) { if (/[*"<>|]/.test(inputPath)) {
@@ -118,17 +126,47 @@ export async function rmRF(inputPath: string): Promise<void> {
'File path must not contain `*`, `"`, `<`, `>` or `|` on Windows' 'File path must not contain `*`, `"`, `<`, `>` or `|` on Windows'
) )
} }
} try {
try { const cmdPath = ioUtil.getCmdPath()
// note if path does not exist, error is silent if (await ioUtil.isDirectory(inputPath, true)) {
await ioUtil.rm(inputPath, { await exec(`${cmdPath} /s /c "rd /s /q "%inputPath%""`, {
force: true, env: {inputPath}
maxRetries: 3, })
recursive: true, } else {
retryDelay: 300 await exec(`${cmdPath} /s /c "del /f /a "%inputPath%""`, {
}) env: {inputPath}
} catch (err) { })
throw new Error(`File was unable to be removed ${err}`) }
} catch (err) {
// if you try to delete a file that doesn't exist, desired result is achieved
// other errors are valid
if (err.code !== 'ENOENT') throw err
}
// Shelling out fails to remove a symlink folder with missing source, this unlink catches that
try {
await ioUtil.unlink(inputPath)
} catch (err) {
// if you try to delete a file that doesn't exist, desired result is achieved
// other errors are valid
if (err.code !== 'ENOENT') throw err
}
} else {
let isDir = false
try {
isDir = await ioUtil.isDirectory(inputPath)
} catch (err) {
// if you try to delete a file that doesn't exist, desired result is achieved
// other errors are valid
if (err.code !== 'ENOENT') throw err
return
}
if (isDir) {
await execFile(`rm`, [`-rf`, `${inputPath}`])
} else {
await ioUtil.unlink(inputPath)
}
} }
} }
+242 -29
View File
@@ -17,10 +17,10 @@
"uuid": "^3.3.2" "uuid": "^3.3.2"
}, },
"devDependencies": { "devDependencies": {
"@types/nock": "^11.1.0", "@types/nock": "^10.0.3",
"@types/semver": "^6.0.0", "@types/semver": "^6.0.0",
"@types/uuid": "^3.4.4", "@types/uuid": "^3.4.4",
"nock": "^13.2.9" "nock": "^10.0.6"
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
@@ -62,13 +62,12 @@
"integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw==" "integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw=="
}, },
"node_modules/@types/nock": { "node_modules/@types/nock": {
"version": "11.1.0", "version": "10.0.3",
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/nock/-/nock-10.0.3.tgz",
"integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", "integrity": "sha512-OthuN+2FuzfZO3yONJ/QVjKmLEuRagS9TV9lEId+WHL9KhftYG+/2z+pxlr0UgVVXSpVD8woie/3fzQn8ft/Ow==",
"deprecated": "This is a stub types definition. nock provides its own type definitions, so you do not need this installed.",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"nock": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
@@ -92,6 +91,41 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true,
"engines": {
"node": "*"
}
},
"node_modules/chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
"integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
"dev": true,
"dependencies": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"pathval": "^1.1.0",
"type-detect": "^4.0.5"
},
"engines": {
"node": ">=4"
}
},
"node_modules/check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true,
"engines": {
"node": "*"
}
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -102,6 +136,33 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"node_modules/deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"dependencies": {
"type-detect": "^4.0.0"
},
"engines": {
"node": ">=0.12"
}
},
"node_modules/deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
"dev": true
},
"node_modules/get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true,
"engines": {
"node": "*"
}
},
"node_modules/json-stringify-safe": { "node_modules/json-stringify-safe": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -114,6 +175,24 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true "dev": true
}, },
"node_modules/minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
"node_modules/mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"dependencies": {
"minimist": "^1.2.5"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -121,27 +200,59 @@
"dev": true "dev": true
}, },
"node_modules/nock": { "node_modules/nock": {
"version": "13.2.9", "version": "10.0.6",
"resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz",
"integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"chai": "^4.1.2",
"debug": "^4.1.0", "debug": "^4.1.0",
"deep-equal": "^1.0.0",
"json-stringify-safe": "^5.0.1", "json-stringify-safe": "^5.0.1",
"lodash": "^4.17.21", "lodash": "^4.17.5",
"propagate": "^2.0.0" "mkdirp": "^0.5.0",
"propagate": "^1.0.0",
"qs": "^6.5.1",
"semver": "^5.5.0"
}, },
"engines": { "engines": {
"node": ">= 10.13" "node": ">= 6.0"
}
},
"node_modules/nock/node_modules/semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true,
"bin": {
"semver": "bin/semver"
}
},
"node_modules/pathval": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
"dev": true,
"engines": {
"node": "*"
} }
}, },
"node_modules/propagate": { "node_modules/propagate": {
"version": "2.0.1", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz",
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=",
"dev": true,
"engines": [
"node >= 0.8.1"
]
},
"node_modules/qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 8" "node": ">=0.6"
} }
}, },
"node_modules/semver": { "node_modules/semver": {
@@ -160,6 +271,15 @@
"node": ">=0.6.11 <=0.7.0 || >=0.7.3" "node": ">=0.6.11 <=0.7.0 || >=0.7.3"
} }
}, },
"node_modules/type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/uuid": { "node_modules/uuid": {
"version": "3.3.2", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
@@ -209,12 +329,12 @@
"integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw==" "integrity": "sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw=="
}, },
"@types/nock": { "@types/nock": {
"version": "11.1.0", "version": "10.0.3",
"resolved": "https://registry.npmjs.org/@types/nock/-/nock-11.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/nock/-/nock-10.0.3.tgz",
"integrity": "sha512-jI/ewavBQ7X5178262JQR0ewicPAcJhXS/iFaNJl0VHLfyosZ/kwSrsa6VNQNSO8i9d8SqdRgOtZSOKJ/+iNMw==", "integrity": "sha512-OthuN+2FuzfZO3yONJ/QVjKmLEuRagS9TV9lEId+WHL9KhftYG+/2z+pxlr0UgVVXSpVD8woie/3fzQn8ft/Ow==",
"dev": true, "dev": true,
"requires": { "requires": {
"nock": "*" "@types/node": "*"
} }
}, },
"@types/node": { "@types/node": {
@@ -238,6 +358,32 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"assertion-error": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
"dev": true
},
"chai": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
"integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"pathval": "^1.1.0",
"type-detect": "^4.0.5"
}
},
"check-error": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
"dev": true
},
"debug": { "debug": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@@ -247,6 +393,27 @@
"ms": "^2.1.1" "ms": "^2.1.1"
} }
}, },
"deep-eql": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"requires": {
"type-detect": "^4.0.0"
}
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
"dev": true
},
"get-func-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
"dev": true
},
"json-stringify-safe": { "json-stringify-safe": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -259,6 +426,21 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true "dev": true
}, },
"minimist": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
"integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
"dev": true
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -266,21 +448,46 @@
"dev": true "dev": true
}, },
"nock": { "nock": {
"version": "13.2.9", "version": "10.0.6",
"resolved": "https://registry.npmjs.org/nock/-/nock-13.2.9.tgz", "resolved": "https://registry.npmjs.org/nock/-/nock-10.0.6.tgz",
"integrity": "sha512-1+XfJNYF1cjGB+TKMWi29eZ0b82QOvQs2YoLNzbpWGqFMtRQHTa57osqdGj4FrFPgkO4D4AZinzUJR9VvW3QUA==", "integrity": "sha512-b47OWj1qf/LqSQYnmokNWM8D88KvUl2y7jT0567NB3ZBAZFz2bWp2PC81Xn7u8F2/vJxzkzNZybnemeFa7AZ2w==",
"dev": true, "dev": true,
"requires": { "requires": {
"chai": "^4.1.2",
"debug": "^4.1.0", "debug": "^4.1.0",
"deep-equal": "^1.0.0",
"json-stringify-safe": "^5.0.1", "json-stringify-safe": "^5.0.1",
"lodash": "^4.17.21", "lodash": "^4.17.5",
"propagate": "^2.0.0" "mkdirp": "^0.5.0",
"propagate": "^1.0.0",
"qs": "^6.5.1",
"semver": "^5.5.0"
},
"dependencies": {
"semver": {
"version": "5.7.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
"integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
"dev": true
}
} }
}, },
"pathval": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
"integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
"dev": true
},
"propagate": { "propagate": {
"version": "2.0.1", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", "resolved": "https://registry.npmjs.org/propagate/-/propagate-1.0.0.tgz",
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", "integrity": "sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk=",
"dev": true
},
"qs": {
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
"dev": true "dev": true
}, },
"semver": { "semver": {
@@ -293,6 +500,12 @@
"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=="
}, },
"type-detect": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
"dev": true
},
"uuid": { "uuid": {
"version": "3.3.2", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
+2 -2
View File
@@ -44,9 +44,9 @@
"uuid": "^3.3.2" "uuid": "^3.3.2"
}, },
"devDependencies": { "devDependencies": {
"@types/nock": "^11.1.0", "@types/nock": "^10.0.3",
"@types/semver": "^6.0.0", "@types/semver": "^6.0.0",
"@types/uuid": "^3.4.4", "@types/uuid": "^3.4.4",
"nock": "^13.2.9" "nock": "^10.0.6"
} }
} }
-4
View File
@@ -1,9 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
// NEEDS TO BE UPDATED TO WORK ON NODE 16 BECAUSE NPM AUDIT --JSON OUTPUT CHANGED
// THE AUDIT WORKFLOW IS ONLY RUN ON PRS, BUT IT CAN BE IGNORED AND A RELEASE CAN BE CREATED NONETHELESS
// @fhammerl @rentziass
/* /*
This script takes the output of npm audit --json from stdin This script takes the output of npm audit --json from stdin
and writes a filtered version to stdout. and writes a filtered version to stdout.