mirror of
https://github.com/actions/cache.git
synced 2025-04-05 02:49:22 +07:00
Compare commits
193 Commits
v3.1.0-bet
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5a3ec84eff | ||
![]() |
7de21022a7 | ||
![]() |
76d40dd347 | ||
![]() |
76dd5eb692 | ||
![]() |
8c80c27c5e | ||
![]() |
45cfd0e7ff | ||
![]() |
edd449b9cf | ||
![]() |
0576707e37 | ||
![]() |
3105dc9754 | ||
![]() |
9450d42d15 | ||
![]() |
7d05b27fb9 | ||
![]() |
507b84c6a6 | ||
![]() |
f248408e15 | ||
![]() |
c30eb5542e | ||
![]() |
5b6ae99d8b | ||
![]() |
eca7c65a55 | ||
![]() |
1b5d75f5cf | ||
![]() |
d4323d4df1 | ||
![]() |
da26677639 | ||
![]() |
7921ae235b | ||
![]() |
3937731706 | ||
![]() |
0c907a75c2 | ||
![]() |
710893c236 | ||
![]() |
9fa7e61ec7 | ||
![]() |
36f1e144e1 | ||
![]() |
53aa38c736 | ||
![]() |
1bd1e32a3b | ||
![]() |
882d7ced4c | ||
![]() |
f2695d7a42 | ||
![]() |
f46ceeb60d | ||
![]() |
e6f5858749 | ||
![]() |
4ae6f21c0d | ||
![]() |
c16df86586 | ||
![]() |
b109c12f3b | ||
![]() |
b7d227d702 | ||
![]() |
faf639248d | ||
![]() |
4bc41c01bd | ||
![]() |
6849a64899 | ||
![]() |
5a1720c49e | ||
![]() |
d9fef48d24 | ||
![]() |
a50e8d027b | ||
![]() |
acc9ae5c14 | ||
![]() |
1ea5f18c31 | ||
![]() |
cc679ff3ba | ||
![]() |
366d43d6f8 | ||
![]() |
02bf31969b | ||
![]() |
6f6220be5a | ||
![]() |
ebdd24ede1 | ||
![]() |
255c8ff306 | ||
![]() |
010f24cd9d | ||
![]() |
d6151ba7db | ||
![]() |
4ca7071576 | ||
![]() |
5d692d65f4 | ||
![]() |
3aef79d3a3 | ||
![]() |
aa55e5f344 | ||
![]() |
772385291f | ||
![]() |
e5dc90df92 | ||
![]() |
8585f2ac5c | ||
![]() |
9803087a86 | ||
![]() |
e7e2547a88 | ||
![]() |
71d826cc33 | ||
![]() |
25942a73ac | ||
![]() |
d73025053b | ||
![]() |
8469c94c6a | ||
![]() |
3624ceb22c | ||
![]() |
2cdf405574 | ||
![]() |
a11fb02296 | ||
![]() |
cf7a75e7b9 | ||
![]() |
c74ca4022c | ||
![]() |
f8a7ab490b | ||
![]() |
45b7be0774 | ||
![]() |
81382a721f | ||
![]() |
c4ee99a3bd | ||
![]() |
57b8e405f0 | ||
![]() |
40c3b67b29 | ||
![]() |
e47d9f9ec8 | ||
![]() |
4a28cbc054 | ||
![]() |
bf9a7572fe | ||
![]() |
0c45773b62 | ||
![]() |
8a55f839aa | ||
![]() |
3884cace14 | ||
![]() |
e29dad3e36 | ||
![]() |
ab5e6d0c87 | ||
![]() |
89c7d86c71 | ||
![]() |
d2c84da363 | ||
![]() |
37e7d4eb16 | ||
![]() |
a18323f504 | ||
![]() |
104f95683b | ||
![]() |
a2ed59d39b | ||
![]() |
dc88ab52d7 | ||
![]() |
1d78355196 | ||
![]() |
c36458f13b | ||
![]() |
13aacd865c | ||
![]() |
53b35c5439 | ||
![]() |
65b8989fab | ||
![]() |
d0be34d544 | ||
![]() |
66cf064d47 | ||
![]() |
1326563738 | ||
![]() |
e12d46a63a | ||
![]() |
1baebfc3ba | ||
![]() |
eb94f1a6bf | ||
![]() |
e71876755e | ||
![]() |
01229828ff | ||
![]() |
3185ecfd61 | ||
![]() |
25618a0a67 | ||
![]() |
a0a285ffd4 | ||
![]() |
b00bedba4a | ||
![]() |
99d573b49d | ||
![]() |
6f0a1fdd90 | ||
![]() |
2001ca4114 | ||
![]() |
0e9aed0d0d | ||
![]() |
3b7dac1789 | ||
![]() |
b1378c8403 | ||
![]() |
704facf57e | ||
![]() |
17e2888746 | ||
![]() |
667d8fdfa2 | ||
![]() |
f7ebb81a3f | ||
![]() |
67b839edb6 | ||
![]() |
57f0e3f198 | ||
![]() |
04f198bf0b | ||
![]() |
bd9b49b6c3 | ||
![]() |
ea0503788c | ||
![]() |
6a1a45d49b | ||
![]() |
9c7b3e90bd | ||
![]() |
8f2671f18e | ||
![]() |
6f1f1e10f3 | ||
![]() |
5cb4bb86c0 | ||
![]() |
84995e0d91 | ||
![]() |
bf96a3f9d8 | ||
![]() |
4b8460cbff | ||
![]() |
57014a2baa | ||
![]() |
cb865c1889 | ||
![]() |
4e7c82221f | ||
![]() |
88522ab9f3 | ||
![]() |
ef11f54eee | ||
![]() |
4b381be638 | ||
![]() |
7893481812 | ||
![]() |
940f3d7cf1 | ||
![]() |
e0d62270e2 | ||
![]() |
77eb7eb198 | ||
![]() |
69d9d449ac | ||
![]() |
8d3a1e02aa | ||
![]() |
b1db4b4897 | ||
![]() |
7d4d6f7ffd | ||
![]() |
8f7fa5d715 | ||
![]() |
95b455a0fb | ||
![]() |
81b7281936 | ||
![]() |
6998d139dd | ||
![]() |
2b8105bdae | ||
![]() |
e08330827d | ||
![]() |
22d3da765b | ||
![]() |
627f0f41f6 | ||
![]() |
8e3048d0f7 | ||
![]() |
1b004e8a69 | ||
![]() |
75b110bc85 | ||
![]() |
2b5a782c64 | ||
![]() |
6c2de3ba98 | ||
![]() |
b63536828e | ||
![]() |
cd2aaa9df8 | ||
![]() |
9b7ef12f3e | ||
![]() |
3c08cab74f | ||
![]() |
8315026919 | ||
![]() |
4791017169 | ||
![]() |
22cbf49050 | ||
![]() |
5868318cdc | ||
![]() |
804b679d21 | ||
![]() |
c9869a589f | ||
![]() |
003f5452bf | ||
![]() |
efacb0248b | ||
![]() |
76ee6bdfdc | ||
![]() |
9183691e97 | ||
![]() |
094a24099d | ||
![]() |
87396fe6b4 | ||
![]() |
e630eda107 | ||
![]() |
58c146cc91 | ||
![]() |
6fd2d4538c | ||
![]() |
1f414295fe | ||
![]() |
365406cb70 | ||
![]() |
d6217569d5 | ||
![]() |
84e54000da | ||
![]() |
d0e7eb01c9 | ||
![]() |
4723a57e26 | ||
![]() |
d1507cccba | ||
![]() |
3337563725 | ||
![]() |
d70353d8a4 | ||
![]() |
60c7666709 | ||
![]() |
b053f2b699 | ||
![]() |
501277cfd7 | ||
![]() |
c1a5de879e | ||
![]() |
9b0be58822 | ||
![]() |
c17f4bf466 | ||
![]() |
35f35f44e8 | ||
![]() |
ca1c035094 |
14
.devcontainer/devcontainer.json
Normal file
14
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Node.js & TypeScript",
|
||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:16-bullseye",
|
||||
// Features to add to the dev container. More info: https://containers.dev/implementors/features.
|
||||
// "features": {},
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "npm install"
|
||||
// Configure tool-specific properties.
|
||||
// "customizations": {},
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
22
.github/dependabot.yml
vendored
Normal file
22
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
# 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: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
groups:
|
||||
minor-actions-dependencies:
|
||||
update-types: [minor, patch]
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
allow:
|
||||
- dependency-type: direct
|
||||
- dependency-type: production
|
41
.github/workflows/check-dist.yml
vendored
41
.github/workflows/check-dist.yml
vendored
@ -1,9 +1,3 @@
|
||||
# `dist/index.js` is a special file in Actions.
|
||||
# When you reference an action with `uses:` in a workflow,
|
||||
# `index.js` is the code that will run.
|
||||
# For our project, we generate this file through a build process
|
||||
# from other source files.
|
||||
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
|
||||
name: Check dist/
|
||||
|
||||
on:
|
||||
@ -18,33 +12,8 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-dist:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
cache: npm
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Rebuild the dist/ directory
|
||||
run: npm run build
|
||||
|
||||
- name: Compare the expected and actual dist/ directories
|
||||
run: |
|
||||
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
|
||||
echo "Detected uncommitted changes after build. See status below:"
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
id: diff
|
||||
|
||||
# If index.js was different than expected, upload the expected version as an artifact
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
|
||||
with:
|
||||
name: dist
|
||||
path: dist/
|
||||
call-check-dist:
|
||||
name: Check dist/
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
with:
|
||||
node-version: "20.x"
|
||||
|
2
.github/workflows/close-inactive-issues.yml
vendored
2
.github/workflows/close-inactive-issues.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
days-before-issue-stale: 200
|
||||
days-before-issue-close: 5
|
||||
|
42
.github/workflows/codeql.yml
vendored
42
.github/workflows/codeql.yml
vendored
@ -8,45 +8,39 @@ on:
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
# CodeQL runs on ubuntu-latest and windows-latest
|
||||
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# We must fetch at least the immediate parents so that if this is
|
||||
# a pull request then we can checkout the head.
|
||||
fetch-depth: 2
|
||||
|
||||
# If this run was triggered by a pull request event, then checkout
|
||||
# the head of the pull request instead of the merge commit.
|
||||
- run: git checkout HEAD^2
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v3
|
||||
# Override language selection by uncommenting this and choosing your languages
|
||||
# with:
|
||||
# languages: go, javascript, csharp, python, cpp, java
|
||||
# languages: go, javascript, csharp, python, cpp, java, ruby
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below).
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following
|
||||
# three lines and modify them (or add more) to build your code if your
|
||||
# project uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
17
.github/workflows/licensed.yml
vendored
17
.github/workflows/licensed.yml
vendored
@ -7,18 +7,9 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check licenses
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: npm ci
|
||||
- name: Install licensed
|
||||
run: |
|
||||
cd $RUNNER_TEMP
|
||||
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
|
||||
sudo tar -xzf licensed.tar.gz
|
||||
sudo mv licensed /usr/local/bin/licensed
|
||||
- run: licensed status
|
||||
call-licensed:
|
||||
name: Licensed
|
||||
uses: actions/reusable-workflows/.github/workflows/licensed.yml@main
|
||||
|
20
.github/workflows/publish-immutable-actions.yml
vendored
Normal file
20
.github/workflows/publish-immutable-actions.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
name: 'Publish Immutable Action Version'
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish
|
||||
id: publish
|
||||
uses: actions/publish-immutable-action@0.0.3
|
28
.github/workflows/release-new-action-version.yml
vendored
Normal file
28
.github/workflows/release-new-action-version.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: Release new action version
|
||||
on:
|
||||
release:
|
||||
types: [released]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
TAG_NAME:
|
||||
description: 'Tag name that the major tag will point to'
|
||||
required: true
|
||||
|
||||
env:
|
||||
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
update_tag:
|
||||
name: Update the major tag to include the ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }} changes
|
||||
environment:
|
||||
name: releaseNewActionVersion
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
id: update-major-tag
|
||||
uses: actions/publish-action@v0.3.0
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
16
.github/workflows/workflow.yml
vendored
16
.github/workflows/workflow.yml
vendored
@ -20,11 +20,11 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Node.js 16.x
|
||||
uses: actions/setup-node@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Node.js 20.x
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16.x
|
||||
node-version: 20.x
|
||||
cache: npm
|
||||
- run: npm ci
|
||||
- name: Prettier Format Check
|
||||
@ -43,7 +43,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Generate files in working directory
|
||||
shell: bash
|
||||
run: __tests__/create-cache-files.sh ${{ runner.os }} test-cache
|
||||
@ -66,7 +66,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore cache
|
||||
uses: ./
|
||||
with:
|
||||
@ -96,7 +96,7 @@ jobs:
|
||||
https_proxy: http://squid-proxy:3128
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Generate files
|
||||
run: __tests__/create-cache-files.sh proxy test-cache
|
||||
- name: Save cache
|
||||
@ -119,7 +119,7 @@ jobs:
|
||||
https_proxy: http://squid-proxy:3128
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Restore cache
|
||||
uses: ./
|
||||
with:
|
||||
|
@ -13,4 +13,10 @@ allowed:
|
||||
|
||||
reviewed:
|
||||
npm:
|
||||
- sax
|
||||
- sax
|
||||
- "@protobuf-ts/plugin-framework" # Apache-2.0
|
||||
- "@protobuf-ts/runtime" # Apache-2.0
|
||||
- fs.realpath # ISC
|
||||
- glob # ISC
|
||||
- prettier # MIT
|
||||
- lodash # MIT
|
9330
.licenses/NOTICE
generated
Normal file
9330
.licenses/NOTICE
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
.licenses/npm/@actions/cache.dep.yml
generated
20
.licenses/npm/@actions/cache.dep.yml
generated
@ -1,20 +1,20 @@
|
||||
---
|
||||
name: "@actions/cache"
|
||||
version: 3.0.5
|
||||
version: 4.0.3
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
summary: Actions cache lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/cache
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
- sources: LICENSE.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright 2019 GitHub
|
||||
Copyright 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
||||
|
2
.licenses/npm/@actions/core.dep.yml
generated
2
.licenses/npm/@actions/core.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/core"
|
||||
version: 1.10.0
|
||||
version: 1.11.1
|
||||
type: npm
|
||||
summary: Actions core lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/core
|
||||
|
2
.licenses/npm/@actions/http-client.dep.yml
generated
2
.licenses/npm/@actions/http-client.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@actions/http-client"
|
||||
version: 2.0.1
|
||||
version: 2.1.1
|
||||
type: npm
|
||||
summary: Actions Http Client
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/http-client
|
||||
|
6
.licenses/npm/@actions/io.dep.yml
generated
6
.licenses/npm/@actions/io.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@actions/io"
|
||||
version: 1.1.2
|
||||
version: 1.1.3
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
summary: Actions io lib
|
||||
homepage: https://github.com/actions/toolkit/tree/main/packages/io
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
|
4
.licenses/npm/@azure/abort-controller.dep.yml
generated
4
.licenses/npm/@azure/abort-controller.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/abort-controller"
|
||||
version: 1.0.4
|
||||
version: 1.1.0
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Aborter
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/core/abort-controller/README.md
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/abort-controller/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
@ -1,32 +0,0 @@
|
||||
---
|
||||
name: "@azure/core-asynciterator-polyfill"
|
||||
version: 1.0.2
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
MIT License
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
notices: []
|
2
.licenses/npm/@azure/core-http.dep.yml
generated
2
.licenses/npm/@azure/core-http.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/core-http"
|
||||
version: 2.2.4
|
||||
version: 3.0.4
|
||||
type: npm
|
||||
summary: Isomorphic client Runtime for Typescript/node.js/browser javascript client
|
||||
libraries generated using AutoRest
|
||||
|
7
.licenses/npm/@azure/core-lro.dep.yml
generated
7
.licenses/npm/@azure/core-lro.dep.yml
generated
@ -1,9 +1,10 @@
|
||||
---
|
||||
name: "@azure/core-lro"
|
||||
version: 2.2.4
|
||||
version: 2.5.1
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
summary: Isomorphic client library for supporting long-running operations in node.js
|
||||
and browser.
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-lro/README.md
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
2
.licenses/npm/@azure/core-paging.dep.yml
generated
2
.licenses/npm/@azure/core-paging.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/core-paging"
|
||||
version: 1.2.1
|
||||
version: 1.5.0
|
||||
type: npm
|
||||
summary: Core types for paging async iterable iterators
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-paging/README.md
|
||||
|
@ -1,16 +1,16 @@
|
||||
---
|
||||
name: uuid
|
||||
version: 3.4.0
|
||||
name: "@azure/core-util"
|
||||
version: 1.2.0
|
||||
type: npm
|
||||
summary: RFC4122 (v1, v4, and v5) UUIDs
|
||||
homepage: https://github.com/uuidjs/uuid#readme
|
||||
summary: Core library for shared utility methods
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/core/core-util/
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2010-2016 Robert Kieffer and other contributors
|
||||
Copyright (c) 2020 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@ -29,11 +29,4 @@ licenses:
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
notices:
|
||||
- sources: AUTHORS
|
||||
text: |-
|
||||
Robert Kieffer <robert@broofa.com>
|
||||
Christoph Tavan <dev@tavan.de>
|
||||
AJ ONeal <coolaj86@gmail.com>
|
||||
Vincent Voyer <vincent@zeroload.net>
|
||||
Roman Shtylman <shtylman@gmail.com>
|
||||
notices: []
|
2
.licenses/npm/@azure/logger.dep.yml
generated
2
.licenses/npm/@azure/logger.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@azure/logger"
|
||||
version: 1.0.3
|
||||
version: 1.0.4
|
||||
type: npm
|
||||
summary: Microsoft Azure SDK for JavaScript - Logger
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger/README.md
|
||||
|
7
.licenses/npm/@azure/ms-rest-js.dep.yml
generated
7
.licenses/npm/@azure/ms-rest-js.dep.yml
generated
@ -1,9 +1,10 @@
|
||||
---
|
||||
name: "@azure/ms-rest-js"
|
||||
version: 2.6.1
|
||||
version: 2.7.0
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
summary: Isomorphic client Runtime for Typescript/node.js/browser javascript client
|
||||
libraries generated using AutoRest
|
||||
homepage: https://github.com/Azure/ms-rest-js
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
6
.licenses/npm/@azure/storage-blob.dep.yml
generated
6
.licenses/npm/@azure/storage-blob.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@azure/storage-blob"
|
||||
version: 12.9.0
|
||||
version: 12.13.0
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
summary: Microsoft Azure Storage SDK for JavaScript - Blob
|
||||
homepage: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-blob/
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
12
.licenses/npm/@opentelemetry/api.dep.yml
generated
12
.licenses/npm/@opentelemetry/api.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@opentelemetry/api"
|
||||
version: 1.0.4
|
||||
version: 1.4.0
|
||||
type: npm
|
||||
summary: Public API for OpenTelemetry
|
||||
homepage: https://github.com/open-telemetry/opentelemetry-js-api#readme
|
||||
homepage: https://github.com/open-telemetry/opentelemetry-js/tree/main/api
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
@ -216,10 +216,8 @@ licenses:
|
||||
[opentelemetry-js]: https://github.com/open-telemetry/opentelemetry-js
|
||||
|
||||
[discussions-url]: https://github.com/open-telemetry/opentelemetry-js/discussions
|
||||
[license-url]: https://github.com/open-telemetry/opentelemetry-js-api/blob/main/LICENSE
|
||||
[license-url]: https://github.com/open-telemetry/opentelemetry-js/blob/main/api/LICENSE
|
||||
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
|
||||
[npm-url]: https://www.npmjs.com/package/@opentelemetry/api
|
||||
[npm-img]: https://badge.fury.io/js/%40opentelemetry%2Fapi.svg
|
||||
[docs-tracing]: https://github.com/open-telemetry/opentelemetry-js-api/blob/main/docs/tracing.md
|
||||
[docs-sdk-registration]: https://github.com/open-telemetry/opentelemetry-js-api/blob/main/docs/sdk-registration.md
|
||||
[docs-tracing]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/tracing.md
|
||||
[docs-sdk-registration]: https://github.com/open-telemetry/opentelemetry-js/blob/main/doc/sdk-registration.md
|
||||
notices: []
|
||||
|
185
.licenses/npm/@protobuf-ts/plugin-framework.dep.yml
generated
Normal file
185
.licenses/npm/@protobuf-ts/plugin-framework.dep.yml
generated
Normal file
@ -0,0 +1,185 @@
|
||||
---
|
||||
name: "@protobuf-ts/plugin-framework"
|
||||
version: 2.9.4
|
||||
type: npm
|
||||
summary: framework to create protoc plugins
|
||||
homepage: https://github.com/timostamm/protobuf-ts
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
notices: []
|
186
.licenses/npm/@protobuf-ts/plugin.dep.yml
generated
Normal file
186
.licenses/npm/@protobuf-ts/plugin.dep.yml
generated
Normal file
@ -0,0 +1,186 @@
|
||||
---
|
||||
name: "@protobuf-ts/plugin"
|
||||
version: 2.9.4
|
||||
type: npm
|
||||
summary: The protocol buffer compiler plugin "protobuf-ts" generates TypeScript, gRPC-web,
|
||||
Twirp, and more.
|
||||
homepage: https://github.com/timostamm/protobuf-ts
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
notices: []
|
185
.licenses/npm/@protobuf-ts/protoc.dep.yml
generated
Normal file
185
.licenses/npm/@protobuf-ts/protoc.dep.yml
generated
Normal file
@ -0,0 +1,185 @@
|
||||
---
|
||||
name: "@protobuf-ts/protoc"
|
||||
version: 2.9.4
|
||||
type: npm
|
||||
summary: Installs the protocol buffer compiler "protoc" for you.
|
||||
homepage: https://github.com/timostamm/protobuf-ts
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
notices: []
|
185
.licenses/npm/@protobuf-ts/runtime-rpc.dep.yml
generated
Normal file
185
.licenses/npm/@protobuf-ts/runtime-rpc.dep.yml
generated
Normal file
@ -0,0 +1,185 @@
|
||||
---
|
||||
name: "@protobuf-ts/runtime-rpc"
|
||||
version: 2.9.4
|
||||
type: npm
|
||||
summary: Runtime library for RPC clients generated by the protoc plugin "protobuf-ts"
|
||||
homepage: https://github.com/timostamm/protobuf-ts
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
notices: []
|
185
.licenses/npm/@protobuf-ts/runtime.dep.yml
generated
Normal file
185
.licenses/npm/@protobuf-ts/runtime.dep.yml
generated
Normal file
@ -0,0 +1,185 @@
|
||||
---
|
||||
name: "@protobuf-ts/runtime"
|
||||
version: 2.9.4
|
||||
type: npm
|
||||
summary: Runtime library for code generated by the protoc plugin "protobuf-ts"
|
||||
homepage: https://github.com/timostamm/protobuf-ts
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |2
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
notices: []
|
6
.licenses/npm/@types/node-fetch.dep.yml
generated
6
.licenses/npm/@types/node-fetch.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: "@types/node-fetch"
|
||||
version: 2.6.1
|
||||
version: 2.6.2
|
||||
type: npm
|
||||
summary:
|
||||
homepage:
|
||||
summary: TypeScript definitions for node-fetch
|
||||
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node-fetch
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
2
.licenses/npm/@types/node.dep.yml
generated
2
.licenses/npm/@types/node.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "@types/node"
|
||||
version: 16.11.33
|
||||
version: 16.18.3
|
||||
type: npm
|
||||
summary: TypeScript definitions for Node.js
|
||||
homepage: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node
|
||||
|
42
.licenses/npm/camel-case.dep.yml
generated
Normal file
42
.licenses/npm/camel-case.dep.yml
generated
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
name: camel-case
|
||||
version: 4.1.2
|
||||
type: npm
|
||||
summary: Transform into a string with the separator denoted by the next word capitalized
|
||||
homepage: https://github.com/blakeembrey/change-case/tree/master/packages/camel-case#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
MIT
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/camel-case.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/camel-case
|
||||
[downloads-image]: https://img.shields.io/npm/dm/camel-case.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/camel-case
|
||||
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/camel-case.svg
|
||||
[bundlephobia-url]: https://bundlephobia.com/result?p=camel-case
|
||||
notices: []
|
33
.licenses/npm/commander.dep.yml
generated
Normal file
33
.licenses/npm/commander.dep.yml
generated
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
name: commander
|
||||
version: 6.2.1
|
||||
type: npm
|
||||
summary: the complete solution for node.js command-line programs
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
'Software'), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
@ -1,15 +1,15 @@
|
||||
---
|
||||
name: punycode
|
||||
version: 2.1.1
|
||||
name: dot-object
|
||||
version: 2.1.5
|
||||
type: npm
|
||||
summary: A robust Punycode converter that fully complies to RFC 3492 and RFC 5891,
|
||||
and works on nearly all JavaScript platforms.
|
||||
homepage: https://mths.be/punycode
|
||||
summary: dot-object makes it possible to transform and read (JSON) objects using dot
|
||||
notation.
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE-MIT.txt
|
||||
- sources: MIT-LICENSE
|
||||
text: |
|
||||
Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
Copyright (c) 2013 Rob Halff
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
@ -29,6 +29,4 @@ licenses:
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: Punycode.js is available under the [MIT](https://mths.be/mit) license.
|
||||
notices: []
|
55
.licenses/npm/fs.realpath.dep.yml
generated
Normal file
55
.licenses/npm/fs.realpath.dep.yml
generated
Normal file
@ -0,0 +1,55 @@
|
||||
---
|
||||
name: fs.realpath
|
||||
version: 1.0.0
|
||||
type: npm
|
||||
summary: Use node's fs.realpath, but fall back to the JS implementation if the native
|
||||
one fails
|
||||
homepage:
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
----
|
||||
|
||||
This library bundles a version of the `fs.realpath` and `fs.realpathSync`
|
||||
methods from Node.js v0.10 under the terms of the Node.js MIT license.
|
||||
|
||||
Node's license follows, also included at the header of `old.js` which contains
|
||||
the licensed code:
|
||||
|
||||
Copyright Joyent, Inc. and other Node contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
notices: []
|
32
.licenses/npm/glob.dep.yml
generated
Normal file
32
.licenses/npm/glob.dep.yml
generated
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
name: glob
|
||||
version: 7.2.0
|
||||
type: npm
|
||||
summary: a little globber
|
||||
homepage:
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
## Glob Logo
|
||||
|
||||
Glob's logo created by Tanya Brassie <http://tanyabrassie.com/>, licensed
|
||||
under a Creative Commons Attribution-ShareAlike 4.0 International License
|
||||
https://creativecommons.org/licenses/by-sa/4.0/
|
||||
notices: []
|
26
.licenses/npm/inflight.dep.yml
generated
Normal file
26
.licenses/npm/inflight.dep.yml
generated
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
name: inflight
|
||||
version: 1.0.6
|
||||
type: npm
|
||||
summary: Add callbacks to requests in flight to avoid async duplication
|
||||
homepage: https://github.com/isaacs/inflight
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
28
.licenses/npm/inherits.dep.yml
generated
Normal file
28
.licenses/npm/inherits.dep.yml
generated
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
name: inherits
|
||||
version: 2.0.4
|
||||
type: npm
|
||||
summary: Browser-friendly inheritance fully compatible with standard node.js inherits()
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |+
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
notices: []
|
||||
...
|
58
.licenses/npm/lodash.dep.yml
generated
Normal file
58
.licenses/npm/lodash.dep.yml
generated
Normal file
@ -0,0 +1,58 @@
|
||||
---
|
||||
name: lodash
|
||||
version: 4.17.21
|
||||
type: npm
|
||||
summary: Lodash modular utilities.
|
||||
homepage: https://lodash.com/
|
||||
license: other
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
|
||||
Based on Underscore.js, copyright Jeremy Ashkenas,
|
||||
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals. For exact contribution history, see the revision history
|
||||
available at https://github.com/lodash/lodash
|
||||
|
||||
The following license applies to all parts of this software except as
|
||||
documented below:
|
||||
|
||||
====
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
Copyright and related rights for sample code are waived via CC0. Sample
|
||||
code is defined as all source code displayed within the prose of the
|
||||
documentation.
|
||||
|
||||
CC0: http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
====
|
||||
|
||||
Files located in the node_modules and vendor directories are externally
|
||||
maintained libraries used by this software which have their own
|
||||
licenses; we recommend you read them, as their terms may differ from the
|
||||
terms above.
|
||||
notices: []
|
42
.licenses/npm/lower-case.dep.yml
generated
Normal file
42
.licenses/npm/lower-case.dep.yml
generated
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
name: lower-case
|
||||
version: 2.0.2
|
||||
type: npm
|
||||
summary: Transforms the string to lower case
|
||||
homepage: https://github.com/blakeembrey/change-case/tree/master/packages/lower-case#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
MIT
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/lower-case.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/lower-case
|
||||
[downloads-image]: https://img.shields.io/npm/dm/lower-case.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/lower-case
|
||||
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/lower-case.svg
|
||||
[bundlephobia-url]: https://bundlephobia.com/result?p=lower-case
|
||||
notices: []
|
4
.licenses/npm/minimatch.dep.yml
generated
4
.licenses/npm/minimatch.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: minimatch
|
||||
version: 3.0.4
|
||||
version: 3.1.2
|
||||
type: npm
|
||||
summary: a glob matcher in javascript
|
||||
homepage: https://github.com/isaacs/minimatch#readme
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
42
.licenses/npm/no-case.dep.yml
generated
Normal file
42
.licenses/npm/no-case.dep.yml
generated
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
name: no-case
|
||||
version: 3.0.4
|
||||
type: npm
|
||||
summary: Transform into a lower cased string with spaces between words
|
||||
homepage: https://github.com/blakeembrey/change-case/tree/master/packages/no-case#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
MIT
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/no-case.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/no-case
|
||||
[downloads-image]: https://img.shields.io/npm/dm/no-case.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/no-case
|
||||
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/no-case.svg
|
||||
[bundlephobia-url]: https://bundlephobia.com/result?p=no-case
|
||||
notices: []
|
26
.licenses/npm/once.dep.yml
generated
Normal file
26
.licenses/npm/once.dep.yml
generated
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
name: once
|
||||
version: 1.4.0
|
||||
type: npm
|
||||
summary: Run a function exactly one time
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
42
.licenses/npm/pascal-case.dep.yml
generated
Normal file
42
.licenses/npm/pascal-case.dep.yml
generated
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
name: pascal-case
|
||||
version: 3.1.2
|
||||
type: npm
|
||||
summary: Transform into a string of capitalized words without separators
|
||||
homepage: https://github.com/blakeembrey/change-case/tree/master/packages/pascal-case#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
MIT
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/pascal-case.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/pascal-case
|
||||
[downloads-image]: https://img.shields.io/npm/dm/pascal-case.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/pascal-case
|
||||
[bundlephobia-image]: https://img.shields.io/bundlephobia/minzip/pascal-case.svg
|
||||
[bundlephobia-url]: https://bundlephobia.com/result?p=pascal-case
|
||||
notices: []
|
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: ip-regex
|
||||
version: 2.1.0
|
||||
name: path-is-absolute
|
||||
version: 1.0.1
|
||||
type: npm
|
||||
summary: Regular expression for matching IP addresses (IPv4 & IPv6)
|
||||
homepage: https://github.com/sindresorhus/ip-regex#readme
|
||||
summary: Node.js 0.12 path.isAbsolute() ponyfill
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: license
|
46
.licenses/npm/path-to-regexp.dep.yml
generated
Normal file
46
.licenses/npm/path-to-regexp.dep.yml
generated
Normal file
@ -0,0 +1,46 @@
|
||||
---
|
||||
name: path-to-regexp
|
||||
version: 6.3.0
|
||||
type: npm
|
||||
summary: Express style path to RegExp utility
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
- sources: Readme.md
|
||||
text: |-
|
||||
MIT
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/path-to-regexp
|
||||
[npm-url]: https://npmjs.org/package/path-to-regexp
|
||||
[downloads-image]: https://img.shields.io/npm/dm/path-to-regexp
|
||||
[downloads-url]: https://npmjs.org/package/path-to-regexp
|
||||
[build-image]: https://img.shields.io/github/actions/workflow/status/pillarjs/path-to-regexp/ci.yml?branch=master
|
||||
[build-url]: https://github.com/pillarjs/path-to-regexp/actions/workflows/ci.yml?query=branch%3Amaster
|
||||
[coverage-image]: https://img.shields.io/codecov/c/gh/pillarjs/path-to-regexp
|
||||
[coverage-url]: https://codecov.io/gh/pillarjs/path-to-regexp
|
||||
[license-image]: http://img.shields.io/npm/l/path-to-regexp.svg?style=flat
|
||||
[license-url]: LICENSE.md
|
||||
notices: []
|
3573
.licenses/npm/prettier.dep.yml
generated
Normal file
3573
.licenses/npm/prettier.dep.yml
generated
Normal file
File diff suppressed because it is too large
Load Diff
43
.licenses/npm/psl.dep.yml
generated
43
.licenses/npm/psl.dep.yml
generated
@ -1,43 +0,0 @@
|
||||
---
|
||||
name: psl
|
||||
version: 1.8.0
|
||||
type: npm
|
||||
summary: Domain name parser based on the Public Suffix List
|
||||
homepage: https://github.com/lupomontero/psl#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Lupo Montero lupomontero@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: |-
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Lupo Montero <lupomontero@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
notices: []
|
4
.licenses/npm/semver.dep.yml
generated
4
.licenses/npm/semver.dep.yml
generated
@ -1,9 +1,9 @@
|
||||
---
|
||||
name: semver
|
||||
version: 6.3.0
|
||||
version: 6.3.1
|
||||
type: npm
|
||||
summary: The semantic version parser used by npm.
|
||||
homepage: https://github.com/npm/node-semver#readme
|
||||
homepage:
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
|
23
.licenses/npm/tough-cookie-3.0.1.dep.yml
generated
23
.licenses/npm/tough-cookie-3.0.1.dep.yml
generated
@ -1,23 +0,0 @@
|
||||
---
|
||||
name: tough-cookie
|
||||
version: 3.0.1
|
||||
type: npm
|
||||
summary: RFC6265 Cookies and Cookie Jar for node.js
|
||||
homepage: https://github.com/salesforce/tough-cookie
|
||||
license: bsd-3-clause
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Copyright (c) 2015, Salesforce.com, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
notices: []
|
23
.licenses/npm/tough-cookie-4.0.0.dep.yml
generated
23
.licenses/npm/tough-cookie-4.0.0.dep.yml
generated
@ -1,23 +0,0 @@
|
||||
---
|
||||
name: tough-cookie
|
||||
version: 4.0.0
|
||||
type: npm
|
||||
summary: RFC6265 Cookies and Cookie Jar for node.js
|
||||
homepage: https://github.com/salesforce/tough-cookie
|
||||
license: bsd-3-clause
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Copyright (c) 2015, Salesforce.com, Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
notices: []
|
216
.licenses/npm/ts-poet.dep.yml
generated
Normal file
216
.licenses/npm/ts-poet.dep.yml
generated
Normal file
@ -0,0 +1,216 @@
|
||||
---
|
||||
name: ts-poet
|
||||
version: 4.15.0
|
||||
type: npm
|
||||
summary: code generation DSL for TypeScript
|
||||
homepage:
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: |2+
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
notices: []
|
||||
...
|
23
.licenses/npm/tslib-2.5.0.dep.yml
generated
Normal file
23
.licenses/npm/tslib-2.5.0.dep.yml
generated
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
name: tslib
|
||||
version: 2.5.0
|
||||
type: npm
|
||||
summary: Runtime library for TypeScript helper functions
|
||||
homepage: https://www.typescriptlang.org/
|
||||
license: 0bsd
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: |-
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
23
.licenses/npm/tslib-2.8.1.dep.yml
generated
Normal file
23
.licenses/npm/tslib-2.8.1.dep.yml
generated
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
name: tslib
|
||||
version: 2.8.1
|
||||
type: npm
|
||||
summary: Runtime library for TypeScript helper functions
|
||||
homepage: https://www.typescriptlang.org/
|
||||
license: 0bsd
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: |-
|
||||
Copyright (c) Microsoft Corporation.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
11
.licenses/npm/twirp-ts.dep.yml
generated
Normal file
11
.licenses/npm/twirp-ts.dep.yml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
name: twirp-ts
|
||||
version: 2.5.0
|
||||
type: npm
|
||||
summary: Typescript implementation of the Twirp protocol
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: README.md
|
||||
text: MIT <3
|
||||
notices: []
|
239
.licenses/npm/typescript.dep.yml
generated
Normal file
239
.licenses/npm/typescript.dep.yml
generated
Normal file
@ -0,0 +1,239 @@
|
||||
---
|
||||
name: typescript
|
||||
version: 3.9.10
|
||||
type: npm
|
||||
summary: TypeScript is a language for application scale JavaScript development
|
||||
homepage: https://www.typescriptlang.org/
|
||||
license: apache-2.0
|
||||
licenses:
|
||||
- sources: LICENSE.txt
|
||||
text: "Apache License\n\nVersion 2.0, January 2004\n\nhttp://www.apache.org/licenses/
|
||||
\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\"
|
||||
shall mean the terms and conditions for use, reproduction, and distribution as
|
||||
defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the
|
||||
copyright owner or entity authorized by the copyright owner that is granting the
|
||||
License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common control with
|
||||
that entity. For the purposes of this definition, \"control\" means (i) the power,
|
||||
direct or indirect, to cause the direction or management of such entity, whether
|
||||
by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of
|
||||
the outstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\"
|
||||
(or \"Your\") shall mean an individual or Legal Entity exercising permissions
|
||||
granted by this License.\n\n\"Source\" form shall mean the preferred form for
|
||||
making modifications, including but not limited to software source code, documentation
|
||||
source, and configuration files.\n\n\"Object\" form shall mean any form resulting
|
||||
from mechanical transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation, and conversions
|
||||
to other media types.\n\n\"Work\" shall mean the work of authorship, whether in
|
||||
Source or Object form, made available under the License, as indicated by a copyright
|
||||
notice that is included in or attached to the work (an example is provided in
|
||||
the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source
|
||||
or Object form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications represent,
|
||||
as a whole, an original work of authorship. For the purposes of this License,
|
||||
Derivative Works shall not include works that remain separable from, or merely
|
||||
link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\"
|
||||
shall mean any work of authorship, including the original version of the Work
|
||||
and any modifications or additions to that Work or Derivative Works thereof, that
|
||||
is intentionally submitted to Licensor for inclusion in the Work by the copyright
|
||||
owner or by an individual or Legal Entity authorized to submit on behalf of the
|
||||
copyright owner. For the purposes of this definition, \"submitted\" means any
|
||||
form of electronic, verbal, or written communication sent to the Licensor or its
|
||||
representatives, including but not limited to communication on electronic mailing
|
||||
lists, source code control systems, and issue tracking systems that are managed
|
||||
by, or on behalf of, the Licensor for the purpose of discussing and improving
|
||||
the Work, but excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as \"Not a Contribution.\"\n\n\"Contributor\"
|
||||
shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution
|
||||
has been received by Licensor and subsequently incorporated within the Work.\n\n2.
|
||||
Grant of Copyright License. Subject to the terms and conditions of this License,
|
||||
each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
|
||||
royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works
|
||||
of, publicly display, publicly perform, sublicense, and distribute the Work and
|
||||
such Derivative Works in Source or Object form.\n\n3. Grant of Patent License.
|
||||
Subject to the terms and conditions of this License, each Contributor hereby grants
|
||||
to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made, use, offer
|
||||
to sell, sell, import, and otherwise transfer the Work, where such license applies
|
||||
only to those patent claims licensable by such Contributor that are necessarily
|
||||
infringed by their Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You institute patent
|
||||
litigation against any entity (including a cross-claim or counterclaim in a lawsuit)
|
||||
alleging that the Work or a Contribution incorporated within the Work constitutes
|
||||
direct or contributory patent infringement, then any patent licenses granted to
|
||||
You under this License for that Work shall terminate as of the date such litigation
|
||||
is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without modifications,
|
||||
and in Source or Object form, provided that You meet the following conditions:\n\nYou
|
||||
must give any other recipients of the Work or Derivative Works a copy of this
|
||||
License; and\n\nYou must cause any modified files to carry prominent notices stating
|
||||
that You changed the files; and\n\nYou must retain, in the Source form of any
|
||||
Derivative Works that You distribute, all copyright, patent, trademark, and attribution
|
||||
notices from the Source form of the Work, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works; and\n\nIf the Work includes a \"NOTICE\"
|
||||
text file as part of its distribution, then any Derivative Works that You distribute
|
||||
must include a readable copy of the attribution notices contained within such
|
||||
NOTICE file, excluding those notices that do not pertain to any part of the Derivative
|
||||
Works, in at least one of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or documentation, if provided
|
||||
along with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and do not modify the License.
|
||||
You may add Your own attribution notices within Derivative Works that You distribute,
|
||||
alongside or as an addendum to the NOTICE text from the Work, provided that such
|
||||
additional attribution notices cannot be construed as modifying the License. You
|
||||
may add Your own copyright statement to Your modifications and may provide additional
|
||||
or different license terms and conditions for use, reproduction, or distribution
|
||||
of Your modifications, or for any such Derivative Works as a whole, provided Your
|
||||
use, reproduction, and distribution of the Work otherwise complies with the conditions
|
||||
stated in this License.\n\n5. Submission of Contributions. Unless You explicitly
|
||||
state otherwise, any Contribution intentionally submitted for inclusion in the
|
||||
Work by You to the Licensor shall be under the terms and conditions of this License,
|
||||
without any additional terms or conditions. Notwithstanding the above, nothing
|
||||
herein shall supersede or modify the terms of any separate license agreement you
|
||||
may have executed with Licensor regarding such Contributions.\n\n6. Trademarks.
|
||||
This License does not grant permission to use the trade names, trademarks, service
|
||||
marks, or product names of the Licensor, except as required for reasonable and
|
||||
customary use in describing the origin of the Work and reproducing the content
|
||||
of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable
|
||||
law or agreed to in writing, Licensor provides the Work (and each Contributor
|
||||
provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
||||
OF ANY KIND, either express or implied, including, without limitation, any warranties
|
||||
or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. You are solely responsible for determining the appropriateness of using
|
||||
or redistributing the Work and assume any risks associated with Your exercise
|
||||
of permissions under this License.\n\n8. Limitation of Liability. In no event
|
||||
and under no legal theory, whether in tort (including negligence), contract, or
|
||||
otherwise, unless required by applicable law (such as deliberate and grossly negligent
|
||||
acts) or agreed to in writing, shall any Contributor be liable to You for damages,
|
||||
including any direct, indirect, special, incidental, or consequential damages
|
||||
of any character arising as a result of this License or out of the use or inability
|
||||
to use the Work (including but not limited to damages for loss of goodwill, work
|
||||
stoppage, computer failure or malfunction, or any and all other commercial damages
|
||||
or losses), even if such Contributor has been advised of the possibility of such
|
||||
damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer, and charge a fee
|
||||
for, acceptance of support, warranty, indemnity, or other liability obligations
|
||||
and/or rights consistent with this License. However, in accepting such obligations,
|
||||
You may act only on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify, defend, and hold
|
||||
each Contributor harmless for any liability incurred by, or claims asserted against,
|
||||
such Contributor by reason of your accepting any such warranty or additional liability.\n\nEND
|
||||
OF TERMS AND CONDITIONS\n"
|
||||
notices:
|
||||
- sources: AUTHORS.md
|
||||
text: "TypeScript is authored by:\r\n\r\n - 0verk1ll\r\n - Abubaker Bashir\r\n -
|
||||
Adam Freidin\r\n - Adam Postma\r\n - Adi Dahiya\r\n - Aditya Daflapurkar\r\n -
|
||||
Adnan Chowdhury\r\n - Adrian Leonhard\r\n - Adrien Gibrat\r\n - Ahmad Farid\r\n
|
||||
- Ajay Poshak\r\n - Alan Agius\r\n - Alan Pierce\r\n - Alessandro Vergani\r\n
|
||||
- Alex Chugaev\r\n - Alex Eagle\r\n - Alex Khomchenko\r\n - Alex Ryan\r\n - Alexander\r\n
|
||||
- Alexander Kuvaev\r\n - Alexander Rusakov\r\n - Alexander Tarasyuk\r\n - Ali
|
||||
Sabzevari\r\n - Aluan Haddad\r\n - amaksimovich2\r\n - Anatoly Ressin\r\n - Anders
|
||||
Hejlsberg\r\n - Anders Kaseorg\r\n - Andre Sutherland\r\n - Andreas Martin\r\n
|
||||
- Andrej Baran\r\n - Andrew\r\n - Andrew Branch\r\n - Andrew Casey\r\n - Andrew
|
||||
Faulkner\r\n - Andrew Ochsner\r\n - Andrew Stegmaier\r\n - Andrew Z Allen\r\n
|
||||
- Andrey Roenko\r\n - Andrii Dieiev\r\n - Andr??s Parditka\r\n - Andy Hanson\r\n
|
||||
- Anil Anar\r\n - Anix\r\n - Anton Khlynovskiy\r\n - Anton Tolmachev\r\n - Anubha
|
||||
Mathur\r\n - AnyhowStep\r\n - Armando Aguirre\r\n - Arnaud Tournier\r\n - Arnav
|
||||
Singh\r\n - Arpad Borsos\r\n - Artem Tyurin\r\n - Arthur Ozga\r\n - Asad Saeeduddin\r\n
|
||||
- Austin Cummings\r\n - Avery Morin\r\n - Aziz Khambati\r\n - Basarat Ali Syed\r\n
|
||||
- @begincalendar\r\n - Ben Duffield\r\n - Ben Lichtman\r\n - Ben Mosher\r\n -
|
||||
Benedikt Meurer\r\n - Benjamin Bock\r\n - Benjamin Lichtman\r\n - Benny Neugebauer\r\n
|
||||
- BigAru\r\n - Bill Ticehurst\r\n - Blaine Bublitz\r\n - Blake Embrey\r\n - @bluelovers\r\n
|
||||
- @bootstraponline\r\n - Bowden Kelly\r\n - Bowden Kenny\r\n - Brad Zacher\r\n
|
||||
- Brandon Banks\r\n - Brandon Bloom\r\n - Brandon Slade\r\n - Brendan Kenny\r\n
|
||||
- Brett Mayen\r\n - Brian Terlson\r\n - Bryan Forbes\r\n - Caitlin Potter\r\n
|
||||
- Caleb Sander\r\n - Cameron Taggart\r\n - @cedvdb\r\n - Charles\r\n - Charles
|
||||
Pierce\r\n - Charly POLY\r\n - Chris Bubernak\r\n - Chris Patterson\r\n - christian\r\n
|
||||
- Christophe Vidal\r\n - Chuck Jazdzewski\r\n - Clay Miller\r\n - Colby Russell\r\n
|
||||
- Colin Snover\r\n - Collins Abitekaniza\r\n - Connor Clark\r\n - Cotton Hou\r\n
|
||||
- csigs\r\n - Cyrus Najmabadi\r\n - Dafrok Zhang\r\n - Dahan Gong\r\n - Daiki
|
||||
Nishikawa\r\n - Dan Corder\r\n - Dan Freeman\r\n - Dan Quirk\r\n - Dan Rollo\r\n
|
||||
- Daniel Gooss\r\n - Daniel Imms\r\n - Daniel Krom\r\n - Daniel Kr??l\r\n - Daniel
|
||||
Lehenbauer\r\n - Daniel Rosenwasser\r\n - David Li\r\n - David Sheldrick\r\n -
|
||||
David Sherret\r\n - David Souther\r\n - David Staheli\r\n - Denis Nedelyaev\r\n
|
||||
- Derek P Sifford\r\n - Dhruv Rajvanshi\r\n - Dick van den Brink\r\n - Diogo Franco
|
||||
(Kovensky)\r\n - Dirk B??umer\r\n - Dirk Holtwick\r\n - Dmitrijs Minajevs\r\n
|
||||
- Dom Chen\r\n - Donald Pipowitch\r\n - Doug Ilijev\r\n - dreamran43@gmail.com\r\n
|
||||
- @e-cloud\r\n - Ecole Keine\r\n - Eddie Jaoude\r\n - Edward Thomson\r\n - EECOLOR\r\n
|
||||
- Eli Barzilay\r\n - Elizabeth Dinella\r\n - Ely Alamillo\r\n - Eric Grube\r\n
|
||||
- Eric Tsang\r\n - Erik Edrosa\r\n - Erik McClenney\r\n - Esakki Raj\r\n - Ethan
|
||||
Resnick\r\n - Ethan Rubio\r\n - Eugene Timokhov\r\n - Evan Cahill\r\n - Evan Martin\r\n
|
||||
- Evan Sebastian\r\n - ExE Boss\r\n - Eyas Sharaiha\r\n - Fabian Cook\r\n - @falsandtru\r\n
|
||||
- Filipe Silva\r\n - @flowmemo\r\n - Forbes Lindesay\r\n - Francois Hendriks\r\n
|
||||
- Francois Wouts\r\n - Frank Wallis\r\n - Franti??ek ??iacik\r\n - Frederico Bittencourt\r\n
|
||||
- fullheightcoding\r\n - Gabe Moothart\r\n - Gabriel Isenberg\r\n - Gabriela Araujo
|
||||
Britto\r\n - Gabriela Britto\r\n - gb714us\r\n - Gilad Peleg\r\n - Godfrey Chan\r\n
|
||||
- Gorka Hern??ndez Estomba\r\n - Graeme Wicksted\r\n - Guillaume Salles\r\n -
|
||||
Guy Bedford\r\n - hafiz\r\n - Halasi Tam??s\r\n - Hendrik Liebau\r\n - Henry Mercer\r\n
|
||||
- Herrington Darkholme\r\n - Hoang Pham\r\n - Holger Jeromin\r\n - Homa Wong\r\n
|
||||
- Hye Sung Jung\r\n - Iain Monro\r\n - @IdeaHunter\r\n - Igor Novozhilov\r\n -
|
||||
Igor Oleinikov\r\n - Ika\r\n - iliashkolyar\r\n - IllusionMH\r\n - Ingvar Stepanyan\r\n
|
||||
- Ingvar Stepanyan\r\n - Isiah Meadows\r\n - ispedals\r\n - Ivan Enderlin\r\n
|
||||
- Ivo Gabe de Wolff\r\n - Iwata Hidetaka\r\n - Jack Bates\r\n - Jack Williams\r\n
|
||||
- Jake Boone\r\n - Jakub Korzeniowski\r\n - Jakub M??okosiewicz\r\n - James Henry\r\n
|
||||
- James Keane\r\n - James Whitney\r\n - Jan Melcher\r\n - Jason Freeman\r\n -
|
||||
Jason Jarrett\r\n - Jason Killian\r\n - Jason Ramsay\r\n - JBerger\r\n - Jean
|
||||
Pierre\r\n - Jed Mao\r\n - Jeff Wilcox\r\n - Jeffrey Morlan\r\n - Jesse Schalken\r\n
|
||||
- Jesse Trinity\r\n - Jing Ma\r\n - Jiri Tobisek\r\n - Joe Calzaretta\r\n - Joe
|
||||
Chung\r\n - Joel Day\r\n - Joey Watts\r\n - Johannes Rieken\r\n - John Doe\r\n
|
||||
- John Vilk\r\n - Jonathan Bond-Caron\r\n - Jonathan Park\r\n - Jonathan Toland\r\n
|
||||
- Jordan Harband\r\n - Jordi Oliveras Rovira\r\n - Joscha Feth\r\n - Joseph Wunderlich\r\n
|
||||
- Josh Abernathy\r\n - Josh Goldberg\r\n - Josh Kalderimis\r\n - Josh Soref\r\n
|
||||
- Juan Luis Boya Garc??a\r\n - Julian Williams\r\n - Justin Bay\r\n - Justin Johansson\r\n
|
||||
- jwbay\r\n - K. Prei??er\r\n - Kagami Sascha Rosylight\r\n - Kanchalai Tanglertsampan\r\n
|
||||
- karthikkp\r\n - Kate Mih??likov??\r\n - Keen Yee Liau\r\n - Keith Mashinter\r\n
|
||||
- Ken Howard\r\n - Kenji Imamula\r\n - Kerem Kat\r\n - Kevin Donnelly\r\n - Kevin
|
||||
Gibbons\r\n - Kevin Lang\r\n - Kh???i\r\n - Kitson Kelly\r\n - Klaus Meinhardt\r\n
|
||||
- Kris Zyp\r\n - Kyle Kelley\r\n - K??rlis Ga????is\r\n - laoxiong\r\n - Leon
|
||||
Aves\r\n - Limon Monte\r\n - Lorant Pinter\r\n - Lucien Greathouse\r\n - Luka
|
||||
Hartwig\r\n - Lukas Elmer\r\n - M.Yoshimura\r\n - Maarten Sijm\r\n - Magnus Hiie\r\n
|
||||
- Magnus Kulke\r\n - Manish Bansal\r\n - Manish Giri\r\n - Marcus Noble\r\n -
|
||||
Marin Marinov\r\n - Marius Schulz\r\n - Markus Johnsson\r\n - Markus Wolf\r\n
|
||||
- Martin\r\n - Martin Hiller\r\n - Martin Johns\r\n - Martin Probst\r\n - Martin
|
||||
Vseticka\r\n - Martyn Janes\r\n - Masahiro Wakame\r\n - Mateusz Burzy??ski\r\n
|
||||
- Matt Bierner\r\n - Matt McCutchen\r\n - Matt Mitchell\r\n - Matthew Aynalem\r\n
|
||||
- Matthew Miller\r\n - Mattias Buelens\r\n - Max Heiber\r\n - Maxwell Paul Brickner\r\n
|
||||
- @meyer\r\n - Micah Zoltu\r\n - @micbou\r\n - Michael\r\n - Michael Crane\r\n
|
||||
- Michael Henderson\r\n - Michael Tamm\r\n - Michael Tang\r\n - Michal Przybys\r\n
|
||||
- Mike Busyrev\r\n - Mike Morearty\r\n - Milosz Piechocki\r\n - Mine Starks\r\n
|
||||
- Minh Nguyen\r\n - Mohamed Hegazy\r\n - Mohsen Azimi\r\n - Mukesh Prasad\r\n
|
||||
- Myles Megyesi\r\n - Nathan Day\r\n - Nathan Fenner\r\n - Nathan Shively-Sanders\r\n
|
||||
- Nathan Yee\r\n - ncoley\r\n - Nicholas Yang\r\n - Nicu Micleu??anu\r\n - @nieltg\r\n
|
||||
- Nima Zahedi\r\n - Noah Chen\r\n - Noel Varanda\r\n - Noel Yoo\r\n - Noj Vek\r\n
|
||||
- nrcoley\r\n - Nuno Arruda\r\n - Oleg Mihailik\r\n - Oleksandr Chekhovskyi\r\n
|
||||
- Omer Sheikh\r\n - Orta Therox\r\n - Orta Therox\r\n - Oskar Grunning\r\n - Oskar
|
||||
Segersva??rd\r\n - Oussama Ben Brahim\r\n - Ozair Patel\r\n - Patrick McCartney\r\n
|
||||
- Patrick Zhong\r\n - Paul Koerbitz\r\n - Paul van Brenk\r\n - @pcbro\r\n - Pedro
|
||||
Maltez\r\n - Pete Bacon Darwin\r\n - Peter Burns\r\n - Peter ????ndor\r\n - Philip
|
||||
Pesca\r\n - Philippe Voinov\r\n - Pi Lanningham\r\n - Piero Cangianiello\r\n -
|
||||
Pierre-Antoine Mills\r\n - @piloopin\r\n - Pranav Senthilnathan\r\n - Prateek
|
||||
Goel\r\n - Prateek Nayak\r\n - Prayag Verma\r\n - Priyantha Lankapura\r\n - @progre\r\n
|
||||
- Punya Biswal\r\n - r7kamura\r\n - Rado Kirov\r\n - Raj Dosanjh\r\n - rChaser53\r\n
|
||||
- Reiner Dolp\r\n - Remo H. Jansen\r\n - @rflorian\r\n - Rhys van der Waerden\r\n
|
||||
- @rhysd\r\n - Ricardo N Feliciano\r\n - Richard Karmaz??n\r\n - Richard Knoll\r\n
|
||||
- Roger Spratley\r\n - Ron Buckton\r\n - Rostislav Galimsky\r\n - Rowan Wyborn\r\n
|
||||
- rpgeeganage\r\n - Ruwan Pradeep Geeganage\r\n - Ryan Cavanaugh\r\n - Ryan Clarke\r\n
|
||||
- Ryohei Ikegami\r\n - Salisbury, Tom\r\n - Sam Bostock\r\n - Sam Drugan\r\n -
|
||||
Sam El-Husseini\r\n - Sam Lanning\r\n - Sangmin Lee\r\n - Sanket Mishra\r\n -
|
||||
Sarangan Rajamanickam\r\n - Sasha Joseph\r\n - Sean Barag\r\n - Sergey Rubanov\r\n
|
||||
- Sergey Shandar\r\n - Sergey Tychinin\r\n - Sergii Bezliudnyi\r\n - Sergio Baidon\r\n
|
||||
- Sharon Rolel\r\n - Sheetal Nandi\r\n - Shengping Zhong\r\n - Sheon Han\r\n -
|
||||
Shyyko Serhiy\r\n - Siddharth Singh\r\n - sisisin\r\n - Slawomir Sadziak\r\n -
|
||||
Solal Pirelli\r\n - Soo Jae Hwang\r\n - Stan Thomas\r\n - Stanislav Iliev\r\n
|
||||
- Stanislav Sysoev\r\n - Stas Vilchik\r\n - Stephan Ginth??r\r\n - Steve Lucco\r\n
|
||||
- @styfle\r\n - Sudheesh Singanamalla\r\n - Suhas\r\n - Suhas Deshpande\r\n -
|
||||
superkd37\r\n - S??bastien Arod\r\n - @T18970237136\r\n - @t_\r\n - Tan Li Hau\r\n
|
||||
- Tapan Prakash\r\n - Taras Mankovski\r\n - Tarik Ozket\r\n - Tetsuharu Ohzeki\r\n
|
||||
- The Gitter Badger\r\n - Thomas den Hollander\r\n - Thorsten Ball\r\n - Tien
|
||||
Hoanhtien\r\n - Tim Lancina\r\n - Tim Perry\r\n - Tim Schaub\r\n - Tim Suchanek\r\n
|
||||
- Tim Viiding-Spader\r\n - Tingan Ho\r\n - Titian Cernicova-Dragomir\r\n - tkondo\r\n
|
||||
- Todd Thomson\r\n - togru\r\n - Tom J\r\n - Torben Fitschen\r\n - Toxyxer\r\n
|
||||
- @TravCav\r\n - Troy Tae\r\n - TruongSinh Tran-Nguyen\r\n - Tycho Grouwstra\r\n
|
||||
- uhyo\r\n - Vadi Taslim\r\n - Vakhurin Sergey\r\n - Valera Rozuvan\r\n - Vilic
|
||||
Vane\r\n - Vimal Raghubir\r\n - Vladimir Kurchatkin\r\n - Vladimir Matveev\r\n
|
||||
- Vyacheslav Pukhanov\r\n - Wenlu Wang\r\n - Wes Souza\r\n - Wesley Wigham\r\n
|
||||
- William Orr\r\n - Wilson Hobbs\r\n - xiaofa\r\n - xl1\r\n - Yacine Hmito\r\n
|
||||
- Yang Cao\r\n - York Yao\r\n - @yortus\r\n - Yoshiki Shibukawa\r\n - Yuichi Nukiyama\r\n
|
||||
- Yuval Greenfield\r\n - Yuya Tanaka\r\n - Z\r\n - Zeeshan Ahmed\r\n - Zev Spitz\r\n
|
||||
- Zhengbo Li\r\n - Zixiang Li\r\n - @Zzzen\r\n - ?????????"
|
33
.licenses/npm/universalify.dep.yml
generated
33
.licenses/npm/universalify.dep.yml
generated
@ -1,33 +0,0 @@
|
||||
---
|
||||
name: universalify
|
||||
version: 0.1.2
|
||||
type: npm
|
||||
summary: Make a callback- or promise-based function support both promises and callbacks.
|
||||
homepage: https://github.com/RyanZim/universalify#readme
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
(The MIT License)
|
||||
|
||||
Copyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the 'Software'), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
- sources: README.md
|
||||
text: MIT
|
||||
notices: []
|
@ -3,7 +3,7 @@ name: uuid
|
||||
version: 8.3.2
|
||||
type: npm
|
||||
summary: RFC4122 (v1, v4, and v5) UUIDs
|
||||
homepage: https://github.com/uuidjs/uuid#readme
|
||||
homepage:
|
||||
license: mit
|
||||
licenses:
|
||||
- sources: LICENSE.md
|
26
.licenses/npm/wrappy.dep.yml
generated
Normal file
26
.licenses/npm/wrappy.dep.yml
generated
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
name: wrappy
|
||||
version: 1.0.2
|
||||
type: npm
|
||||
summary: Callback wrapping utility
|
||||
homepage: https://github.com/npm/wrappy
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
notices: []
|
2
.licenses/npm/xml2js.dep.yml
generated
2
.licenses/npm/xml2js.dep.yml
generated
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: xml2js
|
||||
version: 0.4.23
|
||||
version: 0.5.0
|
||||
type: npm
|
||||
summary: Simple XML to JavaScript object converter.
|
||||
homepage: https://github.com/Leonidas-from-XIV/node-xml2js
|
||||
|
24
.licenses/npm/yaml.dep.yml
generated
Normal file
24
.licenses/npm/yaml.dep.yml
generated
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
name: yaml
|
||||
version: 1.10.2
|
||||
type: npm
|
||||
summary: JavaScript parser and stringifier for YAML
|
||||
homepage: https://eemeli.org/yaml/v1/
|
||||
license: isc
|
||||
licenses:
|
||||
- sources: LICENSE
|
||||
text: |
|
||||
Copyright 2018 Eemeli Aro <eemeli@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
notices: []
|
225
README.md
225
README.md
@ -1,7 +1,12 @@
|
||||
# cache
|
||||
# Cache action
|
||||
|
||||
This action allows caching dependencies and build outputs to improve workflow execution time.
|
||||
|
||||
>Two other actions are available in addition to the primary `cache` action:
|
||||
>
|
||||
>* [Restore action](./restore/README.md)
|
||||
>* [Save action](./save/README.md)
|
||||
|
||||
[](https://github.com/actions/cache/actions/workflows/workflow.yml)
|
||||
|
||||
## Documentation
|
||||
@ -9,8 +14,32 @@ This action allows caching dependencies and build outputs to improve workflow ex
|
||||
See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows).
|
||||
|
||||
## What's New
|
||||
|
||||
### ⚠️ Important changes
|
||||
|
||||
The cache backend service has been rewritten from the ground up for improved performance and reliability. [actions/cache](https://github.com/actions/cache) now integrates with the new cache service (v2) APIs.
|
||||
|
||||
The new service will gradually roll out as of **February 1st, 2025**. The legacy service will also be sunset on the same date. Changes in these release are **fully backward compatible**.
|
||||
|
||||
**We are deprecating some versions of this action**. We recommend upgrading to version `v4` or `v3` as soon as possible before **February 1st, 2025.** (Upgrade instructions below).
|
||||
|
||||
If you are using pinned SHAs, please use the SHAs of versions `v4.2.0` or `v3.4.0`
|
||||
|
||||
If you do not upgrade, all workflow runs using any of the deprecated [actions/cache](https://github.com/actions/cache) will fail.
|
||||
|
||||
Upgrading to the recommended versions will not break your workflows.
|
||||
|
||||
Read more about the change & access the migration guide: [reference to the announcement](https://github.com/actions/cache/discussions/1510).
|
||||
|
||||
### v4
|
||||
|
||||
* Integrated with the new cache service (v2) APIs.
|
||||
* Updated to node 20
|
||||
|
||||
### v3
|
||||
* Added support for caching from GHES 3.5.
|
||||
|
||||
* Integrated with the new cache service (v2) APIs.
|
||||
* Added support for caching in GHES 3.5+.
|
||||
* Fixed download issue for files > 2GB during restore.
|
||||
* Updated the minimum runner version support from node 12 -> node 16.
|
||||
* Fixed avoiding empty cache save when no files are available for caching.
|
||||
@ -19,40 +48,56 @@ See ["Caching dependencies to speed up workflows"](https://docs.github.com/en/ac
|
||||
* Fixed cache not working with github workspace directory or current directory.
|
||||
* Fixed the download stuck problem by introducing a timeout of 1 hour for cache downloads.
|
||||
* Fix zstd not working for windows on gnu tar in issues.
|
||||
* Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MINS`. Default is 60 minutes.
|
||||
* Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MINS`. Default is 10 minutes.
|
||||
* New actions are available for granular control over caches - [restore](restore/action.yml) and [save](save/action.yml).
|
||||
* Support cross-os caching as an opt-in feature. See [Cross OS caching](./tips-and-workarounds.md#cross-os-cache) for more info.
|
||||
* Added option to fail job on cache miss. See [Exit workflow on cache miss](./restore/README.md#exit-workflow-on-cache-miss) for more info.
|
||||
* Fix zstd not being used after zstd version upgrade to 1.5.4 on hosted runners
|
||||
* Added option to lookup cache without downloading it.
|
||||
* Reduced segment size to 128MB and segment timeout to 10 minutes to fail fast in case the cache download is stuck.
|
||||
|
||||
Refer [here](https://github.com/actions/cache/blob/v2/README.md) for previous versions
|
||||
See the [v2 README.md](https://github.com/actions/cache/blob/v2/README.md) for older updates.
|
||||
|
||||
## Usage
|
||||
|
||||
### Pre-requisites
|
||||
Create a workflow `.yml` file in your repositories `.github/workflows` directory. An [example workflow](#example-workflow) is available below. For more information, reference the GitHub Help Documentation for [Creating a workflow file](https://help.github.com/en/articles/configuring-a-workflow#creating-a-workflow-file).
|
||||
|
||||
If you are using this inside a container, a POSIX-compliant `tar` needs to be included and accessible in the execution path.
|
||||
Create a workflow `.yml` file in your repository's `.github/workflows` directory. An [example workflow](#example-cache-workflow) is available below. For more information, see the GitHub Help Documentation for [Creating a workflow file](https://help.github.com/en/articles/configuring-a-workflow#creating-a-workflow-file).
|
||||
|
||||
If you are using this inside a container, a POSIX-compliant `tar` needs to be included and accessible from the execution path.
|
||||
|
||||
If you are using a `self-hosted` Windows runner, `GNU tar` and `zstd` are required for [Cross-OS caching](https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cross-os-cache) to work. They are also recommended to be installed in general so the performance is on par with `hosted` Windows runners.
|
||||
|
||||
### Inputs
|
||||
|
||||
* `key` - An explicit key for a cache entry. See [creating a cache key](#creating-a-cache-key).
|
||||
* `path` - A list of files, directories, and wildcard patterns to cache and restore. See [`@actions/glob`](https://github.com/actions/toolkit/tree/main/packages/glob) for supported patterns.
|
||||
* `key` - An explicit key for restoring and saving the cache
|
||||
* `restore-keys` - An ordered list of prefix-matched keys to use for restoring stale cache if no cache hit occurred for key.
|
||||
* `restore-keys` - An ordered multiline string listing the prefix-matched keys, that are used for restoring stale cache if no cache hit occurred for key.
|
||||
* `enableCrossOsArchive` - An optional boolean when enabled, allows Windows runners to save or restore caches that can be restored or saved respectively on other platforms. Default: `false`
|
||||
* `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: `false`
|
||||
* `lookup-only` - If true, only checks if cache entry exists and skips download. Does not change save cache behavior. Default: `false`
|
||||
|
||||
#### Environment Variables
|
||||
* `SEGMENT_DOWNLOAD_TIMEOUT_MINS` - Segment download timeout (in minutes, default `60`) to abort download of the segment if not completed in the defined number of minutes. [Read more](https://github.com/actions/cache/blob/main/workarounds.md#cache-segment-restore-timeout)
|
||||
|
||||
* `SEGMENT_DOWNLOAD_TIMEOUT_MINS` - Segment download timeout (in minutes, default `10`) to abort download of the segment if not completed in the defined number of minutes. [Read more](https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout)
|
||||
|
||||
### Outputs
|
||||
|
||||
* `cache-hit` - A boolean value to indicate an exact match was found for the key.
|
||||
|
||||
> Note: `cache-hit` will be set to `true` only when cache hit occurs for the exact `key` match. For a partial key match via `restore-keys` or a cache miss, it will be set to `false`.
|
||||
* `cache-hit` - A string value to indicate an exact match was found for the key.
|
||||
* If there's a cache hit, this will be 'true' or 'false' to indicate if there's an exact match for `key`.
|
||||
* If there's a cache miss, this will be an empty string.
|
||||
|
||||
See [Skipping steps based on cache-hit](#skipping-steps-based-on-cache-hit) for info on using this output
|
||||
|
||||
### Cache scopes
|
||||
The cache is scoped to the key, [version](#cache-version) and branch. The default branch cache is available to other branches.
|
||||
|
||||
The cache is scoped to the key, [version](#cache-version), and branch. The default branch cache is available to other branches.
|
||||
|
||||
See [Matching a cache key](https://help.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key) for more info.
|
||||
|
||||
### Example workflow
|
||||
### Example cache workflow
|
||||
|
||||
#### Restoring and saving cache using a single action
|
||||
|
||||
```yaml
|
||||
name: Caching Primes
|
||||
@ -64,11 +109,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Primes
|
||||
id: cache-primes
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: prime-numbers
|
||||
key: ${{ runner.os }}-primes
|
||||
@ -81,7 +126,49 @@ jobs:
|
||||
run: /primes.sh -d prime-numbers
|
||||
```
|
||||
|
||||
> Note: You must use the `cache` action in your workflow before you need to use the files that might be restored from the cache. If the provided `key` matches an existing cache, a new cache is not created and if the provided `key` doesn't match an existing cache, a new cache is automatically created provided the job completes successfully.
|
||||
The `cache` action provides a `cache-hit` output which is set to `true` when the cache is restored using the primary `key` and `false` when the cache is restored using `restore-keys` or no cache is restored.
|
||||
|
||||
#### Using a combination of restore and save actions
|
||||
|
||||
```yaml
|
||||
name: Caching Primes
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore cached Primes
|
||||
id: cache-primes-restore
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: ${{ runner.os }}-primes
|
||||
.
|
||||
. //intermediate workflow steps
|
||||
.
|
||||
- name: Save Primes
|
||||
id: cache-primes-save
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: ${{ steps.cache-primes-restore.outputs.cache-primary-key }}
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> You must use the `cache` or `restore` action in your workflow before you need to use the files that might be restored from the cache. If the provided `key` matches an existing cache, a new cache is not created and if the provided `key` doesn't match an existing cache, a new cache is automatically created provided the job completes successfully.
|
||||
|
||||
## Caching Strategies
|
||||
|
||||
With the introduction of the `restore` and `save` actions, a lot of caching use cases can now be achieved. Please see the [caching strategies](./caching-strategies.md) document for understanding how you can use the actions strategically to achieve the desired goal.
|
||||
|
||||
## Implementation Examples
|
||||
|
||||
@ -89,30 +176,32 @@ Every programming language and framework has its own way of caching.
|
||||
|
||||
See [Examples](examples.md) for a list of `actions/cache` implementations for use with:
|
||||
|
||||
- [C# - NuGet](./examples.md#c---nuget)
|
||||
- [Clojure - Lein Deps](./examples.md#clojure---lein-deps)
|
||||
- [D - DUB](./examples.md#d---dub)
|
||||
- [Deno](./examples.md#deno)
|
||||
- [Elixir - Mix](./examples.md#elixir---mix)
|
||||
- [Go - Modules](./examples.md#go---modules)
|
||||
- [Haskell - Cabal](./examples.md#haskell---cabal)
|
||||
- [Haskell - Stack](./examples.md#haskell---stack)
|
||||
- [Java - Gradle](./examples.md#java---gradle)
|
||||
- [Java - Maven](./examples.md#java---maven)
|
||||
- [Node - npm](./examples.md#node---npm)
|
||||
- [Node - Lerna](./examples.md#node---lerna)
|
||||
- [Node - Yarn](./examples.md#node---yarn)
|
||||
- [OCaml/Reason - esy](./examples.md#ocamlreason---esy)
|
||||
- [PHP - Composer](./examples.md#php---composer)
|
||||
- [Python - pip](./examples.md#python---pip)
|
||||
- [Python - pipenv](./examples.md#python---pipenv)
|
||||
- [R - renv](./examples.md#r---renv)
|
||||
- [Ruby - Bundler](./examples.md#ruby---bundler)
|
||||
- [Rust - Cargo](./examples.md#rust---cargo)
|
||||
- [Scala - SBT](./examples.md#scala---sbt)
|
||||
- [Swift, Objective-C - Carthage](./examples.md#swift-objective-c---carthage)
|
||||
- [Swift, Objective-C - CocoaPods](./examples.md#swift-objective-c---cocoapods)
|
||||
- [Swift - Swift Package Manager](./examples.md#swift---swift-package-manager)
|
||||
* [Bun](./examples.md#bun)
|
||||
* [C# - NuGet](./examples.md#c---nuget)
|
||||
* [Clojure - Lein Deps](./examples.md#clojure---lein-deps)
|
||||
* [D - DUB](./examples.md#d---dub)
|
||||
* [Deno](./examples.md#deno)
|
||||
* [Elixir - Mix](./examples.md#elixir---mix)
|
||||
* [Go - Modules](./examples.md#go---modules)
|
||||
* [Haskell - Cabal](./examples.md#haskell---cabal)
|
||||
* [Haskell - Stack](./examples.md#haskell---stack)
|
||||
* [Java - Gradle](./examples.md#java---gradle)
|
||||
* [Java - Maven](./examples.md#java---maven)
|
||||
* [Node - npm](./examples.md#node---npm)
|
||||
* [Node - Lerna](./examples.md#node---lerna)
|
||||
* [Node - Yarn](./examples.md#node---yarn)
|
||||
* [OCaml/Reason - esy](./examples.md#ocamlreason---esy)
|
||||
* [PHP - Composer](./examples.md#php---composer)
|
||||
* [Python - pip](./examples.md#python---pip)
|
||||
* [Python - pipenv](./examples.md#python---pipenv)
|
||||
* [R - renv](./examples.md#r---renv)
|
||||
* [Ruby - Bundler](./examples.md#ruby---bundler)
|
||||
* [Rust - Cargo](./examples.md#rust---cargo)
|
||||
* [Scala - SBT](./examples.md#scala---sbt)
|
||||
* [Swift, Objective-C - Carthage](./examples.md#swift-objective-c---carthage)
|
||||
* [Swift, Objective-C - CocoaPods](./examples.md#swift-objective-c---cocoapods)
|
||||
* [Swift - Swift Package Manager](./examples.md#swift---swift-package-manager)
|
||||
* [Swift - Mint](./examples.md#swift---mint)
|
||||
|
||||
## Creating a cache key
|
||||
|
||||
@ -121,7 +210,7 @@ A cache key can include any of the contexts, functions, literals, and operators
|
||||
For example, using the [`hashFiles`](https://docs.github.com/en/actions/learn-github-actions/expressions#hashfiles) function allows you to create a new cache when dependencies change.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
@ -136,10 +225,10 @@ Additionally, you can use arbitrary command output in a cache key, such as a dat
|
||||
- name: Get Date
|
||||
id: get-date
|
||||
run: |
|
||||
echo "::set-output name=date::$(/bin/date -u "+%Y%m%d")"
|
||||
echo "date=$(/bin/date -u "+%Y%m%d")" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ steps.get-date.outputs.date }}-${{ hashFiles('**/lockfiles') }}
|
||||
@ -153,14 +242,15 @@ A repository can have up to 10GB of caches. Once the 10GB limit is reached, olde
|
||||
|
||||
## Skipping steps based on cache-hit
|
||||
|
||||
Using the `cache-hit` output, subsequent steps (such as install or build) can be skipped when a cache hit occurs on the key. It is recommended to install the missing/updated dependencies in case of a partial key match when the key is dependent on the `hash` of the package file.
|
||||
Using the `cache-hit` output, subsequent steps (such as install or build) can be skipped when a cache hit occurs on the key. It is recommended to install missing/updated dependencies in case of a partial key match when the key is dependent on the `hash` of the package file.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
@ -171,13 +261,13 @@ steps:
|
||||
run: /install.sh
|
||||
```
|
||||
|
||||
> Note: The `id` defined in `actions/cache` must match the `id` in the `if` statement (i.e. `steps.[ID].outputs.cache-hit`)
|
||||
|
||||
> **Note** The `id` defined in `actions/cache` must match the `id` in the `if` statement (i.e. `steps.[ID].outputs.cache-hit`)
|
||||
|
||||
## Cache Version
|
||||
Cache version is a hash [generated](https://github.com/actions/toolkit/blob/500d0b42fee2552ae9eeb5933091fe2fbf14e72d/packages/cache/src/internal/cacheHttpClient.ts#L73-L90) for a combination of compression tool used (Gzip, Zstd, etc. based on the runner OS) and the `path` of directories being cached. If two caches have different versions, they are identified as unique caches while matching. This for example, means that a cache created on `windows-latest` runner can't be restored on `ubuntu-latest` as cache `Version`s are different.
|
||||
|
||||
> Pro tip: [List caches](https://docs.github.com/en/rest/actions/cache#list-github-actions-caches-for-a-repository) API can be used to get the version of a cache. This can be helpful to troubleshoot cache miss due to version.
|
||||
Cache version is a hash [generated](https://github.com/actions/toolkit/blob/500d0b42fee2552ae9eeb5933091fe2fbf14e72d/packages/cache/src/internal/cacheHttpClient.ts#L73-L90) for a combination of compression tool used (Gzip, Zstd, etc. based on the runner OS) and the `path` of directories being cached. If two caches have different versions, they are identified as unique caches while matching. This, for example, means that a cache created on a `windows-latest` runner can't be restored on `ubuntu-latest` as cache `Version`s are different.
|
||||
|
||||
> Pro tip: The [list caches](https://docs.github.com/en/rest/actions/cache#list-github-actions-caches-for-a-repository) API can be used to get the version of a cache. This can be helpful to troubleshoot cache miss due to version.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
@ -188,11 +278,11 @@ jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Primes
|
||||
id: cache-primes
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: prime-numbers
|
||||
key: primes
|
||||
@ -203,7 +293,7 @@ jobs:
|
||||
|
||||
- name: Cache Numbers
|
||||
id: cache-numbers
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: numbers
|
||||
key: primes
|
||||
@ -215,11 +305,11 @@ jobs:
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Primes
|
||||
id: cache-primes
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: prime-numbers
|
||||
key: primes
|
||||
@ -228,22 +318,27 @@ jobs:
|
||||
if: steps.cache-primes.outputs.cache-hit != 'true'
|
||||
run: ./generate-primes -d prime-numbers
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Known practices and workarounds
|
||||
Following are some of the known practices/workarounds which community has used to fulfill specific requirements. You may choose to use them if suits your use case. Note these are not necessarily the only or the recommended solution.
|
||||
|
||||
- [Cache segment restore timeout](./tips-and-workarounds.md#cache-segment-restore-timeout)
|
||||
- [Update a cache](./tips-and-workarounds.md#update-a-cache)
|
||||
- [Use cache across feature branches](./tips-and-workarounds.md#use-cache-across-feature-branches)
|
||||
- [Improving cache restore performance on Windows/Using cross-os caching](./tips-and-workarounds.md#improving-cache-restore-performance-on-windows-using-cross-os-caching)
|
||||
- [Force deletion of caches overriding default cache eviction policy](./tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy)
|
||||
There are a number of community practices/workarounds to fulfill specific requirements. You may choose to use them if they suit your use case. Note these are not necessarily the only solution or even a recommended solution.
|
||||
|
||||
#### Windows environment variables
|
||||
Please note that Windows environment variables (like `%LocalAppData%`) will NOT be expanded by this action. Instead, prefer using `~` in your paths which will expand to HOME directory. For example, instead of `%LocalAppData%`, use `~\AppData\Local`. For a list of supported default environment variables, see [this](https://docs.github.com/en/actions/learn-github-actions/environment-variables) page.
|
||||
* [Cache segment restore timeout](./tips-and-workarounds.md#cache-segment-restore-timeout)
|
||||
* [Update a cache](./tips-and-workarounds.md#update-a-cache)
|
||||
* [Use cache across feature branches](./tips-and-workarounds.md#use-cache-across-feature-branches)
|
||||
* [Cross OS cache](./tips-and-workarounds.md#cross-os-cache)
|
||||
* [Force deletion of caches overriding default cache eviction policy](./tips-and-workarounds.md#force-deletion-of-caches-overriding-default-cache-eviction-policy)
|
||||
|
||||
### Windows environment variables
|
||||
|
||||
Please note that Windows environment variables (like `%LocalAppData%`) will NOT be expanded by this action. Instead, prefer using `~` in your paths which will expand to the HOME directory. For example, instead of `%LocalAppData%`, use `~\AppData\Local`. For a list of supported default environment variables, see the [Learn GitHub Actions: Variables](https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables) page.
|
||||
|
||||
## Contributing
|
||||
We would love for you to contribute to `actions/cache`, pull requests are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||
|
||||
We would love for you to contribute to `actions/cache`. Pull requests are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) for more information.
|
||||
|
||||
## License
|
||||
|
||||
The scripts and documentation in this project are released under the [MIT License](LICENSE)
|
||||
|
184
RELEASES.md
184
RELEASES.md
@ -1,42 +1,174 @@
|
||||
# Releases
|
||||
|
||||
### 3.0.0
|
||||
- Updated minimum runner version support from node 12 -> node 16
|
||||
### 4.2.3
|
||||
|
||||
### 3.0.1
|
||||
- Added support for caching from GHES 3.5.
|
||||
- Fixed download issue for files > 2GB during restore.
|
||||
- Bump `@actions/cache` to v4.0.3 (obfuscates SAS token in debug logs for cache entries)
|
||||
|
||||
### 3.0.2
|
||||
- Added support for dynamic cache size cap on GHES.
|
||||
### 4.2.2
|
||||
|
||||
### 3.0.3
|
||||
- Fixed avoiding empty cache save when no files are available for caching. ([issue](https://github.com/actions/cache/issues/624))
|
||||
- Bump `@actions/cache` to v4.0.2
|
||||
|
||||
### 3.0.4
|
||||
- Fixed tar creation error while trying to create tar with path as `~/` home folder on `ubuntu-latest`. ([issue](https://github.com/actions/cache/issues/689))
|
||||
### 4.2.1
|
||||
|
||||
### 3.0.5
|
||||
- Removed error handling by consuming actions/cache 3.0 toolkit, Now cache server error handling will be done by toolkit. ([PR](https://github.com/actions/cache/pull/834))
|
||||
- Bump `@actions/cache` to v4.0.1
|
||||
|
||||
### 3.0.6
|
||||
- Fixed [#809](https://github.com/actions/cache/issues/809) - zstd -d: no such file or directory error
|
||||
- Fixed [#833](https://github.com/actions/cache/issues/833) - cache doesn't work with github workspace directory
|
||||
### 4.2.0
|
||||
|
||||
### 3.0.7
|
||||
- Fixed [#810](https://github.com/actions/cache/issues/810) - download stuck issue. A new timeout is introduced in the download process to abort the download if it gets stuck and doesn't finish within an hour.
|
||||
TLDR; The cache backend service has been rewritten from the ground up for improved performance and reliability. [actions/cache](https://github.com/actions/cache) now integrates with the new cache service (v2) APIs.
|
||||
|
||||
### 3.0.8
|
||||
- Fix zstd not working for windows on gnu tar in issues [#888](https://github.com/actions/cache/issues/888) and [#891](https://github.com/actions/cache/issues/891).
|
||||
- Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MINS`. Default is 60 minutes.
|
||||
The new service will gradually roll out as of **February 1st, 2025**. The legacy service will also be sunset on the same date. Changes in these release are **fully backward compatible**.
|
||||
|
||||
### 3.0.9
|
||||
- Enhanced the warning message for cache unavailablity in case of GHES.
|
||||
**We are deprecating some versions of this action**. We recommend upgrading to version `v4` or `v3` as soon as possible before **February 1st, 2025.** (Upgrade instructions below).
|
||||
|
||||
If you are using pinned SHAs, please use the SHAs of versions `v4.2.0` or `v3.4.0`
|
||||
|
||||
If you do not upgrade, all workflow runs using any of the deprecated [actions/cache](https://github.com/actions/cache) will fail.
|
||||
|
||||
Upgrading to the recommended versions will not break your workflows.
|
||||
|
||||
### 4.1.2
|
||||
|
||||
- Add GitHub Enterprise Cloud instances hostname filters to inform API endpoint choices - [#1474](https://github.com/actions/cache/pull/1474)
|
||||
- Security fix: Bump braces from 3.0.2 to 3.0.3 - [#1475](https://github.com/actions/cache/pull/1475)
|
||||
|
||||
### 4.1.1
|
||||
|
||||
- Restore original behavior of `cache-hit` output - [#1467](https://github.com/actions/cache/pull/1467)
|
||||
|
||||
### 4.1.0
|
||||
|
||||
- Ensure `cache-hit` output is set when a cache is missed - [#1404](https://github.com/actions/cache/pull/1404)
|
||||
- Deprecate `save-always` input - [#1452](https://github.com/actions/cache/pull/1452)
|
||||
|
||||
### 4.0.2
|
||||
|
||||
- Fixed restore `fail-on-cache-miss` not working.
|
||||
|
||||
### 4.0.1
|
||||
|
||||
- Updated `isGhes` check
|
||||
|
||||
### 4.0.0
|
||||
|
||||
- Updated minimum runner version support from node 12 -> node 20
|
||||
|
||||
### 3.4.0
|
||||
|
||||
- Integrated with the new cache service (v2) APIs
|
||||
|
||||
### 3.3.3
|
||||
|
||||
- Updates @actions/cache to v3.2.3 to fix accidental mutated path arguments to `getCacheVersion` [actions/toolkit#1378](https://github.com/actions/toolkit/pull/1378)
|
||||
- Additional audit fixes of npm package(s)
|
||||
|
||||
### 3.3.2
|
||||
|
||||
- Fixes bug with Azure SDK causing blob downloads to get stuck.
|
||||
|
||||
### 3.3.1
|
||||
|
||||
- Reduced segment size to 128MB and segment timeout to 10 minutes to fail fast in case the cache download is stuck.
|
||||
|
||||
### 3.3.0
|
||||
|
||||
- Added option to lookup cache without downloading it.
|
||||
|
||||
### 3.2.6
|
||||
|
||||
- Fix zstd not being used after zstd version upgrade to 1.5.4 on hosted runners.
|
||||
|
||||
### 3.2.5
|
||||
|
||||
- Added fix to prevent from setting MYSYS environment variable globally.
|
||||
|
||||
### 3.2.4
|
||||
|
||||
- Added option to fail job on cache miss.
|
||||
|
||||
### 3.2.3
|
||||
|
||||
- Support cross os caching on Windows as an opt-in feature.
|
||||
- Fix issue with symlink restoration on Windows for cross-os caches.
|
||||
|
||||
### 3.2.2
|
||||
|
||||
- Reverted the changes made in 3.2.1 to use gnu tar and zstd by default on windows.
|
||||
|
||||
### 3.2.1
|
||||
|
||||
- Update `@actions/cache` on windows to use gnu tar and zstd by default and fallback to bsdtar and zstd if gnu tar is not available. ([issue](https://github.com/actions/cache/issues/984))
|
||||
- Added support for fallback to gzip to restore old caches on windows.
|
||||
- Added logs for cache version in case of a cache miss.
|
||||
|
||||
### 3.2.0
|
||||
|
||||
- Released the two new actions - [restore](restore/action.yml) and [save](save/action.yml) for granular control on cache
|
||||
|
||||
### 3.2.0-beta.1
|
||||
|
||||
- Added two new actions - [restore](restore/action.yml) and [save](save/action.yml) for granular control on cache.
|
||||
|
||||
### 3.1.0-beta.3
|
||||
|
||||
- Bug fixes for bsdtar fallback if gnutar not available and gzip fallback if cache saved using old cache action on windows.
|
||||
|
||||
### 3.1.0-beta.2
|
||||
|
||||
- Added support for fallback to gzip to restore old caches on windows.
|
||||
|
||||
### 3.1.0-beta.1
|
||||
|
||||
- Update `@actions/cache` on windows to use gnu tar and zstd by default and fallback to bsdtar and zstd if gnu tar is not available. ([issue](https://github.com/actions/cache/issues/984))
|
||||
|
||||
### 3.0.11
|
||||
|
||||
- Update toolkit version to 3.0.5 to include `@actions/core@^1.10.0`
|
||||
- Update `@actions/cache` to use updated `saveState` and `setOutput` functions from `@actions/core@^1.10.0`
|
||||
|
||||
### 3.0.10
|
||||
|
||||
- Fix a bug with sorting inputs.
|
||||
- Update definition for restore-keys in README.md
|
||||
|
||||
### 3.0.11
|
||||
- Update toolkit version to 3.0.5 to include `@actions/core@^1.10.0`
|
||||
- Update `@actions/cache` to use updated `saveState` and `setOutput` functions from `@actions/core@^1.10.0`
|
||||
### 3.0.9
|
||||
|
||||
- Enhanced the warning message for cache unavailablity in case of GHES.
|
||||
|
||||
### 3.0.8
|
||||
|
||||
- Fix zstd not working for windows on gnu tar in issues [#888](https://github.com/actions/cache/issues/888) and [#891](https://github.com/actions/cache/issues/891).
|
||||
- Allowing users to provide a custom timeout as input for aborting download of a cache segment using an environment variable `SEGMENT_DOWNLOAD_TIMEOUT_MINS`. Default is 60 minutes.
|
||||
|
||||
### 3.0.7
|
||||
|
||||
- Fixed [#810](https://github.com/actions/cache/issues/810) - download stuck issue. A new timeout is introduced in the download process to abort the download if it gets stuck and doesn't finish within an hour.
|
||||
|
||||
### 3.0.6
|
||||
|
||||
- Fixed [#809](https://github.com/actions/cache/issues/809) - zstd -d: no such file or directory error
|
||||
- Fixed [#833](https://github.com/actions/cache/issues/833) - cache doesn't work with github workspace directory
|
||||
|
||||
### 3.0.5
|
||||
|
||||
- Removed error handling by consuming actions/cache 3.0 toolkit, Now cache server error handling will be done by toolkit. ([PR](https://github.com/actions/cache/pull/834))
|
||||
|
||||
### 3.0.4
|
||||
|
||||
- Fixed tar creation error while trying to create tar with path as `~/` home folder on `ubuntu-latest`. ([issue](https://github.com/actions/cache/issues/689))
|
||||
|
||||
### 3.0.3
|
||||
|
||||
- Fixed avoiding empty cache save when no files are available for caching. ([issue](https://github.com/actions/cache/issues/624))
|
||||
|
||||
### 3.0.2
|
||||
|
||||
- Added support for dynamic cache size cap on GHES.
|
||||
|
||||
### 3.0.1
|
||||
|
||||
- Added support for caching from GHES 3.5.
|
||||
- Fixed download issue for files > 2GB during restore.
|
||||
|
||||
### 3.0.0
|
||||
|
||||
- Updated minimum runner version support from node 12 -> node 16
|
||||
|
@ -1,24 +1,33 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Outputs, RefKey, State } from "../src/constants";
|
||||
import { Events, RefKey } from "../src/constants";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
jest.mock("@actions/core");
|
||||
jest.mock("@actions/cache");
|
||||
|
||||
let pristineEnv: NodeJS.ProcessEnv;
|
||||
|
||||
beforeAll(() => {
|
||||
pristineEnv = process.env;
|
||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||
return jest.requireActual("@actions/core").getInput(name, options);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = pristineEnv;
|
||||
delete process.env[Events.Key];
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
process.env = pristineEnv;
|
||||
});
|
||||
|
||||
test("isGhes returns true if server url is not github.com", () => {
|
||||
try {
|
||||
process.env["GITHUB_SERVER_URL"] = "http://example.com";
|
||||
@ -79,83 +88,6 @@ test("isExactKeyMatch with same key and different casing returns true", () => {
|
||||
expect(actionUtils.isExactKeyMatch(key, cacheKey)).toBe(true);
|
||||
});
|
||||
|
||||
test("setOutputAndState with undefined entry to set cache-hit output", () => {
|
||||
const key = "linux-rust";
|
||||
const cacheKey = undefined;
|
||||
|
||||
const setOutputMock = jest.spyOn(core, "setOutput");
|
||||
const saveStateMock = jest.spyOn(core, "saveState");
|
||||
|
||||
actionUtils.setOutputAndState(key, cacheKey);
|
||||
|
||||
expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false");
|
||||
expect(setOutputMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(saveStateMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("setOutputAndState with exact match to set cache-hit output and state", () => {
|
||||
const key = "linux-rust";
|
||||
const cacheKey = "linux-rust";
|
||||
|
||||
const setOutputMock = jest.spyOn(core, "setOutput");
|
||||
const saveStateMock = jest.spyOn(core, "saveState");
|
||||
|
||||
actionUtils.setOutputAndState(key, cacheKey);
|
||||
|
||||
expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "true");
|
||||
expect(setOutputMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(saveStateMock).toHaveBeenCalledWith(State.CacheMatchedKey, cacheKey);
|
||||
expect(saveStateMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("setOutputAndState with no exact match to set cache-hit output and state", () => {
|
||||
const key = "linux-rust";
|
||||
const cacheKey = "linux-rust-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
|
||||
const setOutputMock = jest.spyOn(core, "setOutput");
|
||||
const saveStateMock = jest.spyOn(core, "saveState");
|
||||
|
||||
actionUtils.setOutputAndState(key, cacheKey);
|
||||
|
||||
expect(setOutputMock).toHaveBeenCalledWith(Outputs.CacheHit, "false");
|
||||
expect(setOutputMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(saveStateMock).toHaveBeenCalledWith(State.CacheMatchedKey, cacheKey);
|
||||
expect(saveStateMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("getCacheState with no state returns undefined", () => {
|
||||
const getStateMock = jest.spyOn(core, "getState");
|
||||
getStateMock.mockImplementation(() => {
|
||||
return "";
|
||||
});
|
||||
|
||||
const state = actionUtils.getCacheState();
|
||||
|
||||
expect(state).toBe(undefined);
|
||||
|
||||
expect(getStateMock).toHaveBeenCalledWith(State.CacheMatchedKey);
|
||||
expect(getStateMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("getCacheState with valid state", () => {
|
||||
const cacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
|
||||
const getStateMock = jest.spyOn(core, "getState");
|
||||
getStateMock.mockImplementation(() => {
|
||||
return cacheKey;
|
||||
});
|
||||
|
||||
const state = actionUtils.getCacheState();
|
||||
|
||||
expect(state).toEqual(cacheKey);
|
||||
|
||||
expect(getStateMock).toHaveBeenCalledWith(State.CacheMatchedKey);
|
||||
expect(getStateMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("logWarning logs a message with a warning prefix", () => {
|
||||
const message = "A warning occurred.";
|
||||
|
||||
@ -251,6 +183,26 @@ test("getInputAsInt throws if required and value missing", () => {
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test("getInputAsBool returns false if input not set", () => {
|
||||
expect(actionUtils.getInputAsBool("undefined")).toBe(false);
|
||||
});
|
||||
|
||||
test("getInputAsBool returns value if input is valid", () => {
|
||||
testUtils.setInput("foo", "true");
|
||||
expect(actionUtils.getInputAsBool("foo")).toBe(true);
|
||||
});
|
||||
|
||||
test("getInputAsBool returns false if input is invalid or NaN", () => {
|
||||
testUtils.setInput("foo", "bar");
|
||||
expect(actionUtils.getInputAsBool("foo")).toBe(false);
|
||||
});
|
||||
|
||||
test("getInputAsBool throws if required and value missing", () => {
|
||||
expect(() =>
|
||||
actionUtils.getInputAsBool("undefined2", { required: true })
|
||||
).toThrowError();
|
||||
});
|
||||
|
||||
test("isCacheFeatureAvailable for ac enabled", () => {
|
||||
jest.spyOn(cache, "isFeatureAvailable").mockImplementation(() => true);
|
||||
|
||||
@ -288,3 +240,28 @@ test("isCacheFeatureAvailable for ac disabled on dotcom", () => {
|
||||
delete process.env["GITHUB_SERVER_URL"];
|
||||
}
|
||||
});
|
||||
|
||||
test("isGhes returns false when the GITHUB_SERVER_URL environment variable is not defined", async () => {
|
||||
delete process.env["GITHUB_SERVER_URL"];
|
||||
expect(actionUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
test("isGhes returns false when the GITHUB_SERVER_URL environment variable is set to github.com", async () => {
|
||||
process.env["GITHUB_SERVER_URL"] = "https://github.com";
|
||||
expect(actionUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
test("isGhes returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL", async () => {
|
||||
process.env["GITHUB_SERVER_URL"] = "https://contoso.ghe.com";
|
||||
expect(actionUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
test("isGhes returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix", async () => {
|
||||
process.env["GITHUB_SERVER_URL"] = "https://mock-github.localhost";
|
||||
expect(actionUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
test("isGhes returns true when the GITHUB_SERVER_URL environment variable is set to some other URL", async () => {
|
||||
process.env["GITHUB_SERVER_URL"] = "https://src.onpremise.fabrikam.com";
|
||||
expect(actionUtils.isGhes()).toBeTruthy();
|
||||
});
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, RefKey } from "../src/constants";
|
||||
import run from "../src/restore";
|
||||
import { Events, RefKey } from "../src/constants";
|
||||
import { restoreRun } from "../src/restoreImpl";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
@ -27,9 +27,17 @@ beforeAll(() => {
|
||||
return actualUtils.getInputAsArray(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsBool").mockImplementation(
|
||||
(name, options) => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.getInputAsBool(name, options);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
process.env[Events.Key] = Events.Push;
|
||||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
@ -45,164 +53,13 @@ afterEach(() => {
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("restore with invalid event outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const invalidEvent = "commit_comment";
|
||||
process.env[Events.Key] = invalidEvent;
|
||||
delete process.env[RefKey];
|
||||
await run();
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Event Validation Error: The event type ${invalidEvent} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
|
||||
await run();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
test("restore on GHES without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
|
||||
await run();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
test("restore on GHES with AC available ", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(key);
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore with no path should fail", async () => {
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await run();
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
// this input isn't necessary for restore b/c tarball contains entries relative to workspace
|
||||
expect(failedMock).not.toHaveBeenCalledWith(
|
||||
"Input required and not supplied: path"
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with no key", async () => {
|
||||
testUtils.setInput(Inputs.Path, "node_modules");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await run();
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
"Input required and not supplied: key"
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with too many keys should fail", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKeys = [...Array(20).keys()].map(x => x.toString());
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys
|
||||
});
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await run();
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, restoreKeys);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Key Validation Error: Keys are limited to a maximum of 10.`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with large key should fail", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "foo".repeat(512); // Over the 512 character limit
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key
|
||||
});
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await run();
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Key Validation Error: ${key} cannot be larger than 512 characters.`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with invalid key should fail", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "comma,comma";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key
|
||||
});
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await run();
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Key Validation Error: ${key} cannot contain commas.`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with no cache found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
@ -214,12 +71,22 @@ test("restore with no cache found", async () => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await run();
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
@ -234,7 +101,8 @@ test("restore with restore keys and no cache found", async () => {
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey]
|
||||
restoreKeys: [restoreKey],
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
@ -246,12 +114,22 @@ test("restore with restore keys and no cache found", async () => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await run();
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [restoreKey]);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
@ -264,27 +142,39 @@ test("restore with cache found for key", async () => {
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(key);
|
||||
});
|
||||
|
||||
await run();
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, []);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
|
||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(true);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
@ -297,30 +187,172 @@ test("restore with cache found for restore key", async () => {
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey]
|
||||
restoreKeys: [restoreKey],
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(actionUtils, "setCacheHitOutput");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(restoreKey);
|
||||
});
|
||||
|
||||
await run();
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith([path], key, [restoreKey]);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
|
||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith(false);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache restored from key: ${restoreKey}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("Fail restore when fail on cache miss is enabled and primary + restore keys not found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
failOnCacheMiss: true
|
||||
});
|
||||
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${key}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test("restore when fail on cache miss is enabled and primary key doesn't match restored key", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
failOnCacheMiss: true
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(restoreKey);
|
||||
});
|
||||
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", restoreKey);
|
||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache restored from key: ${restoreKey}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore with fail on cache miss disabled and no cache found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
failOnCacheMiss: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await restoreRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache not found for input keys: ${key}, ${restoreKey}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
467
__tests__/restoreImpl.test.ts
Normal file
467
__tests__/restoreImpl.test.ts
Normal file
@ -0,0 +1,467 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, RefKey } from "../src/constants";
|
||||
import { restoreImpl } from "../src/restoreImpl";
|
||||
import { StateProvider } from "../src/stateProvider";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
jest.mock("../src/utils/actionUtils");
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||
(key, cacheResult) => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.isExactKeyMatch(key, cacheResult);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.isValidEvent();
|
||||
});
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
|
||||
(name, options) => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.getInputAsArray(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsBool").mockImplementation(
|
||||
(name, options) => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.getInputAsBool(name, options);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
process.env[Events.Key] = Events.Push;
|
||||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => true
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
testUtils.clearInputs();
|
||||
delete process.env[Events.Key];
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("restore with invalid event outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const invalidEvent = "commit_comment";
|
||||
process.env[Events.Key] = invalidEvent;
|
||||
delete process.env[RefKey];
|
||||
await restoreImpl(new StateProvider());
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Event Validation Error: The event type ${invalidEvent} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||
});
|
||||
|
||||
test("restore on GHES without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||
});
|
||||
|
||||
test("restore on GHES with AC available ", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(key);
|
||||
});
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore with no path should fail", async () => {
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await restoreImpl(new StateProvider());
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
// this input isn't necessary for restore b/c tarball contains entries relative to workspace
|
||||
expect(failedMock).not.toHaveBeenCalledWith(
|
||||
"Input required and not supplied: path"
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with no key", async () => {
|
||||
testUtils.setInput(Inputs.Path, "node_modules");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await restoreImpl(new StateProvider());
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
"Input required and not supplied: key"
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with too many keys should fail", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKeys = [...Array(20).keys()].map(x => x.toString());
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await restoreImpl(new StateProvider());
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
restoreKeys,
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Key Validation Error: Keys are limited to a maximum of 10.`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with large key should fail", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "foo".repeat(512); // Over the 512 character limit
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await restoreImpl(new StateProvider());
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Key Validation Error: ${key} cannot be larger than 512 characters.`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with invalid key should fail", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "comma,comma";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
await restoreImpl(new StateProvider());
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
`Key Validation Error: ${key} cannot contain commas.`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with no cache found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache not found for input keys: ${key}`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with restore keys and no cache found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache not found for input keys: ${key}, ${restoreKey}`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with cache found for key", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(key);
|
||||
});
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore with cache found for restore key", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(restoreKey);
|
||||
});
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache restored from key: ${restoreKey}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore with lookup-only set", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
lookupOnly: true
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const stateMock = jest.spyOn(core, "saveState");
|
||||
const setCacheHitOutputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(key);
|
||||
});
|
||||
|
||||
await restoreImpl(new StateProvider());
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: true
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_KEY", key);
|
||||
expect(stateMock).toHaveBeenCalledWith("CACHE_RESULT", key);
|
||||
expect(stateMock).toHaveBeenCalledTimes(2);
|
||||
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledTimes(1);
|
||||
expect(setCacheHitOutputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache found and can be restored from key: ${key}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore failure with earlyExit should call process exit", async () => {
|
||||
testUtils.setInput(Inputs.Path, "node_modules");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const restoreCacheMock = jest.spyOn(cache, "restoreCache");
|
||||
const processExitMock = jest.spyOn(process, "exit").mockImplementation();
|
||||
|
||||
// call restoreImpl with `earlyExit` set to true
|
||||
await restoreImpl(new StateProvider(), true);
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(failedMock).toHaveBeenCalledWith(
|
||||
"Input required and not supplied: key"
|
||||
);
|
||||
expect(processExitMock).toHaveBeenCalledWith(1);
|
||||
});
|
222
__tests__/restoreOnly.test.ts
Normal file
222
__tests__/restoreOnly.test.ts
Normal file
@ -0,0 +1,222 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, RefKey } from "../src/constants";
|
||||
import { restoreOnlyRun } from "../src/restoreImpl";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
jest.mock("../src/utils/actionUtils");
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||
(key, cacheResult) => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.isExactKeyMatch(key, cacheResult);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.isValidEvent();
|
||||
});
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
|
||||
(name, options) => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.getInputAsArray(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsBool").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsBool(name, options);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
process.env[Events.Key] = Events.Push;
|
||||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => true
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
testUtils.clearInputs();
|
||||
delete process.env[Events.Key];
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("restore with no cache found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const outputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await restoreOnlyRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||
expect(outputMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache not found for input keys: ${key}`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with restore keys and no cache found", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const outputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
|
||||
await restoreOnlyRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache not found for input keys: ${key}, ${restoreKey}`
|
||||
);
|
||||
});
|
||||
|
||||
test("restore with cache found for key", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const outputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(key);
|
||||
});
|
||||
|
||||
await restoreOnlyRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-hit", "true");
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-matched-key", key);
|
||||
|
||||
expect(outputMock).toHaveBeenCalledTimes(3);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(`Cache restored from key: ${key}`);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("restore with cache found for restore key", async () => {
|
||||
const path = "node_modules";
|
||||
const key = "node-test";
|
||||
const restoreKey = "node-";
|
||||
testUtils.setInputs({
|
||||
path: path,
|
||||
key,
|
||||
restoreKeys: [restoreKey],
|
||||
enableCrossOsArchive: false
|
||||
});
|
||||
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const outputMock = jest.spyOn(core, "setOutput");
|
||||
const restoreCacheMock = jest
|
||||
.spyOn(cache, "restoreCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(restoreKey);
|
||||
});
|
||||
|
||||
await restoreOnlyRun();
|
||||
|
||||
expect(restoreCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(restoreCacheMock).toHaveBeenCalledWith(
|
||||
[path],
|
||||
key,
|
||||
[restoreKey],
|
||||
{
|
||||
lookupOnly: false
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-primary-key", key);
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-hit", "false");
|
||||
expect(outputMock).toHaveBeenCalledWith("cache-matched-key", restoreKey);
|
||||
|
||||
expect(outputMock).toHaveBeenCalledTimes(3);
|
||||
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache restored from key: ${restoreKey}`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
@ -2,7 +2,7 @@ import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, RefKey } from "../src/constants";
|
||||
import run from "../src/save";
|
||||
import { saveRun } from "../src/saveImpl";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
@ -15,8 +15,8 @@ beforeAll(() => {
|
||||
return jest.requireActual("@actions/core").getInput(name, options);
|
||||
});
|
||||
|
||||
jest.spyOn(actionUtils, "getCacheState").mockImplementation(() => {
|
||||
return jest.requireActual("../src/utils/actionUtils").getCacheState();
|
||||
jest.spyOn(core, "getState").mockImplementation(name => {
|
||||
return jest.requireActual("@actions/core").getState(name);
|
||||
});
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
|
||||
@ -35,6 +35,14 @@ beforeAll(() => {
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsBool").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsBool(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||
(key, cacheResult) => {
|
||||
return jest
|
||||
@ -65,294 +73,6 @@ afterEach(() => {
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("save with invalid event outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const invalidEvent = "commit_comment";
|
||||
process.env[Events.Key] = invalidEvent;
|
||||
delete process.env[RefKey];
|
||||
await run();
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Event Validation Error: The event type ${invalidEvent} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with no primary key in state outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return "";
|
||||
});
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Error retrieving key from state.`
|
||||
);
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save on ghes without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save on GHES with AC available", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||
|
||||
const cacheId = 4;
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith([inputPath], primaryKey, {
|
||||
uploadChunkSize: 4000000
|
||||
});
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with exact match returns early", async () => {
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = primaryKey;
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with missing input outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
"Input required and not supplied: path"
|
||||
);
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with large cache outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Error(
|
||||
"Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
|
||||
);
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
"Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with reserve cache failure outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
const actualCache = jest.requireActual("@actions/cache");
|
||||
const error = new actualCache.ReserveCacheError(
|
||||
`Unable to reserve cache with key ${primaryKey}, another job may be creating this cache.`
|
||||
);
|
||||
throw error;
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Unable to reserve cache with key ${primaryKey}, another job may be creating this cache.`
|
||||
);
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with server error outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Error("HTTP Error Occurred");
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
expect.anything()
|
||||
);
|
||||
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(logWarningMock).toHaveBeenCalledWith("HTTP Error Occurred");
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with valid inputs uploads a cache", async () => {
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
@ -362,11 +82,11 @@ test("save with valid inputs uploads a cache", async () => {
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
return primaryKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
return savedCacheKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
@ -380,12 +100,17 @@ test("save with valid inputs uploads a cache", async () => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await run();
|
||||
await saveRun();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith([inputPath], primaryKey, {
|
||||
uploadChunkSize: 4000000
|
||||
});
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
{
|
||||
uploadChunkSize: 4000000
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
408
__tests__/saveImpl.test.ts
Normal file
408
__tests__/saveImpl.test.ts
Normal file
@ -0,0 +1,408 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, RefKey } from "../src/constants";
|
||||
import { saveImpl } from "../src/saveImpl";
|
||||
import { StateProvider } from "../src/stateProvider";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
jest.mock("@actions/core");
|
||||
jest.mock("@actions/cache");
|
||||
jest.mock("../src/utils/actionUtils");
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||
return jest.requireActual("@actions/core").getInput(name, options);
|
||||
});
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsArray(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsInt").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsInt(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsBool").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsBool(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||
(key, cacheResult) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.isExactKeyMatch(key, cacheResult);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.isValidEvent();
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
process.env[Events.Key] = Events.Push;
|
||||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => true
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
testUtils.clearInputs();
|
||||
delete process.env[Events.Key];
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("save with invalid event outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
const invalidEvent = "commit_comment";
|
||||
process.env[Events.Key] = invalidEvent;
|
||||
delete process.env[RefKey];
|
||||
await saveImpl(new StateProvider());
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Event Validation Error: The event type ${invalidEvent} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with no primary key in state outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const savedCacheKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return "";
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
});
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(`Key is not specified.`);
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save on ghes without AC available should no-op", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => false
|
||||
);
|
||||
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save on GHES with AC available", async () => {
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => true);
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||
|
||||
const cacheId = 4;
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
{
|
||||
uploadChunkSize: 4000000
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with exact match returns early", async () => {
|
||||
const infoMock = jest.spyOn(core, "info");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = primaryKey;
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(infoMock).toHaveBeenCalledWith(
|
||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with missing input outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
const saveCacheMock = jest.spyOn(cache, "saveCache");
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(0);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
"Input required and not supplied: path"
|
||||
);
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with large cache outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Error(
|
||||
"Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
|
||||
);
|
||||
});
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
expect.anything(),
|
||||
false
|
||||
);
|
||||
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
"Cache size of ~6144 MB (6442450944 B) is over the 5GB limit, not saving cache."
|
||||
);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with reserve cache failure outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
const actualCache = jest.requireActual("@actions/cache");
|
||||
const error = new actualCache.ReserveCacheError(
|
||||
`Unable to reserve cache with key ${primaryKey}, another job may be creating this cache.`
|
||||
);
|
||||
throw error;
|
||||
});
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
expect.anything(),
|
||||
false
|
||||
);
|
||||
|
||||
expect(logWarningMock).toHaveBeenCalledWith(
|
||||
`Unable to reserve cache with key ${primaryKey}, another job may be creating this cache.`
|
||||
);
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with server error outputs warning", async () => {
|
||||
const logWarningMock = jest.spyOn(actionUtils, "logWarning");
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
throw new Error("HTTP Error Occurred");
|
||||
});
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
expect.anything(),
|
||||
false
|
||||
);
|
||||
|
||||
expect(logWarningMock).toHaveBeenCalledTimes(1);
|
||||
expect(logWarningMock).toHaveBeenCalledWith("HTTP Error Occurred");
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save with valid inputs uploads a cache", async () => {
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
const savedCacheKey = "Linux-node-";
|
||||
|
||||
jest.spyOn(core, "getState")
|
||||
// Cache Entry State
|
||||
.mockImplementationOnce(() => {
|
||||
return savedCacheKey;
|
||||
})
|
||||
// Cache Key State
|
||||
.mockImplementationOnce(() => {
|
||||
return primaryKey;
|
||||
});
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||
|
||||
const cacheId = 4;
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await saveImpl(new StateProvider());
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
{
|
||||
uploadChunkSize: 4000000
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
139
__tests__/saveOnly.test.ts
Normal file
139
__tests__/saveOnly.test.ts
Normal file
@ -0,0 +1,139 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, RefKey } from "../src/constants";
|
||||
import { saveOnlyRun } from "../src/saveImpl";
|
||||
import * as actionUtils from "../src/utils/actionUtils";
|
||||
import * as testUtils from "../src/utils/testUtils";
|
||||
|
||||
jest.mock("@actions/core");
|
||||
jest.mock("@actions/cache");
|
||||
jest.mock("../src/utils/actionUtils");
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||
return jest.requireActual("@actions/core").getInput(name, options);
|
||||
});
|
||||
|
||||
jest.spyOn(core, "setOutput").mockImplementation((key, value) => {
|
||||
return jest.requireActual("@actions/core").getInput(key, value);
|
||||
});
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsArray").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsArray(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsInt").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsInt(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "getInputAsBool").mockImplementation(
|
||||
(name, options) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.getInputAsBool(name, options);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isExactKeyMatch").mockImplementation(
|
||||
(key, cacheResult) => {
|
||||
return jest
|
||||
.requireActual("../src/utils/actionUtils")
|
||||
.isExactKeyMatch(key, cacheResult);
|
||||
}
|
||||
);
|
||||
|
||||
jest.spyOn(actionUtils, "isValidEvent").mockImplementation(() => {
|
||||
const actualUtils = jest.requireActual("../src/utils/actionUtils");
|
||||
return actualUtils.isValidEvent();
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
process.env[Events.Key] = Events.Push;
|
||||
process.env[RefKey] = "refs/heads/feature-branch";
|
||||
|
||||
jest.spyOn(actionUtils, "isGhes").mockImplementation(() => false);
|
||||
jest.spyOn(actionUtils, "isCacheFeatureAvailable").mockImplementation(
|
||||
() => true
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
testUtils.clearInputs();
|
||||
delete process.env[Events.Key];
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("save with valid inputs uploads a cache", async () => {
|
||||
const failedMock = jest.spyOn(core, "setFailed");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Key, primaryKey);
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||
|
||||
const cacheId = 4;
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await saveOnlyRun();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
{
|
||||
uploadChunkSize: 4000000
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(failedMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("save failing logs the warning message", async () => {
|
||||
const warningMock = jest.spyOn(core, "warning");
|
||||
|
||||
const primaryKey = "Linux-node-bb828da54c148048dd17899ba9fda624811cfb43";
|
||||
|
||||
const inputPath = "node_modules";
|
||||
testUtils.setInput(Inputs.Key, primaryKey);
|
||||
testUtils.setInput(Inputs.Path, inputPath);
|
||||
testUtils.setInput(Inputs.UploadChunkSize, "4000000");
|
||||
|
||||
const cacheId = -1;
|
||||
const saveCacheMock = jest
|
||||
.spyOn(cache, "saveCache")
|
||||
.mockImplementationOnce(() => {
|
||||
return Promise.resolve(cacheId);
|
||||
});
|
||||
|
||||
await saveOnlyRun();
|
||||
|
||||
expect(saveCacheMock).toHaveBeenCalledTimes(1);
|
||||
expect(saveCacheMock).toHaveBeenCalledWith(
|
||||
[inputPath],
|
||||
primaryKey,
|
||||
{
|
||||
uploadChunkSize: 4000000
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
expect(warningMock).toHaveBeenCalledTimes(1);
|
||||
expect(warningMock).toHaveBeenCalledWith("Cache save failed.");
|
||||
});
|
89
__tests__/stateProvider.test.ts
Normal file
89
__tests__/stateProvider.test.ts
Normal file
@ -0,0 +1,89 @@
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, RefKey, State } from "../src/constants";
|
||||
import {
|
||||
IStateProvider,
|
||||
NullStateProvider,
|
||||
StateProvider
|
||||
} from "../src/stateProvider";
|
||||
|
||||
jest.mock("@actions/core");
|
||||
|
||||
beforeAll(() => {
|
||||
jest.spyOn(core, "getInput").mockImplementation((name, options) => {
|
||||
return jest.requireActual("@actions/core").getInput(name, options);
|
||||
});
|
||||
|
||||
jest.spyOn(core, "setOutput").mockImplementation((key, value) => {
|
||||
return jest.requireActual("@actions/core").setOutput(key, value);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env[Events.Key];
|
||||
delete process.env[RefKey];
|
||||
});
|
||||
|
||||
test("StateProvider saves states", async () => {
|
||||
const states = new Map<string, string>();
|
||||
const getStateMock = jest
|
||||
.spyOn(core, "getState")
|
||||
.mockImplementation(key => states.get(key) || "");
|
||||
|
||||
const saveStateMock = jest
|
||||
.spyOn(core, "saveState")
|
||||
.mockImplementation((key, value) => {
|
||||
states.set(key, value);
|
||||
});
|
||||
|
||||
const setOutputMock = jest
|
||||
.spyOn(core, "setOutput")
|
||||
.mockImplementation((key, value) => {
|
||||
return jest.requireActual("@actions/core").setOutput(key, value);
|
||||
});
|
||||
|
||||
const cacheMatchedKey = "node-cache";
|
||||
|
||||
const stateProvider: IStateProvider = new StateProvider();
|
||||
stateProvider.setState("stateKey", "stateValue");
|
||||
stateProvider.setState(State.CacheMatchedKey, cacheMatchedKey);
|
||||
const stateValue = stateProvider.getState("stateKey");
|
||||
const cacheStateValue = stateProvider.getCacheState();
|
||||
|
||||
expect(stateValue).toBe("stateValue");
|
||||
expect(cacheStateValue).toBe(cacheMatchedKey);
|
||||
expect(getStateMock).toHaveBeenCalledTimes(2);
|
||||
expect(saveStateMock).toHaveBeenCalledTimes(2);
|
||||
expect(setOutputMock).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test("NullStateProvider saves outputs", async () => {
|
||||
const getStateMock = jest
|
||||
.spyOn(core, "getState")
|
||||
.mockImplementation(name =>
|
||||
jest.requireActual("@actions/core").getState(name)
|
||||
);
|
||||
|
||||
const setOutputMock = jest
|
||||
.spyOn(core, "setOutput")
|
||||
.mockImplementation((key, value) => {
|
||||
return jest.requireActual("@actions/core").setOutput(key, value);
|
||||
});
|
||||
|
||||
const saveStateMock = jest
|
||||
.spyOn(core, "saveState")
|
||||
.mockImplementation((key, value) => {
|
||||
return jest.requireActual("@actions/core").saveState(key, value);
|
||||
});
|
||||
|
||||
const cacheMatchedKey = "node-cache";
|
||||
const nullStateProvider: IStateProvider = new NullStateProvider();
|
||||
nullStateProvider.setState(State.CacheMatchedKey, "outputValue");
|
||||
nullStateProvider.setState(State.CachePrimaryKey, cacheMatchedKey);
|
||||
nullStateProvider.getState("outputKey");
|
||||
nullStateProvider.getCacheState();
|
||||
|
||||
expect(getStateMock).toHaveBeenCalledTimes(0);
|
||||
expect(setOutputMock).toHaveBeenCalledTimes(2);
|
||||
expect(saveStateMock).toHaveBeenCalledTimes(0);
|
||||
});
|
26
action.yml
26
action.yml
@ -9,19 +9,39 @@ inputs:
|
||||
description: 'An explicit key for restoring and saving the cache'
|
||||
required: true
|
||||
restore-keys:
|
||||
description: 'An ordered list of keys to use for restoring stale cache if no cache hit occurred for key. Note `cache-hit` returns false in this case.'
|
||||
description: 'An ordered multiline string listing the prefix-matched keys, that are used for restoring stale cache if no cache hit occurred for key. Note `cache-hit` returns false in this case.'
|
||||
required: false
|
||||
upload-chunk-size:
|
||||
description: 'The chunk size used to split up large files during upload, in bytes'
|
||||
required: false
|
||||
enableCrossOsArchive:
|
||||
description: 'An optional boolean when enabled, allows windows runners to save or restore caches that can be restored or saved respectively on other platforms'
|
||||
default: 'false'
|
||||
required: false
|
||||
fail-on-cache-miss:
|
||||
description: 'Fail the workflow if cache entry is not found'
|
||||
default: 'false'
|
||||
required: false
|
||||
lookup-only:
|
||||
description: 'Check if a cache entry exists for the given input(s) (key, restore-keys) without downloading the cache'
|
||||
default: 'false'
|
||||
required: false
|
||||
save-always:
|
||||
description: 'Run the post step to save the cache even if another step before fails'
|
||||
default: 'false'
|
||||
required: false
|
||||
deprecationMessage: |
|
||||
save-always does not work as intended and will be removed in a future release.
|
||||
A separate `actions/cache/restore` step should be used instead.
|
||||
See https://github.com/actions/cache/tree/main/save#always-save-cache for more details.
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate an exact match was found for the primary key'
|
||||
runs:
|
||||
using: 'node16'
|
||||
using: 'node20'
|
||||
main: 'dist/restore/index.js'
|
||||
post: 'dist/save/index.js'
|
||||
post-if: 'success()'
|
||||
post-if: "success()"
|
||||
branding:
|
||||
icon: 'archive'
|
||||
color: 'gray-dark'
|
||||
|
289
caching-strategies.md
Normal file
289
caching-strategies.md
Normal file
@ -0,0 +1,289 @@
|
||||
# Caching Strategies
|
||||
|
||||
This document lists some of the strategies (and example workflows if possible) which can be used to ...
|
||||
|
||||
- use an effective cache key and/or path
|
||||
- solve some common use cases around saving and restoring caches
|
||||
- leverage the step inputs and outputs more effectively
|
||||
|
||||
## Choosing the right key
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
key: ${{ some-metadata }}-cache
|
||||
```
|
||||
|
||||
In your workflows, you can use different strategies to name your key depending on your use case so that the cache is scoped appropriately for your need. For example, you can have cache specific to OS, or based on the lockfile or commit SHA or even workflow run.
|
||||
|
||||
### Updating cache for any change in the dependencies
|
||||
|
||||
One of the most common use case is to use hash for lockfile as key. This way, same cache will be restored for a lockfile until there's a change in dependencies listed in lockfile.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: cache-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
### Using restore keys to download the closest matching cache
|
||||
|
||||
If cache is not found matching the primary key, restore keys can be used to download the closest matching cache that was recently created. This ensures that the build/install step will need to additionally fetch just a handful of newer dependencies, and hence saving build time.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: cache-npm-${{ hashFiles('**/lockfiles') }}
|
||||
restore-keys: |
|
||||
cache-npm-
|
||||
```
|
||||
|
||||
The restore keys can be provided as a complete name, or a prefix, read more [here](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key) on how a cache key is matched using restore keys.
|
||||
|
||||
### Separate caches by Operating System
|
||||
|
||||
In case of workflows with matrix running for multiple Operating Systems, the caches can be stored separately for each of them. This can be used in combination with hashfiles in case multiple caches are being generated per OS.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: ${{ runner.os }}-cache
|
||||
```
|
||||
|
||||
### Creating a short lived cache
|
||||
|
||||
Caches scoped to the particular workflow run id or run attempt can be stored and referred by using the run id/attempt. This is an effective way to have a short lived cache.
|
||||
|
||||
```yaml
|
||||
key: cache-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
```
|
||||
|
||||
On similar lines, commit sha can be used to create a very specialized and short lived cache.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: cache-${{ github.sha }}
|
||||
```
|
||||
|
||||
### Using multiple factors while forming a key depending on the need
|
||||
|
||||
Cache key can be formed by combination of more than one metadata, evaluated info.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
The [GitHub Context](https://docs.github.com/en/actions/learn-github-actions/contexts#github-context) can be used to create keys using the workflows metadata.
|
||||
|
||||
## Restoring Cache
|
||||
|
||||
### Understanding how to choose path
|
||||
|
||||
While setting paths for caching dependencies it is important to give correct path depending on the hosted runner you are using or whether the action is running in a container job. Assigning different `path` for save and restore will result in cache miss.
|
||||
|
||||
Below are GitHub hosted runner specific paths one should take care of when writing a workflow which saves/restores caches across OS.
|
||||
|
||||
#### Ubuntu Paths
|
||||
|
||||
Home directory (`~/`) = `/home/runner`
|
||||
|
||||
`${{ github.workspace }}` = `/home/runner/work/repo/repo`
|
||||
|
||||
`process.env['RUNNER_TEMP']`=`/home/runner/work/_temp`
|
||||
|
||||
`process.cwd()` = `/home/runner/work/repo/repo`
|
||||
|
||||
#### Windows Paths
|
||||
|
||||
Home directory (`~/`) = `C:\Users\runneradmin`
|
||||
|
||||
`${{ github.workspace }}` = `D:\a\repo\repo`
|
||||
|
||||
`process.env['RUNNER_TEMP']` = `D:\a\_temp`
|
||||
|
||||
`process.cwd()` = `D:\a\repo\repo`
|
||||
|
||||
#### macOS Paths
|
||||
|
||||
Home directory (`~/`) = `/Users/runner`
|
||||
|
||||
`${{ github.workspace }}` = `/Users/runner/work/repo/repo`
|
||||
|
||||
`process.env['RUNNER_TEMP']` = `/Users/runner/work/_temp`
|
||||
|
||||
`process.cwd()` = `/Users/runner/work/repo/repo`
|
||||
|
||||
Where:
|
||||
|
||||
`cwd()` = Current working directory where the repository code resides.
|
||||
|
||||
`RUNNER_TEMP` = Environment variable defined for temporary storage location.
|
||||
|
||||
### Make cache read only / Reuse cache from centralized job
|
||||
|
||||
In case you are using a centralized job to create and save your cache that can be reused by other jobs in your repository, this action will take care of your restore only needs and make the cache read-only.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: /install.sh
|
||||
|
||||
- name: Build
|
||||
run: /build.sh
|
||||
|
||||
- name: Publish package to public
|
||||
run: /publish.sh
|
||||
```
|
||||
|
||||
### Failing/Exiting the workflow if cache with exact key is not found
|
||||
|
||||
You can use the output of this action to exit the workflow on cache miss. This way you can restrict your workflow to only initiate the build when `cache-hit` occurs, in other words, cache with exact key is found.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
- name: Check cache hit
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: exit 1
|
||||
|
||||
- name: Build
|
||||
run: /build.sh
|
||||
```
|
||||
|
||||
## Saving cache
|
||||
|
||||
### Reusing primary key from restore cache as input to save action
|
||||
|
||||
If you want to avoid re-computing the cache key again in `save` action, the outputs from `restore` action can be used as input to the `save` action.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache/restore@v4
|
||||
id: restore-cache
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
.
|
||||
.
|
||||
.
|
||||
- uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
```
|
||||
|
||||
### Re-evaluate cache key while saving cache
|
||||
|
||||
On the other hand, the key can also be explicitly re-computed while executing the save action. This helps in cases where the lockfiles are generated during the build.
|
||||
|
||||
Let's say we have a restore step that computes key at runtime
|
||||
|
||||
```yaml
|
||||
uses: actions/cache/restore@v4
|
||||
id: restore-cache
|
||||
with:
|
||||
key: cache-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
Case 1: Where an user would want to reuse the key as it is
|
||||
|
||||
```yaml
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
```
|
||||
|
||||
Case 2: Where the user would want to re-evaluate the key
|
||||
|
||||
```yaml
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: npm-cache-${{hashfiles(package-lock.json)}}
|
||||
```
|
||||
|
||||
### Saving cache even if the build fails
|
||||
|
||||
See [Always save cache](./save/README.md#always-save-cache).
|
||||
|
||||
### Saving cache once and reusing in multiple workflows
|
||||
|
||||
In case of multi-module projects, where the built artifact of one project needs to be reused in subsequent child modules, the need of rebuilding the parent module again and again with every build can be eliminated. The `actions/cache` or `actions/cache/save` action can be used to build and save the parent module artifact once, and restored multiple times while building the child modules.
|
||||
|
||||
#### Step 1 - Build the parent module and save it
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
run: ./build-parent-module.sh
|
||||
|
||||
- uses: actions/cache/save@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
#### Step 2 - Restore the built artifact from cache using the same key and path
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: ./install.sh
|
||||
|
||||
- name: Build
|
||||
run: ./build-child-module.sh
|
||||
|
||||
- name: Publish package to public
|
||||
run: ./publish.sh
|
||||
```
|
65475
dist/restore-only/index.js
vendored
Normal file
65475
dist/restore-only/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
64450
dist/restore/index.js
vendored
64450
dist/restore/index.js
vendored
File diff suppressed because one or more lines are too long
65488
dist/save-only/index.js
vendored
Normal file
65488
dist/save-only/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
64462
dist/save/index.js
vendored
64462
dist/save/index.js
vendored
File diff suppressed because one or more lines are too long
167
examples.md
167
examples.md
@ -1,5 +1,6 @@
|
||||
# Examples
|
||||
|
||||
- [Bun](#bun)
|
||||
- [C# - NuGet](#c---nuget)
|
||||
- [Clojure - Lein Deps](#clojure---lein-deps)
|
||||
- [D - DUB](#d---dub)
|
||||
@ -38,13 +39,35 @@
|
||||
- [Swift, Objective-C - Carthage](#swift-objective-c---carthage)
|
||||
- [Swift, Objective-C - CocoaPods](#swift-objective-c---cocoapods)
|
||||
- [Swift - Swift Package Manager](#swift---swift-package-manager)
|
||||
- [Swift - Mint](#swift---mint)
|
||||
- [* - Bazel](#---bazel)
|
||||
|
||||
## Bun
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.bun/install/cache
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~\.bun
|
||||
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
|
||||
```
|
||||
|
||||
## C# - NuGet
|
||||
|
||||
Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/package-references-in-project-files#locking-dependencies):
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
@ -53,10 +76,10 @@ Using [NuGet lock files](https://docs.microsoft.com/nuget/consume-packages/packa
|
||||
```
|
||||
|
||||
Depending on the environment, huge packages might be pre-installed in the global cache folder.
|
||||
With `actions/cache@v3` you can now exclude unwanted packages with [exclude pattern](https://github.com/actions/toolkit/tree/main/packages/glob#exclude-patterns)
|
||||
With `actions/cache@v4` you can now exclude unwanted packages with [exclude pattern](https://github.com/actions/toolkit/tree/main/packages/glob#exclude-patterns)
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.nuget/packages
|
||||
@ -67,13 +90,13 @@ With `actions/cache@v3` you can now exclude unwanted packages with [exclude patt
|
||||
```
|
||||
|
||||
Or you could move the cache folder like below.
|
||||
>Note: This workflow does not work for projects that require files to be placed in user profile package folder
|
||||
> **Note** This workflow does not work for projects that require files to be placed in user profile package folder
|
||||
|
||||
```yaml
|
||||
env:
|
||||
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
|
||||
steps:
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
|
||||
@ -85,7 +108,7 @@ steps:
|
||||
|
||||
```yaml
|
||||
- name: Cache lein project dependencies
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-clojure-${{ hashFiles('**/project.clj') }}
|
||||
@ -99,7 +122,7 @@ steps:
|
||||
### POSIX
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.dub
|
||||
key: ${{ runner.os }}-dub-${{ hashFiles('**/dub.selections.json') }}
|
||||
@ -110,7 +133,7 @@ steps:
|
||||
### Windows
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~\AppData\Local\dub
|
||||
key: ${{ runner.os }}-dub-${{ hashFiles('**/dub.selections.json') }}
|
||||
@ -123,7 +146,7 @@ steps:
|
||||
### Linux
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.deno
|
||||
@ -134,7 +157,7 @@ steps:
|
||||
### macOS
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.deno
|
||||
@ -145,7 +168,7 @@ steps:
|
||||
### Windows
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~\.deno
|
||||
@ -156,7 +179,7 @@ steps:
|
||||
## Elixir - Mix
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
deps
|
||||
@ -183,7 +206,7 @@ steps:
|
||||
### Linux
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
@ -196,7 +219,7 @@ steps:
|
||||
### macOS
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/Library/Caches/go-build
|
||||
@ -209,7 +232,7 @@ steps:
|
||||
### Windows
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~\AppData\Local\go-build
|
||||
@ -225,7 +248,7 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
||||
|
||||
```yaml
|
||||
- name: Cache ~/.cabal/packages, ~/.cabal/store and dist-newstyle
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cabal/packages
|
||||
@ -240,14 +263,14 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
||||
### Linux or macOS
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
name: Cache ~/.stack
|
||||
with:
|
||||
path: ~/.stack
|
||||
key: ${{ runner.os }}-stack-global-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-global-
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
name: Cache .stack-work
|
||||
with:
|
||||
path: .stack-work
|
||||
@ -259,7 +282,7 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
||||
### Windows
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
name: Cache %APPDATA%\stack %LOCALAPPDATA%\Programs\stack
|
||||
with:
|
||||
path: |
|
||||
@ -268,7 +291,7 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
||||
key: ${{ runner.os }}-stack-global-${{ hashFiles('stack.yaml') }}-${{ hashFiles('package.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-stack-global-
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
name: Cache .stack-work
|
||||
with:
|
||||
path: .stack-work
|
||||
@ -279,10 +302,10 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
||||
|
||||
## Java - Gradle
|
||||
|
||||
>Note: Ensure no Gradle daemons are running anymore when your workflow completes. Creating the cache package might fail due to locks being held by Gradle. Refer to the [Gradle Daemon documentation](https://docs.gradle.org/current/userguide/gradle_daemon.html) on how to disable or stop the Gradle Daemons.
|
||||
> **Note** Ensure no Gradle daemons are running anymore when your workflow completes. Creating the cache package might fail due to locks being held by Gradle. Refer to the [Gradle Daemon documentation](https://docs.gradle.org/current/userguide/gradle_daemon.html) on how to disable or stop the Gradle Daemons.
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@ -296,7 +319,7 @@ We cache the elements of the Cabal store separately, as the entirety of `~/.caba
|
||||
|
||||
```yaml
|
||||
- name: Cache local Maven repository
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
@ -311,7 +334,7 @@ For npm, cache files are stored in `~/.npm` on Posix, or `~\AppData\npm-cache` o
|
||||
If using `npm config` to retrieve the cache directory, ensure you run [actions/setup-node](https://github.com/actions/setup-node) first to ensure your `npm` version is correct.
|
||||
After [deprecation](https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/) of save-state and set-output commands, the correct way to set output is using `${GITHUB_OUTPUT}`. For linux, we can use `${GITHUB_OUTPUT}` whereas for windows we need to use `${env:GITHUB_OUTPUT}` due to two different default shells in these two different OS ie `bash` and `pwsh` respectively.
|
||||
|
||||
>Note: It is not recommended to cache `node_modules`, as it can break across Node versions and won't work with `npm ci`
|
||||
> **Note** It is not recommended to cache `node_modules`, as it can break across Node versions and won't work with `npm ci`
|
||||
|
||||
### **Get npm cache directory using same shell**
|
||||
### Bash shell
|
||||
@ -332,7 +355,7 @@ After [deprecation](https://github.blog/changelog/2022-10-11-github-actions-depr
|
||||
`Get npm cache directory` step can then be used with `actions/cache` as shown below
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
id: npm-cache # use this to check for `cache-hit` ==> if: steps.npm-cache.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir.outputs.dir }}
|
||||
@ -345,7 +368,7 @@ After [deprecation](https://github.blog/changelog/2022-10-11-github-actions-depr
|
||||
|
||||
```yaml
|
||||
- name: restore lerna
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
|
||||
@ -357,9 +380,9 @@ The yarn cache directory will depend on your operating system and version of `ya
|
||||
```yaml
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
@ -375,9 +398,9 @@ The yarn 2 cache directory will depend on your config. See https://yarnpkg.com/c
|
||||
```yaml
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
|
||||
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
@ -392,7 +415,7 @@ Esy allows you to export built dependencies and import pre-built dependencies.
|
||||
```yaml
|
||||
- name: Restore Cache
|
||||
id: restore-cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: _export
|
||||
key: ${{ runner.os }}-esy-${{ hashFiles('esy.lock/index.json') }}
|
||||
@ -420,8 +443,8 @@ Esy allows you to export built dependencies and import pre-built dependencies.
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
- uses: actions/cache@v3
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
@ -442,7 +465,7 @@ Locations:
|
||||
### Simple example
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
@ -455,7 +478,7 @@ Replace `~/.cache/pip` with the correct `path` if not using Ubuntu.
|
||||
### Multiple OS's in a workflow
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
if: startsWith(runner.os, 'Linux')
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
@ -463,7 +486,7 @@ Replace `~/.cache/pip` with the correct `path` if not using Ubuntu.
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
if: startsWith(runner.os, 'macOS')
|
||||
with:
|
||||
path: ~/Library/Caches/pip
|
||||
@ -471,7 +494,7 @@ Replace `~/.cache/pip` with the correct `path` if not using Ubuntu.
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
if: startsWith(runner.os, 'Windows')
|
||||
with:
|
||||
path: ~\AppData\Local\pip\Cache
|
||||
@ -497,7 +520,7 @@ jobs:
|
||||
- os: windows-latest
|
||||
path: ~\AppData\Local\pip\Cache
|
||||
steps:
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ matrix.path }}
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
@ -507,15 +530,16 @@ jobs:
|
||||
|
||||
### Using pip to get cache location
|
||||
|
||||
> Note: This requires pip 20.1+
|
||||
> **Note** This requires pip 20.1+
|
||||
```yaml
|
||||
- name: Get pip cache dir
|
||||
id: pip-cache
|
||||
shell: bash
|
||||
run: |
|
||||
echo "::set-output name=dir::$(pip cache dir)"
|
||||
echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: pip cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.pip-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
@ -533,7 +557,7 @@ jobs:
|
||||
|
||||
⋮
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.local/share/virtualenvs
|
||||
key: ${{ runner.os }}-python-${{ steps.setup-python.outputs.python-version }}-pipenv-${{ hashFiles('Pipfile.lock') }}
|
||||
@ -560,7 +584,7 @@ For renv, the cache directory will vary by OS. The `RENV_PATHS_ROOT` environment
|
||||
cat("##[set-output name=r-version;]", R.Version()$version.string, sep = "")
|
||||
shell: Rscript {0}
|
||||
- name: Restore Renv package cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.RENV_PATHS_ROOT }}
|
||||
key: ${{ steps.get-version.outputs.os-version }}-${{ steps.get-version.outputs.r-version }}-${{ inputs.cache-version }}-${{ hashFiles('renv.lock') }}
|
||||
@ -586,7 +610,7 @@ whenever possible:
|
||||
## Rust - Cargo
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/bin/
|
||||
@ -601,7 +625,7 @@ whenever possible:
|
||||
|
||||
```yaml
|
||||
- name: Cache SBT
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.ivy2/cache
|
||||
@ -612,7 +636,7 @@ whenever possible:
|
||||
## Swift, Objective-C - Carthage
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: Carthage
|
||||
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
|
||||
@ -623,7 +647,7 @@ whenever possible:
|
||||
## Swift, Objective-C - CocoaPods
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: Pods
|
||||
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
|
||||
@ -634,10 +658,57 @@ whenever possible:
|
||||
## Swift - Swift Package Manager
|
||||
|
||||
```yaml
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: .build
|
||||
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-spm-
|
||||
```
|
||||
|
||||
## Swift - Mint
|
||||
|
||||
```yaml
|
||||
env:
|
||||
MINT_PATH: .mint/lib
|
||||
MINT_LINK_PATH: .mint/bin
|
||||
steps:
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: .mint
|
||||
key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-mint-
|
||||
```
|
||||
|
||||
## * - Bazel
|
||||
|
||||
[`bazelisk`](https://github.com/bazelbuild/bazelisk) does not have be to separately downloaded and installed because it's already included in GitHub's `ubuntu-latest` and `macos-latest` base images.
|
||||
|
||||
### Linux
|
||||
|
||||
```yaml
|
||||
- name: Cache Bazel
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/bazel
|
||||
key: ${{ runner.os }}-bazel-${{ hashFiles('.bazelversion', '.bazelrc', 'WORKSPACE', 'WORKSPACE.bazel', 'MODULE.bazel') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bazel-
|
||||
- run: bazelisk test //...
|
||||
```
|
||||
|
||||
### macOS
|
||||
|
||||
```yaml
|
||||
- name: Cache Bazel
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
/private/var/tmp/_bazel_runner/
|
||||
key: ${{ runner.os }}-bazel-${{ hashFiles('.bazelversion', '.bazelrc', 'WORKSPACE', 'WORKSPACE.bazel', 'MODULE.bazel') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-bazel-
|
||||
- run: bazelisk test //...
|
||||
```
|
||||
|
1773
package-lock.json
generated
1773
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "cache",
|
||||
"version": "3.0.11",
|
||||
"version": "4.2.3",
|
||||
"private": true,
|
||||
"description": "Cache dependencies and build outputs",
|
||||
"main": "dist/restore/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts",
|
||||
"build": "tsc && ncc build -o dist/restore src/restore.ts && ncc build -o dist/save src/save.ts && ncc build -o dist/restore-only src/restoreOnly.ts && ncc build -o dist/save-only src/saveOnly.ts",
|
||||
"test": "tsc --noEmit && jest --coverage",
|
||||
"lint": "eslint **/*.ts --cache",
|
||||
"format": "prettier --write **/*.ts",
|
||||
@ -23,10 +23,10 @@
|
||||
"author": "GitHub",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.0.5",
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/cache": "^4.0.3",
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/io": "^1.1.2"
|
||||
"@actions/io": "^1.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.5.2",
|
||||
@ -34,7 +34,7 @@
|
||||
"@types/node": "^16.18.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"@vercel/ncc": "^0.38.3",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
|
135
restore/README.md
Normal file
135
restore/README.md
Normal file
@ -0,0 +1,135 @@
|
||||
# Restore action
|
||||
|
||||
The restore action restores a cache. It works similarly to the `cache` action except that it doesn't have a post step to save the cache. This action provides granular ability to restore a cache without having to save it. It accepts the same set of inputs as the `cache` action.
|
||||
|
||||
## Documentation
|
||||
|
||||
### Inputs
|
||||
|
||||
* `key` - An explicit key for a cache entry. See [creating a cache key](../README.md#creating-a-cache-key).
|
||||
* `path` - A list of files, directories, and wildcard patterns to restore. See [`@actions/glob`](https://github.com/actions/toolkit/tree/main/packages/glob) for supported patterns.
|
||||
* `restore-keys` - An ordered list of prefix-matched keys to use for restoring stale cache if no cache hit occurred for key.
|
||||
* `fail-on-cache-miss` - Fail the workflow if cache entry is not found. Default: `false`
|
||||
* `lookup-only` - If true, only checks if cache entry exists and skips download. Default: `false`
|
||||
|
||||
### Outputs
|
||||
|
||||
* `cache-hit` - A boolean value to indicate an exact match was found for the key.
|
||||
* `cache-primary-key` - Cache primary key passed in the input to use in subsequent steps of the workflow.
|
||||
* `cache-matched-key` - Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys.
|
||||
|
||||
> **Note**
|
||||
`cache-hit` will be set to `true` only when cache hit occurs for the exact `key` match. For a partial key match via `restore-keys` or a cache miss, it will be set to `false`.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
* `SEGMENT_DOWNLOAD_TIMEOUT_MINS` - Segment download timeout (in minutes, default `10`) to abort download of the segment if not completed in the defined number of minutes. [Read more](https://github.com/actions/cache/blob/main/tips-and-workarounds.md#cache-segment-restore-timeout)
|
||||
|
||||
## Use cases
|
||||
|
||||
As this is a newly introduced action to give users more control in their workflows, below are some use cases where one can use this action.
|
||||
|
||||
### Only restore cache
|
||||
|
||||
If you are using separate jobs to create and save your cache(s) to be reused by other jobs in a repository, this action will take care of your cache restoring needs.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: /install.sh
|
||||
|
||||
- name: Build
|
||||
run: /build.sh
|
||||
|
||||
- name: Publish package to public
|
||||
run: /publish.sh
|
||||
```
|
||||
|
||||
Once the cache is restored, unlike `actions/cache`, this action won't run a post step to do post-processing, and the rest of the workflow will run as usual.
|
||||
|
||||
### Save intermediate private build artifacts
|
||||
|
||||
In case of multi-module projects, where the built artifact of one project needs to be reused in subsequent child modules, the need to rebuild the parent module again and again with every build can be eliminated. The `actions/cache` or `actions/cache/save` action can be used to build and save the parent module artifact once, and it can be restored multiple times while building the child modules.
|
||||
|
||||
#### Step 1 - Build the parent module and save it
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Build
|
||||
run: /build-parent-module.sh
|
||||
|
||||
- uses: actions/cache/save@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
#### Step 2 - Restore the built artifact from cache using the same key and path
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
- name: Install Dependencies
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: /install.sh
|
||||
|
||||
- name: Build
|
||||
run: /build-child-module.sh
|
||||
|
||||
- name: Publish package to public
|
||||
run: /publish.sh
|
||||
```
|
||||
|
||||
### Exit workflow on cache miss
|
||||
|
||||
You can use `fail-on-cache-miss: true` to exit a workflow on a cache miss. This way you can restrict your workflow to only build when there is a `cache-hit`.
|
||||
|
||||
To fail if there is no cache hit for the primary key, leave `restore-keys` empty!
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
fail-on-cache-miss: true
|
||||
|
||||
- name: Build
|
||||
run: /build.sh
|
||||
```
|
||||
|
||||
## Tips
|
||||
|
||||
### Reusing primary key and restored key in the save action
|
||||
|
||||
Usually you may want to use the same `key` with both `actions/cache/restore` and `actions/cache/save` actions. To achieve this, use `outputs` from the `restore` action to reuse the same primary key (or the key of the cache that was restored).
|
||||
|
||||
### Using restore action outputs to make save action behave just like the cache action
|
||||
|
||||
The outputs `cache-primary-key` and `cache-matched-key` can be used to check if the restored cache is same as the given primary key. Alternatively, the `cache-hit` output can also be used to check if the restored was a complete match or a partially restored cache.
|
||||
|
||||
### Ensuring proper restores and save happen across the actions
|
||||
|
||||
It is very important to use the same `key` and `path` that were used by either `actions/cache` or `actions/cache/save` while saving the cache. Learn more about cache key [naming](https://github.com/actions/cache#creating-a-cache-key) and [versioning](https://github.com/actions/cache#cache-version) here.
|
38
restore/action.yml
Normal file
38
restore/action.yml
Normal file
@ -0,0 +1,38 @@
|
||||
name: 'Restore Cache'
|
||||
description: 'Restore Cache artifacts like dependencies and build outputs to improve workflow execution time'
|
||||
author: 'GitHub'
|
||||
inputs:
|
||||
path:
|
||||
description: 'A list of files, directories, and wildcard patterns to restore'
|
||||
required: true
|
||||
key:
|
||||
description: 'An explicit key for restoring the cache'
|
||||
required: true
|
||||
restore-keys:
|
||||
description: 'An ordered multiline string listing the prefix-matched keys, that are used for restoring stale cache if no cache hit occurred for key. Note `cache-hit` returns false in this case.'
|
||||
required: false
|
||||
enableCrossOsArchive:
|
||||
description: 'An optional boolean when enabled, allows windows runners to restore caches that were saved on other platforms'
|
||||
default: 'false'
|
||||
required: false
|
||||
fail-on-cache-miss:
|
||||
description: 'Fail the workflow if cache entry is not found'
|
||||
default: 'false'
|
||||
required: false
|
||||
lookup-only:
|
||||
description: 'Check if a cache entry exists for the given input(s) (key, restore-keys) without downloading the cache'
|
||||
default: 'false'
|
||||
required: false
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate an exact match was found for the primary key'
|
||||
cache-primary-key:
|
||||
description: 'A resolved cache key for which cache match was attempted'
|
||||
cache-matched-key:
|
||||
description: 'Key of the cache that was restored, it could either be the primary key on cache-hit or a partial/complete match of one of the restore keys'
|
||||
runs:
|
||||
using: 'node20'
|
||||
main: '../dist/restore-only/index.js'
|
||||
branding:
|
||||
icon: 'archive'
|
||||
color: 'gray-dark'
|
116
save/README.md
Normal file
116
save/README.md
Normal file
@ -0,0 +1,116 @@
|
||||
# Save action
|
||||
|
||||
The save action saves a cache. It works similarly to the `cache` action except that it doesn't first do a restore. This action provides granular ability to save a cache without having to restore it, or to do a save at any stage of the workflow job -- not only in post phase.
|
||||
|
||||
## Documentation
|
||||
|
||||
### Inputs
|
||||
|
||||
* `key` - An explicit key for a cache entry. See [creating a cache key](../README.md#creating-a-cache-key).
|
||||
* `path` - A list of files, directories, and wildcard patterns to cache. See [`@actions/glob`](https://github.com/actions/toolkit/tree/main/packages/glob) for supported patterns.
|
||||
* `upload-chunk-size` - The chunk size used to split up large files during upload, in bytes
|
||||
|
||||
### Outputs
|
||||
|
||||
This action has no outputs.
|
||||
|
||||
## Use cases
|
||||
|
||||
|
||||
### Only save cache
|
||||
|
||||
If you are using separate jobs for generating common artifacts and sharing them across jobs, this action will take care of your cache saving needs.
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Dependencies
|
||||
run: /install.sh
|
||||
|
||||
- name: Build artifacts
|
||||
run: /build.sh
|
||||
|
||||
- uses: actions/cache/save@v4
|
||||
id: cache
|
||||
with:
|
||||
path: path/to/dependencies
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
### Re-evaluate cache key while saving
|
||||
|
||||
With this save action, the key can now be re-evaluated while executing the action. This helps in cases where lockfiles are generated during the build.
|
||||
|
||||
Let's say we have a restore step that computes a key at runtime.
|
||||
|
||||
#### Restore a cache
|
||||
|
||||
```yaml
|
||||
uses: actions/cache/restore@v4
|
||||
id: restore-cache
|
||||
with:
|
||||
key: cache-${{ hashFiles('**/lockfiles') }}
|
||||
```
|
||||
|
||||
#### Case 1 - Where a user would want to reuse the key as it is
|
||||
```yaml
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
|
||||
```
|
||||
|
||||
#### Case 2 - Where the user would want to re-evaluate the key
|
||||
|
||||
```yaml
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: npm-cache-${{hashfiles(package-lock.json)}}
|
||||
```
|
||||
|
||||
### Always save cache
|
||||
|
||||
There are instances where some flaky test cases would fail the entire workflow and users would get frustrated because the builds would run for hours and the cache couldn't be saved as the workflow failed in between.
|
||||
For such use-cases, users now have the ability to use the `actions/cache/save` action to save the cache by using an [`always()`](https://docs.github.com/actions/writing-workflows/choosing-what-your-workflow-does/expressions#always) condition.
|
||||
This way the cache will always be saved if generated, or a warning will be generated that nothing is found on the cache path. Users can also use the `if` condition to only execute the `actions/cache/save` action depending on the output of previous steps. This way they get more control of when to save the cache.
|
||||
|
||||
To avoid saving a cache that already exists, the `cache-hit` output from a restore step should be checked.
|
||||
|
||||
The `cache-primary-key` output from the restore step should also be used to ensure
|
||||
the cache key does not change during the build if it's calculated based on file contents.
|
||||
|
||||
Here's an example where we imagine we're calculating a lot of prime numbers and want to cache them:
|
||||
|
||||
```yaml
|
||||
name: Always Caching Prime Numbers
|
||||
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore cached Prime Numbers
|
||||
id: cache-prime-numbers-restore
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
key: ${{ runner.os }}-prime-numbers
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
|
||||
# Intermediate workflow steps
|
||||
|
||||
- name: Always Save Prime Numbers
|
||||
id: cache-prime-numbers-save
|
||||
if: always() && steps.cache-prime-numbers-restore.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
key: ${{ steps.cache-prime-numbers-restore.outputs.cache-primary-key }}
|
||||
path: |
|
||||
path/to/dependencies
|
||||
some/other/dependencies
|
||||
```
|
23
save/action.yml
Normal file
23
save/action.yml
Normal file
@ -0,0 +1,23 @@
|
||||
name: 'Save a cache'
|
||||
description: 'Save Cache artifacts like dependencies and build outputs to improve workflow execution time'
|
||||
author: 'GitHub'
|
||||
inputs:
|
||||
path:
|
||||
description: 'A list of files, directories, and wildcard patterns to cache'
|
||||
required: true
|
||||
key:
|
||||
description: 'An explicit key for saving the cache'
|
||||
required: true
|
||||
upload-chunk-size:
|
||||
description: 'The chunk size used to split up large files during upload, in bytes'
|
||||
required: false
|
||||
enableCrossOsArchive:
|
||||
description: 'An optional boolean when enabled, allows windows runners to save caches that can be restored on other platforms'
|
||||
default: 'false'
|
||||
required: false
|
||||
runs:
|
||||
using: 'node20'
|
||||
main: '../dist/save-only/index.js'
|
||||
branding:
|
||||
icon: 'archive'
|
||||
color: 'gray-dark'
|
@ -1,12 +1,17 @@
|
||||
export enum Inputs {
|
||||
Key = "key",
|
||||
Path = "path",
|
||||
RestoreKeys = "restore-keys",
|
||||
UploadChunkSize = "upload-chunk-size"
|
||||
Key = "key", // Input for cache, restore, save action
|
||||
Path = "path", // Input for cache, restore, save action
|
||||
RestoreKeys = "restore-keys", // Input for cache, restore action
|
||||
UploadChunkSize = "upload-chunk-size", // Input for cache, save action
|
||||
EnableCrossOsArchive = "enableCrossOsArchive", // Input for cache, restore, save action
|
||||
FailOnCacheMiss = "fail-on-cache-miss", // Input for cache, restore action
|
||||
LookupOnly = "lookup-only" // Input for cache, restore action
|
||||
}
|
||||
|
||||
export enum Outputs {
|
||||
CacheHit = "cache-hit"
|
||||
CacheHit = "cache-hit", // Output from cache, restore action
|
||||
CachePrimaryKey = "cache-primary-key", // Output from restore action
|
||||
CacheMatchedKey = "cache-matched-key" // Output from restore action
|
||||
}
|
||||
|
||||
export enum State {
|
||||
|
@ -1,62 +1,3 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
import { restoreRun } from "./restoreImpl";
|
||||
|
||||
import { Events, Inputs, State } from "./constants";
|
||||
import * as utils from "./utils/actionUtils";
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
if (!utils.isCacheFeatureAvailable()) {
|
||||
utils.setCacheHitOutput(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate inputs, this can cause task failure
|
||||
if (!utils.isValidEvent()) {
|
||||
utils.logWarning(
|
||||
`Event Validation Error: The event type ${
|
||||
process.env[Events.Key]
|
||||
} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const primaryKey = core.getInput(Inputs.Key, { required: true });
|
||||
core.saveState(State.CachePrimaryKey, primaryKey);
|
||||
|
||||
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
|
||||
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
||||
required: true
|
||||
});
|
||||
|
||||
const cacheKey = await cache.restoreCache(
|
||||
cachePaths,
|
||||
primaryKey,
|
||||
restoreKeys
|
||||
);
|
||||
|
||||
if (!cacheKey) {
|
||||
core.info(
|
||||
`Cache not found for input keys: ${[
|
||||
primaryKey,
|
||||
...restoreKeys
|
||||
].join(", ")}`
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the matched cache key
|
||||
utils.setCacheState(cacheKey);
|
||||
|
||||
const isExactKeyMatch = utils.isExactKeyMatch(primaryKey, cacheKey);
|
||||
utils.setCacheHitOutput(isExactKeyMatch);
|
||||
core.info(`Cache restored from key: ${cacheKey}`);
|
||||
} catch (error: unknown) {
|
||||
core.setFailed((error as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
|
||||
export default run;
|
||||
restoreRun(true);
|
||||
|
121
src/restoreImpl.ts
Normal file
121
src/restoreImpl.ts
Normal file
@ -0,0 +1,121 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, Outputs, State } from "./constants";
|
||||
import {
|
||||
IStateProvider,
|
||||
NullStateProvider,
|
||||
StateProvider
|
||||
} from "./stateProvider";
|
||||
import * as utils from "./utils/actionUtils";
|
||||
|
||||
export async function restoreImpl(
|
||||
stateProvider: IStateProvider,
|
||||
earlyExit?: boolean | undefined
|
||||
): Promise<string | undefined> {
|
||||
try {
|
||||
if (!utils.isCacheFeatureAvailable()) {
|
||||
core.setOutput(Outputs.CacheHit, "false");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate inputs, this can cause task failure
|
||||
if (!utils.isValidEvent()) {
|
||||
utils.logWarning(
|
||||
`Event Validation Error: The event type ${
|
||||
process.env[Events.Key]
|
||||
} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const primaryKey = core.getInput(Inputs.Key, { required: true });
|
||||
stateProvider.setState(State.CachePrimaryKey, primaryKey);
|
||||
|
||||
const restoreKeys = utils.getInputAsArray(Inputs.RestoreKeys);
|
||||
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
||||
required: true
|
||||
});
|
||||
const enableCrossOsArchive = utils.getInputAsBool(
|
||||
Inputs.EnableCrossOsArchive
|
||||
);
|
||||
const failOnCacheMiss = utils.getInputAsBool(Inputs.FailOnCacheMiss);
|
||||
const lookupOnly = utils.getInputAsBool(Inputs.LookupOnly);
|
||||
|
||||
const cacheKey = await cache.restoreCache(
|
||||
cachePaths,
|
||||
primaryKey,
|
||||
restoreKeys,
|
||||
{ lookupOnly: lookupOnly },
|
||||
enableCrossOsArchive
|
||||
);
|
||||
|
||||
if (!cacheKey) {
|
||||
// `cache-hit` is intentionally not set to `false` here to preserve existing behavior
|
||||
// See https://github.com/actions/cache/issues/1466
|
||||
|
||||
if (failOnCacheMiss) {
|
||||
throw new Error(
|
||||
`Failed to restore cache entry. Exiting as fail-on-cache-miss is set. Input key: ${primaryKey}`
|
||||
);
|
||||
}
|
||||
core.info(
|
||||
`Cache not found for input keys: ${[
|
||||
primaryKey,
|
||||
...restoreKeys
|
||||
].join(", ")}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Store the matched cache key in states
|
||||
stateProvider.setState(State.CacheMatchedKey, cacheKey);
|
||||
|
||||
const isExactKeyMatch = utils.isExactKeyMatch(
|
||||
core.getInput(Inputs.Key, { required: true }),
|
||||
cacheKey
|
||||
);
|
||||
|
||||
core.setOutput(Outputs.CacheHit, isExactKeyMatch.toString());
|
||||
if (lookupOnly) {
|
||||
core.info(`Cache found and can be restored from key: ${cacheKey}`);
|
||||
} else {
|
||||
core.info(`Cache restored from key: ${cacheKey}`);
|
||||
}
|
||||
|
||||
return cacheKey;
|
||||
} catch (error: unknown) {
|
||||
core.setFailed((error as Error).message);
|
||||
if (earlyExit) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function run(
|
||||
stateProvider: IStateProvider,
|
||||
earlyExit: boolean | undefined
|
||||
): Promise<void> {
|
||||
await restoreImpl(stateProvider, earlyExit);
|
||||
|
||||
// node will stay alive if any promises are not resolved,
|
||||
// which is a possibility if HTTP requests are dangling
|
||||
// due to retries or timeouts. We know that if we got here
|
||||
// that all promises that we care about have successfully
|
||||
// resolved, so simply exit with success.
|
||||
if (earlyExit) {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
export async function restoreOnlyRun(
|
||||
earlyExit?: boolean | undefined
|
||||
): Promise<void> {
|
||||
await run(new NullStateProvider(), earlyExit);
|
||||
}
|
||||
|
||||
export async function restoreRun(
|
||||
earlyExit?: boolean | undefined
|
||||
): Promise<void> {
|
||||
await run(new StateProvider(), earlyExit);
|
||||
}
|
3
src/restoreOnly.ts
Normal file
3
src/restoreOnly.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { restoreOnlyRun } from "./restoreImpl";
|
||||
|
||||
restoreOnlyRun(true);
|
62
src/save.ts
62
src/save.ts
@ -1,61 +1,3 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
import { saveRun } from "./saveImpl";
|
||||
|
||||
import { Events, Inputs, State } from "./constants";
|
||||
import * as utils from "./utils/actionUtils";
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
||||
process.on("uncaughtException", e => utils.logWarning(e.message));
|
||||
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
if (!utils.isCacheFeatureAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!utils.isValidEvent()) {
|
||||
utils.logWarning(
|
||||
`Event Validation Error: The event type ${
|
||||
process.env[Events.Key]
|
||||
} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const state = utils.getCacheState();
|
||||
|
||||
// Inputs are re-evaluted before the post action, so we want the original key used for restore
|
||||
const primaryKey = core.getState(State.CachePrimaryKey);
|
||||
if (!primaryKey) {
|
||||
utils.logWarning(`Error retrieving key from state.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (utils.isExactKeyMatch(primaryKey, state)) {
|
||||
core.info(
|
||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
||||
required: true
|
||||
});
|
||||
|
||||
const cacheId = await cache.saveCache(cachePaths, primaryKey, {
|
||||
uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize)
|
||||
});
|
||||
|
||||
if (cacheId != -1) {
|
||||
core.info(`Cache saved with key: ${primaryKey}`);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
utils.logWarning((error as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
|
||||
export default run;
|
||||
saveRun(true);
|
||||
|
124
src/saveImpl.ts
Normal file
124
src/saveImpl.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Events, Inputs, State } from "./constants";
|
||||
import {
|
||||
IStateProvider,
|
||||
NullStateProvider,
|
||||
StateProvider
|
||||
} from "./stateProvider";
|
||||
import * as utils from "./utils/actionUtils";
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
||||
process.on("uncaughtException", e => utils.logWarning(e.message));
|
||||
|
||||
export async function saveImpl(
|
||||
stateProvider: IStateProvider
|
||||
): Promise<number | void> {
|
||||
let cacheId = -1;
|
||||
try {
|
||||
if (!utils.isCacheFeatureAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!utils.isValidEvent()) {
|
||||
utils.logWarning(
|
||||
`Event Validation Error: The event type ${
|
||||
process.env[Events.Key]
|
||||
} is not supported because it's not tied to a branch or tag ref.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// If restore has stored a primary key in state, reuse that
|
||||
// Else re-evaluate from inputs
|
||||
const primaryKey =
|
||||
stateProvider.getState(State.CachePrimaryKey) ||
|
||||
core.getInput(Inputs.Key);
|
||||
|
||||
if (!primaryKey) {
|
||||
utils.logWarning(`Key is not specified.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// If matched restore key is same as primary key, then do not save cache
|
||||
// NO-OP in case of SaveOnly action
|
||||
const restoredKey = stateProvider.getCacheState();
|
||||
|
||||
if (utils.isExactKeyMatch(primaryKey, restoredKey)) {
|
||||
core.info(
|
||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const cachePaths = utils.getInputAsArray(Inputs.Path, {
|
||||
required: true
|
||||
});
|
||||
|
||||
const enableCrossOsArchive = utils.getInputAsBool(
|
||||
Inputs.EnableCrossOsArchive
|
||||
);
|
||||
|
||||
cacheId = await cache.saveCache(
|
||||
cachePaths,
|
||||
primaryKey,
|
||||
{ uploadChunkSize: utils.getInputAsInt(Inputs.UploadChunkSize) },
|
||||
enableCrossOsArchive
|
||||
);
|
||||
|
||||
if (cacheId != -1) {
|
||||
core.info(`Cache saved with key: ${primaryKey}`);
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
utils.logWarning((error as Error).message);
|
||||
}
|
||||
return cacheId;
|
||||
}
|
||||
|
||||
export async function saveOnlyRun(
|
||||
earlyExit?: boolean | undefined
|
||||
): Promise<void> {
|
||||
try {
|
||||
const cacheId = await saveImpl(new NullStateProvider());
|
||||
if (cacheId === -1) {
|
||||
core.warning(`Cache save failed.`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (earlyExit) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// node will stay alive if any promises are not resolved,
|
||||
// which is a possibility if HTTP requests are dangling
|
||||
// due to retries or timeouts. We know that if we got here
|
||||
// that all promises that we care about have successfully
|
||||
// resolved, so simply exit with success.
|
||||
if (earlyExit) {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveRun(earlyExit?: boolean | undefined): Promise<void> {
|
||||
try {
|
||||
await saveImpl(new StateProvider());
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
if (earlyExit) {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// node will stay alive if any promises are not resolved,
|
||||
// which is a possibility if HTTP requests are dangling
|
||||
// due to retries or timeouts. We know that if we got here
|
||||
// that all promises that we care about have successfully
|
||||
// resolved, so simply exit with success.
|
||||
if (earlyExit) {
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
3
src/saveOnly.ts
Normal file
3
src/saveOnly.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { saveOnlyRun } from "./saveImpl";
|
||||
|
||||
saveOnlyRun(true);
|
46
src/stateProvider.ts
Normal file
46
src/stateProvider.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Outputs, State } from "./constants";
|
||||
|
||||
export interface IStateProvider {
|
||||
setState(key: string, value: string): void;
|
||||
getState(key: string): string;
|
||||
|
||||
getCacheState(): string | undefined;
|
||||
}
|
||||
|
||||
class StateProviderBase implements IStateProvider {
|
||||
getCacheState(): string | undefined {
|
||||
const cacheKey = this.getState(State.CacheMatchedKey);
|
||||
if (cacheKey) {
|
||||
core.debug(`Cache state/key: ${cacheKey}`);
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
|
||||
setState = (key: string, value: string) => {};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
getState = (key: string) => "";
|
||||
}
|
||||
|
||||
export class StateProvider extends StateProviderBase {
|
||||
setState = core.saveState;
|
||||
getState = core.getState;
|
||||
}
|
||||
|
||||
export class NullStateProvider extends StateProviderBase {
|
||||
stateToOutputMap = new Map<string, string>([
|
||||
[State.CacheMatchedKey, Outputs.CacheMatchedKey],
|
||||
[State.CachePrimaryKey, Outputs.CachePrimaryKey]
|
||||
]);
|
||||
|
||||
setState = (key: string, value: string) => {
|
||||
core.setOutput(this.stateToOutputMap.get(key) as string, value);
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
getState = (key: string) => "";
|
||||
}
|
@ -1,13 +1,19 @@
|
||||
import * as cache from "@actions/cache";
|
||||
import * as core from "@actions/core";
|
||||
|
||||
import { Outputs, RefKey, State } from "../constants";
|
||||
import { RefKey } from "../constants";
|
||||
|
||||
export function isGhes(): boolean {
|
||||
const ghUrl = new URL(
|
||||
process.env["GITHUB_SERVER_URL"] || "https://github.com"
|
||||
);
|
||||
return ghUrl.hostname.toUpperCase() !== "GITHUB.COM";
|
||||
|
||||
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
|
||||
const isGitHubHost = hostname === "GITHUB.COM";
|
||||
const isGitHubEnterpriseCloudHost = hostname.endsWith(".GHE.COM");
|
||||
const isLocalHost = hostname.endsWith(".LOCALHOST");
|
||||
|
||||
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
|
||||
}
|
||||
|
||||
export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
|
||||
@ -19,30 +25,6 @@ export function isExactKeyMatch(key: string, cacheKey?: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
export function setCacheState(state: string): void {
|
||||
core.saveState(State.CacheMatchedKey, state);
|
||||
}
|
||||
|
||||
export function setCacheHitOutput(isCacheHit: boolean): void {
|
||||
core.setOutput(Outputs.CacheHit, isCacheHit.toString());
|
||||
}
|
||||
|
||||
export function setOutputAndState(key: string, cacheKey?: string): void {
|
||||
setCacheHitOutput(isExactKeyMatch(key, cacheKey));
|
||||
// Store the matched cache key if it exists
|
||||
cacheKey && setCacheState(cacheKey);
|
||||
}
|
||||
|
||||
export function getCacheState(): string | undefined {
|
||||
const cacheKey = core.getState(State.CacheMatchedKey);
|
||||
if (cacheKey) {
|
||||
core.debug(`Cache state/key: ${cacheKey}`);
|
||||
return cacheKey;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function logWarning(message: string): void {
|
||||
const warningPrefix = "[warning]";
|
||||
core.info(`${warningPrefix}${message}`);
|
||||
@ -76,6 +58,14 @@ export function getInputAsInt(
|
||||
return value;
|
||||
}
|
||||
|
||||
export function getInputAsBool(
|
||||
name: string,
|
||||
options?: core.InputOptions
|
||||
): boolean {
|
||||
const result = core.getInput(name, options);
|
||||
return result.toLowerCase() === "true";
|
||||
}
|
||||
|
||||
export function isCacheFeatureAvailable(): boolean {
|
||||
if (cache.isFeatureAvailable()) {
|
||||
return true;
|
||||
|
@ -13,6 +13,9 @@ interface CacheInput {
|
||||
path: string;
|
||||
key: string;
|
||||
restoreKeys?: string[];
|
||||
enableCrossOsArchive?: boolean;
|
||||
failOnCacheMiss?: boolean;
|
||||
lookupOnly?: boolean;
|
||||
}
|
||||
|
||||
export function setInputs(input: CacheInput): void {
|
||||
@ -20,6 +23,15 @@ export function setInputs(input: CacheInput): void {
|
||||
setInput(Inputs.Key, input.key);
|
||||
input.restoreKeys &&
|
||||
setInput(Inputs.RestoreKeys, input.restoreKeys.join("\n"));
|
||||
input.enableCrossOsArchive !== undefined &&
|
||||
setInput(
|
||||
Inputs.EnableCrossOsArchive,
|
||||
input.enableCrossOsArchive.toString()
|
||||
);
|
||||
input.failOnCacheMiss !== undefined &&
|
||||
setInput(Inputs.FailOnCacheMiss, input.failOnCacheMiss.toString());
|
||||
input.lookupOnly !== undefined &&
|
||||
setInput(Inputs.LookupOnly, input.lookupOnly.toString());
|
||||
}
|
||||
|
||||
export function clearInputs(): void {
|
||||
@ -27,4 +39,7 @@ export function clearInputs(): void {
|
||||
delete process.env[getInputName(Inputs.Key)];
|
||||
delete process.env[getInputName(Inputs.RestoreKeys)];
|
||||
delete process.env[getInputName(Inputs.UploadChunkSize)];
|
||||
delete process.env[getInputName(Inputs.EnableCrossOsArchive)];
|
||||
delete process.env[getInputName(Inputs.FailOnCacheMiss)];
|
||||
delete process.env[getInputName(Inputs.LookupOnly)];
|
||||
}
|
||||
|
@ -1,46 +1,44 @@
|
||||
# Tips and workarounds
|
||||
|
||||
## Cache segment restore timeout
|
||||
|
||||
A cache gets downloaded in multiple segments of fixed sizes (`1GB` for a `32-bit` runner and `2GB` for a `64-bit` runner). Sometimes, a segment download gets stuck which causes the workflow job to be stuck forever and fail. Version `v3.0.8` of `actions/cache` introduces a segment download timeout. The segment download timeout will allow the segment download to get aborted and hence allow the job to proceed with a cache miss.
|
||||
|
||||
Default value of this timeout is 60 minutes and can be customized by specifying an [environment variable](https://docs.github.com/en/actions/learn-github-actions/environment-variables) named `SEGMENT_DOWNLOAD_TIMEOUT_MINS` with timeout value in minutes.
|
||||
Default value of this timeout is 10 minutes and can be customized by specifying an [environment variable](https://docs.github.com/en/actions/learn-github-actions/environment-variables) named `SEGMENT_DOWNLOAD_TIMEOUT_MINS` with timeout value in minutes.
|
||||
|
||||
## Update a cache
|
||||
|
||||
A cache today is immutable and cannot be updated. But some use cases require the cache to be saved even though there was a "hit" during restore. To do so, use a `key` which is unique for every run and use `restore-keys` to restore the nearest cache. For example:
|
||||
|
||||
```yaml
|
||||
- name: update cache on every commit
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: prime-numbers
|
||||
key: primes-${{ runner.os }}-${{ github.run_id }} # Can use time based key as well
|
||||
restore-keys: |
|
||||
primes-${{ runner.os }}
|
||||
```
|
||||
```
|
||||
|
||||
Please note that this will create a new cache on every run and hence will consume the cache [quota](./README.md#cache-limits).
|
||||
|
||||
## Use cache across feature branches
|
||||
|
||||
Reusing cache across feature branches is not allowed today to provide cache [isolation](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache). However if both feature branches are from the default branch, a good way to achieve this is to ensure that the default branch has a cache. This cache will then be consumable by both feature branches.
|
||||
|
||||
## Improving cache restore performance on Windows/Using cross-os caching
|
||||
Currently, cache restore is slow on Windows due to tar being inherently slow and the compression algorithm `gzip` in use. `zstd` is the default algorithm in use on linux and macos. It was disabled on Windows due to issues with bsd tar(libarchive), the tar implementation in use on Windows.
|
||||
## Cross OS cache
|
||||
|
||||
To improve cache restore performance, we can re-enable `zstd` as the compression algorithm using the following workaround. Add the following step to your workflow before the cache step:
|
||||
From `v3.2.3` cache is cross-os compatible when `enableCrossOsArchive` input is passed as true. This means that a cache created on `ubuntu-latest` or `mac-latest` can be used by `windows-latest` and vice versa, provided the workflow which runs on `windows-latest` have input `enableCrossOsArchive` as true. This is useful to cache dependencies which are independent of the runner platform. This will help reduce the consumption of the cache quota and help build for multiple platforms from the same cache. Things to keep in mind while using this feature:
|
||||
|
||||
```yaml
|
||||
- if: ${{ runner.os == 'Windows' }}
|
||||
name: Use GNU tar
|
||||
shell: cmd
|
||||
run: |
|
||||
echo "Adding GNU tar to PATH"
|
||||
echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%"
|
||||
```
|
||||
|
||||
The `cache` action will use GNU tar instead of bsd tar on Windows. This should work on all Github Hosted runners as it is. For self-hosted runners, please ensure you have GNU tar and `zstd` installed.
|
||||
|
||||
The above workaround is also needed if you wish to use cross-os caching since difference of compression algorithms will result in different cache versions for the same cache key. So the above workaround will ensure `zstd` is used for caching on all platforms thus resulting in the same cache version for the same cache key.
|
||||
- Only cache files that are compatible across OSs.
|
||||
- Caching symlinks might cause issues while restoring them as they behave differently on different OSs.
|
||||
- Be mindful when caching files from outside your github workspace directory as the directory is located at different places across OS.
|
||||
- Avoid using directory pointers such as `${{ github.workspace }}` or `~` (home) which eventually evaluate to an absolute path that does not match across OSs.
|
||||
|
||||
## Force deletion of caches overriding default cache eviction policy
|
||||
Caches have [branch scope restriction](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache) in place. This means that if caches for a specific branch are using a lot of storage quota, it may result into more frequently used caches from `default` branch getting thrashed. For example, if there are many pull requests happening on a repo and are creating caches, these cannot be used in default branch scope but will still occupy a lot of space till they get cleaned up by [eviction policy](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy). But sometime we want to clean them up on a faster cadence so as to ensure default branch is not thrashing. In order to achieve this, [gh-actions-cache cli](https://github.com/actions/gh-actions-cache/) can be used to delete caches for specific branches.
|
||||
|
||||
This workflow uses `gh-actions-cache` to delete all the caches created by a branch.
|
||||
Caches have [branch scope restriction](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache) in place. This means that if caches for a specific branch are using a lot of storage quota, it may result into more frequently used caches from `default` branch getting thrashed. For example, if there are many pull requests happening on a repo and are creating caches, these cannot be used in default branch scope but will still occupy a lot of space till they get cleaned up by [eviction policy](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy). But sometime we want to clean them up on a faster cadence so as to ensure default branch is not thrashing.
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
@ -55,29 +53,29 @@ on:
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# `actions:write` permission is required to delete caches
|
||||
# See also: https://docs.github.com/en/rest/actions/cache?apiVersion=2022-11-28#delete-a-github-actions-cache-for-a-repository-using-a-cache-id
|
||||
actions: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
REPO=${{ github.repository }}
|
||||
BRANCH=${{ github.ref }}
|
||||
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
||||
cacheKeysForPR=$(gh cache list --ref $BRANCH --limit 100 --json id --jq '.[].id')
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
gh cache delete $cacheKey
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_REPO: ${{ github.repository }}
|
||||
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
```
|
||||
</details>
|
||||
|
||||
</details>
|
||||
|
Loading…
x
Reference in New Issue
Block a user