Compare commits
319 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d38e51528 | |||
| 123c3678fa | |||
| a6e9f4bab2 | |||
| 758b556388 | |||
| 9e060cb3e1 | |||
| 5501ba08b7 | |||
| 4446f00fc7 | |||
| 965dcc7493 | |||
| d464f9dd60 | |||
| c9ab4f9548 | |||
| a2986ee511 | |||
| e827417593 | |||
| b05d26b3fa | |||
| ecdfc18bf2 | |||
| e8e0ce7ad8 | |||
| dc6427f3c3 | |||
| 76339b5f68 | |||
| c0ef67ec49 | |||
| 968fd7f8d3 | |||
| 9b27fa97f9 | |||
| 065cf9f0b1 | |||
| b77f226465 | |||
| f61ae48376 | |||
| 4236fc3e78 | |||
| f366966232 | |||
| bd561a6765 | |||
| 26490f0d3b | |||
| ee91adfbc4 | |||
| a039cff4a1 | |||
| 9dd77993e7 | |||
| dd1bb93c72 | |||
| 7292b3508f | |||
| 4a47af6481 | |||
| a68693e20a | |||
| acf4bd70fb | |||
| 7ae5c2f423 | |||
| d5470e6023 | |||
| e68ab4b91a | |||
| d3a48dd52f | |||
| c4d47c1922 | |||
| 5fc5cdde44 | |||
| 2a9d836b08 | |||
| 3a3b073ef2 | |||
| d3a0fb260e | |||
| be4fdc505f | |||
| 6be37922c5 | |||
| dfc20acda2 | |||
| dc1fec82a6 | |||
| 9339b3573b | |||
| 67a08de5c7 | |||
| d73fffceed | |||
| 16f0b3d28e | |||
| 398e2cb68b | |||
| 4b9031fa77 | |||
| 959cb66bd5 | |||
| 3e0b611f99 | |||
| 83c13c81ba | |||
| bccbba401a | |||
| 3a191eecf6 | |||
| 97f5a6f0dc | |||
| 48a7cdbf9c | |||
| 3f1933edf9 | |||
| 2215c8e5aa | |||
| af6de2cb95 | |||
| 1dc58e3080 | |||
| 20596c1d96 | |||
| 557f80fd03 | |||
| 32c52bb78a | |||
| 6d9a3fe547 | |||
| 4e1c194b34 | |||
| 09cb71a033 | |||
| 2506e78e82 | |||
| f8003d52ff | |||
| e263dfb89d | |||
| 2e53bd8485 | |||
| b5e3b25b34 | |||
| b71834a510 | |||
| c6f0239e63 | |||
| c655f38a0f | |||
| cf8caa4e0d | |||
| 8734e578c6 | |||
| 74ac6db523 | |||
| 6fc2f678c8 | |||
| 5ef62e14dd | |||
| 7b29e67278 | |||
| 9d2227dbb0 | |||
| 5a8462ec27 | |||
| fcaf488df6 | |||
| 2b48e40e62 | |||
| 44ec738e27 | |||
| 3af0128b01 | |||
| e74405f68c | |||
| cc6abe3c3a | |||
| c6502bc679 | |||
| bdd6eb4293 | |||
| 6785788751 | |||
| ddf2d52556 | |||
| 7c1b12a15e | |||
| fdbf9e3ec2 | |||
| 369aa55cdc | |||
| e1191599bb | |||
| c043714a35 | |||
| 3ac6e0fdf2 | |||
| d9f9074fee | |||
| 2c52220624 | |||
| b2e6a5a284 | |||
| e48877e66c | |||
| bdddd872e3 | |||
| 8a2701f328 | |||
| eb7ff8401e | |||
| 45ec4a2087 | |||
| 02869fefb4 | |||
| 701191f50e | |||
| 539724611c | |||
| 3d01d7ed69 | |||
| d75223fd4a | |||
| 056c217a52 | |||
| d795a0ad0d | |||
| b0464628c0 | |||
| 0380590fdd | |||
| 5e183dabac | |||
| 97b7fa81c8 | |||
| 87afd16bb2 | |||
| c40fa0d905 | |||
| dc9f635a0d | |||
| 7847d31696 | |||
| 10d3b034e0 | |||
| 8eca440361 | |||
| 6ec87f46b7 | |||
| d1f9584cda | |||
| b8933d0495 | |||
| 0a988d204e | |||
| 136f9dfe37 | |||
| ed78411ffb | |||
| dd097c7f4e | |||
| f01262913d | |||
| c034e76488 | |||
| 9ca26d4946 | |||
| 417dbfff73 | |||
| 8883833d6d | |||
| 79efd648ac | |||
| e8c242695d | |||
| 48f166f6d5 | |||
| 4bc377e1b4 | |||
| bf1b64008f | |||
| 894f77901e | |||
| 7993066184 | |||
| f014075da9 | |||
| 4500de75c1 | |||
| 47017fa24b | |||
| d97deb1f60 | |||
| df111e1104 | |||
| a3588a70ba | |||
| 6b63a2bfc3 | |||
| 290017ff81 | |||
| 2a876cd69d | |||
| 7cba4c8084 | |||
| f79b906406 | |||
| 1bcc453b44 | |||
| dcae869a03 | |||
| 23769d04c7 | |||
| d3ab50471b | |||
| 1388fd1cac | |||
| 5b446d2657 | |||
| 006d6978c1 | |||
| 02afeb1577 | |||
| d47594b536 | |||
| 2823824b94 | |||
| cbc06d6766 | |||
| 9bb6708527 | |||
| be1151df02 | |||
| 130842f4e8 | |||
| ab82301c62 | |||
| fea4f6b5c5 | |||
| d3ade9ecfc | |||
| fb592eec03 | |||
| 70e79399a2 | |||
| acb230b99a | |||
| 5e0fa1aaaa | |||
| ac2468e605 | |||
| 3c8fcfce19 | |||
| 45467b9199 | |||
| 700a55077d | |||
| 6fa8f07827 | |||
| d16e86a709 | |||
| ae3ac0db0c | |||
| b319d6afff | |||
| b8ac8fc14a | |||
| 028d621193 | |||
| b0d901f9c2 | |||
| 394e804dc8 | |||
| d402248c45 | |||
| 66e8437b3e | |||
| 9c7501a5f3 | |||
| 3b4b5725f0 | |||
| 9a364e607b | |||
| 625c3f4856 | |||
| 1c3a637017 | |||
| ec0ca1b19b | |||
| 57cd003e61 | |||
| b5befc6c6d | |||
| 88a490d2ce | |||
| a8d1fb0687 | |||
| 347c887e54 | |||
| d5af54ee78 | |||
| 44b9401378 | |||
| fb5ae2a0e0 | |||
| 8024983ab0 | |||
| d44f9b8f13 | |||
| 9b4ee219ef | |||
| ee5d8970ad | |||
| 2874e3a741 | |||
| ad4afeeff1 | |||
| f9bdf6a054 | |||
| 59c7ebde79 | |||
| 0c907a43d3 | |||
| d1c1fc4108 | |||
| 36f30e6d37 | |||
| 308e05bc50 | |||
| 33a9b6c09c | |||
| ddc5fa4ae8 | |||
| 9b08f07cd3 | |||
| d26e9423f4 | |||
| 714f93aedc | |||
| 844423665b | |||
| f2ba502b92 | |||
| 1db3130eb3 | |||
| ca8a35d78f | |||
| f7f057193f | |||
| 8e146e124e | |||
| 1ea77a84d7 | |||
| 7da95b182e | |||
| 7c689a5156 | |||
| 8c6c662cda | |||
| 3898ed70c4 | |||
| 9a41b33065 | |||
| 7aea3e735f | |||
| b1eb18b224 | |||
| 48e42b1fdd | |||
| b738f10ef3 | |||
| 8f32f385e0 | |||
| 011f07d1dc | |||
| aa7077acfb | |||
| 86207b5042 | |||
| 523ce8ccda | |||
| f58042f9cc | |||
| 091616a0b8 | |||
| 8da1e670b6 | |||
| 06f7fd9df1 | |||
| 0fe20e9d56 | |||
| f82db4c00b | |||
| b8cca0c71f | |||
| 6f0cb0c45e | |||
| 944ede4d09 | |||
| 227b1ce741 | |||
| 447ee85f36 | |||
| a6be3de743 | |||
| 26b94036cb | |||
| f3e6fb165e | |||
| 3a607d0f00 | |||
| c9316bb4a7 | |||
| ec43e5810d | |||
| 01715621b0 | |||
| 6c64260c6d | |||
| bf3fc9226a | |||
| c6723084aa | |||
| bcb928642f | |||
| 8c3fc9ed99 | |||
| 1ef3214cee | |||
| ece2273b24 | |||
| 717b895584 | |||
| 8ff772deb1 | |||
| 8a3652e16d | |||
| eb6226501b | |||
| d65ee66d9b | |||
| 6d3feab2bf | |||
| 79e1d8bb74 | |||
| a0907ed2e2 | |||
| bd54a2413a | |||
| 89397db14b | |||
| d48d6b62a4 | |||
| bab3dcf7f3 | |||
| c51178a15e | |||
| bbc6082700 | |||
| cf3aaeb491 | |||
| cf4886cccb | |||
| 0c5da92b52 | |||
| 513216f1dd | |||
| 3c90578c30 | |||
| be5a2ce677 | |||
| 683703c114 | |||
| c28e7d4d5f | |||
| 12e323ae30 | |||
| dbb1ea35ff | |||
| f31c2921c1 | |||
| 41b3ce3141 | |||
| 8d8a914a94 | |||
| 36db4d62ad | |||
| a25b686a45 | |||
| 957610a37a | |||
| 6ed621e7d1 | |||
| 8007c1c535 | |||
| 6444290c57 | |||
| f32d6bc043 | |||
| 2e4ab87130 | |||
| ef199a9ab0 | |||
| 917a43eb6e | |||
| 07cac0a6b3 | |||
| 2046ee6d6b | |||
| 2b476323c4 | |||
| aebe304a19 | |||
| e8f276a715 | |||
| d156bcaa78 | |||
| 5ae4c5be28 | |||
| d50f1ac1b9 | |||
| 87cb7035bb | |||
| 1b1e81526b | |||
| 525ebf0c50 | |||
| 07341e11d8 |
@@ -0,0 +1,27 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/artifact"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
groups:
|
||||
# Group minor and patch updates together but keep major separate
|
||||
artifact-minor-patch:
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/cache"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
groups:
|
||||
# Group minor and patch updates together but keep major separate
|
||||
cache-minor-patch:
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
||||
@@ -22,12 +22,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 24.x
|
||||
|
||||
# Need root node_modules because certain npm packages like jest are configured for the entire repository and it won't be possible
|
||||
# without these to just compile the artifacts package
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
echo -n 'hello from file 2' > artifact-path/second.txt
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const {default: artifact} = require('./packages/artifact/lib/artifact')
|
||||
@@ -77,12 +77,12 @@ jobs:
|
||||
needs: [upload]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 24.x
|
||||
|
||||
# Need root node_modules because certain npm packages like jest are configured for the entire repository and it won't be possible
|
||||
# without these to just compile the artifacts package
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
working-directory: packages/artifact
|
||||
|
||||
- name: List and Download Artifacts
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const {default: artifactClient} = require('./packages/artifact/lib/artifact')
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
}
|
||||
}
|
||||
- name: Delete Artifacts
|
||||
uses: actions/github-script@v7
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const {default: artifactClient} = require('./packages/artifact/lib/artifact')
|
||||
|
||||
@@ -18,12 +18,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 24.x
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
|
||||
@@ -22,12 +22,12 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 24.x
|
||||
|
||||
# In order to save & restore cache from a shell script, certain env variables need to be set that are only available in the
|
||||
# node context. This runs a local action that gets and sets the necessary env variables that are needed
|
||||
@@ -39,9 +39,11 @@ jobs:
|
||||
- name: Install root npm packages
|
||||
run: npm ci
|
||||
|
||||
# We need to install only runtime dependencies (omit dev dependencies) to verify that what we're shipping is all
|
||||
# that is needed
|
||||
- name: Compile cache package
|
||||
run: |
|
||||
npm ci
|
||||
npm ci --omit=dev
|
||||
npm run tsc
|
||||
working-directory: packages/cache
|
||||
|
||||
|
||||
@@ -17,16 +17,16 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- shell: bash
|
||||
run: |
|
||||
rm "C:\Program Files\Git\usr\bin\tar.exe"
|
||||
|
||||
- name: Set Node.js 20.x
|
||||
uses: actions/setup-node@v1
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 24.x
|
||||
|
||||
# In order to save & restore cache from a shell script, certain env variables need to be set that are only available in the
|
||||
# node context. This runs a local action that gets and sets the necessary env variables that are needed
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
@@ -28,15 +28,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: setup repo
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: verify package exists
|
||||
run: ls packages/${{ github.event.inputs.package }}
|
||||
|
||||
- name: Set Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 20.x
|
||||
node-version: 24.x
|
||||
|
||||
- name: npm install
|
||||
run: npm install
|
||||
@@ -69,16 +69,16 @@ jobs:
|
||||
id-token: write
|
||||
steps:
|
||||
|
||||
- name: Set Node.js 24.x
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 24.x
|
||||
|
||||
- name: download artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ github.event.inputs.package }}
|
||||
|
||||
- name: setup authentication
|
||||
run: echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >> .npmrc
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: publish
|
||||
run: npm publish --provenance *.tgz
|
||||
|
||||
|
||||
@@ -18,19 +18,19 @@ jobs:
|
||||
matrix:
|
||||
runs-on: [ubuntu-latest, macos-latest-large, windows-latest]
|
||||
|
||||
# Node 18 is the current default Node version in hosted runners, so users may still use the toolkit with it when running tests (see https://github.com/actions/toolkit/issues/1841)
|
||||
# Node 20 is the currently support Node version for actions - https://docs.github.com/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runsusing-for-javascript-actions
|
||||
node-version: [18.x, 20.x]
|
||||
# Node 20 is the currently supported stable Node version for actions - https://docs.github.com/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runsusing-for-javascript-actions
|
||||
# Node 24 is the new version being added with support in actions runners
|
||||
node-version: [20.x, 24.x]
|
||||
fail-fast: false
|
||||
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set up Node ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
if: ${{ github.repository_owner == 'actions' }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Update Octokit
|
||||
working-directory: packages/github
|
||||
run: |
|
||||
|
||||
@@ -24,7 +24,7 @@ The GitHub Actions ToolKit provides a set of packages to make creating actions e
|
||||
Provides functions for inputs, outputs, results, logging, secrets and variables. Read more [here](packages/core)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/core
|
||||
npm install @actions/core
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -33,7 +33,7 @@ $ npm install @actions/core
|
||||
Provides functions to exec cli tools and process output. Read more [here](packages/exec)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/exec
|
||||
npm install @actions/exec
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -42,7 +42,7 @@ $ npm install @actions/exec
|
||||
Provides functions to search for files matching glob patterns. Read more [here](packages/glob)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/glob
|
||||
npm install @actions/glob
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -51,7 +51,7 @@ $ npm install @actions/glob
|
||||
A lightweight HTTP client optimized for building actions. Read more [here](packages/http-client)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/http-client
|
||||
npm install @actions/http-client
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -60,7 +60,7 @@ $ npm install @actions/http-client
|
||||
Provides disk i/o functions like cp, mv, rmRF, which etc. Read more [here](packages/io)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/io
|
||||
npm install @actions/io
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -71,7 +71,7 @@ Provides functions for downloading and caching tools. e.g. setup-* actions. Rea
|
||||
See @actions/cache for caching workflow dependencies.
|
||||
|
||||
```bash
|
||||
$ npm install @actions/tool-cache
|
||||
npm install @actions/tool-cache
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -80,7 +80,7 @@ $ npm install @actions/tool-cache
|
||||
Provides an Octokit client hydrated with the context that the current action is being run in. Read more [here](packages/github)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/github
|
||||
npm install @actions/github
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -89,7 +89,7 @@ $ npm install @actions/github
|
||||
Provides functions to interact with actions artifacts. Read more [here](packages/artifact)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/artifact
|
||||
npm install @actions/artifact
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -98,7 +98,7 @@ $ npm install @actions/artifact
|
||||
Provides functions to cache dependencies and build outputs to improve workflow execution time. Read more [here](packages/cache)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/cache
|
||||
npm install @actions/cache
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -107,7 +107,7 @@ $ npm install @actions/cache
|
||||
Provides functions to write attestations for workflow artifacts. Read more [here](packages/attest)
|
||||
|
||||
```bash
|
||||
$ npm install @actions/attest
|
||||
npm install @actions/attest
|
||||
```
|
||||
<br/>
|
||||
|
||||
@@ -227,9 +227,23 @@ console.log(`We can even get context data, like the repo: ${context.repo.repo}`)
|
||||
```
|
||||
<br/>
|
||||
|
||||
## Contributing
|
||||
## Note
|
||||
|
||||
We welcome contributions. See [how to contribute](.github/CONTRIBUTING.md).
|
||||
Thank you for your interest in this GitHub repo, however, right now we are not taking contributions.
|
||||
|
||||
We continue to focus our resources on strategic areas that help our customers be successful while making developers' lives easier. While GitHub Actions remains a key part of this vision, we are allocating resources towards other areas of Actions and are not taking contributions to this repository at this time. The GitHub public roadmap is the best place to follow along for any updates on features we’re working on and what stage they’re in.
|
||||
|
||||
We are taking the following steps to better direct requests related to GitHub Actions, including:
|
||||
|
||||
1. We will be directing questions and support requests to our [Community Discussions area](https://github.com/orgs/community/discussions/categories/actions)
|
||||
|
||||
2. High Priority bugs can be reported through Community Discussions or you can report these to our support team https://support.github.com/contact/bug-report.
|
||||
|
||||
3. Security Issues should be handled as per our [security.md](SECURITY.md).
|
||||
|
||||
We will still provide security updates for this project and fix major breaking changes during this time.
|
||||
|
||||
You are welcome to still raise bugs in this repo.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
os: [ubuntu-16.04, windows-2019]
|
||||
runs-on: ${{matrix.os}}
|
||||
actions:
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
version: ${{matrix.node}}
|
||||
- run: |
|
||||
|
||||
@@ -18,7 +18,7 @@ e.g. To use https://github.com/actions/setup-node, users will author:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
using: actions/setup-node@v4
|
||||
using: actions/setup-node@v5
|
||||
```
|
||||
|
||||
# Define Metadata
|
||||
|
||||
+23
-2
@@ -4,8 +4,29 @@ module.exports = {
|
||||
roots: ['<rootDir>/packages'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/__tests__/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1',
|
||||
'^@actions/io$': '<rootDir>/packages/io/lib/io.js',
|
||||
'^@actions/io/lib/io-util$': '<rootDir>/packages/io/lib/io-util.js',
|
||||
'^@actions/http-client$': '<rootDir>/packages/http-client/lib/index.js',
|
||||
'^@actions/http-client/lib/auth$': '<rootDir>/packages/http-client/lib/auth.js',
|
||||
'^@actions/github$': '<rootDir>/packages/github/lib/github.js',
|
||||
'^@actions/github/lib/utils$': '<rootDir>/packages/github/lib/utils.js'
|
||||
},
|
||||
transform: {
|
||||
'^.+\\.(ts|js)$': ['ts-jest', {
|
||||
isolatedModules: true,
|
||||
diagnostics: {warnOnly: true},
|
||||
tsconfig: {
|
||||
allowJs: true,
|
||||
esModuleInterop: true,
|
||||
module: 'commonjs',
|
||||
moduleResolution: 'node'
|
||||
}
|
||||
}]
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'/node_modules/(?!(@octokit|@actions/github|@actions/http-client|@actions/io|universal-user-agent|before-after-hook)/)'
|
||||
],
|
||||
verbose: true
|
||||
}
|
||||
|
||||
Generated
+6685
-4916
File diff suppressed because it is too large
Load Diff
+16
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "root",
|
||||
"private": true,
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"audit-all": "lerna run audit-moderate",
|
||||
"bootstrap": "lerna exec -- npm install",
|
||||
@@ -17,7 +17,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.4",
|
||||
"@types/node": "^20.5.7",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/signale": "^1.4.1",
|
||||
"concurrently": "^6.1.0",
|
||||
"eslint": "^8.0.1",
|
||||
@@ -32,5 +32,19 @@
|
||||
"prettier": "^3.0.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"overrides": {
|
||||
"semver": "^7.6.0",
|
||||
"tar": "^6.2.1",
|
||||
"@octokit/plugin-paginate-rest": "^14.0.0",
|
||||
"@octokit/request": "^10.0.7",
|
||||
"@octokit/request-error": "^7.1.0",
|
||||
"@octokit/core": "^7.0.6",
|
||||
"tmp": "^0.2.4",
|
||||
"@types/node": "^24.1.0",
|
||||
"brace-expansion": "^2.0.2",
|
||||
"form-data": "^4.0.4",
|
||||
"uri-js": "npm:uri-js-replace@^1.0.1",
|
||||
"node-fetch": "^3.3.2"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,31 @@
|
||||
# @actions/artifact Releases
|
||||
|
||||
### 5.0.3
|
||||
|
||||
- Bump `@actions/http-client` to `3.0.2`
|
||||
|
||||
### 5.0.1
|
||||
|
||||
- Fix Node.js 24 punycode deprecation warning by updating `@azure/storage-blob` from `^12.15.0` to `^12.29.1` [#2211](https://github.com/actions/toolkit/pull/2211)
|
||||
- Removed direct `@azure/core-http` dependency (now uses `@azure/core-rest-pipeline` via storage-blob)
|
||||
|
||||
### 5.0.0
|
||||
|
||||
- Dependency updates for Node.js 24 runtime support
|
||||
- Update `@actions/core` to v2
|
||||
- Update `@actions/http-client` to v3
|
||||
|
||||
### 4.0.0
|
||||
|
||||
- Add support for Node 24 [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
- Fix: artifact pagination bugs and configurable artifact count limits [#2165](https://github.com/actions/toolkit/pull/2165)
|
||||
- Fix: reject the promise on timeout [#2124](https://github.com/actions/toolkit/pull/2124)
|
||||
- Update dependency versions
|
||||
|
||||
### 2.3.3
|
||||
|
||||
- Dependency updates [#2049](https://github.com/actions/toolkit/pull/2049)
|
||||
|
||||
### 2.3.2
|
||||
|
||||
- Added masking for Shared Access Signature (SAS) artifact URLs [#1982](https://github.com/actions/toolkit/pull/1982)
|
||||
@@ -15,7 +41,7 @@
|
||||
|
||||
### 2.2.2
|
||||
|
||||
- Default concurrency to 5 for uploading artifacts [#1962](https://github.com/actions/toolkit/pull/1962
|
||||
- Default concurrency to 5 for uploading artifacts [#1962](https://github.com/actions/toolkit/pull/1962)
|
||||
|
||||
### 2.2.1
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import * as config from '../src/internal/shared/config'
|
||||
import os from 'os'
|
||||
|
||||
// Mock the 'os' module
|
||||
jest.mock('os', () => ({
|
||||
cpus: jest.fn()
|
||||
}))
|
||||
// Mock the `cpus()` function in the `os` module
|
||||
jest.mock('os', () => {
|
||||
const osActual = jest.requireActual('os')
|
||||
return {
|
||||
...osActual,
|
||||
cpus: jest.fn()
|
||||
}
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules()
|
||||
@@ -101,3 +105,45 @@ describe('uploadConcurrencyEnv', () => {
|
||||
}).toThrow()
|
||||
})
|
||||
})
|
||||
|
||||
describe('getMaxArtifactListCount', () => {
|
||||
beforeEach(() => {
|
||||
delete process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT
|
||||
})
|
||||
|
||||
it('should return default 1000 when no env set', () => {
|
||||
expect(config.getMaxArtifactListCount()).toBe(1000)
|
||||
})
|
||||
|
||||
it('should return value set in ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT', () => {
|
||||
process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT = '2000'
|
||||
expect(config.getMaxArtifactListCount()).toBe(2000)
|
||||
})
|
||||
|
||||
it('should throw if value set in ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT is invalid', () => {
|
||||
process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT = 'abc'
|
||||
expect(() => {
|
||||
config.getMaxArtifactListCount()
|
||||
}).toThrow(
|
||||
'Invalid value set for ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT env variable'
|
||||
)
|
||||
})
|
||||
|
||||
it('should throw if ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT is < 1', () => {
|
||||
process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT = '0'
|
||||
expect(() => {
|
||||
config.getMaxArtifactListCount()
|
||||
}).toThrow(
|
||||
'Invalid value set for ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT env variable'
|
||||
)
|
||||
})
|
||||
|
||||
it('should throw if ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT is negative', () => {
|
||||
process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT = '-100'
|
||||
expect(() => {
|
||||
config.getMaxArtifactListCount()
|
||||
}).toThrow(
|
||||
'Invalid value set for ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT env variable'
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -111,6 +111,16 @@ const mockGetArtifactSuccess = jest.fn(() => {
|
||||
}
|
||||
})
|
||||
|
||||
const mockGetArtifactHung = jest.fn(() => {
|
||||
const message = new http.IncomingMessage(new net.Socket())
|
||||
message.statusCode = 200
|
||||
// Don't push any data or call push(null) to end the stream
|
||||
// This creates a stream that hangs and never completes
|
||||
return {
|
||||
message
|
||||
}
|
||||
})
|
||||
|
||||
const mockGetArtifactFailure = jest.fn(() => {
|
||||
const message = new http.IncomingMessage(new net.Socket())
|
||||
message.statusCode = 500
|
||||
@@ -611,4 +621,32 @@ describe('download-artifact', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('streamExtractExternal', () => {
|
||||
it('should fail if the timeout is exceeded', async () => {
|
||||
const mockSlowGetArtifact = jest.fn(mockGetArtifactHung)
|
||||
|
||||
const mockHttpClient = (HttpClient as jest.Mock).mockImplementation(
|
||||
() => {
|
||||
return {
|
||||
get: mockSlowGetArtifact
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
try {
|
||||
await streamExtractExternal(
|
||||
fixtures.blobStorageUrl,
|
||||
fixtures.workspaceDir,
|
||||
{timeout: 2}
|
||||
)
|
||||
expect(true).toBe(false) // should not be called
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(Error)
|
||||
expect(e.message).toContain('did not respond in 2ms')
|
||||
expect(mockHttpClient).toHaveBeenCalledWith(getUserAgentString())
|
||||
expect(mockSlowGetArtifact).toHaveBeenCalledTimes(1)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -170,6 +170,126 @@ describe('list-artifact', () => {
|
||||
)
|
||||
).rejects.toThrow('boom')
|
||||
})
|
||||
|
||||
it('should handle pagination correctly when fetching multiple pages', async () => {
|
||||
const mockRequest = github.getOctokit(fixtures.token)
|
||||
.request as MockedRequest
|
||||
|
||||
const manyArtifacts = Array.from({length: 150}, (_, i) => ({
|
||||
id: i + 1,
|
||||
name: `artifact-${i + 1}`,
|
||||
size: 100,
|
||||
createdAt: new Date('2023-12-01')
|
||||
}))
|
||||
|
||||
mockRequest
|
||||
.mockResolvedValueOnce({
|
||||
status: 200,
|
||||
headers: {},
|
||||
url: '',
|
||||
data: {
|
||||
...artifactsToListResponse(manyArtifacts.slice(0, 100)),
|
||||
total_count: 150
|
||||
}
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
status: 200,
|
||||
headers: {},
|
||||
url: '',
|
||||
data: {
|
||||
...artifactsToListResponse(manyArtifacts.slice(100, 150)),
|
||||
total_count: 150
|
||||
}
|
||||
})
|
||||
|
||||
const response = await listArtifactsPublic(
|
||||
fixtures.runId,
|
||||
fixtures.owner,
|
||||
fixtures.repo,
|
||||
fixtures.token,
|
||||
false
|
||||
)
|
||||
|
||||
// Verify that both API calls were made
|
||||
expect(mockRequest).toHaveBeenCalledTimes(2)
|
||||
|
||||
// Should return all 150 artifacts across both pages
|
||||
expect(response.artifacts).toHaveLength(150)
|
||||
|
||||
// Verify we got artifacts from both pages
|
||||
expect(response.artifacts[0].name).toBe('artifact-1')
|
||||
expect(response.artifacts[99].name).toBe('artifact-100')
|
||||
expect(response.artifacts[100].name).toBe('artifact-101')
|
||||
expect(response.artifacts[149].name).toBe('artifact-150')
|
||||
})
|
||||
|
||||
it('should respect ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT environment variable', async () => {
|
||||
const originalEnv = process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT
|
||||
process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT = '150'
|
||||
|
||||
jest.resetModules()
|
||||
|
||||
try {
|
||||
const {listArtifactsPublic: listArtifactsPublicReloaded} = await import(
|
||||
'../src/internal/find/list-artifacts'
|
||||
)
|
||||
const githubReloaded = await import('@actions/github')
|
||||
|
||||
const mockRequest = (githubReloaded.getOctokit as jest.Mock)(
|
||||
fixtures.token
|
||||
).request as MockedRequest
|
||||
|
||||
const manyArtifacts = Array.from({length: 200}, (_, i) => ({
|
||||
id: i + 1,
|
||||
name: `artifact-${i + 1}`,
|
||||
size: 100,
|
||||
createdAt: new Date('2023-12-01')
|
||||
}))
|
||||
|
||||
mockRequest
|
||||
.mockResolvedValueOnce({
|
||||
status: 200,
|
||||
headers: {},
|
||||
url: '',
|
||||
data: {
|
||||
...artifactsToListResponse(manyArtifacts.slice(0, 100)),
|
||||
total_count: 200
|
||||
}
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
status: 200,
|
||||
headers: {},
|
||||
url: '',
|
||||
data: {
|
||||
...artifactsToListResponse(manyArtifacts.slice(100, 150)),
|
||||
total_count: 200
|
||||
}
|
||||
})
|
||||
|
||||
const response = await listArtifactsPublicReloaded(
|
||||
fixtures.runId,
|
||||
fixtures.owner,
|
||||
fixtures.repo,
|
||||
fixtures.token,
|
||||
false
|
||||
)
|
||||
|
||||
// Should only return 150 artifacts due to the limit
|
||||
expect(response.artifacts).toHaveLength(150)
|
||||
expect(response.artifacts[0].name).toBe('artifact-1')
|
||||
expect(response.artifacts[149].name).toBe('artifact-150')
|
||||
} finally {
|
||||
// Restore original environment variable
|
||||
if (originalEnv !== undefined) {
|
||||
process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT = originalEnv
|
||||
} else {
|
||||
delete process.env.ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT
|
||||
}
|
||||
|
||||
// Reset modules again to restore original state
|
||||
jest.resetModules()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('internal', () => {
|
||||
|
||||
@@ -108,7 +108,7 @@ describe('upload-artifact', () => {
|
||||
fixtures.files.map(file => ({
|
||||
sourcePath: path.join(fixtures.uploadDirectory, file.name),
|
||||
destinationPath: file.name,
|
||||
stats: new fs.Stats()
|
||||
stats: fs.statSync(path.join(fixtures.uploadDirectory, file.name))
|
||||
}))
|
||||
)
|
||||
jest.spyOn(config, 'getRuntimeToken').mockReturnValue(fixtures.runtimeToken)
|
||||
|
||||
Generated
+944
-608
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/artifact",
|
||||
"version": "2.3.2",
|
||||
"version": "5.0.3",
|
||||
"preview": true,
|
||||
"description": "Actions artifact lib",
|
||||
"keywords": [
|
||||
@@ -40,14 +40,15 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/github": "^5.1.1",
|
||||
"@actions/http-client": "^2.1.0",
|
||||
"@azure/storage-blob": "^12.15.0",
|
||||
"@octokit/core": "^3.5.1",
|
||||
"@actions/core": "^2.0.0",
|
||||
"@actions/github": "^6.0.1",
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@azure/storage-blob": "^12.29.1",
|
||||
"@octokit/core": "^5.2.1",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
"@octokit/plugin-retry": "^3.0.9",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/request": "^8.4.1",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@protobuf-ts/plugin": "^2.2.3-alpha.1",
|
||||
"archiver": "^7.0.1",
|
||||
"jwt-decode": "^3.1.2",
|
||||
@@ -56,8 +57,12 @@
|
||||
"devDependencies": {
|
||||
"@types/archiver": "^5.3.2",
|
||||
"@types/unzip-stream": "^0.3.4",
|
||||
"typedoc": "^0.25.4",
|
||||
"typedoc": "^0.28.13",
|
||||
"typedoc-plugin-markdown": "^3.17.1",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"overrides": {
|
||||
"uri-js": "npm:uri-js-replace@^1.0.1",
|
||||
"node-fetch": "^3.3.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,8 @@ async function streamExtract(
|
||||
|
||||
export async function streamExtractExternal(
|
||||
url: string,
|
||||
directory: string
|
||||
directory: string,
|
||||
opts: {timeout: number} = {timeout: 30 * 1000}
|
||||
): Promise<StreamExtractResponse> {
|
||||
const client = new httpClient.HttpClient(getUserAgentString())
|
||||
const response = await client.get(url)
|
||||
@@ -74,16 +75,17 @@ export async function streamExtractExternal(
|
||||
)
|
||||
}
|
||||
|
||||
const timeout = 30 * 1000 // 30 seconds
|
||||
let sha256Digest: string | undefined = undefined
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const timerFn = (): void => {
|
||||
response.message.destroy(
|
||||
new Error(`Blob storage chunk did not respond in ${timeout}ms`)
|
||||
const timeoutError = new Error(
|
||||
`Blob storage chunk did not respond in ${opts.timeout}ms`
|
||||
)
|
||||
response.message.destroy(timeoutError)
|
||||
reject(timeoutError)
|
||||
}
|
||||
const timer = setTimeout(timerFn, timeout)
|
||||
const timer = setTimeout(timerFn, opts.timeout)
|
||||
|
||||
const hashStream = crypto.createHash('sha256').setEncoding('hex')
|
||||
const passThrough = new stream.PassThrough()
|
||||
|
||||
@@ -9,12 +9,12 @@ import {retry} from '@octokit/plugin-retry'
|
||||
import {OctokitOptions} from '@octokit/core/dist-types/types'
|
||||
import {internalArtifactTwirpClient} from '../shared/artifact-twirp-client'
|
||||
import {getBackendIdsFromToken} from '../shared/util'
|
||||
import {getMaxArtifactListCount} from '../shared/config'
|
||||
import {ListArtifactsRequest, Timestamp} from '../../generated'
|
||||
|
||||
// Limiting to 1000 for perf reasons
|
||||
const maximumArtifactCount = 1000
|
||||
const maximumArtifactCount = getMaxArtifactListCount()
|
||||
const paginationCount = 100
|
||||
const maxNumberOfPages = maximumArtifactCount / paginationCount
|
||||
const maxNumberOfPages = Math.ceil(maximumArtifactCount / paginationCount)
|
||||
|
||||
export async function listArtifactsPublic(
|
||||
workflowRunId: number,
|
||||
@@ -59,7 +59,7 @@ export async function listArtifactsPublic(
|
||||
const totalArtifactCount = listArtifactResponse.total_count
|
||||
if (totalArtifactCount > maximumArtifactCount) {
|
||||
warning(
|
||||
`Workflow run ${workflowRunId} has more than 1000 artifacts. Results will be incomplete as only the first ${maximumArtifactCount} artifacts will be returned`
|
||||
`Workflow run ${workflowRunId} has ${totalArtifactCount} artifacts, exceeding the limit of ${maximumArtifactCount}. Results will be incomplete as only the first ${maximumArtifactCount} artifacts will be returned`
|
||||
)
|
||||
numberOfPages = maxNumberOfPages
|
||||
}
|
||||
@@ -81,7 +81,7 @@ export async function listArtifactsPublic(
|
||||
// Iterate over any remaining pages
|
||||
for (
|
||||
currentPageNumber;
|
||||
currentPageNumber < numberOfPages;
|
||||
currentPageNumber <= numberOfPages;
|
||||
currentPageNumber++
|
||||
) {
|
||||
debug(`Fetching page ${currentPageNumber} of artifact list`)
|
||||
|
||||
@@ -97,3 +97,19 @@ export function getUploadChunkTimeout(): number {
|
||||
|
||||
return timeout
|
||||
}
|
||||
|
||||
// This value can be changed with ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT variable.
|
||||
// Defaults to 1000 as a safeguard for rate limiting.
|
||||
export function getMaxArtifactListCount(): number {
|
||||
const maxCountVar =
|
||||
process.env['ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT'] || '1000'
|
||||
|
||||
const maxCount = parseInt(maxCountVar)
|
||||
if (isNaN(maxCount) || maxCount < 1) {
|
||||
throw new Error(
|
||||
'Invalid value set for ACTIONS_ARTIFACT_MAX_ARTIFACT_COUNT env variable'
|
||||
)
|
||||
}
|
||||
|
||||
return maxCount
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {BlobClient, BlockBlobUploadStreamOptions} from '@azure/storage-blob'
|
||||
import {TransferProgressEvent} from '@azure/core-http'
|
||||
import {TransferProgressEvent} from '@azure/core-http-compat'
|
||||
import {ZipUploadStream} from './zip'
|
||||
import {
|
||||
getUploadChunkSize,
|
||||
|
||||
@@ -15,6 +15,14 @@ initiated.
|
||||
See [Using artifact attestations to establish provenance for builds](https://docs.github.com/en/actions/security-guides/using-artifact-attestations-to-establish-provenance-for-builds)
|
||||
for more information on artifact attestations.
|
||||
|
||||
## Table of Contents
|
||||
- [Usage](#usage)
|
||||
- [attest](#attest)
|
||||
- [attestProvenance](#attestprovenance)
|
||||
- [Attestation](#attestation)
|
||||
- [Sigstore Instance](#sigstore-instance)
|
||||
- [Storage](#storage)
|
||||
|
||||
## Usage
|
||||
|
||||
### `attest`
|
||||
@@ -165,6 +173,74 @@ export type Attestation = {
|
||||
For details about the Sigstore bundle format, see the [Bundle protobuf
|
||||
specification](https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto).
|
||||
|
||||
### createStorageRecord
|
||||
|
||||
The `createStorageRecord` function creates an
|
||||
[artifact metadata storage record](https://docs.github.com/en/rest/orgs/artifact-metadata?apiVersion=2022-11-28#create-artifact-metadata-storage-record)
|
||||
on behalf of an attested artifact. It accepts parameters defining artifact
|
||||
and package registry details. The storage record contains metadata about where the artifact is stored on a given package registry.
|
||||
|
||||
```js
|
||||
const { createStorageRecord } = require('@actions/attest');
|
||||
const core = require('@actions/core');
|
||||
|
||||
async function run() {
|
||||
// In order to persist attestations to the repo, this should be a token with
|
||||
// repository write permissions.
|
||||
const ghToken = core.getInput('gh-token');
|
||||
|
||||
const record = await createStorageRecord(
|
||||
artifactOptions: {
|
||||
name: 'my-artifact-name',
|
||||
digest: { 'sha256': '36ab4667...'},
|
||||
version: "v1.0.0"
|
||||
},
|
||||
packageRegistryOptions: {
|
||||
registryUrl: "https://my-fave-pkg-registry.com"
|
||||
},
|
||||
token: ghToken
|
||||
);
|
||||
|
||||
console.log(record);
|
||||
}
|
||||
|
||||
run();
|
||||
```
|
||||
|
||||
The `createStorageRecord` function supports the following options:
|
||||
|
||||
```typescript
|
||||
// Artifact details to associate the record with
|
||||
export type ArtifactOptions = {
|
||||
// The name of the artifact
|
||||
name: string
|
||||
// The digest of the artifact
|
||||
digest: string
|
||||
// The version of the artifact
|
||||
version?: string
|
||||
// The status of the artifact
|
||||
status?: string
|
||||
}
|
||||
// Includes details about the package registry the artifact was published to
|
||||
export type PackageRegistryOptions = {
|
||||
// The URL of the package registry
|
||||
registryUrl: string
|
||||
// The URL of the artifact in the package registry
|
||||
artifactUrl?: string
|
||||
// The package registry repository the artifact was published to.
|
||||
repo?: string
|
||||
// The path of the artifact in the package registry repository.
|
||||
path?: string
|
||||
}
|
||||
// GitHub token for writing attestations.
|
||||
token: string
|
||||
// Optional parameters for the write operation.
|
||||
// The number of times to retry the request.
|
||||
retryAttempts?: number
|
||||
// HTTP headers to include in request to Artifact Metadata API.
|
||||
headers?: RequestHeaders
|
||||
```
|
||||
|
||||
## Sigstore Instance
|
||||
|
||||
When generating the signed attestation there are two different Sigstore
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @actions/attest Releases
|
||||
|
||||
### 2.2.1
|
||||
|
||||
- Bump `@actions/http-client` to `3.0.2`
|
||||
- Bump `undici` to `6.23.0`
|
||||
|
||||
### 2.2.0
|
||||
|
||||
- Bump @actions/core from 1.11.1 to 2.0.2
|
||||
- Bump @actions/github from 6.0.0 to 7.0.0
|
||||
- Bump @actions/http-client from 2.2.3 to 3.0.1
|
||||
|
||||
### 2.0.0
|
||||
|
||||
- Add support for Node 24 [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
- Bump @sigstore/bundle from 3.0.0 to 3.1.0
|
||||
- Bump @sigstore/sign from 3.0.0 to 3.1.0
|
||||
- Bump jose from 5.2.3 to 5.10.0
|
||||
|
||||
### 1.6.0
|
||||
|
||||
- Update `buildSLSAProvenancePredicate` to populate `workflow.ref` field from the `ref` claim in the OIDC token [#1969](https://github.com/actions/toolkit/pull/1969)
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
import {MockAgent, setGlobalDispatcher} from 'undici'
|
||||
import {createStorageRecord} from '../src/artifactMetadata'
|
||||
|
||||
describe('createStorageRecord', () => {
|
||||
const originalEnv = process.env
|
||||
const token = 'token'
|
||||
const headers = {'X-GitHub-Foo': 'true'}
|
||||
|
||||
const artifactOptions = {
|
||||
name: 'my-lib',
|
||||
version: '1.0.0',
|
||||
digest: `sha256:${'a'.repeat(64)}`
|
||||
}
|
||||
const packageRegistryOptions = {
|
||||
registryUrl: 'https://my-registry.org'
|
||||
}
|
||||
|
||||
const mockAgent = new MockAgent()
|
||||
setGlobalDispatcher(mockAgent)
|
||||
|
||||
beforeEach(() => {
|
||||
process.env = {
|
||||
...originalEnv,
|
||||
GITHUB_REPOSITORY: 'foo/bar'
|
||||
}
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
process.env = originalEnv
|
||||
})
|
||||
|
||||
describe('when the api call is successful', () => {
|
||||
beforeEach(() => {
|
||||
mockAgent
|
||||
.get('https://api.github.com')
|
||||
.intercept({
|
||||
path: '/orgs/foo/artifacts/metadata/storage-record',
|
||||
method: 'POST',
|
||||
headers: {authorization: `token ${token}`, ...headers},
|
||||
body: JSON.stringify({
|
||||
name: 'my-lib',
|
||||
version: '1.0.0',
|
||||
digest: `sha256:${'a'.repeat(64)}`,
|
||||
registry_url: 'https://my-registry.org'
|
||||
})
|
||||
})
|
||||
.reply(200, {storage_records: [{id: 123}, {id: 456}]})
|
||||
})
|
||||
|
||||
it('persists the storage record', async () => {
|
||||
await expect(
|
||||
createStorageRecord(
|
||||
artifactOptions,
|
||||
packageRegistryOptions,
|
||||
token,
|
||||
undefined,
|
||||
headers
|
||||
)
|
||||
).resolves.toEqual([123, 456])
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the api call fails', () => {
|
||||
beforeEach(() => {
|
||||
mockAgent
|
||||
.get('https://api.github.com')
|
||||
.intercept({
|
||||
path: '/orgs/foo/artifacts/metadata/storage-record',
|
||||
method: 'POST',
|
||||
headers: {authorization: `token ${token}`},
|
||||
body: JSON.stringify({
|
||||
name: 'my-lib',
|
||||
version: '1.0.0',
|
||||
digest: `sha256:${'a'.repeat(64)}`,
|
||||
registry_url: 'https://my-registry.org'
|
||||
})
|
||||
})
|
||||
.reply(500, 'oops')
|
||||
})
|
||||
|
||||
it('throws an error', async () => {
|
||||
await expect(
|
||||
createStorageRecord(
|
||||
artifactOptions,
|
||||
packageRegistryOptions,
|
||||
token,
|
||||
0,
|
||||
headers
|
||||
)
|
||||
).rejects.toThrow(/oops/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('when the api call fails but succeeds on retry', () => {
|
||||
beforeEach(() => {
|
||||
const pool = mockAgent.get('https://api.github.com')
|
||||
|
||||
pool
|
||||
.intercept({
|
||||
path: '/orgs/foo/artifacts/metadata/storage-record',
|
||||
method: 'POST',
|
||||
headers: {authorization: `token ${token}`},
|
||||
body: JSON.stringify({
|
||||
...artifactOptions,
|
||||
registry_url: packageRegistryOptions.registryUrl
|
||||
})
|
||||
})
|
||||
.reply(500, 'oops')
|
||||
.times(1)
|
||||
|
||||
pool
|
||||
.intercept({
|
||||
path: '/orgs/foo/artifacts/metadata/storage-record',
|
||||
method: 'POST',
|
||||
headers: {authorization: `token ${token}`},
|
||||
body: JSON.stringify({
|
||||
...artifactOptions,
|
||||
registry_url: packageRegistryOptions.registryUrl
|
||||
})
|
||||
})
|
||||
.reply(200, {storage_records: [{id: 123}, {id: 456}]})
|
||||
.times(1)
|
||||
})
|
||||
|
||||
it('persists the storage record', async () => {
|
||||
await expect(
|
||||
createStorageRecord(
|
||||
artifactOptions,
|
||||
packageRegistryOptions,
|
||||
token,
|
||||
undefined,
|
||||
headers
|
||||
)
|
||||
).resolves.toEqual([123, 456])
|
||||
})
|
||||
})
|
||||
})
|
||||
Generated
+427
-1745
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/attest",
|
||||
"version": "1.6.0",
|
||||
"version": "2.2.1",
|
||||
"description": "Actions attestation lib",
|
||||
"keywords": [
|
||||
"github",
|
||||
@@ -35,20 +35,20 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sigstore/mock": "^0.8.0",
|
||||
"@sigstore/mock": "^0.10.0",
|
||||
"@sigstore/rekor-types": "^3.0.0",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"nock": "^13.5.1",
|
||||
"undici": "^5.28.5"
|
||||
"undici": "^6.23.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/github": "^6.0.0",
|
||||
"@actions/http-client": "^2.2.3",
|
||||
"@actions/core": "^2.0.2",
|
||||
"@actions/github": "^7.0.0",
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@octokit/plugin-retry": "^6.0.1",
|
||||
"@sigstore/bundle": "^3.0.0",
|
||||
"@sigstore/sign": "^3.0.0",
|
||||
"jose": "^5.2.3"
|
||||
"@sigstore/bundle": "^3.1.0",
|
||||
"@sigstore/sign": "^3.1.0",
|
||||
"jose": "^5.10.0"
|
||||
},
|
||||
"overrides": {
|
||||
"@octokit/plugin-retry": {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import * as github from '@actions/github'
|
||||
import {retry} from '@octokit/plugin-retry'
|
||||
import {RequestHeaders} from '@octokit/types'
|
||||
|
||||
const CREATE_STORAGE_RECORD_REQUEST =
|
||||
'POST /orgs/{owner}/artifacts/metadata/storage-record'
|
||||
const DEFAULT_RETRY_COUNT = 5
|
||||
|
||||
/**
|
||||
* Options for creating a storage record for an attested artifact.
|
||||
*/
|
||||
export type ArtifactOptions = {
|
||||
// Includes details about the attested artifact
|
||||
// The name of the artifact
|
||||
name: string
|
||||
// The digest of the artifact
|
||||
digest: string
|
||||
// The version of the artifact
|
||||
version?: string
|
||||
// The status of the artifact
|
||||
status?: string
|
||||
}
|
||||
// Includes details about the package registry the artifact was published to
|
||||
export type PackageRegistryOptions = {
|
||||
// The URL of the package registry
|
||||
registryUrl: string
|
||||
// The URL of the artifact in the package registry
|
||||
artifactUrl?: string
|
||||
// The package registry repository the artifact was published to.
|
||||
repo?: string
|
||||
// The path of the artifact in the package registry repository.
|
||||
path?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a storage record on behalf of an artifact that has been attested
|
||||
* @param artifactOptions - parameters for the storage record API request.
|
||||
* @param packageRegistryOptions - parameters for the package registry API request.
|
||||
* @param token - GitHub token used to authenticate the request.
|
||||
* @param retryAttempts - The number of retries to attempt if the request fails.
|
||||
* @param headers - Additional headers to include in the request.
|
||||
*
|
||||
* @returns The ID of the storage record.
|
||||
* @throws Error if the storage record fails to persist.
|
||||
*/
|
||||
export async function createStorageRecord(
|
||||
artifactOptions: ArtifactOptions,
|
||||
packageRegistryOptions: PackageRegistryOptions,
|
||||
token: string,
|
||||
retryAttempts?: number,
|
||||
headers?: RequestHeaders
|
||||
): Promise<number[]> {
|
||||
const retries = retryAttempts ?? DEFAULT_RETRY_COUNT
|
||||
const octokit = github.getOctokit(token, {retry: {retries}}, retry)
|
||||
try {
|
||||
const response = await octokit.request(CREATE_STORAGE_RECORD_REQUEST, {
|
||||
owner: github.context.repo.owner,
|
||||
headers,
|
||||
...buildRequestParams(artifactOptions, packageRegistryOptions)
|
||||
})
|
||||
|
||||
const data =
|
||||
typeof response.data == 'string'
|
||||
? JSON.parse(response.data)
|
||||
: response.data
|
||||
|
||||
return data?.storage_records.map((r: {id: number}) => r.id)
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : err
|
||||
throw new Error(`Failed to persist storage record: ${message}`)
|
||||
}
|
||||
}
|
||||
|
||||
function buildRequestParams(
|
||||
artifactOptions: ArtifactOptions,
|
||||
packageRegistryOptions: PackageRegistryOptions
|
||||
): Record<string, unknown> {
|
||||
const {registryUrl, artifactUrl, ...rest} = packageRegistryOptions
|
||||
return {
|
||||
...artifactOptions,
|
||||
registry_url: registryUrl,
|
||||
artifact_url: artifactUrl,
|
||||
...rest
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export {createStorageRecord} from './artifactMetadata'
|
||||
export {AttestOptions, attest} from './attest'
|
||||
export {
|
||||
AttestProvenanceOptions,
|
||||
|
||||
@@ -29,7 +29,11 @@ export const writeAttestation = async (
|
||||
owner: github.context.repo.owner,
|
||||
repo: github.context.repo.repo,
|
||||
headers: options.headers,
|
||||
data: {bundle: attestation}
|
||||
bundle: attestation as {
|
||||
mediaType?: string
|
||||
verificationMaterial?: {[key: string]: unknown}
|
||||
dsseEnvelope?: {[key: string]: unknown}
|
||||
}
|
||||
})
|
||||
|
||||
const data =
|
||||
|
||||
Vendored
+46
@@ -1,5 +1,51 @@
|
||||
# @actions/cache Releases
|
||||
|
||||
### 5.0.5
|
||||
|
||||
- Bump `@actions/glob` to `0.5.1`
|
||||
|
||||
### 5.0.4
|
||||
|
||||
- Bump `@actions/http-client` to `3.0.2`
|
||||
|
||||
### 5.0.3
|
||||
|
||||
Prevent retries for rate limited cache operations [2243](https://github.com/actions/toolkit/pull/2243).
|
||||
|
||||
### 5.0.1
|
||||
|
||||
- Fix Node.js 24 punycode deprecation warning by updating `@azure/storage-blob` from `^12.13.0` to `^12.29.1` [#2213](https://github.com/actions/toolkit/pull/2213)
|
||||
- Newer storage-blob uses `@azure/core-rest-pipeline` instead of deprecated `@azure/core-http`, which eliminates the transitive dependency on `node-fetch@2` → `whatwg-url@5` → `tr46@0.0.3` that used the deprecated punycode module
|
||||
|
||||
### 5.0.0
|
||||
|
||||
- Remove `@azure/ms-rest-js` dependency [#2197](https://github.com/actions/toolkit/pull/2197)
|
||||
- The `TransferProgressEvent` type is now imported from `@azure/core-rest-pipeline` instead of `@azure/ms-rest-js`
|
||||
- Bump `@actions/core` from `^1.11.1` to `^2.0.0` [#2198](https://github.com/actions/toolkit/pull/2198)
|
||||
- Bump `@actions/exec` from `^1.0.1` to `^2.0.0` [#2198](https://github.com/actions/toolkit/pull/2198)
|
||||
- Bump `@actions/glob` from `^0.1.0` to `^0.5.0` [#2198](https://github.com/actions/toolkit/pull/2198)
|
||||
- Bump `@actions/http-client` from `^2.1.1` to `^3.0.0` [#2198](https://github.com/actions/toolkit/pull/2198)
|
||||
- Bump `@actions/io` from `^1.0.1` to `^2.0.0` [#2198](https://github.com/actions/toolkit/pull/2198)
|
||||
- Add support for Node.js 24 [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
- Add `node-fetch` override to resolve audit vulnerabilities [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
|
||||
### 4.1.0
|
||||
|
||||
- Remove client side 10GiB cache size limit check & update twirp client [#2118](https://github.com/actions/toolkit/pull/2118)
|
||||
|
||||
### 4.0.5
|
||||
|
||||
- Reintroduce @protobuf-ts/runtime-rpc as a runtime dependency [#2113](https://github.com/actions/toolkit/pull/2113)
|
||||
|
||||
### 4.0.4
|
||||
|
||||
⚠️ Faulty patch release. Upgrade to 4.0.5 instead.
|
||||
|
||||
- Optimized cache dependencies by moving `@protobuf-ts/plugin` to dev dependencies [#2106](https://github.com/actions/toolkit/pull/2106)
|
||||
- Improved cache service availability determination for different cache service versions (v1 and v2) [#2100](https://github.com/actions/toolkit/pull/2100)
|
||||
- Enhanced server error handling: 5xx HTTP errors are now logged as errors instead of warnings [#2099](https://github.com/actions/toolkit/pull/2099)
|
||||
- Fixed cache hit logging to properly distinguish between exact key matches and restore key matches [#2101](https://github.com/actions/toolkit/pull/2101)
|
||||
|
||||
### 4.0.3
|
||||
|
||||
- Added masking for Shared Access Signature (SAS) cache entry URLs [#1982](https://github.com/actions/toolkit/pull/1982)
|
||||
|
||||
+5
-2
@@ -3,10 +3,13 @@
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
const filePath = process.env[`GITHUB_ENV`]
|
||||
fs.appendFileSync(filePath, `ACTIONS_RUNTIME_TOKEN=${process.env.ACTIONS_RUNTIME_TOKEN}${os.EOL}`, {
|
||||
fs.appendFileSync(filePath, `ACTIONS_CACHE_SERVICE_V2=true${os.EOL}`, {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
fs.appendFileSync(filePath, `ACTIONS_CACHE_URL=${process.env.ACTIONS_CACHE_URL}${os.EOL}`, {
|
||||
fs.appendFileSync(filePath, `ACTIONS_RESULTS_URL=${process.env.ACTIONS_RESULTS_URL}${os.EOL}`, {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
fs.appendFileSync(filePath, `ACTIONS_RUNTIME_TOKEN=${process.env.ACTIONS_RUNTIME_TOKEN}${os.EOL}`, {
|
||||
encoding: 'utf8'
|
||||
})
|
||||
fs.appendFileSync(filePath, `GITHUB_RUN_ID=${process.env.GITHUB_RUN_ID}${os.EOL}`, {
|
||||
|
||||
+63
-8
@@ -1,14 +1,69 @@
|
||||
import * as cache from '../src/cache'
|
||||
|
||||
test('isFeatureAvailable returns true if server url is set', () => {
|
||||
try {
|
||||
describe('isFeatureAvailable', () => {
|
||||
const originalEnv = process.env
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules()
|
||||
process.env = {...originalEnv}
|
||||
// Clean cache-related environment variables
|
||||
delete process.env['ACTIONS_CACHE_URL']
|
||||
delete process.env['ACTIONS_RESULTS_URL']
|
||||
delete process.env['ACTIONS_CACHE_SERVICE_V2']
|
||||
delete process.env['GITHUB_SERVER_URL']
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
process.env = originalEnv
|
||||
})
|
||||
|
||||
test('returns true for cache service v1 when ACTIONS_CACHE_URL is set', () => {
|
||||
process.env['ACTIONS_CACHE_URL'] = 'http://cache.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(true)
|
||||
} finally {
|
||||
delete process.env['ACTIONS_CACHE_URL']
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
test('isFeatureAvailable returns false if server url is not set', () => {
|
||||
expect(cache.isFeatureAvailable()).toBe(false)
|
||||
test('returns false for cache service v1 when only ACTIONS_RESULTS_URL is set', () => {
|
||||
process.env['ACTIONS_RESULTS_URL'] = 'http://results.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(false)
|
||||
})
|
||||
|
||||
test('returns true for cache service v1 when both URLs are set', () => {
|
||||
process.env['ACTIONS_CACHE_URL'] = 'http://cache.com'
|
||||
process.env['ACTIONS_RESULTS_URL'] = 'http://results.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(true)
|
||||
})
|
||||
|
||||
test('returns true for cache service v2 when ACTIONS_RESULTS_URL is set', () => {
|
||||
process.env['ACTIONS_CACHE_SERVICE_V2'] = 'true'
|
||||
process.env['ACTIONS_RESULTS_URL'] = 'http://results.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(true)
|
||||
})
|
||||
|
||||
test('returns false for cache service v2 when only ACTIONS_CACHE_URL is set', () => {
|
||||
process.env['ACTIONS_CACHE_SERVICE_V2'] = 'true'
|
||||
process.env['ACTIONS_CACHE_URL'] = 'http://cache.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(false)
|
||||
})
|
||||
|
||||
test('returns false when no cache URLs are set', () => {
|
||||
expect(cache.isFeatureAvailable()).toBe(false)
|
||||
})
|
||||
|
||||
test('returns false for cache service v2 when no URLs are set', () => {
|
||||
process.env['ACTIONS_CACHE_SERVICE_V2'] = 'true'
|
||||
expect(cache.isFeatureAvailable()).toBe(false)
|
||||
})
|
||||
|
||||
test('returns true for GHES with v1 even when v2 flag is set', () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://my-enterprise.github.com'
|
||||
process.env['ACTIONS_CACHE_SERVICE_V2'] = 'true'
|
||||
process.env['ACTIONS_CACHE_URL'] = 'http://cache.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(true)
|
||||
})
|
||||
|
||||
test('returns false for GHES with only ACTIONS_RESULTS_URL', () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://my-enterprise.github.com'
|
||||
process.env['ACTIONS_RESULTS_URL'] = 'http://results.com'
|
||||
expect(cache.isFeatureAvailable()).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
import * as http from 'http'
|
||||
import * as net from 'net'
|
||||
import {HttpClient} from '@actions/http-client'
|
||||
import * as core from '@actions/core'
|
||||
import * as config from '../src/internal/config'
|
||||
import * as cacheUtils from '../src/internal/cacheUtils'
|
||||
import {internalCacheTwirpClient} from '../src/internal/shared/cacheTwirpClient'
|
||||
|
||||
jest.mock('@actions/http-client')
|
||||
|
||||
const clientOptions = {
|
||||
maxAttempts: 5,
|
||||
retryIntervalMs: 1,
|
||||
retryMultiplier: 1.5
|
||||
}
|
||||
|
||||
// noopLogs mocks the console.log and core.* functions to prevent output in the console while testing
|
||||
const noopLogs = (): void => {
|
||||
jest.spyOn(console, 'log').mockImplementation(() => {})
|
||||
jest.spyOn(core, 'debug').mockImplementation(() => {})
|
||||
jest.spyOn(core, 'info').mockImplementation(() => {})
|
||||
jest.spyOn(core, 'warning').mockImplementation(() => {})
|
||||
}
|
||||
|
||||
describe('cacheTwirpClient', () => {
|
||||
beforeAll(() => {
|
||||
noopLogs()
|
||||
jest
|
||||
.spyOn(config, 'getCacheServiceURL')
|
||||
.mockReturnValue('http://localhost:8080')
|
||||
jest.spyOn(cacheUtils, 'getRuntimeToken').mockReturnValue('token')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('should fail immediately on 429 rate limit without retrying', async () => {
|
||||
const mockPost = jest.fn(() => {
|
||||
const msg = new http.IncomingMessage(new net.Socket())
|
||||
msg.statusCode = 429
|
||||
msg.statusMessage = 'Too Many Requests'
|
||||
return {
|
||||
message: msg,
|
||||
readBody: async () => {
|
||||
return Promise.resolve(`{"ok": false}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
;(HttpClient as unknown as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
post: mockPost
|
||||
}
|
||||
})
|
||||
|
||||
const client = internalCacheTwirpClient(clientOptions)
|
||||
await expect(
|
||||
client.CreateCacheEntry({
|
||||
key: 'test-key',
|
||||
version: 'test-version'
|
||||
})
|
||||
).rejects.toThrow(
|
||||
'Failed to CreateCacheEntry: Rate limited: Failed request: (429) Too Many Requests'
|
||||
)
|
||||
|
||||
// Should only be called once - no retries for 429
|
||||
expect(mockPost).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should log warning with retry-after header on 429', async () => {
|
||||
const warningSpy = jest.spyOn(core, 'warning')
|
||||
|
||||
const mockPost = jest.fn(() => {
|
||||
const msg = new http.IncomingMessage(new net.Socket())
|
||||
msg.statusCode = 429
|
||||
msg.statusMessage = 'Too Many Requests'
|
||||
msg.headers = {'retry-after': '60'}
|
||||
return {
|
||||
message: msg,
|
||||
readBody: async () => {
|
||||
return Promise.resolve(`{"ok": false}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
;(HttpClient as unknown as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
post: mockPost
|
||||
}
|
||||
})
|
||||
|
||||
const client = internalCacheTwirpClient(clientOptions)
|
||||
await expect(
|
||||
client.CreateCacheEntry({
|
||||
key: 'test-key',
|
||||
version: 'test-version'
|
||||
})
|
||||
).rejects.toThrow('Rate limited')
|
||||
|
||||
expect(mockPost).toHaveBeenCalledTimes(1)
|
||||
expect(warningSpy).toHaveBeenCalledWith(
|
||||
"You've hit a rate limit, your rate limit will reset in 60 seconds"
|
||||
)
|
||||
})
|
||||
|
||||
it('should not log warning if retry-after header is missing on 429', async () => {
|
||||
const warningSpy = jest.spyOn(core, 'warning')
|
||||
|
||||
const mockPost = jest.fn(() => {
|
||||
const msg = new http.IncomingMessage(new net.Socket())
|
||||
msg.statusCode = 429
|
||||
msg.statusMessage = 'Too Many Requests'
|
||||
// No retry-after header
|
||||
return {
|
||||
message: msg,
|
||||
readBody: async () => {
|
||||
return Promise.resolve(`{"ok": false}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
;(HttpClient as unknown as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
post: mockPost
|
||||
}
|
||||
})
|
||||
|
||||
const client = internalCacheTwirpClient(clientOptions)
|
||||
await expect(
|
||||
client.CreateCacheEntry({
|
||||
key: 'test-key',
|
||||
version: 'test-version'
|
||||
})
|
||||
).rejects.toThrow('Rate limited')
|
||||
|
||||
expect(mockPost).toHaveBeenCalledTimes(1)
|
||||
expect(warningSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not log warning if retry-after header is invalid on 429', async () => {
|
||||
const warningSpy = jest.spyOn(core, 'warning')
|
||||
|
||||
const mockPost = jest.fn(() => {
|
||||
const msg = new http.IncomingMessage(new net.Socket())
|
||||
msg.statusCode = 429
|
||||
msg.statusMessage = 'Too Many Requests'
|
||||
msg.headers = {'retry-after': 'invalid'}
|
||||
return {
|
||||
message: msg,
|
||||
readBody: async () => {
|
||||
return Promise.resolve(`{"ok": false}`)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
;(HttpClient as unknown as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
post: mockPost
|
||||
}
|
||||
})
|
||||
|
||||
const client = internalCacheTwirpClient(clientOptions)
|
||||
await expect(
|
||||
client.CreateCacheEntry({
|
||||
key: 'test-key',
|
||||
version: 'test-version'
|
||||
})
|
||||
).rejects.toThrow('Rate limited')
|
||||
|
||||
expect(mockPost).toHaveBeenCalledTimes(1)
|
||||
expect(warningSpy).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
+18
-6
@@ -6,6 +6,8 @@ import * as cacheUtils from '../src/internal/cacheUtils'
|
||||
import {CacheFilename, CompressionMethod} from '../src/internal/constants'
|
||||
import {ArtifactCacheEntry} from '../src/internal/contracts'
|
||||
import * as tar from '../src/internal/tar'
|
||||
import {HttpClientError} from '@actions/http-client'
|
||||
import {CacheServiceClientJSON} from '../src/generated/results/api/v1/cache.twirp-client'
|
||||
|
||||
jest.mock('../src/internal/cacheHttpClient')
|
||||
jest.mock('../src/internal/cacheUtils')
|
||||
@@ -73,18 +75,28 @@ test('restore with no cache found', async () => {
|
||||
test('restore with server error should fail', async () => {
|
||||
const paths = ['node_modules']
|
||||
const key = 'node-test'
|
||||
const logWarningMock = jest.spyOn(core, 'warning')
|
||||
const logErrorMock = jest.spyOn(core, 'error')
|
||||
|
||||
jest.spyOn(cacheHttpClient, 'getCacheEntry').mockImplementation(() => {
|
||||
throw new Error('HTTP Error Occurred')
|
||||
})
|
||||
// Set cache service to V2 to test error logging for server errors
|
||||
process.env['ACTIONS_CACHE_SERVICE_V2'] = 'true'
|
||||
process.env['ACTIONS_RESULTS_URL'] = 'https://results.local/'
|
||||
|
||||
jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'GetCacheEntryDownloadURL')
|
||||
.mockImplementation(() => {
|
||||
throw new HttpClientError('HTTP Error Occurred', 500)
|
||||
})
|
||||
|
||||
const cacheKey = await restoreCache(paths, key)
|
||||
expect(cacheKey).toBe(undefined)
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
expect(logErrorMock).toHaveBeenCalledTimes(1)
|
||||
expect(logErrorMock).toHaveBeenCalledWith(
|
||||
'Failed to restore: HTTP Error Occurred'
|
||||
)
|
||||
|
||||
// Clean up environment
|
||||
delete process.env['ACTIONS_CACHE_SERVICE_V2']
|
||||
delete process.env['ACTIONS_RESULTS_URL']
|
||||
})
|
||||
|
||||
test('restore with restore keys and no cache found', async () => {
|
||||
|
||||
+9
-4
@@ -8,6 +8,7 @@ import {restoreCache} from '../src/cache'
|
||||
import {CacheFilename, CompressionMethod} from '../src/internal/constants'
|
||||
import {CacheServiceClientJSON} from '../src/generated/results/api/v1/cache.twirp-client'
|
||||
import {DownloadOptions} from '../src/options'
|
||||
import {HttpClientError} from '@actions/http-client'
|
||||
|
||||
jest.mock('../src/internal/cacheHttpClient')
|
||||
jest.mock('../src/internal/cacheUtils')
|
||||
@@ -95,18 +96,18 @@ test('restore with no cache found', async () => {
|
||||
test('restore with server error should fail', async () => {
|
||||
const paths = ['node_modules']
|
||||
const key = 'node-test'
|
||||
const logWarningMock = jest.spyOn(core, 'warning')
|
||||
const logErrorMock = jest.spyOn(core, 'error')
|
||||
|
||||
jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'GetCacheEntryDownloadURL')
|
||||
.mockImplementation(() => {
|
||||
throw new Error('HTTP Error Occurred')
|
||||
throw new HttpClientError('HTTP Error Occurred', 500)
|
||||
})
|
||||
|
||||
const cacheKey = await restoreCache(paths, key)
|
||||
expect(cacheKey).toBe(undefined)
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
expect(logErrorMock).toHaveBeenCalledTimes(1)
|
||||
expect(logErrorMock).toHaveBeenCalledWith(
|
||||
'Failed to restore: HTTP Error Occurred'
|
||||
)
|
||||
})
|
||||
@@ -265,6 +266,7 @@ test('restore with zstd compressed cache found', async () => {
|
||||
const cacheKey = await restoreCache(paths, key, [], options)
|
||||
|
||||
expect(cacheKey).toBe(key)
|
||||
expect(logInfoMock).toHaveBeenCalledWith(`Cache hit for: ${key}`)
|
||||
expect(getCacheVersionMock).toHaveBeenCalledWith(
|
||||
paths,
|
||||
compressionMethod,
|
||||
@@ -342,6 +344,9 @@ test('restore with cache found for restore key', async () => {
|
||||
const cacheKey = await restoreCache(paths, key, restoreKeys, options)
|
||||
|
||||
expect(cacheKey).toBe(restoreKeys[0])
|
||||
expect(logInfoMock).toHaveBeenCalledWith(
|
||||
`Cache hit for restore-key: ${restoreKeys[0]}`
|
||||
)
|
||||
expect(getCacheVersionMock).toHaveBeenCalledWith(
|
||||
paths,
|
||||
compressionMethod,
|
||||
|
||||
+37
-30
@@ -7,11 +7,12 @@ import * as config from '../src/internal/config'
|
||||
import {CacheFilename, CompressionMethod} from '../src/internal/constants'
|
||||
import * as tar from '../src/internal/tar'
|
||||
import {TypedResponse} from '@actions/http-client/lib/interfaces'
|
||||
import {HttpClientError} from '@actions/http-client'
|
||||
import {
|
||||
ReserveCacheResponse,
|
||||
ITypedResponseWithError
|
||||
} from '../src/internal/contracts'
|
||||
import {HttpClientError} from '@actions/http-client'
|
||||
import {CacheServiceClientJSON} from '../src/generated/results/api/v1/cache.twirp-client'
|
||||
|
||||
jest.mock('../src/internal/cacheHttpClient')
|
||||
jest.mock('../src/internal/cacheUtils')
|
||||
@@ -223,46 +224,55 @@ test('save with reserve cache failure should fail', async () => {
|
||||
test('save with server error should fail', async () => {
|
||||
const filePath = 'node_modules'
|
||||
const primaryKey = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
const cachePaths = [path.resolve(filePath)]
|
||||
const logWarningMock = jest.spyOn(core, 'warning')
|
||||
const cacheId = 4
|
||||
const reserveCacheMock = jest
|
||||
.spyOn(cacheHttpClient, 'reserveCache')
|
||||
.mockImplementation(async () => {
|
||||
const response: TypedResponse<ReserveCacheResponse> = {
|
||||
statusCode: 500,
|
||||
result: {cacheId},
|
||||
headers: {}
|
||||
}
|
||||
return response
|
||||
})
|
||||
const logErrorMock = jest.spyOn(core, 'error')
|
||||
|
||||
// Mock cache service version to V2
|
||||
const getCacheServiceVersionMock = jest
|
||||
.spyOn(config, 'getCacheServiceVersion')
|
||||
.mockReturnValue('v2')
|
||||
|
||||
// Mock V2 CreateCacheEntry to succeed
|
||||
const createCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
signedUploadUrl: 'https://blob-storage.local?signed=true',
|
||||
message: ''
|
||||
})
|
||||
)
|
||||
|
||||
// Mock the FinalizeCacheEntryUpload to succeed (since the error should happen in saveCache)
|
||||
jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'FinalizeCacheEntryUpload')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, entryId: '4', message: 'Success'})
|
||||
)
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
|
||||
// Mock the saveCache call to throw a server error
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cacheHttpClient, 'saveCache')
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Error('HTTP Error Occurred')
|
||||
throw new HttpClientError('HTTP Error Occurred', 500)
|
||||
})
|
||||
|
||||
const compression = CompressionMethod.Zstd
|
||||
const getCompressionMock = jest
|
||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||
.mockReturnValueOnce(Promise.resolve(compression))
|
||||
|
||||
await saveCache([filePath], primaryKey)
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1)
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
|
||||
expect(logErrorMock).toHaveBeenCalledTimes(1)
|
||||
expect(logErrorMock).toHaveBeenCalledWith(
|
||||
'Failed to save: HTTP Error Occurred'
|
||||
)
|
||||
|
||||
expect(reserveCacheMock).toHaveBeenCalledTimes(1)
|
||||
expect(reserveCacheMock).toHaveBeenCalledWith(primaryKey, [filePath], {
|
||||
cacheSize: undefined,
|
||||
compressionMethod: compression,
|
||||
enableCrossOsArchive: false
|
||||
})
|
||||
expect(createCacheEntryMock).toHaveBeenCalledTimes(1)
|
||||
const archiveFolder = '/foo/bar'
|
||||
const archiveFile = path.join(archiveFolder, CacheFilename.Zstd)
|
||||
const cachePaths = [path.resolve(filePath)]
|
||||
expect(createTarMock).toHaveBeenCalledTimes(1)
|
||||
expect(createTarMock).toHaveBeenCalledWith(
|
||||
archiveFolder,
|
||||
@@ -270,13 +280,10 @@ test('save with server error should fail', async () => {
|
||||
compression
|
||||
)
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1)
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
cacheId,
|
||||
archiveFile,
|
||||
'',
|
||||
undefined
|
||||
)
|
||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||
|
||||
// Restore the getCacheServiceVersion mock to its original state
|
||||
getCacheServiceVersionMock.mockRestore()
|
||||
})
|
||||
|
||||
test('save with valid inputs uploads a cache', async () => {
|
||||
|
||||
+254
-39
@@ -59,39 +59,6 @@ test('save with missing input should fail', async () => {
|
||||
)
|
||||
})
|
||||
|
||||
test('save with large cache outputs should fail using', async () => {
|
||||
const paths = 'node_modules'
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
const cachePaths = [path.resolve(paths)]
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
const logWarningMock = jest.spyOn(core, 'warning')
|
||||
|
||||
const cacheSize = 11 * 1024 * 1024 * 1024 //~11GB, over the 10GB limit
|
||||
jest
|
||||
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
|
||||
.mockReturnValueOnce(cacheSize)
|
||||
const compression = CompressionMethod.Gzip
|
||||
const getCompressionMock = jest
|
||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||
.mockReturnValueOnce(Promise.resolve(compression))
|
||||
|
||||
const cacheId = await saveCache([paths], key)
|
||||
expect(cacheId).toBe(-1)
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
'Failed to save: Cache size of ~11264 MB (11811160064 B) is over the 10GB limit, not saving cache.'
|
||||
)
|
||||
|
||||
const archiveFolder = '/foo/bar'
|
||||
|
||||
expect(createTarMock).toHaveBeenCalledWith(
|
||||
archiveFolder,
|
||||
cachePaths,
|
||||
compression
|
||||
)
|
||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('create cache entry failure on non-ok response', async () => {
|
||||
const paths = ['node_modules']
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
@@ -99,7 +66,7 @@ test('create cache entry failure on non-ok response', async () => {
|
||||
|
||||
const createCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockResolvedValue({ok: false, signedUploadUrl: ''})
|
||||
.mockResolvedValue({ok: false, signedUploadUrl: '', message: ''})
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
const finalizeCacheEntryMock = jest.spyOn(
|
||||
@@ -182,7 +149,7 @@ test('save cache fails if a signedUploadURL was not passed', async () => {
|
||||
const createCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL})
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL, message: ''})
|
||||
)
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
@@ -240,7 +207,7 @@ test('finalize save cache failure', async () => {
|
||||
const createCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL})
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL, message: ''})
|
||||
)
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
@@ -260,7 +227,7 @@ test('finalize save cache failure', async () => {
|
||||
|
||||
const finalizeCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'FinalizeCacheEntryUpload')
|
||||
.mockReturnValue(Promise.resolve({ok: false, entryId: ''}))
|
||||
.mockReturnValue(Promise.resolve({ok: false, entryId: '', message: ''}))
|
||||
|
||||
const cacheId = await saveCache([paths], key, options)
|
||||
|
||||
@@ -319,7 +286,7 @@ test('save with valid inputs uploads a cache', async () => {
|
||||
jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL})
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL, message: ''})
|
||||
)
|
||||
|
||||
const saveCacheMock = jest.spyOn(cacheHttpClient, 'saveCache')
|
||||
@@ -332,7 +299,9 @@ test('save with valid inputs uploads a cache', async () => {
|
||||
|
||||
const finalizeCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'FinalizeCacheEntryUpload')
|
||||
.mockReturnValue(Promise.resolve({ok: true, entryId: cacheId.toString()}))
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, entryId: cacheId.toString(), message: ''})
|
||||
)
|
||||
|
||||
const expectedCacheId = await saveCache([paths], key)
|
||||
|
||||
@@ -360,6 +329,252 @@ test('save with valid inputs uploads a cache', async () => {
|
||||
expect(expectedCacheId).toBe(cacheId)
|
||||
})
|
||||
|
||||
test('save with extremely large cache should succeed in v2 (no size limit)', async () => {
|
||||
const paths = 'node_modules'
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
const cachePaths = [path.resolve(paths)]
|
||||
const signedUploadURL = 'https://blob-storage.local?signed=true'
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
// Simulate a very large cache (20GB)
|
||||
const archiveFileSize = 20 * 1024 * 1024 * 1024 // 20GB
|
||||
const options: UploadOptions = {
|
||||
archiveSizeBytes: archiveFileSize,
|
||||
useAzureSdk: true,
|
||||
uploadChunkSize: 64 * 1024 * 1024,
|
||||
uploadConcurrency: 8
|
||||
}
|
||||
|
||||
jest
|
||||
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
|
||||
.mockReturnValueOnce(archiveFileSize)
|
||||
|
||||
const cacheId = 4
|
||||
jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL, message: ''})
|
||||
)
|
||||
|
||||
const saveCacheMock = jest.spyOn(cacheHttpClient, 'saveCache')
|
||||
|
||||
const compression = CompressionMethod.Zstd
|
||||
const getCompressionMock = jest
|
||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||
.mockReturnValue(Promise.resolve(compression))
|
||||
const cacheVersion = cacheUtils.getCacheVersion([paths], compression)
|
||||
|
||||
const finalizeCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'FinalizeCacheEntryUpload')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, entryId: cacheId.toString(), message: ''})
|
||||
)
|
||||
|
||||
const expectedCacheId = await saveCache([paths], key)
|
||||
|
||||
const archiveFolder = '/foo/bar'
|
||||
const archiveFile = path.join(archiveFolder, CacheFilename.Zstd)
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
-1,
|
||||
archiveFile,
|
||||
signedUploadURL,
|
||||
options
|
||||
)
|
||||
expect(createTarMock).toHaveBeenCalledWith(
|
||||
archiveFolder,
|
||||
cachePaths,
|
||||
compression
|
||||
)
|
||||
|
||||
expect(finalizeCacheEntryMock).toHaveBeenCalledWith({
|
||||
key,
|
||||
version: cacheVersion,
|
||||
sizeBytes: archiveFileSize.toString()
|
||||
})
|
||||
|
||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||
expect(expectedCacheId).toBe(cacheId)
|
||||
})
|
||||
|
||||
test('save with create cache entry failure and specific error message', async () => {
|
||||
const paths = ['node_modules']
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
const infoLogMock = jest.spyOn(core, 'info')
|
||||
const warningLogMock = jest.spyOn(core, 'warning')
|
||||
const errorMessage = 'Cache storage quota exceeded for repository'
|
||||
|
||||
const createCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockResolvedValue({ok: false, signedUploadUrl: '', message: errorMessage})
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
const compression = CompressionMethod.Zstd
|
||||
const getCompressionMock = jest
|
||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||
.mockResolvedValueOnce(compression)
|
||||
const archiveFileSize = 1024
|
||||
jest
|
||||
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
|
||||
.mockReturnValueOnce(archiveFileSize)
|
||||
|
||||
const cacheId = await saveCache(paths, key)
|
||||
expect(cacheId).toBe(-1)
|
||||
expect(warningLogMock).toHaveBeenCalledWith(
|
||||
`Cache reservation failed: ${errorMessage}`
|
||||
)
|
||||
expect(infoLogMock).toHaveBeenCalledWith(
|
||||
`Failed to save: Unable to reserve cache with key ${key}, another job may be creating this cache.`
|
||||
)
|
||||
|
||||
expect(createCacheEntryMock).toHaveBeenCalledWith({
|
||||
key,
|
||||
version: cacheUtils.getCacheVersion(paths, compression)
|
||||
})
|
||||
expect(createTarMock).toHaveBeenCalledTimes(1)
|
||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('save with finalize cache entry failure and specific error message', async () => {
|
||||
const paths = 'node_modules'
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
const cachePaths = [path.resolve(paths)]
|
||||
const logWarningMock = jest.spyOn(core, 'warning')
|
||||
const signedUploadURL = 'https://blob-storage.local?signed=true'
|
||||
const archiveFileSize = 1024
|
||||
const errorMessage =
|
||||
'Cache entry finalization failed due to concurrent access'
|
||||
const options: UploadOptions = {
|
||||
archiveSizeBytes: archiveFileSize,
|
||||
useAzureSdk: true,
|
||||
uploadChunkSize: 64 * 1024 * 1024,
|
||||
uploadConcurrency: 8
|
||||
}
|
||||
|
||||
const createCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL, message: ''})
|
||||
)
|
||||
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cacheHttpClient, 'saveCache')
|
||||
.mockResolvedValue()
|
||||
|
||||
const compression = CompressionMethod.Zstd
|
||||
const getCompressionMock = jest
|
||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||
.mockReturnValueOnce(Promise.resolve(compression))
|
||||
|
||||
const cacheVersion = cacheUtils.getCacheVersion([paths], compression)
|
||||
jest
|
||||
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
|
||||
.mockReturnValueOnce(archiveFileSize)
|
||||
|
||||
const finalizeCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'FinalizeCacheEntryUpload')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: false, entryId: '', message: errorMessage})
|
||||
)
|
||||
|
||||
const cacheId = await saveCache([paths], key, options)
|
||||
|
||||
expect(createCacheEntryMock).toHaveBeenCalledWith({
|
||||
key,
|
||||
version: cacheVersion
|
||||
})
|
||||
|
||||
const archiveFolder = '/foo/bar'
|
||||
const archiveFile = path.join(archiveFolder, CacheFilename.Zstd)
|
||||
expect(createTarMock).toHaveBeenCalledWith(
|
||||
archiveFolder,
|
||||
cachePaths,
|
||||
compression
|
||||
)
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
-1,
|
||||
archiveFile,
|
||||
signedUploadURL,
|
||||
options
|
||||
)
|
||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||
|
||||
expect(finalizeCacheEntryMock).toHaveBeenCalledWith({
|
||||
key,
|
||||
version: cacheVersion,
|
||||
sizeBytes: archiveFileSize.toString()
|
||||
})
|
||||
|
||||
expect(cacheId).toBe(-1)
|
||||
expect(logWarningMock).toHaveBeenCalledWith(errorMessage)
|
||||
})
|
||||
|
||||
test('save with multiple large caches should succeed in v2 (testing 50GB)', async () => {
|
||||
const paths = ['large-dataset', 'node_modules', 'build-artifacts']
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
const cachePaths = paths.map(p => path.resolve(p))
|
||||
const signedUploadURL = 'https://blob-storage.local?signed=true'
|
||||
const createTarMock = jest.spyOn(tar, 'createTar')
|
||||
// Simulate an extremely large cache (50GB)
|
||||
const archiveFileSize = 50 * 1024 * 1024 * 1024 // 50GB
|
||||
const options: UploadOptions = {
|
||||
archiveSizeBytes: archiveFileSize,
|
||||
useAzureSdk: true,
|
||||
uploadChunkSize: 64 * 1024 * 1024,
|
||||
uploadConcurrency: 8
|
||||
}
|
||||
|
||||
jest
|
||||
.spyOn(cacheUtils, 'getArchiveFileSizeInBytes')
|
||||
.mockReturnValueOnce(archiveFileSize)
|
||||
|
||||
const cacheId = 7
|
||||
jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'CreateCacheEntry')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, signedUploadUrl: signedUploadURL, message: ''})
|
||||
)
|
||||
|
||||
const saveCacheMock = jest.spyOn(cacheHttpClient, 'saveCache')
|
||||
|
||||
const compression = CompressionMethod.Zstd
|
||||
const getCompressionMock = jest
|
||||
.spyOn(cacheUtils, 'getCompressionMethod')
|
||||
.mockReturnValue(Promise.resolve(compression))
|
||||
const cacheVersion = cacheUtils.getCacheVersion(paths, compression)
|
||||
|
||||
const finalizeCacheEntryMock = jest
|
||||
.spyOn(CacheServiceClientJSON.prototype, 'FinalizeCacheEntryUpload')
|
||||
.mockReturnValue(
|
||||
Promise.resolve({ok: true, entryId: cacheId.toString(), message: ''})
|
||||
)
|
||||
|
||||
const expectedCacheId = await saveCache(paths, key)
|
||||
|
||||
const archiveFolder = '/foo/bar'
|
||||
const archiveFile = path.join(archiveFolder, CacheFilename.Zstd)
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
-1,
|
||||
archiveFile,
|
||||
signedUploadURL,
|
||||
options
|
||||
)
|
||||
expect(createTarMock).toHaveBeenCalledWith(
|
||||
archiveFolder,
|
||||
cachePaths,
|
||||
compression
|
||||
)
|
||||
|
||||
expect(finalizeCacheEntryMock).toHaveBeenCalledWith({
|
||||
key,
|
||||
version: cacheVersion,
|
||||
sizeBytes: archiveFileSize.toString()
|
||||
})
|
||||
|
||||
expect(getCompressionMock).toHaveBeenCalledTimes(1)
|
||||
expect(expectedCacheId).toBe(cacheId)
|
||||
})
|
||||
|
||||
test('save with non existing path should not save cache using v2 saveCache', async () => {
|
||||
const path = 'node_modules'
|
||||
const key = 'Linux-node-bb828da54c148048dd17899ba9fda624811cfb43'
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
import * as uploadUtils from '../src/internal/uploadUtils'
|
||||
import {TransferProgressEvent} from '@azure/ms-rest-js'
|
||||
import {TransferProgressEvent} from '@azure/core-rest-pipeline'
|
||||
|
||||
test('upload progress tracked correctly', () => {
|
||||
const progress = new uploadUtils.UploadProgress(1000)
|
||||
|
||||
+452
-804
File diff suppressed because it is too large
Load Diff
Vendored
+16
-11
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/cache",
|
||||
"version": "4.0.3",
|
||||
"version": "5.0.5",
|
||||
"preview": true,
|
||||
"description": "Actions cache lib",
|
||||
"keywords": [
|
||||
@@ -37,20 +37,25 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/glob": "^0.1.0",
|
||||
"@actions/http-client": "^2.1.1",
|
||||
"@actions/io": "^1.0.1",
|
||||
"@actions/core": "^2.0.0",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/glob": "^0.5.1",
|
||||
"@protobuf-ts/runtime-rpc": "^2.11.1",
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@azure/abort-controller": "^1.1.0",
|
||||
"@azure/ms-rest-js": "^2.6.0",
|
||||
"@azure/storage-blob": "^12.13.0",
|
||||
"@protobuf-ts/plugin": "^2.9.4",
|
||||
"@azure/core-rest-pipeline": "^1.22.0",
|
||||
"@azure/storage-blob": "^12.29.1",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.13.9",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/semver": "^6.0.0",
|
||||
"@protobuf-ts/plugin": "^2.9.4",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"overrides": {
|
||||
"uri-js": "npm:uri-js-replace@^1.0.1",
|
||||
"node-fetch": "^3.3.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+77
-18
@@ -12,7 +12,7 @@ import {
|
||||
FinalizeCacheEntryUploadResponse,
|
||||
GetCacheEntryDownloadURLRequest
|
||||
} from './generated/results/api/v1/cache'
|
||||
import {CacheFileSizeLimit} from './internal/constants'
|
||||
import {HttpClientError} from '@actions/http-client'
|
||||
export class ValidationError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
@@ -29,6 +29,14 @@ export class ReserveCacheError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export class FinalizeCacheError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
this.name = 'FinalizeCacheError'
|
||||
Object.setPrototypeOf(this, FinalizeCacheError.prototype)
|
||||
}
|
||||
}
|
||||
|
||||
function checkPaths(paths: string[]): void {
|
||||
if (!paths || paths.length === 0) {
|
||||
throw new ValidationError(
|
||||
@@ -57,7 +65,18 @@ function checkKey(key: string): void {
|
||||
* @returns boolean return true if Actions cache service feature is available, otherwise false
|
||||
*/
|
||||
export function isFeatureAvailable(): boolean {
|
||||
return !!process.env['ACTIONS_CACHE_URL']
|
||||
const cacheServiceVersion = getCacheServiceVersion()
|
||||
|
||||
// Check availability based on cache service version
|
||||
switch (cacheServiceVersion) {
|
||||
case 'v2':
|
||||
// For v2, we need ACTIONS_RESULTS_URL
|
||||
return !!process.env['ACTIONS_RESULTS_URL']
|
||||
case 'v1':
|
||||
default:
|
||||
// For v1, we only need ACTIONS_CACHE_URL
|
||||
return !!process.env['ACTIONS_CACHE_URL']
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,8 +205,17 @@ async function restoreCacheV1(
|
||||
if (typedError.name === ValidationError.name) {
|
||||
throw error
|
||||
} else {
|
||||
// Supress all non-validation cache related errors because caching should be optional
|
||||
core.warning(`Failed to restore: ${(error as Error).message}`)
|
||||
// warn on cache restore failure and continue build
|
||||
// Log server errors (5xx) as errors, all other errors as warnings
|
||||
if (
|
||||
typedError instanceof HttpClientError &&
|
||||
typeof typedError.statusCode === 'number' &&
|
||||
typedError.statusCode >= 500
|
||||
) {
|
||||
core.error(`Failed to restore: ${(error as Error).message}`)
|
||||
} else {
|
||||
core.warning(`Failed to restore: ${(error as Error).message}`)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Try to delete the archive to save space
|
||||
@@ -264,7 +292,12 @@ async function restoreCacheV2(
|
||||
return undefined
|
||||
}
|
||||
|
||||
core.info(`Cache hit for: ${request.key}`)
|
||||
const isRestoreKeyMatch = request.key !== response.matchedKey
|
||||
if (isRestoreKeyMatch) {
|
||||
core.info(`Cache hit for restore-key: ${response.matchedKey}`)
|
||||
} else {
|
||||
core.info(`Cache hit for: ${response.matchedKey}`)
|
||||
}
|
||||
|
||||
if (options?.lookupOnly) {
|
||||
core.info('Lookup only - skipping download')
|
||||
@@ -305,7 +338,16 @@ async function restoreCacheV2(
|
||||
throw error
|
||||
} else {
|
||||
// Supress all non-validation cache related errors because caching should be optional
|
||||
core.warning(`Failed to restore: ${(error as Error).message}`)
|
||||
// Log server errors (5xx) as errors, all other errors as warnings
|
||||
if (
|
||||
typedError instanceof HttpClientError &&
|
||||
typeof typedError.statusCode === 'number' &&
|
||||
typedError.statusCode >= 500
|
||||
) {
|
||||
core.error(`Failed to restore: ${(error as Error).message}`)
|
||||
} else {
|
||||
core.warning(`Failed to restore: ${(error as Error).message}`)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
@@ -437,7 +479,16 @@ async function saveCacheV1(
|
||||
} else if (typedError.name === ReserveCacheError.name) {
|
||||
core.info(`Failed to save: ${typedError.message}`)
|
||||
} else {
|
||||
core.warning(`Failed to save: ${typedError.message}`)
|
||||
// Log server errors (5xx) as errors, all other errors as warnings
|
||||
if (
|
||||
typedError instanceof HttpClientError &&
|
||||
typeof typedError.statusCode === 'number' &&
|
||||
typedError.statusCode >= 500
|
||||
) {
|
||||
core.error(`Failed to save: ${typedError.message}`)
|
||||
} else {
|
||||
core.warning(`Failed to save: ${typedError.message}`)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Try to delete the archive to save space
|
||||
@@ -506,15 +557,6 @@ async function saveCacheV2(
|
||||
const archiveFileSize = utils.getArchiveFileSizeInBytes(archivePath)
|
||||
core.debug(`File Size: ${archiveFileSize}`)
|
||||
|
||||
// For GHES, this check will take place in ReserveCache API with enterprise file size limit
|
||||
if (archiveFileSize > CacheFileSizeLimit && !isGhes()) {
|
||||
throw new Error(
|
||||
`Cache size of ~${Math.round(
|
||||
archiveFileSize / (1024 * 1024)
|
||||
)} MB (${archiveFileSize} B) is over the 10GB limit, not saving cache.`
|
||||
)
|
||||
}
|
||||
|
||||
// Set the archive size in the options, will be used to display the upload progress
|
||||
options.archiveSizeBytes = archiveFileSize
|
||||
|
||||
@@ -534,7 +576,10 @@ async function saveCacheV2(
|
||||
try {
|
||||
const response = await twirpClient.CreateCacheEntry(request)
|
||||
if (!response.ok) {
|
||||
throw new Error('Response was not ok')
|
||||
if (response.message) {
|
||||
core.warning(`Cache reservation failed: ${response.message}`)
|
||||
}
|
||||
throw new Error(response.message || 'Response was not ok')
|
||||
}
|
||||
signedUploadUrl = response.signedUploadUrl
|
||||
} catch (error) {
|
||||
@@ -563,6 +608,9 @@ async function saveCacheV2(
|
||||
core.debug(`FinalizeCacheEntryUploadResponse: ${finalizeResponse.ok}`)
|
||||
|
||||
if (!finalizeResponse.ok) {
|
||||
if (finalizeResponse.message) {
|
||||
throw new FinalizeCacheError(finalizeResponse.message)
|
||||
}
|
||||
throw new Error(
|
||||
`Unable to finalize cache with key ${key}, another job may be finalizing this cache.`
|
||||
)
|
||||
@@ -575,8 +623,19 @@ async function saveCacheV2(
|
||||
throw error
|
||||
} else if (typedError.name === ReserveCacheError.name) {
|
||||
core.info(`Failed to save: ${typedError.message}`)
|
||||
} else if (typedError.name === FinalizeCacheError.name) {
|
||||
core.warning(typedError.message)
|
||||
} else {
|
||||
core.warning(`Failed to save: ${typedError.message}`)
|
||||
// Log server errors (5xx) as errors, all other errors as warnings
|
||||
if (
|
||||
typedError instanceof HttpClientError &&
|
||||
typeof typedError.statusCode === 'number' &&
|
||||
typedError.statusCode >= 500
|
||||
) {
|
||||
core.error(`Failed to save: ${typedError.message}`)
|
||||
} else {
|
||||
core.warning(`Failed to save: ${typedError.message}`)
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Try to delete the archive to save space
|
||||
|
||||
+30
-4
@@ -50,6 +50,12 @@ export interface CreateCacheEntryResponse {
|
||||
* @generated from protobuf field: string signed_upload_url = 2;
|
||||
*/
|
||||
signedUploadUrl: string;
|
||||
/**
|
||||
* When !ok, this field may contain a human-readable error message used to create an annotation
|
||||
*
|
||||
* @generated from protobuf field: string message = 3;
|
||||
*/
|
||||
message: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message github.actions.results.api.v1.FinalizeCacheEntryUploadRequest
|
||||
@@ -94,6 +100,12 @@ export interface FinalizeCacheEntryUploadResponse {
|
||||
* @generated from protobuf field: int64 entry_id = 2;
|
||||
*/
|
||||
entryId: string;
|
||||
/**
|
||||
* When !ok, this field may contain a human-readable error message used to create an annotation
|
||||
*
|
||||
* @generated from protobuf field: string message = 3;
|
||||
*/
|
||||
message: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message github.actions.results.api.v1.GetCacheEntryDownloadURLRequest
|
||||
@@ -211,11 +223,12 @@ class CreateCacheEntryResponse$Type extends MessageType<CreateCacheEntryResponse
|
||||
constructor() {
|
||||
super("github.actions.results.api.v1.CreateCacheEntryResponse", [
|
||||
{ no: 1, name: "ok", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
|
||||
{ no: 2, name: "signed_upload_url", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
{ no: 2, name: "signed_upload_url", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 3, name: "message", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<CreateCacheEntryResponse>): CreateCacheEntryResponse {
|
||||
const message = { ok: false, signedUploadUrl: "" };
|
||||
const message = { ok: false, signedUploadUrl: "", message: "" };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<CreateCacheEntryResponse>(this, message, value);
|
||||
@@ -232,6 +245,9 @@ class CreateCacheEntryResponse$Type extends MessageType<CreateCacheEntryResponse
|
||||
case /* string signed_upload_url */ 2:
|
||||
message.signedUploadUrl = reader.string();
|
||||
break;
|
||||
case /* string message */ 3:
|
||||
message.message = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
@@ -250,6 +266,9 @@ class CreateCacheEntryResponse$Type extends MessageType<CreateCacheEntryResponse
|
||||
/* string signed_upload_url = 2; */
|
||||
if (message.signedUploadUrl !== "")
|
||||
writer.tag(2, WireType.LengthDelimited).string(message.signedUploadUrl);
|
||||
/* string message = 3; */
|
||||
if (message.message !== "")
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.message);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
@@ -333,11 +352,12 @@ class FinalizeCacheEntryUploadResponse$Type extends MessageType<FinalizeCacheEnt
|
||||
constructor() {
|
||||
super("github.actions.results.api.v1.FinalizeCacheEntryUploadResponse", [
|
||||
{ no: 1, name: "ok", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
|
||||
{ no: 2, name: "entry_id", kind: "scalar", T: 3 /*ScalarType.INT64*/ }
|
||||
{ no: 2, name: "entry_id", kind: "scalar", T: 3 /*ScalarType.INT64*/ },
|
||||
{ no: 3, name: "message", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
create(value?: PartialMessage<FinalizeCacheEntryUploadResponse>): FinalizeCacheEntryUploadResponse {
|
||||
const message = { ok: false, entryId: "0" };
|
||||
const message = { ok: false, entryId: "0", message: "" };
|
||||
globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this });
|
||||
if (value !== undefined)
|
||||
reflectionMergePartial<FinalizeCacheEntryUploadResponse>(this, message, value);
|
||||
@@ -354,6 +374,9 @@ class FinalizeCacheEntryUploadResponse$Type extends MessageType<FinalizeCacheEnt
|
||||
case /* int64 entry_id */ 2:
|
||||
message.entryId = reader.int64().toString();
|
||||
break;
|
||||
case /* string message */ 3:
|
||||
message.message = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
@@ -372,6 +395,9 @@ class FinalizeCacheEntryUploadResponse$Type extends MessageType<FinalizeCacheEnt
|
||||
/* int64 entry_id = 2; */
|
||||
if (message.entryId !== "0")
|
||||
writer.tag(2, WireType.Varint).int64(message.entryId);
|
||||
/* string message = 3; */
|
||||
if (message.message !== "")
|
||||
writer.tag(3, WireType.LengthDelimited).string(message.message);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import * as core from '@actions/core'
|
||||
import {HttpClient, HttpClientResponse} from '@actions/http-client'
|
||||
import {BlockBlobClient} from '@azure/storage-blob'
|
||||
import {TransferProgressEvent} from '@azure/ms-rest-js'
|
||||
import {TransferProgressEvent} from '@azure/core-rest-pipeline'
|
||||
import * as buffer from 'buffer'
|
||||
import * as fs from 'fs'
|
||||
import * as stream from 'stream'
|
||||
|
||||
+22
-4
@@ -1,6 +1,6 @@
|
||||
import {info, debug} from '@actions/core'
|
||||
import {info, debug, warning} from '@actions/core'
|
||||
import {getUserAgentString} from './user-agent'
|
||||
import {NetworkError, UsageError} from './errors'
|
||||
import {NetworkError, RateLimitError, UsageError} from './errors'
|
||||
import {getCacheServiceURL} from '../config'
|
||||
import {getRuntimeToken} from '../cacheUtils'
|
||||
import {BearerCredentialHandler} from '@actions/http-client/lib/auth'
|
||||
@@ -109,6 +109,21 @@ class CacheServiceClient implements Rpc {
|
||||
|
||||
errorMessage = `${errorMessage}: ${body.msg}`
|
||||
}
|
||||
|
||||
// Handle rate limiting - don't retry, just warn and exit
|
||||
// For more info, see https://docs.github.com/en/actions/reference/limits
|
||||
if (statusCode === HttpCodes.TooManyRequests) {
|
||||
const retryAfterHeader = response.message.headers['retry-after']
|
||||
if (retryAfterHeader) {
|
||||
const parsedSeconds = parseInt(retryAfterHeader, 10)
|
||||
if (!isNaN(parsedSeconds) && parsedSeconds > 0) {
|
||||
warning(
|
||||
`You've hit a rate limit, your rate limit will reset in ${parsedSeconds} seconds`
|
||||
)
|
||||
}
|
||||
}
|
||||
throw new RateLimitError(`Rate limited: ${errorMessage}`)
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof SyntaxError) {
|
||||
debug(`Raw Body: ${rawBody}`)
|
||||
@@ -118,6 +133,10 @@ class CacheServiceClient implements Rpc {
|
||||
throw error
|
||||
}
|
||||
|
||||
if (error instanceof RateLimitError) {
|
||||
throw error
|
||||
}
|
||||
|
||||
if (NetworkError.isNetworkErrorCode(error?.code)) {
|
||||
throw new NetworkError(error?.code)
|
||||
}
|
||||
@@ -162,8 +181,7 @@ class CacheServiceClient implements Rpc {
|
||||
HttpCodes.BadGateway,
|
||||
HttpCodes.GatewayTimeout,
|
||||
HttpCodes.InternalServerError,
|
||||
HttpCodes.ServiceUnavailable,
|
||||
HttpCodes.TooManyRequests
|
||||
HttpCodes.ServiceUnavailable
|
||||
]
|
||||
|
||||
return retryableStatusCodes.includes(statusCode)
|
||||
|
||||
@@ -70,3 +70,10 @@ export class UsageError extends Error {
|
||||
return msg.includes('insufficient usage')
|
||||
}
|
||||
}
|
||||
|
||||
export class RateLimitError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
this.name = 'RateLimitError'
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import {
|
||||
BlockBlobClient,
|
||||
BlockBlobParallelUploadOptions
|
||||
} from '@azure/storage-blob'
|
||||
import {TransferProgressEvent} from '@azure/ms-rest-js'
|
||||
import {TransferProgressEvent} from '@azure/core-rest-pipeline'
|
||||
import {InvalidResponseError} from './shared/errors'
|
||||
import {UploadOptions} from '../options'
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import * as core from '@actions/core';
|
||||
|
||||
#### Inputs/Outputs
|
||||
|
||||
Action inputs can be read with `getInput` which returns a `string` or `getBooleanInput` which parses a boolean based on the [yaml 1.2 specification](https://yaml.org/spec/1.2/spec.html#id2804923). If `required` set to be false, the input should have a default value in `action.yml`.
|
||||
Action inputs can be read with `getInput` which returns a `string` or `getBooleanInput` which parses a boolean based on the [yaml 1.2 specification](https://yaml.org/spec/1.2/spec.html#id2804923). If `required` is set to be false, the input should have a default value in `action.yml`.
|
||||
|
||||
Outputs can be set with `setOutput` which makes them available to be mapped into inputs of other actions to ensure they are decoupled.
|
||||
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
# @actions/core Releases
|
||||
|
||||
### 1.11.1
|
||||
## 2.0.3
|
||||
|
||||
- Bump `@actions/http-client` to `3.0.2`
|
||||
|
||||
## 2.0.1
|
||||
- Bump @actions/exec from 1.1.1 to 2.0.0 [#2199](https://github.com/actions/toolkit/pull/2199)
|
||||
|
||||
## 2.0.0
|
||||
- Add support for Node 24 [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
- Bump @actions/http-client from 2.0.1 to 3.0.0
|
||||
|
||||
## 1.11.1
|
||||
- Fix uses of `crypto.randomUUID` on Node 18 and earlier [#1842](https://github.com/actions/toolkit/pull/1842)
|
||||
|
||||
### 1.11.0
|
||||
|
||||
Generated
+34
-53
@@ -1,89 +1,70 @@
|
||||
{
|
||||
"name": "@actions/core",
|
||||
"version": "1.11.1",
|
||||
"lockfileVersion": 2,
|
||||
"version": "2.0.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@actions/core",
|
||||
"version": "1.11.1",
|
||||
"version": "2.0.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/http-client": "^2.0.1"
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.18.112"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz",
|
||||
"integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^1.0.1"
|
||||
"@actions/io": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
|
||||
"integrity": "sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6"
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
|
||||
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.18.112",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.112.tgz",
|
||||
"integrity": "sha512-EKrbKUGJROm17+dY/gMi31aJlGLJ75e1IkTojt9n6u+hnaTBDs+M1bIdOawpk2m6YUAXq/R2W0SxCng1tndHCg==",
|
||||
"dev": true
|
||||
"version": "16.18.126",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
|
||||
"integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/exec": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||
"requires": {
|
||||
"@actions/io": "^1.0.1"
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"@actions/http-client": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
|
||||
"integrity": "sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==",
|
||||
"requires": {
|
||||
"tunnel": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.18.112",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.112.tgz",
|
||||
"integrity": "sha512-EKrbKUGJROm17+dY/gMi31aJlGLJ75e1IkTojt9n6u+hnaTBDs+M1bIdOawpk2m6YUAXq/R2W0SxCng1tndHCg==",
|
||||
"dev": true
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/core",
|
||||
"version": "1.11.1",
|
||||
"version": "2.0.3",
|
||||
"description": "Actions core lib",
|
||||
"keywords": [
|
||||
"github",
|
||||
@@ -36,8 +36,8 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/http-client": "^2.0.1"
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.18.112"
|
||||
|
||||
@@ -76,8 +76,8 @@ export async function getDetails(): Promise<{
|
||||
...(await (isWindows
|
||||
? getWindowsInfo()
|
||||
: isMacOS
|
||||
? getMacOsInfo()
|
||||
: getLinuxInfo())),
|
||||
? getMacOsInfo()
|
||||
: getLinuxInfo())),
|
||||
platform,
|
||||
arch,
|
||||
isWindows,
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
# @actions/exec Releases
|
||||
|
||||
### 1.1.1
|
||||
- Update `lockfileVersion` to `v2` in `package-lock.json [#1024](https://github.com/actions/toolkit/pull/1024)
|
||||
## 3.0.0
|
||||
|
||||
### 1.1.0
|
||||
- **Breaking change**: Package is now ESM-only
|
||||
- CommonJS consumers must use dynamic `import()` instead of `require()`
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- Add support for Node 24 [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
- Bump @actions/io dependency from ^1.0.1 to ^2.0.0
|
||||
|
||||
## 1.1.1
|
||||
|
||||
- Update `lockfileVersion` to `v2` in `package-lock.json` [#1024](https://github.com/actions/toolkit/pull/1024)
|
||||
|
||||
## 1.1.0
|
||||
|
||||
- [Fix stdline dropping large output](https://github.com/actions/toolkit/pull/773)
|
||||
- [Add getExecOutput function](https://github.com/actions/toolkit/pull/814)
|
||||
@@ -19,4 +30,4 @@
|
||||
|
||||
### 1.0.0
|
||||
|
||||
- Initial release
|
||||
- Initial release
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as exec from '../src/exec'
|
||||
import * as im from '../src/interfaces'
|
||||
import * as exec from '../src/exec.js'
|
||||
import * as im from '../src/interfaces.js'
|
||||
|
||||
import * as childProcess from 'child_process'
|
||||
import * as fs from 'fs'
|
||||
@@ -11,6 +11,11 @@ import * as io from '@actions/io'
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
const SPAWN_WAIT_SCRIPT = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'spawn-wait-for-file.cjs'
|
||||
)
|
||||
|
||||
let outstream: stream.Writable
|
||||
let errstream: stream.Writable
|
||||
@@ -191,7 +196,7 @@ describe('@actions/exec', () => {
|
||||
const scriptPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stderroutput.js'
|
||||
'stderroutput.cjs'
|
||||
)
|
||||
const nodePath: string = await io.which('node', true)
|
||||
|
||||
@@ -213,7 +218,7 @@ describe('@actions/exec', () => {
|
||||
const scriptPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stderroutput.js'
|
||||
'stderroutput.cjs'
|
||||
)
|
||||
const nodePath: string = await io.which('node', true)
|
||||
|
||||
@@ -250,12 +255,12 @@ describe('@actions/exec', () => {
|
||||
const stdErrPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stderroutput.js'
|
||||
'stderroutput.cjs'
|
||||
)
|
||||
const stdOutPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stdoutoutput.js'
|
||||
'stdoutoutput.cjs'
|
||||
)
|
||||
const nodePath: string = await io.which('node', true)
|
||||
let stdoutCalled = false
|
||||
@@ -290,7 +295,7 @@ describe('@actions/exec', () => {
|
||||
const stdlinePath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stdlineoutput.js'
|
||||
'stdlineoutput.cjs'
|
||||
)
|
||||
const nodePath: string = await io.which('node', true)
|
||||
|
||||
@@ -339,7 +344,7 @@ describe('@actions/exec', () => {
|
||||
const waitForInput: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'wait-for-input.js'
|
||||
'wait-for-input.cjs'
|
||||
)
|
||||
|
||||
const _testExecOptions = getExecOptions()
|
||||
@@ -365,35 +370,20 @@ describe('@actions/exec', () => {
|
||||
fs.writeFileSync(semaphorePath, '')
|
||||
|
||||
const nodePath = await io.which('node', true)
|
||||
const scriptPath = path.join(__dirname, 'scripts', 'wait-for-file.js')
|
||||
const debugList: string[] = []
|
||||
const _testExecOptions = getExecOptions()
|
||||
_testExecOptions.delay = 500
|
||||
_testExecOptions.windowsVerbatimArguments = true
|
||||
_testExecOptions.listeners = {
|
||||
debug: (data: string) => {
|
||||
debugList.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
let exitCode: number
|
||||
if (IS_WINDOWS) {
|
||||
const toolName: string = await io.which('cmd.exe', true)
|
||||
const args = [
|
||||
'/D', // Disable execution of AutoRun commands from registry.
|
||||
'/E:ON', // Enable command extensions. Note, command extensions are enabled by default, unless disabled via registry.
|
||||
'/V:OFF', // Disable delayed environment expansion. Note, delayed environment expansion is disabled by default, unless enabled via registry.
|
||||
'/S', // Will cause first and last quote after /C to be stripped.
|
||||
'/C',
|
||||
`"start "" /B "${nodePath}" "${scriptPath}" "file=${semaphorePath}""`
|
||||
]
|
||||
exitCode = await exec.exec(`"${toolName}"`, args, _testExecOptions)
|
||||
} else {
|
||||
const toolName: string = await io.which('bash', true)
|
||||
const args = ['-c', `node '${scriptPath}' 'file=${semaphorePath}' &`]
|
||||
|
||||
exitCode = await exec.exec(`"${toolName}"`, args, _testExecOptions)
|
||||
}
|
||||
const exitCode = await exec.exec(
|
||||
`"${nodePath}"`,
|
||||
[SPAWN_WAIT_SCRIPT, `file=${semaphorePath}`],
|
||||
_testExecOptions
|
||||
)
|
||||
|
||||
expect(exitCode).toBe(0)
|
||||
expect(
|
||||
@@ -411,36 +401,21 @@ describe('@actions/exec', () => {
|
||||
fs.writeFileSync(semaphorePath, '')
|
||||
|
||||
const nodePath = await io.which('node', true)
|
||||
const scriptPath = path.join(__dirname, 'scripts', 'wait-for-file.js')
|
||||
const debugList: string[] = []
|
||||
const _testExecOptions = getExecOptions()
|
||||
_testExecOptions.delay = 500
|
||||
_testExecOptions.windowsVerbatimArguments = true
|
||||
_testExecOptions.listeners = {
|
||||
debug: (data: string) => {
|
||||
debugList.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
let toolName: string
|
||||
let args: string[]
|
||||
if (IS_WINDOWS) {
|
||||
toolName = await io.which('cmd.exe', true)
|
||||
args = [
|
||||
'/D', // Disable execution of AutoRun commands from registry.
|
||||
'/E:ON', // Enable command extensions. Note, command extensions are enabled by default, unless disabled via registry.
|
||||
'/V:OFF', // Disable delayed environment expansion. Note, delayed environment expansion is disabled by default, unless enabled via registry.
|
||||
'/S', // Will cause first and last quote after /C to be stripped.
|
||||
'/C',
|
||||
`"start "" /B "${nodePath}" "${scriptPath}" "file=${semaphorePath}"" & exit /b 123`
|
||||
]
|
||||
} else {
|
||||
toolName = await io.which('bash', true)
|
||||
args = ['-c', `node '${scriptPath}' 'file=${semaphorePath}' & exit 123`]
|
||||
}
|
||||
|
||||
await exec
|
||||
.exec(`"${toolName}"`, args, _testExecOptions)
|
||||
.exec(
|
||||
`"${nodePath}"`,
|
||||
[SPAWN_WAIT_SCRIPT, `file=${semaphorePath}`, 'exitCode=123'],
|
||||
_testExecOptions
|
||||
)
|
||||
.then(() => {
|
||||
throw new Error('Should not have succeeded')
|
||||
})
|
||||
@@ -465,40 +440,22 @@ describe('@actions/exec', () => {
|
||||
fs.writeFileSync(semaphorePath, '')
|
||||
|
||||
const nodePath = await io.which('node', true)
|
||||
const scriptPath = path.join(__dirname, 'scripts', 'wait-for-file.js')
|
||||
const debugList: string[] = []
|
||||
const _testExecOptions = getExecOptions()
|
||||
_testExecOptions.delay = 500
|
||||
_testExecOptions.failOnStdErr = true
|
||||
_testExecOptions.windowsVerbatimArguments = true
|
||||
_testExecOptions.listeners = {
|
||||
debug: (data: string) => {
|
||||
debugList.push(data)
|
||||
}
|
||||
}
|
||||
|
||||
let toolName: string
|
||||
let args: string[]
|
||||
if (IS_WINDOWS) {
|
||||
toolName = await io.which('cmd.exe', true)
|
||||
args = [
|
||||
'/D', // Disable execution of AutoRun commands from registry.
|
||||
'/E:ON', // Enable command extensions. Note, command extensions are enabled by default, unless disabled via registry.
|
||||
'/V:OFF', // Disable delayed environment expansion. Note, delayed environment expansion is disabled by default, unless enabled via registry.
|
||||
'/S', // Will cause first and last quote after /C to be stripped.
|
||||
'/C',
|
||||
`"start "" /B "${nodePath}" "${scriptPath}" "file=${semaphorePath}"" & echo hi 1>&2`
|
||||
]
|
||||
} else {
|
||||
toolName = await io.which('bash', true)
|
||||
args = [
|
||||
'-c',
|
||||
`node '${scriptPath}' 'file=${semaphorePath}' & echo hi 1>&2`
|
||||
]
|
||||
}
|
||||
|
||||
await exec
|
||||
.exec(`"${toolName}"`, args, _testExecOptions)
|
||||
.exec(
|
||||
`"${nodePath}"`,
|
||||
[SPAWN_WAIT_SCRIPT, `file=${semaphorePath}`, 'stderr=true'],
|
||||
_testExecOptions
|
||||
)
|
||||
.then(() => {
|
||||
throw new Error('Should not have succeeded')
|
||||
})
|
||||
@@ -515,7 +472,7 @@ describe('@actions/exec', () => {
|
||||
).toBe(1)
|
||||
|
||||
fs.unlinkSync(semaphorePath)
|
||||
})
|
||||
}, 10000)
|
||||
|
||||
it('Exec roots relative tool path using unrooted options.cwd', async () => {
|
||||
let exitCode: number
|
||||
@@ -665,12 +622,12 @@ describe('@actions/exec', () => {
|
||||
const stdErrPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stderroutput.js'
|
||||
'stderroutput.cjs'
|
||||
)
|
||||
const stdOutPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stdoutoutput.js'
|
||||
'stdoutoutput.cjs'
|
||||
)
|
||||
const nodePath: string = await io.which('node', true)
|
||||
|
||||
@@ -696,12 +653,12 @@ describe('@actions/exec', () => {
|
||||
const stdErrPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stderroutput.js'
|
||||
'stderroutput.cjs'
|
||||
)
|
||||
const stdOutPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stdoutoutput.js'
|
||||
'stdoutoutput.cjs'
|
||||
)
|
||||
|
||||
const nodePath: string = await io.which('node', true)
|
||||
@@ -746,12 +703,12 @@ describe('@actions/exec', () => {
|
||||
const stdErrPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stderroutput.js'
|
||||
'stderroutput.cjs'
|
||||
)
|
||||
const stdOutPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stdoutoutputlarge.js'
|
||||
'stdoutoutputlarge.cjs'
|
||||
)
|
||||
|
||||
const nodePath: string = await io.which('node', true)
|
||||
@@ -796,7 +753,7 @@ describe('@actions/exec', () => {
|
||||
const stdOutPath: string = path.join(
|
||||
__dirname,
|
||||
'scripts',
|
||||
'stdoutputspecial.js'
|
||||
'stdoutputspecial.cjs'
|
||||
)
|
||||
|
||||
const nodePath: string = await io.which('node', true)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
const childProcess = require('child_process')
|
||||
const path = require('path')
|
||||
|
||||
// Parse args
|
||||
const args = {}
|
||||
for (const arg of process.argv.slice(2)) {
|
||||
const idx = arg.indexOf('=')
|
||||
if (idx !== -1) {
|
||||
args[arg.slice(0, idx)] = arg.slice(idx + 1)
|
||||
}
|
||||
}
|
||||
|
||||
const filePath = args.file
|
||||
if (!filePath) {
|
||||
throw new Error('file is not specified')
|
||||
}
|
||||
|
||||
// Spawn wait-for-file.cjs with inherited stdio
|
||||
// This creates a grandchild process that holds the stdio handles open
|
||||
// after this process (the child) exits
|
||||
const waitScript = path.join(__dirname, 'wait-for-file.cjs')
|
||||
const isWindows = process.platform === 'win32'
|
||||
|
||||
// On Windows, use detached:true to properly keep streams open
|
||||
// On Unix, detached:true also works and creates a new process group
|
||||
const child = childProcess.spawn(process.execPath, [waitScript, `file=${filePath}`], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
detached: true,
|
||||
windowsHide: true
|
||||
})
|
||||
|
||||
// Don't wait for child to exit
|
||||
child.unref()
|
||||
|
||||
// Handle optional stderr output (must happen BEFORE we exit)
|
||||
if (args.stderr === 'true') {
|
||||
process.stderr.write('hi')
|
||||
}
|
||||
|
||||
// Small delay to ensure child has started and inherited handles
|
||||
setTimeout(() => {
|
||||
const exitCode = args.exitCode ? parseInt(args.exitCode, 10) : 0
|
||||
process.exit(exitCode)
|
||||
}, 50)
|
||||
Generated
+8
-14
@@ -1,28 +1,22 @@
|
||||
{
|
||||
"name": "@actions/exec",
|
||||
"version": "1.1.1",
|
||||
"lockfileVersion": 2,
|
||||
"version": "3.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@actions/exec",
|
||||
"version": "1.1.1",
|
||||
"version": "3.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^1.0.1"
|
||||
"@actions/io": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.1.tgz",
|
||||
"integrity": "sha512-rhq+tfZukbtaus7xyUtwKfuiCRXd1hWSfmJNEpFgBQJ4woqPEpsBw04awicjwz9tyG2/MVhAEMfVn664Cri5zA=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/io": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.1.tgz",
|
||||
"integrity": "sha512-rhq+tfZukbtaus7xyUtwKfuiCRXd1hWSfmJNEpFgBQJ4woqPEpsBw04awicjwz9tyG2/MVhAEMfVn664Cri5zA=="
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz",
|
||||
"integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/exec",
|
||||
"version": "1.1.1",
|
||||
"version": "3.0.0",
|
||||
"description": "Actions exec lib",
|
||||
"keywords": [
|
||||
"github",
|
||||
@@ -9,8 +9,15 @@
|
||||
],
|
||||
"homepage": "https://github.com/actions/toolkit/tree/main/packages/exec",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "lib/exec.js",
|
||||
"types": "lib/exec.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/exec.d.ts",
|
||||
"import": "./lib/exec.js"
|
||||
}
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "__tests__"
|
||||
@@ -36,6 +43,6 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/io": "^1.0.1"
|
||||
"@actions/io": "^3.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {StringDecoder} from 'string_decoder'
|
||||
import {ExecOptions, ExecOutput, ExecListeners} from './interfaces'
|
||||
import * as tr from './toolrunner'
|
||||
import {ExecOptions, ExecOutput, ExecListeners} from './interfaces.js'
|
||||
import * as tr from './toolrunner.js'
|
||||
|
||||
export {ExecOptions, ExecOutput, ExecListeners}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as events from 'events'
|
||||
import * as child from 'child_process'
|
||||
import * as path from 'path'
|
||||
import * as stream from 'stream'
|
||||
import * as im from './interfaces'
|
||||
import * as im from './interfaces.js'
|
||||
import * as io from '@actions/io'
|
||||
import * as ioUtil from '@actions/io/lib/io-util'
|
||||
import {setTimeout} from 'timers'
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src"
|
||||
"rootDir": "./src",
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16"
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
|
||||
@@ -6,9 +6,20 @@
|
||||
|
||||
Returns an authenticated Octokit client that follows the machine [proxy settings](https://help.github.com/en/actions/hosting-your-own-runners/using-a-proxy-server-with-self-hosted-runners) and correctly sets GHES base urls. See https://octokit.github.io/rest.js for the API.
|
||||
|
||||
**Note:** This package is ESM-only starting from v9.0.0. For CommonJS projects, use dynamic import:
|
||||
```js
|
||||
const github = require('@actions/github');
|
||||
const core = require('@actions/core');
|
||||
async function main() {
|
||||
const { getOctokit, context } = await import('@actions/github');
|
||||
// ... your code here
|
||||
}
|
||||
main();
|
||||
```
|
||||
|
||||
For bundled actions (recommended), most bundlers like esbuild, webpack, and rollup handle ESM imports automatically.
|
||||
|
||||
```js
|
||||
import * as github from '@actions/github';
|
||||
import * as core from '@actions/core';
|
||||
|
||||
async function run() {
|
||||
// This should be a token with access to your repository scoped in as a secret.
|
||||
@@ -46,7 +57,7 @@ const result = await octokit.graphql(query, variables);
|
||||
Finally, you can get the context of the current action:
|
||||
|
||||
```js
|
||||
const github = require('@actions/github');
|
||||
import * as github from '@actions/github';
|
||||
|
||||
const context = github.context;
|
||||
|
||||
|
||||
@@ -1,5 +1,36 @@
|
||||
# @actions/github Releases
|
||||
|
||||
### 9.0.0
|
||||
|
||||
- **Breaking change**: Package is now ESM-only
|
||||
- CommonJS consumers must use dynamic `import()` instead of `require()`
|
||||
- Example: `const { getOctokit, context } = await import('@actions/github')`
|
||||
- Fix TypeScript compilation by migrating to ESM, enabling proper imports from `@octokit/core/types`
|
||||
|
||||
### 8.0.1
|
||||
|
||||
- Update `undici` to `6.23.0`
|
||||
- Update `@actions/http-client` to `3.0.2`
|
||||
|
||||
### 8.0.0
|
||||
|
||||
- Update @octokit dependencies
|
||||
- `@octokit/core` ^7.0.6
|
||||
- `@octokit/plugin-paginate-rest` ^14.0.0
|
||||
- `@octokit/plugin-rest-endpoint-methods` ^17.0.0
|
||||
- `@octokit/request` ^10.0.7
|
||||
- `@octokit/request-error` ^7.1.0
|
||||
- **Breaking change**: Minimum Node.js version is now 20 (previously 18)
|
||||
|
||||
### 7.0.0
|
||||
|
||||
- Update to v3.0.1 of `@actions/http-client`
|
||||
|
||||
### 6.0.1
|
||||
|
||||
- Dependency updates [#2043](https://github.com/actions/toolkit/pull/2043)
|
||||
- Add `context.runAttempt` [#1588](https://github.com/actions/toolkit/pull/1588)
|
||||
|
||||
### 6.0.0
|
||||
- Support the latest Octokit in @actions/github [#1553](https://github.com/actions/toolkit/pull/1553)
|
||||
- Drop support of NodeJS v14, v16
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import * as path from 'path'
|
||||
import {Context} from '../src/context'
|
||||
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
import {readFileSync} from 'fs'
|
||||
import {Context} from '../src/context.js'
|
||||
|
||||
describe('@actions/context', () => {
|
||||
let context: Context
|
||||
@@ -14,7 +12,10 @@ describe('@actions/context', () => {
|
||||
})
|
||||
|
||||
it('returns the payload object', () => {
|
||||
expect(context.payload).toEqual(require('./payload.json'))
|
||||
const payload = JSON.parse(
|
||||
readFileSync(path.join(__dirname, 'payload.json'), 'utf8')
|
||||
)
|
||||
expect(context.payload).toEqual(payload)
|
||||
})
|
||||
|
||||
it('returns an empty payload if the GITHUB_EVENT_PATH environment variable is falsey', () => {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/** @type {import('jest').Config} */
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1'
|
||||
},
|
||||
transform: {
|
||||
'^.+\\.(ts|js)$': ['ts-jest', {
|
||||
tsconfig: {
|
||||
allowJs: true,
|
||||
esModuleInterop: true,
|
||||
module: 'node16',
|
||||
moduleResolution: 'node16'
|
||||
}
|
||||
}]
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'/node_modules/(?!(@octokit|universal-user-agent|before-after-hook)/)'
|
||||
],
|
||||
verbose: true
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
}
|
||||
Generated
+144
-405
@@ -1,159 +1,161 @@
|
||||
{
|
||||
"name": "@actions/github",
|
||||
"version": "6.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"version": "9.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@actions/github",
|
||||
"version": "6.0.0",
|
||||
"version": "9.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.2.0",
|
||||
"@octokit/core": "^5.0.1",
|
||||
"@octokit/plugin-paginate-rest": "^9.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.0.0",
|
||||
"undici": "^5.28.5"
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@octokit/core": "^7.0.6",
|
||||
"@octokit/plugin-paginate-rest": "^14.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
||||
"@octokit/request": "^10.0.7",
|
||||
"@octokit/request-error": "^7.1.0",
|
||||
"undici": "^6.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"proxy": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz",
|
||||
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
|
||||
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz",
|
||||
"integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz",
|
||||
"integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==",
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz",
|
||||
"integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.0.0",
|
||||
"@octokit/request": "^8.0.2",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^12.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/auth-token": "^6.0.0",
|
||||
"@octokit/graphql": "^9.0.3",
|
||||
"@octokit/request": "^10.0.6",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"before-after-hook": "^4.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz",
|
||||
"integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==",
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz",
|
||||
"integrity": "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/types": "^16.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz",
|
||||
"integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==",
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz",
|
||||
"integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^8.0.1",
|
||||
"@octokit/types": "^12.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/request": "^10.0.6",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz",
|
||||
"integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw=="
|
||||
"version": "27.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz",
|
||||
"integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz",
|
||||
"integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==",
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz",
|
||||
"integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.0.0"
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=5"
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz",
|
||||
"integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==",
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz",
|
||||
"integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.0.0"
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=5"
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "8.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.4.tgz",
|
||||
"integrity": "sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==",
|
||||
"version": "10.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz",
|
||||
"integrity": "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^9.0.0",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^12.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/endpoint": "^11.0.2",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"fast-content-type-parse": "^3.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz",
|
||||
"integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz",
|
||||
"integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz",
|
||||
"integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==",
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz",
|
||||
"integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^19.0.0"
|
||||
"@octokit/openapi-types": "^27.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
@@ -161,6 +163,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
@@ -173,6 +176,7 @@
|
||||
"resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
|
||||
"integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"camelcase": "5.0.0",
|
||||
"chalk": "2.4.2",
|
||||
@@ -190,15 +194,17 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz",
|
||||
"integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw=="
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz",
|
||||
"integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
|
||||
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -208,6 +214,7 @@
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
@@ -222,6 +229,7 @@
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
@@ -230,15 +238,17 @@
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -249,42 +259,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz",
|
||||
"integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -294,34 +310,32 @@
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
|
||||
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.1.1.tgz",
|
||||
"integrity": "sha512-nLgd7zdUAOpB3ZO/xCkU8gy74UER7P0aihU8DkUsDS5ZoFwVCX7u8dy+cv5tVK8UaB/yminU1GiLWE26TKPYpg==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.2.0.tgz",
|
||||
"integrity": "sha512-nYclNIWj9UpXbVJ3W5EXIYiGR88AKZoGt90kyh3zoOBY5QW+7bbtPvMFgKGD4VJmpS3UXQXtlGXSg3lRNLOFLg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"args": "^5.0.3",
|
||||
"basic-auth-parser": "0.0.2-1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"bin": {
|
||||
"proxy": "dist/bin/proxy.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
@@ -331,6 +345,7 @@
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
@@ -342,301 +357,25 @@
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.28.5",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/http-client": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz",
|
||||
"integrity": "sha512-q+epW0trjVUUHboliPb4UF9g2msf+w61b32tAkFEwL/IwP0DQWgbCMM0Hbe3e3WXSKz5VcUXbzJQgy8Hkra/Lg==",
|
||||
"requires": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"@fastify/busboy": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
|
||||
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ=="
|
||||
},
|
||||
"@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA=="
|
||||
},
|
||||
"@octokit/core": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.1.tgz",
|
||||
"integrity": "sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==",
|
||||
"requires": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.0.0",
|
||||
"@octokit/request": "^8.0.2",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^12.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/endpoint": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.1.tgz",
|
||||
"integrity": "sha512-hRlOKAovtINHQPYHZlfyFwaM8OyetxeoC81lAkBy34uLb8exrZB50SQdeW3EROqiY9G9yxQTpp5OHTV54QD+vA==",
|
||||
"requires": {
|
||||
"@octokit/types": "^12.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/graphql": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz",
|
||||
"integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==",
|
||||
"requires": {
|
||||
"@octokit/request": "^8.0.1",
|
||||
"@octokit/types": "^12.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/openapi-types": {
|
||||
"version": "19.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-19.0.0.tgz",
|
||||
"integrity": "sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw=="
|
||||
},
|
||||
"@octokit/plugin-paginate-rest": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.0.0.tgz",
|
||||
"integrity": "sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==",
|
||||
"requires": {
|
||||
"@octokit/types": "^12.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.0.0.tgz",
|
||||
"integrity": "sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==",
|
||||
"requires": {
|
||||
"@octokit/types": "^12.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request": {
|
||||
"version": "8.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.4.tgz",
|
||||
"integrity": "sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==",
|
||||
"requires": {
|
||||
"@octokit/endpoint": "^9.0.0",
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^12.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"@octokit/request-error": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.1.tgz",
|
||||
"integrity": "sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==",
|
||||
"requires": {
|
||||
"@octokit/types": "^12.0.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.0.0.tgz",
|
||||
"integrity": "sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==",
|
||||
"requires": {
|
||||
"@octokit/openapi-types": "^19.0.0"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"args": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
|
||||
"integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "5.0.0",
|
||||
"chalk": "2.4.2",
|
||||
"leven": "2.1.0",
|
||||
"mri": "1.1.4"
|
||||
}
|
||||
},
|
||||
"basic-auth-parser": {
|
||||
"version": "0.0.2-1",
|
||||
"resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2-1.tgz",
|
||||
"integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"before-after-hook": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.1.tgz",
|
||||
"integrity": "sha512-/6FKxSTWoJdbsLDF8tdIjaRiFXiE6UHsEHE3OPI/cwPURCVi1ukP0gmLn7XWEiFk5TcwQjjY5PWsU+j+tgXgmw=="
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
|
||||
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"deprecation": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
|
||||
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true
|
||||
},
|
||||
"is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
|
||||
},
|
||||
"leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
|
||||
"dev": true
|
||||
},
|
||||
"mri": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
|
||||
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"proxy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.1.1.tgz",
|
||||
"integrity": "sha512-nLgd7zdUAOpB3ZO/xCkU8gy74UER7P0aihU8DkUsDS5ZoFwVCX7u8dy+cv5tVK8UaB/yminU1GiLWE26TKPYpg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"args": "^5.0.3",
|
||||
"basic-auth-parser": "0.0.2-1",
|
||||
"debug": "^4.3.4"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||
},
|
||||
"undici": {
|
||||
"version": "5.28.5",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||
"requires": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"universal-user-agent": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
|
||||
"integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/github",
|
||||
"version": "6.0.0",
|
||||
"version": "9.0.0",
|
||||
"description": "Actions github lib",
|
||||
"keywords": [
|
||||
"github",
|
||||
@@ -8,8 +8,19 @@
|
||||
],
|
||||
"homepage": "https://github.com/actions/toolkit/tree/main/packages/github",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "lib/github.js",
|
||||
"types": "lib/github.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/github.d.ts",
|
||||
"import": "./lib/github.js"
|
||||
},
|
||||
"./lib/utils": {
|
||||
"types": "./lib/utils.d.ts",
|
||||
"import": "./lib/utils.js"
|
||||
}
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "__tests__"
|
||||
@@ -38,11 +49,13 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.2.0",
|
||||
"@octokit/core": "^5.0.1",
|
||||
"@octokit/plugin-paginate-rest": "^9.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.0.0",
|
||||
"undici": "^5.28.5"
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@octokit/core": "^7.0.6",
|
||||
"@octokit/plugin-paginate-rest": "^14.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
||||
"@octokit/request": "^10.0.7",
|
||||
"@octokit/request-error": "^7.1.0",
|
||||
"undici": "^6.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"proxy": "^2.1.1"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Originally pulled from https://github.com/JasonEtco/actions-toolkit/blob/main/src/context.ts
|
||||
import {WebhookPayload} from './interfaces'
|
||||
import {WebhookPayload} from './interfaces.js'
|
||||
import {readFileSync, existsSync} from 'fs'
|
||||
import {EOL} from 'os'
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as Context from './context'
|
||||
import {GitHub, getOctokitOptions} from './utils'
|
||||
|
||||
import * as Context from './context.js'
|
||||
import {GitHub, getOctokitOptions} from './utils.js'
|
||||
// octokit + plugins
|
||||
import {OctokitOptions, OctokitPlugin} from '@octokit/core/dist-types/types'
|
||||
import type {OctokitOptions, OctokitPlugin} from '@octokit/core/types'
|
||||
|
||||
export const context = new Context.Context()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as http from 'http'
|
||||
import * as httpClient from '@actions/http-client'
|
||||
import {OctokitOptions} from '@octokit/core/dist-types/types'
|
||||
import type {OctokitOptions} from '@octokit/core/types'
|
||||
import {ProxyAgent, fetch} from 'undici'
|
||||
|
||||
export function getAuthString(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as Context from './context'
|
||||
import * as Utils from './internal/utils'
|
||||
import * as Context from './context.js'
|
||||
import * as Utils from './internal/utils.js'
|
||||
import type {OctokitOptions} from '@octokit/core/types'
|
||||
|
||||
// octokit + plugins
|
||||
import {Octokit} from '@octokit/core'
|
||||
import {OctokitOptions} from '@octokit/core/dist-types/types'
|
||||
import {restEndpointMethods} from '@octokit/plugin-rest-endpoint-methods'
|
||||
import {paginateRest} from '@octokit/plugin-paginate-rest'
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src"
|
||||
"rootDir": "./src",
|
||||
"module": "node16",
|
||||
"moduleResolution": "node16"
|
||||
},
|
||||
"include": [
|
||||
"./src"
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @actions/glob Releases
|
||||
|
||||
### 0.5.1
|
||||
|
||||
- Bump `@actions/core` to `2.0.3`
|
||||
|
||||
### 0.5.0
|
||||
- Added `excludeHiddenFiles` option, which is disabled by default to preserve existing behavior [#1791: Add glob option to ignore hidden files](https://github.com/actions/toolkit/pull/1791)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import {hashFiles} from '../src/glob'
|
||||
import {promises as fs} from 'fs'
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
const ORIGINAL_GITHUB_WORKSPACE = process.env['GITHUB_WORKSPACE']
|
||||
|
||||
/**
|
||||
* These test focus on the ability of globber to find files
|
||||
@@ -12,6 +13,16 @@ const IS_WINDOWS = process.platform === 'win32'
|
||||
describe('globber', () => {
|
||||
beforeAll(async () => {
|
||||
await io.rmRF(getTestTemp())
|
||||
process.env['GITHUB_WORKSPACE'] = __dirname
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
if (ORIGINAL_GITHUB_WORKSPACE) {
|
||||
process.env['GITHUB_WORKSPACE'] = ORIGINAL_GITHUB_WORKSPACE
|
||||
} else {
|
||||
delete process.env['GITHUB_WORKSPACE']
|
||||
}
|
||||
await io.rmRF(getTestTemp())
|
||||
})
|
||||
|
||||
it('basic hashfiles test', async () => {
|
||||
|
||||
Generated
+47
-58
@@ -1,59 +1,64 @@
|
||||
{
|
||||
"name": "@actions/glob",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"lockfileVersion": 3,
|
||||
"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": {
|
||||
"": {
|
||||
"name": "@actions/glob",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/core": "^2.0.3",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz",
|
||||
"integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.3.tgz",
|
||||
"integrity": "sha512-Od9Thc3T1mQJYddvVPM4QGiLUewdh+3txmDYHHxoNdkqysR1MbCT+rFOtNUxYAz+7+6RIsqipVahY2GJqGPyxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^2.0.1",
|
||||
"uuid": "^8.3.2"
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz",
|
||||
"integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.1.0.tgz",
|
||||
"integrity": "sha512-BonhODnXr3amchh4qkmjPMUO8mFi/zLaaCeCAJZqch8iQqyDnVIkySjB38VHAC8IJ+bnlgfOqlhpyCUZHlQsqw==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6"
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
|
||||
"integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@@ -62,12 +67,14 @@
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
@@ -79,37 +86,19 @@
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"license": "MIT",
|
||||
"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"
|
||||
"node_modules/undici": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
}
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "__tests__"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"directory": "packages/glob",
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/actions/toolkit.git"
|
||||
},
|
||||
"scripts": {
|
||||
"audit-moderate": "npm install && npm audit --json --audit-level=moderate > audit.json",
|
||||
"test": "echo \"Error: run tests from root\" && exit 1",
|
||||
"tsc": "tsc"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/glob",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"preview": true,
|
||||
"description": "Actions glob lib",
|
||||
"keywords": [
|
||||
@@ -37,7 +37,7 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/core": "^2.0.3",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export async function hashFiles(
|
||||
let hasMatch = false
|
||||
const githubWorkspace = currentWorkspace
|
||||
? currentWorkspace
|
||||
: process.env['GITHUB_WORKSPACE'] ?? process.cwd()
|
||||
: (process.env['GITHUB_WORKSPACE'] ?? process.cwd())
|
||||
const result = crypto.createHash('sha256')
|
||||
let count = 0
|
||||
for await (const file of globber.globGenerator()) {
|
||||
|
||||
@@ -7,7 +7,7 @@ A lightweight HTTP client optimized for building actions.
|
||||
- HTTP client with TypeScript generics and async/await/Promises
|
||||
- Typings included!
|
||||
- [Proxy support](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/about-self-hosted-runners#using-a-proxy-server-with-self-hosted-runners) just works with actions and the runner
|
||||
- Targets ES2019 (runner runs actions with node 12+). Only supported on node 12+.
|
||||
- Targets ES2019 (runner runs actions with node 24+). Only supported on node 20+.
|
||||
- Basic, Bearer and PAT Support out of the box. Extensible handlers for others.
|
||||
- Redirects supported
|
||||
|
||||
@@ -44,7 +44,7 @@ export NODE_DEBUG=http
|
||||
|
||||
## Node support
|
||||
|
||||
The http-client is built using the latest LTS version of Node 12. It may work on previous node LTS versions but it's tested and officially supported on Node12+.
|
||||
The http-client is built using Node 24. It may work on previous node LTS versions but it's tested and officially supported on Node 20+.
|
||||
|
||||
## Support and Versioning
|
||||
|
||||
|
||||
@@ -1,28 +1,53 @@
|
||||
## Releases
|
||||
# Releases
|
||||
|
||||
## 4.0.0
|
||||
|
||||
- **Breaking change**: Package is now ESM-only
|
||||
- CommonJS consumers must use dynamic `import()` instead of `require()`
|
||||
|
||||
## 3.0.2
|
||||
|
||||
- Bump `undici` from `5.28.5` to `6.23.0`
|
||||
|
||||
## 3.0.1
|
||||
|
||||
- Add support for ACTIONS_ORCHESTRATION_ID in user-agent and default user-agent [#2229](https://github.com/actions/toolkit/pull/2229)
|
||||
|
||||
## 3.0.0
|
||||
|
||||
- Add support for Node 24 [#2110](https://github.com/actions/toolkit/pull/2110)
|
||||
|
||||
## 2.2.3
|
||||
|
||||
- Fixed an issue where proxy username and password were not handled correctly [#1799](https://github.com/actions/toolkit/pull/1799)
|
||||
|
||||
## 2.2.2
|
||||
|
||||
- Better handling of url encoded usernames and passwords in proxy config [#1782](https://github.com/actions/toolkit/pull/1782)
|
||||
|
||||
## 2.2.1
|
||||
|
||||
- Make sure RequestOptions.keepAlive is applied properly on node20 runtime [#1572](https://github.com/actions/toolkit/pull/1572)
|
||||
|
||||
## 2.2.0
|
||||
|
||||
- Add function to return proxy agent dispatcher for compatibility with latest octokit packages [#1547](https://github.com/actions/toolkit/pull/1547)
|
||||
|
||||
## 2.1.1
|
||||
|
||||
- Add `HttpClientResponse.readBodyBuffer` method to read from a response stream and return a buffer [#1475](https://github.com/actions/toolkit/pull/1475)
|
||||
|
||||
## 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
|
||||
|
||||
- Fix an issue with missing `tunnel` dependency [#1085](https://github.com/actions/toolkit/pull/1085)
|
||||
|
||||
## 2.0.0
|
||||
|
||||
- The package is now compiled with TypeScript's [`strict` compiler setting](https://www.typescriptlang.org/tsconfig#strict). To comply with stricter rules:
|
||||
- Some exported types now include `| null` or `| undefined`, matching their actual behavior.
|
||||
- Types implementing the method `RequestHandler.handleAuthentication()` now throw an `Error` rather than returning `null` if they do not support handling an HTTP 401 response. Callers can still use `canHandleAuthentication()` to determine if this handling is supported or not.
|
||||
@@ -34,25 +59,32 @@
|
||||
|
||||
## 1.0.11
|
||||
|
||||
Contains a bug fix where proxy is defined without a user and password. see [PR here](https://github.com/actions/http-client/pull/42)
|
||||
Contains a bug fix where proxy is defined without a user and password. see [PR here](https://github.com/actions/http-client/pull/42)
|
||||
|
||||
## 1.0.9
|
||||
Throw HttpClientError instead of a generic Error from the \<verb>Json() helper methods when the server responds with a non-successful status code.
|
||||
|
||||
Throw HttpClientError instead of a generic Error from the \<verb>Json() helper methods when the server responds with a non-successful status code.
|
||||
|
||||
## 1.0.8
|
||||
|
||||
Fixed security issue where a redirect (e.g. 302) to another domain would pass headers. The fix was to strip the authorization header if the hostname was different. More [details in PR #27](https://github.com/actions/http-client/pull/27)
|
||||
|
||||
## 1.0.7
|
||||
|
||||
Update NPM dependencies and add 429 to the list of HttpCodes
|
||||
|
||||
## 1.0.6
|
||||
|
||||
Automatically sends Content-Type and Accept application/json headers for \<verb>Json() helper methods if not set in the client or parameters.
|
||||
|
||||
## 1.0.5
|
||||
|
||||
Adds \<verb>Json() helper methods for json over http scenarios.
|
||||
|
||||
## 1.0.4
|
||||
|
||||
Started to add \<verb>Json() helper methods. Do not use this release for that. Use >= 1.0.5 since there was an issue with types.
|
||||
|
||||
## 1.0.1 to 1.0.3
|
||||
|
||||
Adds proxy support.
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('auth', () => {
|
||||
bh
|
||||
])
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
@@ -26,7 +26,7 @@ describe('auth', () => {
|
||||
'base64'
|
||||
).toString()
|
||||
expect(creds).toBe('johndoe:password')
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does basic http get request with pat token auth', async () => {
|
||||
@@ -38,7 +38,7 @@ describe('auth', () => {
|
||||
ph
|
||||
])
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
@@ -49,7 +49,7 @@ describe('auth', () => {
|
||||
'base64'
|
||||
).toString()
|
||||
expect(creds).toBe(`PAT:${token}`)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does basic http get request with pat token auth', async () => {
|
||||
@@ -60,13 +60,13 @@ describe('auth', () => {
|
||||
ph
|
||||
])
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
const auth: string = obj.headers.authorization
|
||||
expect(auth).toBe(`Bearer ${token}`)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -21,7 +21,10 @@ describe('basics', () => {
|
||||
_http = new httpm.HttpClient('http-client-tests')
|
||||
})
|
||||
|
||||
afterEach(() => {})
|
||||
afterEach(() => {
|
||||
// Clean up environment variable to prevent test pollution
|
||||
delete process.env['ACTIONS_ORCHESTRATION_ID']
|
||||
})
|
||||
|
||||
it('constructs', () => {
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('thttp-client-tests')
|
||||
@@ -37,41 +40,41 @@ describe('basics', () => {
|
||||
// "user-agent": "typed-test-client-tests"
|
||||
// },
|
||||
// "origin": "173.95.152.44",
|
||||
// "url": "http://postman-echo.com/get"
|
||||
// "url": "https://postman-echo.com/get"
|
||||
// }
|
||||
|
||||
it('does basic http get request', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
expect(obj.headers['user-agent']).toBeTruthy()
|
||||
})
|
||||
|
||||
it('does basic http get request with no user agent', async () => {
|
||||
const http: httpm.HttpClient = new httpm.HttpClient()
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.headers['user-agent']).toBeFalsy()
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
expect(obj.headers['user-agent']).toBe('actions/http-client')
|
||||
})
|
||||
|
||||
/* TODO write a mock rather then relying on a third party
|
||||
it('does basic https get request', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
*/
|
||||
it('does basic http get request with default headers', async () => {
|
||||
@@ -86,14 +89,14 @@ describe('basics', () => {
|
||||
}
|
||||
)
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.headers.accept).toBe('application/json')
|
||||
expect(obj.headers['content-type']).toBe('application/json')
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does basic http get request with merged headers', async () => {
|
||||
@@ -108,7 +111,7 @@ describe('basics', () => {
|
||||
}
|
||||
)
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'http://postman-echo.com/get',
|
||||
'https://postman-echo.com/get',
|
||||
{
|
||||
'content-type': 'application/x-www-form-urlencoded'
|
||||
}
|
||||
@@ -120,18 +123,18 @@ describe('basics', () => {
|
||||
expect(obj.headers['content-type']).toBe(
|
||||
'application/x-www-form-urlencoded'
|
||||
)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('pipes a get request', async () => {
|
||||
return new Promise<void>(async resolve => {
|
||||
const file = fs.createWriteStream(sampleFilePath)
|
||||
;(await _http.get('http://postman-echo.com/get')).message
|
||||
;(await _http.get('https://postman-echo.com/get')).message
|
||||
.pipe(file)
|
||||
.on('close', () => {
|
||||
const body: string = fs.readFileSync(sampleFilePath).toString()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
@@ -139,32 +142,32 @@ describe('basics', () => {
|
||||
|
||||
it('does basic get request with redirects', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'http://postman-echo.com/get'
|
||||
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'https://postman-echo.com/get'
|
||||
)}`
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does basic get request with redirects (303)', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'http://postman-echo.com/get'
|
||||
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'https://postman-echo.com/get'
|
||||
)}&status_code=303`
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('returns 404 for not found get request on redirect', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'http://postman-echo.com/status/404'
|
||||
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'https://postman-echo.com/status/404'
|
||||
)}&status_code=303`
|
||||
)
|
||||
expect(res.message.statusCode).toBe(404)
|
||||
@@ -178,8 +181,8 @@ describe('basics', () => {
|
||||
{allowRedirects: false}
|
||||
)
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'http://postman-echo.com/get'
|
||||
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'https://postman-echo.com/get'
|
||||
)}`
|
||||
)
|
||||
expect(res.message.statusCode).toBe(302)
|
||||
@@ -192,8 +195,8 @@ describe('basics', () => {
|
||||
authorization: 'shhh'
|
||||
}
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'http://www.postman-echo.com/get'
|
||||
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'https://www.postman-echo.com/get'
|
||||
)}`,
|
||||
headers
|
||||
)
|
||||
@@ -205,7 +208,7 @@ describe('basics', () => {
|
||||
expect(obj.headers[httpm.Headers.Accept]).toBe('application/json')
|
||||
expect(obj.headers['Authorization']).toBeUndefined()
|
||||
expect(obj.headers['authorization']).toBeUndefined()
|
||||
expect(obj.url).toBe('http://www.postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://www.postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does not pass Auth with diff hostname redirects', async () => {
|
||||
@@ -214,8 +217,8 @@ describe('basics', () => {
|
||||
Authorization: 'shhh'
|
||||
}
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
`http://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'http://www.postman-echo.com/get'
|
||||
`https://postman-echo.com/redirect-to?url=${encodeURIComponent(
|
||||
'https://www.postman-echo.com/get'
|
||||
)}`,
|
||||
headers
|
||||
)
|
||||
@@ -227,19 +230,19 @@ describe('basics', () => {
|
||||
expect(obj.headers[httpm.Headers.Accept]).toBe('application/json')
|
||||
expect(obj.headers['Authorization']).toBeUndefined()
|
||||
expect(obj.headers['authorization']).toBeUndefined()
|
||||
expect(obj.url).toBe('http://www.postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://www.postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does basic head request', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.head(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
})
|
||||
|
||||
it('does basic http delete request', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.del(
|
||||
'http://postman-echo.com/delete'
|
||||
'https://postman-echo.com/delete'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
@@ -249,32 +252,32 @@ describe('basics', () => {
|
||||
it('does basic http post request', async () => {
|
||||
const b = 'Hello World!'
|
||||
const res: httpm.HttpClientResponse = await _http.post(
|
||||
'http://postman-echo.com/post',
|
||||
'https://postman-echo.com/post',
|
||||
b
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.data).toBe(b)
|
||||
expect(obj.url).toBe('http://postman-echo.com/post')
|
||||
expect(obj.url).toBe('https://postman-echo.com/post')
|
||||
})
|
||||
|
||||
it('does basic http patch request', async () => {
|
||||
const b = 'Hello World!'
|
||||
const res: httpm.HttpClientResponse = await _http.patch(
|
||||
'http://postman-echo.com/patch',
|
||||
'https://postman-echo.com/patch',
|
||||
b
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.data).toBe(b)
|
||||
expect(obj.url).toBe('http://postman-echo.com/patch')
|
||||
expect(obj.url).toBe('https://postman-echo.com/patch')
|
||||
})
|
||||
|
||||
it('does basic http options request', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.options(
|
||||
'http://postman-echo.com'
|
||||
'https://postman-echo.com'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
await res.readBody()
|
||||
@@ -282,7 +285,7 @@ describe('basics', () => {
|
||||
|
||||
it('returns 404 for not found get request', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
'http://postman-echo.com/status/404'
|
||||
'https://postman-echo.com/status/404'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(404)
|
||||
await res.readBody()
|
||||
@@ -290,11 +293,11 @@ describe('basics', () => {
|
||||
|
||||
it('gets a json object', async () => {
|
||||
const jsonObj = await _http.getJson<HttpBinData>(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(jsonObj.statusCode).toBe(200)
|
||||
expect(jsonObj.result).toBeDefined()
|
||||
expect(jsonObj.result?.url).toBe('http://postman-echo.com/get')
|
||||
expect(jsonObj.result?.url).toBe('https://postman-echo.com/get')
|
||||
expect(jsonObj.result?.headers[httpm.Headers.Accept]).toBe(
|
||||
httpm.MediaTypes.ApplicationJson
|
||||
)
|
||||
@@ -305,7 +308,7 @@ describe('basics', () => {
|
||||
|
||||
it('getting a non existent json object returns null', async () => {
|
||||
const jsonObj = await _http.getJson<HttpBinData>(
|
||||
'http://postman-echo.com/status/404'
|
||||
'https://postman-echo.com/status/404'
|
||||
)
|
||||
expect(jsonObj.statusCode).toBe(404)
|
||||
expect(jsonObj.result).toBeNull()
|
||||
@@ -314,12 +317,12 @@ describe('basics', () => {
|
||||
it('posts a json object', async () => {
|
||||
const res = {name: 'foo'}
|
||||
const restRes = await _http.postJson<HttpBinData>(
|
||||
'http://postman-echo.com/post',
|
||||
'https://postman-echo.com/post',
|
||||
res
|
||||
)
|
||||
expect(restRes.statusCode).toBe(200)
|
||||
expect(restRes.result).toBeDefined()
|
||||
expect(restRes.result?.url).toBe('http://postman-echo.com/post')
|
||||
expect(restRes.result?.url).toBe('https://postman-echo.com/post')
|
||||
expect(restRes.result?.json.name).toBe('foo')
|
||||
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe(
|
||||
httpm.MediaTypes.ApplicationJson
|
||||
@@ -335,12 +338,12 @@ describe('basics', () => {
|
||||
it('puts a json object', async () => {
|
||||
const res = {name: 'foo'}
|
||||
const restRes = await _http.putJson<HttpBinData>(
|
||||
'http://postman-echo.com/put',
|
||||
'https://postman-echo.com/put',
|
||||
res
|
||||
)
|
||||
expect(restRes.statusCode).toBe(200)
|
||||
expect(restRes.result).toBeDefined()
|
||||
expect(restRes.result?.url).toBe('http://postman-echo.com/put')
|
||||
expect(restRes.result?.url).toBe('https://postman-echo.com/put')
|
||||
expect(restRes.result?.json.name).toBe('foo')
|
||||
|
||||
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe(
|
||||
@@ -357,12 +360,12 @@ describe('basics', () => {
|
||||
it('patch a json object', async () => {
|
||||
const res = {name: 'foo'}
|
||||
const restRes = await _http.patchJson<HttpBinData>(
|
||||
'http://postman-echo.com/patch',
|
||||
'https://postman-echo.com/patch',
|
||||
res
|
||||
)
|
||||
expect(restRes.statusCode).toBe(200)
|
||||
expect(restRes.result).toBeDefined()
|
||||
expect(restRes.result?.url).toBe('http://postman-echo.com/patch')
|
||||
expect(restRes.result?.url).toBe('https://postman-echo.com/patch')
|
||||
expect(restRes.result?.json.name).toBe('foo')
|
||||
expect(restRes.result?.headers[httpm.Headers.Accept]).toBe(
|
||||
httpm.MediaTypes.ApplicationJson
|
||||
@@ -374,4 +377,66 @@ describe('basics', () => {
|
||||
httpm.MediaTypes.ApplicationJson
|
||||
)
|
||||
})
|
||||
|
||||
it('appends orchestration ID to user-agent when ACTIONS_ORCHESTRATION_ID is set', async () => {
|
||||
const orchId = 'test-orch-id-12345'
|
||||
process.env['ACTIONS_ORCHESTRATION_ID'] = orchId
|
||||
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('http-client-tests')
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.headers['user-agent']).toBe(
|
||||
`http-client-tests actions_orchestration_id/${orchId}`
|
||||
)
|
||||
})
|
||||
|
||||
it('sanitizes invalid characters in orchestration ID', async () => {
|
||||
const orchId = 'test (with) special/chars'
|
||||
process.env['ACTIONS_ORCHESTRATION_ID'] = orchId
|
||||
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('http-client-tests')
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
// Spaces, parentheses, and slashes should be replaced with underscores
|
||||
expect(obj.headers['user-agent']).toBe(
|
||||
'http-client-tests actions_orchestration_id/test__with__special_chars'
|
||||
)
|
||||
})
|
||||
|
||||
it('does not modify user-agent when ACTIONS_ORCHESTRATION_ID is not set', async () => {
|
||||
delete process.env['ACTIONS_ORCHESTRATION_ID']
|
||||
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('http-client-tests')
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.headers['user-agent']).toBe('http-client-tests')
|
||||
})
|
||||
|
||||
it('uses default user-agent with orchestration ID when no custom user-agent provided', async () => {
|
||||
const orchId = 'test-default-id-12345'
|
||||
process.env['ACTIONS_ORCHESTRATION_ID'] = orchId
|
||||
|
||||
const http: httpm.HttpClient = new httpm.HttpClient()
|
||||
const res: httpm.HttpClientResponse = await http.get(
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.headers['user-agent']).toBe(
|
||||
`actions/http-client actions_orchestration_id/${orchId}`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -12,7 +12,7 @@ describe('headers', () => {
|
||||
it('preserves existing headers on getJson', async () => {
|
||||
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
|
||||
let jsonObj = await _http.getJson<any>(
|
||||
'http://postman-echo.com/get',
|
||||
'https://postman-echo.com/get',
|
||||
additionalHeaders
|
||||
)
|
||||
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('foo')
|
||||
@@ -26,7 +26,7 @@ describe('headers', () => {
|
||||
[httpm.Headers.Accept]: 'baz'
|
||||
}
|
||||
}
|
||||
jsonObj = await httpWithHeaders.getJson<any>('http://postman-echo.com/get')
|
||||
jsonObj = await httpWithHeaders.getJson<any>('https://postman-echo.com/get')
|
||||
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
|
||||
expect(jsonObj.headers[httpm.Headers.ContentType]).toContain(
|
||||
httpm.MediaTypes.ApplicationJson
|
||||
@@ -36,7 +36,7 @@ describe('headers', () => {
|
||||
it('preserves existing headers on postJson', async () => {
|
||||
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
|
||||
let jsonObj = await _http.postJson<any>(
|
||||
'http://postman-echo.com/post',
|
||||
'https://postman-echo.com/post',
|
||||
{},
|
||||
additionalHeaders
|
||||
)
|
||||
@@ -52,7 +52,7 @@ describe('headers', () => {
|
||||
}
|
||||
}
|
||||
jsonObj = await httpWithHeaders.postJson<any>(
|
||||
'http://postman-echo.com/post',
|
||||
'https://postman-echo.com/post',
|
||||
{}
|
||||
)
|
||||
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
|
||||
@@ -64,7 +64,7 @@ describe('headers', () => {
|
||||
it('preserves existing headers on putJson', async () => {
|
||||
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
|
||||
let jsonObj = await _http.putJson<any>(
|
||||
'http://postman-echo.com/put',
|
||||
'https://postman-echo.com/put',
|
||||
{},
|
||||
additionalHeaders
|
||||
)
|
||||
@@ -80,7 +80,7 @@ describe('headers', () => {
|
||||
}
|
||||
}
|
||||
jsonObj = await httpWithHeaders.putJson<any>(
|
||||
'http://postman-echo.com/put',
|
||||
'https://postman-echo.com/put',
|
||||
{}
|
||||
)
|
||||
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
|
||||
@@ -92,7 +92,7 @@ describe('headers', () => {
|
||||
it('preserves existing headers on patchJson', async () => {
|
||||
const additionalHeaders = {[httpm.Headers.Accept]: 'foo'}
|
||||
let jsonObj = await _http.patchJson<any>(
|
||||
'http://postman-echo.com/patch',
|
||||
'https://postman-echo.com/patch',
|
||||
{},
|
||||
additionalHeaders
|
||||
)
|
||||
@@ -108,7 +108,7 @@ describe('headers', () => {
|
||||
}
|
||||
}
|
||||
jsonObj = await httpWithHeaders.patchJson<any>(
|
||||
'http://postman-echo.com/patch',
|
||||
'https://postman-echo.com/patch',
|
||||
{}
|
||||
)
|
||||
expect(jsonObj.result.headers[httpm.Headers.Accept]).toBe('baz')
|
||||
|
||||
@@ -13,30 +13,30 @@ describe('basics', () => {
|
||||
|
||||
it.each([true, false])('creates Agent with keepAlive %s', keepAlive => {
|
||||
const http = new httpm.HttpClient('http-client-tests', [], {keepAlive})
|
||||
const agent = http.getAgent('http://postman-echo.com')
|
||||
const agent = http.getAgent('https://postman-echo.com')
|
||||
expect(agent).toHaveProperty('keepAlive', keepAlive)
|
||||
})
|
||||
|
||||
it('does basic http get request with keepAlive true', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
})
|
||||
|
||||
it('does basic head request with keepAlive true', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.head(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
})
|
||||
|
||||
it('does basic http delete request with keepAlive true', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.del(
|
||||
'http://postman-echo.com/delete'
|
||||
'https://postman-echo.com/delete'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
@@ -46,32 +46,32 @@ describe('basics', () => {
|
||||
it('does basic http post request with keepAlive true', async () => {
|
||||
const b = 'Hello World!'
|
||||
const res: httpm.HttpClientResponse = await _http.post(
|
||||
'http://postman-echo.com/post',
|
||||
'https://postman-echo.com/post',
|
||||
b
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.data).toBe(b)
|
||||
expect(obj.url).toBe('http://postman-echo.com/post')
|
||||
expect(obj.url).toBe('https://postman-echo.com/post')
|
||||
})
|
||||
|
||||
it('does basic http patch request with keepAlive true', async () => {
|
||||
const b = 'Hello World!'
|
||||
const res: httpm.HttpClientResponse = await _http.patch(
|
||||
'http://postman-echo.com/patch',
|
||||
'https://postman-echo.com/patch',
|
||||
b
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.data).toBe(b)
|
||||
expect(obj.url).toBe('http://postman-echo.com/patch')
|
||||
expect(obj.url).toBe('https://postman-echo.com/patch')
|
||||
})
|
||||
|
||||
it('does basic http options request with keepAlive true', async () => {
|
||||
const res: httpm.HttpClientResponse = await _http.options(
|
||||
'http://postman-echo.com'
|
||||
'https://postman-echo.com'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
await res.readBody()
|
||||
|
||||
@@ -196,16 +196,16 @@ describe('proxy', () => {
|
||||
})
|
||||
|
||||
it('HttpClient does basic http get request through proxy', async () => {
|
||||
process.env['http_proxy'] = _proxyUrl
|
||||
process.env['https_proxy'] = _proxyUrl
|
||||
const httpClient = new httpm.HttpClient()
|
||||
const res: httpm.HttpClientResponse = await httpClient.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(_proxyConnects).toEqual(['postman-echo.com:80'])
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
expect(_proxyConnects).toEqual(['postman-echo.com:443'])
|
||||
})
|
||||
|
||||
it('HttpClient does basic http get request when bypass proxy', async () => {
|
||||
@@ -213,12 +213,12 @@ describe('proxy', () => {
|
||||
process.env['no_proxy'] = 'postman-echo.com'
|
||||
const httpClient = new httpm.HttpClient()
|
||||
const res: httpm.HttpClientResponse = await httpClient.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
expect(_proxyConnects).toHaveLength(0)
|
||||
})
|
||||
|
||||
@@ -228,12 +228,12 @@ describe('proxy', () => {
|
||||
process.env['https_proxy'] = _proxyUrl
|
||||
const httpClient = new httpm.HttpClient()
|
||||
const res: httpm.HttpClientResponse = await httpClient.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
expect(_proxyConnects).toEqual(['postman-echo.com:443'])
|
||||
})
|
||||
*/
|
||||
@@ -243,12 +243,12 @@ describe('proxy', () => {
|
||||
process.env['no_proxy'] = 'postman-echo.com'
|
||||
const httpClient = new httpm.HttpClient()
|
||||
const res: httpm.HttpClientResponse = await httpClient.get(
|
||||
'http://postman-echo.com/get'
|
||||
'https://postman-echo.com/get'
|
||||
)
|
||||
expect(res.message.statusCode).toBe(200)
|
||||
const body: string = await res.readBody()
|
||||
const obj = JSON.parse(body)
|
||||
expect(obj.url).toBe('http://postman-echo.com/get')
|
||||
expect(obj.url).toBe('https://postman-echo.com/get')
|
||||
expect(_proxyConnects).toHaveLength(0)
|
||||
})
|
||||
|
||||
|
||||
Generated
+57
-199
@@ -1,43 +1,40 @@
|
||||
{
|
||||
"name": "@actions/http-client",
|
||||
"version": "2.2.3",
|
||||
"lockfileVersion": 2,
|
||||
"version": "4.0.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@actions/http-client",
|
||||
"version": "2.2.3",
|
||||
"version": "4.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.28.5"
|
||||
"undici": "^6.23.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.7.1",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/proxy": "^1.0.1",
|
||||
"@types/tunnel": "0.0.3",
|
||||
"proxy": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@fastify/busboy": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
|
||||
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node_modules/@types/node": {
|
||||
"version": "24.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
|
||||
"integrity": "sha512-ut5FthK5moxFKH2T1CUOC6ctR67rQRvvHdFLCD2Ql6KXmMuCrjsSsRI9UsLCm9M18BMwClv4pn327UvB7eeO1w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
|
||||
"integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/proxy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.2.tgz",
|
||||
"integrity": "sha512-NDNsg7YuClVzEenn9SUButu43blypWvljGsIkDV7HI4N9apjrS0aeeMTUG0PYa71lD1AvIgvjkBagqHDiomDjA==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.4.tgz",
|
||||
"integrity": "sha512-KnYy7hpp3wXQ2U0ExvCMF9BvWZ6h2aI0XWb8g705mn26Zmn2HO/eLRi6UuhHELA6MNJtYtiZYWv38gobJN0xXQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@@ -47,6 +44,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz",
|
||||
"integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
@@ -56,6 +54,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
@@ -68,6 +67,7 @@
|
||||
"resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
|
||||
"integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"camelcase": "5.0.0",
|
||||
"chalk": "2.4.2",
|
||||
@@ -89,6 +89,7 @@
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
|
||||
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -98,6 +99,7 @@
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
@@ -112,6 +114,7 @@
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
@@ -120,15 +123,17 @@
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
@@ -144,6 +149,7 @@
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
@@ -153,6 +159,7 @@
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
@@ -162,6 +169,7 @@
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -171,26 +179,32 @@
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
|
||||
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.1.1.tgz",
|
||||
"integrity": "sha512-nLgd7zdUAOpB3ZO/xCkU8gy74UER7P0aihU8DkUsDS5ZoFwVCX7u8dy+cv5tVK8UaB/yminU1GiLWE26TKPYpg==",
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.2.0.tgz",
|
||||
"integrity": "sha512-nYclNIWj9UpXbVJ3W5EXIYiGR88AKZoGt90kyh3zoOBY5QW+7bbtPvMFgKGD4VJmpS3UXQXtlGXSg3lRNLOFLg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"args": "^5.0.3",
|
||||
"basic-auth-parser": "0.0.2-1",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"bin": {
|
||||
"proxy": "dist/bin/proxy.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
@@ -200,6 +214,7 @@
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
@@ -211,183 +226,26 @@
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.28.5",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0"
|
||||
"node": ">=18.17"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/busboy": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz",
|
||||
"integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "20.7.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz",
|
||||
"integrity": "sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/proxy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/proxy/-/proxy-1.0.2.tgz",
|
||||
"integrity": "sha512-NDNsg7YuClVzEenn9SUButu43blypWvljGsIkDV7HI4N9apjrS0aeeMTUG0PYa71lD1AvIgvjkBagqHDiomDjA==",
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.8.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz",
|
||||
"integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/tunnel": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/tunnel/-/tunnel-0.0.3.tgz",
|
||||
"integrity": "sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"args": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/args/-/args-5.0.3.tgz",
|
||||
"integrity": "sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"camelcase": "5.0.0",
|
||||
"chalk": "2.4.2",
|
||||
"leven": "2.1.0",
|
||||
"mri": "1.1.4"
|
||||
}
|
||||
},
|
||||
"basic-auth-parser": {
|
||||
"version": "0.0.2-1",
|
||||
"resolved": "https://registry.npmjs.org/basic-auth-parser/-/basic-auth-parser-0.0.2-1.tgz",
|
||||
"integrity": "sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
|
||||
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
|
||||
"dev": true
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"dev": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"dev": true
|
||||
},
|
||||
"leven": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz",
|
||||
"integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==",
|
||||
"dev": true
|
||||
},
|
||||
"mri": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/mri/-/mri-1.1.4.tgz",
|
||||
"integrity": "sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"proxy": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy/-/proxy-2.1.1.tgz",
|
||||
"integrity": "sha512-nLgd7zdUAOpB3ZO/xCkU8gy74UER7P0aihU8DkUsDS5ZoFwVCX7u8dy+cv5tVK8UaB/yminU1GiLWE26TKPYpg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"args": "^5.0.3",
|
||||
"basic-auth-parser": "0.0.2-1",
|
||||
"debug": "^4.3.4"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tunnel": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
|
||||
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
|
||||
},
|
||||
"undici": {
|
||||
"version": "5.28.5",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.5.tgz",
|
||||
"integrity": "sha512-zICwjrDrcrUE0pyyJc1I2QzBkLM8FINsgOrt6WjA+BgajVq9Nxu2PbFFXUrAggLfDXlZGZBVZYw7WNV5KiBiBA==",
|
||||
"requires": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
}
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@actions/http-client",
|
||||
"version": "2.2.3",
|
||||
"version": "4.0.0",
|
||||
"description": "Actions Http Client",
|
||||
"keywords": [
|
||||
"github",
|
||||
@@ -9,8 +9,27 @@
|
||||
],
|
||||
"homepage": "https://github.com/actions/toolkit/tree/main/packages/http-client",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"main": "lib/index.js",
|
||||
"types": "lib/index.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/index.d.ts",
|
||||
"import": "./lib/index.js"
|
||||
},
|
||||
"./lib/auth": {
|
||||
"types": "./lib/auth.d.ts",
|
||||
"import": "./lib/auth.js"
|
||||
},
|
||||
"./lib/proxy": {
|
||||
"types": "./lib/proxy.d.ts",
|
||||
"import": "./lib/proxy.js"
|
||||
},
|
||||
"./lib/interfaces": {
|
||||
"types": "./lib/interfaces.d.ts",
|
||||
"import": "./lib/interfaces.js"
|
||||
}
|
||||
},
|
||||
"directories": {
|
||||
"lib": "lib",
|
||||
"test": "__tests__"
|
||||
@@ -39,13 +58,16 @@
|
||||
"url": "https://github.com/actions/toolkit/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "20.7.1",
|
||||
"@types/node": "24.1.0",
|
||||
"@types/tunnel": "0.0.3",
|
||||
"proxy": "^2.1.1",
|
||||
"@types/proxy": "^1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.28.5"
|
||||
"undici": "^6.23.0"
|
||||
},
|
||||
"overrides": {
|
||||
"uri-js": "npm:uri-js-replace@^1.0.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as http from 'http'
|
||||
import * as ifm from './interfaces'
|
||||
import {HttpClientResponse} from './index'
|
||||
import * as ifm from './interfaces.js'
|
||||
import {HttpClientResponse} from './index.js'
|
||||
|
||||
export class BasicCredentialHandler implements ifm.RequestHandler {
|
||||
username: string
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import * as http from 'http'
|
||||
import * as https from 'https'
|
||||
import * as ifm from './interfaces'
|
||||
import * as ifm from './interfaces.js'
|
||||
import * as net from 'net'
|
||||
import * as pm from './proxy'
|
||||
import * as pm from './proxy.js'
|
||||
import * as tunnel from 'tunnel'
|
||||
import {ProxyAgent} from 'undici'
|
||||
|
||||
@@ -147,7 +147,7 @@ export class HttpClient {
|
||||
handlers?: ifm.RequestHandler[],
|
||||
requestOptions?: ifm.RequestOptions
|
||||
) {
|
||||
this.userAgent = userAgent
|
||||
this.userAgent = this._getUserAgentWithOrchestrationId(userAgent)
|
||||
this.handlers = handlers || []
|
||||
this.requestOptions = requestOptions
|
||||
if (requestOptions) {
|
||||
@@ -275,11 +275,11 @@ export class HttpClient {
|
||||
Headers.Accept,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(
|
||||
additionalHeaders,
|
||||
Headers.ContentType,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
additionalHeaders[Headers.ContentType] =
|
||||
this._getExistingOrDefaultContentTypeHeader(
|
||||
additionalHeaders,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
const res: HttpClientResponse = await this.post(
|
||||
requestUrl,
|
||||
data,
|
||||
@@ -299,11 +299,11 @@ export class HttpClient {
|
||||
Headers.Accept,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(
|
||||
additionalHeaders,
|
||||
Headers.ContentType,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
additionalHeaders[Headers.ContentType] =
|
||||
this._getExistingOrDefaultContentTypeHeader(
|
||||
additionalHeaders,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
const res: HttpClientResponse = await this.put(
|
||||
requestUrl,
|
||||
data,
|
||||
@@ -323,11 +323,11 @@ export class HttpClient {
|
||||
Headers.Accept,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(
|
||||
additionalHeaders,
|
||||
Headers.ContentType,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
additionalHeaders[Headers.ContentType] =
|
||||
this._getExistingOrDefaultContentTypeHeader(
|
||||
additionalHeaders,
|
||||
MediaTypes.ApplicationJson
|
||||
)
|
||||
const res: HttpClientResponse = await this.patch(
|
||||
requestUrl,
|
||||
data,
|
||||
@@ -628,16 +628,87 @@ export class HttpClient {
|
||||
return lowercaseKeys(headers || {})
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an existing header value or returns a default.
|
||||
* Handles converting number header values to strings since HTTP headers must be strings.
|
||||
* Note: This returns string | string[] since some headers can have multiple values.
|
||||
* For headers that must always be a single string (like Content-Type), use the
|
||||
* specialized _getExistingOrDefaultContentTypeHeader method instead.
|
||||
*/
|
||||
private _getExistingOrDefaultHeader(
|
||||
additionalHeaders: http.OutgoingHttpHeaders,
|
||||
header: string,
|
||||
_default: string
|
||||
): string | number | string[] {
|
||||
): string | string[] {
|
||||
let clientHeader: string | string[] | undefined
|
||||
if (this.requestOptions && this.requestOptions.headers) {
|
||||
const headerValue = lowercaseKeys(this.requestOptions.headers)[header]
|
||||
if (headerValue) {
|
||||
clientHeader =
|
||||
typeof headerValue === 'number' ? headerValue.toString() : headerValue
|
||||
}
|
||||
}
|
||||
|
||||
const additionalValue = additionalHeaders[header]
|
||||
|
||||
if (additionalValue !== undefined) {
|
||||
return typeof additionalValue === 'number'
|
||||
? additionalValue.toString()
|
||||
: additionalValue
|
||||
}
|
||||
|
||||
if (clientHeader !== undefined) {
|
||||
return clientHeader
|
||||
}
|
||||
|
||||
return _default
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialized version of _getExistingOrDefaultHeader for Content-Type header.
|
||||
* Always returns a single string (not an array) since Content-Type should be a single value.
|
||||
* Converts arrays to comma-separated strings and numbers to strings to ensure type safety.
|
||||
* This was split from _getExistingOrDefaultHeader to provide stricter typing for callers
|
||||
* that assign the result to places expecting a string (e.g., additionalHeaders[Headers.ContentType]).
|
||||
*/
|
||||
private _getExistingOrDefaultContentTypeHeader(
|
||||
additionalHeaders: http.OutgoingHttpHeaders,
|
||||
_default: string
|
||||
): string {
|
||||
let clientHeader: string | undefined
|
||||
if (this.requestOptions && this.requestOptions.headers) {
|
||||
clientHeader = lowercaseKeys(this.requestOptions.headers)[header]
|
||||
const headerValue = lowercaseKeys(this.requestOptions.headers)[
|
||||
Headers.ContentType
|
||||
]
|
||||
if (headerValue) {
|
||||
if (typeof headerValue === 'number') {
|
||||
clientHeader = String(headerValue)
|
||||
} else if (Array.isArray(headerValue)) {
|
||||
clientHeader = headerValue.join(', ')
|
||||
} else {
|
||||
clientHeader = headerValue
|
||||
}
|
||||
}
|
||||
}
|
||||
return additionalHeaders[header] || clientHeader || _default
|
||||
|
||||
const additionalValue = additionalHeaders[Headers.ContentType]
|
||||
|
||||
// Return the first non-undefined value, converting numbers or arrays to strings if necessary
|
||||
if (additionalValue !== undefined) {
|
||||
if (typeof additionalValue === 'number') {
|
||||
return String(additionalValue)
|
||||
} else if (Array.isArray(additionalValue)) {
|
||||
return additionalValue.join(', ')
|
||||
} else {
|
||||
return additionalValue
|
||||
}
|
||||
}
|
||||
|
||||
if (clientHeader !== undefined) {
|
||||
return clientHeader
|
||||
}
|
||||
|
||||
return _default
|
||||
}
|
||||
|
||||
private _getAgent(parsedUrl: URL): http.Agent {
|
||||
@@ -745,6 +816,18 @@ export class HttpClient {
|
||||
return proxyAgent
|
||||
}
|
||||
|
||||
private _getUserAgentWithOrchestrationId(userAgent?: string): string {
|
||||
const baseUserAgent = userAgent || 'actions/http-client'
|
||||
const orchId = process.env['ACTIONS_ORCHESTRATION_ID']
|
||||
if (orchId) {
|
||||
// Sanitize the orchestration ID to ensure it contains only valid characters
|
||||
// Valid characters: 0-9, a-z, _, -, .
|
||||
const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, '_')
|
||||
return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`
|
||||
}
|
||||
return baseUserAgent
|
||||
}
|
||||
|
||||
private async _performExponentialBackoff(retryNumber: number): Promise<void> {
|
||||
retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber)
|
||||
const ms: number = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as http from 'http'
|
||||
import * as https from 'https'
|
||||
import {HttpClientResponse} from './index'
|
||||
import {HttpClientResponse} from './index.js'
|
||||
|
||||
export interface HttpClient {
|
||||
options(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user