mirror of https://github.com/actions/setup-go.git
Compare commits
10 Commits
Author | SHA1 | Date |
---|---|---|
|
3041bf56c9 | |
|
41dfa10bad | |
|
941977282c | |
|
d60b41a563 | |
|
e09f57f6a9 | |
|
df1a11710e | |
|
49582f6476 | |
|
b26d40294f | |
|
0a12ed9d6a | |
|
4ab57d7ea2 |
|
@ -0,0 +1,20 @@
|
|||
name: 'Publish Immutable Action Version'
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checking out
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish
|
||||
id: publish
|
||||
uses: actions/publish-immutable-action@0.0.3
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update the ${{ env.TAG_NAME }} tag
|
||||
uses: actions/publish-action@v0.2.2
|
||||
uses: actions/publish-action@v0.3.0
|
||||
with:
|
||||
source-tag: ${{ env.TAG_NAME }}
|
||||
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
|
||||
|
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go Stable
|
||||
|
@ -33,7 +33,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go oldStable
|
||||
|
@ -48,12 +48,14 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
version: [stable, oldstable]
|
||||
architecture: [x64, x32]
|
||||
exclude:
|
||||
- os: macos-latest
|
||||
architecture: x32
|
||||
- os: macos-13
|
||||
architecture: x32
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go ${{ matrix.version }} ${{ matrix.architecture }}
|
||||
|
@ -70,8 +72,14 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
go: [1.17, 1.18, 1.19]
|
||||
os: [macos-latest, windows-latest, ubuntu-latest, macos-13]
|
||||
go: [1.21.13, 1.22.8, 1.23.2]
|
||||
include:
|
||||
- os: windows-latest
|
||||
go: 1.20.14
|
||||
exclude:
|
||||
- os: windows-latest
|
||||
go: 1.23.2
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
@ -90,8 +98,8 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
go-version: [1.16, 1.17]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
go-version: ['1.20', '1.21', '1.22', '1.23']
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go and check latest
|
||||
|
@ -107,7 +115,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go and check latest
|
||||
|
@ -115,7 +123,7 @@ jobs:
|
|||
with:
|
||||
go-version-file: __tests__/data/go.mod
|
||||
- name: verify go
|
||||
run: __tests__/verify-go.sh 1.14
|
||||
run: __tests__/verify-go.sh 1.20.14
|
||||
shell: bash
|
||||
|
||||
go-version-file-with-gowork:
|
||||
|
@ -123,7 +131,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go and check latest
|
||||
|
@ -131,17 +139,16 @@ jobs:
|
|||
with:
|
||||
go-version-file: __tests__/data/go.work
|
||||
- name: verify go
|
||||
run: __tests__/verify-go.sh 1.19
|
||||
run: __tests__/verify-go.sh 1.21
|
||||
shell: bash
|
||||
|
||||
setup-versions-from-manifest:
|
||||
name: Setup ${{ matrix.go }} ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
go: [1.12.16, 1.13.11, 1.14.3]
|
||||
os: [macos-latest, windows-latest, ubuntu-latest, macos-13]
|
||||
go: [1.20.14, 1.21.10, 1.22.8, 1.23.2]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
@ -156,13 +163,12 @@ jobs:
|
|||
shell: bash
|
||||
|
||||
setup-versions-from-dist:
|
||||
name: Setup ${{ matrix.go }} ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, windows-latest, ubuntu-latest]
|
||||
go: [1.9, 1.8.6]
|
||||
os: [windows-latest, ubuntu-latest, macos-13]
|
||||
go: [1.11.12]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
@ -181,14 +187,23 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
go-version: [1.16, 1.17]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest, macos-13]
|
||||
go-version: [1.20.14, 1.21, 1.22, 1.23]
|
||||
include:
|
||||
- os: macos-latest
|
||||
architecture: arm64
|
||||
- os: ubuntu-latest
|
||||
architecture: x64
|
||||
- os: windows-latest
|
||||
architecture: x64
|
||||
- os: macos-13
|
||||
architecture: x64
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Setup Go and check latest
|
||||
uses: ./
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
architecture: x64
|
||||
architecture: ${{ matrix.architecture }}
|
||||
- name: Verify Go
|
||||
run: go version
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
name: undici
|
||||
version: 5.28.3
|
||||
version: 5.28.4
|
||||
type: npm
|
||||
summary: An HTTP/1.1 client, written from scratch for Node.js
|
||||
homepage: https://undici.nodejs.org
|
||||
|
|
21
README.md
21
README.md
|
@ -242,18 +242,14 @@ documentation.
|
|||
|
||||
## Using `setup-go` on GHES
|
||||
|
||||
`setup-go` comes pre-installed on the appliance with GHES if Actions is enabled. When dynamically downloading Go
|
||||
distributions, `setup-go` downloads distributions from [`actions/go-versions`](https://github.com/actions/go-versions)
|
||||
on github.com (outside of the appliance). These calls to `actions/go-versions` are made via unauthenticated requests,
|
||||
which are limited
|
||||
to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). If
|
||||
more requests are made within the time frame, then you will start to see rate-limit errors during downloading that looks
|
||||
like: `##[error]API rate limit exceeded for...`. After that error the action will try to download versions directly
|
||||
from https://storage.googleapis.com/golang, but it also can have rate limit so it's better to put token.
|
||||
`setup-go` comes pre-installed on the appliance with GHES if Actions is enabled.
|
||||
When dynamically downloading Go distributions, `setup-go` downloads distributions from [`actions/go-versions`](https://github.com/actions/go-versions) on github.com (outside of the appliance).
|
||||
|
||||
To get a higher rate limit, you
|
||||
can [generate a personal access token on github.com](https://github.com/settings/tokens/new) and pass it as the `token`
|
||||
input for the action:
|
||||
These calls to `actions/go-versions` are made via unauthenticated requests, which are limited to [60 requests per hour per IP](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting).
|
||||
If more requests are made within the time frame, then the action leverages the `raw API` to retrieve the version-manifest. This approach does not impose a rate limit and hence facilitates unrestricted consumption. This is particularly beneficial for GHES runners, which often share the same IP, to avoid the quick exhaustion of the unauthenticated rate limit.
|
||||
If that fails as well the action will try to download versions directly from https://storage.googleapis.com/golang.
|
||||
|
||||
If that fails as well you can get a higher rate limit with [generating a personal access token on github.com](https://github.com/settings/tokens/new) and passing it as the `token` input to the action:
|
||||
|
||||
```yaml
|
||||
uses: actions/setup-go@v5
|
||||
|
@ -262,8 +258,7 @@ with:
|
|||
go-version: '1.18'
|
||||
```
|
||||
|
||||
If the runner is not able to access github.com, any Go versions requested during a workflow run must come from the
|
||||
runner's tool cache.
|
||||
If the runner is not able to access github.com, any Go versions requested during a workflow run must come from the runner's tool cache.
|
||||
See "[Setting up the tool cache on self-hosted runners without internet access](https://docs.github.com/en/enterprise-server@3.2/admin/github-actions/managing-access-to-actions-from-githubcom/setting-up-the-tool-cache-on-self-hosted-runners-without-internet-access)"
|
||||
for more information.
|
||||
|
||||
|
|
|
@ -209,3 +209,41 @@ describe('isCacheFeatureAvailable', () => {
|
|||
expect(warningSpy).toHaveBeenCalledWith(warningMessage);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isGhes', () => {
|
||||
const pristineEnv = process.env;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
process.env = {...pristineEnv};
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
process.env = pristineEnv;
|
||||
});
|
||||
|
||||
it('returns false when the GITHUB_SERVER_URL environment variable is not defined', async () => {
|
||||
delete process.env['GITHUB_SERVER_URL'];
|
||||
expect(cacheUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false when the GITHUB_SERVER_URL environment variable is set to github.com', async () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://github.com';
|
||||
expect(cacheUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false when the GITHUB_SERVER_URL environment variable is set to a GitHub Enterprise Cloud-style URL', async () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://contoso.ghe.com';
|
||||
expect(cacheUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns false when the GITHUB_SERVER_URL environment variable has a .localhost suffix', async () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://mock-github.localhost';
|
||||
expect(cacheUtils.isGhes()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('returns true when the GITHUB_SERVER_URL environment variable is set to some other URL', async () => {
|
||||
process.env['GITHUB_SERVER_URL'] = 'https://src.onpremise.fabrikam.com';
|
||||
expect(cacheUtils.isGhes()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module example.com/mymodule
|
||||
|
||||
go 1.14
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
example.com/othermodule v1.2.3
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
go 1.19
|
||||
go 1.21
|
||||
|
||||
use .
|
||||
|
|
|
@ -7,6 +7,7 @@ import osm, {type} from 'os';
|
|||
import path from 'path';
|
||||
import * as main from '../src/main';
|
||||
import * as im from '../src/installer';
|
||||
import * as httpm from '@actions/http-client';
|
||||
|
||||
import goJsonData from './data/golang-dl.json';
|
||||
import matchers from '../matchers.json';
|
||||
|
@ -46,6 +47,7 @@ describe('setup-go', () => {
|
|||
let execSpy: jest.SpyInstance;
|
||||
let getManifestSpy: jest.SpyInstance;
|
||||
let getAllVersionsSpy: jest.SpyInstance;
|
||||
let httpmGetJsonSpy: jest.SpyInstance;
|
||||
|
||||
beforeAll(async () => {
|
||||
process.env['GITHUB_ENV'] = ''; // Stub out Environment file functionality so we can verify it writes to standard out (toolkit is backwards compatible)
|
||||
|
@ -90,6 +92,9 @@ describe('setup-go', () => {
|
|||
getManifestSpy = jest.spyOn(tc, 'getManifestFromRepo');
|
||||
getAllVersionsSpy = jest.spyOn(im, 'getManifest');
|
||||
|
||||
// httm
|
||||
httpmGetJsonSpy = jest.spyOn(httpm.HttpClient.prototype, 'getJson');
|
||||
|
||||
// io
|
||||
whichSpy = jest.spyOn(io, 'which');
|
||||
existsSpy = jest.spyOn(fs, 'existsSync');
|
||||
|
@ -151,6 +156,21 @@ describe('setup-go', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('should return manifest from repo', async () => {
|
||||
const manifest = await im.getManifest(undefined);
|
||||
expect(manifest).toEqual(goTestManifest);
|
||||
});
|
||||
|
||||
it('should return manifest from raw URL if repo fetch fails', async () => {
|
||||
getManifestSpy.mockRejectedValue(new Error('Fetch failed'));
|
||||
httpmGetJsonSpy.mockResolvedValue({
|
||||
result: goTestManifest
|
||||
});
|
||||
const manifest = await im.getManifest(undefined);
|
||||
expect(httpmGetJsonSpy).toHaveBeenCalled();
|
||||
expect(manifest).toEqual(goTestManifest);
|
||||
});
|
||||
|
||||
it('can find 1.9 from manifest on linux', async () => {
|
||||
os.platform = 'linux';
|
||||
os.arch = 'x64';
|
||||
|
@ -790,6 +810,9 @@ describe('setup-go', () => {
|
|||
getManifestSpy.mockImplementation(() => {
|
||||
throw new Error('Unable to download manifest');
|
||||
});
|
||||
httpmGetJsonSpy.mockRejectedValue(
|
||||
new Error('Unable to download manifest from raw URL')
|
||||
);
|
||||
getAllVersionsSpy.mockImplementationOnce(() => undefined);
|
||||
|
||||
dlSpy.mockImplementation(async () => '/some/temp/path');
|
||||
|
|
|
@ -57964,6 +57964,132 @@ function onConnectTimeout (socket) {
|
|||
module.exports = buildConnector
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 4462:
|
||||
/***/ ((module) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
/** @type {Record<string, string | undefined>} */
|
||||
const headerNameLowerCasedRecord = {}
|
||||
|
||||
// https://developer.mozilla.org/docs/Web/HTTP/Headers
|
||||
const wellknownHeaderNames = [
|
||||
'Accept',
|
||||
'Accept-Encoding',
|
||||
'Accept-Language',
|
||||
'Accept-Ranges',
|
||||
'Access-Control-Allow-Credentials',
|
||||
'Access-Control-Allow-Headers',
|
||||
'Access-Control-Allow-Methods',
|
||||
'Access-Control-Allow-Origin',
|
||||
'Access-Control-Expose-Headers',
|
||||
'Access-Control-Max-Age',
|
||||
'Access-Control-Request-Headers',
|
||||
'Access-Control-Request-Method',
|
||||
'Age',
|
||||
'Allow',
|
||||
'Alt-Svc',
|
||||
'Alt-Used',
|
||||
'Authorization',
|
||||
'Cache-Control',
|
||||
'Clear-Site-Data',
|
||||
'Connection',
|
||||
'Content-Disposition',
|
||||
'Content-Encoding',
|
||||
'Content-Language',
|
||||
'Content-Length',
|
||||
'Content-Location',
|
||||
'Content-Range',
|
||||
'Content-Security-Policy',
|
||||
'Content-Security-Policy-Report-Only',
|
||||
'Content-Type',
|
||||
'Cookie',
|
||||
'Cross-Origin-Embedder-Policy',
|
||||
'Cross-Origin-Opener-Policy',
|
||||
'Cross-Origin-Resource-Policy',
|
||||
'Date',
|
||||
'Device-Memory',
|
||||
'Downlink',
|
||||
'ECT',
|
||||
'ETag',
|
||||
'Expect',
|
||||
'Expect-CT',
|
||||
'Expires',
|
||||
'Forwarded',
|
||||
'From',
|
||||
'Host',
|
||||
'If-Match',
|
||||
'If-Modified-Since',
|
||||
'If-None-Match',
|
||||
'If-Range',
|
||||
'If-Unmodified-Since',
|
||||
'Keep-Alive',
|
||||
'Last-Modified',
|
||||
'Link',
|
||||
'Location',
|
||||
'Max-Forwards',
|
||||
'Origin',
|
||||
'Permissions-Policy',
|
||||
'Pragma',
|
||||
'Proxy-Authenticate',
|
||||
'Proxy-Authorization',
|
||||
'RTT',
|
||||
'Range',
|
||||
'Referer',
|
||||
'Referrer-Policy',
|
||||
'Refresh',
|
||||
'Retry-After',
|
||||
'Sec-WebSocket-Accept',
|
||||
'Sec-WebSocket-Extensions',
|
||||
'Sec-WebSocket-Key',
|
||||
'Sec-WebSocket-Protocol',
|
||||
'Sec-WebSocket-Version',
|
||||
'Server',
|
||||
'Server-Timing',
|
||||
'Service-Worker-Allowed',
|
||||
'Service-Worker-Navigation-Preload',
|
||||
'Set-Cookie',
|
||||
'SourceMap',
|
||||
'Strict-Transport-Security',
|
||||
'Supports-Loading-Mode',
|
||||
'TE',
|
||||
'Timing-Allow-Origin',
|
||||
'Trailer',
|
||||
'Transfer-Encoding',
|
||||
'Upgrade',
|
||||
'Upgrade-Insecure-Requests',
|
||||
'User-Agent',
|
||||
'Vary',
|
||||
'Via',
|
||||
'WWW-Authenticate',
|
||||
'X-Content-Type-Options',
|
||||
'X-DNS-Prefetch-Control',
|
||||
'X-Frame-Options',
|
||||
'X-Permitted-Cross-Domain-Policies',
|
||||
'X-Powered-By',
|
||||
'X-Requested-With',
|
||||
'X-XSS-Protection'
|
||||
]
|
||||
|
||||
for (let i = 0; i < wellknownHeaderNames.length; ++i) {
|
||||
const key = wellknownHeaderNames[i]
|
||||
const lowerCasedKey = key.toLowerCase()
|
||||
headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] =
|
||||
lowerCasedKey
|
||||
}
|
||||
|
||||
// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
|
||||
Object.setPrototypeOf(headerNameLowerCasedRecord, null)
|
||||
|
||||
module.exports = {
|
||||
wellknownHeaderNames,
|
||||
headerNameLowerCasedRecord
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8045:
|
||||
|
@ -58796,6 +58922,7 @@ const { InvalidArgumentError } = __nccwpck_require__(8045)
|
|||
const { Blob } = __nccwpck_require__(4300)
|
||||
const nodeUtil = __nccwpck_require__(3837)
|
||||
const { stringify } = __nccwpck_require__(3477)
|
||||
const { headerNameLowerCasedRecord } = __nccwpck_require__(4462)
|
||||
|
||||
const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v))
|
||||
|
||||
|
@ -59005,6 +59132,15 @@ function parseKeepAliveTimeout (val) {
|
|||
return m ? parseInt(m[1], 10) * 1000 : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a header name and returns its lowercase value.
|
||||
* @param {string | Buffer} value Header name
|
||||
* @returns {string}
|
||||
*/
|
||||
function headerNameToString (value) {
|
||||
return headerNameLowerCasedRecord[value] || value.toLowerCase()
|
||||
}
|
||||
|
||||
function parseHeaders (headers, obj = {}) {
|
||||
// For H2 support
|
||||
if (!Array.isArray(headers)) return headers
|
||||
|
@ -59276,6 +59412,7 @@ module.exports = {
|
|||
isIterable,
|
||||
isAsyncIterable,
|
||||
isDestroyed,
|
||||
headerNameToString,
|
||||
parseRawHeaders,
|
||||
parseHeaders,
|
||||
parseKeepAliveTimeout,
|
||||
|
@ -65923,14 +66060,18 @@ const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(3983
|
|||
const assert = __nccwpck_require__(9491)
|
||||
const { isUint8Array } = __nccwpck_require__(9830)
|
||||
|
||||
let supportedHashes = []
|
||||
|
||||
// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable
|
||||
/** @type {import('crypto')|undefined} */
|
||||
let crypto
|
||||
|
||||
try {
|
||||
crypto = __nccwpck_require__(6113)
|
||||
const possibleRelevantHashes = ['sha256', 'sha384', 'sha512']
|
||||
supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash))
|
||||
/* c8 ignore next 3 */
|
||||
} catch {
|
||||
|
||||
}
|
||||
|
||||
function responseURL (response) {
|
||||
|
@ -66458,66 +66599,56 @@ function bytesMatch (bytes, metadataList) {
|
|||
return true
|
||||
}
|
||||
|
||||
// 3. If parsedMetadata is the empty set, return true.
|
||||
// 3. If response is not eligible for integrity validation, return false.
|
||||
// TODO
|
||||
|
||||
// 4. If parsedMetadata is the empty set, return true.
|
||||
if (parsedMetadata.length === 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 4. Let metadata be the result of getting the strongest
|
||||
// 5. Let metadata be the result of getting the strongest
|
||||
// metadata from parsedMetadata.
|
||||
const list = parsedMetadata.sort((c, d) => d.algo.localeCompare(c.algo))
|
||||
// get the strongest algorithm
|
||||
const strongest = list[0].algo
|
||||
// get all entries that use the strongest algorithm; ignore weaker
|
||||
const metadata = list.filter((item) => item.algo === strongest)
|
||||
const strongest = getStrongestMetadata(parsedMetadata)
|
||||
const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest)
|
||||
|
||||
// 5. For each item in metadata:
|
||||
// 6. For each item in metadata:
|
||||
for (const item of metadata) {
|
||||
// 1. Let algorithm be the alg component of item.
|
||||
const algorithm = item.algo
|
||||
|
||||
// 2. Let expectedValue be the val component of item.
|
||||
let expectedValue = item.hash
|
||||
const expectedValue = item.hash
|
||||
|
||||
// See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e
|
||||
// "be liberal with padding". This is annoying, and it's not even in the spec.
|
||||
|
||||
if (expectedValue.endsWith('==')) {
|
||||
expectedValue = expectedValue.slice(0, -2)
|
||||
}
|
||||
|
||||
// 3. Let actualValue be the result of applying algorithm to bytes.
|
||||
let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64')
|
||||
|
||||
if (actualValue.endsWith('==')) {
|
||||
actualValue = actualValue.slice(0, -2)
|
||||
if (actualValue[actualValue.length - 1] === '=') {
|
||||
if (actualValue[actualValue.length - 2] === '=') {
|
||||
actualValue = actualValue.slice(0, -2)
|
||||
} else {
|
||||
actualValue = actualValue.slice(0, -1)
|
||||
}
|
||||
}
|
||||
|
||||
// 4. If actualValue is a case-sensitive match for expectedValue,
|
||||
// return true.
|
||||
if (actualValue === expectedValue) {
|
||||
return true
|
||||
}
|
||||
|
||||
let actualBase64URL = crypto.createHash(algorithm).update(bytes).digest('base64url')
|
||||
|
||||
if (actualBase64URL.endsWith('==')) {
|
||||
actualBase64URL = actualBase64URL.slice(0, -2)
|
||||
}
|
||||
|
||||
if (actualBase64URL === expectedValue) {
|
||||
if (compareBase64Mixed(actualValue, expectedValue)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Return false.
|
||||
// 7. Return false.
|
||||
return false
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options
|
||||
// https://www.w3.org/TR/CSP2/#source-list-syntax
|
||||
// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1
|
||||
const parseHashWithOptions = /((?<algo>sha256|sha384|sha512)-(?<hash>[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e]?)?/i
|
||||
const parseHashWithOptions = /(?<algo>sha256|sha384|sha512)-((?<hash>[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i
|
||||
|
||||
/**
|
||||
* @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata
|
||||
|
@ -66531,8 +66662,6 @@ function parseMetadata (metadata) {
|
|||
// 2. Let empty be equal to true.
|
||||
let empty = true
|
||||
|
||||
const supportedHashes = crypto.getHashes()
|
||||
|
||||
// 3. For each token returned by splitting metadata on spaces:
|
||||
for (const token of metadata.split(' ')) {
|
||||
// 1. Set empty to false.
|
||||
|
@ -66542,7 +66671,11 @@ function parseMetadata (metadata) {
|
|||
const parsedToken = parseHashWithOptions.exec(token)
|
||||
|
||||
// 3. If token does not parse, continue to the next token.
|
||||
if (parsedToken === null || parsedToken.groups === undefined) {
|
||||
if (
|
||||
parsedToken === null ||
|
||||
parsedToken.groups === undefined ||
|
||||
parsedToken.groups.algo === undefined
|
||||
) {
|
||||
// Note: Chromium blocks the request at this point, but Firefox
|
||||
// gives a warning that an invalid integrity was given. The
|
||||
// correct behavior is to ignore these, and subsequently not
|
||||
|
@ -66551,11 +66684,11 @@ function parseMetadata (metadata) {
|
|||
}
|
||||
|
||||
// 4. Let algorithm be the hash-algo component of token.
|
||||
const algorithm = parsedToken.groups.algo
|
||||
const algorithm = parsedToken.groups.algo.toLowerCase()
|
||||
|
||||
// 5. If algorithm is a hash function recognized by the user
|
||||
// agent, add the parsed token to result.
|
||||
if (supportedHashes.includes(algorithm.toLowerCase())) {
|
||||
if (supportedHashes.includes(algorithm)) {
|
||||
result.push(parsedToken.groups)
|
||||
}
|
||||
}
|
||||
|
@ -66568,6 +66701,82 @@ function parseMetadata (metadata) {
|
|||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ algo: 'sha256' | 'sha384' | 'sha512' }[]} metadataList
|
||||
*/
|
||||
function getStrongestMetadata (metadataList) {
|
||||
// Let algorithm be the algo component of the first item in metadataList.
|
||||
// Can be sha256
|
||||
let algorithm = metadataList[0].algo
|
||||
// If the algorithm is sha512, then it is the strongest
|
||||
// and we can return immediately
|
||||
if (algorithm[3] === '5') {
|
||||
return algorithm
|
||||
}
|
||||
|
||||
for (let i = 1; i < metadataList.length; ++i) {
|
||||
const metadata = metadataList[i]
|
||||
// If the algorithm is sha512, then it is the strongest
|
||||
// and we can break the loop immediately
|
||||
if (metadata.algo[3] === '5') {
|
||||
algorithm = 'sha512'
|
||||
break
|
||||
// If the algorithm is sha384, then a potential sha256 or sha384 is ignored
|
||||
} else if (algorithm[3] === '3') {
|
||||
continue
|
||||
// algorithm is sha256, check if algorithm is sha384 and if so, set it as
|
||||
// the strongest
|
||||
} else if (metadata.algo[3] === '3') {
|
||||
algorithm = 'sha384'
|
||||
}
|
||||
}
|
||||
return algorithm
|
||||
}
|
||||
|
||||
function filterMetadataListByAlgorithm (metadataList, algorithm) {
|
||||
if (metadataList.length === 1) {
|
||||
return metadataList
|
||||
}
|
||||
|
||||
let pos = 0
|
||||
for (let i = 0; i < metadataList.length; ++i) {
|
||||
if (metadataList[i].algo === algorithm) {
|
||||
metadataList[pos++] = metadataList[i]
|
||||
}
|
||||
}
|
||||
|
||||
metadataList.length = pos
|
||||
|
||||
return metadataList
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two base64 strings, allowing for base64url
|
||||
* in the second string.
|
||||
*
|
||||
* @param {string} actualValue always base64
|
||||
* @param {string} expectedValue base64 or base64url
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function compareBase64Mixed (actualValue, expectedValue) {
|
||||
if (actualValue.length !== expectedValue.length) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < actualValue.length; ++i) {
|
||||
if (actualValue[i] !== expectedValue[i]) {
|
||||
if (
|
||||
(actualValue[i] === '+' && expectedValue[i] === '-') ||
|
||||
(actualValue[i] === '/' && expectedValue[i] === '_')
|
||||
) {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request
|
||||
function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) {
|
||||
// TODO
|
||||
|
@ -66983,7 +67192,8 @@ module.exports = {
|
|||
urlHasHttpsScheme,
|
||||
urlIsHttpHttpsScheme,
|
||||
readAllBytes,
|
||||
normalizeMethodRecord
|
||||
normalizeMethodRecord,
|
||||
parseMetadata
|
||||
}
|
||||
|
||||
|
||||
|
@ -69070,12 +69280,17 @@ function parseLocation (statusCode, headers) {
|
|||
|
||||
// https://tools.ietf.org/html/rfc7231#section-6.4.4
|
||||
function shouldRemoveHeader (header, removeContent, unknownOrigin) {
|
||||
return (
|
||||
(header.length === 4 && header.toString().toLowerCase() === 'host') ||
|
||||
(removeContent && header.toString().toLowerCase().indexOf('content-') === 0) ||
|
||||
(unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') ||
|
||||
(unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie')
|
||||
)
|
||||
if (header.length === 4) {
|
||||
return util.headerNameToString(header) === 'host'
|
||||
}
|
||||
if (removeContent && util.headerNameToString(header).startsWith('content-')) {
|
||||
return true
|
||||
}
|
||||
if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) {
|
||||
const name = util.headerNameToString(header)
|
||||
return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization'
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc7231#section-6.4
|
||||
|
@ -80960,7 +81175,11 @@ const getCacheDirectoryPath = (packageManagerInfo) => __awaiter(void 0, void 0,
|
|||
exports.getCacheDirectoryPath = getCacheDirectoryPath;
|
||||
function isGhes() {
|
||||
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
|
||||
const isGitHubHost = hostname === 'GITHUB.COM';
|
||||
const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
|
||||
const isLocalHost = hostname.endsWith('.LOCALHOST');
|
||||
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
|
||||
}
|
||||
exports.isGhes = isGhes;
|
||||
function isCacheFeatureAvailable() {
|
||||
|
|
|
@ -64982,6 +64982,132 @@ function onConnectTimeout (socket) {
|
|||
module.exports = buildConnector
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 4462:
|
||||
/***/ ((module) => {
|
||||
|
||||
"use strict";
|
||||
|
||||
|
||||
/** @type {Record<string, string | undefined>} */
|
||||
const headerNameLowerCasedRecord = {}
|
||||
|
||||
// https://developer.mozilla.org/docs/Web/HTTP/Headers
|
||||
const wellknownHeaderNames = [
|
||||
'Accept',
|
||||
'Accept-Encoding',
|
||||
'Accept-Language',
|
||||
'Accept-Ranges',
|
||||
'Access-Control-Allow-Credentials',
|
||||
'Access-Control-Allow-Headers',
|
||||
'Access-Control-Allow-Methods',
|
||||
'Access-Control-Allow-Origin',
|
||||
'Access-Control-Expose-Headers',
|
||||
'Access-Control-Max-Age',
|
||||
'Access-Control-Request-Headers',
|
||||
'Access-Control-Request-Method',
|
||||
'Age',
|
||||
'Allow',
|
||||
'Alt-Svc',
|
||||
'Alt-Used',
|
||||
'Authorization',
|
||||
'Cache-Control',
|
||||
'Clear-Site-Data',
|
||||
'Connection',
|
||||
'Content-Disposition',
|
||||
'Content-Encoding',
|
||||
'Content-Language',
|
||||
'Content-Length',
|
||||
'Content-Location',
|
||||
'Content-Range',
|
||||
'Content-Security-Policy',
|
||||
'Content-Security-Policy-Report-Only',
|
||||
'Content-Type',
|
||||
'Cookie',
|
||||
'Cross-Origin-Embedder-Policy',
|
||||
'Cross-Origin-Opener-Policy',
|
||||
'Cross-Origin-Resource-Policy',
|
||||
'Date',
|
||||
'Device-Memory',
|
||||
'Downlink',
|
||||
'ECT',
|
||||
'ETag',
|
||||
'Expect',
|
||||
'Expect-CT',
|
||||
'Expires',
|
||||
'Forwarded',
|
||||
'From',
|
||||
'Host',
|
||||
'If-Match',
|
||||
'If-Modified-Since',
|
||||
'If-None-Match',
|
||||
'If-Range',
|
||||
'If-Unmodified-Since',
|
||||
'Keep-Alive',
|
||||
'Last-Modified',
|
||||
'Link',
|
||||
'Location',
|
||||
'Max-Forwards',
|
||||
'Origin',
|
||||
'Permissions-Policy',
|
||||
'Pragma',
|
||||
'Proxy-Authenticate',
|
||||
'Proxy-Authorization',
|
||||
'RTT',
|
||||
'Range',
|
||||
'Referer',
|
||||
'Referrer-Policy',
|
||||
'Refresh',
|
||||
'Retry-After',
|
||||
'Sec-WebSocket-Accept',
|
||||
'Sec-WebSocket-Extensions',
|
||||
'Sec-WebSocket-Key',
|
||||
'Sec-WebSocket-Protocol',
|
||||
'Sec-WebSocket-Version',
|
||||
'Server',
|
||||
'Server-Timing',
|
||||
'Service-Worker-Allowed',
|
||||
'Service-Worker-Navigation-Preload',
|
||||
'Set-Cookie',
|
||||
'SourceMap',
|
||||
'Strict-Transport-Security',
|
||||
'Supports-Loading-Mode',
|
||||
'TE',
|
||||
'Timing-Allow-Origin',
|
||||
'Trailer',
|
||||
'Transfer-Encoding',
|
||||
'Upgrade',
|
||||
'Upgrade-Insecure-Requests',
|
||||
'User-Agent',
|
||||
'Vary',
|
||||
'Via',
|
||||
'WWW-Authenticate',
|
||||
'X-Content-Type-Options',
|
||||
'X-DNS-Prefetch-Control',
|
||||
'X-Frame-Options',
|
||||
'X-Permitted-Cross-Domain-Policies',
|
||||
'X-Powered-By',
|
||||
'X-Requested-With',
|
||||
'X-XSS-Protection'
|
||||
]
|
||||
|
||||
for (let i = 0; i < wellknownHeaderNames.length; ++i) {
|
||||
const key = wellknownHeaderNames[i]
|
||||
const lowerCasedKey = key.toLowerCase()
|
||||
headerNameLowerCasedRecord[key] = headerNameLowerCasedRecord[lowerCasedKey] =
|
||||
lowerCasedKey
|
||||
}
|
||||
|
||||
// Note: object prototypes should not be able to be referenced. e.g. `Object#hasOwnProperty`.
|
||||
Object.setPrototypeOf(headerNameLowerCasedRecord, null)
|
||||
|
||||
module.exports = {
|
||||
wellknownHeaderNames,
|
||||
headerNameLowerCasedRecord
|
||||
}
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ 8045:
|
||||
|
@ -65814,6 +65940,7 @@ const { InvalidArgumentError } = __nccwpck_require__(8045)
|
|||
const { Blob } = __nccwpck_require__(4300)
|
||||
const nodeUtil = __nccwpck_require__(3837)
|
||||
const { stringify } = __nccwpck_require__(3477)
|
||||
const { headerNameLowerCasedRecord } = __nccwpck_require__(4462)
|
||||
|
||||
const [nodeMajor, nodeMinor] = process.versions.node.split('.').map(v => Number(v))
|
||||
|
||||
|
@ -66023,6 +66150,15 @@ function parseKeepAliveTimeout (val) {
|
|||
return m ? parseInt(m[1], 10) * 1000 : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a header name and returns its lowercase value.
|
||||
* @param {string | Buffer} value Header name
|
||||
* @returns {string}
|
||||
*/
|
||||
function headerNameToString (value) {
|
||||
return headerNameLowerCasedRecord[value] || value.toLowerCase()
|
||||
}
|
||||
|
||||
function parseHeaders (headers, obj = {}) {
|
||||
// For H2 support
|
||||
if (!Array.isArray(headers)) return headers
|
||||
|
@ -66294,6 +66430,7 @@ module.exports = {
|
|||
isIterable,
|
||||
isAsyncIterable,
|
||||
isDestroyed,
|
||||
headerNameToString,
|
||||
parseRawHeaders,
|
||||
parseHeaders,
|
||||
parseKeepAliveTimeout,
|
||||
|
@ -72941,14 +73078,18 @@ const { isBlobLike, toUSVString, ReadableStreamFrom } = __nccwpck_require__(3983
|
|||
const assert = __nccwpck_require__(9491)
|
||||
const { isUint8Array } = __nccwpck_require__(9830)
|
||||
|
||||
let supportedHashes = []
|
||||
|
||||
// https://nodejs.org/api/crypto.html#determining-if-crypto-support-is-unavailable
|
||||
/** @type {import('crypto')|undefined} */
|
||||
let crypto
|
||||
|
||||
try {
|
||||
crypto = __nccwpck_require__(6113)
|
||||
const possibleRelevantHashes = ['sha256', 'sha384', 'sha512']
|
||||
supportedHashes = crypto.getHashes().filter((hash) => possibleRelevantHashes.includes(hash))
|
||||
/* c8 ignore next 3 */
|
||||
} catch {
|
||||
|
||||
}
|
||||
|
||||
function responseURL (response) {
|
||||
|
@ -73476,66 +73617,56 @@ function bytesMatch (bytes, metadataList) {
|
|||
return true
|
||||
}
|
||||
|
||||
// 3. If parsedMetadata is the empty set, return true.
|
||||
// 3. If response is not eligible for integrity validation, return false.
|
||||
// TODO
|
||||
|
||||
// 4. If parsedMetadata is the empty set, return true.
|
||||
if (parsedMetadata.length === 0) {
|
||||
return true
|
||||
}
|
||||
|
||||
// 4. Let metadata be the result of getting the strongest
|
||||
// 5. Let metadata be the result of getting the strongest
|
||||
// metadata from parsedMetadata.
|
||||
const list = parsedMetadata.sort((c, d) => d.algo.localeCompare(c.algo))
|
||||
// get the strongest algorithm
|
||||
const strongest = list[0].algo
|
||||
// get all entries that use the strongest algorithm; ignore weaker
|
||||
const metadata = list.filter((item) => item.algo === strongest)
|
||||
const strongest = getStrongestMetadata(parsedMetadata)
|
||||
const metadata = filterMetadataListByAlgorithm(parsedMetadata, strongest)
|
||||
|
||||
// 5. For each item in metadata:
|
||||
// 6. For each item in metadata:
|
||||
for (const item of metadata) {
|
||||
// 1. Let algorithm be the alg component of item.
|
||||
const algorithm = item.algo
|
||||
|
||||
// 2. Let expectedValue be the val component of item.
|
||||
let expectedValue = item.hash
|
||||
const expectedValue = item.hash
|
||||
|
||||
// See https://github.com/web-platform-tests/wpt/commit/e4c5cc7a5e48093220528dfdd1c4012dc3837a0e
|
||||
// "be liberal with padding". This is annoying, and it's not even in the spec.
|
||||
|
||||
if (expectedValue.endsWith('==')) {
|
||||
expectedValue = expectedValue.slice(0, -2)
|
||||
}
|
||||
|
||||
// 3. Let actualValue be the result of applying algorithm to bytes.
|
||||
let actualValue = crypto.createHash(algorithm).update(bytes).digest('base64')
|
||||
|
||||
if (actualValue.endsWith('==')) {
|
||||
actualValue = actualValue.slice(0, -2)
|
||||
if (actualValue[actualValue.length - 1] === '=') {
|
||||
if (actualValue[actualValue.length - 2] === '=') {
|
||||
actualValue = actualValue.slice(0, -2)
|
||||
} else {
|
||||
actualValue = actualValue.slice(0, -1)
|
||||
}
|
||||
}
|
||||
|
||||
// 4. If actualValue is a case-sensitive match for expectedValue,
|
||||
// return true.
|
||||
if (actualValue === expectedValue) {
|
||||
return true
|
||||
}
|
||||
|
||||
let actualBase64URL = crypto.createHash(algorithm).update(bytes).digest('base64url')
|
||||
|
||||
if (actualBase64URL.endsWith('==')) {
|
||||
actualBase64URL = actualBase64URL.slice(0, -2)
|
||||
}
|
||||
|
||||
if (actualBase64URL === expectedValue) {
|
||||
if (compareBase64Mixed(actualValue, expectedValue)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Return false.
|
||||
// 7. Return false.
|
||||
return false
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webappsec-subresource-integrity/#grammardef-hash-with-options
|
||||
// https://www.w3.org/TR/CSP2/#source-list-syntax
|
||||
// https://www.rfc-editor.org/rfc/rfc5234#appendix-B.1
|
||||
const parseHashWithOptions = /((?<algo>sha256|sha384|sha512)-(?<hash>[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e]?)?/i
|
||||
const parseHashWithOptions = /(?<algo>sha256|sha384|sha512)-((?<hash>[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i
|
||||
|
||||
/**
|
||||
* @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata
|
||||
|
@ -73549,8 +73680,6 @@ function parseMetadata (metadata) {
|
|||
// 2. Let empty be equal to true.
|
||||
let empty = true
|
||||
|
||||
const supportedHashes = crypto.getHashes()
|
||||
|
||||
// 3. For each token returned by splitting metadata on spaces:
|
||||
for (const token of metadata.split(' ')) {
|
||||
// 1. Set empty to false.
|
||||
|
@ -73560,7 +73689,11 @@ function parseMetadata (metadata) {
|
|||
const parsedToken = parseHashWithOptions.exec(token)
|
||||
|
||||
// 3. If token does not parse, continue to the next token.
|
||||
if (parsedToken === null || parsedToken.groups === undefined) {
|
||||
if (
|
||||
parsedToken === null ||
|
||||
parsedToken.groups === undefined ||
|
||||
parsedToken.groups.algo === undefined
|
||||
) {
|
||||
// Note: Chromium blocks the request at this point, but Firefox
|
||||
// gives a warning that an invalid integrity was given. The
|
||||
// correct behavior is to ignore these, and subsequently not
|
||||
|
@ -73569,11 +73702,11 @@ function parseMetadata (metadata) {
|
|||
}
|
||||
|
||||
// 4. Let algorithm be the hash-algo component of token.
|
||||
const algorithm = parsedToken.groups.algo
|
||||
const algorithm = parsedToken.groups.algo.toLowerCase()
|
||||
|
||||
// 5. If algorithm is a hash function recognized by the user
|
||||
// agent, add the parsed token to result.
|
||||
if (supportedHashes.includes(algorithm.toLowerCase())) {
|
||||
if (supportedHashes.includes(algorithm)) {
|
||||
result.push(parsedToken.groups)
|
||||
}
|
||||
}
|
||||
|
@ -73586,6 +73719,82 @@ function parseMetadata (metadata) {
|
|||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {{ algo: 'sha256' | 'sha384' | 'sha512' }[]} metadataList
|
||||
*/
|
||||
function getStrongestMetadata (metadataList) {
|
||||
// Let algorithm be the algo component of the first item in metadataList.
|
||||
// Can be sha256
|
||||
let algorithm = metadataList[0].algo
|
||||
// If the algorithm is sha512, then it is the strongest
|
||||
// and we can return immediately
|
||||
if (algorithm[3] === '5') {
|
||||
return algorithm
|
||||
}
|
||||
|
||||
for (let i = 1; i < metadataList.length; ++i) {
|
||||
const metadata = metadataList[i]
|
||||
// If the algorithm is sha512, then it is the strongest
|
||||
// and we can break the loop immediately
|
||||
if (metadata.algo[3] === '5') {
|
||||
algorithm = 'sha512'
|
||||
break
|
||||
// If the algorithm is sha384, then a potential sha256 or sha384 is ignored
|
||||
} else if (algorithm[3] === '3') {
|
||||
continue
|
||||
// algorithm is sha256, check if algorithm is sha384 and if so, set it as
|
||||
// the strongest
|
||||
} else if (metadata.algo[3] === '3') {
|
||||
algorithm = 'sha384'
|
||||
}
|
||||
}
|
||||
return algorithm
|
||||
}
|
||||
|
||||
function filterMetadataListByAlgorithm (metadataList, algorithm) {
|
||||
if (metadataList.length === 1) {
|
||||
return metadataList
|
||||
}
|
||||
|
||||
let pos = 0
|
||||
for (let i = 0; i < metadataList.length; ++i) {
|
||||
if (metadataList[i].algo === algorithm) {
|
||||
metadataList[pos++] = metadataList[i]
|
||||
}
|
||||
}
|
||||
|
||||
metadataList.length = pos
|
||||
|
||||
return metadataList
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two base64 strings, allowing for base64url
|
||||
* in the second string.
|
||||
*
|
||||
* @param {string} actualValue always base64
|
||||
* @param {string} expectedValue base64 or base64url
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function compareBase64Mixed (actualValue, expectedValue) {
|
||||
if (actualValue.length !== expectedValue.length) {
|
||||
return false
|
||||
}
|
||||
for (let i = 0; i < actualValue.length; ++i) {
|
||||
if (actualValue[i] !== expectedValue[i]) {
|
||||
if (
|
||||
(actualValue[i] === '+' && expectedValue[i] === '-') ||
|
||||
(actualValue[i] === '/' && expectedValue[i] === '_')
|
||||
) {
|
||||
continue
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// https://w3c.github.io/webappsec-upgrade-insecure-requests/#upgrade-request
|
||||
function tryUpgradeRequestToAPotentiallyTrustworthyURL (request) {
|
||||
// TODO
|
||||
|
@ -74001,7 +74210,8 @@ module.exports = {
|
|||
urlHasHttpsScheme,
|
||||
urlIsHttpHttpsScheme,
|
||||
readAllBytes,
|
||||
normalizeMethodRecord
|
||||
normalizeMethodRecord,
|
||||
parseMetadata
|
||||
}
|
||||
|
||||
|
||||
|
@ -76088,12 +76298,17 @@ function parseLocation (statusCode, headers) {
|
|||
|
||||
// https://tools.ietf.org/html/rfc7231#section-6.4.4
|
||||
function shouldRemoveHeader (header, removeContent, unknownOrigin) {
|
||||
return (
|
||||
(header.length === 4 && header.toString().toLowerCase() === 'host') ||
|
||||
(removeContent && header.toString().toLowerCase().indexOf('content-') === 0) ||
|
||||
(unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') ||
|
||||
(unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie')
|
||||
)
|
||||
if (header.length === 4) {
|
||||
return util.headerNameToString(header) === 'host'
|
||||
}
|
||||
if (removeContent && util.headerNameToString(header).startsWith('content-')) {
|
||||
return true
|
||||
}
|
||||
if (unknownOrigin && (header.length === 13 || header.length === 6 || header.length === 19)) {
|
||||
const name = util.headerNameToString(header)
|
||||
return name === 'authorization' || name === 'cookie' || name === 'proxy-authorization'
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// https://tools.ietf.org/html/rfc7231#section-6.4
|
||||
|
@ -87830,6 +88045,7 @@ const cache_utils_1 = __nccwpck_require__(1678);
|
|||
const restoreCache = (versionSpec, packageManager, cacheDependencyPath) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const packageManagerInfo = yield (0, cache_utils_1.getPackageManagerInfo)(packageManager);
|
||||
const platform = process.env.RUNNER_OS;
|
||||
const arch = process.arch;
|
||||
const cachePaths = yield (0, cache_utils_1.getCacheDirectoryPath)(packageManagerInfo);
|
||||
const dependencyFilePath = cacheDependencyPath
|
||||
? cacheDependencyPath
|
||||
|
@ -87839,7 +88055,7 @@ const restoreCache = (versionSpec, packageManager, cacheDependencyPath) => __awa
|
|||
throw new Error('Some specified paths were not resolved, unable to cache dependencies.');
|
||||
}
|
||||
const linuxVersion = process.env.RUNNER_OS === 'Linux' ? `${process.env.ImageOS}-` : '';
|
||||
const primaryKey = `setup-go-${platform}-${linuxVersion}go-${versionSpec}-${fileHash}`;
|
||||
const primaryKey = `setup-go-${platform}-${arch}-${linuxVersion}go-${versionSpec}-${fileHash}`;
|
||||
core.debug(`primary key is ${primaryKey}`);
|
||||
core.saveState(constants_1.State.CachePrimaryKey, primaryKey);
|
||||
const cacheKey = yield cache.restoreCache(cachePaths, primaryKey);
|
||||
|
@ -87949,7 +88165,11 @@ const getCacheDirectoryPath = (packageManagerInfo) => __awaiter(void 0, void 0,
|
|||
exports.getCacheDirectoryPath = getCacheDirectoryPath;
|
||||
function isGhes() {
|
||||
const ghUrl = new URL(process.env['GITHUB_SERVER_URL'] || 'https://github.com');
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
|
||||
const isGitHubHost = hostname === 'GITHUB.COM';
|
||||
const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
|
||||
const isLocalHost = hostname.endsWith('.LOCALHOST');
|
||||
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
|
||||
}
|
||||
exports.isGhes = isGhes;
|
||||
function isCacheFeatureAvailable() {
|
||||
|
@ -88039,6 +88259,10 @@ const sys = __importStar(__nccwpck_require__(5632));
|
|||
const fs_1 = __importDefault(__nccwpck_require__(7147));
|
||||
const os_1 = __importDefault(__nccwpck_require__(2037));
|
||||
const utils_1 = __nccwpck_require__(1314);
|
||||
const MANIFEST_REPO_OWNER = 'actions';
|
||||
const MANIFEST_REPO_NAME = 'go-versions';
|
||||
const MANIFEST_REPO_BRANCH = 'main';
|
||||
const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
|
||||
function getGo(versionSpec_1, checkLatest_1, auth_1) {
|
||||
return __awaiter(this, arguments, void 0, function* (versionSpec, checkLatest, auth, arch = os_1.default.arch()) {
|
||||
var _a;
|
||||
|
@ -88213,10 +88437,34 @@ function extractGoArchive(archivePath) {
|
|||
exports.extractGoArchive = extractGoArchive;
|
||||
function getManifest(auth) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return tc.getManifestFromRepo('actions', 'go-versions', auth, 'main');
|
||||
try {
|
||||
return yield getManifestFromRepo(auth);
|
||||
}
|
||||
catch (err) {
|
||||
core.debug('Fetching the manifest via the API failed.');
|
||||
if (err instanceof Error) {
|
||||
core.debug(err.message);
|
||||
}
|
||||
}
|
||||
return yield getManifestFromURL();
|
||||
});
|
||||
}
|
||||
exports.getManifest = getManifest;
|
||||
function getManifestFromRepo(auth) {
|
||||
core.debug(`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`);
|
||||
return tc.getManifestFromRepo(MANIFEST_REPO_OWNER, MANIFEST_REPO_NAME, auth, MANIFEST_REPO_BRANCH);
|
||||
}
|
||||
function getManifestFromURL() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
core.debug('Falling back to fetching the manifest using raw URL.');
|
||||
const http = new httpm.HttpClient('tool-cache');
|
||||
const response = yield http.getJson(MANIFEST_URL);
|
||||
if (!response.result) {
|
||||
throw new Error(`Unable to get manifest from ${MANIFEST_URL}`);
|
||||
}
|
||||
return response.result;
|
||||
});
|
||||
}
|
||||
function getInfoFromManifest(versionSpec_1, stable_1, auth_1) {
|
||||
return __awaiter(this, arguments, void 0, function* (versionSpec, stable, auth, arch = os_1.default.arch(), manifest) {
|
||||
let info = null;
|
||||
|
|
|
@ -2214,12 +2214,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
@ -2504,10 +2504,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
|
@ -3175,9 +3176,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
|
@ -4559,12 +4560,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"braces": "^3.0.2",
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -5739,9 +5740,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "5.28.3",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz",
|
||||
"integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==",
|
||||
"version": "5.28.4",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz",
|
||||
"integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==",
|
||||
"dependencies": {
|
||||
"@fastify/busboy": "^2.0.0"
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@ export const restoreCache = async (
|
|||
) => {
|
||||
const packageManagerInfo = await getPackageManagerInfo(packageManager);
|
||||
const platform = process.env.RUNNER_OS;
|
||||
const arch = process.arch;
|
||||
|
||||
const cachePaths = await getCacheDirectoryPath(packageManagerInfo);
|
||||
|
||||
|
@ -31,7 +32,7 @@ export const restoreCache = async (
|
|||
|
||||
const linuxVersion =
|
||||
process.env.RUNNER_OS === 'Linux' ? `${process.env.ImageOS}-` : '';
|
||||
const primaryKey = `setup-go-${platform}-${linuxVersion}go-${versionSpec}-${fileHash}`;
|
||||
const primaryKey = `setup-go-${platform}-${arch}-${linuxVersion}go-${versionSpec}-${fileHash}`;
|
||||
core.debug(`primary key is ${primaryKey}`);
|
||||
|
||||
core.saveState(State.CachePrimaryKey, primaryKey);
|
||||
|
|
|
@ -63,7 +63,13 @@ export function isGhes(): boolean {
|
|||
const ghUrl = new URL(
|
||||
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
|
||||
);
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM';
|
||||
|
||||
const hostname = ghUrl.hostname.trimEnd().toUpperCase();
|
||||
const isGitHubHost = hostname === 'GITHUB.COM';
|
||||
const isGitHubEnterpriseCloudHost = hostname.endsWith('.GHE.COM');
|
||||
const isLocalHost = hostname.endsWith('.LOCALHOST');
|
||||
|
||||
return !isGitHubHost && !isGitHubEnterpriseCloudHost && !isLocalHost;
|
||||
}
|
||||
|
||||
export function isCacheFeatureAvailable(): boolean {
|
||||
|
|
|
@ -8,6 +8,11 @@ import fs from 'fs';
|
|||
import os from 'os';
|
||||
import {StableReleaseAlias} from './utils';
|
||||
|
||||
const MANIFEST_REPO_OWNER = 'actions';
|
||||
const MANIFEST_REPO_NAME = 'go-versions';
|
||||
const MANIFEST_REPO_BRANCH = 'main';
|
||||
const MANIFEST_URL = `https://raw.githubusercontent.com/${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}/${MANIFEST_REPO_BRANCH}/versions-manifest.json`;
|
||||
|
||||
type InstallationType = 'dist' | 'manifest';
|
||||
|
||||
export interface IGoVersionFile {
|
||||
|
@ -274,8 +279,43 @@ export async function extractGoArchive(archivePath: string): Promise<string> {
|
|||
return extPath;
|
||||
}
|
||||
|
||||
export async function getManifest(auth: string | undefined) {
|
||||
return tc.getManifestFromRepo('actions', 'go-versions', auth, 'main');
|
||||
export async function getManifest(
|
||||
auth: string | undefined
|
||||
): Promise<tc.IToolRelease[]> {
|
||||
try {
|
||||
return await getManifestFromRepo(auth);
|
||||
} catch (err) {
|
||||
core.debug('Fetching the manifest via the API failed.');
|
||||
if (err instanceof Error) {
|
||||
core.debug(err.message);
|
||||
}
|
||||
}
|
||||
return await getManifestFromURL();
|
||||
}
|
||||
|
||||
function getManifestFromRepo(
|
||||
auth: string | undefined
|
||||
): Promise<tc.IToolRelease[]> {
|
||||
core.debug(
|
||||
`Getting manifest from ${MANIFEST_REPO_OWNER}/${MANIFEST_REPO_NAME}@${MANIFEST_REPO_BRANCH}`
|
||||
);
|
||||
return tc.getManifestFromRepo(
|
||||
MANIFEST_REPO_OWNER,
|
||||
MANIFEST_REPO_NAME,
|
||||
auth,
|
||||
MANIFEST_REPO_BRANCH
|
||||
);
|
||||
}
|
||||
|
||||
async function getManifestFromURL(): Promise<tc.IToolRelease[]> {
|
||||
core.debug('Falling back to fetching the manifest using raw URL.');
|
||||
|
||||
const http: httpm.HttpClient = new httpm.HttpClient('tool-cache');
|
||||
const response = await http.getJson<tc.IToolRelease[]>(MANIFEST_URL);
|
||||
if (!response.result) {
|
||||
throw new Error(`Unable to get manifest from ${MANIFEST_URL}`);
|
||||
}
|
||||
return response.result;
|
||||
}
|
||||
|
||||
export async function getInfoFromManifest(
|
||||
|
|
Loading…
Reference in New Issue