mirror of
https://github.com/github/codeql-action.git
synced 2026-10-21 02:01:27 +00:00
Compare commits
30 Commits
releases/v
...
mbg/use-gi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9e3972d38 | ||
|
|
1c350b1564 | ||
|
|
1772d44790 | ||
|
|
0a458f10ac | ||
|
|
7a6e2f798f | ||
|
|
46d3daa879 | ||
|
|
2edace40f1 | ||
|
|
e5b217aeb5 | ||
|
|
3ec43abae3 | ||
|
|
3afe9c01db | ||
|
|
8844fb33e0 | ||
|
|
8884b5b423 | ||
|
|
b2bf75026d | ||
|
|
f2547e0e83 | ||
|
|
f728bb6678 | ||
|
|
c1641847bb | ||
|
|
047c751d92 | ||
|
|
f6e8dce502 | ||
|
|
a08b587b61 | ||
|
|
bfe264b559 | ||
|
|
f9b4185b99 | ||
|
|
66c96fdc35 | ||
|
|
1d30a842cd | ||
|
|
1b0a617641 | ||
|
|
96501a33ac | ||
|
|
a2438139ce | ||
|
|
e0625309c3 | ||
|
|
61bfcffab9 | ||
|
|
102e46e9d1 | ||
|
|
0735d7910f |
4
.github/workflows/__analysis-kinds.yml
generated
vendored
4
.github/workflows/__analysis-kinds.yml
generated
vendored
@@ -87,7 +87,7 @@ jobs:
|
|||||||
post-processed-sarif-path: '${{ runner.temp }}/post-processed'
|
post-processed-sarif-path: '${{ runner.temp }}/post-processed'
|
||||||
|
|
||||||
- name: Upload SARIF files
|
- name: Upload SARIF files
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: |
|
name: |
|
||||||
analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||||
@@ -95,7 +95,7 @@ jobs:
|
|||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
- name: Upload post-processed SARIF
|
- name: Upload post-processed SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: |
|
name: |
|
||||||
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||||
|
|||||||
2
.github/workflows/__config-export.yml
generated
vendored
2
.github/workflows/__config-export.yml
generated
vendored
@@ -65,7 +65,7 @@ jobs:
|
|||||||
output: '${{ runner.temp }}/results'
|
output: '${{ runner.temp }}/results'
|
||||||
upload-database: false
|
upload-database: false
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||||
|
|||||||
2
.github/workflows/__config-input.yml
generated
vendored
2
.github/workflows/__config-input.yml
generated
vendored
@@ -47,7 +47,7 @@ jobs:
|
|||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|||||||
2
.github/workflows/__diagnostics-export.yml
generated
vendored
2
.github/workflows/__diagnostics-export.yml
generated
vendored
@@ -76,7 +76,7 @@ jobs:
|
|||||||
output: '${{ runner.temp }}/results'
|
output: '${{ runner.temp }}/results'
|
||||||
upload-database: false
|
upload-database: false
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||||
|
|||||||
2
.github/workflows/__export-file-baseline-information.yml
generated
vendored
2
.github/workflows/__export-file-baseline-information.yml
generated
vendored
@@ -97,7 +97,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
output: '${{ runner.temp }}/results'
|
output: '${{ runner.temp }}/results'
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||||
|
|||||||
2
.github/workflows/__job-run-uuid-sarif.yml
generated
vendored
2
.github/workflows/__job-run-uuid-sarif.yml
generated
vendored
@@ -62,7 +62,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
output: '${{ runner.temp }}/results'
|
output: '${{ runner.temp }}/results'
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: '${{ runner.temp }}/results/javascript.sarif'
|
path: '${{ runner.temp }}/results/javascript.sarif'
|
||||||
|
|||||||
2
.github/workflows/__packaging-codescanning-config-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-codescanning-config-inputs-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
|||||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||||
cache: false
|
cache: false
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|||||||
2
.github/workflows/__packaging-config-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-config-inputs-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
|||||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||||
cache: false
|
cache: false
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|||||||
2
.github/workflows/__packaging-config-js.yml
generated
vendored
2
.github/workflows/__packaging-config-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
|||||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||||
cache: false
|
cache: false
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|||||||
2
.github/workflows/__packaging-inputs-js.yml
generated
vendored
2
.github/workflows/__packaging-inputs-js.yml
generated
vendored
@@ -80,7 +80,7 @@ jobs:
|
|||||||
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
go-version: ${{ inputs.go-version || '>=1.21.0' }}
|
||||||
cache: false
|
cache: false
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ jobs:
|
|||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||||
- name: Check expected artifacts exist
|
- name: Check expected artifacts exist
|
||||||
run: |
|
run: |
|
||||||
LANGUAGES="cpp csharp go java javascript python"
|
LANGUAGES="cpp csharp go java javascript python"
|
||||||
|
|||||||
2
.github/workflows/debug-artifacts-safe.yml
vendored
2
.github/workflows/debug-artifacts-safe.yml
vendored
@@ -82,7 +82,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Download all artifacts
|
- name: Download all artifacts
|
||||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||||
- name: Check expected artifacts exist
|
- name: Check expected artifacts exist
|
||||||
run: |
|
run: |
|
||||||
VERSIONS="stable-v2.20.7 default linked nightly-latest"
|
VERSIONS="stable-v2.20.7 default linked nightly-latest"
|
||||||
|
|||||||
2
.github/workflows/post-release-mergeback.yml
vendored
2
.github/workflows/post-release-mergeback.yml
vendored
@@ -47,7 +47,7 @@ jobs:
|
|||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # ensure we have all tags and can push commits
|
fetch-depth: 0 # ensure we have all tags and can push commits
|
||||||
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
8
.github/workflows/pr-checks.yml
vendored
8
.github/workflows/pr-checks.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
|||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
@@ -110,7 +110,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
@@ -175,7 +175,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Upload repo size comment
|
- name: Upload repo size comment
|
||||||
if: steps.fetch-base.outcome == 'success'
|
if: steps.fetch-base.outcome == 'success'
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: repo-size-comment
|
name: repo-size-comment
|
||||||
path: ${{ runner.temp }}/repo-size/
|
path: ${{ runner.temp }}/repo-size/
|
||||||
@@ -223,7 +223,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Download repo size comment
|
- name: Download repo size comment
|
||||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||||
with:
|
with:
|
||||||
name: repo-size-comment
|
name: repo-size-comment
|
||||||
path: repo-size-comment
|
path: repo-size-comment
|
||||||
|
|||||||
2
.github/workflows/query-filters.yml
vendored
2
.github/workflows/query-filters.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
- name: Install Node.js
|
- name: Install Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: npm
|
cache: npm
|
||||||
|
|||||||
2
.github/workflows/rebuild.yml
vendored
2
.github/workflows/rebuild.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
|||||||
ref: ${{ env.HEAD_REF }}
|
ref: ${{ env.HEAD_REF }}
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
2
.github/workflows/update-bundle.yml
vendored
2
.github/workflows/update-bundle.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
|||||||
git config --global user.name "github-actions[bot]"
|
git config --global user.name "github-actions[bot]"
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||||
with:
|
with:
|
||||||
node-version: 24
|
node-version: 24
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
|
See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
|
||||||
|
|
||||||
|
## [UNRELEASED]
|
||||||
|
|
||||||
|
No user facing changes.
|
||||||
|
|
||||||
## 4.39.0 - 15 Oct 2026
|
## 4.39.0 - 15 Oct 2026
|
||||||
|
|
||||||
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205)
|
- _Breaking change_: Bump the minimum required CodeQL bundle version to 2.20.7. [#4205](https://github.com/github/codeql-action/pull/4205)
|
||||||
|
|||||||
244
lib/entry-points.js
generated
244
lib/entry-points.js
generated
@@ -26401,7 +26401,7 @@ var require_utils4 = __commonJS({
|
|||||||
})();
|
})();
|
||||||
Object.defineProperty(exports2, "__esModule", { value: true });
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
||||||
exports2.GitHub = exports2.defaults = exports2.context = void 0;
|
exports2.GitHub = exports2.defaults = exports2.context = void 0;
|
||||||
exports2.getOctokitOptions = getOctokitOptions2;
|
exports2.getOctokitOptions = getOctokitOptions;
|
||||||
var Context = __importStar2(require_context());
|
var Context = __importStar2(require_context());
|
||||||
var Utils = __importStar2(require_utils3());
|
var Utils = __importStar2(require_utils3());
|
||||||
var core_1 = (init_dist_src2(), __toCommonJS(dist_src_exports));
|
var core_1 = (init_dist_src2(), __toCommonJS(dist_src_exports));
|
||||||
@@ -26417,7 +26417,7 @@ var require_utils4 = __commonJS({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports2.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports2.defaults);
|
exports2.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports2.defaults);
|
||||||
function getOctokitOptions2(token, options) {
|
function getOctokitOptions(token, options) {
|
||||||
const opts = Object.assign({}, options || {});
|
const opts = Object.assign({}, options || {});
|
||||||
const auth2 = Utils.getAuthString(token, opts);
|
const auth2 = Utils.getAuthString(token, opts);
|
||||||
if (auth2) {
|
if (auth2) {
|
||||||
@@ -140010,7 +140010,7 @@ var require_utils10 = __commonJS({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports2.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports2.defaults);
|
exports2.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports2.defaults);
|
||||||
function getOctokitOptions2(token, options) {
|
function getOctokitOptions(token, options) {
|
||||||
const opts = Object.assign({}, options || {});
|
const opts = Object.assign({}, options || {});
|
||||||
const auth2 = Utils.getAuthString(token, opts);
|
const auth2 = Utils.getAuthString(token, opts);
|
||||||
if (auth2) {
|
if (auth2) {
|
||||||
@@ -140018,7 +140018,7 @@ var require_utils10 = __commonJS({
|
|||||||
}
|
}
|
||||||
return opts;
|
return opts;
|
||||||
}
|
}
|
||||||
exports2.getOctokitOptions = getOctokitOptions2;
|
exports2.getOctokitOptions = getOctokitOptions;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -169558,7 +169558,6 @@ function checkSchema(schema, obj, options = {}, path30 = "") {
|
|||||||
// src/util.ts
|
// src/util.ts
|
||||||
var BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json";
|
var BASE_DATABASE_OIDS_FILE_NAME = "base-database-oids.json";
|
||||||
var BROKEN_VERSIONS = ["0.0.0-20211207"];
|
var BROKEN_VERSIONS = ["0.0.0-20211207"];
|
||||||
var GITHUB_DOTCOM_URL = "https://github.com";
|
|
||||||
var DEFAULT_DEBUG_ARTIFACT_NAME = "debug-artifacts";
|
var DEFAULT_DEBUG_ARTIFACT_NAME = "debug-artifacts";
|
||||||
var DEFAULT_DEBUG_DATABASE_NAME = "db";
|
var DEFAULT_DEBUG_DATABASE_NAME = "db";
|
||||||
var DEFAULT_RESERVED_RAM_SCALING_FACTOR = 0.05;
|
var DEFAULT_RESERVED_RAM_SCALING_FACTOR = 0.05;
|
||||||
@@ -169774,34 +169773,6 @@ function getGeneratedSuitePath(config, language) {
|
|||||||
"config-queries.qls"
|
"config-queries.qls"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
function parseGitHubUrl(inputUrl) {
|
|
||||||
const originalUrl = inputUrl;
|
|
||||||
if (inputUrl.indexOf("://") === -1) {
|
|
||||||
inputUrl = `https://${inputUrl}`;
|
|
||||||
}
|
|
||||||
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
|
||||||
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
|
||||||
}
|
|
||||||
let url2;
|
|
||||||
try {
|
|
||||||
url2 = new URL(inputUrl);
|
|
||||||
} catch {
|
|
||||||
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
|
||||||
}
|
|
||||||
if (url2.hostname === "github.com" || url2.hostname === "api.github.com") {
|
|
||||||
return GITHUB_DOTCOM_URL;
|
|
||||||
}
|
|
||||||
if (url2.pathname.indexOf("/api/v3") !== -1) {
|
|
||||||
url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3"));
|
|
||||||
}
|
|
||||||
if (url2.hostname.startsWith("api.")) {
|
|
||||||
url2.hostname = url2.hostname.substring(4);
|
|
||||||
}
|
|
||||||
if (!url2.pathname.endsWith("/")) {
|
|
||||||
url2.pathname = `${url2.pathname}/`;
|
|
||||||
}
|
|
||||||
return url2.toString();
|
|
||||||
}
|
|
||||||
var CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR = "CODEQL_ACTION_WARNED_ABOUT_VERSION";
|
var CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR = "CODEQL_ACTION_WARNED_ABOUT_VERSION";
|
||||||
var hasBeenWarnedAboutVersion = false;
|
var hasBeenWarnedAboutVersion = false;
|
||||||
function checkGitHubVersionInRange(version, logger2) {
|
function checkGitHubVersionInRange(version, logger2) {
|
||||||
@@ -170183,7 +170154,7 @@ function getDiffRangesJsonFilePath(env = getEnv()) {
|
|||||||
return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME);
|
return path2.join(getTemporaryDirectory(env), PR_DIFF_RANGE_JSON_FILENAME);
|
||||||
}
|
}
|
||||||
function getActionVersion() {
|
function getActionVersion() {
|
||||||
return "4.39.0";
|
return "4.39.1";
|
||||||
}
|
}
|
||||||
function getWorkflowEventName(env = getEnv()) {
|
function getWorkflowEventName(env = getEnv()) {
|
||||||
return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);
|
return env.getRequired("GITHUB_EVENT_NAME" /* GITHUB_EVENT_NAME */);
|
||||||
@@ -170659,6 +170630,50 @@ retry.VERSION = VERSION7;
|
|||||||
// src/api-client.ts
|
// src/api-client.ts
|
||||||
var import_undici = __toESM(require_undici());
|
var import_undici = __toESM(require_undici());
|
||||||
|
|
||||||
|
// src/github.ts
|
||||||
|
var GITHUB_DOTCOM_URL = "https://github.com";
|
||||||
|
var GITHUB_DOTCOM_API_URL = "https://api.github.com";
|
||||||
|
function parseGitHubUrl(inputUrl) {
|
||||||
|
const originalUrl = inputUrl;
|
||||||
|
if (inputUrl.indexOf("://") === -1) {
|
||||||
|
inputUrl = `https://${inputUrl}`;
|
||||||
|
}
|
||||||
|
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
||||||
|
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
||||||
|
}
|
||||||
|
let url2;
|
||||||
|
try {
|
||||||
|
url2 = new URL(inputUrl);
|
||||||
|
} catch {
|
||||||
|
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
||||||
|
}
|
||||||
|
if (url2.hostname === "github.com" || url2.hostname === "api.github.com") {
|
||||||
|
return GITHUB_DOTCOM_URL;
|
||||||
|
}
|
||||||
|
if (url2.pathname.indexOf("/api/v3") !== -1) {
|
||||||
|
url2.pathname = url2.pathname.substring(0, url2.pathname.indexOf("/api/v3"));
|
||||||
|
}
|
||||||
|
if (url2.hostname.startsWith("api.")) {
|
||||||
|
url2.hostname = url2.hostname.substring(4);
|
||||||
|
}
|
||||||
|
if (!url2.pathname.endsWith("/")) {
|
||||||
|
url2.pathname = `${url2.pathname}/`;
|
||||||
|
}
|
||||||
|
return url2.toString();
|
||||||
|
}
|
||||||
|
function getCurrentInstance(env) {
|
||||||
|
return {
|
||||||
|
url: env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
||||||
|
apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function getDotcomInstance() {
|
||||||
|
return {
|
||||||
|
url: GITHUB_DOTCOM_URL,
|
||||||
|
apiURL: GITHUB_DOTCOM_API_URL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// src/repository.ts
|
// src/repository.ts
|
||||||
function isRepositoryNwoStr(val) {
|
function isRepositoryNwoStr(val) {
|
||||||
return val.includes("/");
|
return val.includes("/");
|
||||||
@@ -170723,48 +170738,80 @@ function makeProxyRequestOptions(dispatcher) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
var InstanceApiClient = class {
|
||||||
|
client;
|
||||||
|
apiDetails;
|
||||||
|
authorizationHeader;
|
||||||
|
constructor(apiDetails, clientOptions = {}) {
|
||||||
|
this.apiDetails = apiDetails;
|
||||||
|
this.client = createApiClientWithDetails(apiDetails, clientOptions);
|
||||||
|
const token = this.apiDetails.auth?.trim();
|
||||||
|
if (token !== void 0 && token !== "") {
|
||||||
|
this.authorizationHeader = `token ${token}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Gets a value for the `Authorization` header for a request to `url`; or `undefined` if the
|
||||||
|
* `Authorization` header should not be set for `url`.
|
||||||
|
*
|
||||||
|
* @param logger The logger to use for debugging messages.
|
||||||
|
* @param url The URL for which we want to add an `Authorization` header.
|
||||||
|
*/
|
||||||
|
getAuthorizationHeaderFor(logger2, url2) {
|
||||||
|
if (this.authorizationHeader === void 0) {
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
if (url2.startsWith(`${this.apiDetails.url}/`) || this.apiDetails.apiURL && url2.startsWith(`${this.apiDetails.apiURL}/`)) {
|
||||||
|
logger2.debug(`Providing an authorization token.`);
|
||||||
|
return this.authorizationHeader;
|
||||||
|
}
|
||||||
|
logger2.debug(`Not using an authorization token.`);
|
||||||
|
return void 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
function createApiClientWithDetails(apiDetails, { allowExternal = false, proxy = void 0 } = {}) {
|
function createApiClientWithDetails(apiDetails, { allowExternal = false, proxy = void 0 } = {}) {
|
||||||
const auth2 = allowExternal && apiDetails.externalRepoAuth || apiDetails.auth;
|
const auth2 = allowExternal && apiDetails.externalRepoAuth !== void 0 ? apiDetails.externalRepoAuth : apiDetails.auth;
|
||||||
const retryingOctokit = githubUtils.GitHub.plugin(retry);
|
const retryingOctokit = githubUtils.GitHub.plugin(retry);
|
||||||
const requestOptions = makeProxyRequestOptions(proxy);
|
const requestOptions = makeProxyRequestOptions(proxy);
|
||||||
return new retryingOctokit(
|
const opts = {
|
||||||
githubUtils.getOctokitOptions(auth2, {
|
auth: auth2 !== void 0 && auth2.trim() !== "" ? `token ${auth2}` : void 0,
|
||||||
baseUrl: apiDetails.apiURL,
|
baseUrl: apiDetails.apiURL,
|
||||||
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
||||||
log: {
|
log: {
|
||||||
debug: core6.debug,
|
debug: core6.debug,
|
||||||
info: core6.info,
|
info: core6.info,
|
||||||
warn: core6.warning,
|
warn: core6.warning,
|
||||||
error: core6.error
|
error: core6.error
|
||||||
},
|
},
|
||||||
request: requestOptions,
|
request: requestOptions,
|
||||||
retry: {
|
retry: {
|
||||||
doNotRetry: DO_NOT_RETRY_STATUSES
|
doNotRetry: DO_NOT_RETRY_STATUSES
|
||||||
}
|
}
|
||||||
})
|
};
|
||||||
);
|
return new retryingOctokit(opts);
|
||||||
}
|
}
|
||||||
function getApiDetails(env = getEnv()) {
|
function getApiDetails(env = getEnv()) {
|
||||||
return {
|
return {
|
||||||
auth: getRequiredInput("token"),
|
auth: getRequiredInput("token"),
|
||||||
url: env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
...getCurrentInstance(env)
|
||||||
apiURL: env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function getApiClient(env = getEnv()) {
|
function getApiClient(env = getEnv(), apiDetails) {
|
||||||
return createApiClientWithDetails(getApiDetails(env));
|
return createApiClientWithDetails(apiDetails ?? getApiDetails(env));
|
||||||
|
}
|
||||||
|
function getDotcomApiDetails(env) {
|
||||||
|
if (env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */) === GITHUB_DOTCOM_URL) {
|
||||||
|
return getApiDetails(env);
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
auth: void 0,
|
||||||
|
...getDotcomInstance()
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function getApiClientWithExternalAuth(apiDetails, proxy) {
|
function getApiClientWithExternalAuth(apiDetails, proxy) {
|
||||||
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
||||||
}
|
}
|
||||||
function getAuthorizationHeaderFor(logger2, apiDetails, url2) {
|
|
||||||
if (url2.startsWith(`${apiDetails.url}/`) || apiDetails.apiURL && url2.startsWith(`${apiDetails.apiURL}/`)) {
|
|
||||||
logger2.debug(`Providing an authorization token.`);
|
|
||||||
return `token ${apiDetails.auth}`;
|
|
||||||
}
|
|
||||||
logger2.debug(`Not using an authorization token.`);
|
|
||||||
return void 0;
|
|
||||||
}
|
|
||||||
var cachedGitHubVersion = void 0;
|
var cachedGitHubVersion = void 0;
|
||||||
async function getGitHubVersionFromApi(apiClient, apiDetails) {
|
async function getGitHubVersionFromApi(apiClient, apiDetails) {
|
||||||
if (parseGitHubUrl(apiDetails.url) === GITHUB_DOTCOM_URL) {
|
if (parseGitHubUrl(apiDetails.url) === GITHUB_DOTCOM_URL) {
|
||||||
@@ -175770,38 +175817,38 @@ function getCodeQLActionRepository(action) {
|
|||||||
`The value of '${"GITHUB_ACTION_REPOSITORY" /* GITHUB_ACTION_REPOSITORY */}' is '${actionRepository}', which does not match the expected 'owner/repo' format.`
|
`The value of '${"GITHUB_ACTION_REPOSITORY" /* GITHUB_ACTION_REPOSITORY */}' is '${actionRepository}', which does not match the expected 'owner/repo' format.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
var DEFAULT_DOWNLOAD_SOURCE = [
|
var isSameDownloadSource = ([srcInstance, srcRepo], [otherInstance, otherRepo]) => {
|
||||||
GITHUB_DOTCOM_URL,
|
return srcInstance.url === otherInstance.url && srcRepo === otherRepo;
|
||||||
CODEQL_DEFAULT_ACTION_REPOSITORY
|
|
||||||
];
|
|
||||||
var isSameDownloadSource = ([srcUrl, srcRepo], [otherUrl, otherRepo]) => {
|
|
||||||
return srcUrl === otherUrl && srcRepo === otherRepo;
|
|
||||||
};
|
};
|
||||||
function getDefaultDotcomDownloadURL(tagName, assetName) {
|
function getDefaultDotcomDownloadURL(tagName, assetName) {
|
||||||
return `${GITHUB_DOTCOM_URL}/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${assetName}`;
|
return `${GITHUB_DOTCOM_URL}/${CODEQL_DEFAULT_ACTION_REPOSITORY}/releases/download/${tagName}/${assetName}`;
|
||||||
}
|
}
|
||||||
async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName, assetKind = "CodeQL bundle") {
|
async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName, assetKind = "CodeQL bundle") {
|
||||||
const codeQLActionRepository = getCodeQLActionRepository(action);
|
const codeQLActionRepository = getCodeQLActionRepository(action);
|
||||||
|
const defaultDownloadSource = [
|
||||||
|
getDotcomApiDetails(action.env),
|
||||||
|
CODEQL_DEFAULT_ACTION_REPOSITORY
|
||||||
|
];
|
||||||
const potentialDownloadSources = [
|
const potentialDownloadSources = [
|
||||||
// This GitHub instance, and this Action.
|
// This GitHub instance, and this Action.
|
||||||
[apiDetails.url, codeQLActionRepository],
|
[apiDetails, codeQLActionRepository],
|
||||||
// This GitHub instance, and the canonical Action.
|
// This GitHub instance, and the canonical Action.
|
||||||
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
[apiDetails, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||||
// GitHub.com, and the canonical Action.
|
// GitHub.com, and the canonical Action.
|
||||||
DEFAULT_DOWNLOAD_SOURCE
|
defaultDownloadSource
|
||||||
];
|
];
|
||||||
const uniqueDownloadSources = potentialDownloadSources.filter(
|
const uniqueDownloadSources = potentialDownloadSources.filter(
|
||||||
(source, index2, self2) => {
|
(source, index2, self2) => {
|
||||||
return !self2.slice(0, index2).some((other) => isSameDownloadSource(source, other));
|
return !self2.slice(0, index2).some((other) => isSameDownloadSource(source, other));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
for (const [instanceURL, repository] of uniqueDownloadSources) {
|
for (const [instance8, repository] of uniqueDownloadSources) {
|
||||||
if (isSameDownloadSource(DEFAULT_DOWNLOAD_SOURCE, [instanceURL, repository])) {
|
if (isSameDownloadSource(defaultDownloadSource, [instance8, repository])) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const { owner: repositoryOwner, repo: repositoryName } = parseRepositoryNwo(repository);
|
const { owner: repositoryOwner, repo: repositoryName } = parseRepositoryNwo(repository);
|
||||||
try {
|
try {
|
||||||
const release2 = await getApiClient().rest.repos.getReleaseByTag({
|
const release2 = await getApiClient(action.env, instance8).rest.repos.getReleaseByTag({
|
||||||
owner: repositoryOwner,
|
owner: repositoryOwner,
|
||||||
repo: repositoryName,
|
repo: repositoryName,
|
||||||
tag: tagName
|
tag: tagName
|
||||||
@@ -175809,14 +175856,14 @@ async function getCodeQLAssetDownloadURL(action, apiDetails, tagName, assetName,
|
|||||||
for (const asset of release2.data.assets) {
|
for (const asset of release2.data.assets) {
|
||||||
if (asset.name === assetName) {
|
if (asset.name === assetName) {
|
||||||
action.logger.info(
|
action.logger.info(
|
||||||
`Found ${assetKind} ${assetName} in ${repository} on ${instanceURL} with URL ${asset.url}.`
|
`Found ${assetKind} ${assetName} in ${repository} on ${instance8.apiURL} with URL ${asset.url}.`
|
||||||
);
|
);
|
||||||
return asset.url;
|
return asset.url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
action.logger.info(
|
action.logger.info(
|
||||||
`Looked for ${assetKind} ${assetName} in ${repository} on ${instanceURL} but got error ${e}.`
|
`Looked for ${assetKind} ${assetName} in ${repository} on ${instance8.apiURL} but got error ${e}.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176637,7 +176684,8 @@ async function getCodeQLSource(toolsInput, defaultCliVersion, rawLanguages, othe
|
|||||||
cliVersion: cliVersion2,
|
cliVersion: cliVersion2,
|
||||||
compressionMethod,
|
compressionMethod,
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: resolvedVersion ?? "unknown"
|
toolsVersion: resolvedVersion ?? "unknown",
|
||||||
|
apiDetails
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger2) {
|
async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger2) {
|
||||||
@@ -176651,7 +176699,7 @@ async function tryGetFallbackToolcacheVersion(cliVersion2, tagName, logger2) {
|
|||||||
);
|
);
|
||||||
return fallbackVersion;
|
return fallbackVersion;
|
||||||
}
|
}
|
||||||
var downloadCodeQL = async function(source, apiDetails, tarVersion, tempDir, logger2) {
|
var downloadCodeQL = async function(source, tarVersion, tempDir, logger2) {
|
||||||
const { bundle, compressionMethod } = source;
|
const { bundle, compressionMethod } = source;
|
||||||
const codeqlURL = bundle.url;
|
const codeqlURL = bundle.url;
|
||||||
const parsedCodeQLURL = new URL(codeqlURL);
|
const parsedCodeQLURL = new URL(codeqlURL);
|
||||||
@@ -176663,11 +176711,8 @@ var downloadCodeQL = async function(source, apiDetails, tarVersion, tempDir, log
|
|||||||
if (searchParams.has("token")) {
|
if (searchParams.has("token")) {
|
||||||
logger2.debug("CodeQL tools URL contains an authorization token.");
|
logger2.debug("CodeQL tools URL contains an authorization token.");
|
||||||
} else {
|
} else {
|
||||||
authorization = getAuthorizationHeaderFor(
|
const client = new InstanceApiClient(source.apiDetails);
|
||||||
logger2,
|
authorization = client.getAuthorizationHeaderFor(logger2, codeqlURL);
|
||||||
apiDetails,
|
|
||||||
codeqlURL
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const toolcacheDestination = getToolcacheDestination({ logger: logger2 }, source);
|
const toolcacheDestination = getToolcacheDestination({ logger: logger2 }, source);
|
||||||
const extractedBundlePath = toolcacheDestination.orElse(
|
const extractedBundlePath = toolcacheDestination.orElse(
|
||||||
@@ -176789,7 +176834,6 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
|||||||
const result = await downloadCodeQLBundle(
|
const result = await downloadCodeQLBundle(
|
||||||
{ env: getEnv(), features, logger: logger2 },
|
{ env: getEnv(), features, logger: logger2 },
|
||||||
source,
|
source,
|
||||||
apiDetails,
|
|
||||||
zstdAvailability.version,
|
zstdAvailability.version,
|
||||||
tempDir
|
tempDir
|
||||||
);
|
);
|
||||||
@@ -176809,19 +176853,13 @@ async function setupCodeQLBundle(toolsInput, apiDetails, tempDir, variant, defau
|
|||||||
toolsVersion: source.toolsVersion
|
toolsVersion: source.toolsVersion
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, tempDir) {
|
async function downloadCodeQLBundle(action, source, tarVersion, tempDir) {
|
||||||
const { bundle } = source;
|
const { bundle } = source;
|
||||||
const { logger: logger2 } = action;
|
const { logger: logger2 } = action;
|
||||||
await tryDeleteToolcacheBundles(action);
|
await tryDeleteToolcacheBundles(action);
|
||||||
const startTime = import_perf_hooks4.performance.now();
|
const startTime = import_perf_hooks4.performance.now();
|
||||||
try {
|
try {
|
||||||
return await downloadCodeQL(
|
return await downloadCodeQL(source, tarVersion, tempDir, logger2);
|
||||||
source,
|
|
||||||
apiDetails,
|
|
||||||
tarVersion,
|
|
||||||
tempDir,
|
|
||||||
logger2
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (bundle.kind !== "per-language" || bundle.combinedBundleURL === void 0 || asHTTPError(e)?.status !== 404) {
|
if (bundle.kind !== "per-language" || bundle.combinedBundleURL === void 0 || asHTTPError(e)?.status !== 404) {
|
||||||
throw e;
|
throw e;
|
||||||
@@ -176832,7 +176870,6 @@ async function downloadCodeQLBundle(action, source, apiDetails, tarVersion, temp
|
|||||||
...source,
|
...source,
|
||||||
bundle: { kind: "combined", url: bundle.combinedBundleURL }
|
bundle: { kind: "combined", url: bundle.combinedBundleURL }
|
||||||
},
|
},
|
||||||
apiDetails,
|
|
||||||
tarVersion,
|
tarVersion,
|
||||||
tempDir,
|
tempDir,
|
||||||
logger2
|
logger2
|
||||||
@@ -178490,8 +178527,8 @@ async function recordClearCleanupSizes(codeql, config, reports, logger2) {
|
|||||||
report.clear_cleanup_measurement_duration_ms = durationMs;
|
report.clear_cleanup_measurement_duration_ms = durationMs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails) {
|
async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundledDb, bundledDbSize, apiDetails, env = getEnv()) {
|
||||||
const client = getApiClient();
|
const client = getApiClient(env, apiDetails);
|
||||||
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
||||||
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
||||||
let uploadsBaseUrl = uploadsUrl.toString();
|
let uploadsBaseUrl = uploadsUrl.toString();
|
||||||
@@ -178512,7 +178549,6 @@ async function uploadBundledDatabase(repositoryNwo, language, commitOid, bundled
|
|||||||
commit_oid: commitOid,
|
commit_oid: commitOid,
|
||||||
data: bundledDbReadStream,
|
data: bundledDbReadStream,
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `token ${apiDetails.auth}`,
|
|
||||||
"Content-Type": "application/zip",
|
"Content-Type": "application/zip",
|
||||||
"Content-Length": bundledDbSize
|
"Content-Length": bundledDbSize
|
||||||
},
|
},
|
||||||
@@ -180011,6 +180047,7 @@ async function shouldDisableCombineSarifFiles(sarifObjects, githubVersion) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger2) {
|
async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, logger2) {
|
||||||
|
const env = getEnv();
|
||||||
logger2.info("Combining SARIF files using the CodeQL CLI");
|
logger2.info("Combining SARIF files using the CodeQL CLI");
|
||||||
const sarifObjects = sarifFiles.map(readSarifFile);
|
const sarifObjects = sarifFiles.map(readSarifFile);
|
||||||
const deprecationWarningMessage = gitHubVersion.type === "GitHub Enterprise Server" /* GHES */ ? "and will be removed in GitHub Enterprise Server 3.18" : "and will be removed in July 2025";
|
const deprecationWarningMessage = gitHubVersion.type === "GitHub Enterprise Server" /* GHES */ ? "and will be removed in GitHub Enterprise Server 3.18" : "and will be removed in July 2025";
|
||||||
@@ -180043,8 +180080,7 @@ async function combineSarifFilesUsingCLI(sarifFiles, gitHubVersion, features, lo
|
|||||||
externalRepoAuth: getOptionalInput(
|
externalRepoAuth: getOptionalInput(
|
||||||
"external-repository-token"
|
"external-repository-token"
|
||||||
),
|
),
|
||||||
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
|
...getCurrentInstance(env)
|
||||||
apiURL: getRequiredEnvParam("GITHUB_API_URL")
|
|
||||||
};
|
};
|
||||||
const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type);
|
const codeQLDefaultVersionInfo = await features.getEnabledDefaultCliVersions(gitHubVersion.type);
|
||||||
const initCodeQLResult = await initCodeQL(
|
const initCodeQLResult = await initCodeQL(
|
||||||
@@ -186450,8 +186486,7 @@ async function run3(actionState) {
|
|||||||
apiDetails = {
|
apiDetails = {
|
||||||
auth: getRequiredInput("token"),
|
auth: getRequiredInput("token"),
|
||||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||||
url: actionState.env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
...getCurrentInstance(actionState.env)
|
||||||
apiURL: actionState.env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
|
||||||
};
|
};
|
||||||
const gitHubVersion = await getGitHubVersion();
|
const gitHubVersion = await getGitHubVersion();
|
||||||
checkGitHubVersionInRange(gitHubVersion, logger2);
|
checkGitHubVersionInRange(gitHubVersion, logger2);
|
||||||
@@ -187493,8 +187528,7 @@ async function run6(actionState) {
|
|||||||
const apiDetails = {
|
const apiDetails = {
|
||||||
auth: getRequiredInput("token"),
|
auth: getRequiredInput("token"),
|
||||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||||
url: actionState.env.getRequired("GITHUB_SERVER_URL" /* GITHUB_SERVER_URL */),
|
...getCurrentInstance(actionState.env)
|
||||||
apiURL: actionState.env.getRequired("GITHUB_API_URL" /* GITHUB_API_URL */)
|
|
||||||
};
|
};
|
||||||
const gitHubVersion = await getGitHubVersion();
|
const gitHubVersion = await getGitHubVersion();
|
||||||
checkGitHubVersionInRange(gitHubVersion, logger2);
|
checkGitHubVersionInRange(gitHubVersion, logger2);
|
||||||
@@ -187912,6 +187946,7 @@ async function getProxyBinaryPath(action, apiDetails) {
|
|||||||
const logger2 = action.logger;
|
const logger2 = action.logger;
|
||||||
logger2.startGroup("Setting up authentication proxy");
|
logger2.startGroup("Setting up authentication proxy");
|
||||||
try {
|
try {
|
||||||
|
const client = new InstanceApiClient(apiDetails);
|
||||||
const proxyFileName = getProxyFilename();
|
const proxyFileName = getProxyFilename();
|
||||||
const proxyInfo = await getDownloadUrl(action, apiDetails);
|
const proxyInfo = await getDownloadUrl(action, apiDetails);
|
||||||
logger2.info(
|
logger2.info(
|
||||||
@@ -187922,9 +187957,8 @@ async function getProxyBinaryPath(action, apiDetails) {
|
|||||||
logger2.info(
|
logger2.info(
|
||||||
`Authentication proxy is not in the toolcache. Will try to download it from '${proxyInfo.url}'.`
|
`Authentication proxy is not in the toolcache. Will try to download it from '${proxyInfo.url}'.`
|
||||||
);
|
);
|
||||||
const authorization = getAuthorizationHeaderFor(
|
const authorization = client.getAuthorizationHeaderFor(
|
||||||
logger2,
|
logger2,
|
||||||
apiDetails,
|
|
||||||
proxyInfo.url
|
proxyInfo.url
|
||||||
);
|
);
|
||||||
const temp = await downloadProxy(logger2, proxyInfo.url, authorization);
|
const temp = await downloadProxy(logger2, proxyInfo.url, authorization);
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "4.39.0",
|
"version": "4.39.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "4.39.0",
|
"version": "4.39.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"pr-checks"
|
"pr-checks"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "codeql",
|
"name": "codeql",
|
||||||
"version": "4.39.0",
|
"version": "4.39.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "CodeQL action",
|
"description": "CodeQL action",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ steps:
|
|||||||
post-processed-sarif-path: "${{ runner.temp }}/post-processed"
|
post-processed-sarif-path: "${{ runner.temp }}/post-processed"
|
||||||
|
|
||||||
- name: Upload SARIF files
|
- name: Upload SARIF files
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: |
|
name: |
|
||||||
analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||||
@@ -54,7 +54,7 @@ steps:
|
|||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
- name: Upload post-processed SARIF
|
- name: Upload post-processed SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: |
|
name: |
|
||||||
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ steps:
|
|||||||
output: "${{ runner.temp }}/results"
|
output: "${{ runner.temp }}/results"
|
||||||
upload-database: false
|
upload-database: false
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ steps:
|
|||||||
output: "${{ runner.temp }}/results"
|
output: "${{ runner.temp }}/results"
|
||||||
upload-database: false
|
upload-database: false
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ steps:
|
|||||||
with:
|
with:
|
||||||
output: "${{ runner.temp }}/results"
|
output: "${{ runner.temp }}/results"
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ steps:
|
|||||||
with:
|
with:
|
||||||
output: "${{ runner.temp }}/results"
|
output: "${{ runner.temp }}/results"
|
||||||
- name: Upload SARIF
|
- name: Upload SARIF
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
|
||||||
path: "${{ runner.temp }}/results/javascript.sarif"
|
path: "${{ runner.temp }}/results/javascript.sarif"
|
||||||
|
|||||||
@@ -215,8 +215,8 @@ const languageSetups: LanguageSetups = {
|
|||||||
name: "Install Node.js",
|
name: "Install Node.js",
|
||||||
uses: pinnedUses(
|
uses: pinnedUses(
|
||||||
"actions/setup-node",
|
"actions/setup-node",
|
||||||
"820762786026740c76f36085b0efc47a31fe5020",
|
"949feb2413d6458794dcd2491c4babbbce0c15c1",
|
||||||
"v7.0.0",
|
"v7.1.0",
|
||||||
),
|
),
|
||||||
with: {
|
with: {
|
||||||
"node-version": defaultLanguageVersions.javascript,
|
"node-version": defaultLanguageVersions.javascript,
|
||||||
|
|||||||
@@ -8,7 +8,14 @@ import * as actionsUtil from "./actions-util";
|
|||||||
import * as api from "./api-client";
|
import * as api from "./api-client";
|
||||||
import { DO_NOT_RETRY_STATUSES } from "./api-client";
|
import { DO_NOT_RETRY_STATUSES } from "./api-client";
|
||||||
import { ActionsEnvVars, RegistryProxyVars } from "./environment";
|
import { ActionsEnvVars, RegistryProxyVars } from "./environment";
|
||||||
import { callee, getTestEnv, setupTests } from "./testing-utils";
|
import { GITHUB_DOTCOM_API_URL, GITHUB_DOTCOM_URL } from "./github";
|
||||||
|
import {
|
||||||
|
callee,
|
||||||
|
getTestEnv,
|
||||||
|
RecordingLogger,
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
setupTests,
|
||||||
|
} from "./testing-utils";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
|
|
||||||
setupTests(test);
|
setupTests(test);
|
||||||
@@ -284,3 +291,62 @@ test("makeProxyRequestOptions - returns fetch with custom proxy", async (t) => {
|
|||||||
githubUtils.defaults.request,
|
githubUtils.defaults.request,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"getApiClientWithExternalAuth constructs clients with or without tokens",
|
||||||
|
(t) => {
|
||||||
|
t.notThrows(() => {
|
||||||
|
api.getApiClientWithExternalAuth(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
api.getApiClientWithExternalAuth({
|
||||||
|
...SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
auth: undefined,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test("getAuthorizationHeaderFor - returns undefined if there's no token", (t) => {
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
|
||||||
|
for (const authValue of [undefined, "", " "]) {
|
||||||
|
const client = new api.InstanceApiClient({
|
||||||
|
...SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
auth: authValue,
|
||||||
|
});
|
||||||
|
t.is(
|
||||||
|
client.getAuthorizationHeaderFor(logger, `${GITHUB_DOTCOM_URL}/github`),
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getAuthorizationHeaderFor - returns header value with token if url is allowed", (t) => {
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
const client = new api.InstanceApiClient({
|
||||||
|
...SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const url of [
|
||||||
|
`${GITHUB_DOTCOM_URL}/github`,
|
||||||
|
`${GITHUB_DOTCOM_API_URL}/github`,
|
||||||
|
]) {
|
||||||
|
t.is(
|
||||||
|
client.getAuthorizationHeaderFor(logger, url),
|
||||||
|
`token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getAuthorizationHeaderFor - returns undefined if url is not allowed", (t) => {
|
||||||
|
const logger = new RecordingLogger();
|
||||||
|
const client = new api.InstanceApiClient({
|
||||||
|
...SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const url of [
|
||||||
|
`https://localhost/github`,
|
||||||
|
`https://api.localhost/github`,
|
||||||
|
]) {
|
||||||
|
t.is(client.getAuthorizationHeaderFor(logger, url), undefined);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import * as core from "@actions/core";
|
import * as core from "@actions/core";
|
||||||
import * as githubUtils from "@actions/github/lib/utils";
|
import * as githubUtils from "@actions/github/lib/utils";
|
||||||
|
import type { OctokitOptions } from "@octokit/core";
|
||||||
import * as retry from "@octokit/plugin-retry";
|
import * as retry from "@octokit/plugin-retry";
|
||||||
import { RequestRequestOptions } from "@octokit/types";
|
import { RequestRequestOptions } from "@octokit/types";
|
||||||
import {
|
import {
|
||||||
@@ -12,26 +13,34 @@ import {
|
|||||||
import type { ActionState } from "./action-common";
|
import type { ActionState } from "./action-common";
|
||||||
import { getActionVersion, getRequiredInput } from "./actions-util";
|
import { getActionVersion, getRequiredInput } from "./actions-util";
|
||||||
import {
|
import {
|
||||||
ActionsEnvVars,
|
|
||||||
EnvVar,
|
EnvVar,
|
||||||
ReadOnlyEnv,
|
ReadOnlyEnv,
|
||||||
RegistryProxyVars,
|
RegistryProxyVars,
|
||||||
getEnv,
|
getEnv,
|
||||||
exportEnvVar,
|
exportEnvVar,
|
||||||
|
ActionsEnvVars,
|
||||||
} from "./environment";
|
} from "./environment";
|
||||||
|
import {
|
||||||
|
getCurrentInstance,
|
||||||
|
getDotcomInstance,
|
||||||
|
GITHUB_DOTCOM_URL,
|
||||||
|
parseGitHubUrl,
|
||||||
|
type GitHubApiCombinedDetails,
|
||||||
|
type GitHubApiDetails,
|
||||||
|
} from "./github";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
||||||
import {
|
import {
|
||||||
asHTTPError,
|
asHTTPError,
|
||||||
ConfigurationError,
|
ConfigurationError,
|
||||||
getRequiredEnvParam,
|
getRequiredEnvParam,
|
||||||
GITHUB_DOTCOM_URL,
|
|
||||||
GitHubVariant,
|
GitHubVariant,
|
||||||
GitHubVersion,
|
GitHubVersion,
|
||||||
parseGitHubUrl,
|
|
||||||
parseMatrixInput,
|
parseMatrixInput,
|
||||||
} from "./util";
|
} from "./util";
|
||||||
|
|
||||||
|
export type { GitHubApiDetails, GitHubApiCombinedDetails } from "./github";
|
||||||
|
|
||||||
const GITHUB_ENTERPRISE_VERSION_HEADER = "x-github-enterprise-version";
|
const GITHUB_ENTERPRISE_VERSION_HEADER = "x-github-enterprise-version";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,21 +52,6 @@ const GITHUB_ENTERPRISE_VERSION_HEADER = "x-github-enterprise-version";
|
|||||||
*/
|
*/
|
||||||
export const DO_NOT_RETRY_STATUSES = [400, 410, 422, 451];
|
export const DO_NOT_RETRY_STATUSES = [400, 410, 422, 451];
|
||||||
|
|
||||||
export type GitHubApiCombinedDetails = GitHubApiDetails &
|
|
||||||
GitHubApiExternalRepoDetails;
|
|
||||||
|
|
||||||
export interface GitHubApiDetails {
|
|
||||||
auth: string;
|
|
||||||
url: string;
|
|
||||||
apiURL: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GitHubApiExternalRepoDetails {
|
|
||||||
externalRepoAuth?: string;
|
|
||||||
url: string;
|
|
||||||
apiURL: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the configuration for the private registry authentication proxy,
|
* Gets the configuration for the private registry authentication proxy,
|
||||||
* if it is available in the environment.
|
* if it is available in the environment.
|
||||||
@@ -128,6 +122,66 @@ export function makeProxyRequestOptions(
|
|||||||
/** The type of GitHub API client we use. */
|
/** The type of GitHub API client we use. */
|
||||||
export type ApiClient = InstanceType<typeof githubUtils.GitHub>;
|
export type ApiClient = InstanceType<typeof githubUtils.GitHub>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates a {@link GitHubApiCombinedDetails} along with operations which ensure that any credentials
|
||||||
|
* are only used with the GitHub instance that is represented by the {@link GitHubApiCombinedDetails} value.
|
||||||
|
*/
|
||||||
|
export class InstanceApiClient {
|
||||||
|
private readonly client: ApiClient;
|
||||||
|
private readonly apiDetails: GitHubApiCombinedDetails;
|
||||||
|
private readonly authorizationHeader: string | undefined;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
apiDetails: GitHubApiCombinedDetails,
|
||||||
|
clientOptions: CreateApiClientOptions = {},
|
||||||
|
) {
|
||||||
|
this.apiDetails = apiDetails;
|
||||||
|
this.client = createApiClientWithDetails(apiDetails, clientOptions);
|
||||||
|
|
||||||
|
// Compute the Authorization header value if we have a token.
|
||||||
|
const token = this.apiDetails.auth?.trim();
|
||||||
|
if (token !== undefined && token !== "") {
|
||||||
|
this.authorizationHeader = `token ${token}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In most cases, we use an {@link ApiClient} which automatically handles auth for requests
|
||||||
|
* made with it and this method is not needed and should not be used in that setting.
|
||||||
|
*
|
||||||
|
* In some cases, we need to make requests that can't go through an {@link ApiClient}, but still
|
||||||
|
* require auth. For example, this is the case when using the `toolcache` module to download
|
||||||
|
* files. For these cases, this method gets a value for the `Authorization` header for a request
|
||||||
|
* to `url`; or `undefined` if the `Authorization` header should not be set for `url`.
|
||||||
|
*
|
||||||
|
* @param logger The logger to use for debugging messages.
|
||||||
|
* @param url The URL for which we want to add an `Authorization` header.
|
||||||
|
*/
|
||||||
|
public getAuthorizationHeaderFor(
|
||||||
|
logger: Logger,
|
||||||
|
url: string,
|
||||||
|
): string | undefined {
|
||||||
|
// We don't have to check the `url` if we don't have a token to begin with.
|
||||||
|
if (this.authorizationHeader === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only want to provide an authorization header if we are downloading
|
||||||
|
// from the same GitHub instance the Action is running on.
|
||||||
|
// This avoids leaking Enterprise tokens to dotcom.
|
||||||
|
if (
|
||||||
|
url.startsWith(`${this.apiDetails.url}/`) ||
|
||||||
|
(this.apiDetails.apiURL && url.startsWith(`${this.apiDetails.apiURL}/`))
|
||||||
|
) {
|
||||||
|
logger.debug(`Providing an authorization token.`);
|
||||||
|
return this.authorizationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Not using an authorization token.`);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Options for `createApiClientWithDetails`. */
|
/** Options for `createApiClientWithDetails`. */
|
||||||
interface CreateApiClientOptions {
|
interface CreateApiClientOptions {
|
||||||
allowExternal?: boolean;
|
allowExternal?: boolean;
|
||||||
@@ -139,37 +193,82 @@ function createApiClientWithDetails(
|
|||||||
{ allowExternal = false, proxy = undefined }: CreateApiClientOptions = {},
|
{ allowExternal = false, proxy = undefined }: CreateApiClientOptions = {},
|
||||||
): ApiClient {
|
): ApiClient {
|
||||||
const auth =
|
const auth =
|
||||||
(allowExternal && apiDetails.externalRepoAuth) || apiDetails.auth;
|
allowExternal && apiDetails.externalRepoAuth !== undefined
|
||||||
|
? apiDetails.externalRepoAuth
|
||||||
|
: apiDetails.auth;
|
||||||
const retryingOctokit = githubUtils.GitHub.plugin(retry.retry);
|
const retryingOctokit = githubUtils.GitHub.plugin(retry.retry);
|
||||||
const requestOptions = makeProxyRequestOptions(proxy);
|
const requestOptions = makeProxyRequestOptions(proxy);
|
||||||
return new retryingOctokit(
|
|
||||||
githubUtils.getOctokitOptions(auth, {
|
const opts: OctokitOptions = {
|
||||||
baseUrl: apiDetails.apiURL,
|
auth:
|
||||||
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
auth !== undefined && auth.trim() !== "" ? `token ${auth}` : undefined,
|
||||||
log: {
|
baseUrl: apiDetails.apiURL,
|
||||||
debug: core.debug,
|
userAgent: `CodeQL-Action/${getActionVersion()}`,
|
||||||
info: core.info,
|
log: {
|
||||||
warn: core.warning,
|
debug: core.debug,
|
||||||
error: core.error,
|
info: core.info,
|
||||||
},
|
warn: core.warning,
|
||||||
request: requestOptions,
|
error: core.error,
|
||||||
retry: {
|
},
|
||||||
doNotRetry: DO_NOT_RETRY_STATUSES,
|
request: requestOptions,
|
||||||
},
|
retry: {
|
||||||
}),
|
doNotRetry: DO_NOT_RETRY_STATUSES,
|
||||||
);
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return new retryingOctokit(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a `GitHubApiDetails` object describing the GitHub instance we are currently running on.
|
||||||
|
*
|
||||||
|
* @param env The environment variables to read.
|
||||||
|
*/
|
||||||
export function getApiDetails(env: ReadOnlyEnv = getEnv()): GitHubApiDetails {
|
export function getApiDetails(env: ReadOnlyEnv = getEnv()): GitHubApiDetails {
|
||||||
return {
|
return {
|
||||||
auth: getRequiredInput("token"),
|
auth: getRequiredInput("token"),
|
||||||
url: env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
...getCurrentInstance(env),
|
||||||
apiURL: env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getApiClient(env: ReadOnlyEnv = getEnv()) {
|
/**
|
||||||
return createApiClientWithDetails(getApiDetails(env));
|
* Constructs an {@link ApiClient} using {@link apiDetails}.
|
||||||
|
*
|
||||||
|
* If {@link apiDetails} is not specified, then the GitHub instance URLs are taken from {@link env}
|
||||||
|
* and the auth token is taken from the `token` input.
|
||||||
|
*
|
||||||
|
* If {@link env} is not specified, then the process environment is used.
|
||||||
|
*
|
||||||
|
* @param env The environment to obtain the GitHub instance URLs from.
|
||||||
|
* @param apiDetails The {@link GitHubApiDetails} to construct the {@link ApiClient} for.
|
||||||
|
*/
|
||||||
|
export function getApiClient(
|
||||||
|
env: ReadOnlyEnv = getEnv(),
|
||||||
|
apiDetails?: GitHubApiDetails,
|
||||||
|
) {
|
||||||
|
return createApiClientWithDetails(apiDetails ?? getApiDetails(env));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gets a `GitHubApiDetails` object describing the GitHub Dotcom instance.
|
||||||
|
*
|
||||||
|
* @param env The environment variables to read.
|
||||||
|
*/
|
||||||
|
export function getDotcomApiDetails(env: ReadOnlyEnv): GitHubApiDetails {
|
||||||
|
// If we are currently running on dotcom, then just call `getApiDetails` which will
|
||||||
|
// construct the appropriate `GitHubApiDetails` from the environment and include the
|
||||||
|
// value of the `token` input. The `token` input relates to the GitHub instance that
|
||||||
|
// we are running on only. Therefore, if we are not currently running on dotcom,
|
||||||
|
// then we construct `GitHubApiDetails` without the `token` value and using the
|
||||||
|
// hard-coded instance and API URLs.
|
||||||
|
if (env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL) === GITHUB_DOTCOM_URL) {
|
||||||
|
return getApiDetails(env);
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
auth: undefined,
|
||||||
|
...getDotcomInstance(),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getApiClientWithExternalAuth(
|
export function getApiClientWithExternalAuth(
|
||||||
@@ -179,36 +278,6 @@ export function getApiClientWithExternalAuth(
|
|||||||
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
return createApiClientWithDetails(apiDetails, { allowExternal: true, proxy });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a value for the `Authorization` header for a request to `url`; or `undefined` if the
|
|
||||||
* `Authorization` header should not be set for `url`.
|
|
||||||
*
|
|
||||||
* @param logger The logger to use for debugging messages.
|
|
||||||
* @param apiDetails Details of the GitHub API we are using.
|
|
||||||
* @param url The URL for which we want to add an `Authorization` header.
|
|
||||||
*
|
|
||||||
* @returns The value for the `Authorization` header or `undefined` if it shouldn't be populated.
|
|
||||||
*/
|
|
||||||
export function getAuthorizationHeaderFor(
|
|
||||||
logger: Logger,
|
|
||||||
apiDetails: GitHubApiDetails,
|
|
||||||
url: string,
|
|
||||||
): string | undefined {
|
|
||||||
// We only want to provide an authorization header if we are downloading
|
|
||||||
// from the same GitHub instance the Action is running on.
|
|
||||||
// This avoids leaking Enterprise tokens to dotcom.
|
|
||||||
if (
|
|
||||||
url.startsWith(`${apiDetails.url}/`) ||
|
|
||||||
(apiDetails.apiURL && url.startsWith(`${apiDetails.apiURL}/`))
|
|
||||||
) {
|
|
||||||
logger.debug(`Providing an authorization token.`);
|
|
||||||
return `token ${apiDetails.auth}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.debug(`Not using an authorization token.`);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cachedGitHubVersion: GitHubVersion | undefined = undefined;
|
let cachedGitHubVersion: GitHubVersion | undefined = undefined;
|
||||||
|
|
||||||
export async function getGitHubVersionFromApi(
|
export async function getGitHubVersionFromApi(
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import type { GitHubApiDetails } from "./github";
|
||||||
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
|
import { BuiltInLanguage, parseBuiltInLanguage } from "./languages";
|
||||||
import { BundlePlatform } from "./platform";
|
import { BundlePlatform } from "./platform";
|
||||||
import type { CompressionMethod } from "./tar";
|
import type { CompressionMethod } from "./tar";
|
||||||
@@ -17,6 +18,8 @@ export type CodeQLBundle =
|
|||||||
export interface CodeQLDownloadSource {
|
export interface CodeQLDownloadSource {
|
||||||
/** Distinguishes downloads from local archives and cached installations. */
|
/** Distinguishes downloads from local archives and cached installations. */
|
||||||
sourceType: "download";
|
sourceType: "download";
|
||||||
|
/** Information about the GitHub instance that contains the asset. */
|
||||||
|
apiDetails: GitHubApiDetails;
|
||||||
/** The bundle to download. */
|
/** The bundle to download. */
|
||||||
bundle: CodeQLBundle;
|
bundle: CodeQLBundle;
|
||||||
/** The compression format of the bundle archive. */
|
/** The compression format of the bundle archive. */
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import {
|
|||||||
makeVersionInfo,
|
makeVersionInfo,
|
||||||
createTestConfig,
|
createTestConfig,
|
||||||
makeMacro,
|
makeMacro,
|
||||||
|
mockApiDetails,
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
import { ToolsDownloadStatusReport } from "./tools-download";
|
import { ToolsDownloadStatusReport } from "./tools-download";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
@@ -126,19 +127,6 @@ function mockReleaseApi({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function mockApiDetails(apiDetails: GitHubApiDetails) {
|
|
||||||
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
|
||||||
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
|
||||||
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
|
||||||
// `getApiDetails()` via an imported `api` module.
|
|
||||||
sinon
|
|
||||||
.stub(actionsUtil, "getRequiredInput")
|
|
||||||
.withArgs("token")
|
|
||||||
.returns(apiDetails.auth);
|
|
||||||
process.env["GITHUB_SERVER_URL"] = apiDetails.url;
|
|
||||||
process.env["GITHUB_API_URL"] = apiDetails.apiURL || "";
|
|
||||||
}
|
|
||||||
|
|
||||||
async function stubCodeql(): Promise<codeql.CodeQL> {
|
async function stubCodeql(): Promise<codeql.CodeQL> {
|
||||||
const codeqlObject = await codeql.getCodeQLForTesting();
|
const codeqlObject = await codeql.getCodeQLForTesting();
|
||||||
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
sinon.stub(codeqlObject, "getVersion").resolves(makeVersionInfo("2.17.6"));
|
||||||
@@ -290,6 +278,7 @@ for (const { cliVersion, tagName, expectedToolcacheVersion } of [
|
|||||||
async (t) => {
|
async (t) => {
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
|
||||||
const result = await installIntoToolcache({
|
const result = await installIntoToolcache({
|
||||||
cliVersion,
|
cliVersion,
|
||||||
@@ -470,6 +459,7 @@ test.serial(
|
|||||||
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
|
||||||
await installIntoToolcache({
|
await installIntoToolcache({
|
||||||
tagName: "codeql-bundle-20200601",
|
tagName: "codeql-bundle-20200601",
|
||||||
@@ -517,6 +507,7 @@ test.serial(
|
|||||||
|
|
||||||
await util.withTmpDir(async (tmpDir) => {
|
await util.withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
|
||||||
await installIntoToolcache({
|
await installIntoToolcache({
|
||||||
tagName: "codeql-bundle-20200601",
|
tagName: "codeql-bundle-20200601",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as fs from "fs";
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
import * as github from "@actions/github";
|
import * as github from "@actions/github";
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
@@ -10,7 +11,10 @@ import { GitHubApiDetails } from "./api-client";
|
|||||||
import * as apiClient from "./api-client";
|
import * as apiClient from "./api-client";
|
||||||
import { createStubCodeQL } from "./codeql";
|
import { createStubCodeQL } from "./codeql";
|
||||||
import { Config } from "./config-utils";
|
import { Config } from "./config-utils";
|
||||||
import { cleanupAndUploadDatabases } from "./database-upload";
|
import {
|
||||||
|
cleanupAndUploadDatabases,
|
||||||
|
uploadBundledDatabase,
|
||||||
|
} from "./database-upload";
|
||||||
import { Feature } from "./feature-flags";
|
import { Feature } from "./feature-flags";
|
||||||
import * as gitUtils from "./git-utils";
|
import * as gitUtils from "./git-utils";
|
||||||
import { BuiltInLanguage } from "./languages";
|
import { BuiltInLanguage } from "./languages";
|
||||||
@@ -23,6 +27,7 @@ import {
|
|||||||
getTestEnv,
|
getTestEnv,
|
||||||
initAllState,
|
initAllState,
|
||||||
RecordingLogger,
|
RecordingLogger,
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
setupActionsVars,
|
setupActionsVars,
|
||||||
setupTests,
|
setupTests,
|
||||||
} from "./testing-utils";
|
} from "./testing-utils";
|
||||||
@@ -550,3 +555,90 @@ test.serial(
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test.serial(
|
||||||
|
"uploadBundledDatabase provides expected request arguments",
|
||||||
|
async (t) =>
|
||||||
|
withTmpDir(async (tmpDir) => {
|
||||||
|
// Write some file that `uploadBundledDatabase` can use for its `fs.createReadStream(bundledDb)` call
|
||||||
|
// so we don't have to stub that or create a fake `ReadStream`.
|
||||||
|
const dbPath = path.join(tmpDir, "db");
|
||||||
|
const content = JSON.stringify({});
|
||||||
|
fs.writeFileSync(dbPath, content);
|
||||||
|
|
||||||
|
// A simple stub for `fetch` that satisfies Octokit when it inspects the response.
|
||||||
|
const fetchStub = sinon.stub().resolves({
|
||||||
|
status: 200,
|
||||||
|
headers: new Headers(),
|
||||||
|
text: async () => "",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Construct a real `ApiClient`.
|
||||||
|
const client = apiClient.getApiClient(
|
||||||
|
getTestEnv(),
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Then wrap the real `request` method in a stub that calls it with our stubbed `fetch`.
|
||||||
|
// This ensures that we have a real `ApiClient` with a mostly real `request`, but which
|
||||||
|
// does not perform any actual requests.
|
||||||
|
const request = client.request;
|
||||||
|
sinon.stub(client, "request").callsFake(async (route, options) =>
|
||||||
|
request(route, {
|
||||||
|
...options,
|
||||||
|
request: { ...options?.request, fetch: fetchStub },
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Stub `getApiClient` to return our modified `ApiClient`.
|
||||||
|
const getApiClient = sinon
|
||||||
|
.stub(apiClient, "getApiClient")
|
||||||
|
.returns(client);
|
||||||
|
|
||||||
|
// Calling `uploadBundledDatabase` shouldn't throw.
|
||||||
|
const nwo: RepositoryNwo = { owner: "test", repo: "foo" };
|
||||||
|
const language: BuiltInLanguage = BuiltInLanguage.java;
|
||||||
|
|
||||||
|
const env = getTestEnv();
|
||||||
|
await t.notThrowsAsync(async () => {
|
||||||
|
await uploadBundledDatabase(
|
||||||
|
nwo,
|
||||||
|
language,
|
||||||
|
"123",
|
||||||
|
dbPath,
|
||||||
|
content.length,
|
||||||
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
|
env,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that our stubs were called and that they received the expected arguments.
|
||||||
|
t.is(getApiClient.callCount, 1);
|
||||||
|
t.deepEqual(getApiClient.args[0], [env, SAMPLE_DOTCOM_API_DETAILS]);
|
||||||
|
|
||||||
|
t.is(fetchStub.callCount, 1);
|
||||||
|
|
||||||
|
const args = fetchStub.args[0];
|
||||||
|
t.is(args.length, 2);
|
||||||
|
|
||||||
|
const url = args[0];
|
||||||
|
t.is(
|
||||||
|
url,
|
||||||
|
`https://uploads.github.com/repos/${nwo.owner}/${nwo.repo}/code-scanning/codeql/databases/${language}?name=${language}-database&commit_oid=123`,
|
||||||
|
);
|
||||||
|
|
||||||
|
const options = args[1];
|
||||||
|
t.like(options, {
|
||||||
|
// Going via `new Headers` and `Object.fromEntries` ensures we get the same cases
|
||||||
|
// for the header keys as we are given.
|
||||||
|
headers: Object.fromEntries(
|
||||||
|
new Headers({
|
||||||
|
authorization: `token ${SAMPLE_DOTCOM_API_DETAILS.auth}`,
|
||||||
|
"Content-Type": "application/zip",
|
||||||
|
"Content-Length": content.length.toString(),
|
||||||
|
}).entries(),
|
||||||
|
),
|
||||||
|
method: "POST",
|
||||||
|
} satisfies RequestInit);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|||||||
@@ -10,13 +10,15 @@ import {
|
|||||||
} from "./api-client";
|
} from "./api-client";
|
||||||
import { type CodeQL } from "./codeql";
|
import { type CodeQL } from "./codeql";
|
||||||
import { Config } from "./config-utils";
|
import { Config } from "./config-utils";
|
||||||
|
import type { ReadOnlyEnv } from "./environment";
|
||||||
import { Feature } from "./feature-flags";
|
import { Feature } from "./feature-flags";
|
||||||
import * as gitUtils from "./git-utils";
|
import * as gitUtils from "./git-utils";
|
||||||
|
import { parseGitHubUrl } from "./github";
|
||||||
import { Logger, withGroupAsync } from "./logging";
|
import { Logger, withGroupAsync } from "./logging";
|
||||||
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
import { OverlayDatabaseMode } from "./overlay/overlay-database-mode";
|
||||||
import { RepositoryNwo } from "./repository";
|
import { RepositoryNwo } from "./repository";
|
||||||
import * as util from "./util";
|
import * as util from "./util";
|
||||||
import { asHTTPError, bundleDb, CleanupLevel, parseGitHubUrl } from "./util";
|
import { asHTTPError, bundleDb, CleanupLevel } from "./util";
|
||||||
|
|
||||||
/** Information about a database upload. */
|
/** Information about a database upload. */
|
||||||
export interface DatabaseUploadResult {
|
export interface DatabaseUploadResult {
|
||||||
@@ -258,15 +260,19 @@ async function recordClearCleanupSizes(
|
|||||||
*
|
*
|
||||||
* @returns the duration of the upload in milliseconds
|
* @returns the duration of the upload in milliseconds
|
||||||
*/
|
*/
|
||||||
async function uploadBundledDatabase(
|
export async function uploadBundledDatabase(
|
||||||
repositoryNwo: RepositoryNwo,
|
repositoryNwo: RepositoryNwo,
|
||||||
language: string,
|
language: string,
|
||||||
commitOid: string,
|
commitOid: string,
|
||||||
bundledDb: string,
|
bundledDb: string,
|
||||||
bundledDbSize: number,
|
bundledDbSize: number,
|
||||||
apiDetails: GitHubApiDetails,
|
apiDetails: GitHubApiDetails,
|
||||||
|
env: ReadOnlyEnv = util.getEnv(),
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const client = getApiClient();
|
// It is important that the `apiDetails` that `getApiClient` uses match the ones we were given,
|
||||||
|
// because we use `apiDetails.url` below to construct the URL to upload the database to. That
|
||||||
|
// URL will be specific to the GitHub instance given by `apiDetails` and so the client must match it.
|
||||||
|
const client = getApiClient(env, apiDetails);
|
||||||
|
|
||||||
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
const uploadsUrl = new URL(parseGitHubUrl(apiDetails.url));
|
||||||
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
uploadsUrl.hostname = `uploads.${uploadsUrl.hostname}`;
|
||||||
@@ -292,7 +298,6 @@ async function uploadBundledDatabase(
|
|||||||
commit_oid: commitOid,
|
commit_oid: commitOid,
|
||||||
data: bundledDbReadStream,
|
data: bundledDbReadStream,
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `token ${apiDetails.auth}`,
|
|
||||||
"Content-Type": "application/zip",
|
"Content-Type": "application/zip",
|
||||||
"Content-Length": bundledDbSize,
|
"Content-Length": bundledDbSize,
|
||||||
},
|
},
|
||||||
|
|||||||
111
src/github.test.ts
Normal file
111
src/github.test.ts
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import test from "ava";
|
||||||
|
|
||||||
|
import { ActionsEnvVars } from "./environment";
|
||||||
|
import * as github from "./github";
|
||||||
|
import { getTestEnv, setupTests } from "./testing-utils";
|
||||||
|
|
||||||
|
setupTests(test);
|
||||||
|
|
||||||
|
test("parseGitHubUrl", (t) => {
|
||||||
|
t.deepEqual(github.parseGitHubUrl("github.com"), "https://github.com");
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.com"),
|
||||||
|
"https://github.com",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://api.github.com"),
|
||||||
|
"https://github.com",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.com/foo/bar"),
|
||||||
|
"https://github.com",
|
||||||
|
);
|
||||||
|
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("github.example.com"),
|
||||||
|
"https://github.example.com/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.example.com"),
|
||||||
|
"https://github.example.com/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://api.github.example.com"),
|
||||||
|
"https://github.example.com/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.example.com/api/v3"),
|
||||||
|
"https://github.example.com/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.example.com:1234"),
|
||||||
|
"https://github.example.com:1234/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://api.github.example.com:1234"),
|
||||||
|
"https://github.example.com:1234/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.example.com:1234/api/v3"),
|
||||||
|
"https://github.example.com:1234/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.example.com/base/path"),
|
||||||
|
"https://github.example.com/base/path/",
|
||||||
|
);
|
||||||
|
t.deepEqual(
|
||||||
|
github.parseGitHubUrl("https://github.example.com/base/path/api/v3"),
|
||||||
|
"https://github.example.com/base/path/",
|
||||||
|
);
|
||||||
|
|
||||||
|
t.throws(() => github.parseGitHubUrl(""), {
|
||||||
|
message: '"" is not a valid URL',
|
||||||
|
});
|
||||||
|
t.throws(() => github.parseGitHubUrl("ssh://github.com"), {
|
||||||
|
message: '"ssh://github.com" is not a http or https URL',
|
||||||
|
});
|
||||||
|
t.throws(() => github.parseGitHubUrl("http:///::::433"), {
|
||||||
|
message: '"http:///::::433" is not a valid URL',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getCurrentInstance throws if required env vars aren't set", (t) => {
|
||||||
|
t.throws(() => github.getCurrentInstance(getTestEnv()));
|
||||||
|
t.throws(() => {
|
||||||
|
const env = getTestEnv({
|
||||||
|
[ActionsEnvVars.GITHUB_SERVER_URL]: "https://localhost",
|
||||||
|
});
|
||||||
|
github.getCurrentInstance(env);
|
||||||
|
});
|
||||||
|
t.throws(() => {
|
||||||
|
const env = getTestEnv({
|
||||||
|
[ActionsEnvVars.GITHUB_API_URL]: "https://api.localhost",
|
||||||
|
});
|
||||||
|
github.getCurrentInstance(env);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getCurrentInstance constructs instance from environment", (t) => {
|
||||||
|
const url = "https://localhost";
|
||||||
|
const apiUrl = "https://api.localhost";
|
||||||
|
|
||||||
|
const env = getTestEnv({
|
||||||
|
[ActionsEnvVars.GITHUB_SERVER_URL]: url,
|
||||||
|
[ActionsEnvVars.GITHUB_API_URL]: apiUrl,
|
||||||
|
});
|
||||||
|
const instance = github.getCurrentInstance(env);
|
||||||
|
|
||||||
|
t.is(instance.url, url);
|
||||||
|
t.is(instance.apiURL, apiUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("getCurrentInstance constructs dotcom instance with dotcom env vars", (t) => {
|
||||||
|
const env = getTestEnv({
|
||||||
|
[ActionsEnvVars.GITHUB_SERVER_URL]: github.GITHUB_DOTCOM_URL,
|
||||||
|
[ActionsEnvVars.GITHUB_API_URL]: github.GITHUB_DOTCOM_API_URL,
|
||||||
|
});
|
||||||
|
const instance = github.getCurrentInstance(env);
|
||||||
|
const dotcomInstance = github.getDotcomInstance();
|
||||||
|
|
||||||
|
t.deepEqual(dotcomInstance, instance);
|
||||||
|
});
|
||||||
110
src/github.ts
Normal file
110
src/github.ts
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { ActionsEnvVars, type ReadOnlyEnv } from "./environment";
|
||||||
|
import { ConfigurationError } from "./util";
|
||||||
|
|
||||||
|
/** A string representing a GitHub instance address. */
|
||||||
|
export type InstanceURL = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL for github.com.
|
||||||
|
*/
|
||||||
|
export const GITHUB_DOTCOM_URL: InstanceURL = "https://github.com";
|
||||||
|
|
||||||
|
/** A string representing a GitHub API instance address. */
|
||||||
|
export type InstanceApiURL = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL for api.github.com.
|
||||||
|
*/
|
||||||
|
export const GITHUB_DOTCOM_API_URL: InstanceApiURL = "https://api.github.com";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents information about a GitHub instance, how to authenticate to it,
|
||||||
|
* and how to authenticate to other repos on it.
|
||||||
|
*/
|
||||||
|
export type GitHubApiCombinedDetails = GitHubApiDetails &
|
||||||
|
GitHubApiExternalRepoDetails;
|
||||||
|
|
||||||
|
/** Represents information about a GitHub instance. */
|
||||||
|
export type GitHubInstance = {
|
||||||
|
/** The base URL of the GitHub instance, such as `https://github.com`. */
|
||||||
|
url: string;
|
||||||
|
/**
|
||||||
|
* The API base URL of the GitHub instance, such as `https://api.github.com`.
|
||||||
|
* Typically this is the `api.` subdomain of the `url` domain.
|
||||||
|
*/
|
||||||
|
apiURL: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Represents a {@link GitHubInstance} with a token for accessing the API. */
|
||||||
|
export type GitHubApiDetails = GitHubInstance & {
|
||||||
|
/** The token to use for accessing the API of the GitHub instance. */
|
||||||
|
auth?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents information for accessing a repository on the same GitHub instance as the Action
|
||||||
|
* is currently running on.
|
||||||
|
*/
|
||||||
|
export type GitHubApiExternalRepoDetails = {
|
||||||
|
/** An optional token for accessing repo(s) on the same GitHub instance. */
|
||||||
|
externalRepoAuth?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses user input of a github.com or GHES URL to a canonical form.
|
||||||
|
* Removes any API prefix or suffix if one is present.
|
||||||
|
*/
|
||||||
|
export function parseGitHubUrl(inputUrl: string): string {
|
||||||
|
const originalUrl = inputUrl;
|
||||||
|
if (inputUrl.indexOf("://") === -1) {
|
||||||
|
inputUrl = `https://${inputUrl}`;
|
||||||
|
}
|
||||||
|
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
||||||
|
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let url: URL;
|
||||||
|
try {
|
||||||
|
url = new URL(inputUrl);
|
||||||
|
} catch {
|
||||||
|
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we detect this is trying to be to github.com
|
||||||
|
// then return with a fixed canonical URL.
|
||||||
|
if (url.hostname === "github.com" || url.hostname === "api.github.com") {
|
||||||
|
return GITHUB_DOTCOM_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the API prefix if it's present
|
||||||
|
if (url.pathname.indexOf("/api/v3") !== -1) {
|
||||||
|
url.pathname = url.pathname.substring(0, url.pathname.indexOf("/api/v3"));
|
||||||
|
}
|
||||||
|
// Also consider subdomain isolation on GHES
|
||||||
|
if (url.hostname.startsWith("api.")) {
|
||||||
|
url.hostname = url.hostname.substring(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normalise path to having a trailing slash for consistency
|
||||||
|
if (!url.pathname.endsWith("/")) {
|
||||||
|
url.pathname = `${url.pathname}/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieves a {@link GitHubInstance} describing the instance we are running on. */
|
||||||
|
export function getCurrentInstance(env: ReadOnlyEnv): GitHubInstance {
|
||||||
|
return {
|
||||||
|
url: env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
||||||
|
apiURL: env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieves a {@link GitHubInstance} describing the GitHub.com instance. */
|
||||||
|
export function getDotcomInstance(): GitHubInstance {
|
||||||
|
return {
|
||||||
|
url: GITHUB_DOTCOM_URL,
|
||||||
|
apiURL: GITHUB_DOTCOM_API_URL,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -50,6 +50,7 @@ import {
|
|||||||
loadRepositoryProperties,
|
loadRepositoryProperties,
|
||||||
RepositoryPropertyName,
|
RepositoryPropertyName,
|
||||||
} from "./feature-flags/properties";
|
} from "./feature-flags/properties";
|
||||||
|
import * as github from "./github";
|
||||||
import {
|
import {
|
||||||
checkInstallPython311,
|
checkInstallPython311,
|
||||||
checkPacksForOverlayCompatibility,
|
checkPacksForOverlayCompatibility,
|
||||||
@@ -233,8 +234,7 @@ async function run(
|
|||||||
apiDetails = {
|
apiDetails = {
|
||||||
auth: getRequiredInput("token"),
|
auth: getRequiredInput("token"),
|
||||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||||
url: actionState.env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
...github.getCurrentInstance(actionState.env),
|
||||||
apiURL: actionState.env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const gitHubVersion = await getGitHubVersion();
|
const gitHubVersion = await getGitHubVersion();
|
||||||
|
|||||||
@@ -17,9 +17,10 @@ import { getGitHubVersion } from "./api-client";
|
|||||||
import { CodeQL } from "./codeql";
|
import { CodeQL } from "./codeql";
|
||||||
import { ComputedInput, getToolsInput } from "./config/inputs";
|
import { ComputedInput, getToolsInput } from "./config/inputs";
|
||||||
import { getRawLanguagesNoAutodetect } from "./config-utils";
|
import { getRawLanguagesNoAutodetect } from "./config-utils";
|
||||||
import { ActionsEnvVars, EnvVar } from "./environment";
|
import { EnvVar } from "./environment";
|
||||||
import { initFeatures } from "./feature-flags";
|
import { initFeatures } from "./feature-flags";
|
||||||
import { loadRepositoryProperties } from "./feature-flags/properties";
|
import { loadRepositoryProperties } from "./feature-flags/properties";
|
||||||
|
import * as github from "./github";
|
||||||
import { initCodeQL } from "./init";
|
import { initCodeQL } from "./init";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { getRepositoryNwo } from "./repository";
|
import { getRepositoryNwo } from "./repository";
|
||||||
@@ -112,8 +113,7 @@ async function run(
|
|||||||
const apiDetails = {
|
const apiDetails = {
|
||||||
auth: getRequiredInput("token"),
|
auth: getRequiredInput("token"),
|
||||||
externalRepoAuth: getOptionalInput("external-repository-token"),
|
externalRepoAuth: getOptionalInput("external-repository-token"),
|
||||||
url: actionState.env.getRequired(ActionsEnvVars.GITHUB_SERVER_URL),
|
...github.getCurrentInstance(actionState.env),
|
||||||
apiURL: actionState.env.getRequired(ActionsEnvVars.GITHUB_API_URL),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const gitHubVersion = await getGitHubVersion();
|
const gitHubVersion = await getGitHubVersion();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import {
|
|||||||
getTestEnv,
|
getTestEnv,
|
||||||
initAllState,
|
initAllState,
|
||||||
makeMacro,
|
makeMacro,
|
||||||
|
mockApiDetails,
|
||||||
mockBundleDownloadApi,
|
mockBundleDownloadApi,
|
||||||
setupActionsVars,
|
setupActionsVars,
|
||||||
setupTests,
|
setupTests,
|
||||||
@@ -155,6 +156,7 @@ test.serial(
|
|||||||
compressionMethod: "gzip",
|
compressionMethod: "gzip",
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: "1.2.3",
|
toolsVersion: "1.2.3",
|
||||||
|
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -221,6 +223,7 @@ for (const {
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
const source = await setupCodeql.getCodeQLSource(
|
const source = await setupCodeql.getCodeQLSource(
|
||||||
"linked",
|
"linked",
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
@@ -255,6 +258,7 @@ test.serial(
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
const source = await setupCodeql.getCodeQLSource(
|
const source = await setupCodeql.getCodeQLSource(
|
||||||
"latest",
|
"latest",
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
@@ -298,6 +302,7 @@ test.serial(
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
const result = await setupCodeql.setupCodeQLBundle(
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
"linked",
|
"linked",
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
@@ -431,6 +436,7 @@ test.serial(
|
|||||||
compressionMethod: "zstd",
|
compressionMethod: "zstd",
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: expectedVersion,
|
toolsVersion: expectedVersion,
|
||||||
|
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||||
} satisfies setupCodeql.CodeQLToolsSource);
|
} satisfies setupCodeql.CodeQLToolsSource);
|
||||||
|
|
||||||
const result = await setupCodeql.setupCodeQLBundle(
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
@@ -479,6 +485,7 @@ test.serial(
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" });
|
setupActionsVars(tmpDir, tmpDir, { GITHUB_EVENT_NAME: "dynamic" });
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
|
||||||
const source = await setupCodeql.getCodeQLSource(
|
const source = await setupCodeql.getCodeQLSource(
|
||||||
undefined,
|
undefined,
|
||||||
@@ -503,6 +510,7 @@ test.serial(
|
|||||||
compressionMethod: "zstd",
|
compressionMethod: "zstd",
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: expectedVersion,
|
toolsVersion: expectedVersion,
|
||||||
|
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||||
} satisfies setupCodeql.CodeQLToolsSource);
|
} satisfies setupCodeql.CodeQLToolsSource);
|
||||||
|
|
||||||
// Afterwards, ensure that we see the expected messages in the log.
|
// Afterwards, ensure that we see the expected messages in the log.
|
||||||
@@ -624,6 +632,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
const source = await setupCodeql.getCodeQLSource(
|
const source = await setupCodeql.getCodeQLSource(
|
||||||
toolsInput,
|
toolsInput,
|
||||||
SAMPLE_DEFAULT_CLI_VERSION,
|
SAMPLE_DEFAULT_CLI_VERSION,
|
||||||
@@ -649,6 +658,7 @@ for (const toolsInput of ["nightly", "nightly-latest"]) {
|
|||||||
cliVersion: undefined,
|
cliVersion: undefined,
|
||||||
compressionMethod: "zstd",
|
compressionMethod: "zstd",
|
||||||
toolsVersion: "0.0.0-30260213",
|
toolsVersion: "0.0.0-30260213",
|
||||||
|
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||||
t.true(latestNightlyRequest.calledOnce);
|
t.true(latestNightlyRequest.calledOnce);
|
||||||
});
|
});
|
||||||
@@ -801,6 +811,7 @@ for (const date of ["20200101", "30260213"]) {
|
|||||||
cliVersion: undefined,
|
cliVersion: undefined,
|
||||||
compressionMethod: "zstd",
|
compressionMethod: "zstd",
|
||||||
toolsVersion: `0.0.0-${date}`,
|
toolsVersion: `0.0.0-${date}`,
|
||||||
|
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||||
} satisfies setupCodeql.CodeQLDownloadSource);
|
} satisfies setupCodeql.CodeQLDownloadSource);
|
||||||
|
|
||||||
await t.throwsAsync(
|
await t.throwsAsync(
|
||||||
@@ -945,6 +956,7 @@ const toolcacheInputFallbackMacro = makeMacro({
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
|
||||||
for (const [k, v] of Object.entries(environment)) {
|
for (const [k, v] of Object.entries(environment)) {
|
||||||
process.env[k] = v;
|
process.env[k] = v;
|
||||||
@@ -1165,6 +1177,7 @@ test.serial(
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
const source = await setupCodeql.getCodeQLSource(
|
const source = await setupCodeql.getCodeQLSource(
|
||||||
undefined,
|
undefined,
|
||||||
PER_LANGUAGE_CLI_VERSION,
|
PER_LANGUAGE_CLI_VERSION,
|
||||||
@@ -1207,6 +1220,7 @@ test.serial(
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
for (const { otherLanguagePacksReason, features } of [
|
for (const { otherLanguagePacksReason, features } of [
|
||||||
// The per-language feature is disabled.
|
// The per-language feature is disabled.
|
||||||
{ otherLanguagePacksReason: undefined, features: createFeatures([]) },
|
{ otherLanguagePacksReason: undefined, features: createFeatures([]) },
|
||||||
@@ -1276,7 +1290,14 @@ for (const fallback of [false, true]) {
|
|||||||
request: { fetch: fetchRelease },
|
request: { fetch: fetchRelease },
|
||||||
});
|
});
|
||||||
sinon.stub(api, "getApiClient").value(() => client);
|
sinon.stub(api, "getApiClient").value(() => client);
|
||||||
const authorizationSpy = sinon.spy(api, "getAuthorizationHeaderFor");
|
|
||||||
|
const spyClient = new api.InstanceApiClient(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
const authorizationSpy = sinon.spy(
|
||||||
|
spyClient,
|
||||||
|
"getAuthorizationHeaderFor",
|
||||||
|
);
|
||||||
|
sinon.stub(api, "InstanceApiClient").returns(spyClient);
|
||||||
|
|
||||||
const extractStub = stubDownloadAndExtract();
|
const extractStub = stubDownloadAndExtract();
|
||||||
if (fallback) {
|
if (fallback) {
|
||||||
extractStub.onFirstCall().rejects(new HTTPError("Not Found", 404));
|
extractStub.onFirstCall().rejects(new HTTPError("Not Found", 404));
|
||||||
@@ -1286,6 +1307,7 @@ for (const fallback of [false, true]) {
|
|||||||
setupActionsVars(tmpDir, tmpDir, {
|
setupActionsVars(tmpDir, tmpDir, {
|
||||||
GITHUB_ACTION_REPOSITORY: "codeql-testing/action-fork",
|
GITHUB_ACTION_REPOSITORY: "codeql-testing/action-fork",
|
||||||
});
|
});
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
const result = await setupCodeql.setupCodeQLBundle(
|
const result = await setupCodeql.setupCodeQLBundle(
|
||||||
undefined,
|
undefined,
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
@@ -1308,9 +1330,9 @@ for (const fallback of [false, true]) {
|
|||||||
t.is(extractStub.firstCall.args[0], assetURL);
|
t.is(extractStub.firstCall.args[0], assetURL);
|
||||||
t.is(extractStub.lastCall.args[0], fallback ? combinedURL : assetURL);
|
t.is(extractStub.lastCall.args[0], fallback ? combinedURL : assetURL);
|
||||||
t.is(authorizationSpy.callCount, extractStub.callCount);
|
t.is(authorizationSpy.callCount, extractStub.callCount);
|
||||||
t.is(authorizationSpy.firstCall.args[2], assetURL);
|
t.is(authorizationSpy.firstCall.args[1], assetURL);
|
||||||
t.is(
|
t.is(
|
||||||
authorizationSpy.lastCall.args[2],
|
authorizationSpy.lastCall.args[1],
|
||||||
fallback ? combinedURL : assetURL,
|
fallback ? combinedURL : assetURL,
|
||||||
);
|
);
|
||||||
t.is(extractStub.lastCall.args[3], "token token");
|
t.is(extractStub.lastCall.args[3], "token token");
|
||||||
@@ -1553,6 +1575,7 @@ for (const error of [
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
await t.throwsAsync(
|
await t.throwsAsync(
|
||||||
setupCodeql.setupCodeQLBundle(
|
setupCodeql.setupCodeQLBundle(
|
||||||
undefined,
|
undefined,
|
||||||
@@ -1853,8 +1876,8 @@ async function runDownloadCodeQL(
|
|||||||
cliVersion: CLEANUP_CLI_VERSION,
|
cliVersion: CLEANUP_CLI_VERSION,
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: CLEANUP_CLI_VERSION,
|
toolsVersion: CLEANUP_CLI_VERSION,
|
||||||
|
apiDetails: SAMPLE_DOTCOM_API_DETAILS,
|
||||||
},
|
},
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
|
||||||
undefined, // tarVersion
|
undefined, // tarVersion
|
||||||
toolcacheRoot, // tempDir
|
toolcacheRoot, // tempDir
|
||||||
);
|
);
|
||||||
@@ -2259,6 +2282,7 @@ test.serial(
|
|||||||
async (t) => {
|
async (t) => {
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
||||||
|
|
||||||
stubDownloadAndExtract();
|
stubDownloadAndExtract();
|
||||||
@@ -2294,6 +2318,7 @@ test.serial(
|
|||||||
|
|
||||||
await withTmpDir(async (tmpDir) => {
|
await withTmpDir(async (tmpDir) => {
|
||||||
setupActionsVars(tmpDir, tmpDir);
|
setupActionsVars(tmpDir, tmpDir);
|
||||||
|
mockApiDetails(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
process.env[ActionsEnvVars.RUNNER_ENVIRONMENT] = "github-hosted";
|
||||||
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
delete process.env[EnvVar.HAS_SET_UP_CODEQL];
|
||||||
const staleDirectory = createToolcacheEntry(
|
const staleDirectory = createToolcacheEntry(
|
||||||
|
|||||||
@@ -718,6 +718,7 @@ export async function getCodeQLSource(
|
|||||||
compressionMethod,
|
compressionMethod,
|
||||||
sourceType: "download",
|
sourceType: "download",
|
||||||
toolsVersion: resolvedVersion ?? "unknown",
|
toolsVersion: resolvedVersion ?? "unknown",
|
||||||
|
apiDetails,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,7 +747,6 @@ async function tryGetFallbackToolcacheVersion(
|
|||||||
// be able to stub this function and have other functions in this file use that stub.
|
// be able to stub this function and have other functions in this file use that stub.
|
||||||
export const downloadCodeQL = async function (
|
export const downloadCodeQL = async function (
|
||||||
source: CodeQLDownloadSource,
|
source: CodeQLDownloadSource,
|
||||||
apiDetails: api.GitHubApiDetails,
|
|
||||||
tarVersion: tar.TarVersion | undefined,
|
tarVersion: tar.TarVersion | undefined,
|
||||||
tempDir: string,
|
tempDir: string,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
@@ -767,11 +767,8 @@ export const downloadCodeQL = async function (
|
|||||||
if (searchParams.has("token")) {
|
if (searchParams.has("token")) {
|
||||||
logger.debug("CodeQL tools URL contains an authorization token.");
|
logger.debug("CodeQL tools URL contains an authorization token.");
|
||||||
} else {
|
} else {
|
||||||
authorization = api.getAuthorizationHeaderFor(
|
const client = new api.InstanceApiClient(source.apiDetails);
|
||||||
logger,
|
authorization = client.getAuthorizationHeaderFor(logger, codeqlURL);
|
||||||
apiDetails,
|
|
||||||
codeqlURL,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolcacheDestination = getToolcacheDestination({ logger }, source);
|
const toolcacheDestination = getToolcacheDestination({ logger }, source);
|
||||||
@@ -985,7 +982,6 @@ export async function setupCodeQLBundle(
|
|||||||
const result = await downloadCodeQLBundle(
|
const result = await downloadCodeQLBundle(
|
||||||
{ env: getEnv(), features, logger },
|
{ env: getEnv(), features, logger },
|
||||||
source,
|
source,
|
||||||
apiDetails,
|
|
||||||
zstdAvailability.version,
|
zstdAvailability.version,
|
||||||
tempDir,
|
tempDir,
|
||||||
);
|
);
|
||||||
@@ -1021,7 +1017,6 @@ export async function setupCodeQLBundle(
|
|||||||
export async function downloadCodeQLBundle(
|
export async function downloadCodeQLBundle(
|
||||||
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
|
action: ActionState<["Logger", "ReadOnlyEnv", "FeatureFlags"]>,
|
||||||
source: CodeQLDownloadSource,
|
source: CodeQLDownloadSource,
|
||||||
apiDetails: api.GitHubApiDetails,
|
|
||||||
tarVersion: tar.TarVersion | undefined,
|
tarVersion: tar.TarVersion | undefined,
|
||||||
tempDir: string,
|
tempDir: string,
|
||||||
): Promise<{
|
): Promise<{
|
||||||
@@ -1035,13 +1030,7 @@ export async function downloadCodeQLBundle(
|
|||||||
|
|
||||||
const startTime = performance.now();
|
const startTime = performance.now();
|
||||||
try {
|
try {
|
||||||
return await downloadCodeQL(
|
return await downloadCodeQL(source, tarVersion, tempDir, logger);
|
||||||
source,
|
|
||||||
apiDetails,
|
|
||||||
tarVersion,
|
|
||||||
tempDir,
|
|
||||||
logger,
|
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (
|
if (
|
||||||
bundle.kind !== "per-language" ||
|
bundle.kind !== "per-language" ||
|
||||||
@@ -1057,7 +1046,6 @@ export async function downloadCodeQLBundle(
|
|||||||
...source,
|
...source,
|
||||||
bundle: { kind: "combined", url: bundle.combinedBundleURL },
|
bundle: { kind: "combined", url: bundle.combinedBundleURL },
|
||||||
},
|
},
|
||||||
apiDetails,
|
|
||||||
tarVersion,
|
tarVersion,
|
||||||
tempDir,
|
tempDir,
|
||||||
logger,
|
logger,
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ import { ActionState } from "../action-common";
|
|||||||
import { isRunningLocalAction } from "../actions-util";
|
import { isRunningLocalAction } from "../actions-util";
|
||||||
import * as api from "../api-client";
|
import * as api from "../api-client";
|
||||||
import { ActionsEnvVars } from "../environment";
|
import { ActionsEnvVars } from "../environment";
|
||||||
|
import { GITHUB_DOTCOM_URL } from "../github";
|
||||||
import {
|
import {
|
||||||
isRepositoryNwoStr,
|
isRepositoryNwoStr,
|
||||||
parseRepositoryNwo,
|
parseRepositoryNwo,
|
||||||
type RepositoryNwoStr,
|
type RepositoryNwoStr,
|
||||||
} from "../repository";
|
} from "../repository";
|
||||||
import { GITHUB_DOTCOM_URL, type InstanceURL } from "../util";
|
|
||||||
|
|
||||||
/** The NWO of the standard CodeQL Action repository. */
|
/** The NWO of the standard CodeQL Action repository. */
|
||||||
export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
export const CODEQL_DEFAULT_ACTION_REPOSITORY = "github/codeql-action";
|
||||||
@@ -47,20 +47,14 @@ export function getCodeQLActionRepository(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**A download source is a pair of strings. */
|
/**A download source is a pair of strings. */
|
||||||
export type DownloadSource = [InstanceURL, RepositoryNwoStr];
|
export type DownloadSource = [api.GitHubApiDetails, RepositoryNwoStr];
|
||||||
|
|
||||||
/** GitHub.com, and the canonical Action. */
|
|
||||||
export const DEFAULT_DOWNLOAD_SOURCE: DownloadSource = [
|
|
||||||
GITHUB_DOTCOM_URL,
|
|
||||||
CODEQL_DEFAULT_ACTION_REPOSITORY,
|
|
||||||
];
|
|
||||||
|
|
||||||
/** Decides if the two provided download sources are the same. */
|
/** Decides if the two provided download sources are the same. */
|
||||||
const isSameDownloadSource = (
|
const isSameDownloadSource = (
|
||||||
[srcUrl, srcRepo]: DownloadSource,
|
[srcInstance, srcRepo]: DownloadSource,
|
||||||
[otherUrl, otherRepo]: DownloadSource,
|
[otherInstance, otherRepo]: DownloadSource,
|
||||||
) => {
|
) => {
|
||||||
return srcUrl === otherUrl && srcRepo === otherRepo;
|
return srcInstance.url === otherInstance.url && srcRepo === otherRepo;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A download URL is represented as a string. */
|
/** A download URL is represented as a string. */
|
||||||
@@ -103,13 +97,21 @@ export async function getCodeQLAssetDownloadURL(
|
|||||||
): Promise<DownloadURL> {
|
): Promise<DownloadURL> {
|
||||||
const codeQLActionRepository = getCodeQLActionRepository(action);
|
const codeQLActionRepository = getCodeQLActionRepository(action);
|
||||||
|
|
||||||
|
// We construct the default GitHub.com source here, because `getDotcomApiDetails`
|
||||||
|
// may retrieve the `token` input if we are currently running on GitHub.com and
|
||||||
|
// we want to avoid doing that statically.
|
||||||
|
const defaultDownloadSource: DownloadSource = [
|
||||||
|
api.getDotcomApiDetails(action.env),
|
||||||
|
CODEQL_DEFAULT_ACTION_REPOSITORY,
|
||||||
|
];
|
||||||
|
|
||||||
const potentialDownloadSources: DownloadSource[] = [
|
const potentialDownloadSources: DownloadSource[] = [
|
||||||
// This GitHub instance, and this Action.
|
// This GitHub instance, and this Action.
|
||||||
[apiDetails.url, codeQLActionRepository],
|
[apiDetails, codeQLActionRepository],
|
||||||
// This GitHub instance, and the canonical Action.
|
// This GitHub instance, and the canonical Action.
|
||||||
[apiDetails.url, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
[apiDetails, CODEQL_DEFAULT_ACTION_REPOSITORY],
|
||||||
// GitHub.com, and the canonical Action.
|
// GitHub.com, and the canonical Action.
|
||||||
DEFAULT_DOWNLOAD_SOURCE,
|
defaultDownloadSource,
|
||||||
];
|
];
|
||||||
|
|
||||||
// We now filter out any duplicates.
|
// We now filter out any duplicates.
|
||||||
@@ -122,34 +124,34 @@ export async function getCodeQLAssetDownloadURL(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const [instanceURL, repository] of uniqueDownloadSources) {
|
for (const [instance, repository] of uniqueDownloadSources) {
|
||||||
// If we've reached the final case, short-circuit the API check since we know the asset exists and is public.
|
// If we've reached the final case, short-circuit the API check since we know the asset exists and is public.
|
||||||
if (
|
if (isSameDownloadSource(defaultDownloadSource, [instance, repository])) {
|
||||||
isSameDownloadSource(DEFAULT_DOWNLOAD_SOURCE, [instanceURL, repository])
|
|
||||||
) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { owner: repositoryOwner, repo: repositoryName } =
|
const { owner: repositoryOwner, repo: repositoryName } =
|
||||||
parseRepositoryNwo(repository);
|
parseRepositoryNwo(repository);
|
||||||
try {
|
try {
|
||||||
const release = await api.getApiClient().rest.repos.getReleaseByTag({
|
const release = await api
|
||||||
owner: repositoryOwner,
|
.getApiClient(action.env, instance)
|
||||||
repo: repositoryName,
|
.rest.repos.getReleaseByTag({
|
||||||
tag: tagName,
|
owner: repositoryOwner,
|
||||||
});
|
repo: repositoryName,
|
||||||
|
tag: tagName,
|
||||||
|
});
|
||||||
|
|
||||||
for (const asset of release.data.assets) {
|
for (const asset of release.data.assets) {
|
||||||
if (asset.name === assetName) {
|
if (asset.name === assetName) {
|
||||||
action.logger.info(
|
action.logger.info(
|
||||||
`Found ${assetKind} ${assetName} in ${repository} on ${instanceURL} with URL ${asset.url}.`,
|
`Found ${assetKind} ${assetName} in ${repository} on ${instance.apiURL} with URL ${asset.url}.`,
|
||||||
);
|
);
|
||||||
return asset.url;
|
return asset.url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
action.logger.info(
|
action.logger.info(
|
||||||
`Looked for ${assetKind} ${assetName} in ${repository} on ${instanceURL} but got error ${e}.`,
|
`Looked for ${assetKind} ${assetName} in ${repository} on ${instance.apiURL} but got error ${e}.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { ActionState } from "./action-common";
|
|||||||
import * as actionsUtil from "./actions-util";
|
import * as actionsUtil from "./actions-util";
|
||||||
import * as apiClient from "./api-client";
|
import * as apiClient from "./api-client";
|
||||||
import * as defaults from "./defaults.json";
|
import * as defaults from "./defaults.json";
|
||||||
import { ActionsEnvVars } from "./environment";
|
import { ActionsEnvVars, type Env } from "./environment";
|
||||||
import { setUpFeatureFlagTests } from "./feature-flags/testing-util";
|
import { setUpFeatureFlagTests } from "./feature-flags/testing-util";
|
||||||
import { UnvalidatedObject, validateSchema } from "./json";
|
import { UnvalidatedObject, validateSchema } from "./json";
|
||||||
import { makeFromSchema } from "./json/testing-util";
|
import { makeFromSchema } from "./json/testing-util";
|
||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
initAllState,
|
initAllState,
|
||||||
makeMacro,
|
makeMacro,
|
||||||
makeTestToken,
|
makeTestToken,
|
||||||
|
mockApiDetails,
|
||||||
RecordingLogger,
|
RecordingLogger,
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
setupTests,
|
setupTests,
|
||||||
@@ -613,18 +614,23 @@ test("getProxyPackage - includes platform in name", (t) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function mockGetApiClient(endpoints: any) {
|
function mockGetApiClient(env: Env, endpoints: any) {
|
||||||
return (
|
const getRequiredInput = mockApiDetails(SAMPLE_DOTCOM_API_DETAILS, env);
|
||||||
sinon
|
const getApiClient = sinon
|
||||||
.stub(apiClient, "getApiClient")
|
.stub(apiClient, "getApiClient")
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||||
.returns({ rest: endpoints } as any)
|
.returns({ rest: endpoints } as any);
|
||||||
);
|
|
||||||
|
return { getRequiredInput, getApiClient };
|
||||||
}
|
}
|
||||||
|
|
||||||
type ReleaseAssets = Array<{ name: string; url?: string }>;
|
type ReleaseAssets = Array<{ name: string; url?: string }>;
|
||||||
|
|
||||||
function mockGetReleaseByTag(expectedTag?: string, assets?: ReleaseAssets) {
|
function mockGetReleaseByTag(
|
||||||
|
env: Env,
|
||||||
|
expectedTag?: string,
|
||||||
|
assets?: ReleaseAssets,
|
||||||
|
) {
|
||||||
const getReleaseByTag =
|
const getReleaseByTag =
|
||||||
assets === undefined
|
assets === undefined
|
||||||
? sinon.stub().rejects()
|
? sinon.stub().rejects()
|
||||||
@@ -645,7 +651,7 @@ function mockGetReleaseByTag(expectedTag?: string, assets?: ReleaseAssets) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
getReleaseByTag,
|
getReleaseByTag,
|
||||||
getApiClient: mockGetApiClient({ repos: { getReleaseByTag } }),
|
...mockGetApiClient(env, { repos: { getReleaseByTag } }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -671,7 +677,6 @@ test.serial(
|
|||||||
"getDownloadUrl logs unknown platforms/arch and defaults to linux64",
|
"getDownloadUrl logs unknown platforms/arch and defaults to linux64",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const logger = new RecordingLogger();
|
const logger = new RecordingLogger();
|
||||||
mockGetReleaseByTag();
|
|
||||||
|
|
||||||
await withTmpDir(async (tempDir) => {
|
await withTmpDir(async (tempDir) => {
|
||||||
const features = mockOfflineFeatures(tempDir, logger);
|
const features = mockOfflineFeatures(tempDir, logger);
|
||||||
@@ -681,6 +686,7 @@ test.serial(
|
|||||||
logger,
|
logger,
|
||||||
features,
|
features,
|
||||||
});
|
});
|
||||||
|
mockGetReleaseByTag(state.env);
|
||||||
|
|
||||||
// Stub this to always return `true` so we get the default repo for the tests.
|
// Stub this to always return `true` so we get the default repo for the tests.
|
||||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||||
@@ -710,11 +716,11 @@ test.serial(
|
|||||||
"getDownloadUrl returns default bundle URL for linked version",
|
"getDownloadUrl returns default bundle URL for linked version",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const logger = new RecordingLogger();
|
const logger = new RecordingLogger();
|
||||||
mockGetReleaseByTag();
|
|
||||||
|
|
||||||
await withTmpDir(async (tempDir) => {
|
await withTmpDir(async (tempDir) => {
|
||||||
const features = mockOfflineFeatures(tempDir, logger);
|
const features = mockOfflineFeatures(tempDir, logger);
|
||||||
const state = initAllState({ logger, features });
|
const state = initAllState({ logger, features });
|
||||||
|
mockGetReleaseByTag(state.env);
|
||||||
|
|
||||||
// Stub this to always return `true` so we get the default repo for the tests.
|
// Stub this to always return `true` so we get the default repo for the tests.
|
||||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||||
@@ -750,7 +756,11 @@ test.serial(
|
|||||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||||
|
|
||||||
for (const assets of testAssets) {
|
for (const assets of testAssets) {
|
||||||
const stubs = mockGetReleaseByTag(defaults.bundleVersion, assets);
|
const stubs = mockGetReleaseByTag(
|
||||||
|
state.env,
|
||||||
|
defaults.bundleVersion,
|
||||||
|
assets,
|
||||||
|
);
|
||||||
const info = await startProxyExports.getDownloadUrl(
|
const info = await startProxyExports.getDownloadUrl(
|
||||||
state,
|
state,
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
@@ -768,6 +778,7 @@ test.serial(
|
|||||||
// mockGetReleaseByTag stubs the global getApiClient; since we are calling
|
// mockGetReleaseByTag stubs the global getApiClient; since we are calling
|
||||||
// that in a loop, we need to manually restore it here
|
// that in a loop, we need to manually restore it here
|
||||||
stubs.getApiClient.restore();
|
stubs.getApiClient.restore();
|
||||||
|
stubs.getRequiredInput.restore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -783,7 +794,7 @@ test.serial("getDownloadUrl returns matching release asset", async (t) => {
|
|||||||
url: "url-we-want",
|
url: "url-we-want",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const stubs = mockGetReleaseByTag(defaults.bundleVersion, assets);
|
const stubs = mockGetReleaseByTag(state.env, defaults.bundleVersion, assets);
|
||||||
|
|
||||||
await withTmpDir(async (tempDir) => {
|
await withTmpDir(async (tempDir) => {
|
||||||
state.env.set(ActionsEnvVars.RUNNER_TEMP, tempDir);
|
state.env.set(ActionsEnvVars.RUNNER_TEMP, tempDir);
|
||||||
@@ -925,7 +936,8 @@ test.serial(
|
|||||||
"getProxyBinaryPath - returns path from tool cache if available",
|
"getProxyBinaryPath - returns path from tool cache if available",
|
||||||
async (t) => {
|
async (t) => {
|
||||||
const logger = new RecordingLogger();
|
const logger = new RecordingLogger();
|
||||||
mockGetReleaseByTag();
|
|
||||||
|
sinon.stub(apiClient, "getApiDetails").returns(SAMPLE_DOTCOM_API_DETAILS);
|
||||||
|
|
||||||
await withTmpDir(async (tempDir) => {
|
await withTmpDir(async (tempDir) => {
|
||||||
const toolcachePath = "/path/to/proxy/dir";
|
const toolcachePath = "/path/to/proxy/dir";
|
||||||
@@ -935,8 +947,11 @@ test.serial(
|
|||||||
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
sinon.stub(actionsUtil, "isRunningLocalAction").returns(true);
|
||||||
|
|
||||||
const features = mockOfflineFeatures(tempDir, logger);
|
const features = mockOfflineFeatures(tempDir, logger);
|
||||||
|
const state = initAllState({ logger, features });
|
||||||
|
mockGetReleaseByTag(state.env);
|
||||||
|
|
||||||
const result = await startProxyExports.getProxyBinaryPath(
|
const result = await startProxyExports.getProxyBinaryPath(
|
||||||
initAllState({ logger, features }),
|
state,
|
||||||
SAMPLE_DOTCOM_API_DETAILS,
|
SAMPLE_DOTCOM_API_DETAILS,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -956,7 +971,7 @@ test.serial(
|
|||||||
const logger = new RecordingLogger();
|
const logger = new RecordingLogger();
|
||||||
const state = initAllState({ logger });
|
const state = initAllState({ logger });
|
||||||
const downloadUrl = "url-we-want";
|
const downloadUrl = "url-we-want";
|
||||||
const stubs = mockGetReleaseByTag(defaults.bundleVersion, [
|
const stubs = mockGetReleaseByTag(state.env, defaults.bundleVersion, [
|
||||||
{
|
{
|
||||||
name: startProxyExports.getProxyPackage(getTestPlatform(state)),
|
name: startProxyExports.getProxyPackage(getTestPlatform(state)),
|
||||||
url: downloadUrl,
|
url: downloadUrl,
|
||||||
@@ -965,9 +980,16 @@ test.serial(
|
|||||||
|
|
||||||
const toolcachePath = "/path/to/proxy/dir";
|
const toolcachePath = "/path/to/proxy/dir";
|
||||||
const find = sinon.stub(toolcache, "find").returns("");
|
const find = sinon.stub(toolcache, "find").returns("");
|
||||||
|
const apiDetails = {
|
||||||
|
auth: "",
|
||||||
|
url: "",
|
||||||
|
apiURL: "",
|
||||||
|
} satisfies apiClient.GitHubApiDetails;
|
||||||
|
const client = new apiClient.InstanceApiClient(apiDetails);
|
||||||
const getAuthorizationHeaderFor = sinon
|
const getAuthorizationHeaderFor = sinon
|
||||||
.stub(apiClient, "getAuthorizationHeaderFor")
|
.stub(client, "getAuthorizationHeaderFor")
|
||||||
.returns(undefined);
|
.returns(undefined);
|
||||||
|
sinon.stub(apiClient, "InstanceApiClient").returns(client);
|
||||||
const archivePath = "/path/to/archive";
|
const archivePath = "/path/to/archive";
|
||||||
const downloadTool = sinon
|
const downloadTool = sinon
|
||||||
.stub(toolcache, "downloadTool")
|
.stub(toolcache, "downloadTool")
|
||||||
@@ -1007,7 +1029,7 @@ test.serial(
|
|||||||
t.is(result.version, defaults.cliVersion);
|
t.is(result.version, defaults.cliVersion);
|
||||||
|
|
||||||
checkExpectedLogMessages(t, logger.messages, [
|
checkExpectedLogMessages(t, logger.messages, [
|
||||||
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://github.com with URL ${downloadUrl}`,
|
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://api.github.com with URL ${downloadUrl}`,
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1039,14 +1061,21 @@ test.serial(
|
|||||||
headers: {},
|
headers: {},
|
||||||
url: "GET /repos/:owner/:repo/releases/tags/:tag",
|
url: "GET /repos/:owner/:repo/releases/tags/:tag",
|
||||||
});
|
});
|
||||||
mockGetApiClient({ repos: { getReleaseByTag } });
|
mockGetApiClient(state.env, { repos: { getReleaseByTag } });
|
||||||
|
|
||||||
await withTmpDir(async (tempDir) => {
|
await withTmpDir(async (tempDir) => {
|
||||||
const toolcachePath = "/path/to/proxy/dir";
|
const toolcachePath = "/path/to/proxy/dir";
|
||||||
const find = sinon.stub(toolcache, "find").returns("");
|
const find = sinon.stub(toolcache, "find").returns("");
|
||||||
|
const apiDetails = {
|
||||||
|
auth: "",
|
||||||
|
url: "",
|
||||||
|
apiURL: "",
|
||||||
|
} satisfies apiClient.GitHubApiDetails;
|
||||||
|
const client = new apiClient.InstanceApiClient(apiDetails);
|
||||||
const getAuthorizationHeaderFor = sinon
|
const getAuthorizationHeaderFor = sinon
|
||||||
.stub(apiClient, "getAuthorizationHeaderFor")
|
.stub(client, "getAuthorizationHeaderFor")
|
||||||
.returns(undefined);
|
.returns(undefined);
|
||||||
|
sinon.stub(apiClient, "InstanceApiClient").returns(client);
|
||||||
const archivePath = "/path/to/archive";
|
const archivePath = "/path/to/archive";
|
||||||
const downloadTool = sinon
|
const downloadTool = sinon
|
||||||
.stub(toolcache, "downloadTool")
|
.stub(toolcache, "downloadTool")
|
||||||
@@ -1107,7 +1136,7 @@ test.serial(
|
|||||||
});
|
});
|
||||||
|
|
||||||
checkExpectedLogMessages(t, logger.messages, [
|
checkExpectedLogMessages(t, logger.messages, [
|
||||||
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://github.com with URL url-we-want.`,
|
`Found private registry proxy ${startProxyExports.getProxyPackage(getTestPlatform(state))} in test/repo on https://api.github.com with URL url-we-want.`,
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import * as toolcache from "@actions/tool-cache";
|
|||||||
|
|
||||||
import { ActionState } from "./action-common";
|
import { ActionState } from "./action-common";
|
||||||
import {
|
import {
|
||||||
getAuthorizationHeaderFor,
|
|
||||||
getGitHubVersion,
|
getGitHubVersion,
|
||||||
GitHubApiDetails,
|
InstanceApiClient,
|
||||||
|
type GitHubApiDetails,
|
||||||
} from "./api-client";
|
} from "./api-client";
|
||||||
import * as artifactScanner from "./artifact-scanner";
|
import * as artifactScanner from "./artifact-scanner";
|
||||||
import * as defaults from "./defaults.json";
|
import * as defaults from "./defaults.json";
|
||||||
@@ -423,6 +423,7 @@ export async function getProxyBinaryPath(
|
|||||||
logger.startGroup("Setting up authentication proxy");
|
logger.startGroup("Setting up authentication proxy");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const client = new InstanceApiClient(apiDetails);
|
||||||
const proxyFileName = getProxyFilename();
|
const proxyFileName = getProxyFilename();
|
||||||
const proxyInfo = await getDownloadUrl(action, apiDetails);
|
const proxyInfo = await getDownloadUrl(action, apiDetails);
|
||||||
|
|
||||||
@@ -437,9 +438,8 @@ export async function getProxyBinaryPath(
|
|||||||
`Authentication proxy is not in the toolcache. Will try to download it from '${proxyInfo.url}'.`,
|
`Authentication proxy is not in the toolcache. Will try to download it from '${proxyInfo.url}'.`,
|
||||||
);
|
);
|
||||||
|
|
||||||
const authorization = getAuthorizationHeaderFor(
|
const authorization = client.getAuthorizationHeaderFor(
|
||||||
logger,
|
logger,
|
||||||
apiDetails,
|
|
||||||
proxyInfo.url,
|
proxyInfo.url,
|
||||||
);
|
);
|
||||||
const temp = await downloadProxy(logger, proxyInfo.url, authorization);
|
const temp = await downloadProxy(logger, proxyInfo.url, authorization);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import {
|
|||||||
exportEnvVar,
|
exportEnvVar,
|
||||||
} from "./environment";
|
} from "./environment";
|
||||||
import { getRef } from "./git-utils";
|
import { getRef } from "./git-utils";
|
||||||
|
import { GITHUB_DOTCOM_URL } from "./github";
|
||||||
import * as json from "./json";
|
import * as json from "./json";
|
||||||
import type { Logger } from "./logging";
|
import type { Logger } from "./logging";
|
||||||
import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching";
|
import type { OverlayBaseDatabaseDownloadStats } from "./overlay/caching";
|
||||||
@@ -41,7 +42,6 @@ import {
|
|||||||
ConfigurationError,
|
ConfigurationError,
|
||||||
getRequiredEnvParam,
|
getRequiredEnvParam,
|
||||||
isInTestMode,
|
isInTestMode,
|
||||||
GITHUB_DOTCOM_URL,
|
|
||||||
DiskUsage,
|
DiskUsage,
|
||||||
assertNever,
|
assertNever,
|
||||||
BuildMode,
|
BuildMode,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import * as sinon from "sinon";
|
|||||||
|
|
||||||
import { ActionState, StateFeature } from "./action-common";
|
import { ActionState, StateFeature } from "./action-common";
|
||||||
import { ActionsEnv, getActionVersion } from "./actions-util";
|
import { ActionsEnv, getActionVersion } from "./actions-util";
|
||||||
|
import * as actionsUtil from "./actions-util";
|
||||||
import { AnalysisKind } from "./analyses";
|
import { AnalysisKind } from "./analyses";
|
||||||
import * as apiClient from "./api-client";
|
import * as apiClient from "./api-client";
|
||||||
import { GitHubApiDetails } from "./api-client";
|
import { GitHubApiDetails } from "./api-client";
|
||||||
@@ -52,6 +53,23 @@ export const SAMPLE_DOTCOM_API_DETAILS = {
|
|||||||
apiURL: "https://api.github.com",
|
apiURL: "https://api.github.com",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function mockApiDetails(
|
||||||
|
apiDetails: Required<GitHubApiDetails>,
|
||||||
|
env: Env = getEnv(),
|
||||||
|
) {
|
||||||
|
// This is a workaround to mock `api.getApiDetails()` since it doesn't seem to be possible to
|
||||||
|
// mock this directly. The difficulty is that `getApiDetails()` is called locally in
|
||||||
|
// `api-client.ts`, but `sinon.stub(api, "getApiDetails")` only affects calls to
|
||||||
|
// `getApiDetails()` via an imported `api` module.
|
||||||
|
const getRequiredInput = sinon.stub(actionsUtil, "getRequiredInput");
|
||||||
|
getRequiredInput.withArgs("token").returns(apiDetails.auth);
|
||||||
|
|
||||||
|
env.set("GITHUB_SERVER_URL", apiDetails.url);
|
||||||
|
env.set("GITHUB_API_URL", apiDetails.apiURL ?? "");
|
||||||
|
|
||||||
|
return getRequiredInput;
|
||||||
|
}
|
||||||
|
|
||||||
export const LINKED_CLI_VERSION = {
|
export const LINKED_CLI_VERSION = {
|
||||||
cliVersion: defaults.cliVersion,
|
cliVersion: defaults.cliVersion,
|
||||||
tagName: defaults.bundleVersion,
|
tagName: defaults.bundleVersion,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { ActionsEnvVars, EnvVar, exportEnvVar } from "./environment";
|
|||||||
import { FeatureEnablement } from "./feature-flags";
|
import { FeatureEnablement } from "./feature-flags";
|
||||||
import * as fingerprints from "./fingerprints";
|
import * as fingerprints from "./fingerprints";
|
||||||
import * as gitUtils from "./git-utils";
|
import * as gitUtils from "./git-utils";
|
||||||
|
import * as github from "./github";
|
||||||
import { initCodeQL } from "./init";
|
import { initCodeQL } from "./init";
|
||||||
import { Logger } from "./logging";
|
import { Logger } from "./logging";
|
||||||
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
import { getRepositoryNwo, RepositoryNwo } from "./repository";
|
||||||
@@ -33,7 +34,6 @@ import * as util from "./util";
|
|||||||
import {
|
import {
|
||||||
ConfigurationError,
|
ConfigurationError,
|
||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
getRequiredEnvParam,
|
|
||||||
GitHubVariant,
|
GitHubVariant,
|
||||||
GitHubVersion,
|
GitHubVersion,
|
||||||
satisfiesGHESVersion,
|
satisfiesGHESVersion,
|
||||||
@@ -104,6 +104,8 @@ async function combineSarifFilesUsingCLI(
|
|||||||
features: FeatureEnablement,
|
features: FeatureEnablement,
|
||||||
logger: Logger,
|
logger: Logger,
|
||||||
): Promise<Partial<sarif.Log>> {
|
): Promise<Partial<sarif.Log>> {
|
||||||
|
const env = util.getEnv();
|
||||||
|
|
||||||
logger.info("Combining SARIF files using the CodeQL CLI");
|
logger.info("Combining SARIF files using the CodeQL CLI");
|
||||||
|
|
||||||
const sarifObjects = sarifFiles.map(sarif.readSarifFile);
|
const sarifObjects = sarifFiles.map(sarif.readSarifFile);
|
||||||
@@ -152,8 +154,7 @@ async function combineSarifFilesUsingCLI(
|
|||||||
externalRepoAuth: actionsUtil.getOptionalInput(
|
externalRepoAuth: actionsUtil.getOptionalInput(
|
||||||
"external-repository-token",
|
"external-repository-token",
|
||||||
),
|
),
|
||||||
url: getRequiredEnvParam("GITHUB_SERVER_URL"),
|
...github.getCurrentInstance(env),
|
||||||
apiURL: getRequiredEnvParam("GITHUB_API_URL"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const codeQLDefaultVersionInfo =
|
const codeQLDefaultVersionInfo =
|
||||||
|
|||||||
@@ -164,66 +164,6 @@ test.serial("getExtraOptionsEnvParam() fails on invalid JSON", (t) => {
|
|||||||
process.env.CODEQL_ACTION_EXTRA_OPTIONS = origExtraOptions;
|
process.env.CODEQL_ACTION_EXTRA_OPTIONS = origExtraOptions;
|
||||||
});
|
});
|
||||||
|
|
||||||
test("parseGitHubUrl", (t) => {
|
|
||||||
t.deepEqual(util.parseGitHubUrl("github.com"), "https://github.com");
|
|
||||||
t.deepEqual(util.parseGitHubUrl("https://github.com"), "https://github.com");
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://api.github.com"),
|
|
||||||
"https://github.com",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.com/foo/bar"),
|
|
||||||
"https://github.com",
|
|
||||||
);
|
|
||||||
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("github.example.com"),
|
|
||||||
"https://github.example.com/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.example.com"),
|
|
||||||
"https://github.example.com/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://api.github.example.com"),
|
|
||||||
"https://github.example.com/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.example.com/api/v3"),
|
|
||||||
"https://github.example.com/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.example.com:1234"),
|
|
||||||
"https://github.example.com:1234/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://api.github.example.com:1234"),
|
|
||||||
"https://github.example.com:1234/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.example.com:1234/api/v3"),
|
|
||||||
"https://github.example.com:1234/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.example.com/base/path"),
|
|
||||||
"https://github.example.com/base/path/",
|
|
||||||
);
|
|
||||||
t.deepEqual(
|
|
||||||
util.parseGitHubUrl("https://github.example.com/base/path/api/v3"),
|
|
||||||
"https://github.example.com/base/path/",
|
|
||||||
);
|
|
||||||
|
|
||||||
t.throws(() => util.parseGitHubUrl(""), {
|
|
||||||
message: '"" is not a valid URL',
|
|
||||||
});
|
|
||||||
t.throws(() => util.parseGitHubUrl("ssh://github.com"), {
|
|
||||||
message: '"ssh://github.com" is not a http or https URL',
|
|
||||||
});
|
|
||||||
t.throws(() => util.parseGitHubUrl("http:///::::433"), {
|
|
||||||
message: '"http:///::::433" is not a valid URL',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("allowed API versions", async (t) => {
|
test("allowed API versions", async (t) => {
|
||||||
t.is(util.apiVersionInRange("1.33.0", "1.33", "2.0"), undefined);
|
t.is(util.apiVersionInRange("1.33.0", "1.33", "2.0"), undefined);
|
||||||
t.is(util.apiVersionInRange("1.33.1", "1.33", "2.0"), undefined);
|
t.is(util.apiVersionInRange("1.33.1", "1.33", "2.0"), undefined);
|
||||||
|
|||||||
48
src/util.ts
48
src/util.ts
@@ -50,11 +50,6 @@ const BROKEN_VERSIONS = ["0.0.0-20211207"];
|
|||||||
/** A string representing a GitHub instance. */
|
/** A string representing a GitHub instance. */
|
||||||
export type InstanceURL = string;
|
export type InstanceURL = string;
|
||||||
|
|
||||||
/**
|
|
||||||
* The URL for github.com.
|
|
||||||
*/
|
|
||||||
export const GITHUB_DOTCOM_URL: InstanceURL = "https://github.com";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default name of the debugging artifact.
|
* Default name of the debugging artifact.
|
||||||
*/
|
*/
|
||||||
@@ -470,49 +465,6 @@ export function getGeneratedSuitePath(config: Config, language: Language) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses user input of a github.com or GHES URL to a canonical form.
|
|
||||||
* Removes any API prefix or suffix if one is present.
|
|
||||||
*/
|
|
||||||
export function parseGitHubUrl(inputUrl: string): string {
|
|
||||||
const originalUrl = inputUrl;
|
|
||||||
if (inputUrl.indexOf("://") === -1) {
|
|
||||||
inputUrl = `https://${inputUrl}`;
|
|
||||||
}
|
|
||||||
if (!inputUrl.startsWith("http://") && !inputUrl.startsWith("https://")) {
|
|
||||||
throw new ConfigurationError(`"${originalUrl}" is not a http or https URL`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let url: URL;
|
|
||||||
try {
|
|
||||||
url = new URL(inputUrl);
|
|
||||||
} catch {
|
|
||||||
throw new ConfigurationError(`"${originalUrl}" is not a valid URL`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we detect this is trying to be to github.com
|
|
||||||
// then return with a fixed canonical URL.
|
|
||||||
if (url.hostname === "github.com" || url.hostname === "api.github.com") {
|
|
||||||
return GITHUB_DOTCOM_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the API prefix if it's present
|
|
||||||
if (url.pathname.indexOf("/api/v3") !== -1) {
|
|
||||||
url.pathname = url.pathname.substring(0, url.pathname.indexOf("/api/v3"));
|
|
||||||
}
|
|
||||||
// Also consider subdomain isolation on GHES
|
|
||||||
if (url.hostname.startsWith("api.")) {
|
|
||||||
url.hostname = url.hostname.substring(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalise path to having a trailing slash for consistency
|
|
||||||
if (!url.pathname.endsWith("/")) {
|
|
||||||
url.pathname = `${url.pathname}/`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
const CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR =
|
const CODEQL_ACTION_WARNED_ABOUT_VERSION_ENV_VAR =
|
||||||
"CODEQL_ACTION_WARNED_ABOUT_VERSION";
|
"CODEQL_ACTION_WARNED_ABOUT_VERSION";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user