From 1cf165678a8612d86f317db018d2c0cdb2c06917 Mon Sep 17 00:00:00 2001 From: Ludy87 Date: Tue, 19 Aug 2025 14:18:09 +0200 Subject: [PATCH] push --- README.md | 14 +- action.yml | 4 + dist/index.js | 424 +++++++++++++++++++++++++++++++++--------- package-lock.json | 1 + src/.stylelintrc.json | 8 + src/main.ts | 10 +- 6 files changed, 367 insertions(+), 94 deletions(-) create mode 100644 src/.stylelintrc.json diff --git a/README.md b/README.md index b5e0f4c..eadaf87 100644 --- a/README.md +++ b/README.md @@ -154,14 +154,14 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob # Default: ${{ github.token }} token: '' - # Optional parameter to override the default behavior of file matching algorithm. + # Optional parameter to override the default behavior of file matching algorithm. # By default files that match at least one pattern defined by the filters will be included. # This parameter allows to override the "at least one pattern" behavior to make it so that - # all of the patterns have to match or otherwise the file is excluded. - # An example scenario where this is useful if you would like to match all - # .ts files in a sub-directory but not .md files. - # The filters below will match markdown files despite the exclusion syntax UNLESS - # you specify 'every' as the predicate-quantifier parameter. When you do that, + # all of the patterns have to match or otherwise the file is excluded. + # An example scenario where this is useful if you would like to match all + # .ts files in a sub-directory but not .md files. + # The filters below will match markdown files despite the exclusion syntax UNLESS + # you specify 'every' as the predicate-quantifier parameter. When you do that, # it will only match the .ts files in the subdirectory as expected. # # backend: @@ -178,6 +178,8 @@ For more information, see [CHANGELOG](https://github.com/dorny/paths-filter/blob - `'false'` - if **none** of changed files matches any of filter rules - For each filter, it sets an output variable with the name `${FILTER_NAME}_count` to the count of matching files. - If enabled, for each filter it sets an output variable with the name `${FILTER_NAME}_files`. It will contain a list of all files matching the filter. +- `all_changed` - `'true'` if every filter contains at least one changed file or if no filters match any files (vacuous truth), otherwise `'false'`. +- `any_changed` - `'true'` if **any** filter contains at least one changed file, otherwise `'false'`. - `changes` - JSON array with names of all filters matching any of the changed files. ## Examples diff --git a/action.yml b/action.yml index e7d24f5..172455a 100644 --- a/action.yml +++ b/action.yml @@ -45,6 +45,10 @@ inputs: required: false default: '100' outputs: + all_changed: + description: Boolean value indicating if all of the filters contained at least one changed file. If no filters matched, this value is 'true'. + any_changed: + description: Boolean value indicating if any of the filters contained at least one changed file changes: description: JSON array with names of all filters matching any of changed files runs: diff --git a/dist/index.js b/dist/index.js index cc7d7d4..93d1e2e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -745,11 +745,14 @@ async function getChangedFilesFromApi(token, pullRequest) { function exportResults(results, format) { core.info('Results:'); const changes = []; + let anyChanged = false; + let hasUnchangedFilter = false; for (const [key, files] of Object.entries(results)) { const value = files.length > 0; core.startGroup(`Filter ${key} = ${value}`); if (files.length > 0) { changes.push(key); + anyChanged = true; core.info('Matching files:'); for (const file of files) { core.info(`${file.filename} [${file.status}]`); @@ -757,6 +760,7 @@ function exportResults(results, format) { } else { core.info('Matching files: none'); + hasUnchangedFilter = true; } core.setOutput(key, value); core.setOutput(`${key}_count`, files.length); @@ -766,6 +770,9 @@ function exportResults(results, format) { } core.endGroup(); } + const allChanged = anyChanged ? !hasUnchangedFilter : true; + core.setOutput('all_changed', allChanged); + core.setOutput('any_changed', anyChanged); if (results['changes'] === undefined) { const changesJson = JSON.stringify(changes); core.info(`Changes output set to ${changesJson}`); @@ -1360,7 +1367,7 @@ class OidcClient { .catch(error => { throw new Error(`Failed to get ID Token. \n Error Code : ${error.statusCode}\n - Error Message: ${error.message}`); + Error Message: ${error.result.message}`); }); const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; if (!id_token) { @@ -4408,7 +4415,7 @@ module.exports = __toCommonJS(dist_src_exports); var import_universal_user_agent = __nccwpck_require__(5030); // pkg/dist-src/version.js -var VERSION = "9.0.4"; +var VERSION = "9.0.6"; // pkg/dist-src/defaults.js var userAgent = `octokit-endpoint.js/${VERSION} ${(0, import_universal_user_agent.getUserAgent)()}`; @@ -4513,9 +4520,9 @@ function addQueryParameters(url, parameters) { } // pkg/dist-src/util/extract-url-variable-names.js -var urlVariableRegex = /\{[^}]+\}/g; +var urlVariableRegex = /\{[^{}}]+\}/g; function removeNonChars(variableName) { - return variableName.replace(/^\W+|\W+$/g, "").split(/,/); + return variableName.replace(/(?:^\W+)|(?:(? { const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json"; return `application/vnd.github.${preview}-preview${format}`; @@ -4950,7 +4957,7 @@ __export(dist_src_exports, { module.exports = __toCommonJS(dist_src_exports); // pkg/dist-src/version.js -var VERSION = "9.1.5"; +var VERSION = "9.2.2"; // pkg/dist-src/normalize-paginated-list-response.js function normalizePaginatedListResponse(response) { @@ -4998,7 +5005,7 @@ function iterator(octokit, route, parameters) { const response = await requestMethod({ method, url, headers }); const normalizedResponse = normalizePaginatedListResponse(response); url = ((normalizedResponse.headers.link || "").match( - /<([^>]+)>;\s*rel="next"/ + /<([^<>]+)>;\s*rel="next"/ ) || [])[1]; return { value: normalizedResponse }; } catch (error) { @@ -5111,6 +5118,8 @@ var paginatingEndpoints = [ "GET /orgs/{org}/members/{username}/codespaces", "GET /orgs/{org}/migrations", "GET /orgs/{org}/migrations/{migration_id}/repositories", + "GET /orgs/{org}/organization-roles/{role_id}/teams", + "GET /orgs/{org}/organization-roles/{role_id}/users", "GET /orgs/{org}/outside_collaborators", "GET /orgs/{org}/packages", "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", @@ -7489,7 +7498,7 @@ var RequestError = class extends Error { if (options.request.headers.authorization) { requestCopy.headers = Object.assign({}, options.request.headers, { authorization: options.request.headers.authorization.replace( - / .*$/, + /(?]+)>; rel="deprecation"/); + const matches = headers.link && headers.link.match(/<([^<>]+)>; rel="deprecation"/); const deprecationLink = matches && matches.pop(); log.warn( `[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}` @@ -7701,11 +7711,17 @@ async function getResponseData(response) { function toErrorMessage(data) { if (typeof data === "string") return data; + let suffix; + if ("documentation_url" in data) { + suffix = ` - ${data.documentation_url}`; + } else { + suffix = ""; + } if ("message" in data) { if (Array.isArray(data.errors)) { - return `${data.message}: ${data.errors.map(JSON.stringify).join(", ")}`; + return `${data.message}: ${data.errors.map(JSON.stringify).join(", ")}${suffix}`; } - return data.message; + return `${data.message}${suffix}`; } return `Unknown error: ${JSON.stringify(data)}`; } @@ -19839,7 +19855,7 @@ module.exports = { const { parseSetCookie } = __nccwpck_require__(4408) -const { stringify, getHeadersList } = __nccwpck_require__(3121) +const { stringify } = __nccwpck_require__(3121) const { webidl } = __nccwpck_require__(1744) const { Headers } = __nccwpck_require__(554) @@ -19915,14 +19931,13 @@ function getSetCookies (headers) { webidl.brandCheck(headers, Headers, { strict: false }) - const cookies = getHeadersList(headers).cookies + const cookies = headers.getSetCookie() if (!cookies) { return [] } - // In older versions of undici, cookies is a list of name:value. - return cookies.map((pair) => parseSetCookie(Array.isArray(pair) ? pair[1] : pair)) + return cookies.map((pair) => parseSetCookie(pair)) } /** @@ -20350,14 +20365,15 @@ module.exports = { /***/ }), /***/ 3121: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { +/***/ ((module) => { "use strict"; -const assert = __nccwpck_require__(9491) -const { kHeadersList } = __nccwpck_require__(2785) - +/** + * @param {string} value + * @returns {boolean} + */ function isCTLExcludingHtab (value) { if (value.length === 0) { return false @@ -20618,31 +20634,13 @@ function stringify (cookie) { return out.join('; ') } -let kHeadersListNode - -function getHeadersList (headers) { - if (headers[kHeadersList]) { - return headers[kHeadersList] - } - - if (!kHeadersListNode) { - kHeadersListNode = Object.getOwnPropertySymbols(headers).find( - (symbol) => symbol.description === 'headers list' - ) - - assert(kHeadersListNode, 'Headers cannot be parsed') - } - - const headersList = headers[kHeadersListNode] - assert(headersList) - - return headersList -} - module.exports = { isCTLExcludingHtab, - stringify, - getHeadersList + validateCookieName, + validateCookiePath, + validateCookieValue, + toIMFDate, + stringify } @@ -20843,6 +20841,132 @@ function onConnectTimeout (socket) { module.exports = buildConnector +/***/ }), + +/***/ 4462: +/***/ ((module) => { + +"use strict"; + + +/** @type {Record} */ +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: @@ -21675,6 +21799,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)) @@ -21884,6 +22009,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 @@ -22155,6 +22289,7 @@ module.exports = { isIterable, isAsyncIterable, isDestroyed, + headerNameToString, parseRawHeaders, parseHeaders, parseKeepAliveTimeout, @@ -22434,6 +22569,14 @@ const { isUint8Array, isArrayBuffer } = __nccwpck_require__(9830) const { File: UndiciFile } = __nccwpck_require__(8511) const { parseMIMEType, serializeAMimeType } = __nccwpck_require__(685) +let random +try { + const crypto = __nccwpck_require__(6005) + random = (max) => crypto.randomInt(0, max) +} catch { + random = (max) => Math.floor(Math.random(max)) +} + let ReadableStream = globalThis.ReadableStream /** @type {globalThis['File']} */ @@ -22519,7 +22662,7 @@ function extractBody (object, keepalive = false) { // Set source to a copy of the bytes held by object. source = new Uint8Array(object.buffer.slice(object.byteOffset, object.byteOffset + object.byteLength)) } else if (util.isFormDataLike(object)) { - const boundary = `----formdata-undici-0${`${Math.floor(Math.random() * 1e11)}`.padStart(11, '0')}` + const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, '0')}` const prefix = `--${boundary}\r\nContent-Disposition: form-data` /*! formdata-polyfill. MIT License. Jimmy Wärting */ @@ -24501,6 +24644,7 @@ const { isValidHeaderName, isValidHeaderValue } = __nccwpck_require__(2538) +const util = __nccwpck_require__(3837) const { webidl } = __nccwpck_require__(1744) const assert = __nccwpck_require__(9491) @@ -25054,6 +25198,9 @@ Object.defineProperties(Headers.prototype, { [Symbol.toStringTag]: { value: 'Headers', configurable: true + }, + [util.inspect.custom]: { + enumerable: false } }) @@ -26291,6 +26438,9 @@ function httpRedirectFetch (fetchParams, response) { // https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name request.headersList.delete('authorization') + // https://fetch.spec.whatwg.org/#authentication-entries + request.headersList.delete('proxy-authorization', true) + // "Cookie" and "Host" are forbidden request-headers, which undici doesn't implement. request.headersList.delete('cookie') request.headersList.delete('host') @@ -28799,14 +28949,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) { @@ -29334,66 +29488,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 = /((?sha256|sha384|sha512)-(?[A-z0-9+/]{1}.*={0,2}))( +[\x21-\x7e]?)?/i +const parseHashWithOptions = /(?sha256|sha384|sha512)-((?[A-Za-z0-9+/]+|[A-Za-z0-9_-]+)={0,2}(?:\s|$)( +[!-~]*)?)?/i /** * @see https://w3c.github.io/webappsec-subresource-integrity/#parse-metadata @@ -29407,8 +29551,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. @@ -29418,7 +29560,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 @@ -29427,11 +29573,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) } } @@ -29444,6 +29590,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 @@ -29859,7 +30081,8 @@ module.exports = { urlHasHttpsScheme, urlIsHttpHttpsScheme, readAllBytes, - normalizeMethodRecord + normalizeMethodRecord, + parseMetadata } @@ -31946,12 +32169,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 @@ -34149,6 +34377,20 @@ class Pool extends PoolBase { ? { ...options.interceptors } : undefined this[kFactory] = factory + + this.on('connectionError', (origin, targets, error) => { + // If a connection error occurs, we remove the client from the pool, + // and emit a connectionError event. They will not be re-used. + // Fixes https://github.com/nodejs/undici/issues/3895 + for (const target of targets) { + // Do not use kRemoveClient here, as it will close the client, + // but the client cannot be closed in this state. + const idx = this[kClients].indexOf(target) + if (idx !== -1) { + this[kClients].splice(idx, 1) + } + } + }) } [kGetDispatcher] () { @@ -37269,6 +37511,14 @@ module.exports = require("net"); /***/ }), +/***/ 6005: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:crypto"); + +/***/ }), + /***/ 5673: /***/ ((module) => { diff --git a/package-lock.json b/package-lock.json index 1b6589b..f449f37 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1563,6 +1563,7 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.6.tgz", "integrity": "sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==", "dev": true, + "license": "MIT", "dependencies": { "undici-types": "~5.26.4" } diff --git a/src/.stylelintrc.json b/src/.stylelintrc.json new file mode 100644 index 0000000..23ea1f6 --- /dev/null +++ b/src/.stylelintrc.json @@ -0,0 +1,8 @@ +{ + "extends": [ + "stylelint-config-standard" + ], + "plugins": [ + "@stylistic/stylelint-plugin" + ] +} diff --git a/src/main.ts b/src/main.ts index 8320287..f620560 100644 --- a/src/main.ts +++ b/src/main.ts @@ -230,18 +230,22 @@ async function getChangedFilesFromApi(token: string, pullRequest: PullRequestEve function exportResults(results: FilterResults, format: ExportFormat): void { core.info('Results:') - const changes = [] + const changes: string[] = [] + let anyChanged = false + let hasUnchangedFilter = false for (const [key, files] of Object.entries(results)) { const value = files.length > 0 core.startGroup(`Filter ${key} = ${value}`) if (files.length > 0) { changes.push(key) + anyChanged = true core.info('Matching files:') for (const file of files) { core.info(`${file.filename} [${file.status}]`) } } else { core.info('Matching files: none') + hasUnchangedFilter = true } core.setOutput(key, value) @@ -253,6 +257,10 @@ function exportResults(results: FilterResults, format: ExportFormat): void { core.endGroup() } + const allChanged = anyChanged ? !hasUnchangedFilter : true + core.setOutput('all_changed', allChanged) + core.setOutput('any_changed', anyChanged) + if (results['changes'] === undefined) { const changesJson = JSON.stringify(changes) core.info(`Changes output set to ${changesJson}`)