mirror of
https://github.com/github/codeql-action
synced 2026-10-31 20:01:33 +03:00
Compare commits
114
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77591e2c4a | ||
|
|
7a44a9db3f | ||
|
|
e2ac371513 | ||
|
|
7deb0a15d3 | ||
|
|
f959778b39 | ||
|
|
d38ad56358 | ||
|
|
bc9796e2e0 | ||
|
|
ab5b0e3aab | ||
|
|
57a47f44df | ||
|
|
076d055bee | ||
|
|
6d4cd5d744 | ||
|
|
42fb267c1c | ||
|
|
832a783bd4 | ||
|
|
160e695297 | ||
|
|
8aac4e47ac | ||
|
|
e8d7df4f04 | ||
|
|
c1bba77db0 | ||
|
|
6bc82e05fd | ||
|
|
42f00f2d33 | ||
|
|
cedee6de9f | ||
|
|
f52cbc8309 | ||
|
|
c5aaca4bb9 | ||
|
|
3e58739c65 | ||
|
|
a6ccefb47c | ||
|
|
0e64858573 | ||
|
|
beb9f533db | ||
|
|
a1c70789a3 | ||
|
|
d94d88d717 | ||
|
|
a6d296a341 | ||
|
|
28f6d316c0 | ||
|
|
1d0f911837 | ||
|
|
05bd050f34 | ||
|
|
325a3a2ae3 | ||
|
|
6394750070 | ||
|
|
f1588cde0c | ||
|
|
f985be5b50 | ||
|
|
4dcc8a9cdc | ||
|
|
fbe3ae9de8 | ||
|
|
2a384c1c14 | ||
|
|
0c8e06dfb2 | ||
|
|
b2ff80ddac | ||
|
|
48f3548141 | ||
|
|
800dfbe5e1 | ||
|
|
1314d3d17e | ||
|
|
f7f9d3f341 | ||
|
|
eb5bd2d0b9 | ||
|
|
9aa0515f67 | ||
|
|
0720e13f0b | ||
|
|
38ba96d2aa | ||
|
|
679da45cc3 | ||
|
|
d5dd165f8b | ||
|
|
fbf75ebd7b | ||
|
|
6a50972d16 | ||
|
|
5cb12c41c2 | ||
|
|
e8f487178f | ||
|
|
a0671be58e | ||
|
|
9ea34c5169 | ||
|
|
9fda641d8d | ||
|
|
b126facd4e | ||
|
|
835dadecbf | ||
|
|
a02edfe319 | ||
|
|
173919c9d5 | ||
|
|
6095dc4d51 | ||
|
|
b333fc6f5b | ||
|
|
60b658ed10 | ||
|
|
e4e324705e | ||
|
|
faf7a50b01 | ||
|
|
2591c2031f | ||
|
|
34cae51104 | ||
|
|
9308bcd6bb | ||
|
|
fa9b76ac37 | ||
|
|
6059a66dec | ||
|
|
cb4fc9e8db | ||
|
|
be82188a2a | ||
|
|
c656a11252 | ||
|
|
bd9f639752 | ||
|
|
0a0c3a2e09 | ||
|
|
46a8de52fc | ||
|
|
f8cea24201 | ||
|
|
b1993d9139 | ||
|
|
ee1e1399e2 | ||
|
|
e7d3af2e1e | ||
|
|
13a6d8be95 | ||
|
|
b20883b0cd | ||
|
|
bf20b3e07b | ||
|
|
f1aa4f497a | ||
|
|
9a55d5bc5f | ||
|
|
17cd475099 | ||
|
|
c9aa45dd0f | ||
|
|
e3b8227a28 | ||
|
|
8a01181ce2 | ||
|
|
80e142568f | ||
|
|
b748848f27 | ||
|
|
5e767eff5a | ||
|
|
9752869470 | ||
|
|
c62c214723 | ||
|
|
18c2cfc765 | ||
|
|
1996ca9f5d | ||
|
|
12c4c7d0e9 | ||
|
|
919e8aaa40 | ||
|
|
4918026b93 | ||
|
|
e8c164b902 | ||
|
|
9fccf271ff | ||
|
|
c12cf8d49a | ||
|
|
0fcbec3eec | ||
|
|
0ae8b05d08 | ||
|
|
49cdf744d9 | ||
|
|
aac4202424 | ||
|
|
e7ece62b96 | ||
|
|
d9e374ef85 | ||
|
|
f4b47e7013 | ||
|
|
4e14537b54 | ||
|
|
e142eee9b4 | ||
|
|
dcd1b12beb |
No files matched your search
@@ -4,14 +4,15 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
exclude:
|
||||
- "@actions/*"
|
||||
labels:
|
||||
- Rebuild
|
||||
# Ignore incompatible dependency updates
|
||||
ignore:
|
||||
# There is a type incompatibility issue between v0.0.9 and our other dependencies.
|
||||
- dependency-name: "@octokit/plugin-retry"
|
||||
versions: ["~6.0.0"]
|
||||
# This is broken due to the way configuration files have changed.
|
||||
# This is broken due to the way configuration files have changed.
|
||||
# This might be fixed when we move to eslint v9.
|
||||
- dependency-name: "eslint-plugin-import"
|
||||
versions: [">=2.30.0"]
|
||||
@@ -28,6 +29,10 @@ updates:
|
||||
- "/.github/actions"
|
||||
schedule:
|
||||
interval: weekly
|
||||
cooldown:
|
||||
default-days: 7
|
||||
exclude:
|
||||
- "actions/*"
|
||||
labels:
|
||||
- Rebuild
|
||||
groups:
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ jobs:
|
||||
use-all-platform-bundle: 'false'
|
||||
setup-kotlin: 'true'
|
||||
- name: Install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache@3
|
||||
- name: Check toolcache contains CodeQL
|
||||
continue-on-error: true
|
||||
uses: actions/github-script@v8
|
||||
|
||||
Generated
+1
-1
@@ -68,7 +68,7 @@ jobs:
|
||||
const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL');
|
||||
fs.rmdirSync(codeqlPath, { recursive: true });
|
||||
- name: Install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache@3
|
||||
- name: Check toolcache does not contain CodeQL
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
|
||||
@@ -125,5 +125,6 @@ jobs:
|
||||
fi
|
||||
done
|
||||
env:
|
||||
CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false
|
||||
CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true
|
||||
CODEQL_ACTION_TEST_MODE: true
|
||||
Generated
-12
@@ -48,18 +48,6 @@ jobs:
|
||||
timeout-minutes: 45
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
# These steps are required to initialise the `gh` cli in a container that doesn't
|
||||
# come pre-installed with it. The reason for that is that this is later
|
||||
# needed by the `prepare-test` workflow to find the latest release of CodeQL.
|
||||
- name: Set up GitHub CLI
|
||||
run: |
|
||||
apt update
|
||||
apt install -y curl libreadline8 gnupg2 software-properties-common zstd
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
apt-key add /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
apt-add-repository https://cli.github.com/packages
|
||||
apt install -y gh
|
||||
env: {}
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v6
|
||||
- name: Prepare test
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ jobs:
|
||||
use-all-platform-bundle: 'false'
|
||||
setup-kotlin: 'true'
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@80740b3b13bf9857e28854481ca95a84e78a2bdf # v1.284.0
|
||||
uses: ruby/setup-ruby@90be1154f987f4dc0fe0dd0feedac9e473aa4ba8 # v1.286.0
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
- name: Install Code Scanning integration
|
||||
|
||||
@@ -111,7 +111,7 @@ jobs:
|
||||
# Otherwise, just commit the changes.
|
||||
if git rev-parse --verify MERGE_HEAD >/dev/null 2>&1; then
|
||||
echo "In progress merge detected, finishing it up."
|
||||
git merge --continue
|
||||
git merge --continue --no-edit
|
||||
else
|
||||
echo "No in-progress merge detected, committing changes."
|
||||
git commit -m "Rebuild"
|
||||
|
||||
@@ -57,6 +57,24 @@ jobs:
|
||||
- name: Update bundle
|
||||
uses: ./.github/actions/update-bundle
|
||||
|
||||
- name: Bump Action minor version if new CodeQL minor version series
|
||||
id: bump-action-version
|
||||
run: |
|
||||
prior_cli_version=$(jq -r '.priorCliVersion' src/defaults.json)
|
||||
cli_version=$(jq -r '.cliVersion' src/defaults.json)
|
||||
|
||||
prior_minor=$(echo "$prior_cli_version" | cut -d. -f2)
|
||||
current_minor=$(echo "$cli_version" | cut -d. -f2)
|
||||
|
||||
if [[ "$current_minor" != "$prior_minor" ]]; then
|
||||
echo "New CodeQL minor version series ($prior_cli_version -> $cli_version), bumping Action minor version"
|
||||
npm version minor --no-git-tag-version
|
||||
echo "bumped=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "Same minor version series ($prior_cli_version -> $cli_version), skipping Action version bump"
|
||||
echo "bumped=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Rebuild Action
|
||||
run: npm run build
|
||||
|
||||
@@ -71,11 +89,19 @@ jobs:
|
||||
- name: Open pull request
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ACTION_VERSION_BUMPED: ${{ steps.bump-action-version.outputs.bumped }}
|
||||
run: |
|
||||
cli_version=$(jq -r '.cliVersion' src/defaults.json)
|
||||
action_version=$(jq -r '.version' package.json)
|
||||
|
||||
pr_body="This pull request updates the default CodeQL bundle, as used with \`tools: linked\` and on GHES, to $cli_version."
|
||||
if [[ "$ACTION_VERSION_BUMPED" == "true" ]]; then
|
||||
pr_body+=$'\n\n'"Since this is a new CodeQL minor version series, this PR also bumps the Action version to $action_version."
|
||||
fi
|
||||
|
||||
pr_url=$(gh pr create \
|
||||
--title "Update default bundle to $cli_version" \
|
||||
--body "This pull request updates the default CodeQL bundle, as used with \`tools: linked\` and on GHES, to $cli_version." \
|
||||
--body "$pr_body" \
|
||||
--assignee "$GITHUB_ACTOR" \
|
||||
--draft \
|
||||
)
|
||||
|
||||
@@ -6,6 +6,15 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
|
||||
|
||||
No user facing changes.
|
||||
|
||||
## 4.32.1 - 02 Feb 2026
|
||||
|
||||
- A warning is now shown in Default Setup workflow logs if a [private package registry is configured](https://docs.github.com/en/code-security/how-tos/secure-at-scale/configure-organization-security/manage-usage-and-access/giving-org-access-private-registries) using a GitHub Personal Access Token (PAT), but no username is configured. [#3422](https://github.com/github/codeql-action/pull/3422)
|
||||
- Fixed a bug which caused the CodeQL Action to fail when repository properties cannot successfully be retrieved. [#3421](https://github.com/github/codeql-action/pull/3421)
|
||||
|
||||
## 4.32.0 - 26 Jan 2026
|
||||
|
||||
- Update default CodeQL bundle version to [2.24.0](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.24.0). [#3425](https://github.com/github/codeql-action/pull/3425)
|
||||
|
||||
## 4.31.11 - 23 Jan 2026
|
||||
|
||||
- When running a Default Setup workflow with [Actions debugging enabled](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging), the CodeQL Action will now use more unique names when uploading logs from the Dependabot authentication proxy as workflow artifacts. This ensures that the artifact names do not clash between multiple jobs in a build matrix. [#3409](https://github.com/github/codeql-action/pull/3409)
|
||||
|
||||
Generated
+28836
-10103
File diff suppressed because it is too large.
Load diff
Generated
+24592
-9591
File diff suppressed because it is too large.
Load diff
Generated
+24581
-9587
File diff suppressed because it is too large.
Load diff
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"bundleVersion": "codeql-bundle-v2.23.9",
|
||||
"cliVersion": "2.23.9",
|
||||
"priorBundleVersion": "codeql-bundle-v2.23.8",
|
||||
"priorCliVersion": "2.23.8"
|
||||
"bundleVersion": "codeql-bundle-v2.24.0",
|
||||
"cliVersion": "2.24.0",
|
||||
"priorBundleVersion": "codeql-bundle-v2.23.9",
|
||||
"priorCliVersion": "2.23.9"
|
||||
}
|
||||
Generated
+29371
-10624
File diff suppressed because it is too large.
Load diff
Generated
+27262
-12178
File diff suppressed because it is too large.
Load diff
Generated
+24574
-9585
File diff suppressed because it is too large.
Load diff
Generated
+24584
-9590
File diff suppressed because it is too large.
Load diff
Generated
+28825
-10091
File diff suppressed because it is too large.
Load diff
Generated
+32413
-17307
File diff suppressed because it is too large.
Load diff
Generated
+29168
-14179
File diff suppressed because it is too large.
Load diff
Generated
+28808
-10074
File diff suppressed because it is too large.
Load diff
Generated
+24585
-9591
File diff suppressed because it is too large.
Load diff
Generated
+310
-360
@@ -1,25 +1,25 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.31.12",
|
||||
"version": "4.32.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "codeql",
|
||||
"version": "4.31.12",
|
||||
"version": "4.32.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^5.0.2",
|
||||
"@actions/artifact": "^5.0.3",
|
||||
"@actions/artifact-legacy": "npm:@actions/artifact@^1.1.2",
|
||||
"@actions/cache": "^5.0.3",
|
||||
"@actions/core": "^2.0.2",
|
||||
"@actions/cache": "^5.0.5",
|
||||
"@actions/core": "^2.0.3",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/github": "^7.0.0",
|
||||
"@actions/github": "^8.0.0",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@actions/http-client": "^3.0.0",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@actions/tool-cache": "^3.0.0",
|
||||
"@octokit/plugin-retry": "^6.0.0",
|
||||
"@actions/tool-cache": "^3.0.1",
|
||||
"@octokit/plugin-retry": "^8.0.0",
|
||||
"@schemastore/package": "0.0.10",
|
||||
"archiver": "^7.0.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -55,7 +55,7 @@
|
||||
"eslint-plugin-filenames": "^1.3.2",
|
||||
"eslint-plugin-github": "^5.1.8",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-jsdoc": "^62.2.0",
|
||||
"eslint-plugin-jsdoc": "^62.3.0",
|
||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||
"glob": "^11.1.0",
|
||||
"nock": "^14.0.10",
|
||||
@@ -72,14 +72,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-5.0.2.tgz",
|
||||
"integrity": "sha512-NmA+THO1s/Ubqf5y34EZofB1FRORcToa3T8Mb3/Z87TCCozTtvBUaxDn8OPPwgyYQ4ft0nd01Z4kFSu2DTWqGw==",
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-5.0.3.tgz",
|
||||
"integrity": "sha512-FIEG8Kum0wABZnktJvFi1xuVPc31xrunhZwLCvjrCGISQOm0ifyo7cjqf6PHiEeqoWMa5HIGOsB+lGM4aKCseA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.0",
|
||||
"@actions/github": "^6.0.1",
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@azure/storage-blob": "^12.29.1",
|
||||
"@octokit/core": "^5.2.1",
|
||||
"@octokit/plugin-request-log": "^1.0.4",
|
||||
@@ -164,6 +164,33 @@
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/core": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz",
|
||||
"integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.1.0",
|
||||
"@octokit/request": "^8.4.1",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/endpoint": {
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||
@@ -177,12 +204,86 @@
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/graphql": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz",
|
||||
"integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^8.4.1",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/openapi-types": {
|
||||
"version": "12.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
|
||||
"integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
|
||||
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
|
||||
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/@octokit/plugin-retry": {
|
||||
"version": "3.0.9",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
|
||||
@@ -243,16 +344,22 @@
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="
|
||||
},
|
||||
"node_modules/@actions/artifact/node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@actions/cache": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.0.3.tgz",
|
||||
"integrity": "sha512-9joY8Oup+nIpksSBlkuf9/mltnhWx3lydk1tA2PVnXaxFLIIrKqrWDN2CZXlJ+PEErcBARKYn4mHiUCTyMh4Vg==",
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@actions/cache/-/cache-5.0.5.tgz",
|
||||
"integrity": "sha512-jiQSg0gfd+C2KPgcmdCOq7dCuCIQQWQ4b1YfGIRaaA9w7PJbRwTOcCz4LiFEUnqZGf0ha/8OKL3BeNwetHzYsQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.0",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@actions/glob": "^0.5.1",
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@azure/abort-controller": "^1.1.0",
|
||||
"@azure/core-rest-pipeline": "^1.22.0",
|
||||
@@ -269,13 +376,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.2.tgz",
|
||||
"integrity": "sha512-Ast1V7yHbGAhplAsuVlnb/5J8Mtr/Zl6byPPL+Qjq3lmfIgWF1ak1iYfF/079cRERiuTALTXkSuEUdZeDCfGtA==",
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.3.tgz",
|
||||
"integrity": "sha512-Od9Thc3T1mQJYddvVPM4QGiLUewdh+3txmDYHHxoNdkqysR1MbCT+rFOtNUxYAz+7+6RIsqipVahY2GJqGPyxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.1"
|
||||
"@actions/http-client": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
@@ -288,129 +395,77 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-7.0.0.tgz",
|
||||
"integrity": "sha512-PyGODO938aoBTZd/IfN/+e+Pd5hUcVpyf+thm4CPESLeqhdSkq5QwMTGX9v84XHE1ifmHWBQ60KB8kIgm96opw==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/github/-/github-8.0.0.tgz",
|
||||
"integrity": "sha512-bBukvVRvIf7NshWEXFVnBaXs/ZyGzDvx+jbB5AdJij9CUG4VFEYJJD6T6y06dDkuULalQQUNvKXIH71yqw7SoQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@octokit/core": "^5.0.1",
|
||||
"@octokit/plugin-paginate-rest": "^9.2.2",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^10.4.0",
|
||||
"@octokit/request": "^8.4.1",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/core": "^7.0.6",
|
||||
"@octokit/plugin-paginate-rest": "^14.0.0",
|
||||
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
|
||||
"@octokit/request": "^10.0.7",
|
||||
"@octokit/request-error": "^7.1.0",
|
||||
"undici": "^5.28.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github/node_modules/@octokit/endpoint": {
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||
"node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz",
|
||||
"integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github/node_modules/@octokit/request": {
|
||||
"version": "8.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||
"node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "17.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz",
|
||||
"integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^9.0.6",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github/node_modules/@octokit/request-error": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"peerDependencies": {
|
||||
"@octokit/core": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/github/node_modules/@octokit/types/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/glob": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.5.0.tgz",
|
||||
"integrity": "sha512-tST2rjPvJLRZLuT9NMUtyBjvj9Yo0MiJS3ow004slMvm8GFM+Zv9HvMJ7HWzfUyJnGrJvDsYkWBaaG3YKXRtCw==",
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.5.1.tgz",
|
||||
"integrity": "sha512-+dv/t2aKQdKp9WWSp+1yIXVJzH5Q38M0Mta26pzIbeec14EcIleMB7UU6N7sNgbEuYfyuVGpE5pOKjl6j1WXkA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
"@actions/core": "^2.0.3",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/@actions/core": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
|
||||
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/exec": "^1.1.1",
|
||||
"@actions/http-client": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/@actions/exec": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/@actions/http-client": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||
"integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.25.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob/node_modules/@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.1.tgz",
|
||||
"integrity": "sha512-SbGS8c/vySbNO3kjFgSW77n83C4MQx/Yoe+b1hAdpuvfHxnkHzDq2pWljUpAA56Si1Gae/7zjeZsV0CYjmLo/w==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
|
||||
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
"undici": "^5.28.5"
|
||||
"undici": "^6.23.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client/node_modules/undici": {
|
||||
"version": "6.23.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
|
||||
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
@@ -420,14 +475,14 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/tool-cache": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-3.0.0.tgz",
|
||||
"integrity": "sha512-JBx8gEWuu8Lqaqx/hEnL6QdKvF06suBR4y+dBDi9vJbHx1r+p6QtmBKhQYhiKjDUYIoDX1bUrbyAYPChoPK+XA==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-3.0.1.tgz",
|
||||
"integrity": "sha512-euK7sID37jMg1yWGkdXkLPI5Te7x/+2QMUPeHXogcpzUZ81mqlDZ+CgYhQo3LtB8LpVnnQyjs+hTTU0Ir4Y0RQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^2.0.1",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/http-client": "^3.0.1",
|
||||
"@actions/http-client": "^3.0.2",
|
||||
"@actions/io": "^2.0.0",
|
||||
"semver": "^6.1.0"
|
||||
}
|
||||
@@ -753,26 +808,26 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/jsdoccomment": {
|
||||
"version": "0.81.0",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.81.0.tgz",
|
||||
"integrity": "sha512-4V4A0hFAB19id7w9iwiosV/rqwlH+PXEuYnnu1Cyc5jUjTwsE2G1qsX9TOCmfCmsWYBg6xeDC/XDFUzXAxDg3A==",
|
||||
"version": "0.82.0",
|
||||
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.82.0.tgz",
|
||||
"integrity": "sha512-xs3OTxPefjTZaoDS7H1X2pV33enAmZg+8YldjmeYk7XZnq420phdnp6o0JtrsHBdSRJ5+RTocgyED9TL3epgpw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.8",
|
||||
"@typescript-eslint/types": "^8.53.0",
|
||||
"@typescript-eslint/types": "^8.53.1",
|
||||
"comment-parser": "1.4.4",
|
||||
"esquery": "^1.7.0",
|
||||
"jsdoc-type-pratt-parser": "~7.0.0"
|
||||
"jsdoc-type-pratt-parser": "~7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || ^22.13.0 || >=24"
|
||||
}
|
||||
},
|
||||
"node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": {
|
||||
"version": "8.53.1",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz",
|
||||
"integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==",
|
||||
"version": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz",
|
||||
"integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -1445,9 +1500,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/brace-expansion": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.1.tgz",
|
||||
"integrity": "sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
@@ -1649,185 +1704,83 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/auth-token": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
|
||||
"integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz",
|
||||
"integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz",
|
||||
"integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==",
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz",
|
||||
"integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/auth-token": "^4.0.0",
|
||||
"@octokit/graphql": "^7.1.0",
|
||||
"@octokit/request": "^8.4.1",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"before-after-hook": "^2.2.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/auth-token": "^6.0.0",
|
||||
"@octokit/graphql": "^9.0.3",
|
||||
"@octokit/request": "^10.0.6",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"before-after-hook": "^4.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/endpoint": {
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||
"node_modules/@octokit/core/node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@octokit/endpoint": {
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.2.tgz",
|
||||
"integrity": "sha512-4zCpzP1fWc7QlqunZ5bSEjxc6yLAlRTnDwKtgXfcI/FxxGoqedDG8V2+xJ60bV2kODqcGB+nATdtap/XYq2NZQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/types": "^16.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/request": {
|
||||
"version": "8.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^9.0.6",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/request-error": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/core/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
"node_modules/@octokit/endpoint/node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@octokit/graphql": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz",
|
||||
"integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==",
|
||||
"version": "9.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz",
|
||||
"integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request": "^8.4.1",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
"@octokit/request": "^10.0.6",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"universal-user-agent": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/endpoint": {
|
||||
"version": "9.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/request": {
|
||||
"version": "8.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||
"dependencies": {
|
||||
"@octokit/endpoint": "^9.0.6",
|
||||
"@octokit/request-error": "^5.1.1",
|
||||
"@octokit/types": "^13.1.0",
|
||||
"universal-user-agent": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/request-error": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
}
|
||||
"node_modules/@octokit/graphql/node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@octokit/openapi-types": {
|
||||
"version": "27.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz",
|
||||
"integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
|
||||
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-request-log": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
|
||||
@@ -1837,83 +1790,61 @@
|
||||
"@octokit/core": ">=3"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods": {
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
|
||||
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^12.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
|
||||
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
|
||||
"version": "12.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
|
||||
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^20.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz",
|
||||
"integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==",
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.0.3.tgz",
|
||||
"integrity": "sha512-vKGx1i3MC0za53IzYBSBXcrhmd+daQDzuZfYDd52X5S0M2otf3kVZTVP8bLA3EkU0lTvd1WEC2OlNNa4G+dohA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/request-error": "^5.0.0",
|
||||
"@octokit/types": "^13.0.0",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"bottleneck": "^2.15.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@octokit/core": "5"
|
||||
"@octokit/core": ">=7"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": {
|
||||
"version": "24.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg=="
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry/node_modules/@octokit/request-error": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||
"node_modules/@octokit/request": {
|
||||
"version": "10.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz",
|
||||
"integrity": "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/types": "^13.1.0",
|
||||
"deprecation": "^2.0.0",
|
||||
"once": "^1.4.0"
|
||||
"@octokit/endpoint": "^11.0.2",
|
||||
"@octokit/request-error": "^7.0.2",
|
||||
"@octokit/types": "^16.0.0",
|
||||
"fast-content-type-parse": "^3.0.0",
|
||||
"universal-user-agent": "^7.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 18"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/plugin-retry/node_modules/@octokit/types": {
|
||||
"version": "13.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||
"node_modules/@octokit/request-error": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz",
|
||||
"integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^24.2.0"
|
||||
"@octokit/types": "^16.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/@octokit/request/node_modules/universal-user-agent": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
|
||||
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@octokit/types": {
|
||||
"version": "16.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz",
|
||||
"integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@octokit/openapi-types": "^27.0.0"
|
||||
@@ -3663,7 +3594,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/before-after-hook": {
|
||||
"version": "2.2.3",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz",
|
||||
"integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/binary": {
|
||||
@@ -3834,9 +3767,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001727",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
|
||||
"integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
|
||||
"version": "1.0.30001766",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz",
|
||||
"integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -3851,7 +3784,8 @@
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
]
|
||||
],
|
||||
"license": "CC-BY-4.0"
|
||||
},
|
||||
"node_modules/cbor": {
|
||||
"version": "10.0.9",
|
||||
@@ -4942,19 +4876,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsdoc": {
|
||||
"version": "62.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.2.0.tgz",
|
||||
"integrity": "sha512-juIekE88Gy1FnjsQuwkrZ3OW4UCkQuhiBf9QqF9U1xgqtan4rQFCOUn4cKeHR1ObBqJ8/pG8a0lZlAuKlDLpdw==",
|
||||
"version": "62.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.3.0.tgz",
|
||||
"integrity": "sha512-Gc5Ls5qQC6NwqtQTtJ2JE5BwvX348ZCZ+4+QiZ9RpoQ1TCcxFF8Z0E5jaLkTyYNqyhx+uKAvljNHE0B7PBw+iw==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@es-joy/jsdoccomment": "~0.81.0",
|
||||
"@es-joy/jsdoccomment": "~0.82.0",
|
||||
"@es-joy/resolve.exports": "1.2.0",
|
||||
"are-docs-informative": "^0.0.2",
|
||||
"comment-parser": "1.4.4",
|
||||
"debug": "^4.4.3",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"espree": "^11.0.0",
|
||||
"espree": "^11.1.0",
|
||||
"esquery": "^1.7.0",
|
||||
"html-entities": "^2.6.0",
|
||||
"object-deep-merge": "^2.0.0",
|
||||
@@ -5015,9 +4949,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jsdoc/node_modules/espree": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-11.0.0.tgz",
|
||||
"integrity": "sha512-+gMeWRrIh/NsG+3NaLeWHuyeyk70p2tbvZIWBYcqQ4/7Xvars6GYTZNhF1sIeLcc6Wb11He5ffz3hsHyXFrw5A==",
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-11.1.0.tgz",
|
||||
"integrity": "sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
@@ -5450,6 +5384,22 @@
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-content-type-parse": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz",
|
||||
"integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"license": "MIT"
|
||||
@@ -5492,9 +5442,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-xml-parser": {
|
||||
"version": "5.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.3.tgz",
|
||||
"integrity": "sha512-2O3dkPAAC6JavuMm8+4+pgTk+5hoAs+CjZ+sWcQLkX9+/tHRuTkQh/Oaifr8qDmZ8iEHb771Ea6G8CdwkrgvYA==",
|
||||
"version": "5.3.4",
|
||||
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.4.tgz",
|
||||
"integrity": "sha512-EFd6afGmXlCx8H8WTZHhAoDaWaGyuIBoZJ2mknrNxug+aZKjkp0a0dlars9Izl+jF+7Gu1/5f/2h68cQpe0IiA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -6536,9 +6486,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jsdoc-type-pratt-parser": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.0.0.tgz",
|
||||
"integrity": "sha512-c7YbokssPOSHmqTbSAmTtnVgAVa/7lumWNYqomgd5KOMyPrRve2anx6lonfOsXEQacqF9FKVUj7bLg4vRSvdYA==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-7.1.0.tgz",
|
||||
"integrity": "sha512-SX7q7XyCwzM/MEDCYz0l8GgGbJAACGFII9+WfNYr5SLEKukHWRy2Jk3iWRe7P+lpYJNs7oQ+OSei4JtKGUjd7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@@ -8184,9 +8134,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "7.5.6",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.6.tgz",
|
||||
"integrity": "sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==",
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
|
||||
"integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
|
||||
+8
-8
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "codeql",
|
||||
"version": "4.31.12",
|
||||
"version": "4.32.2",
|
||||
"private": true,
|
||||
"description": "CodeQL action",
|
||||
"scripts": {
|
||||
@@ -24,17 +24,17 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/artifact": "^5.0.2",
|
||||
"@actions/artifact": "^5.0.3",
|
||||
"@actions/artifact-legacy": "npm:@actions/artifact@^1.1.2",
|
||||
"@actions/cache": "^5.0.3",
|
||||
"@actions/core": "^2.0.2",
|
||||
"@actions/cache": "^5.0.5",
|
||||
"@actions/core": "^2.0.3",
|
||||
"@actions/exec": "^2.0.0",
|
||||
"@actions/github": "^7.0.0",
|
||||
"@actions/github": "^8.0.0",
|
||||
"@actions/glob": "^0.5.0",
|
||||
"@actions/http-client": "^3.0.0",
|
||||
"@actions/io": "^2.0.0",
|
||||
"@actions/tool-cache": "^3.0.0",
|
||||
"@octokit/plugin-retry": "^6.0.0",
|
||||
"@actions/tool-cache": "^3.0.1",
|
||||
"@octokit/plugin-retry": "^8.0.0",
|
||||
"@schemastore/package": "0.0.10",
|
||||
"archiver": "^7.0.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -70,7 +70,7 @@
|
||||
"eslint-plugin-filenames": "^1.3.2",
|
||||
"eslint-plugin-github": "^5.1.8",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-jsdoc": "^62.2.0",
|
||||
"eslint-plugin-jsdoc": "^62.3.0",
|
||||
"eslint-plugin-no-async-foreach": "^0.1.1",
|
||||
"glob": "^11.1.0",
|
||||
"nock": "^14.0.10",
|
||||
|
||||
@@ -4,7 +4,7 @@ versions:
|
||||
- toolcache
|
||||
steps:
|
||||
- name: Install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache@3
|
||||
- name: Check toolcache contains CodeQL
|
||||
continue-on-error: true
|
||||
uses: actions/github-script@v8
|
||||
|
||||
@@ -16,7 +16,7 @@ steps:
|
||||
const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL');
|
||||
fs.rmdirSync(codeqlPath, { recursive: true });
|
||||
- name: Install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache
|
||||
run: npm install @actions/tool-cache@3
|
||||
- name: Check toolcache does not contain CodeQL
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
|
||||
@@ -5,6 +5,7 @@ versions: ["nightly-latest"]
|
||||
installGo: true
|
||||
installDotNet: true
|
||||
env:
|
||||
CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS: false
|
||||
CODEQL_ACTION_SUBLANGUAGE_FILE_COVERAGE: true
|
||||
steps:
|
||||
- uses: ./../action/init
|
||||
|
||||
@@ -3,19 +3,6 @@ description: "Tests using a proxy specified by the https_proxy environment varia
|
||||
versions: ["linked", "nightly-latest"]
|
||||
container:
|
||||
image: ubuntu:22.04
|
||||
container-init-steps:
|
||||
# These steps are required to initialise the `gh` cli in a container that doesn't
|
||||
# come pre-installed with it. The reason for that is that this is later
|
||||
# needed by the `prepare-test` workflow to find the latest release of CodeQL.
|
||||
name: Set up GitHub CLI
|
||||
run: |
|
||||
apt update
|
||||
apt install -y curl libreadline8 gnupg2 software-properties-common zstd
|
||||
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
apt-key add /usr/share/keyrings/githubcli-archive-keyring.gpg
|
||||
apt-add-repository https://cli.github.com/packages
|
||||
apt install -y gh
|
||||
env: {}
|
||||
services:
|
||||
squid-proxy:
|
||||
image: ubuntu/squid:latest
|
||||
|
||||
@@ -4,7 +4,7 @@ description: "Tests using RuboCop to analyze a multi-language repository and the
|
||||
versions: ["default"]
|
||||
steps:
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@80740b3b13bf9857e28854481ca95a84e78a2bdf # v1.284.0
|
||||
uses: ruby/setup-ruby@90be1154f987f4dc0fe0dd0feedac9e473aa4ba8 # v1.286.0
|
||||
with:
|
||||
ruby-version: 2.6
|
||||
- name: Install Code Scanning integration
|
||||
|
||||
@@ -87,7 +87,6 @@ test("status report fields", async (t) => {
|
||||
);
|
||||
return "";
|
||||
},
|
||||
databasePrintBaseline: async () => "",
|
||||
});
|
||||
|
||||
const config = createTestConfig({
|
||||
|
||||
+10
-2
@@ -495,10 +495,18 @@ export async function runQueries(
|
||||
endTimeInterpretResults.getTime() - startTimeInterpretResults.getTime();
|
||||
logger.endGroup();
|
||||
|
||||
logger.info(analysisSummary);
|
||||
if (qualityAnalysisSummary) {
|
||||
if (analysisSummary.trim()) {
|
||||
logger.info(analysisSummary);
|
||||
}
|
||||
if (qualityAnalysisSummary?.trim()) {
|
||||
logger.info(qualityAnalysisSummary);
|
||||
}
|
||||
if (!config.enableFileCoverageInformation) {
|
||||
logger.info(
|
||||
"To speed up pull request analysis, file coverage information is only enabled when analyzing " +
|
||||
"the default branch and protected branches.",
|
||||
);
|
||||
}
|
||||
|
||||
if (await features.getValue(Feature.QaTelemetryEnabled)) {
|
||||
// Note: QA adds the `code-quality` query suite to the `queries` input,
|
||||
|
||||
+2
-1
@@ -306,7 +306,8 @@ export function wrapApiConfigurationError(e: unknown) {
|
||||
}
|
||||
if (
|
||||
httpError.message.includes("Bad credentials") ||
|
||||
httpError.message.includes("Not Found")
|
||||
httpError.message.includes("Not Found") ||
|
||||
httpError.message.includes("Requires authentication")
|
||||
) {
|
||||
return new ConfigurationError(
|
||||
"Please check that your token is valid and has the required permissions: contents: read, security-events: write",
|
||||
|
||||
+112
-27
@@ -4,37 +4,122 @@ import * as path from "path";
|
||||
|
||||
import test from "ava";
|
||||
|
||||
import { scanArtifactsForTokens } from "./artifact-scanner";
|
||||
import {
|
||||
GITHUB_PAT_CLASSIC_PATTERN,
|
||||
isAuthToken,
|
||||
scanArtifactsForTokens,
|
||||
TokenType,
|
||||
} from "./artifact-scanner";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { getRecordingLogger, LoggedMessage } from "./testing-utils";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
getRecordingLogger,
|
||||
LoggedMessage,
|
||||
makeTestToken,
|
||||
} from "./testing-utils";
|
||||
|
||||
test("scanArtifactsForTokens detects GitHub tokens in files", async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-"));
|
||||
|
||||
try {
|
||||
// Create a test file with a fake GitHub token
|
||||
const testFile = path.join(tempDir, "test.txt");
|
||||
fs.writeFileSync(
|
||||
testFile,
|
||||
"This is a test file with token ghp_1234567890123456789012345678901234AB",
|
||||
);
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
async () => await scanArtifactsForTokens([testFile], logger),
|
||||
);
|
||||
|
||||
t.regex(
|
||||
error?.message || "",
|
||||
/Found 1 potential GitHub token.*Personal Access Token/,
|
||||
);
|
||||
t.regex(error?.message || "", /test\.txt/);
|
||||
} finally {
|
||||
// Clean up
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
test("makeTestToken", (t) => {
|
||||
t.is(makeTestToken().length, 36);
|
||||
t.is(makeTestToken(255).length, 255);
|
||||
});
|
||||
|
||||
test("isAuthToken", (t) => {
|
||||
// Undefined for strings that aren't tokens
|
||||
t.is(isAuthToken("some string"), undefined);
|
||||
t.is(isAuthToken("ghp_"), undefined);
|
||||
t.is(isAuthToken("ghp_123"), undefined);
|
||||
|
||||
// Token types for strings that are tokens.
|
||||
t.is(isAuthToken(`ghp_${makeTestToken()}`), TokenType.PersonalAccessClassic);
|
||||
t.is(isAuthToken(`ghp_${makeTestToken()}`), TokenType.PersonalAccessClassic);
|
||||
t.is(
|
||||
isAuthToken(`ghs_${makeTestToken(255)}`),
|
||||
TokenType.AppInstallationAccess,
|
||||
);
|
||||
t.is(
|
||||
isAuthToken(`github_pat_${makeTestToken(22)}_${makeTestToken(59)}`),
|
||||
TokenType.PersonalAccessFineGrained,
|
||||
);
|
||||
|
||||
// With a custom pattern set
|
||||
t.is(
|
||||
isAuthToken(`ghp_${makeTestToken()}`, [GITHUB_PAT_CLASSIC_PATTERN]),
|
||||
TokenType.PersonalAccessClassic,
|
||||
);
|
||||
t.is(
|
||||
isAuthToken(`github_pat_${makeTestToken(22)}_${makeTestToken(59)}`, [
|
||||
GITHUB_PAT_CLASSIC_PATTERN,
|
||||
]),
|
||||
undefined,
|
||||
);
|
||||
});
|
||||
|
||||
const testTokens = [
|
||||
{
|
||||
type: TokenType.PersonalAccessClassic,
|
||||
value: `ghp_${makeTestToken()}`,
|
||||
checkPattern: "Personal Access Token",
|
||||
},
|
||||
{
|
||||
type: TokenType.PersonalAccessFineGrained,
|
||||
value:
|
||||
"github_pat_1234567890ABCDEFGHIJKL_MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHI",
|
||||
checkPattern: "Personal Access Token",
|
||||
},
|
||||
{
|
||||
type: TokenType.OAuth,
|
||||
value: `gho_${makeTestToken()}`,
|
||||
},
|
||||
{
|
||||
type: TokenType.UserToServer,
|
||||
value: `ghu_${makeTestToken()}`,
|
||||
},
|
||||
{
|
||||
type: TokenType.ServerToServer,
|
||||
value: `ghs_${makeTestToken()}`,
|
||||
},
|
||||
{
|
||||
type: TokenType.Refresh,
|
||||
value: `ghr_${makeTestToken()}`,
|
||||
},
|
||||
{
|
||||
type: TokenType.AppInstallationAccess,
|
||||
value: `ghs_${makeTestToken(255)}`,
|
||||
},
|
||||
];
|
||||
|
||||
for (const { type, value, checkPattern } of testTokens) {
|
||||
test(`scanArtifactsForTokens detects GitHub ${type} tokens in files`, async (t) => {
|
||||
const logMessages = [];
|
||||
const logger = getRecordingLogger(logMessages, { logToConsole: false });
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-"));
|
||||
|
||||
try {
|
||||
// Create a test file with a fake GitHub token
|
||||
const testFile = path.join(tempDir, "test.txt");
|
||||
fs.writeFileSync(testFile, `This is a test file with token ${value}`);
|
||||
|
||||
const error = await t.throwsAsync(
|
||||
async () => await scanArtifactsForTokens([testFile], logger),
|
||||
);
|
||||
|
||||
t.regex(
|
||||
error?.message || "",
|
||||
new RegExp(`Found 1 potential GitHub token.*${checkPattern || type}`),
|
||||
);
|
||||
t.regex(error?.message || "", /test\.txt/);
|
||||
|
||||
checkExpectedLogMessages(t, logMessages, [
|
||||
"Starting best-effort check",
|
||||
`Found 1 ${type}`,
|
||||
]);
|
||||
} finally {
|
||||
// Clean up
|
||||
fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test("scanArtifactsForTokens handles files without tokens", async (t) => {
|
||||
const logger = getRunnerLogger(true);
|
||||
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "scanner-test-"));
|
||||
|
||||
+60
-13
@@ -7,33 +7,62 @@ import * as exec from "@actions/exec";
|
||||
import { Logger } from "./logging";
|
||||
import { getErrorMessage } from "./util";
|
||||
|
||||
/**
|
||||
* Enumerates known types of GitHub token formats.
|
||||
*/
|
||||
export enum TokenType {
|
||||
PersonalAccessClassic = "Personal Access Token (Classic)",
|
||||
PersonalAccessFineGrained = "Personal Access Token (Fine-grained)",
|
||||
OAuth = "OAuth Access Token",
|
||||
UserToServer = "User-to-Server Token",
|
||||
ServerToServer = "Server-to-Server Token",
|
||||
Refresh = "Refresh Token",
|
||||
AppInstallationAccess = "App Installation Access Token",
|
||||
}
|
||||
|
||||
/** A value of this type associates a token type with its pattern. */
|
||||
export interface TokenPattern {
|
||||
type: TokenType;
|
||||
pattern: RegExp;
|
||||
}
|
||||
|
||||
/** The pattern for PATs (Classic) */
|
||||
export const GITHUB_PAT_CLASSIC_PATTERN: TokenPattern = {
|
||||
type: TokenType.PersonalAccessClassic,
|
||||
pattern: /\bghp_[a-zA-Z0-9]{36}\b/g,
|
||||
};
|
||||
|
||||
/** The pattern for PATs (Fine-grained) */
|
||||
export const GITHUB_PAT_FINE_GRAINED_PATTERN: TokenPattern = {
|
||||
type: TokenType.PersonalAccessFineGrained,
|
||||
pattern: /\bgithub_pat_[a-zA-Z0-9_]+\b/g,
|
||||
};
|
||||
|
||||
/**
|
||||
* GitHub token patterns to scan for.
|
||||
* These patterns match various GitHub token formats.
|
||||
*/
|
||||
const GITHUB_TOKEN_PATTERNS = [
|
||||
const GITHUB_TOKEN_PATTERNS: TokenPattern[] = [
|
||||
GITHUB_PAT_CLASSIC_PATTERN,
|
||||
GITHUB_PAT_FINE_GRAINED_PATTERN,
|
||||
{
|
||||
name: "Personal Access Token",
|
||||
pattern: /\bghp_[a-zA-Z0-9]{36}\b/g,
|
||||
},
|
||||
{
|
||||
name: "OAuth Access Token",
|
||||
type: TokenType.OAuth,
|
||||
pattern: /\bgho_[a-zA-Z0-9]{36}\b/g,
|
||||
},
|
||||
{
|
||||
name: "User-to-Server Token",
|
||||
type: TokenType.UserToServer,
|
||||
pattern: /\bghu_[a-zA-Z0-9]{36}\b/g,
|
||||
},
|
||||
{
|
||||
name: "Server-to-Server Token",
|
||||
type: TokenType.ServerToServer,
|
||||
pattern: /\bghs_[a-zA-Z0-9]{36}\b/g,
|
||||
},
|
||||
{
|
||||
name: "Refresh Token",
|
||||
type: TokenType.Refresh,
|
||||
pattern: /\bghr_[a-zA-Z0-9]{36}\b/g,
|
||||
},
|
||||
{
|
||||
name: "App Installation Access Token",
|
||||
type: TokenType.AppInstallationAccess,
|
||||
pattern: /\bghs_[a-zA-Z0-9]{255}\b/g,
|
||||
},
|
||||
];
|
||||
@@ -48,6 +77,24 @@ interface ScanResult {
|
||||
findings: TokenFinding[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether `value` matches any token `patterns`.
|
||||
* @param value The value to match against.
|
||||
* @param patterns The patterns to check.
|
||||
* @returns The type of the first matching pattern, or `undefined` if none match.
|
||||
*/
|
||||
export function isAuthToken(
|
||||
value: string,
|
||||
patterns: TokenPattern[] = GITHUB_TOKEN_PATTERNS,
|
||||
) {
|
||||
for (const { type, pattern } of patterns) {
|
||||
if (value.match(pattern)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a file for GitHub tokens.
|
||||
*
|
||||
@@ -65,13 +112,13 @@ function scanFileForTokens(
|
||||
try {
|
||||
const content = fs.readFileSync(filePath, "utf8");
|
||||
|
||||
for (const { name, pattern } of GITHUB_TOKEN_PATTERNS) {
|
||||
for (const { type, pattern } of GITHUB_TOKEN_PATTERNS) {
|
||||
const matches = content.match(pattern);
|
||||
if (matches) {
|
||||
for (let i = 0; i < matches.length; i++) {
|
||||
findings.push({ tokenType: name, filePath: relativePath });
|
||||
findings.push({ tokenType: type, filePath: relativePath });
|
||||
}
|
||||
logger.debug(`Found ${matches.length} ${name}(s) in ${relativePath}`);
|
||||
logger.debug(`Found ${matches.length} ${type}(s) in ${relativePath}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-20
@@ -186,10 +186,6 @@ export interface CodeQL {
|
||||
config: Config,
|
||||
features: FeatureEnablement,
|
||||
): Promise<string>;
|
||||
/**
|
||||
* Run 'codeql database print-baseline'.
|
||||
*/
|
||||
databasePrintBaseline(databasePath: string): Promise<string>;
|
||||
/**
|
||||
* Run 'codeql database export-diagnostics'
|
||||
*
|
||||
@@ -493,10 +489,6 @@ export function createStubCodeQL(partialCodeql: Partial<CodeQL>): CodeQL {
|
||||
partialCodeql,
|
||||
"databaseInterpretResults",
|
||||
),
|
||||
databasePrintBaseline: resolveFunction(
|
||||
partialCodeql,
|
||||
"databasePrintBaseline",
|
||||
),
|
||||
databaseExportDiagnostics: resolveFunction(
|
||||
partialCodeql,
|
||||
"databaseExportDiagnostics",
|
||||
@@ -628,6 +620,13 @@ async function getCodeQLForCmd(
|
||||
extraArgs.push("--overlay-base");
|
||||
}
|
||||
|
||||
const baselineFilesOptions = config.enableFileCoverageInformation
|
||||
? [
|
||||
"--calculate-language-specific-baseline",
|
||||
"--sublanguage-file-coverage",
|
||||
]
|
||||
: ["--no-calculate-baseline"];
|
||||
|
||||
await runCli(
|
||||
cmd,
|
||||
[
|
||||
@@ -639,12 +638,14 @@ async function getCodeQLForCmd(
|
||||
"--db-cluster",
|
||||
config.dbLocation,
|
||||
`--source-root=${sourceRoot}`,
|
||||
"--calculate-language-specific-baseline",
|
||||
...baselineFilesOptions,
|
||||
"--extractor-include-aliases",
|
||||
"--sublanguage-file-coverage",
|
||||
...extraArgs,
|
||||
...getExtraOptionsFromEnv(["database", "init"], {
|
||||
ignoringOptions: ["--overwrite"],
|
||||
// Some user configs specify `--no-calculate-baseline` as an additional
|
||||
// argument to `codeql database init`. Therefore ignore the baseline file
|
||||
// options here to avoid specifying the same argument twice and erroring.
|
||||
ignoringOptions: ["--overwrite", ...baselineFilesOptions],
|
||||
}),
|
||||
],
|
||||
{ stdin: externalRepositoryToken },
|
||||
@@ -885,15 +886,6 @@ async function getCodeQLForCmd(
|
||||
noStreamStdout: true,
|
||||
});
|
||||
},
|
||||
async databasePrintBaseline(databasePath: string): Promise<string> {
|
||||
const codeqlArgs = [
|
||||
"database",
|
||||
"print-baseline",
|
||||
...getExtraOptionsFromEnv(["database", "print-baseline"]),
|
||||
databasePath,
|
||||
];
|
||||
return await runCli(cmd, codeqlArgs);
|
||||
},
|
||||
async databaseCleanupCluster(
|
||||
config: Config,
|
||||
cleanupLevel: CleanupLevel,
|
||||
|
||||
@@ -89,6 +89,7 @@ function createTestInitConfigInputs(
|
||||
},
|
||||
features: createFeatures([]),
|
||||
repositoryProperties: {},
|
||||
enableFileCoverageInformation: true,
|
||||
logger: getRunnerLogger(true),
|
||||
} satisfies configUtils.InitConfigInputs,
|
||||
overrides,
|
||||
|
||||
+14
-9
@@ -26,7 +26,10 @@ import {
|
||||
parseUserConfig,
|
||||
UserConfig,
|
||||
} from "./config/db-config";
|
||||
import { addDiagnostic, makeTelemetryDiagnostic } from "./diagnostics";
|
||||
import {
|
||||
addNoLanguageDiagnostic,
|
||||
makeTelemetryDiagnostic,
|
||||
} from "./diagnostics";
|
||||
import { shouldPerformDiffInformedAnalysis } from "./diff-informed-analysis-utils";
|
||||
import { EnvVar } from "./environment";
|
||||
import * as errorMessages from "./error-messages";
|
||||
@@ -214,6 +217,11 @@ export interface Config {
|
||||
* A partial mapping from repository properties that affect us to their values.
|
||||
*/
|
||||
repositoryProperties: RepositoryProperties;
|
||||
|
||||
/**
|
||||
* Whether to enable file coverage information.
|
||||
*/
|
||||
enableFileCoverageInformation: boolean;
|
||||
}
|
||||
|
||||
async function getSupportedLanguageMap(
|
||||
@@ -433,6 +441,7 @@ export interface InitConfigInputs {
|
||||
apiDetails: api.GitHubApiCombinedDetails;
|
||||
features: FeatureEnablement;
|
||||
repositoryProperties: RepositoryProperties;
|
||||
enableFileCoverageInformation: boolean;
|
||||
analysisKinds: AnalysisKind[];
|
||||
logger: Logger;
|
||||
}
|
||||
@@ -462,6 +471,7 @@ export async function initActionState(
|
||||
repositoryProperties,
|
||||
analysisKinds,
|
||||
logger,
|
||||
enableFileCoverageInformation,
|
||||
}: InitConfigInputs,
|
||||
userConfig: UserConfig,
|
||||
): Promise<Config> {
|
||||
@@ -542,6 +552,7 @@ export async function initActionState(
|
||||
overlayDatabaseMode: OverlayDatabaseMode.None,
|
||||
useOverlayDatabaseCaching: false,
|
||||
repositoryProperties,
|
||||
enableFileCoverageInformation,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1408,11 +1419,8 @@ async function logGitVersionTelemetry(
|
||||
gitVersion: GitVersionInfo,
|
||||
): Promise<void> {
|
||||
if (config.languages.length > 0) {
|
||||
addDiagnostic(
|
||||
addNoLanguageDiagnostic(
|
||||
config,
|
||||
// Arbitrarily choose the first language. We could also choose all languages, but that
|
||||
// increases the risk of misinterpreting the data.
|
||||
config.languages[0],
|
||||
makeTelemetryDiagnostic(
|
||||
"codeql-action/git-version-telemetry",
|
||||
"Git version telemetry",
|
||||
@@ -1438,11 +1446,8 @@ async function logGeneratedFilesTelemetry(
|
||||
return;
|
||||
}
|
||||
|
||||
addDiagnostic(
|
||||
addNoLanguageDiagnostic(
|
||||
config,
|
||||
// Arbitrarily choose the first language. We could also choose all languages, but that
|
||||
// increases the risk of misinterpreting the data.
|
||||
config.languages[0],
|
||||
makeTelemetryDiagnostic(
|
||||
"codeql-action/generated-files-telemetry",
|
||||
"Generated files telemetry",
|
||||
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"bundleVersion": "codeql-bundle-v2.23.9",
|
||||
"cliVersion": "2.23.9",
|
||||
"priorBundleVersion": "codeql-bundle-v2.23.8",
|
||||
"priorCliVersion": "2.23.8"
|
||||
"bundleVersion": "codeql-bundle-v2.24.0",
|
||||
"cliVersion": "2.24.0",
|
||||
"priorBundleVersion": "codeql-bundle-v2.23.9",
|
||||
"priorCliVersion": "2.23.9"
|
||||
}
|
||||
@@ -117,6 +117,20 @@ export function addDiagnostic(
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a diagnostic that is not specific to any language. */
|
||||
export function addNoLanguageDiagnostic(
|
||||
config: Config,
|
||||
diagnostic: DiagnosticMessage,
|
||||
) {
|
||||
addDiagnostic(
|
||||
config,
|
||||
// Arbitrarily choose the first language. We could also choose all languages, but that
|
||||
// increases the risk of misinterpreting the data.
|
||||
config.languages[0],
|
||||
diagnostic,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the given diagnostic to the database.
|
||||
*
|
||||
|
||||
@@ -70,6 +70,8 @@ export enum Feature {
|
||||
OverlayAnalysisSwift = "overlay_analysis_swift",
|
||||
PythonDefaultIsToNotExtractStdlib = "python_default_is_to_not_extract_stdlib",
|
||||
QaTelemetryEnabled = "qa_telemetry_enabled",
|
||||
/** Note that this currently only disables baseline file coverage information. */
|
||||
SkipFileCoverageOnPrs = "skip_file_coverage_on_prs",
|
||||
UploadOverlayDbToApi = "upload_overlay_db_to_api",
|
||||
UseRepositoryProperties = "use_repository_properties",
|
||||
ValidateDbConfig = "validate_db_config",
|
||||
@@ -286,6 +288,15 @@ export const featureConfig = {
|
||||
legacyApi: true,
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.SkipFileCoverageOnPrs]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_SKIP_FILE_COVERAGE_ON_PRS",
|
||||
// For testing, this is not behind a CLI version check yet. However
|
||||
// before rolling this out externally, we should set a minimum version here
|
||||
// since current versions of the CodeQL CLI will log if baseline information
|
||||
// cannot be found when interpreting results.
|
||||
minimumVersion: undefined,
|
||||
},
|
||||
[Feature.UploadOverlayDbToApi]: {
|
||||
defaultValue: false,
|
||||
envVar: "CODEQL_ACTION_UPLOAD_OVERLAY_DB_TO_API",
|
||||
|
||||
@@ -78,11 +78,17 @@ export async function loadPropertiesFromApi(
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Loaded the following values for the repository properties:");
|
||||
for (const [property, value] of Object.entries(properties).sort(
|
||||
([nameA], [nameB]) => nameA.localeCompare(nameB),
|
||||
)) {
|
||||
logger.debug(` ${property}: ${value}`);
|
||||
if (Object.keys(properties).length === 0) {
|
||||
logger.debug("No known repository properties were found.");
|
||||
} else {
|
||||
logger.debug(
|
||||
"Loaded the following values for the repository properties:",
|
||||
);
|
||||
for (const [property, value] of Object.entries(properties).sort(
|
||||
([nameA], [nameB]) => nameA.localeCompare(nameB),
|
||||
)) {
|
||||
logger.debug(` ${property}: ${value}`);
|
||||
}
|
||||
}
|
||||
|
||||
return properties;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as fs from "fs";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as github from "@actions/github";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
@@ -129,48 +128,31 @@ export async function tryUploadSarifIfRunFailed(
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
): Promise<UploadFailedSarifResult> {
|
||||
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] !== "true") {
|
||||
// If analyze didn't complete successfully and the job status hasn't
|
||||
// already been set to Failure/ConfigurationError previously, this
|
||||
// means that something along the way failed in a step that is not
|
||||
// owned by the Action, for example a manual build step. We
|
||||
// consider this a configuration error.
|
||||
core.exportVariable(
|
||||
EnvVar.JOB_STATUS,
|
||||
process.env[EnvVar.JOB_STATUS] ?? JobStatus.ConfigErrorStatus,
|
||||
);
|
||||
|
||||
// If the only enabled analysis kind is `code-quality`, then we shouldn't
|
||||
// upload the failed SARIF to Code Scanning.
|
||||
if (!isCodeScanningEnabled(config)) {
|
||||
return {
|
||||
upload_failed_run_skipped_because: "Code Scanning is not enabled.",
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
return await maybeUploadFailedSarif(
|
||||
config,
|
||||
repositoryNwo,
|
||||
features,
|
||||
logger,
|
||||
);
|
||||
} catch (e) {
|
||||
logger.debug(
|
||||
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`,
|
||||
);
|
||||
return createFailedUploadFailedSarifResult(e);
|
||||
}
|
||||
} else {
|
||||
core.exportVariable(
|
||||
EnvVar.JOB_STATUS,
|
||||
process.env[EnvVar.JOB_STATUS] ?? JobStatus.SuccessStatus,
|
||||
);
|
||||
// Only upload the failed SARIF to Code scanning if Code scanning is enabled.
|
||||
if (!isCodeScanningEnabled(config)) {
|
||||
return {
|
||||
upload_failed_run_skipped_because: "Code Scanning is not enabled.",
|
||||
};
|
||||
}
|
||||
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true") {
|
||||
return {
|
||||
upload_failed_run_skipped_because:
|
||||
"Analyze Action completed successfully",
|
||||
};
|
||||
}
|
||||
try {
|
||||
return await maybeUploadFailedSarif(
|
||||
config,
|
||||
repositoryNwo,
|
||||
features,
|
||||
logger,
|
||||
);
|
||||
} catch (e) {
|
||||
logger.debug(
|
||||
`Failed to upload a SARIF file for this failed CodeQL code scanning run. ${e}`,
|
||||
);
|
||||
return createFailedUploadFailedSarifResult(e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function run(
|
||||
@@ -335,20 +317,3 @@ async function removeUploadedSarif(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the final job status sent in the `init-post` Action, based on the
|
||||
* current value of the JOB_STATUS environment variable. If the variable is
|
||||
* unset, or if its value is not one of the JobStatus enum values, returns
|
||||
* Unknown. Otherwise it returns the status set in the environment variable.
|
||||
*/
|
||||
export function getFinalJobStatus(): JobStatus {
|
||||
const jobStatusFromEnvironment = process.env[EnvVar.JOB_STATUS];
|
||||
if (
|
||||
!jobStatusFromEnvironment ||
|
||||
!Object.values(JobStatus).includes(jobStatusFromEnvironment as JobStatus)
|
||||
) {
|
||||
return JobStatus.UnknownStatus;
|
||||
}
|
||||
return jobStatusFromEnvironment as JobStatus;
|
||||
}
|
||||
+72
-4
@@ -14,12 +14,13 @@ import {
|
||||
import { getGitHubVersion } from "./api-client";
|
||||
import { CachingKind } from "./caching-utils";
|
||||
import { getCodeQL } from "./codeql";
|
||||
import { Config, getConfig } from "./config-utils";
|
||||
import { type Config, getConfig } from "./config-utils";
|
||||
import * as debugArtifacts from "./debug-artifacts";
|
||||
import {
|
||||
DependencyCachingUsageReport,
|
||||
getDependencyCacheUsage,
|
||||
} from "./dependency-caching";
|
||||
import { EnvVar } from "./environment";
|
||||
import { Features } from "./feature-flags";
|
||||
import * as gitUtils from "./git-utils";
|
||||
import * as initActionPostHelper from "./init-action-post-helper";
|
||||
@@ -33,6 +34,7 @@ import {
|
||||
getActionsStatus,
|
||||
ActionName,
|
||||
getJobStatusDisplayName,
|
||||
JobStatus,
|
||||
} from "./status-report";
|
||||
import { checkDiskUsage, checkGitHubVersionInRange, wrapError } from "./util";
|
||||
|
||||
@@ -85,7 +87,7 @@ async function run(startedAt: Date) {
|
||||
logger,
|
||||
);
|
||||
|
||||
// If we are analysing the default branch and some kind of caching is enabled,
|
||||
// If we are analyzing the default branch and some kind of caching is enabled,
|
||||
// then try to determine our overall cache usage for dependency caches. We only
|
||||
// do this under these circumstances to avoid slowing down analyses for PRs
|
||||
// and where caching may not be enabled.
|
||||
@@ -115,7 +117,7 @@ async function run(startedAt: Date) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
const jobStatus = initActionPostHelper.getFinalJobStatus();
|
||||
const jobStatus = getFinalJobStatus(config);
|
||||
logger.info(`CodeQL job status was ${getJobStatusDisplayName(jobStatus)}.`);
|
||||
|
||||
const statusReportBase = await createStatusReportBase(
|
||||
@@ -130,7 +132,7 @@ async function run(startedAt: Date) {
|
||||
const statusReport: InitPostStatusReport = {
|
||||
...statusReportBase,
|
||||
...uploadFailedSarifResult,
|
||||
job_status: initActionPostHelper.getFinalJobStatus(),
|
||||
job_status: jobStatus,
|
||||
dependency_caching_usage: dependencyCachingUsage,
|
||||
};
|
||||
logger.info("Sending status report for init-post step.");
|
||||
@@ -139,6 +141,72 @@ async function run(startedAt: Date) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the final job status to be reported in the status report.
|
||||
*
|
||||
* If the job status has already been set by another step, we use that.
|
||||
* Otherwise, we determine the job status based on whether the analyze step
|
||||
* completed successfully and whether we have a valid CodeQL config.
|
||||
*/
|
||||
function getFinalJobStatus(config: Config | undefined): JobStatus {
|
||||
const existingJobStatus = getJobStatusFromEnvironment();
|
||||
if (existingJobStatus !== undefined) {
|
||||
return existingJobStatus;
|
||||
}
|
||||
|
||||
let jobStatus: JobStatus;
|
||||
|
||||
if (process.env[EnvVar.ANALYZE_DID_COMPLETE_SUCCESSFULLY] === "true") {
|
||||
core.exportVariable(EnvVar.JOB_STATUS, JobStatus.SuccessStatus);
|
||||
jobStatus = JobStatus.SuccessStatus;
|
||||
} else if (config !== undefined) {
|
||||
// - We have computed a CodeQL config
|
||||
// - Analyze didn't complete successfully
|
||||
// - The job status hasn't already been set to Failure/ConfigurationError
|
||||
//
|
||||
// This means that something along the way failed in a step that is not
|
||||
// owned by the Action, for example a manual build step. We consider this a
|
||||
// configuration error.
|
||||
jobStatus = JobStatus.ConfigErrorStatus;
|
||||
} else {
|
||||
// If we didn't manage to compute a CodeQL config, it is unclear at this
|
||||
// point why the analyze Action didn't complete.
|
||||
// - One possibility is that the workflow run was cancelled. We could
|
||||
// consider determining workflow cancellation using the GitHub API, but
|
||||
// for now we treat all these cases as unknown.
|
||||
// - Another possibility is that we're running a workflow that only runs
|
||||
// `init`, for instance a workflow that was created before `setup-codeql`
|
||||
// was available and uses `init` just to set up the CodeQL tools.
|
||||
jobStatus = JobStatus.UnknownStatus;
|
||||
}
|
||||
|
||||
// This shouldn't be necessary, but in the odd case that we run more than one
|
||||
// `init` post step, ensure the job status is consistent between them.
|
||||
core.exportVariable(EnvVar.JOB_STATUS, jobStatus);
|
||||
return jobStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the job status from the environment variable, if it has been set.
|
||||
*
|
||||
* If the job status is invalid, return `UnknownStatus`.
|
||||
*/
|
||||
function getJobStatusFromEnvironment(): JobStatus | undefined {
|
||||
const jobStatusFromEnvironment = process.env[EnvVar.JOB_STATUS];
|
||||
|
||||
if (jobStatusFromEnvironment !== undefined) {
|
||||
// Validate the job status from the environment. If it is invalid, return unknown.
|
||||
if (
|
||||
Object.values(JobStatus).includes(jobStatusFromEnvironment as JobStatus)
|
||||
) {
|
||||
return jobStatusFromEnvironment as JobStatus;
|
||||
}
|
||||
return JobStatus.UnknownStatus;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async function runWrapper() {
|
||||
const startedAt = new Date();
|
||||
const logger = getActionsLogger();
|
||||
|
||||
+82
-18
@@ -2,6 +2,7 @@ import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as github from "@actions/github";
|
||||
import * as io from "@actions/io";
|
||||
import * as semver from "semver";
|
||||
import { v4 as uuidV4 } from "uuid";
|
||||
@@ -30,18 +31,23 @@ import {
|
||||
} from "./dependency-caching";
|
||||
import {
|
||||
addDiagnostic,
|
||||
addNoLanguageDiagnostic,
|
||||
flushDiagnostics,
|
||||
logUnwrittenDiagnostics,
|
||||
makeDiagnostic,
|
||||
makeTelemetryDiagnostic,
|
||||
} from "./diagnostics";
|
||||
import { EnvVar } from "./environment";
|
||||
import { Feature, Features } from "./feature-flags";
|
||||
import { loadPropertiesFromApi } from "./feature-flags/properties";
|
||||
import { Feature, FeatureEnablement, Features } from "./feature-flags";
|
||||
import {
|
||||
loadPropertiesFromApi,
|
||||
RepositoryProperties,
|
||||
} from "./feature-flags/properties";
|
||||
import {
|
||||
checkInstallPython311,
|
||||
checkPacksForOverlayCompatibility,
|
||||
cleanupDatabaseClusterDirectory,
|
||||
getFileCoverageInformationEnabled,
|
||||
initCodeQL,
|
||||
initConfig,
|
||||
runDatabaseInitCluster,
|
||||
@@ -53,7 +59,7 @@ import {
|
||||
OverlayBaseDatabaseDownloadStats,
|
||||
OverlayDatabaseMode,
|
||||
} from "./overlay-database-utils";
|
||||
import { getRepositoryNwo } from "./repository";
|
||||
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
||||
import { ToolsSource } from "./setup-codeql";
|
||||
import {
|
||||
ActionName,
|
||||
@@ -87,6 +93,8 @@ import {
|
||||
checkActionVersion,
|
||||
getErrorMessage,
|
||||
BuildMode,
|
||||
GitHubVersion,
|
||||
Result,
|
||||
} from "./util";
|
||||
import { checkWorkflow } from "./workflow";
|
||||
|
||||
@@ -237,12 +245,12 @@ async function run(startedAt: Date) {
|
||||
);
|
||||
|
||||
// Fetch the values of known repository properties that affect us.
|
||||
const enableRepoProps = await features.getValue(
|
||||
Feature.UseRepositoryProperties,
|
||||
const repositoryPropertiesResult = await loadRepositoryProperties(
|
||||
repositoryNwo,
|
||||
gitHubVersion,
|
||||
features,
|
||||
logger,
|
||||
);
|
||||
const repositoryProperties = enableRepoProps
|
||||
? await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo)
|
||||
: {};
|
||||
|
||||
// Create a unique identifier for this run.
|
||||
const jobRunUuid = uuidV4();
|
||||
@@ -334,6 +342,7 @@ async function run(startedAt: Date) {
|
||||
}
|
||||
|
||||
analysisKinds = await getAnalysisKinds(logger);
|
||||
const debugMode = getOptionalInput("debug") === "true" || core.isDebug();
|
||||
config = await initConfig(features, {
|
||||
analysisKinds,
|
||||
languagesInput: getOptionalInput("languages"),
|
||||
@@ -350,7 +359,7 @@ async function run(startedAt: Date) {
|
||||
// - The `init` Action is passed `debug: true`.
|
||||
// - Actions step debugging is enabled (e.g. by [enabling debug logging for a rerun](https://docs.github.com/en/actions/managing-workflow-runs/re-running-workflows-and-jobs#re-running-all-the-jobs-in-a-workflow),
|
||||
// or by setting the `ACTIONS_STEP_DEBUG` secret to `true`).
|
||||
debugMode: getOptionalInput("debug") === "true" || core.isDebug(),
|
||||
debugMode,
|
||||
debugArtifactName:
|
||||
getOptionalInput("debug-artifact-name") || DEFAULT_DEBUG_ARTIFACT_NAME,
|
||||
debugDatabaseName:
|
||||
@@ -363,10 +372,28 @@ async function run(startedAt: Date) {
|
||||
githubVersion: gitHubVersion,
|
||||
apiDetails,
|
||||
features,
|
||||
repositoryProperties,
|
||||
repositoryProperties: repositoryPropertiesResult.orElse({}),
|
||||
enableFileCoverageInformation: await getFileCoverageInformationEnabled(
|
||||
debugMode,
|
||||
repositoryNwo,
|
||||
features,
|
||||
),
|
||||
logger,
|
||||
});
|
||||
|
||||
if (repositoryPropertiesResult.isFailure()) {
|
||||
addNoLanguageDiagnostic(
|
||||
config,
|
||||
makeTelemetryDiagnostic(
|
||||
"codeql-action/repository-properties-load-failure",
|
||||
"Failed to load repository properties",
|
||||
{
|
||||
error: getErrorMessage(repositoryPropertiesResult.value),
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
await checkInstallPython311(config.languages, codeql);
|
||||
} catch (unwrappedError) {
|
||||
const error = wrapError(unwrappedError);
|
||||
@@ -429,11 +456,8 @@ async function run(startedAt: Date) {
|
||||
|
||||
// Log CodeQL download telemetry, if appropriate
|
||||
if (toolsDownloadStatusReport) {
|
||||
addDiagnostic(
|
||||
addNoLanguageDiagnostic(
|
||||
config,
|
||||
// Arbitrarily choose the first language. We could also choose all languages, but that
|
||||
// increases the risk of misinterpreting the data.
|
||||
config.languages[0],
|
||||
makeTelemetryDiagnostic(
|
||||
"codeql-action/bundle-download-telemetry",
|
||||
"CodeQL bundle download telemetry",
|
||||
@@ -775,6 +799,49 @@ async function run(startedAt: Date) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads [repository properties](https://docs.github.com/en/organizations/managing-organization-settings/managing-custom-properties-for-repositories-in-your-organization) if applicable.
|
||||
*/
|
||||
async function loadRepositoryProperties(
|
||||
repositoryNwo: RepositoryNwo,
|
||||
gitHubVersion: GitHubVersion,
|
||||
features: FeatureEnablement,
|
||||
logger: Logger,
|
||||
): Promise<Result<RepositoryProperties, unknown>> {
|
||||
// See if we can skip loading repository properties early. In particular,
|
||||
// repositories owned by users cannot have repository properties, so we can
|
||||
// skip the API call entirely in that case.
|
||||
const repositoryOwnerType = github.context.payload.repository?.owner.type;
|
||||
logger.debug(
|
||||
`Repository owner type is '${repositoryOwnerType ?? "unknown"}'.`,
|
||||
);
|
||||
if (repositoryOwnerType === "User") {
|
||||
logger.debug(
|
||||
"Skipping loading repository properties because the repository is owned by a user and " +
|
||||
"therefore cannot have repository properties.",
|
||||
);
|
||||
return Result.success({});
|
||||
}
|
||||
|
||||
if (!(await features.getValue(Feature.UseRepositoryProperties))) {
|
||||
logger.debug(
|
||||
"Skipping loading repository properties because the UseRepositoryProperties feature flag is disabled.",
|
||||
);
|
||||
return Result.success({});
|
||||
}
|
||||
|
||||
try {
|
||||
return Result.success(
|
||||
await loadPropertiesFromApi(gitHubVersion, logger, repositoryNwo),
|
||||
);
|
||||
} catch (error) {
|
||||
logger.warning(
|
||||
`Failed to load repository properties: ${getErrorMessage(error)}`,
|
||||
);
|
||||
return Result.failure(error);
|
||||
}
|
||||
}
|
||||
|
||||
function getTrapCachingEnabled(): boolean {
|
||||
// If the workflow specified something always respect that
|
||||
const trapCaching = getOptionalInput("trap-caching");
|
||||
@@ -791,11 +858,8 @@ async function recordZstdAvailability(
|
||||
config: configUtils.Config,
|
||||
zstdAvailability: ZstdAvailability,
|
||||
) {
|
||||
addDiagnostic(
|
||||
addNoLanguageDiagnostic(
|
||||
config,
|
||||
// Arbitrarily choose the first language. We could also choose all languages, but that
|
||||
// increases the risk of misinterpreting the data.
|
||||
config.languages[0],
|
||||
makeTelemetryDiagnostic(
|
||||
"codeql-action/zstd-availability",
|
||||
"Zstandard availability",
|
||||
|
||||
@@ -2,14 +2,20 @@ import * as fs from "fs";
|
||||
import path from "path";
|
||||
|
||||
import test, { ExecutionContext } from "ava";
|
||||
import * as sinon from "sinon";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { createStubCodeQL } from "./codeql";
|
||||
import { Feature } from "./feature-flags";
|
||||
import {
|
||||
checkPacksForOverlayCompatibility,
|
||||
cleanupDatabaseClusterDirectory,
|
||||
getFileCoverageInformationEnabled,
|
||||
} from "./init";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { parseRepositoryNwo } from "./repository";
|
||||
import {
|
||||
createFeatures,
|
||||
LoggedMessage,
|
||||
createTestConfig,
|
||||
getRecordingLogger,
|
||||
@@ -442,3 +448,61 @@ test(
|
||||
expectedResult: true,
|
||||
},
|
||||
);
|
||||
|
||||
test("file coverage information enabled when debugMode is true", async (t) => {
|
||||
t.true(
|
||||
await getFileCoverageInformationEnabled(
|
||||
true, // debugMode
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures([Feature.SkipFileCoverageOnPrs]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test("file coverage information enabled when not analyzing a pull request", async (t) => {
|
||||
sinon.stub(actionsUtil, "isAnalyzingPullRequest").returns(false);
|
||||
|
||||
t.true(
|
||||
await getFileCoverageInformationEnabled(
|
||||
false, // debugMode
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures([Feature.SkipFileCoverageOnPrs]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test("file coverage information enabled when owner is not 'github'", async (t) => {
|
||||
sinon.stub(actionsUtil, "isAnalyzingPullRequest").returns(true);
|
||||
|
||||
t.true(
|
||||
await getFileCoverageInformationEnabled(
|
||||
false, // debugMode
|
||||
parseRepositoryNwo("other-org/some-repo"),
|
||||
createFeatures([Feature.SkipFileCoverageOnPrs]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test("file coverage information enabled when feature flag is not enabled", async (t) => {
|
||||
sinon.stub(actionsUtil, "isAnalyzingPullRequest").returns(true);
|
||||
|
||||
t.true(
|
||||
await getFileCoverageInformationEnabled(
|
||||
false, // debugMode
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures([]),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test("file coverage information disabled when all conditions for skipping are met", async (t) => {
|
||||
sinon.stub(actionsUtil, "isAnalyzingPullRequest").returns(true);
|
||||
|
||||
t.false(
|
||||
await getFileCoverageInformationEnabled(
|
||||
false, // debugMode
|
||||
parseRepositoryNwo("github/codeql-action"),
|
||||
createFeatures([Feature.SkipFileCoverageOnPrs]),
|
||||
),
|
||||
);
|
||||
});
|
||||
+29
-2
@@ -5,13 +5,22 @@ import * as toolrunner from "@actions/exec/lib/toolrunner";
|
||||
import * as io from "@actions/io";
|
||||
import * as yaml from "js-yaml";
|
||||
|
||||
import { getOptionalInput, isSelfHostedRunner } from "./actions-util";
|
||||
import {
|
||||
getOptionalInput,
|
||||
isAnalyzingPullRequest,
|
||||
isSelfHostedRunner,
|
||||
} from "./actions-util";
|
||||
import { GitHubApiDetails } from "./api-client";
|
||||
import { CodeQL, setupCodeQL } from "./codeql";
|
||||
import * as configUtils from "./config-utils";
|
||||
import { CodeQLDefaultVersionInfo, FeatureEnablement } from "./feature-flags";
|
||||
import {
|
||||
CodeQLDefaultVersionInfo,
|
||||
Feature,
|
||||
FeatureEnablement,
|
||||
} from "./feature-flags";
|
||||
import { KnownLanguage, Language } from "./languages";
|
||||
import { Logger, withGroupAsync } from "./logging";
|
||||
import { RepositoryNwo } from "./repository";
|
||||
import { ToolsSource } from "./setup-codeql";
|
||||
import { ZstdAvailability } from "./tar";
|
||||
import { ToolsDownloadStatusReport } from "./tools-download";
|
||||
@@ -288,3 +297,21 @@ export function cleanupDatabaseClusterDirectory(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFileCoverageInformationEnabled(
|
||||
debugMode: boolean,
|
||||
repositoryNwo: RepositoryNwo,
|
||||
features: FeatureEnablement,
|
||||
): Promise<boolean> {
|
||||
return (
|
||||
// Always enable file coverage information in debug mode
|
||||
debugMode ||
|
||||
// We're most interested in speeding up PRs, and we want to keep
|
||||
// submitting file coverage information for the default branch since
|
||||
// it is used to populate the status page.
|
||||
!isAnalyzingPullRequest() ||
|
||||
// For now, restrict this feature to the GitHub org
|
||||
repositoryNwo.owner !== "github" ||
|
||||
!(await features.getValue(Feature.SkipFileCoverageOnPrs))
|
||||
);
|
||||
}
|
||||
+8
-100
@@ -2,29 +2,22 @@ import { ChildProcess, spawn } from "child_process";
|
||||
import * as path from "path";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as toolcache from "@actions/tool-cache";
|
||||
import { pki } from "node-forge";
|
||||
|
||||
import * as actionsUtil from "./actions-util";
|
||||
import { getApiDetails, getAuthorizationHeaderFor } from "./api-client";
|
||||
import { Config } from "./config-utils";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { getActionsLogger, Logger } from "./logging";
|
||||
import {
|
||||
Credential,
|
||||
credentialToStr,
|
||||
getCredentials,
|
||||
getDownloadUrl,
|
||||
getProxyBinaryPath,
|
||||
getSafeErrorMessage,
|
||||
parseLanguage,
|
||||
UPDATEJOB_PROXY,
|
||||
sendFailedStatusReport,
|
||||
sendSuccessStatusReport,
|
||||
} from "./start-proxy";
|
||||
import {
|
||||
ActionName,
|
||||
createStatusReportBase,
|
||||
getActionsStatus,
|
||||
sendStatusReport,
|
||||
sendUnhandledErrorStatusReport,
|
||||
StatusReportBase,
|
||||
} from "./status-report";
|
||||
import { ActionName, sendUnhandledErrorStatusReport } from "./status-report";
|
||||
import * as util from "./util";
|
||||
|
||||
const KEY_SIZE = 2048;
|
||||
@@ -94,35 +87,6 @@ function generateCertificateAuthority(): CertificateAuthority {
|
||||
return { cert: pem, key };
|
||||
}
|
||||
|
||||
interface StartProxyStatus extends StatusReportBase {
|
||||
// A comma-separated list of registry types which are configured for CodeQL.
|
||||
// This only includes registry types we support, not all that are configured.
|
||||
registry_types: string;
|
||||
}
|
||||
|
||||
async function sendSuccessStatusReport(
|
||||
startedAt: Date,
|
||||
config: Partial<Config>,
|
||||
registry_types: string[],
|
||||
logger: Logger,
|
||||
) {
|
||||
const statusReportBase = await createStatusReportBase(
|
||||
ActionName.StartProxy,
|
||||
"success",
|
||||
startedAt,
|
||||
config,
|
||||
await util.checkDiskUsage(logger),
|
||||
logger,
|
||||
);
|
||||
if (statusReportBase !== undefined) {
|
||||
const statusReport: StartProxyStatus = {
|
||||
...statusReportBase,
|
||||
registry_types: registry_types.join(","),
|
||||
};
|
||||
await sendStatusReport(statusReport);
|
||||
}
|
||||
}
|
||||
|
||||
async function run(startedAt: Date) {
|
||||
// To capture errors appropriately, keep as much code within the try-catch as
|
||||
// possible, and only use safe functions outside.
|
||||
@@ -181,25 +145,7 @@ async function run(startedAt: Date) {
|
||||
logger,
|
||||
);
|
||||
} catch (unwrappedError) {
|
||||
const error = util.wrapError(unwrappedError);
|
||||
core.setFailed(`start-proxy action failed: ${error.message}`);
|
||||
|
||||
// We skip sending the error message and stack trace here to avoid the possibility
|
||||
// of leaking any sensitive information into the telemetry.
|
||||
const errorStatusReportBase = await createStatusReportBase(
|
||||
ActionName.StartProxy,
|
||||
getActionsStatus(error),
|
||||
startedAt,
|
||||
{
|
||||
languages: language && [language],
|
||||
},
|
||||
await util.checkDiskUsage(logger),
|
||||
logger,
|
||||
"Error from start-proxy Action omitted",
|
||||
);
|
||||
if (errorStatusReportBase !== undefined) {
|
||||
await sendStatusReport(errorStatusReportBase);
|
||||
}
|
||||
await sendFailedStatusReport(logger, startedAt, language, unwrappedError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +160,7 @@ async function runWrapper() {
|
||||
await sendUnhandledErrorStatusReport(
|
||||
ActionName.StartProxy,
|
||||
startedAt,
|
||||
new Error("Error from start-proxy Action omitted"),
|
||||
getSafeErrorMessage(util.wrapError(error)),
|
||||
logger,
|
||||
);
|
||||
}
|
||||
@@ -277,42 +223,4 @@ async function startProxy(
|
||||
core.setOutput("proxy_urls", JSON.stringify(registry_urls));
|
||||
}
|
||||
|
||||
async function getProxyBinaryPath(logger: Logger): Promise<string> {
|
||||
const proxyFileName =
|
||||
process.platform === "win32" ? `${UPDATEJOB_PROXY}.exe` : UPDATEJOB_PROXY;
|
||||
const proxyInfo = await getDownloadUrl(logger);
|
||||
|
||||
let proxyBin = toolcache.find(proxyFileName, proxyInfo.version);
|
||||
if (!proxyBin) {
|
||||
const apiDetails = getApiDetails();
|
||||
const authorization = getAuthorizationHeaderFor(
|
||||
logger,
|
||||
apiDetails,
|
||||
proxyInfo.url,
|
||||
);
|
||||
const temp = await toolcache.downloadTool(
|
||||
proxyInfo.url,
|
||||
undefined,
|
||||
authorization,
|
||||
{
|
||||
accept: "application/octet-stream",
|
||||
},
|
||||
);
|
||||
const extracted = await toolcache.extractTar(temp);
|
||||
proxyBin = await toolcache.cacheDir(
|
||||
extracted,
|
||||
proxyFileName,
|
||||
proxyInfo.version,
|
||||
);
|
||||
}
|
||||
proxyBin = path.join(proxyBin, proxyFileName);
|
||||
return proxyBin;
|
||||
}
|
||||
|
||||
function credentialToStr(c: Credential): string {
|
||||
return `Type: ${c.type}; Host: ${c.host}; Url: ${c.url} Username: ${
|
||||
c.username
|
||||
}; Password: ${c.password !== undefined}; Token: ${c.token !== undefined}`;
|
||||
}
|
||||
|
||||
void runWrapper();
|
||||
+334
-3
@@ -1,16 +1,110 @@
|
||||
import test from "ava";
|
||||
import * as filepath from "path";
|
||||
|
||||
import * as core from "@actions/core";
|
||||
import * as toolcache from "@actions/tool-cache";
|
||||
import test, { ExecutionContext } from "ava";
|
||||
import sinon from "sinon";
|
||||
|
||||
import * as apiClient from "./api-client";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { getRunnerLogger } from "./logging";
|
||||
import { getRunnerLogger, Logger } from "./logging";
|
||||
import * as startProxyExports from "./start-proxy";
|
||||
import { parseLanguage } from "./start-proxy";
|
||||
import { setupTests } from "./testing-utils";
|
||||
import * as statusReport from "./status-report";
|
||||
import {
|
||||
checkExpectedLogMessages,
|
||||
getRecordingLogger,
|
||||
makeTestToken,
|
||||
setupTests,
|
||||
withRecordingLoggerAsync,
|
||||
} from "./testing-utils";
|
||||
import { ConfigurationError } from "./util";
|
||||
|
||||
setupTests(test);
|
||||
|
||||
const sendFailedStatusReportTest = test.macro({
|
||||
exec: async (
|
||||
t: ExecutionContext<unknown>,
|
||||
err: Error,
|
||||
expectedMessage: string,
|
||||
expectedStatus: statusReport.ActionStatus = "failure",
|
||||
) => {
|
||||
const now = new Date();
|
||||
|
||||
// Override core.setFailed to avoid it setting the program's exit code
|
||||
sinon.stub(core, "setFailed").returns();
|
||||
|
||||
const createStatusReportBase = sinon.stub(
|
||||
statusReport,
|
||||
"createStatusReportBase",
|
||||
);
|
||||
createStatusReportBase.resolves(undefined);
|
||||
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
await startProxyExports.sendFailedStatusReport(
|
||||
logger,
|
||||
now,
|
||||
undefined,
|
||||
err,
|
||||
);
|
||||
|
||||
// Check that the stub has been called exactly once, with the expected arguments,
|
||||
// but not with the message from the error.
|
||||
sinon.assert.calledOnceWithExactly(
|
||||
createStatusReportBase,
|
||||
statusReport.ActionName.StartProxy,
|
||||
expectedStatus,
|
||||
now,
|
||||
sinon.match.any,
|
||||
sinon.match.any,
|
||||
sinon.match.any,
|
||||
expectedMessage,
|
||||
);
|
||||
t.false(
|
||||
createStatusReportBase.calledWith(
|
||||
statusReport.ActionName.StartProxy,
|
||||
expectedStatus,
|
||||
now,
|
||||
sinon.match.any,
|
||||
sinon.match.any,
|
||||
sinon.match.any,
|
||||
sinon.match((msg: string) => msg.includes(err.message)),
|
||||
),
|
||||
"createStatusReportBase was called with the error message",
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
title: (providedTitle = "") => `sendFailedStatusReport - ${providedTitle}`,
|
||||
});
|
||||
|
||||
test(
|
||||
"reports generic error message for non-StartProxyError error",
|
||||
sendFailedStatusReportTest,
|
||||
new Error("Something went wrong today"),
|
||||
"Error from start-proxy Action omitted (Error).",
|
||||
);
|
||||
|
||||
test(
|
||||
"reports generic error message for non-StartProxyError error with safe error message",
|
||||
sendFailedStatusReportTest,
|
||||
new Error(
|
||||
startProxyExports.getStartProxyErrorMessage(
|
||||
startProxyExports.StartProxyErrorType.DownloadFailed,
|
||||
),
|
||||
),
|
||||
"Error from start-proxy Action omitted (Error).",
|
||||
);
|
||||
|
||||
test(
|
||||
"reports generic error message for ConfigurationError error",
|
||||
sendFailedStatusReportTest,
|
||||
new ConfigurationError("Something went wrong today"),
|
||||
"Error from start-proxy Action omitted (ConfigurationError).",
|
||||
"user-error",
|
||||
);
|
||||
|
||||
const toEncodedJSON = (data: any) =>
|
||||
Buffer.from(JSON.stringify(data)).toString("base64");
|
||||
|
||||
@@ -174,6 +268,37 @@ test("getCredentials throws an error when non-printable characters are used", as
|
||||
}
|
||||
});
|
||||
|
||||
test("getCredentials logs a warning when a PAT is used without a username", async (t) => {
|
||||
const loggedMessages = [];
|
||||
const logger = getRecordingLogger(loggedMessages);
|
||||
const likelyWrongCredentials = toEncodedJSON([
|
||||
{
|
||||
type: "git_server",
|
||||
host: "https://github.com/",
|
||||
password: `ghp_${makeTestToken()}`,
|
||||
},
|
||||
]);
|
||||
|
||||
const results = startProxyExports.getCredentials(
|
||||
logger,
|
||||
undefined,
|
||||
likelyWrongCredentials,
|
||||
undefined,
|
||||
);
|
||||
|
||||
// The configuration should be accepted, despite the likely problem.
|
||||
t.assert(results);
|
||||
t.is(results.length, 1);
|
||||
t.is(results[0].type, "git_server");
|
||||
t.is(results[0].host, "https://github.com/");
|
||||
t.assert(results[0].password?.startsWith("ghp_"));
|
||||
|
||||
// A warning should have been logged.
|
||||
checkExpectedLogMessages(t, loggedMessages, [
|
||||
"using a GitHub Personal Access Token (PAT), but no username was provided",
|
||||
]);
|
||||
});
|
||||
|
||||
test("parseLanguage", async (t) => {
|
||||
// Exact matches
|
||||
t.deepEqual(parseLanguage("csharp"), KnownLanguage.csharp);
|
||||
@@ -265,3 +390,209 @@ test("getDownloadUrl returns matching release asset", async (t) => {
|
||||
t.is(info.version, defaults.cliVersion);
|
||||
t.is(info.url, "url-we-want");
|
||||
});
|
||||
|
||||
test("credentialToStr - hides passwords", (t) => {
|
||||
const secret = "password123";
|
||||
const credential = {
|
||||
type: "maven_credential",
|
||||
password: secret,
|
||||
};
|
||||
|
||||
const str = startProxyExports.credentialToStr(credential);
|
||||
|
||||
t.false(str.includes(secret));
|
||||
t.is(
|
||||
"Type: maven_credential; Host: undefined; Url: undefined Username: undefined; Password: true; Token: false",
|
||||
str,
|
||||
);
|
||||
});
|
||||
|
||||
test("credentialToStr - hides tokens", (t) => {
|
||||
const secret = "password123";
|
||||
const credential = {
|
||||
type: "maven_credential",
|
||||
token: secret,
|
||||
};
|
||||
|
||||
const str = startProxyExports.credentialToStr(credential);
|
||||
|
||||
t.false(str.includes(secret));
|
||||
t.is(
|
||||
"Type: maven_credential; Host: undefined; Url: undefined Username: undefined; Password: false; Token: true",
|
||||
str,
|
||||
);
|
||||
});
|
||||
|
||||
test("getSafeErrorMessage - returns actual message for `StartProxyError`", (t) => {
|
||||
const error = new startProxyExports.StartProxyError(
|
||||
startProxyExports.StartProxyErrorType.DownloadFailed,
|
||||
);
|
||||
t.is(
|
||||
startProxyExports.getSafeErrorMessage(error),
|
||||
startProxyExports.getStartProxyErrorMessage(error.errorType),
|
||||
);
|
||||
});
|
||||
|
||||
test("getSafeErrorMessage - does not return message for arbitrary errors", (t) => {
|
||||
const error = new Error(
|
||||
startProxyExports.getStartProxyErrorMessage(
|
||||
startProxyExports.StartProxyErrorType.DownloadFailed,
|
||||
),
|
||||
);
|
||||
|
||||
const message = startProxyExports.getSafeErrorMessage(error);
|
||||
|
||||
t.not(message, error.message);
|
||||
t.assert(message.startsWith("Error from start-proxy Action omitted"));
|
||||
t.assert(message.includes(error.name));
|
||||
});
|
||||
|
||||
const wrapFailureTest = test.macro({
|
||||
exec: async (
|
||||
t: ExecutionContext<unknown>,
|
||||
setup: () => void,
|
||||
fn: (logger: Logger) => Promise<void>,
|
||||
) => {
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
setup();
|
||||
|
||||
await t.throwsAsync(fn(logger), {
|
||||
instanceOf: startProxyExports.StartProxyError,
|
||||
});
|
||||
});
|
||||
},
|
||||
title: (providedTitle) => `${providedTitle} - wraps errors on failure`,
|
||||
});
|
||||
|
||||
test("downloadProxy - returns file path on success", async (t) => {
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
const testPath = "/some/path";
|
||||
sinon.stub(toolcache, "downloadTool").resolves(testPath);
|
||||
|
||||
const result = await startProxyExports.downloadProxy(
|
||||
logger,
|
||||
"url",
|
||||
undefined,
|
||||
);
|
||||
t.is(result, testPath);
|
||||
});
|
||||
});
|
||||
|
||||
test(
|
||||
"downloadProxy",
|
||||
wrapFailureTest,
|
||||
() => {
|
||||
sinon.stub(toolcache, "downloadTool").throws();
|
||||
},
|
||||
async (logger) => {
|
||||
await startProxyExports.downloadProxy(logger, "url", undefined);
|
||||
},
|
||||
);
|
||||
|
||||
test("extractProxy - returns file path on success", async (t) => {
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
const testPath = "/some/path";
|
||||
sinon.stub(toolcache, "extractTar").resolves(testPath);
|
||||
|
||||
const result = await startProxyExports.extractProxy(logger, "/other/path");
|
||||
t.is(result, testPath);
|
||||
});
|
||||
});
|
||||
|
||||
test(
|
||||
"extractProxy",
|
||||
wrapFailureTest,
|
||||
() => {
|
||||
sinon.stub(toolcache, "extractTar").throws();
|
||||
},
|
||||
async (logger) => {
|
||||
await startProxyExports.extractProxy(logger, "path");
|
||||
},
|
||||
);
|
||||
|
||||
test("cacheProxy - returns file path on success", async (t) => {
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
const testPath = "/some/path";
|
||||
sinon.stub(toolcache, "cacheDir").resolves(testPath);
|
||||
|
||||
const result = await startProxyExports.cacheProxy(
|
||||
logger,
|
||||
"/other/path",
|
||||
"proxy",
|
||||
"1.0",
|
||||
);
|
||||
t.is(result, testPath);
|
||||
});
|
||||
});
|
||||
|
||||
test(
|
||||
"cacheProxy",
|
||||
wrapFailureTest,
|
||||
() => {
|
||||
sinon.stub(toolcache, "cacheDir").throws();
|
||||
},
|
||||
async (logger) => {
|
||||
await startProxyExports.cacheProxy(logger, "/other/path", "proxy", "1.0");
|
||||
},
|
||||
);
|
||||
|
||||
test("getProxyBinaryPath - returns path from tool cache if available", async (t) => {
|
||||
mockGetReleaseByTag();
|
||||
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
const toolcachePath = "/path/to/proxy/dir";
|
||||
sinon.stub(toolcache, "find").returns(toolcachePath);
|
||||
|
||||
const path = await startProxyExports.getProxyBinaryPath(logger);
|
||||
|
||||
t.assert(path);
|
||||
t.is(
|
||||
path,
|
||||
filepath.join(toolcachePath, startProxyExports.getProxyFilename()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("getProxyBinaryPath - downloads proxy if not in cache", async (t) => {
|
||||
const downloadUrl = "url-we-want";
|
||||
mockGetReleaseByTag([
|
||||
{ name: startProxyExports.getProxyPackage(), url: downloadUrl },
|
||||
]);
|
||||
|
||||
await withRecordingLoggerAsync(async (logger) => {
|
||||
const toolcachePath = "/path/to/proxy/dir";
|
||||
const find = sinon.stub(toolcache, "find").returns("");
|
||||
const getApiDetails = sinon.stub(apiClient, "getApiDetails").returns({
|
||||
auth: "",
|
||||
url: "",
|
||||
apiURL: "",
|
||||
});
|
||||
const getAuthorizationHeaderFor = sinon
|
||||
.stub(apiClient, "getAuthorizationHeaderFor")
|
||||
.returns(undefined);
|
||||
const archivePath = "/path/to/archive";
|
||||
const downloadTool = sinon
|
||||
.stub(toolcache, "downloadTool")
|
||||
.resolves(archivePath);
|
||||
const extractedPath = "/path/to/extracted";
|
||||
const extractTar = sinon
|
||||
.stub(toolcache, "extractTar")
|
||||
.resolves(extractedPath);
|
||||
const cacheDir = sinon.stub(toolcache, "cacheDir").resolves(toolcachePath);
|
||||
|
||||
const path = await startProxyExports.getProxyBinaryPath(logger);
|
||||
|
||||
t.assert(find.calledOnce);
|
||||
t.assert(getApiDetails.calledOnce);
|
||||
t.assert(getAuthorizationHeaderFor.calledOnce);
|
||||
t.assert(downloadTool.calledOnceWith(downloadUrl));
|
||||
t.assert(extractTar.calledOnceWith(archivePath));
|
||||
t.assert(cacheDir.calledOnceWith(extractedPath));
|
||||
|
||||
t.assert(path);
|
||||
t.is(
|
||||
path,
|
||||
filepath.join(toolcachePath, startProxyExports.getProxyFilename()),
|
||||
);
|
||||
});
|
||||
});
|
||||
+294
-2
@@ -1,11 +1,161 @@
|
||||
import * as core from "@actions/core";
|
||||
import * as path from "path";
|
||||
|
||||
import { getApiClient } from "./api-client";
|
||||
import * as core from "@actions/core";
|
||||
import * as toolcache from "@actions/tool-cache";
|
||||
|
||||
import {
|
||||
getApiClient,
|
||||
getApiDetails,
|
||||
getAuthorizationHeaderFor,
|
||||
} from "./api-client";
|
||||
import * as artifactScanner from "./artifact-scanner";
|
||||
import { Config } from "./config-utils";
|
||||
import * as defaults from "./defaults.json";
|
||||
import { KnownLanguage } from "./languages";
|
||||
import { Logger } from "./logging";
|
||||
import {
|
||||
ActionName,
|
||||
createStatusReportBase,
|
||||
getActionsStatus,
|
||||
sendStatusReport,
|
||||
StatusReportBase,
|
||||
} from "./status-report";
|
||||
import * as util from "./util";
|
||||
import { ConfigurationError, getErrorMessage, isDefined } from "./util";
|
||||
|
||||
/**
|
||||
* Enumerates specific error types for which we have corresponding error messages that
|
||||
* are safe to include in status reports.
|
||||
*/
|
||||
export enum StartProxyErrorType {
|
||||
DownloadFailed,
|
||||
ExtractionFailed,
|
||||
CacheFailed,
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns The error message corresponding to the error type.
|
||||
*/
|
||||
export function getStartProxyErrorMessage(
|
||||
errorType: StartProxyErrorType,
|
||||
): string {
|
||||
switch (errorType) {
|
||||
case StartProxyErrorType.DownloadFailed:
|
||||
return "Failed to download proxy archive.";
|
||||
case StartProxyErrorType.ExtractionFailed:
|
||||
return "Failed to extract proxy archive.";
|
||||
case StartProxyErrorType.CacheFailed:
|
||||
return "Failed to add proxy to toolcache";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to avoid accidentally leaking secrets that may be contained in exception
|
||||
* messages in the `start-proxy` action. Consequently, we don't report the messages
|
||||
* of arbitrary exceptions. This type of error ensures that the message is one from
|
||||
* `StartProxyErrorType` and therefore safe to include in a status report.
|
||||
*/
|
||||
export class StartProxyError extends Error {
|
||||
public readonly errorType: StartProxyErrorType;
|
||||
|
||||
constructor(errorType: StartProxyErrorType) {
|
||||
super();
|
||||
this.errorType = errorType;
|
||||
}
|
||||
}
|
||||
|
||||
interface StartProxyStatus extends StatusReportBase {
|
||||
// A comma-separated list of registry types which are configured for CodeQL.
|
||||
// This only includes registry types we support, not all that are configured.
|
||||
registry_types: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a status report for the `start-proxy` action indicating a successful outcome.
|
||||
*
|
||||
* @param startedAt When the action was started.
|
||||
* @param config The configuration used.
|
||||
* @param registry_types The types of registries that are configured.
|
||||
* @param logger The logger to use.
|
||||
*/
|
||||
export async function sendSuccessStatusReport(
|
||||
startedAt: Date,
|
||||
config: Partial<Config>,
|
||||
registry_types: string[],
|
||||
logger: Logger,
|
||||
) {
|
||||
const statusReportBase = await createStatusReportBase(
|
||||
ActionName.StartProxy,
|
||||
"success",
|
||||
startedAt,
|
||||
config,
|
||||
await util.checkDiskUsage(logger),
|
||||
logger,
|
||||
);
|
||||
if (statusReportBase !== undefined) {
|
||||
const statusReport: StartProxyStatus = {
|
||||
...statusReportBase,
|
||||
registry_types: registry_types.join(","),
|
||||
};
|
||||
await sendStatusReport(statusReport);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an error message for `error` that can safely be reported in a status report,
|
||||
* i.e. that does not contain sensitive information.
|
||||
*
|
||||
* @param error The error for which to get an error message.
|
||||
*/
|
||||
export function getSafeErrorMessage(error: Error): string {
|
||||
// If the error is a `StartProxyError`, resolve the error type to the corresponding
|
||||
// error message.
|
||||
if (error instanceof StartProxyError) {
|
||||
return getStartProxyErrorMessage(error.errorType);
|
||||
}
|
||||
|
||||
// Otherwise, omit the actual error message.
|
||||
return `Error from start-proxy Action omitted (${error.constructor.name}).`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a status report for the `start-proxy` action indicating a failure.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param startedAt When the action was started.
|
||||
* @param language The language provided as input, if any.
|
||||
* @param unwrappedError The exception that was thrown.
|
||||
*/
|
||||
export async function sendFailedStatusReport(
|
||||
logger: Logger,
|
||||
startedAt: Date,
|
||||
language: KnownLanguage | undefined,
|
||||
unwrappedError: unknown,
|
||||
) {
|
||||
const error = util.wrapError(unwrappedError);
|
||||
core.setFailed(`start-proxy action failed: ${error.message}`);
|
||||
|
||||
// To avoid the possibility of leaking sensitive information into the telemetry,
|
||||
// we don't include arbitrary error messages. Instead, `getSafeErrorMessage` will
|
||||
// return a generic message that includes the type of the error, unless it can decide
|
||||
// that the message is safe to include.
|
||||
const statusReportMessage = getSafeErrorMessage(error);
|
||||
const errorStatusReportBase = await createStatusReportBase(
|
||||
ActionName.StartProxy,
|
||||
getActionsStatus(error),
|
||||
startedAt,
|
||||
{
|
||||
languages: language && [language],
|
||||
},
|
||||
await util.checkDiskUsage(logger),
|
||||
logger,
|
||||
statusReportMessage,
|
||||
);
|
||||
if (errorStatusReportBase !== undefined) {
|
||||
await sendStatusReport(errorStatusReportBase);
|
||||
}
|
||||
}
|
||||
|
||||
export const UPDATEJOB_PROXY = "update-job-proxy";
|
||||
export const UPDATEJOB_PROXY_VERSION = "v2.0.20250624110901";
|
||||
const UPDATEJOB_PROXY_URL_PREFIX =
|
||||
@@ -62,6 +212,13 @@ export function parseLanguage(language: string): KnownLanguage | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function isPAT(value: string) {
|
||||
return artifactScanner.isAuthToken(value, [
|
||||
artifactScanner.GITHUB_PAT_CLASSIC_PATTERN,
|
||||
artifactScanner.GITHUB_PAT_FINE_GRAINED_PATTERN,
|
||||
]);
|
||||
}
|
||||
|
||||
const LANGUAGE_TO_REGISTRY_TYPE: Partial<Record<KnownLanguage, string[]>> = {
|
||||
java: ["maven_repository"],
|
||||
csharp: ["nuget_feed"],
|
||||
@@ -161,6 +318,19 @@ export function getCredentials(
|
||||
);
|
||||
}
|
||||
|
||||
// If the password or token looks like a GitHub PAT, warn if no username is configured.
|
||||
if (
|
||||
!isDefined(e.username) &&
|
||||
((isDefined(e.password) && isPAT(e.password)) ||
|
||||
(isDefined(e.token) && isPAT(e.token)))
|
||||
) {
|
||||
logger.warning(
|
||||
`A ${e.type} private registry is configured for ${e.host || e.url} using a GitHub Personal Access Token (PAT), but no username was provided. ` +
|
||||
`This may not work correctly. When configuring a private registry using a PAT, select "Username and password" and enter the username of the user ` +
|
||||
`who generated the PAT.`,
|
||||
);
|
||||
}
|
||||
|
||||
out.push({
|
||||
type: e.type,
|
||||
host: e.host,
|
||||
@@ -256,3 +426,125 @@ export async function getDownloadUrl(
|
||||
version: UPDATEJOB_PROXY_VERSION,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretty-prints a `Credential` value to a string, but hides the actual password or token values.
|
||||
*
|
||||
* @param c The credential to convert to a string.
|
||||
*/
|
||||
export function credentialToStr(c: Credential): string {
|
||||
return `Type: ${c.type}; Host: ${c.host}; Url: ${c.url} Username: ${
|
||||
c.username
|
||||
}; Password: ${c.password !== undefined}; Token: ${c.token !== undefined}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to download a file from `url` into the toolcache.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param url The URL to download the proxy binary from.
|
||||
* @param authorization The authorization information to use.
|
||||
* @returns If successful, the path to the downloaded file.
|
||||
*/
|
||||
export async function downloadProxy(
|
||||
logger: Logger,
|
||||
url: string,
|
||||
authorization: string | undefined,
|
||||
) {
|
||||
try {
|
||||
// Download the proxy archive from `url`. We let `downloadTool` choose where
|
||||
// to store it. The path to the downloaded file will be returned if successful.
|
||||
return toolcache.downloadTool(url, /* dest: */ undefined, authorization, {
|
||||
accept: "application/octet-stream",
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to download proxy archive from ${url}: ${getErrorMessage(error)}`,
|
||||
);
|
||||
throw new StartProxyError(StartProxyErrorType.DownloadFailed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to extract the proxy binary from the `archive`.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param archive The archive to extract.
|
||||
* @returns The path to the extracted file(s).
|
||||
*/
|
||||
export async function extractProxy(logger: Logger, archive: string) {
|
||||
try {
|
||||
return await toolcache.extractTar(archive);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to extract proxy archive from ${archive}: ${getErrorMessage(error)}`,
|
||||
);
|
||||
throw new StartProxyError(StartProxyErrorType.ExtractionFailed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to store the proxy in the toolcache.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @param source The source path to add to the toolcache.
|
||||
* @param filename The filename of the proxy binary.
|
||||
* @param version The version of the proxy.
|
||||
* @returns The path to the directory in the toolcache.
|
||||
*/
|
||||
export async function cacheProxy(
|
||||
logger: Logger,
|
||||
source: string,
|
||||
filename: string,
|
||||
version: string,
|
||||
) {
|
||||
try {
|
||||
return await toolcache.cacheDir(source, filename, version);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to add proxy archive from ${source} to toolcache: ${getErrorMessage(error)}`,
|
||||
);
|
||||
throw new StartProxyError(StartProxyErrorType.CacheFailed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the platform-specific filename of the proxy binary.
|
||||
*/
|
||||
export function getProxyFilename() {
|
||||
return process.platform === "win32"
|
||||
? `${UPDATEJOB_PROXY}.exe`
|
||||
: UPDATEJOB_PROXY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a path to the proxy binary. If possible, this function will find the proxy in the
|
||||
* runner's tool cache. Otherwise, it downloads and extracts the proxy binary,
|
||||
* and stores it in the tool cache.
|
||||
*
|
||||
* @param logger The logger to use.
|
||||
* @returns The path to the proxy binary.
|
||||
*/
|
||||
export async function getProxyBinaryPath(logger: Logger): Promise<string> {
|
||||
const proxyFileName = getProxyFilename();
|
||||
const proxyInfo = await getDownloadUrl(logger);
|
||||
|
||||
let proxyBin = toolcache.find(proxyFileName, proxyInfo.version);
|
||||
if (!proxyBin) {
|
||||
const apiDetails = getApiDetails();
|
||||
const authorization = getAuthorizationHeaderFor(
|
||||
logger,
|
||||
apiDetails,
|
||||
proxyInfo.url,
|
||||
);
|
||||
const temp = await downloadProxy(logger, proxyInfo.url, authorization);
|
||||
const extracted = await extractProxy(logger, temp);
|
||||
proxyBin = await cacheProxy(
|
||||
logger,
|
||||
extracted,
|
||||
proxyFileName,
|
||||
proxyInfo.version,
|
||||
);
|
||||
}
|
||||
return path.join(proxyBin, proxyFileName);
|
||||
}
|
||||
@@ -208,6 +208,23 @@ export function checkExpectedLogMessages(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises a recording logger and calls `body` with it.
|
||||
*
|
||||
* @param body The test that requires a recording logger.
|
||||
* @returns The logged messages.
|
||||
*/
|
||||
export async function withRecordingLoggerAsync(
|
||||
body: (logger: Logger) => Promise<void>,
|
||||
): Promise<LoggedMessage[]> {
|
||||
const messages = [];
|
||||
const logger = getRecordingLogger(messages);
|
||||
|
||||
await body(logger);
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
/** Mock the HTTP request to the feature flags enablement API endpoint. */
|
||||
export function mockFeatureFlagApiEndpoint(
|
||||
responseStatusCode: number,
|
||||
@@ -408,7 +425,14 @@ export function createTestConfig(overrides: Partial<Config>): Config {
|
||||
overlayDatabaseMode: OverlayDatabaseMode.None,
|
||||
useOverlayDatabaseCaching: false,
|
||||
repositoryProperties: {},
|
||||
enableFileCoverageInformation: true,
|
||||
} satisfies Config,
|
||||
overrides,
|
||||
);
|
||||
}
|
||||
|
||||
export function makeTestToken(length: number = 36) {
|
||||
const chars =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
return chars.repeat(Math.ceil(length / chars.length)).slice(0, length);
|
||||
}
|
||||
@@ -563,3 +563,28 @@ test("joinAtMost - truncates list if array is > than limit", (t) => {
|
||||
t.assert(result.includes("test5"));
|
||||
t.false(result.includes("test6"));
|
||||
});
|
||||
|
||||
test("Result.success creates a success result", (t) => {
|
||||
const result = util.Result.success("test value");
|
||||
t.true(result.isSuccess());
|
||||
t.false(result.isFailure());
|
||||
t.is(result.value, "test value");
|
||||
});
|
||||
|
||||
test("Result.failure creates a failure result", (t) => {
|
||||
const error = new Error("test error");
|
||||
const result = util.Result.failure(error);
|
||||
t.false(result.isSuccess());
|
||||
t.true(result.isFailure());
|
||||
t.is(result.value, error);
|
||||
});
|
||||
|
||||
test("Result.orElse returns the value for a success result", (t) => {
|
||||
const result = util.Result.success("success value");
|
||||
t.is(result.orElse("default value"), "success value");
|
||||
});
|
||||
|
||||
test("Result.orElse returns the default value for a failure result", (t) => {
|
||||
const result = util.Result.failure(new Error("test error"));
|
||||
t.is(result.orElse("default value"), "default value");
|
||||
});
|
||||
+40
@@ -1292,3 +1292,43 @@ export function joinAtMost(
|
||||
|
||||
return array.join(separator);
|
||||
}
|
||||
|
||||
/** A success result. */
|
||||
type Success<T> = Result<T, never>;
|
||||
/** A failure result. */
|
||||
type Failure<E> = Result<never, E>;
|
||||
|
||||
/**
|
||||
* A simple result type representing either a success or a failure.
|
||||
*/
|
||||
export class Result<T, E> {
|
||||
private constructor(
|
||||
private readonly _ok: boolean,
|
||||
public readonly value: T | E,
|
||||
) {}
|
||||
|
||||
/** Creates a success result. */
|
||||
static success<T>(value: T): Success<T> {
|
||||
return new Result(true, value) as Success<T>;
|
||||
}
|
||||
|
||||
/** Creates a failure result. */
|
||||
static failure<E>(value: E): Failure<E> {
|
||||
return new Result(false, value) as Failure<E>;
|
||||
}
|
||||
|
||||
/** Whether this result represents a success. */
|
||||
isSuccess(): this is Success<T> {
|
||||
return this._ok;
|
||||
}
|
||||
|
||||
/** Whether this result represents a failure. */
|
||||
isFailure(): this is Failure<E> {
|
||||
return !this._ok;
|
||||
}
|
||||
|
||||
/** Get the value if this is a success, or return the default value if this is a failure. */
|
||||
orElse<U>(defaultValue: U): T | U {
|
||||
return this.isSuccess() ? this.value : defaultValue;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"lib": ["ES2021"],
|
||||
"target": "ES2021",
|
||||
"lib": ["ES2022"],
|
||||
"target": "ES2022",
|
||||
"module": "commonjs",
|
||||
"outDir": "./build",
|
||||
"rootDir": "./src",
|
||||
|
||||
Reference in new issue
Block a user