From fdccf93e9893c774295db9653e2bde48ee08aba1 Mon Sep 17 00:00:00 2001 From: Shane <6071159+smashedr@users.noreply.github.com> Date: Wed, 26 Aug 2026 15:30:14 -0700 Subject: [PATCH] Fix Previous Release Notes Generation --- .github/example/draft.yaml | 2 +- .github/workflows/check-build.yaml | 4 +- .github/workflows/issue.yaml | 2 +- .github/workflows/labeler.yaml | 4 +- .github/workflows/lint.yaml | 4 +- .github/workflows/mirror.yaml | 2 +- .github/workflows/pull.yaml | 2 +- .github/workflows/test.yaml | 2 +- dist/index.js | 1146 ++++++++++++++++++++-------- package-lock.json | 424 +++++----- package.json | 8 +- src/index.js | 14 +- 12 files changed, 1109 insertions(+), 505 deletions(-) diff --git a/.github/example/draft.yaml b/.github/example/draft.yaml index 3c4a617..4ac0c79 100644 --- a/.github/example/draft.yaml +++ b/.github/example/draft.yaml @@ -33,7 +33,7 @@ jobs: - name: "Draft Release Action" id: draft - uses: cssnr/draft-release-action@notes + uses: cssnr/draft-release-action@master with: semver: patch prerelease: false diff --git a/.github/workflows/check-build.yaml b/.github/workflows/check-build.yaml index c190625..0eeb53f 100644 --- a/.github/workflows/check-build.yaml +++ b/.github/workflows/check-build.yaml @@ -43,12 +43,12 @@ jobs: run: env - name: "Checkout Pull" - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: ref: ${{ github.event.pull_request.head.sha }} - name: "Setup Node" - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 24 diff --git a/.github/workflows/issue.yaml b/.github/workflows/issue.yaml index 9b25afd..8184c70 100644 --- a/.github/workflows/issue.yaml +++ b/.github/workflows/issue.yaml @@ -17,7 +17,7 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: "AI Issue" uses: cssnr/ai-issue-action@v1 diff --git a/.github/workflows/labeler.yaml b/.github/workflows/labeler.yaml index 95030e5..c37a7bc 100644 --- a/.github/workflows/labeler.yaml +++ b/.github/workflows/labeler.yaml @@ -19,7 +19,7 @@ jobs: steps: - name: "Checkout Configs" - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: repository: cssnr/configs ref: master @@ -46,7 +46,7 @@ jobs: file: .configs/labels/labels.yaml - name: "Labeler" - uses: actions/labeler@v6 + uses: actions/labeler@v7 with: sync-labels: true configuration-path: .configs/labels/labeler.yaml diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 0a0c387..d6253fc 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -24,10 +24,10 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: "Setup Node" - uses: actions/setup-node@v6 + uses: actions/setup-node@v7 with: node-version: 24 diff --git a/.github/workflows/mirror.yaml b/.github/workflows/mirror.yaml index b7bd36f..c8a428d 100644 --- a/.github/workflows/mirror.yaml +++ b/.github/workflows/mirror.yaml @@ -18,7 +18,7 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: fetch-depth: 0 diff --git a/.github/workflows/pull.yaml b/.github/workflows/pull.yaml index e2fdf3c..790d6f1 100644 --- a/.github/workflows/pull.yaml +++ b/.github/workflows/pull.yaml @@ -25,7 +25,7 @@ jobs: run: echo "$GITHUB_CTX" - name: "Checkout Pull" - uses: actions/checkout@v6 + uses: actions/checkout@v7 with: ref: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f7a0507..51bdd9b 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -29,7 +29,7 @@ jobs: steps: - name: "Checkout" - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: "Debug event.json" if: ${{ !github.event.act }} diff --git a/dist/index.js b/dist/index.js index 609e2cd..570c403 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2587,7 +2587,13 @@ function requireRequest$1 () { } else if (typeof val[i] === 'object') { throw new InvalidArgumentError(`invalid ${key} header`) } else { - arr.push(`${val[i]}`); + // Coerce primitives (and reject unsafe coercions such as functions + // with a crafted toString/Symbol.toPrimitive). + const str = `${val[i]}`; + if (!isValidHeaderValue(str)) { + throw new InvalidArgumentError(`invalid ${key} header`) + } + arr.push(str); } } val = arr; @@ -2598,7 +2604,12 @@ function requireRequest$1 () { } else if (val === null) { val = ''; } else { + // Coerce primitives (and reject unsafe coercions such as functions + // with a crafted toString/Symbol.toPrimitive). val = `${val}`; + if (!isValidHeaderValue(val)) { + throw new InvalidArgumentError(`invalid ${key} header`) + } } if (headerName === 'host') { @@ -2749,6 +2760,7 @@ function requireDispatcherBase () { get webSocketOptions () { return { + maxFragments: this[kWebSocketOptions].maxFragments ?? 131072, maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 } } @@ -8653,6 +8665,7 @@ function requireClientH1 () { RequestContentLengthMismatchError, ResponseContentLengthMismatchError, RequestAbortedError, + InvalidArgumentError, HeadersTimeoutError, HeadersOverflowError, SocketError, @@ -8700,6 +8713,9 @@ function requireClientH1 () { const FastBuffer = Buffer[Symbol.species]; const addListener = util.addListener; const removeAllListeners = util.removeAllListeners; + const kIdleSocketValidation = Symbol('kIdleSocketValidation'); + const kIdleSocketValidationTimeout = Symbol('kIdleSocketValidationTimeout'); + const kSocketUsed = Symbol('kSocketUsed'); let extractBody; @@ -9014,6 +9030,11 @@ function requireClientH1 () { return -1 } + if (client[kRunning] === 0) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))); + return -1 + } + const request = client[kQueue][client[kRunningIdx]]; if (!request) { return -1 @@ -9117,6 +9138,11 @@ function requireClientH1 () { return -1 } + if (client[kRunning] === 0) { + util.destroy(socket, new SocketError('bad response', util.getSocketInfo(socket))); + return -1 + } + const request = client[kQueue][client[kRunningIdx]]; /* istanbul ignore next: difficult to make a test case for */ @@ -9290,6 +9316,7 @@ function requireClientH1 () { request.onComplete(headers); client[kQueue][client[kRunningIdx]++] = null; + socket[kSocketUsed] = true; if (socket[kWriting]) { assert(client[kRunning] === 0); @@ -9348,6 +9375,9 @@ function requireClientH1 () { socket[kWriting] = false; socket[kReset] = false; socket[kBlocking] = false; + socket[kIdleSocketValidation] = 0; + socket[kIdleSocketValidationTimeout] = null; + socket[kSocketUsed] = false; socket[kParser] = new Parser(client, socket, llhttpInstance); addListener(socket, 'error', function (err) { @@ -9394,6 +9424,8 @@ function requireClientH1 () { const client = this[kClient]; const parser = this[kParser]; + clearIdleSocketValidation(this); + if (parser) { if (!this[kError] && parser.statusCode && !parser.shouldKeepAlive) { this[kError] = parser.finish() || this[kError]; @@ -9459,7 +9491,7 @@ function requireClientH1 () { return socket.destroyed }, busy (request) { - if (socket[kWriting] || socket[kReset] || socket[kBlocking]) { + if (socket[kWriting] || socket[kReset] || socket[kBlocking] || socket[kIdleSocketValidation] === 1) { return true } @@ -9497,6 +9529,31 @@ function requireClientH1 () { } } + function clearIdleSocketValidation (socket) { + if (socket[kIdleSocketValidationTimeout]) { + clearTimeout(socket[kIdleSocketValidationTimeout]); + socket[kIdleSocketValidationTimeout] = null; + } + + socket[kIdleSocketValidation] = 0; + } + + function scheduleIdleSocketValidation (client, socket) { + socket[kIdleSocketValidation] = 1; + socket[kIdleSocketValidationTimeout] = setTimeout(() => { + socket[kIdleSocketValidationTimeout] = null; + socket[kIdleSocketValidation] = 2; + + if (client[kSocket] === socket && !socket.destroyed) { + client[kResume](); + } + }, 0); + socket[kIdleSocketValidationTimeout].unref?.(); + } + + /** + * @param {import('./client.js')} client + */ function resumeH1 (client) { const socket = client[kSocket]; @@ -9511,6 +9568,32 @@ function requireClientH1 () { socket[kNoRef] = false; } + if (client[kRunning] === 0 && client[kPending] > 0 && socket[kSocketUsed]) { + if (socket[kIdleSocketValidation] === 0) { + scheduleIdleSocketValidation(client, socket); + socket[kParser].readMore(); + if (socket.destroyed) { + return + } + return + } + + if (socket[kIdleSocketValidation] === 1) { + socket[kParser].readMore(); + if (socket.destroyed) { + return + } + return + } + } + + if (client[kRunning] === 0) { + socket[kParser].readMore(); + if (socket.destroyed) { + return + } + } + if (client[kSize] === 0) { if (socket[kParser].timeoutType !== TIMEOUT_KEEP_ALIVE) { socket[kParser].setTimeout(client[kKeepAliveTimeoutValue], TIMEOUT_KEEP_ALIVE); @@ -9566,8 +9649,16 @@ function requireClientH1 () { } body = bodyStream.stream; contentLength = bodyStream.length; - } else if (util.isBlobLike(body) && request.contentType == null && body.type) { - headers.push('content-type', body.type); + } else if (util.isBlobLike(body) && request.contentType == null) { + const contentType = body.type; + if (contentType) { + const contentTypeValue = `${contentType}`; + if (!util.isValidHeaderValue(contentTypeValue)) { + util.errorRequest(client, request, new InvalidArgumentError('invalid content-type header')); + return false + } + headers.push('content-type', contentTypeValue); + } } if (body && typeof body.read === 'function') { @@ -9604,6 +9695,7 @@ function requireClientH1 () { } const socket = client[kSocket]; + clearIdleSocketValidation(socket); const abort = (err) => { if (request.aborted || request.completed) { @@ -13001,6 +13093,28 @@ function requireRetryHandler () { return new Date(retryAfter).getTime() - current } + function validatePartialResponseContentLength (headers, range, statusCode, retryCount) { + const contentLength = headers['content-length']; + if (contentLength == null) { + return null + } + + if (!Number.isFinite(range.start) || !Number.isFinite(range.end)) { + return null + } + + const length = Number(contentLength); + const expectedLength = range.end - range.start + 1; + if (!Number.isFinite(length) || length !== expectedLength) { + return new RequestRetryError('Content-Length mismatch', statusCode, { + headers, + data: { count: retryCount } + }) + } + + return null + } + class RetryHandler { constructor (opts, handlers) { const { retryOptions, ...dispatchOpts } = opts; @@ -13215,6 +13329,12 @@ function requireRetryHandler () { return false } + const contentLengthError = validatePartialResponseContentLength(headers, contentRange, statusCode, this.retryCount); + if (contentLengthError != null) { + this.abort(contentLengthError); + return false + } + const { start, size, end = size - 1 } = contentRange; assert(this.start === start, 'content-range mismatch'); @@ -13238,6 +13358,12 @@ function requireRetryHandler () { ) } + const contentLengthError = validatePartialResponseContentLength(headers, range, statusCode, this.retryCount); + if (contentLengthError != null) { + this.abort(contentLengthError); + return false + } + const { start, size, end = size - 1 } = range; assert( start != null && Number.isFinite(start), @@ -23626,7 +23752,7 @@ function requireUtil$2 () { if ( code < 0x20 || // exclude CTLs (0-31) - code === 0x7F || // DEL + code > 0x7E || // exclude DEL and non-ascii code === 0x3B // ; ) { throw new Error('Invalid cookie path') @@ -23635,16 +23761,80 @@ function requireUtil$2 () { } /** - * I have no idea why these values aren't allowed to be honest, - * but Deno tests these. - Khafra + * ::= | + * + * ::= any one of the 52 alphabetic characters A through Z in + * upper case and a through z in lower case + * + * ::= any one of the ten digits 0 through 9r + * + * @see https://www.rfc-editor.org/rfc/rfc1034#section-3.5 + * @param {number} code + */ + function isLetterOrDigit (code) { + return ( + (code >= 0x30 && code <= 0x39) || // 0-9 + (code >= 0x41 && code <= 0x5A) || // A-Z + (code >= 0x61 && code <= 0x7A) // a-z + ) + } + + /** + * Validates a cookie domain against the "preferred name syntax". + * + * ::= | " " + * ::=