From 83d5c0db92220f75b8d1a0c37da74a302d13d2ad Mon Sep 17 00:00:00 2001 From: Kamil Szymanski Date: Thu, 15 Oct 2026 08:58:30 +1030 Subject: [PATCH] fix: retry transient GitHub API errors without duplicating dispatches --- dist/index.js | 4902 ++++++++++++++++++++++++++++++------ package-lock.json | 144 +- package.json | 13 +- src/main.ts | 54 +- src/octokit-client.test.ts | 211 ++ src/octokit-client.ts | 60 + src/wait-for-run.test.ts | 108 + src/wait-for-run.ts | 54 + tsconfig.json | 6 +- 9 files changed, 4779 insertions(+), 773 deletions(-) create mode 100644 src/octokit-client.test.ts create mode 100644 src/octokit-client.ts create mode 100644 src/wait-for-run.test.ts create mode 100644 src/wait-for-run.ts diff --git a/dist/index.js b/dist/index.js index 5976c83..f6a4b11 100644 --- a/dist/index.js +++ b/dist/index.js @@ -8,6 +8,10 @@ var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { get: all[name], enumerable: true }); +}; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) @@ -31,9 +35,9 @@ var require_tunnel = __commonJS({ "use strict"; var net = require("net"); var tls = require("tls"); - var http = require("http"); - var https = require("https"); - var events = require("events"); + var http2 = require("http"); + var https2 = require("https"); + var events2 = require("events"); var assert = require("assert"); var util = require("util"); exports2.httpOverHttp = httpOverHttp2; @@ -42,67 +46,67 @@ var require_tunnel = __commonJS({ exports2.httpsOverHttps = httpsOverHttps2; function httpOverHttp2(options) { var agent = new TunnelingAgent(options); - agent.request = http.request; + agent.request = http2.request; return agent; } function httpsOverHttp2(options) { var agent = new TunnelingAgent(options); - agent.request = http.request; + agent.request = http2.request; agent.createSocket = createSecureSocket; agent.defaultPort = 443; return agent; } function httpOverHttps2(options) { var agent = new TunnelingAgent(options); - agent.request = https.request; + agent.request = https2.request; return agent; } function httpsOverHttps2(options) { var agent = new TunnelingAgent(options); - agent.request = https.request; + agent.request = https2.request; agent.createSocket = createSecureSocket; agent.defaultPort = 443; return agent; } function TunnelingAgent(options) { - var self = this; - self.options = options || {}; - self.proxyOptions = self.options.proxy || {}; - self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; - self.requests = []; - self.sockets = []; - self.on("free", function onFree(socket, host, port, localAddress) { + var self2 = this; + self2.options = options || {}; + self2.proxyOptions = self2.options.proxy || {}; + self2.maxSockets = self2.options.maxSockets || http2.Agent.defaultMaxSockets; + self2.requests = []; + self2.sockets = []; + self2.on("free", function onFree(socket, host, port, localAddress) { var options2 = toOptions(host, port, localAddress); - for (var i = 0, len = self.requests.length; i < len; ++i) { - var pending = self.requests[i]; + for (var i = 0, len = self2.requests.length; i < len; ++i) { + var pending = self2.requests[i]; if (pending.host === options2.host && pending.port === options2.port) { - self.requests.splice(i, 1); + self2.requests.splice(i, 1); pending.request.onSocket(socket); return; } } socket.destroy(); - self.removeSocket(socket); + self2.removeSocket(socket); }); } - util.inherits(TunnelingAgent, events.EventEmitter); + util.inherits(TunnelingAgent, events2.EventEmitter); TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { - var self = this; - var options = mergeOptions({ request: req }, self.options, toOptions(host, port, localAddress)); - if (self.sockets.length >= this.maxSockets) { - self.requests.push(options); + var self2 = this; + var options = mergeOptions({ request: req }, self2.options, toOptions(host, port, localAddress)); + if (self2.sockets.length >= this.maxSockets) { + self2.requests.push(options); return; } - self.createSocket(options, function(socket) { + self2.createSocket(options, function(socket) { socket.on("free", onFree); socket.on("close", onCloseOrRemove); socket.on("agentRemove", onCloseOrRemove); req.onSocket(socket); function onFree() { - self.emit("free", socket, options); + self2.emit("free", socket, options); } function onCloseOrRemove(err) { - self.removeSocket(socket); + self2.removeSocket(socket); socket.removeListener("free", onFree); socket.removeListener("close", onCloseOrRemove); socket.removeListener("agentRemove", onCloseOrRemove); @@ -110,10 +114,10 @@ var require_tunnel = __commonJS({ }); }; TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { - var self = this; + var self2 = this; var placeholder = {}; - self.sockets.push(placeholder); - var connectOptions = mergeOptions({}, self.proxyOptions, { + self2.sockets.push(placeholder); + var connectOptions = mergeOptions({}, self2.proxyOptions, { method: "CONNECT", path: options.host + ":" + options.port, agent: false, @@ -129,7 +133,7 @@ var require_tunnel = __commonJS({ connectOptions.headers["Proxy-Authorization"] = "Basic " + new Buffer(connectOptions.proxyAuth).toString("base64"); } debug2("making CONNECT request"); - var connectReq = self.request(connectOptions); + var connectReq = self2.request(connectOptions); connectReq.useChunkedEncodingByDefault = false; connectReq.once("response", onResponse); connectReq.once("upgrade", onUpgrade); @@ -156,7 +160,7 @@ var require_tunnel = __commonJS({ var error2 = new Error("tunneling socket could not be established, statusCode=" + res.statusCode); error2.code = "ECONNRESET"; options.request.emit("error", error2); - self.removeSocket(placeholder); + self2.removeSocket(placeholder); return; } if (head.length > 0) { @@ -165,11 +169,11 @@ var require_tunnel = __commonJS({ var error2 = new Error("got illegal response body from proxy"); error2.code = "ECONNRESET"; options.request.emit("error", error2); - self.removeSocket(placeholder); + self2.removeSocket(placeholder); return; } debug2("tunneling connection has established"); - self.sockets[self.sockets.indexOf(placeholder)] = socket; + self2.sockets[self2.sockets.indexOf(placeholder)] = socket; return cb(socket); } function onError(cause) { @@ -182,7 +186,7 @@ var require_tunnel = __commonJS({ var error2 = new Error("tunneling socket could not be established, cause=" + cause.message); error2.code = "ECONNRESET"; options.request.emit("error", error2); - self.removeSocket(placeholder); + self2.removeSocket(placeholder); } }; TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { @@ -199,15 +203,15 @@ var require_tunnel = __commonJS({ } }; function createSecureSocket(options, cb) { - var self = this; - TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var self2 = this; + TunnelingAgent.prototype.createSocket.call(self2, options, function(socket) { var hostHeader = options.request.getHeader("host"); - var tlsOptions = mergeOptions({}, self.options, { + var tlsOptions = mergeOptions({}, self2.options, { socket, servername: hostHeader ? hostHeader.replace(/:.*$/, "") : options.host }); var secureSocket = tls.connect(0, tlsOptions); - self.sockets[self.sockets.indexOf(socket)] = secureSocket; + self2.sockets[self2.sockets.indexOf(socket)] = secureSocket; cb(secureSocket); }); } @@ -1048,14 +1052,14 @@ var require_util = __commonJS({ } const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80; let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`; - let path = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; + let path6 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`; if (origin[origin.length - 1] === "/") { origin = origin.slice(0, origin.length - 1); } - if (path && path[0] !== "/") { - path = `/${path}`; + if (path6 && path6[0] !== "/") { + path6 = `/${path6}`; } - return new URL(`${origin}${path}`); + return new URL(`${origin}${path6}`); } if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) { throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`."); @@ -1357,7 +1361,7 @@ var require_util = __commonJS({ } obj[kListeners] = null; } - function errorRequest(client, request2, err) { + function errorRequest2(client, request2, err) { try { request2.onError(err); assert(request2.aborted); @@ -1408,7 +1412,7 @@ var require_util = __commonJS({ bufferToLowerCasedHeaderName, addListener, removeAllListeners, - errorRequest, + errorRequest: errorRequest2, parseRawHeaders, parseHeaders, parseKeepAliveTimeout, @@ -1506,39 +1510,39 @@ var require_diagnostics = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path, origin } + request: { method, path: path6, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path); + debuglog("sending request to %s %s/%s", method, origin, path6); }); diagnosticsChannel.channel("undici:request:headers").subscribe((evt) => { const { - request: { method, path, origin }, + request: { method, path: path6, origin }, response: { statusCode } } = evt; debuglog( "received response to %s %s/%s - HTTP %d", method, origin, - path, + path6, statusCode ); }); diagnosticsChannel.channel("undici:request:trailers").subscribe((evt) => { const { - request: { method, path, origin } + request: { method, path: path6, origin } } = evt; - debuglog("trailers received from %s %s/%s", method, origin, path); + debuglog("trailers received from %s %s/%s", method, origin, path6); }); diagnosticsChannel.channel("undici:request:error").subscribe((evt) => { const { - request: { method, path, origin }, + request: { method, path: path6, origin }, error: error2 } = evt; debuglog( "request to %s %s/%s errored - %s", method, origin, - path, + path6, error2.message ); }); @@ -1587,9 +1591,9 @@ var require_diagnostics = __commonJS({ }); diagnosticsChannel.channel("undici:client:sendHeaders").subscribe((evt) => { const { - request: { method, path, origin } + request: { method, path: path6, origin } } = evt; - debuglog("sending request to %s %s/%s", method, origin, path); + debuglog("sending request to %s %s/%s", method, origin, path6); }); } diagnosticsChannel.channel("undici:websocket:open").subscribe((evt) => { @@ -1652,7 +1656,7 @@ var require_request = __commonJS({ var kHandler = Symbol("handler"); var Request = class { constructor(origin, { - path, + path: path6, method, body, headers, @@ -1667,11 +1671,11 @@ var require_request = __commonJS({ expectContinue, servername }, handler2) { - if (typeof path !== "string") { + if (typeof path6 !== "string") { throw new InvalidArgumentError("path must be a string"); - } else if (path[0] !== "/" && !(path.startsWith("http://") || path.startsWith("https://")) && method !== "CONNECT") { + } else if (path6[0] !== "/" && !(path6.startsWith("http://") || path6.startsWith("https://")) && method !== "CONNECT") { throw new InvalidArgumentError("path must be an absolute URL or start with a slash"); - } else if (invalidPathRegex.test(path)) { + } else if (invalidPathRegex.test(path6)) { throw new InvalidArgumentError("invalid request path"); } if (typeof method !== "string") { @@ -1734,7 +1738,7 @@ var require_request = __commonJS({ this.completed = false; this.aborted = false; this.upgrade = upgrade || null; - this.path = query ? buildURL(path, query) : path; + this.path = query ? buildURL(path6, query) : path6; this.origin = origin; this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent; this.blocking = blocking == null ? false : blocking; @@ -1951,8 +1955,8 @@ var require_request = __commonJS({ var require_dispatcher = __commonJS({ "node_modules/undici/lib/dispatcher/dispatcher.js"(exports2, module2) { "use strict"; - var EventEmitter = require("node:events"); - var Dispatcher = class extends EventEmitter { + var EventEmitter2 = require("node:events"); + var Dispatcher = class extends EventEmitter2 { dispatch() { throw new Error("not implemented"); } @@ -2046,9 +2050,9 @@ var require_dispatcher_base = __commonJS({ } close(callback) { if (callback === void 0) { - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { this.close((err, data) => { - return err ? reject(err) : resolve(data); + return err ? reject(err) : resolve2(data); }); }); } @@ -2086,12 +2090,12 @@ var require_dispatcher_base = __commonJS({ err = null; } if (callback === void 0) { - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { this.destroy(err, (err2, data) => { return err2 ? ( /* istanbul ignore next: should never error */ reject(err2) - ) : resolve(data); + ) : resolve2(data); }); }); } @@ -2403,7 +2407,7 @@ var require_connect = __commonJS({ var util = require_util(); var { InvalidArgumentError, ConnectTimeoutError } = require_errors(); var timers = require_timers(); - function noop3() { + function noop4() { } var tls; var SessionCache; @@ -2528,7 +2532,7 @@ var require_connect = __commonJS({ } var setupConnectTimeout = process.platform === "win32" ? (socketWeakRef, opts) => { if (!opts.timeout) { - return noop3; + return noop4; } let s1 = null; let s2 = null; @@ -2544,7 +2548,7 @@ var require_connect = __commonJS({ }; } : (socketWeakRef, opts) => { if (!opts.timeout) { - return noop3; + return noop4; } let s1 = null; const fastTimer = timers.setFastTimeout(() => { @@ -4358,8 +4362,8 @@ var require_util2 = __commonJS({ function createDeferredPromise() { let res; let rej; - const promise = new Promise((resolve, reject) => { - res = resolve; + const promise = new Promise((resolve2, reject) => { + res = resolve2; rej = reject; }); return { promise, resolve: res, reject: rej }; @@ -5335,7 +5339,7 @@ var require_body = __commonJS({ random = (max) => Math.floor(Math.random(max)); } var textEncoder = new TextEncoder(); - function noop3() { + function noop4() { } var hasFinalizationRegistry = globalThis.FinalizationRegistry && process.version.indexOf("v18") !== 0; var streamRegistry; @@ -5343,7 +5347,7 @@ var require_body = __commonJS({ streamRegistry = new FinalizationRegistry((weakRef) => { const stream = weakRef.deref(); if (stream && !stream.locked && !isDisturbed(stream) && !isErrored(stream)) { - stream.cancel("Response object has been garbage collected").catch(noop3); + stream.cancel("Response object has been garbage collected").catch(noop4); } }); } @@ -6247,7 +6251,7 @@ var require_client_h1 = __commonJS({ return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } function writeH1(client, request2) { - const { method, path, host, upgrade, blocking, reset } = request2; + const { method, path: path6, host, upgrade, blocking, reset } = request2; let { body, headers, contentLength } = request2; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH"; if (util.isFormDataLike(body)) { @@ -6313,7 +6317,7 @@ var require_client_h1 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - let header = `${method} ${path} HTTP/1.1\r + let header = `${method} ${path6} HTTP/1.1\r `; if (typeof host === "string") { header += `host: ${host}\r @@ -6500,12 +6504,12 @@ upgrade: ${upgrade}\r cb(); } } - const waitForDrain = () => new Promise((resolve, reject) => { + const waitForDrain = () => new Promise((resolve2, reject) => { assert(callback === null); if (socket[kError]) { reject(socket[kError]); } else { - callback = resolve; + callback = resolve2; } }); socket.on("close", onDrain).on("drain", onDrain); @@ -6839,7 +6843,7 @@ var require_client_h2 = __commonJS({ } function writeH2(client, request2) { const session = client[kHTTP2Session]; - const { method, path, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; + const { method, path: path6, host, upgrade, expectContinue, signal, headers: reqHeaders } = request2; let { body } = request2; if (upgrade) { util.errorRequest(client, request2, new Error("Upgrade not supported for H2")); @@ -6906,7 +6910,7 @@ var require_client_h2 = __commonJS({ }); return true; } - headers[HTTP2_HEADER_PATH] = path; + headers[HTTP2_HEADER_PATH] = path6; headers[HTTP2_HEADER_SCHEME] = "https"; const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH"; if (body && typeof body.read === "function") { @@ -7142,12 +7146,12 @@ var require_client_h2 = __commonJS({ cb(); } } - const waitForDrain = () => new Promise((resolve, reject) => { + const waitForDrain = () => new Promise((resolve2, reject) => { assert(callback === null); if (socket[kError]) { reject(socket[kError]); } else { - callback = resolve; + callback = resolve2; } }); h2stream.on("close", onDrain).on("drain", onDrain); @@ -7259,9 +7263,9 @@ var require_redirect_handler = __commonJS({ return this.handler.onHeaders(statusCode, headers, resume, statusText); } const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); - const path = search ? `${pathname}${search}` : pathname; + const path6 = search ? `${pathname}${search}` : pathname; this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin); - this.opts.path = path; + this.opts.path = path6; this.opts.origin = origin; this.opts.maxRedirections = 0; this.opts.query = null; @@ -7365,7 +7369,7 @@ var require_client = __commonJS({ "use strict"; var assert = require("node:assert"); var net = require("node:net"); - var http = require("node:http"); + var http2 = require("node:http"); var util = require_util(); var { channels } = require_diagnostics(); var Request = require_request(); @@ -7422,7 +7426,7 @@ var require_client = __commonJS({ var connectH2 = require_client_h2(); var deprecatedInterceptorWarned = false; var kClosedResolve = Symbol("kClosedResolve"); - var noop3 = () => { + var noop4 = () => { }; function getPipelining(client) { return client[kPipelining] ?? client[kHTTPContext]?.defaultPipelining ?? 1; @@ -7552,7 +7556,7 @@ var require_client = __commonJS({ this[kUrl] = util.parseOrigin(url); this[kConnector] = connect2; this[kPipelining] = pipelining != null ? pipelining : 1; - this[kMaxHeadersSize] = maxHeaderSize || http.maxHeaderSize; + this[kMaxHeadersSize] = maxHeaderSize || http2.maxHeaderSize; this[kKeepAliveDefaultTimeout] = keepAliveTimeout == null ? 4e3 : keepAliveTimeout; this[kKeepAliveMaxTimeout] = keepAliveMaxTimeout == null ? 6e5 : keepAliveMaxTimeout; this[kKeepAliveTimeoutThreshold] = keepAliveTimeoutThreshold == null ? 2e3 : keepAliveTimeoutThreshold; @@ -7624,16 +7628,16 @@ var require_client = __commonJS({ return this[kNeedDrain] < 2; } async [kClose]() { - return new Promise((resolve) => { + return new Promise((resolve2) => { if (this[kSize]) { - this[kClosedResolve] = resolve; + this[kClosedResolve] = resolve2; } else { - resolve(null); + resolve2(null); } }); } async [kDestroy](err) { - return new Promise((resolve) => { + return new Promise((resolve2) => { const requests = this[kQueue].splice(this[kPendingIdx]); for (let i = 0; i < requests.length; i++) { const request2 = requests[i]; @@ -7644,7 +7648,7 @@ var require_client = __commonJS({ this[kClosedResolve](); this[kClosedResolve] = null; } - resolve(null); + resolve2(null); }; if (this[kHTTPContext]) { this[kHTTPContext].destroy(err, callback); @@ -7695,7 +7699,7 @@ var require_client = __commonJS({ }); } try { - const socket = await new Promise((resolve, reject) => { + const socket = await new Promise((resolve2, reject) => { client[kConnector]({ host, hostname, @@ -7707,19 +7711,19 @@ var require_client = __commonJS({ if (err) { reject(err); } else { - resolve(socket2); + resolve2(socket2); } }); }); if (client.destroyed) { - util.destroy(socket.on("error", noop3), new ClientDestroyedError()); + util.destroy(socket.on("error", noop4), new ClientDestroyedError()); return; } assert(socket); try { client[kHTTPContext] = socket.alpnProtocol === "h2" ? await connectH2(client, socket) : await connectH1(client, socket); } catch (err) { - socket.destroy().on("error", noop3); + socket.destroy().on("error", noop4); throw err; } client[kConnecting] = false; @@ -8043,8 +8047,8 @@ var require_pool_base = __commonJS({ if (this[kQueue].isEmpty()) { await Promise.all(this[kClients].map((c) => c.close())); } else { - await new Promise((resolve) => { - this[kClosedResolve] = resolve; + await new Promise((resolve2) => { + this[kClosedResolve] = resolve2; }); } } @@ -8359,7 +8363,7 @@ var require_agent = __commonJS({ function defaultFactory(origin, opts) { return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } - var Agent = class extends DispatcherBase { + var Agent3 = class extends DispatcherBase { constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { super(); if (typeof factory !== "function") { @@ -8431,7 +8435,7 @@ var require_agent = __commonJS({ await Promise.all(destroyPromises); } }; - module2.exports = Agent; + module2.exports = Agent3; } }); @@ -8441,7 +8445,7 @@ var require_proxy_agent = __commonJS({ "use strict"; var { kProxy, kClose, kDestroy, kDispatch, kInterceptors } = require_symbols(); var { URL: URL2 } = require("node:url"); - var Agent = require_agent(); + var Agent3 = require_agent(); var Pool = require_pool(); var DispatcherBase = require_dispatcher_base(); var { InvalidArgumentError, RequestAbortedError, SecureProxyConnectionError } = require_errors(); @@ -8460,7 +8464,7 @@ var require_proxy_agent = __commonJS({ function defaultFactory(origin, opts) { return new Pool(origin, opts); } - var noop3 = () => { + var noop4 = () => { }; function defaultAgentFactory(origin, opts) { if (opts.connections === 1) { @@ -8495,10 +8499,10 @@ var require_proxy_agent = __commonJS({ }; const { origin, - path = "/", + path: path6 = "/", headers = {} } = opts; - opts.path = origin + path; + opts.path = origin + path6; if (!("host" in headers) && !("Host" in headers)) { const { host } = new URL2(origin); headers.host = host; @@ -8556,7 +8560,7 @@ var require_proxy_agent = __commonJS({ return agentFactory(origin2, options); }; this[kClient] = clientFactory(url, { connect }); - this[kAgent] = new Agent({ + this[kAgent] = new Agent3({ ...opts, factory, connect: async (opts2, callback) => { @@ -8577,7 +8581,7 @@ var require_proxy_agent = __commonJS({ servername: this[kProxyTls]?.servername || proxyHostname }); if (statusCode !== 200) { - socket.on("error", noop3).destroy(); + socket.on("error", noop4).destroy(); callback(new RequestAbortedError(`Proxy response (${statusCode}) !== 200 when HTTP Tunneling`)); } if (opts2.protocol !== "https:") { @@ -8665,7 +8669,7 @@ var require_env_http_proxy_agent = __commonJS({ var DispatcherBase = require_dispatcher_base(); var { kClose, kDestroy, kClosed, kDestroyed, kDispatch, kNoProxyAgent, kHttpProxyAgent, kHttpsProxyAgent } = require_symbols(); var ProxyAgent2 = require_proxy_agent(); - var Agent = require_agent(); + var Agent3 = require_agent(); var DEFAULT_PORTS = { "http:": 80, "https:": 443 @@ -8685,7 +8689,7 @@ var require_env_http_proxy_agent = __commonJS({ }); } const { httpProxy, httpsProxy, noProxy, ...agentOpts } = opts; - this[kNoProxyAgent] = new Agent(agentOpts); + this[kNoProxyAgent] = new Agent3(agentOpts); const HTTP_PROXY = httpProxy ?? process.env.http_proxy ?? process.env.HTTP_PROXY; if (HTTP_PROXY) { this[kHttpProxyAgent] = new ProxyAgent2({ ...agentOpts, uri: HTTP_PROXY }); @@ -9107,14 +9111,14 @@ var require_retry_agent = __commonJS({ this.#options = options; } dispatch(opts, handler2) { - const retry = new RetryHandler({ + const retry2 = new RetryHandler({ ...opts, retryOptions: this.#options }, { dispatch: this.#agent.dispatch.bind(this.#agent), handler: handler2 }); - return this.#agent.dispatch(opts, retry); + return this.#agent.dispatch(opts, retry2); } close() { return this.#agent.close(); @@ -9142,7 +9146,7 @@ var require_readable = __commonJS({ var kAbort = Symbol("kAbort"); var kContentType = Symbol("kContentType"); var kContentLength = Symbol("kContentLength"); - var noop3 = () => { + var noop4 = () => { }; var BodyReadable = class extends Readable { constructor({ @@ -9259,7 +9263,7 @@ var require_readable = __commonJS({ if (this._readableState.closeEmitted) { return null; } - return await new Promise((resolve, reject) => { + return await new Promise((resolve2, reject) => { if (this[kContentLength] > limit) { this.destroy(new AbortError()); } @@ -9272,9 +9276,9 @@ var require_readable = __commonJS({ if (signal?.aborted) { reject(signal.reason ?? new AbortError()); } else { - resolve(null); + resolve2(null); } - }).on("error", noop3).on("data", function(chunk) { + }).on("error", noop4).on("data", function(chunk) { limit -= chunk.length; if (limit <= 0) { this.destroy(); @@ -9283,15 +9287,15 @@ var require_readable = __commonJS({ }); } }; - function isLocked(self) { - return self[kBody] && self[kBody].locked === true || self[kConsume]; + function isLocked(self2) { + return self2[kBody] && self2[kBody].locked === true || self2[kConsume]; } - function isUnusable(self) { - return util.isDisturbed(self) || isLocked(self); + function isUnusable(self2) { + return util.isDisturbed(self2) || isLocked(self2); } async function consume(stream, type) { assert(!stream[kConsume]); - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { if (isUnusable(stream)) { const rState = stream._readableState; if (rState.destroyed && rState.closeEmitted === false) { @@ -9308,7 +9312,7 @@ var require_readable = __commonJS({ stream[kConsume] = { type, stream, - resolve, + resolve: resolve2, reject, length: 0, body: [] @@ -9378,18 +9382,18 @@ var require_readable = __commonJS({ return buffer; } function consumeEnd(consume2) { - const { type, body, resolve, stream, length } = consume2; + const { type, body, resolve: resolve2, stream, length } = consume2; try { if (type === "text") { - resolve(chunksDecode(body, length)); + resolve2(chunksDecode(body, length)); } else if (type === "json") { - resolve(JSON.parse(chunksDecode(body, length))); + resolve2(JSON.parse(chunksDecode(body, length))); } else if (type === "arrayBuffer") { - resolve(chunksConcat(body, length).buffer); + resolve2(chunksConcat(body, length).buffer); } else if (type === "blob") { - resolve(new Blob(body, { type: stream[kContentType] })); + resolve2(new Blob(body, { type: stream[kContentType] })); } else if (type === "bytes") { - resolve(chunksConcat(body, length)); + resolve2(chunksConcat(body, length)); } consumeFinish(consume2); } catch (err) { @@ -9646,9 +9650,9 @@ var require_api_request = __commonJS({ }; function request2(opts, callback) { if (callback === void 0) { - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { request2.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data); + return err ? reject(err) : resolve2(data); }); }); } @@ -9674,42 +9678,42 @@ var require_abort_signal = __commonJS({ var { RequestAbortedError } = require_errors(); var kListener = Symbol("kListener"); var kSignal = Symbol("kSignal"); - function abort(self) { - if (self.abort) { - self.abort(self[kSignal]?.reason); + function abort(self2) { + if (self2.abort) { + self2.abort(self2[kSignal]?.reason); } else { - self.reason = self[kSignal]?.reason ?? new RequestAbortedError(); + self2.reason = self2[kSignal]?.reason ?? new RequestAbortedError(); } - removeSignal(self); + removeSignal(self2); } - function addSignal(self, signal) { - self.reason = null; - self[kSignal] = null; - self[kListener] = null; + function addSignal(self2, signal) { + self2.reason = null; + self2[kSignal] = null; + self2[kListener] = null; if (!signal) { return; } if (signal.aborted) { - abort(self); + abort(self2); return; } - self[kSignal] = signal; - self[kListener] = () => { - abort(self); + self2[kSignal] = signal; + self2[kListener] = () => { + abort(self2); }; - addAbortListener(self[kSignal], self[kListener]); + addAbortListener(self2[kSignal], self2[kListener]); } - function removeSignal(self) { - if (!self[kSignal]) { + function removeSignal(self2) { + if (!self2[kSignal]) { return; } - if ("removeEventListener" in self[kSignal]) { - self[kSignal].removeEventListener("abort", self[kListener]); + if ("removeEventListener" in self2[kSignal]) { + self2[kSignal].removeEventListener("abort", self2[kListener]); } else { - self[kSignal].removeListener("abort", self[kListener]); + self2[kSignal].removeListener("abort", self2[kListener]); } - self[kSignal] = null; - self[kListener] = null; + self2[kSignal] = null; + self2[kListener] = null; } module2.exports = { addSignal, @@ -9871,9 +9875,9 @@ var require_api_stream = __commonJS({ }; function stream(opts, factory, callback) { if (callback === void 0) { - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { stream.call(this, opts, factory, (err, data) => { - return err ? reject(err) : resolve(data); + return err ? reject(err) : resolve2(data); }); }); } @@ -10158,9 +10162,9 @@ var require_api_upgrade = __commonJS({ }; function upgrade(opts, callback) { if (callback === void 0) { - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { upgrade.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data); + return err ? reject(err) : resolve2(data); }); }); } @@ -10252,9 +10256,9 @@ var require_api_connect = __commonJS({ }; function connect(opts, callback) { if (callback === void 0) { - return new Promise((resolve, reject) => { + return new Promise((resolve2, reject) => { connect.call(this, opts, (err, data) => { - return err ? reject(err) : resolve(data); + return err ? reject(err) : resolve2(data); }); }); } @@ -10419,20 +10423,20 @@ var require_mock_utils = __commonJS({ } return true; } - function safeUrl(path) { - if (typeof path !== "string") { - return path; + function safeUrl(path6) { + if (typeof path6 !== "string") { + return path6; } - const pathSegments = path.split("?"); + const pathSegments = path6.split("?"); if (pathSegments.length !== 2) { - return path; + return path6; } const qp = new URLSearchParams(pathSegments.pop()); qp.sort(); return [...pathSegments, qp.toString()].join("?"); } - function matchKey(mockDispatch2, { path, method, body, headers }) { - const pathMatch = matchValue(mockDispatch2.path, path); + function matchKey(mockDispatch2, { path: path6, method, body, headers }) { + const pathMatch = matchValue(mockDispatch2.path, path6); const methodMatch = matchValue(mockDispatch2.method, method); const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true; const headersMatch = matchHeaders(mockDispatch2, headers); @@ -10454,7 +10458,7 @@ var require_mock_utils = __commonJS({ function getMockDispatch(mockDispatches, key) { const basePath = key.query ? buildURL(key.path, key.query) : key.path; const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath; - let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path }) => matchValue(safeUrl(path), resolvedPath)); + let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path6 }) => matchValue(safeUrl(path6), resolvedPath)); if (matchedMockDispatches.length === 0) { throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`); } @@ -10492,9 +10496,9 @@ var require_mock_utils = __commonJS({ } } function buildKey(opts) { - const { path, method, body, headers, query } = opts; + const { path: path6, method, body, headers, query } = opts; return { - path, + path: path6, method, body, headers, @@ -10957,10 +10961,10 @@ var require_pending_interceptors_formatter = __commonJS({ } format(pendingInterceptors) { const withPrettyHeaders = pendingInterceptors.map( - ({ method, path, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ + ({ method, path: path6, data: { statusCode }, persist, times, timesInvoked, origin }) => ({ Method: method, Origin: origin, - Path: path, + Path: path6, "Status code": statusCode, Persistent: persist ? PERSISTENT : NOT_PERSISTENT, Invocations: timesInvoked, @@ -10979,7 +10983,7 @@ var require_mock_agent = __commonJS({ "node_modules/undici/lib/mock/mock-agent.js"(exports2, module2) { "use strict"; var { kClients } = require_symbols(); - var Agent = require_agent(); + var Agent3 = require_agent(); var { kAgent, kMockAgentSet, @@ -11006,7 +11010,7 @@ var require_mock_agent = __commonJS({ if (opts?.agent && typeof opts.agent.dispatch !== "function") { throw new InvalidArgumentError("Argument opts.agent must implement Agent"); } - const agent = opts?.agent ? opts.agent : new Agent(opts); + const agent = opts?.agent ? opts.agent : new Agent3(opts); this[kAgent] = agent; this[kClients] = agent[kClients]; this[kOptions] = buildMockOptions(opts); @@ -11110,9 +11114,9 @@ var require_global2 = __commonJS({ "use strict"; var globalDispatcher = Symbol.for("undici.globalDispatcher.1"); var { InvalidArgumentError } = require_errors(); - var Agent = require_agent(); + var Agent3 = require_agent(); if (getGlobalDispatcher() === void 0) { - setGlobalDispatcher(new Agent()); + setGlobalDispatcher(new Agent3()); } function setGlobalDispatcher(agent) { if (!agent || typeof agent.dispatch !== "function") { @@ -11723,10 +11727,10 @@ var require_headers = __commonJS({ const lowercaseName = isLowerCase ? name : name.toLowerCase(); const exists2 = this[kHeadersMap].get(lowercaseName); if (exists2) { - const delimiter = lowercaseName === "cookie" ? "; " : ", "; + const delimiter3 = lowercaseName === "cookie" ? "; " : ", "; this[kHeadersMap].set(lowercaseName, { name: exists2.name, - value: `${exists2.value}${delimiter}${value}` + value: `${exists2.value}${delimiter3}${value}` }); } else { this[kHeadersMap].set(lowercaseName, { name, value }); @@ -12595,15 +12599,15 @@ var require_request2 = __commonJS({ signal = input[kSignal]; } const origin = environmentSettingsObject.settingsObject.origin; - let window = "client"; + let window2 = "client"; if (request2.window?.constructor?.name === "EnvironmentSettingsObject" && sameOrigin(request2.window, origin)) { - window = request2.window; + window2 = request2.window; } if (init.window != null) { - throw new TypeError(`'window' option '${window}' must be null`); + throw new TypeError(`'window' option '${window2}' must be null`); } if ("window" in init) { - window = "no-window"; + window2 = "no-window"; } request2 = makeRequest({ // URL request’s URL. @@ -12618,7 +12622,7 @@ var require_request2 = __commonJS({ // client This’s relevant settings object. client: environmentSettingsObject.settingsObject, // window window. - window, + window: window2, // priority request’s priority. priority: request2.priority, // origin request’s origin. The propagation of the origin is only significant for navigation requests @@ -14116,7 +14120,7 @@ var require_fetch = __commonJS({ function dispatch({ body }) { const url = requestCurrentURL(request2); const agent = fetchParams.controller.dispatcher; - return new Promise((resolve, reject) => agent.dispatch( + return new Promise((resolve2, reject) => agent.dispatch( { path: url.pathname + url.search, origin: url.origin, @@ -14192,7 +14196,7 @@ var require_fetch = __commonJS({ } } const onError = this.onError.bind(this); - resolve({ + resolve2({ status, statusText, headersList, @@ -14238,7 +14242,7 @@ var require_fetch = __commonJS({ for (let i = 0; i < rawHeaders.length; i += 2) { headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true); } - resolve({ + resolve2({ status, statusText: STATUS_CODES[status], headersList, @@ -14643,7 +14647,7 @@ var require_util4 = __commonJS({ var { getEncoding } = require_encoding(); var { serializeAMimeType, parseMIMEType } = require_data_url(); var { types } = require("node:util"); - var { StringDecoder } = require("string_decoder"); + var { StringDecoder: StringDecoder2 } = require("string_decoder"); var { btoa } = require("node:buffer"); var staticPropertyDescriptors = { enumerable: true, @@ -14734,7 +14738,7 @@ var require_util4 = __commonJS({ dataURL += serializeAMimeType(parsed); } dataURL += ";base64,"; - const decoder = new StringDecoder("latin1"); + const decoder = new StringDecoder2("latin1"); for (const chunk of bytes) { dataURL += btoa(decoder.write(chunk)); } @@ -14763,7 +14767,7 @@ var require_util4 = __commonJS({ } case "BinaryString": { let binaryString = ""; - const decoder = new StringDecoder("latin1"); + const decoder = new StringDecoder2("latin1"); for (const chunk of bytes) { binaryString += decoder.write(chunk); } @@ -15841,9 +15845,9 @@ var require_util6 = __commonJS({ } } } - function validateCookiePath(path) { - for (let i = 0; i < path.length; ++i) { - const code = path.charCodeAt(i); + function validateCookiePath(path6) { + for (let i = 0; i < path6.length; ++i) { + const code = path6.charCodeAt(i); if (code < 32 || // exclude CTLs (0-31) code === 127 || // DEL code === 59) { @@ -17831,8 +17835,8 @@ var require_util8 = __commonJS({ return true; } function delay(ms) { - return new Promise((resolve) => { - setTimeout(resolve, ms).unref(); + return new Promise((resolve2) => { + setTimeout(resolve2, ms).unref(); }); } module2.exports = { @@ -18378,7 +18382,7 @@ var require_undici = __commonJS({ var Dispatcher = require_dispatcher(); var Pool = require_pool(); var BalancedPool = require_balanced_pool(); - var Agent = require_agent(); + var Agent3 = require_agent(); var ProxyAgent2 = require_proxy_agent(); var EnvHttpProxyAgent = require_env_http_proxy_agent(); var RetryAgent = require_retry_agent(); @@ -18401,7 +18405,7 @@ var require_undici = __commonJS({ module2.exports.Client = Client; module2.exports.Pool = Pool; module2.exports.BalancedPool = BalancedPool; - module2.exports.Agent = Agent; + module2.exports.Agent = Agent3; module2.exports.ProxyAgent = ProxyAgent2; module2.exports.EnvHttpProxyAgent = EnvHttpProxyAgent; module2.exports.RetryAgent = RetryAgent; @@ -18437,11 +18441,11 @@ var require_undici = __commonJS({ if (typeof opts.path !== "string") { throw new InvalidArgumentError("invalid opts.path"); } - let path = opts.path; + let path6 = opts.path; if (!opts.path.startsWith("/")) { - path = `/${path}`; + path6 = `/${path6}`; } - url = new URL(util.parseOrigin(url).origin + path); + url = new URL(util.parseOrigin(url).origin + path6); } else { if (!opts) { opts = typeof url === "object" ? url : {}; @@ -18518,10 +18522,10 @@ var require_proxy = __commonJS({ "use strict"; Object.defineProperty(exports2, "__esModule", { value: true }); exports2.getProxyUrl = getProxyUrl2; - exports2.checkBypass = checkBypass; + exports2.checkBypass = checkBypass2; function getProxyUrl2(reqUrl) { const usingSsl = reqUrl.protocol === "https:"; - if (checkBypass(reqUrl)) { + if (checkBypass2(reqUrl)) { return void 0; } const proxyVar = (() => { @@ -18533,21 +18537,21 @@ var require_proxy = __commonJS({ })(); if (proxyVar) { try { - return new DecodedURL(proxyVar); + return new DecodedURL2(proxyVar); } catch (_a) { if (!proxyVar.startsWith("http://") && !proxyVar.startsWith("https://")) - return new DecodedURL(`http://${proxyVar}`); + return new DecodedURL2(`http://${proxyVar}`); } } else { return void 0; } } - function checkBypass(reqUrl) { + function checkBypass2(reqUrl) { if (!reqUrl.hostname) { return false; } const reqHost = reqUrl.hostname; - if (isLoopbackAddress(reqHost)) { + if (isLoopbackAddress2(reqHost)) { return true; } const noProxy = process.env["no_proxy"] || process.env["NO_PROXY"] || ""; @@ -18573,11 +18577,11 @@ var require_proxy = __commonJS({ } return false; } - function isLoopbackAddress(host) { + function isLoopbackAddress2(host) { const hostLower = host.toLowerCase(); return hostLower === "localhost" || hostLower.startsWith("127.") || hostLower.startsWith("[::1]") || hostLower.startsWith("[0:0:0:0:0:0:0:1]"); } - var DecodedURL = class extends URL { + var DecodedURL2 = class extends URL { constructor(url, base) { super(url, base); this._decodedUsername = decodeURIComponent(super.username); @@ -18634,13 +18638,13 @@ var require_lib = __commonJS({ return result; }; })(); - var __awaiter3 = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { + var __awaiter12 = exports2 && exports2.__awaiter || function(thisArg, _arguments, P, generator) { function adopt(value) { - return value instanceof P ? value : new P(function(resolve) { - resolve(value); + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); }); } - return new (P || (P = Promise))(function(resolve, reject) { + return new (P || (P = Promise))(function(resolve2, reject) { function fulfilled(value) { try { step(generator.next(value)); @@ -18656,7 +18660,7 @@ var require_lib = __commonJS({ } } function step(result) { - result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); @@ -18665,8 +18669,8 @@ var require_lib = __commonJS({ exports2.HttpClient = exports2.HttpClientResponse = exports2.HttpClientError = exports2.MediaTypes = exports2.Headers = exports2.HttpCodes = void 0; exports2.getProxyUrl = getProxyUrl2; exports2.isHttps = isHttps; - var http = __importStar(require("http")); - var https = __importStar(require("https")); + var http2 = __importStar(require("http")); + var https2 = __importStar(require("https")); var pm = __importStar(require_proxy()); var tunnel2 = __importStar(require_tunnel2()); var undici_1 = require_undici(); @@ -18725,10 +18729,10 @@ var require_lib = __commonJS({ HttpCodes2.ServiceUnavailable, HttpCodes2.GatewayTimeout ]; - var RetryableHttpVerbs = ["OPTIONS", "GET", "DELETE", "HEAD"]; - var ExponentialBackoffCeiling = 10; - var ExponentialBackoffTimeSlice = 5; - var HttpClientError = class _HttpClientError extends Error { + var RetryableHttpVerbs2 = ["OPTIONS", "GET", "DELETE", "HEAD"]; + var ExponentialBackoffCeiling2 = 10; + var ExponentialBackoffTimeSlice2 = 5; + var HttpClientError2 = class _HttpClientError extends Error { constructor(message, statusCode) { super(message); this.name = "HttpClientError"; @@ -18736,39 +18740,39 @@ var require_lib = __commonJS({ Object.setPrototypeOf(this, _HttpClientError.prototype); } }; - exports2.HttpClientError = HttpClientError; - var HttpClientResponse = class { + exports2.HttpClientError = HttpClientError2; + var HttpClientResponse2 = class { constructor(message) { this.message = message; } readBody() { - return __awaiter3(this, void 0, void 0, function* () { - return new Promise((resolve) => __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { + return new Promise((resolve2) => __awaiter12(this, void 0, void 0, function* () { let output = Buffer.alloc(0); this.message.on("data", (chunk) => { output = Buffer.concat([output, chunk]); }); this.message.on("end", () => { - resolve(output.toString()); + resolve2(output.toString()); }); })); }); } readBodyBuffer() { - return __awaiter3(this, void 0, void 0, function* () { - return new Promise((resolve) => __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { + return new Promise((resolve2) => __awaiter12(this, void 0, void 0, function* () { const chunks = []; this.message.on("data", (chunk) => { chunks.push(chunk); }); this.message.on("end", () => { - resolve(Buffer.concat(chunks)); + resolve2(Buffer.concat(chunks)); }); })); }); } }; - exports2.HttpClientResponse = HttpClientResponse; + exports2.HttpClientResponse = HttpClientResponse2; function isHttps(requestUrl) { const parsedUrl = new URL(requestUrl); return parsedUrl.protocol === "https:"; @@ -18812,42 +18816,42 @@ var require_lib = __commonJS({ } } options(requestUrl, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("OPTIONS", requestUrl, null, additionalHeaders || {}); }); } get(requestUrl, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("GET", requestUrl, null, additionalHeaders || {}); }); } del(requestUrl, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("DELETE", requestUrl, null, additionalHeaders || {}); }); } post(requestUrl, data, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("POST", requestUrl, data, additionalHeaders || {}); }); } patch(requestUrl, data, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("PATCH", requestUrl, data, additionalHeaders || {}); }); } put(requestUrl, data, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("PUT", requestUrl, data, additionalHeaders || {}); }); } head(requestUrl, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request("HEAD", requestUrl, null, additionalHeaders || {}); }); } sendStream(verb, requestUrl, stream, additionalHeaders) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { return this.request(verb, requestUrl, stream, additionalHeaders); }); } @@ -18856,14 +18860,14 @@ var require_lib = __commonJS({ * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise */ getJson(requestUrl_1) { - return __awaiter3(this, arguments, void 0, function* (requestUrl, additionalHeaders = {}) { + return __awaiter12(this, arguments, void 0, function* (requestUrl, additionalHeaders = {}) { additionalHeaders[Headers2.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers2.Accept, MediaTypes2.ApplicationJson); const res = yield this.get(requestUrl, additionalHeaders); return this._processResponse(res, this.requestOptions); }); } postJson(requestUrl_1, obj_1) { - return __awaiter3(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + return __awaiter12(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { const data = JSON.stringify(obj, null, 2); additionalHeaders[Headers2.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers2.Accept, MediaTypes2.ApplicationJson); additionalHeaders[Headers2.ContentType] = this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes2.ApplicationJson); @@ -18872,7 +18876,7 @@ var require_lib = __commonJS({ }); } putJson(requestUrl_1, obj_1) { - return __awaiter3(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + return __awaiter12(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { const data = JSON.stringify(obj, null, 2); additionalHeaders[Headers2.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers2.Accept, MediaTypes2.ApplicationJson); additionalHeaders[Headers2.ContentType] = this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes2.ApplicationJson); @@ -18881,7 +18885,7 @@ var require_lib = __commonJS({ }); } patchJson(requestUrl_1, obj_1) { - return __awaiter3(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + return __awaiter12(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { const data = JSON.stringify(obj, null, 2); additionalHeaders[Headers2.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers2.Accept, MediaTypes2.ApplicationJson); additionalHeaders[Headers2.ContentType] = this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes2.ApplicationJson); @@ -18895,13 +18899,13 @@ var require_lib = __commonJS({ * Prefer get, del, post and patch */ request(verb, requestUrl, data, headers) { - return __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { if (this._disposed) { throw new Error("Client has already been disposed."); } const parsedUrl = new URL(requestUrl); let info2 = this._prepareRequest(verb, parsedUrl, headers); - const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; + const maxTries = this._allowRetries && RetryableHttpVerbs2.includes(verb) ? this._maxRetries + 1 : 1; let numTries = 0; let response; do { @@ -18969,15 +18973,15 @@ var require_lib = __commonJS({ * @param data */ requestRaw(info2, data) { - return __awaiter3(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => { + return __awaiter12(this, void 0, void 0, function* () { + return new Promise((resolve2, reject) => { function callbackForResult(err, res) { if (err) { reject(err); } else if (!res) { reject(new Error("Unknown error")); } else { - resolve(res); + resolve2(res); } } this.requestRawWithCallback(info2, data, callbackForResult); @@ -19005,7 +19009,7 @@ var require_lib = __commonJS({ } } const req = info2.httpModule.request(info2.options, (msg) => { - const res = new HttpClientResponse(msg); + const res = new HttpClientResponse2(msg); handleResult(void 0, res); }); let socket; @@ -19055,7 +19059,7 @@ var require_lib = __commonJS({ const info2 = {}; info2.parsedUrl = requestUrl; const usingSsl = info2.parsedUrl.protocol === "https:"; - info2.httpModule = usingSsl ? https : http; + info2.httpModule = usingSsl ? https2 : http2; const defaultPort = usingSsl ? 443 : 80; info2.options = {}; info2.options.host = info2.parsedUrl.hostname; @@ -19076,9 +19080,9 @@ var require_lib = __commonJS({ } _mergeHeaders(headers) { if (this.requestOptions && this.requestOptions.headers) { - return Object.assign({}, lowercaseKeys2(this.requestOptions.headers), lowercaseKeys2(headers || {})); + return Object.assign({}, lowercaseKeys3(this.requestOptions.headers), lowercaseKeys3(headers || {})); } - return lowercaseKeys2(headers || {}); + return lowercaseKeys3(headers || {}); } /** * Gets an existing header value or returns a default. @@ -19090,7 +19094,7 @@ var require_lib = __commonJS({ _getExistingOrDefaultHeader(additionalHeaders, header, _default) { let clientHeader; if (this.requestOptions && this.requestOptions.headers) { - const headerValue = lowercaseKeys2(this.requestOptions.headers)[header]; + const headerValue = lowercaseKeys3(this.requestOptions.headers)[header]; if (headerValue) { clientHeader = typeof headerValue === "number" ? headerValue.toString() : headerValue; } @@ -19114,7 +19118,7 @@ var require_lib = __commonJS({ _getExistingOrDefaultContentTypeHeader(additionalHeaders, _default) { let clientHeader; if (this.requestOptions && this.requestOptions.headers) { - const headerValue = lowercaseKeys2(this.requestOptions.headers)[Headers2.ContentType]; + const headerValue = lowercaseKeys3(this.requestOptions.headers)[Headers2.ContentType]; if (headerValue) { if (typeof headerValue === "number") { clientHeader = String(headerValue); @@ -19156,7 +19160,7 @@ var require_lib = __commonJS({ const usingSsl = parsedUrl.protocol === "https:"; let maxSockets = 100; if (this.requestOptions) { - maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + maxSockets = this.requestOptions.maxSockets || http2.globalAgent.maxSockets; } if (proxyUrl && proxyUrl.hostname) { const agentOptions = { @@ -19178,7 +19182,7 @@ var require_lib = __commonJS({ } if (!agent) { const options = { keepAlive: this._keepAlive, maxSockets }; - agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + agent = usingSsl ? new https2.Agent(options) : new http2.Agent(options); this._agent = agent; } if (usingSsl && this._ignoreSslError) { @@ -19218,15 +19222,15 @@ var require_lib = __commonJS({ return baseUserAgent; } _performExponentialBackoff(retryNumber) { - return __awaiter3(this, void 0, void 0, function* () { - retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); - const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); - return new Promise((resolve) => setTimeout(() => resolve(), ms)); + return __awaiter12(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling2, retryNumber); + const ms = ExponentialBackoffTimeSlice2 * Math.pow(2, retryNumber); + return new Promise((resolve2) => setTimeout(() => resolve2(), ms)); }); } _processResponse(res, options) { - return __awaiter3(this, void 0, void 0, function* () { - return new Promise((resolve, reject) => __awaiter3(this, void 0, void 0, function* () { + return __awaiter12(this, void 0, void 0, function* () { + return new Promise((resolve2, reject) => __awaiter12(this, void 0, void 0, function* () { const statusCode = res.message.statusCode || 0; const response = { statusCode, @@ -19234,7 +19238,7 @@ var require_lib = __commonJS({ headers: {} }; if (statusCode === HttpCodes2.NotFound) { - resolve(response); + resolve2(response); } function dateTimeDeserializer(key, value) { if (typeof value === "string") { @@ -19269,18 +19273,18 @@ var require_lib = __commonJS({ } else { msg = `Failed request: (${statusCode})`; } - const err = new HttpClientError(msg, statusCode); + const err = new HttpClientError2(msg, statusCode); err.result = response.result; reject(err); } else { - resolve(response); + resolve2(response); } })); }); } }; exports2.HttpClient = HttpClient3; - var lowercaseKeys2 = (obj) => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {}); + var lowercaseKeys3 = (obj) => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {}); } }); @@ -19380,469 +19384,3503 @@ var require_fast_content_type_parse = __commonJS({ } }); -// node_modules/@actions/core/lib/command.js -var os = __toESM(require("os"), 1); - -// node_modules/@actions/core/lib/utils.js -function toCommandValue(input) { - if (input === null || input === void 0) { - return ""; - } else if (typeof input === "string" || input instanceof String) { - return input; - } - return JSON.stringify(input); -} -function toCommandProperties(annotationProperties) { - if (!Object.keys(annotationProperties).length) { - return {}; - } - return { - title: annotationProperties.title, - file: annotationProperties.file, - line: annotationProperties.startLine, - endLine: annotationProperties.endLine, - col: annotationProperties.startColumn, - endColumn: annotationProperties.endColumn - }; -} - -// node_modules/@actions/core/lib/command.js -function issueCommand(command, properties, message) { - const cmd = new Command(command, properties, message); - process.stdout.write(cmd.toString() + os.EOL); -} -var CMD_STRING = "::"; -var Command = class { - constructor(command, properties, message) { - if (!command) { - command = "missing.command"; - } - this.command = command; - this.properties = properties; - this.message = message; - } - toString() { - let cmdStr = CMD_STRING + this.command; - if (this.properties && Object.keys(this.properties).length > 0) { - cmdStr += " "; - let first = true; - for (const key in this.properties) { - if (this.properties.hasOwnProperty(key)) { - const val = this.properties[key]; - if (val) { - if (first) { - first = false; +// node_modules/bottleneck/light.js +var require_light = __commonJS({ + "node_modules/bottleneck/light.js"(exports2, module2) { + (function(global2, factory) { + typeof exports2 === "object" && typeof module2 !== "undefined" ? module2.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global2.Bottleneck = factory(); + })(exports2, (function() { + "use strict"; + var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {}; + function getCjsExportFromNamespace(n) { + return n && n["default"] || n; + } + var load = function(received, defaults2, onto = {}) { + var k, ref, v; + for (k in defaults2) { + v = defaults2[k]; + onto[k] = (ref = received[k]) != null ? ref : v; + } + return onto; + }; + var overwrite = function(received, defaults2, onto = {}) { + var k, v; + for (k in received) { + v = received[k]; + if (defaults2[k] !== void 0) { + onto[k] = v; + } + } + return onto; + }; + var parser = { + load, + overwrite + }; + var DLList; + DLList = class DLList { + constructor(incr, decr) { + this.incr = incr; + this.decr = decr; + this._first = null; + this._last = null; + this.length = 0; + } + push(value) { + var node; + this.length++; + if (typeof this.incr === "function") { + this.incr(); + } + node = { + value, + prev: this._last, + next: null + }; + if (this._last != null) { + this._last.next = node; + this._last = node; + } else { + this._first = this._last = node; + } + return void 0; + } + shift() { + var value; + if (this._first == null) { + return; + } else { + this.length--; + if (typeof this.decr === "function") { + this.decr(); + } + } + value = this._first.value; + if ((this._first = this._first.next) != null) { + this._first.prev = null; + } else { + this._last = null; + } + return value; + } + first() { + if (this._first != null) { + return this._first.value; + } + } + getArray() { + var node, ref, results; + node = this._first; + results = []; + while (node != null) { + results.push((ref = node, node = node.next, ref.value)); + } + return results; + } + forEachShift(cb) { + var node; + node = this.shift(); + while (node != null) { + cb(node), node = this.shift(); + } + return void 0; + } + debug() { + var node, ref, ref1, ref2, results; + node = this._first; + results = []; + while (node != null) { + results.push((ref = node, node = node.next, { + value: ref.value, + prev: (ref1 = ref.prev) != null ? ref1.value : void 0, + next: (ref2 = ref.next) != null ? ref2.value : void 0 + })); + } + return results; + } + }; + var DLList_1 = DLList; + var Events; + Events = class Events { + constructor(instance) { + this.instance = instance; + this._events = {}; + if (this.instance.on != null || this.instance.once != null || this.instance.removeAllListeners != null) { + throw new Error("An Emitter already exists for this object"); + } + this.instance.on = (name, cb) => { + return this._addListener(name, "many", cb); + }; + this.instance.once = (name, cb) => { + return this._addListener(name, "once", cb); + }; + this.instance.removeAllListeners = (name = null) => { + if (name != null) { + return delete this._events[name]; } else { - cmdStr += ","; + return this._events = {}; } - cmdStr += `${key}=${escapeProperty(val)}`; + }; + } + _addListener(name, status, cb) { + var base; + if ((base = this._events)[name] == null) { + base[name] = []; } + this._events[name].push({ cb, status }); + return this.instance; } - } - } - cmdStr += `${CMD_STRING}${escapeData(this.message)}`; - return cmdStr; - } -}; -function escapeData(s) { - return toCommandValue(s).replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A"); -} -function escapeProperty(s) { - return toCommandValue(s).replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C"); -} - -// node_modules/@actions/core/lib/file-command.js -var crypto = __toESM(require("crypto"), 1); -var fs = __toESM(require("fs"), 1); -var os2 = __toESM(require("os"), 1); -function issueFileCommand(command, message) { - const filePath = process.env[`GITHUB_${command}`]; - if (!filePath) { - throw new Error(`Unable to find environment variable for file command ${command}`); - } - if (!fs.existsSync(filePath)) { - throw new Error(`Missing file at path: ${filePath}`); - } - fs.appendFileSync(filePath, `${toCommandValue(message)}${os2.EOL}`, { - encoding: "utf8" - }); -} -function prepareKeyValueMessage(key, value) { - const delimiter = `ghadelimiter_${crypto.randomUUID()}`; - const convertedValue = toCommandValue(value); - if (key.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedValue.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - return `${key}<<${delimiter}${os2.EOL}${convertedValue}${os2.EOL}${delimiter}`; -} - -// node_modules/@actions/core/lib/core.js -var os4 = __toESM(require("os"), 1); - -// node_modules/@actions/http-client/lib/index.js -var tunnel = __toESM(require_tunnel2(), 1); -var import_undici = __toESM(require_undici(), 1); -var HttpCodes; -(function(HttpCodes2) { - HttpCodes2[HttpCodes2["OK"] = 200] = "OK"; - HttpCodes2[HttpCodes2["MultipleChoices"] = 300] = "MultipleChoices"; - HttpCodes2[HttpCodes2["MovedPermanently"] = 301] = "MovedPermanently"; - HttpCodes2[HttpCodes2["ResourceMoved"] = 302] = "ResourceMoved"; - HttpCodes2[HttpCodes2["SeeOther"] = 303] = "SeeOther"; - HttpCodes2[HttpCodes2["NotModified"] = 304] = "NotModified"; - HttpCodes2[HttpCodes2["UseProxy"] = 305] = "UseProxy"; - HttpCodes2[HttpCodes2["SwitchProxy"] = 306] = "SwitchProxy"; - HttpCodes2[HttpCodes2["TemporaryRedirect"] = 307] = "TemporaryRedirect"; - HttpCodes2[HttpCodes2["PermanentRedirect"] = 308] = "PermanentRedirect"; - HttpCodes2[HttpCodes2["BadRequest"] = 400] = "BadRequest"; - HttpCodes2[HttpCodes2["Unauthorized"] = 401] = "Unauthorized"; - HttpCodes2[HttpCodes2["PaymentRequired"] = 402] = "PaymentRequired"; - HttpCodes2[HttpCodes2["Forbidden"] = 403] = "Forbidden"; - HttpCodes2[HttpCodes2["NotFound"] = 404] = "NotFound"; - HttpCodes2[HttpCodes2["MethodNotAllowed"] = 405] = "MethodNotAllowed"; - HttpCodes2[HttpCodes2["NotAcceptable"] = 406] = "NotAcceptable"; - HttpCodes2[HttpCodes2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; - HttpCodes2[HttpCodes2["RequestTimeout"] = 408] = "RequestTimeout"; - HttpCodes2[HttpCodes2["Conflict"] = 409] = "Conflict"; - HttpCodes2[HttpCodes2["Gone"] = 410] = "Gone"; - HttpCodes2[HttpCodes2["TooManyRequests"] = 429] = "TooManyRequests"; - HttpCodes2[HttpCodes2["InternalServerError"] = 500] = "InternalServerError"; - HttpCodes2[HttpCodes2["NotImplemented"] = 501] = "NotImplemented"; - HttpCodes2[HttpCodes2["BadGateway"] = 502] = "BadGateway"; - HttpCodes2[HttpCodes2["ServiceUnavailable"] = 503] = "ServiceUnavailable"; - HttpCodes2[HttpCodes2["GatewayTimeout"] = 504] = "GatewayTimeout"; -})(HttpCodes || (HttpCodes = {})); -var Headers; -(function(Headers2) { - Headers2["Accept"] = "accept"; - Headers2["ContentType"] = "content-type"; -})(Headers || (Headers = {})); -var MediaTypes; -(function(MediaTypes2) { - MediaTypes2["ApplicationJson"] = "application/json"; -})(MediaTypes || (MediaTypes = {})); -var HttpRedirectCodes = [ - HttpCodes.MovedPermanently, - HttpCodes.ResourceMoved, - HttpCodes.SeeOther, - HttpCodes.TemporaryRedirect, - HttpCodes.PermanentRedirect -]; -var HttpResponseRetryCodes = [ - HttpCodes.BadGateway, - HttpCodes.ServiceUnavailable, - HttpCodes.GatewayTimeout -]; - -// node_modules/@actions/core/lib/summary.js -var import_os = require("os"); -var import_fs = require("fs"); -var __awaiter = function(thisArg, _arguments, P, generator) { - function adopt(value) { - return value instanceof P ? value : new P(function(resolve) { - resolve(value); - }); - } - return new (P || (P = Promise))(function(resolve, reject) { - function fulfilled(value) { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - } - function rejected(value) { - try { - step(generator["throw"](value)); - } catch (e) { - reject(e); - } - } - function step(result) { - result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); - } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var { access, appendFile, writeFile } = import_fs.promises; -var SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; -var Summary = class { - constructor() { - this._buffer = ""; - } - /** - * Finds the summary file path from the environment, rejects if env var is not found or file does not exist - * Also checks r/w permissions. - * - * @returns step summary file path - */ - filePath() { - return __awaiter(this, void 0, void 0, function* () { - if (this._filePath) { - return this._filePath; - } - const pathFromEnv = process.env[SUMMARY_ENV_VAR]; - if (!pathFromEnv) { - throw new Error(`Unable to find environment variable for $${SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); - } - try { - yield access(pathFromEnv, import_fs.constants.R_OK | import_fs.constants.W_OK); - } catch (_a) { - throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); - } - this._filePath = pathFromEnv; - return this._filePath; - }); - } - /** - * Wraps content in an HTML tag, adding any HTML attributes - * - * @param {string} tag HTML tag to wrap - * @param {string | null} content content within the tag - * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add - * - * @returns {string} content wrapped in HTML element - */ - wrap(tag, content, attrs = {}) { - const htmlAttrs = Object.entries(attrs).map(([key, value]) => ` ${key}="${value}"`).join(""); - if (!content) { - return `<${tag}${htmlAttrs}>`; - } - return `<${tag}${htmlAttrs}>${content}`; - } - /** - * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. - * - * @param {SummaryWriteOptions} [options] (optional) options for write operation - * - * @returns {Promise} summary instance + listenerCount(name) { + if (this._events[name] != null) { + return this._events[name].length; + } else { + return 0; + } + } + async trigger(name, ...args) { + var e, promises3; + try { + if (name !== "debug") { + this.trigger("debug", `Event triggered: ${name}`, args); + } + if (this._events[name] == null) { + return; + } + this._events[name] = this._events[name].filter(function(listener) { + return listener.status !== "none"; + }); + promises3 = this._events[name].map(async (listener) => { + var e2, returned; + if (listener.status === "none") { + return; + } + if (listener.status === "once") { + listener.status = "none"; + } + try { + returned = typeof listener.cb === "function" ? listener.cb(...args) : void 0; + if (typeof (returned != null ? returned.then : void 0) === "function") { + return await returned; + } else { + return returned; + } + } catch (error2) { + e2 = error2; + { + this.trigger("error", e2); + } + return null; + } + }); + return (await Promise.all(promises3)).find(function(x) { + return x != null; + }); + } catch (error2) { + e = error2; + { + this.trigger("error", e); + } + return null; + } + } + }; + var Events_1 = Events; + var DLList$1, Events$1, Queues; + DLList$1 = DLList_1; + Events$1 = Events_1; + Queues = class Queues { + constructor(num_priorities) { + var i; + this.Events = new Events$1(this); + this._length = 0; + this._lists = (function() { + var j, ref, results; + results = []; + for (i = j = 1, ref = num_priorities; 1 <= ref ? j <= ref : j >= ref; i = 1 <= ref ? ++j : --j) { + results.push(new DLList$1((() => { + return this.incr(); + }), (() => { + return this.decr(); + }))); + } + return results; + }).call(this); + } + incr() { + if (this._length++ === 0) { + return this.Events.trigger("leftzero"); + } + } + decr() { + if (--this._length === 0) { + return this.Events.trigger("zero"); + } + } + push(job) { + return this._lists[job.options.priority].push(job); + } + queued(priority) { + if (priority != null) { + return this._lists[priority].length; + } else { + return this._length; + } + } + shiftAll(fn) { + return this._lists.forEach(function(list) { + return list.forEachShift(fn); + }); + } + getFirst(arr = this._lists) { + var j, len, list; + for (j = 0, len = arr.length; j < len; j++) { + list = arr[j]; + if (list.length > 0) { + return list; + } + } + return []; + } + shiftLastFrom(priority) { + return this.getFirst(this._lists.slice(priority).reverse()).shift(); + } + }; + var Queues_1 = Queues; + var BottleneckError; + BottleneckError = class BottleneckError extends Error { + }; + var BottleneckError_1 = BottleneckError; + var BottleneckError$1, DEFAULT_PRIORITY, Job, NUM_PRIORITIES, parser$1; + NUM_PRIORITIES = 10; + DEFAULT_PRIORITY = 5; + parser$1 = parser; + BottleneckError$1 = BottleneckError_1; + Job = class Job { + constructor(task, args, options, jobDefaults, rejectOnDrop, Events2, _states, Promise2) { + this.task = task; + this.args = args; + this.rejectOnDrop = rejectOnDrop; + this.Events = Events2; + this._states = _states; + this.Promise = Promise2; + this.options = parser$1.load(options, jobDefaults); + this.options.priority = this._sanitizePriority(this.options.priority); + if (this.options.id === jobDefaults.id) { + this.options.id = `${this.options.id}-${this._randomIndex()}`; + } + this.promise = new this.Promise((_resolve, _reject) => { + this._resolve = _resolve; + this._reject = _reject; + }); + this.retryCount = 0; + } + _sanitizePriority(priority) { + var sProperty; + sProperty = ~~priority !== priority ? DEFAULT_PRIORITY : priority; + if (sProperty < 0) { + return 0; + } else if (sProperty > NUM_PRIORITIES - 1) { + return NUM_PRIORITIES - 1; + } else { + return sProperty; + } + } + _randomIndex() { + return Math.random().toString(36).slice(2); + } + doDrop({ error: error2, message = "This job has been dropped by Bottleneck" } = {}) { + if (this._states.remove(this.options.id)) { + if (this.rejectOnDrop) { + this._reject(error2 != null ? error2 : new BottleneckError$1(message)); + } + this.Events.trigger("dropped", { args: this.args, options: this.options, task: this.task, promise: this.promise }); + return true; + } else { + return false; + } + } + _assertStatus(expected) { + var status; + status = this._states.jobStatus(this.options.id); + if (!(status === expected || expected === "DONE" && status === null)) { + throw new BottleneckError$1(`Invalid job status ${status}, expected ${expected}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`); + } + } + doReceive() { + this._states.start(this.options.id); + return this.Events.trigger("received", { args: this.args, options: this.options }); + } + doQueue(reachedHWM, blocked) { + this._assertStatus("RECEIVED"); + this._states.next(this.options.id); + return this.Events.trigger("queued", { args: this.args, options: this.options, reachedHWM, blocked }); + } + doRun() { + if (this.retryCount === 0) { + this._assertStatus("QUEUED"); + this._states.next(this.options.id); + } else { + this._assertStatus("EXECUTING"); + } + return this.Events.trigger("scheduled", { args: this.args, options: this.options }); + } + async doExecute(chained, clearGlobalState, run2, free) { + var error2, eventInfo, passed; + if (this.retryCount === 0) { + this._assertStatus("RUNNING"); + this._states.next(this.options.id); + } else { + this._assertStatus("EXECUTING"); + } + eventInfo = { args: this.args, options: this.options, retryCount: this.retryCount }; + this.Events.trigger("executing", eventInfo); + try { + passed = await (chained != null ? chained.schedule(this.options, this.task, ...this.args) : this.task(...this.args)); + if (clearGlobalState()) { + this.doDone(eventInfo); + await free(this.options, eventInfo); + this._assertStatus("DONE"); + return this._resolve(passed); + } + } catch (error1) { + error2 = error1; + return this._onFailure(error2, eventInfo, clearGlobalState, run2, free); + } + } + doExpire(clearGlobalState, run2, free) { + var error2, eventInfo; + if (this._states.jobStatus(this.options.id === "RUNNING")) { + this._states.next(this.options.id); + } + this._assertStatus("EXECUTING"); + eventInfo = { args: this.args, options: this.options, retryCount: this.retryCount }; + error2 = new BottleneckError$1(`This job timed out after ${this.options.expiration} ms.`); + return this._onFailure(error2, eventInfo, clearGlobalState, run2, free); + } + async _onFailure(error2, eventInfo, clearGlobalState, run2, free) { + var retry2, retryAfter; + if (clearGlobalState()) { + retry2 = await this.Events.trigger("failed", error2, eventInfo); + if (retry2 != null) { + retryAfter = ~~retry2; + this.Events.trigger("retry", `Retrying ${this.options.id} after ${retryAfter} ms`, eventInfo); + this.retryCount++; + return run2(retryAfter); + } else { + this.doDone(eventInfo); + await free(this.options, eventInfo); + this._assertStatus("DONE"); + return this._reject(error2); + } + } + } + doDone(eventInfo) { + this._assertStatus("EXECUTING"); + this._states.next(this.options.id); + return this.Events.trigger("done", eventInfo); + } + }; + var Job_1 = Job; + var BottleneckError$2, LocalDatastore, parser$2; + parser$2 = parser; + BottleneckError$2 = BottleneckError_1; + LocalDatastore = class LocalDatastore { + constructor(instance, storeOptions, storeInstanceOptions) { + this.instance = instance; + this.storeOptions = storeOptions; + this.clientId = this.instance._randomIndex(); + parser$2.load(storeInstanceOptions, storeInstanceOptions, this); + this._nextRequest = this._lastReservoirRefresh = this._lastReservoirIncrease = Date.now(); + this._running = 0; + this._done = 0; + this._unblockTime = 0; + this.ready = this.Promise.resolve(); + this.clients = {}; + this._startHeartbeat(); + } + _startHeartbeat() { + var base; + if (this.heartbeat == null && (this.storeOptions.reservoirRefreshInterval != null && this.storeOptions.reservoirRefreshAmount != null || this.storeOptions.reservoirIncreaseInterval != null && this.storeOptions.reservoirIncreaseAmount != null)) { + return typeof (base = this.heartbeat = setInterval(() => { + var amount, incr, maximum, now, reservoir; + now = Date.now(); + if (this.storeOptions.reservoirRefreshInterval != null && now >= this._lastReservoirRefresh + this.storeOptions.reservoirRefreshInterval) { + this._lastReservoirRefresh = now; + this.storeOptions.reservoir = this.storeOptions.reservoirRefreshAmount; + this.instance._drainAll(this.computeCapacity()); + } + if (this.storeOptions.reservoirIncreaseInterval != null && now >= this._lastReservoirIncrease + this.storeOptions.reservoirIncreaseInterval) { + ({ + reservoirIncreaseAmount: amount, + reservoirIncreaseMaximum: maximum, + reservoir + } = this.storeOptions); + this._lastReservoirIncrease = now; + incr = maximum != null ? Math.min(amount, maximum - reservoir) : amount; + if (incr > 0) { + this.storeOptions.reservoir += incr; + return this.instance._drainAll(this.computeCapacity()); + } + } + }, this.heartbeatInterval)).unref === "function" ? base.unref() : void 0; + } else { + return clearInterval(this.heartbeat); + } + } + async __publish__(message) { + await this.yieldLoop(); + return this.instance.Events.trigger("message", message.toString()); + } + async __disconnect__(flush) { + await this.yieldLoop(); + clearInterval(this.heartbeat); + return this.Promise.resolve(); + } + yieldLoop(t = 0) { + return new this.Promise(function(resolve2, reject) { + return setTimeout(resolve2, t); + }); + } + computePenalty() { + var ref; + return (ref = this.storeOptions.penalty) != null ? ref : 15 * this.storeOptions.minTime || 5e3; + } + async __updateSettings__(options) { + await this.yieldLoop(); + parser$2.overwrite(options, options, this.storeOptions); + this._startHeartbeat(); + this.instance._drainAll(this.computeCapacity()); + return true; + } + async __running__() { + await this.yieldLoop(); + return this._running; + } + async __queued__() { + await this.yieldLoop(); + return this.instance.queued(); + } + async __done__() { + await this.yieldLoop(); + return this._done; + } + async __groupCheck__(time) { + await this.yieldLoop(); + return this._nextRequest + this.timeout < time; + } + computeCapacity() { + var maxConcurrent, reservoir; + ({ maxConcurrent, reservoir } = this.storeOptions); + if (maxConcurrent != null && reservoir != null) { + return Math.min(maxConcurrent - this._running, reservoir); + } else if (maxConcurrent != null) { + return maxConcurrent - this._running; + } else if (reservoir != null) { + return reservoir; + } else { + return null; + } + } + conditionsCheck(weight) { + var capacity; + capacity = this.computeCapacity(); + return capacity == null || weight <= capacity; + } + async __incrementReservoir__(incr) { + var reservoir; + await this.yieldLoop(); + reservoir = this.storeOptions.reservoir += incr; + this.instance._drainAll(this.computeCapacity()); + return reservoir; + } + async __currentReservoir__() { + await this.yieldLoop(); + return this.storeOptions.reservoir; + } + isBlocked(now) { + return this._unblockTime >= now; + } + check(weight, now) { + return this.conditionsCheck(weight) && this._nextRequest - now <= 0; + } + async __check__(weight) { + var now; + await this.yieldLoop(); + now = Date.now(); + return this.check(weight, now); + } + async __register__(index, weight, expiration) { + var now, wait; + await this.yieldLoop(); + now = Date.now(); + if (this.conditionsCheck(weight)) { + this._running += weight; + if (this.storeOptions.reservoir != null) { + this.storeOptions.reservoir -= weight; + } + wait = Math.max(this._nextRequest - now, 0); + this._nextRequest = now + wait + this.storeOptions.minTime; + return { + success: true, + wait, + reservoir: this.storeOptions.reservoir + }; + } else { + return { + success: false + }; + } + } + strategyIsBlock() { + return this.storeOptions.strategy === 3; + } + async __submit__(queueLength, weight) { + var blocked, now, reachedHWM; + await this.yieldLoop(); + if (this.storeOptions.maxConcurrent != null && weight > this.storeOptions.maxConcurrent) { + throw new BottleneckError$2(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${this.storeOptions.maxConcurrent}`); + } + now = Date.now(); + reachedHWM = this.storeOptions.highWater != null && queueLength === this.storeOptions.highWater && !this.check(weight, now); + blocked = this.strategyIsBlock() && (reachedHWM || this.isBlocked(now)); + if (blocked) { + this._unblockTime = now + this.computePenalty(); + this._nextRequest = this._unblockTime + this.storeOptions.minTime; + this.instance._dropAllQueued(); + } + return { + reachedHWM, + blocked, + strategy: this.storeOptions.strategy + }; + } + async __free__(index, weight) { + await this.yieldLoop(); + this._running -= weight; + this._done += weight; + this.instance._drainAll(this.computeCapacity()); + return { + running: this._running + }; + } + }; + var LocalDatastore_1 = LocalDatastore; + var BottleneckError$3, States; + BottleneckError$3 = BottleneckError_1; + States = class States { + constructor(status1) { + this.status = status1; + this._jobs = {}; + this.counts = this.status.map(function() { + return 0; + }); + } + next(id) { + var current, next; + current = this._jobs[id]; + next = current + 1; + if (current != null && next < this.status.length) { + this.counts[current]--; + this.counts[next]++; + return this._jobs[id]++; + } else if (current != null) { + this.counts[current]--; + return delete this._jobs[id]; + } + } + start(id) { + var initial; + initial = 0; + this._jobs[id] = initial; + return this.counts[initial]++; + } + remove(id) { + var current; + current = this._jobs[id]; + if (current != null) { + this.counts[current]--; + delete this._jobs[id]; + } + return current != null; + } + jobStatus(id) { + var ref; + return (ref = this.status[this._jobs[id]]) != null ? ref : null; + } + statusJobs(status) { + var k, pos, ref, results, v; + if (status != null) { + pos = this.status.indexOf(status); + if (pos < 0) { + throw new BottleneckError$3(`status must be one of ${this.status.join(", ")}`); + } + ref = this._jobs; + results = []; + for (k in ref) { + v = ref[k]; + if (v === pos) { + results.push(k); + } + } + return results; + } else { + return Object.keys(this._jobs); + } + } + statusCounts() { + return this.counts.reduce(((acc, v, i) => { + acc[this.status[i]] = v; + return acc; + }), {}); + } + }; + var States_1 = States; + var DLList$2, Sync; + DLList$2 = DLList_1; + Sync = class Sync { + constructor(name, Promise2) { + this.schedule = this.schedule.bind(this); + this.name = name; + this.Promise = Promise2; + this._running = 0; + this._queue = new DLList$2(); + } + isEmpty() { + return this._queue.length === 0; + } + async _tryToRun() { + var args, cb, error2, reject, resolve2, returned, task; + if (this._running < 1 && this._queue.length > 0) { + this._running++; + ({ task, args, resolve: resolve2, reject } = this._queue.shift()); + cb = await (async function() { + try { + returned = await task(...args); + return function() { + return resolve2(returned); + }; + } catch (error1) { + error2 = error1; + return function() { + return reject(error2); + }; + } + })(); + this._running--; + this._tryToRun(); + return cb(); + } + } + schedule(task, ...args) { + var promise, reject, resolve2; + resolve2 = reject = null; + promise = new this.Promise(function(_resolve, _reject) { + resolve2 = _resolve; + return reject = _reject; + }); + this._queue.push({ task, args, resolve: resolve2, reject }); + this._tryToRun(); + return promise; + } + }; + var Sync_1 = Sync; + var version2 = "2.19.5"; + var version$1 = { + version: version2 + }; + var version$2 = /* @__PURE__ */ Object.freeze({ + version: version2, + default: version$1 + }); + var require$$2 = () => console.log("You must import the full version of Bottleneck in order to use this feature."); + var require$$3 = () => console.log("You must import the full version of Bottleneck in order to use this feature."); + var require$$4 = () => console.log("You must import the full version of Bottleneck in order to use this feature."); + var Events$2, Group, IORedisConnection$1, RedisConnection$1, Scripts$1, parser$3; + parser$3 = parser; + Events$2 = Events_1; + RedisConnection$1 = require$$2; + IORedisConnection$1 = require$$3; + Scripts$1 = require$$4; + Group = (function() { + class Group2 { + constructor(limiterOptions = {}) { + this.deleteKey = this.deleteKey.bind(this); + this.limiterOptions = limiterOptions; + parser$3.load(this.limiterOptions, this.defaults, this); + this.Events = new Events$2(this); + this.instances = {}; + this.Bottleneck = Bottleneck_1; + this._startAutoCleanup(); + this.sharedConnection = this.connection != null; + if (this.connection == null) { + if (this.limiterOptions.datastore === "redis") { + this.connection = new RedisConnection$1(Object.assign({}, this.limiterOptions, { Events: this.Events })); + } else if (this.limiterOptions.datastore === "ioredis") { + this.connection = new IORedisConnection$1(Object.assign({}, this.limiterOptions, { Events: this.Events })); + } + } + } + key(key = "") { + var ref; + return (ref = this.instances[key]) != null ? ref : (() => { + var limiter; + limiter = this.instances[key] = new this.Bottleneck(Object.assign(this.limiterOptions, { + id: `${this.id}-${key}`, + timeout: this.timeout, + connection: this.connection + })); + this.Events.trigger("created", limiter, key); + return limiter; + })(); + } + async deleteKey(key = "") { + var deleted, instance; + instance = this.instances[key]; + if (this.connection) { + deleted = await this.connection.__runCommand__(["del", ...Scripts$1.allKeys(`${this.id}-${key}`)]); + } + if (instance != null) { + delete this.instances[key]; + await instance.disconnect(); + } + return instance != null || deleted > 0; + } + limiters() { + var k, ref, results, v; + ref = this.instances; + results = []; + for (k in ref) { + v = ref[k]; + results.push({ + key: k, + limiter: v + }); + } + return results; + } + keys() { + return Object.keys(this.instances); + } + async clusterKeys() { + var cursor, end, found, i, k, keys, len, next, start; + if (this.connection == null) { + return this.Promise.resolve(this.keys()); + } + keys = []; + cursor = null; + start = `b_${this.id}-`.length; + end = "_settings".length; + while (cursor !== 0) { + [next, found] = await this.connection.__runCommand__(["scan", cursor != null ? cursor : 0, "match", `b_${this.id}-*_settings`, "count", 1e4]); + cursor = ~~next; + for (i = 0, len = found.length; i < len; i++) { + k = found[i]; + keys.push(k.slice(start, -end)); + } + } + return keys; + } + _startAutoCleanup() { + var base; + clearInterval(this.interval); + return typeof (base = this.interval = setInterval(async () => { + var e, k, ref, results, time, v; + time = Date.now(); + ref = this.instances; + results = []; + for (k in ref) { + v = ref[k]; + try { + if (await v._store.__groupCheck__(time)) { + results.push(this.deleteKey(k)); + } else { + results.push(void 0); + } + } catch (error2) { + e = error2; + results.push(v.Events.trigger("error", e)); + } + } + return results; + }, this.timeout / 2)).unref === "function" ? base.unref() : void 0; + } + updateSettings(options = {}) { + parser$3.overwrite(options, this.defaults, this); + parser$3.overwrite(options, options, this.limiterOptions); + if (options.timeout != null) { + return this._startAutoCleanup(); + } + } + disconnect(flush = true) { + var ref; + if (!this.sharedConnection) { + return (ref = this.connection) != null ? ref.disconnect(flush) : void 0; + } + } + } + Group2.prototype.defaults = { + timeout: 1e3 * 60 * 5, + connection: null, + Promise, + id: "group-key" + }; + return Group2; + }).call(commonjsGlobal); + var Group_1 = Group; + var Batcher, Events$3, parser$4; + parser$4 = parser; + Events$3 = Events_1; + Batcher = (function() { + class Batcher2 { + constructor(options = {}) { + this.options = options; + parser$4.load(this.options, this.defaults, this); + this.Events = new Events$3(this); + this._arr = []; + this._resetPromise(); + this._lastFlush = Date.now(); + } + _resetPromise() { + return this._promise = new this.Promise((res, rej) => { + return this._resolve = res; + }); + } + _flush() { + clearTimeout(this._timeout); + this._lastFlush = Date.now(); + this._resolve(); + this.Events.trigger("batch", this._arr); + this._arr = []; + return this._resetPromise(); + } + add(data) { + var ret; + this._arr.push(data); + ret = this._promise; + if (this._arr.length === this.maxSize) { + this._flush(); + } else if (this.maxTime != null && this._arr.length === 1) { + this._timeout = setTimeout(() => { + return this._flush(); + }, this.maxTime); + } + return ret; + } + } + Batcher2.prototype.defaults = { + maxTime: null, + maxSize: null, + Promise + }; + return Batcher2; + }).call(commonjsGlobal); + var Batcher_1 = Batcher; + var require$$4$1 = () => console.log("You must import the full version of Bottleneck in order to use this feature."); + var require$$8 = getCjsExportFromNamespace(version$2); + var Bottleneck2, DEFAULT_PRIORITY$1, Events$4, Job$1, LocalDatastore$1, NUM_PRIORITIES$1, Queues$1, RedisDatastore$1, States$1, Sync$1, parser$5, splice = [].splice; + NUM_PRIORITIES$1 = 10; + DEFAULT_PRIORITY$1 = 5; + parser$5 = parser; + Queues$1 = Queues_1; + Job$1 = Job_1; + LocalDatastore$1 = LocalDatastore_1; + RedisDatastore$1 = require$$4$1; + Events$4 = Events_1; + States$1 = States_1; + Sync$1 = Sync_1; + Bottleneck2 = (function() { + class Bottleneck3 { + constructor(options = {}, ...invalid) { + var storeInstanceOptions, storeOptions; + this._addToQueue = this._addToQueue.bind(this); + this._validateOptions(options, invalid); + parser$5.load(options, this.instanceDefaults, this); + this._queues = new Queues$1(NUM_PRIORITIES$1); + this._scheduled = {}; + this._states = new States$1(["RECEIVED", "QUEUED", "RUNNING", "EXECUTING"].concat(this.trackDoneStatus ? ["DONE"] : [])); + this._limiter = null; + this.Events = new Events$4(this); + this._submitLock = new Sync$1("submit", this.Promise); + this._registerLock = new Sync$1("register", this.Promise); + storeOptions = parser$5.load(options, this.storeDefaults, {}); + this._store = (function() { + if (this.datastore === "redis" || this.datastore === "ioredis" || this.connection != null) { + storeInstanceOptions = parser$5.load(options, this.redisStoreDefaults, {}); + return new RedisDatastore$1(this, storeOptions, storeInstanceOptions); + } else if (this.datastore === "local") { + storeInstanceOptions = parser$5.load(options, this.localStoreDefaults, {}); + return new LocalDatastore$1(this, storeOptions, storeInstanceOptions); + } else { + throw new Bottleneck3.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`); + } + }).call(this); + this._queues.on("leftzero", () => { + var ref; + return (ref = this._store.heartbeat) != null ? typeof ref.ref === "function" ? ref.ref() : void 0 : void 0; + }); + this._queues.on("zero", () => { + var ref; + return (ref = this._store.heartbeat) != null ? typeof ref.unref === "function" ? ref.unref() : void 0 : void 0; + }); + } + _validateOptions(options, invalid) { + if (!(options != null && typeof options === "object" && invalid.length === 0)) { + throw new Bottleneck3.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1."); + } + } + ready() { + return this._store.ready; + } + clients() { + return this._store.clients; + } + channel() { + return `b_${this.id}`; + } + channel_client() { + return `b_${this.id}_${this._store.clientId}`; + } + publish(message) { + return this._store.__publish__(message); + } + disconnect(flush = true) { + return this._store.__disconnect__(flush); + } + chain(_limiter) { + this._limiter = _limiter; + return this; + } + queued(priority) { + return this._queues.queued(priority); + } + clusterQueued() { + return this._store.__queued__(); + } + empty() { + return this.queued() === 0 && this._submitLock.isEmpty(); + } + running() { + return this._store.__running__(); + } + done() { + return this._store.__done__(); + } + jobStatus(id) { + return this._states.jobStatus(id); + } + jobs(status) { + return this._states.statusJobs(status); + } + counts() { + return this._states.statusCounts(); + } + _randomIndex() { + return Math.random().toString(36).slice(2); + } + check(weight = 1) { + return this._store.__check__(weight); + } + _clearGlobalState(index) { + if (this._scheduled[index] != null) { + clearTimeout(this._scheduled[index].expiration); + delete this._scheduled[index]; + return true; + } else { + return false; + } + } + async _free(index, job, options, eventInfo) { + var e, running; + try { + ({ running } = await this._store.__free__(index, options.weight)); + this.Events.trigger("debug", `Freed ${options.id}`, eventInfo); + if (running === 0 && this.empty()) { + return this.Events.trigger("idle"); + } + } catch (error1) { + e = error1; + return this.Events.trigger("error", e); + } + } + _run(index, job, wait) { + var clearGlobalState, free, run2; + job.doRun(); + clearGlobalState = this._clearGlobalState.bind(this, index); + run2 = this._run.bind(this, index, job); + free = this._free.bind(this, index, job); + return this._scheduled[index] = { + timeout: setTimeout(() => { + return job.doExecute(this._limiter, clearGlobalState, run2, free); + }, wait), + expiration: job.options.expiration != null ? setTimeout(function() { + return job.doExpire(clearGlobalState, run2, free); + }, wait + job.options.expiration) : void 0, + job + }; + } + _drainOne(capacity) { + return this._registerLock.schedule(() => { + var args, index, next, options, queue; + if (this.queued() === 0) { + return this.Promise.resolve(null); + } + queue = this._queues.getFirst(); + ({ options, args } = next = queue.first()); + if (capacity != null && options.weight > capacity) { + return this.Promise.resolve(null); + } + this.Events.trigger("debug", `Draining ${options.id}`, { args, options }); + index = this._randomIndex(); + return this._store.__register__(index, options.weight, options.expiration).then(({ success, wait, reservoir }) => { + var empty; + this.Events.trigger("debug", `Drained ${options.id}`, { success, args, options }); + if (success) { + queue.shift(); + empty = this.empty(); + if (empty) { + this.Events.trigger("empty"); + } + if (reservoir === 0) { + this.Events.trigger("depleted", empty); + } + this._run(index, next, wait); + return this.Promise.resolve(options.weight); + } else { + return this.Promise.resolve(null); + } + }); + }); + } + _drainAll(capacity, total = 0) { + return this._drainOne(capacity).then((drained) => { + var newCapacity; + if (drained != null) { + newCapacity = capacity != null ? capacity - drained : capacity; + return this._drainAll(newCapacity, total + drained); + } else { + return this.Promise.resolve(total); + } + }).catch((e) => { + return this.Events.trigger("error", e); + }); + } + _dropAllQueued(message) { + return this._queues.shiftAll(function(job) { + return job.doDrop({ message }); + }); + } + stop(options = {}) { + var done, waitForExecuting; + options = parser$5.load(options, this.stopDefaults); + waitForExecuting = (at) => { + var finished; + finished = () => { + var counts; + counts = this._states.counts; + return counts[0] + counts[1] + counts[2] + counts[3] === at; + }; + return new this.Promise((resolve2, reject) => { + if (finished()) { + return resolve2(); + } else { + return this.on("done", () => { + if (finished()) { + this.removeAllListeners("done"); + return resolve2(); + } + }); + } + }); + }; + done = options.dropWaitingJobs ? (this._run = function(index, next) { + return next.doDrop({ + message: options.dropErrorMessage + }); + }, this._drainOne = () => { + return this.Promise.resolve(null); + }, this._registerLock.schedule(() => { + return this._submitLock.schedule(() => { + var k, ref, v; + ref = this._scheduled; + for (k in ref) { + v = ref[k]; + if (this.jobStatus(v.job.options.id) === "RUNNING") { + clearTimeout(v.timeout); + clearTimeout(v.expiration); + v.job.doDrop({ + message: options.dropErrorMessage + }); + } + } + this._dropAllQueued(options.dropErrorMessage); + return waitForExecuting(0); + }); + })) : this.schedule({ + priority: NUM_PRIORITIES$1 - 1, + weight: 0 + }, () => { + return waitForExecuting(1); + }); + this._receive = function(job) { + return job._reject(new Bottleneck3.prototype.BottleneckError(options.enqueueErrorMessage)); + }; + this.stop = () => { + return this.Promise.reject(new Bottleneck3.prototype.BottleneckError("stop() has already been called")); + }; + return done; + } + async _addToQueue(job) { + var args, blocked, error2, options, reachedHWM, shifted, strategy; + ({ args, options } = job); + try { + ({ reachedHWM, blocked, strategy } = await this._store.__submit__(this.queued(), options.weight)); + } catch (error1) { + error2 = error1; + this.Events.trigger("debug", `Could not queue ${options.id}`, { args, options, error: error2 }); + job.doDrop({ error: error2 }); + return false; + } + if (blocked) { + job.doDrop(); + return true; + } else if (reachedHWM) { + shifted = strategy === Bottleneck3.prototype.strategy.LEAK ? this._queues.shiftLastFrom(options.priority) : strategy === Bottleneck3.prototype.strategy.OVERFLOW_PRIORITY ? this._queues.shiftLastFrom(options.priority + 1) : strategy === Bottleneck3.prototype.strategy.OVERFLOW ? job : void 0; + if (shifted != null) { + shifted.doDrop(); + } + if (shifted == null || strategy === Bottleneck3.prototype.strategy.OVERFLOW) { + if (shifted == null) { + job.doDrop(); + } + return reachedHWM; + } + } + job.doQueue(reachedHWM, blocked); + this._queues.push(job); + await this._drainAll(); + return reachedHWM; + } + _receive(job) { + if (this._states.jobStatus(job.options.id) != null) { + job._reject(new Bottleneck3.prototype.BottleneckError(`A job with the same id already exists (id=${job.options.id})`)); + return false; + } else { + job.doReceive(); + return this._submitLock.schedule(this._addToQueue, job); + } + } + submit(...args) { + var cb, fn, job, options, ref, ref1, task; + if (typeof args[0] === "function") { + ref = args, [fn, ...args] = ref, [cb] = splice.call(args, -1); + options = parser$5.load({}, this.jobDefaults); + } else { + ref1 = args, [options, fn, ...args] = ref1, [cb] = splice.call(args, -1); + options = parser$5.load(options, this.jobDefaults); + } + task = (...args2) => { + return new this.Promise(function(resolve2, reject) { + return fn(...args2, function(...args3) { + return (args3[0] != null ? reject : resolve2)(args3); + }); + }); + }; + job = new Job$1(task, args, options, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); + job.promise.then(function(args2) { + return typeof cb === "function" ? cb(...args2) : void 0; + }).catch(function(args2) { + if (Array.isArray(args2)) { + return typeof cb === "function" ? cb(...args2) : void 0; + } else { + return typeof cb === "function" ? cb(args2) : void 0; + } + }); + return this._receive(job); + } + schedule(...args) { + var job, options, task; + if (typeof args[0] === "function") { + [task, ...args] = args; + options = {}; + } else { + [options, task, ...args] = args; + } + job = new Job$1(task, args, options, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); + this._receive(job); + return job.promise; + } + wrap(fn) { + var schedule, wrapped; + schedule = this.schedule.bind(this); + wrapped = function(...args) { + return schedule(fn.bind(this), ...args); + }; + wrapped.withOptions = function(options, ...args) { + return schedule(options, fn, ...args); + }; + return wrapped; + } + async updateSettings(options = {}) { + await this._store.__updateSettings__(parser$5.overwrite(options, this.storeDefaults)); + parser$5.overwrite(options, this.instanceDefaults, this); + return this; + } + currentReservoir() { + return this._store.__currentReservoir__(); + } + incrementReservoir(incr = 0) { + return this._store.__incrementReservoir__(incr); + } + } + Bottleneck3.default = Bottleneck3; + Bottleneck3.Events = Events$4; + Bottleneck3.version = Bottleneck3.prototype.version = require$$8.version; + Bottleneck3.strategy = Bottleneck3.prototype.strategy = { + LEAK: 1, + OVERFLOW: 2, + OVERFLOW_PRIORITY: 4, + BLOCK: 3 + }; + Bottleneck3.BottleneckError = Bottleneck3.prototype.BottleneckError = BottleneckError_1; + Bottleneck3.Group = Bottleneck3.prototype.Group = Group_1; + Bottleneck3.RedisConnection = Bottleneck3.prototype.RedisConnection = require$$2; + Bottleneck3.IORedisConnection = Bottleneck3.prototype.IORedisConnection = require$$3; + Bottleneck3.Batcher = Bottleneck3.prototype.Batcher = Batcher_1; + Bottleneck3.prototype.jobDefaults = { + priority: DEFAULT_PRIORITY$1, + weight: 1, + expiration: null, + id: "" + }; + Bottleneck3.prototype.storeDefaults = { + maxConcurrent: null, + minTime: 0, + highWater: null, + strategy: Bottleneck3.prototype.strategy.LEAK, + penalty: null, + reservoir: null, + reservoirRefreshInterval: null, + reservoirRefreshAmount: null, + reservoirIncreaseInterval: null, + reservoirIncreaseAmount: null, + reservoirIncreaseMaximum: null + }; + Bottleneck3.prototype.localStoreDefaults = { + Promise, + timeout: null, + heartbeatInterval: 250 + }; + Bottleneck3.prototype.redisStoreDefaults = { + Promise, + timeout: null, + heartbeatInterval: 5e3, + clientTimeout: 1e4, + Redis: null, + clientOptions: {}, + clusterNodes: null, + clearDatastore: false, + connection: null + }; + Bottleneck3.prototype.instanceDefaults = { + datastore: "local", + connection: null, + id: "", + rejectOnDrop: true, + trackDoneStatus: false, + Promise + }; + Bottleneck3.prototype.stopDefaults = { + enqueueErrorMessage: "This limiter has been stopped and cannot accept new jobs.", + dropWaitingJobs: true, + dropErrorMessage: "This limiter has been stopped." + }; + return Bottleneck3; + }).call(commonjsGlobal); + var Bottleneck_1 = Bottleneck2; + var lib = Bottleneck_1; + return lib; + })); + } +}); + +// node_modules/@actions/core/lib/core.js +var core_exports = {}; +__export(core_exports, { + ExitCode: () => ExitCode, + addPath: () => addPath, + debug: () => debug, + endGroup: () => endGroup, + error: () => error, + exportVariable: () => exportVariable, + getBooleanInput: () => getBooleanInput, + getIDToken: () => getIDToken, + getInput: () => getInput, + getMultilineInput: () => getMultilineInput, + getState: () => getState, + group: () => group, + info: () => info, + isDebug: () => isDebug, + markdownSummary: () => markdownSummary, + notice: () => notice, + platform: () => platform_exports, + saveState: () => saveState, + setCommandEcho: () => setCommandEcho, + setFailed: () => setFailed, + setOutput: () => setOutput, + setSecret: () => setSecret, + startGroup: () => startGroup, + summary: () => summary, + toPlatformPath: () => toPlatformPath, + toPosixPath: () => toPosixPath, + toWin32Path: () => toWin32Path, + warning: () => warning +}); + +// node_modules/@actions/core/lib/command.js +var os = __toESM(require("os"), 1); + +// node_modules/@actions/core/lib/utils.js +function toCommandValue(input) { + if (input === null || input === void 0) { + return ""; + } else if (typeof input === "string" || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} + +// node_modules/@actions/core/lib/command.js +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +function issue(name, message = "") { + issueCommand(name, {}, message); +} +var CMD_STRING = "::"; +var Command = class { + constructor(command, properties, message) { + if (!command) { + command = "missing.command"; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += " "; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } else { + cmdStr += ","; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +}; +function escapeData(s) { + return toCommandValue(s).replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A"); +} +function escapeProperty(s) { + return toCommandValue(s).replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C"); +} + +// node_modules/@actions/core/lib/file-command.js +var crypto = __toESM(require("crypto"), 1); +var fs = __toESM(require("fs"), 1); +var os2 = __toESM(require("os"), 1); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${toCommandValue(message)}${os2.EOL}`, { + encoding: "utf8" + }); +} +function prepareKeyValueMessage(key, value) { + const delimiter3 = `ghadelimiter_${crypto.randomUUID()}`; + const convertedValue = toCommandValue(value); + if (key.includes(delimiter3)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter3}"`); + } + if (convertedValue.includes(delimiter3)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter3}"`); + } + return `${key}<<${delimiter3}${os2.EOL}${convertedValue}${os2.EOL}${delimiter3}`; +} + +// node_modules/@actions/core/lib/core.js +var os5 = __toESM(require("os"), 1); +var path5 = __toESM(require("path"), 1); + +// node_modules/@actions/http-client/lib/index.js +var http = __toESM(require("http"), 1); +var https = __toESM(require("https"), 1); + +// node_modules/@actions/http-client/lib/proxy.js +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === "https:"; + if (checkBypass(reqUrl)) { + return void 0; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env["https_proxy"] || process.env["HTTPS_PROXY"]; + } else { + return process.env["http_proxy"] || process.env["HTTP_PROXY"]; + } + })(); + if (proxyVar) { + try { + return new DecodedURL(proxyVar); + } catch (_a) { + if (!proxyVar.startsWith("http://") && !proxyVar.startsWith("https://")) + return new DecodedURL(`http://${proxyVar}`); + } + } else { + return void 0; + } +} +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const reqHost = reqUrl.hostname; + if (isLoopbackAddress(reqHost)) { + return true; + } + const noProxy = process.env["no_proxy"] || process.env["NO_PROXY"] || ""; + if (!noProxy) { + return false; + } + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } else if (reqUrl.protocol === "http:") { + reqPort = 80; + } else if (reqUrl.protocol === "https:") { + reqPort = 443; + } + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === "number") { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + for (const upperNoProxyItem of noProxy.split(",").map((x) => x.trim().toUpperCase()).filter((x) => x)) { + if (upperNoProxyItem === "*" || upperReqHosts.some((x) => x === upperNoProxyItem || x.endsWith(`.${upperNoProxyItem}`) || upperNoProxyItem.startsWith(".") && x.endsWith(`${upperNoProxyItem}`))) { + return true; + } + } + return false; +} +function isLoopbackAddress(host) { + const hostLower = host.toLowerCase(); + return hostLower === "localhost" || hostLower.startsWith("127.") || hostLower.startsWith("[::1]") || hostLower.startsWith("[0:0:0:0:0:0:0:1]"); +} +var DecodedURL = class extends URL { + constructor(url, base) { + super(url, base); + this._decodedUsername = decodeURIComponent(super.username); + this._decodedPassword = decodeURIComponent(super.password); + } + get username() { + return this._decodedUsername; + } + get password() { + return this._decodedPassword; + } +}; + +// node_modules/@actions/http-client/lib/index.js +var tunnel = __toESM(require_tunnel2(), 1); +var import_undici = __toESM(require_undici(), 1); +var __awaiter = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var HttpCodes; +(function(HttpCodes2) { + HttpCodes2[HttpCodes2["OK"] = 200] = "OK"; + HttpCodes2[HttpCodes2["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes2[HttpCodes2["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes2[HttpCodes2["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes2[HttpCodes2["SeeOther"] = 303] = "SeeOther"; + HttpCodes2[HttpCodes2["NotModified"] = 304] = "NotModified"; + HttpCodes2[HttpCodes2["UseProxy"] = 305] = "UseProxy"; + HttpCodes2[HttpCodes2["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes2[HttpCodes2["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes2[HttpCodes2["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes2[HttpCodes2["BadRequest"] = 400] = "BadRequest"; + HttpCodes2[HttpCodes2["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes2[HttpCodes2["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes2[HttpCodes2["Forbidden"] = 403] = "Forbidden"; + HttpCodes2[HttpCodes2["NotFound"] = 404] = "NotFound"; + HttpCodes2[HttpCodes2["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes2[HttpCodes2["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes2[HttpCodes2["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes2[HttpCodes2["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes2[HttpCodes2["Conflict"] = 409] = "Conflict"; + HttpCodes2[HttpCodes2["Gone"] = 410] = "Gone"; + HttpCodes2[HttpCodes2["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes2[HttpCodes2["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes2[HttpCodes2["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes2[HttpCodes2["BadGateway"] = 502] = "BadGateway"; + HttpCodes2[HttpCodes2["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes2[HttpCodes2["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes || (HttpCodes = {})); +var Headers; +(function(Headers2) { + Headers2["Accept"] = "accept"; + Headers2["ContentType"] = "content-type"; +})(Headers || (Headers = {})); +var MediaTypes; +(function(MediaTypes2) { + MediaTypes2["ApplicationJson"] = "application/json"; +})(MediaTypes || (MediaTypes = {})); +var HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +var HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +var RetryableHttpVerbs = ["OPTIONS", "GET", "DELETE", "HEAD"]; +var ExponentialBackoffCeiling = 10; +var ExponentialBackoffTimeSlice = 5; +var HttpClientError = class _HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = "HttpClientError"; + this.statusCode = statusCode; + Object.setPrototypeOf(this, _HttpClientError.prototype); + } +}; +var HttpClientResponse = class { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve2) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on("data", (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on("end", () => { + resolve2(output.toString()); + }); + })); + }); + } + readBodyBuffer() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve2) => __awaiter(this, void 0, void 0, function* () { + const chunks = []; + this.message.on("data", (chunk) => { + chunks.push(chunk); + }); + this.message.on("end", () => { + resolve2(Buffer.concat(chunks)); + }); + })); + }); + } +}; +var HttpClient = class { + constructor(userAgent2, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = this._getUserAgentWithOrchestrationId(userAgent2); + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("OPTIONS", requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("GET", requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("DELETE", requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("POST", requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("PATCH", requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("PUT", requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request("HEAD", requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, additionalHeaders = {}) { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl_1, obj_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl_1, obj_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl_1, obj_1) { + return __awaiter(this, arguments, void 0, function* (requestUrl, obj, additionalHeaders = {}) { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultContentTypeHeader(additionalHeaders, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error("Client has already been disposed."); + } + const parsedUrl = new URL(requestUrl); + let info2 = this._prepareRequest(verb, parsedUrl, headers); + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info2, data); + if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler2 of this.handlers) { + if (handler2.canHandleAuthentication(response)) { + authenticationHandler = handler2; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info2, data); + } else { + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && HttpRedirectCodes.includes(response.message.statusCode) && this._allowRedirects && redirectsRemaining > 0) { + const redirectUrl = response.message.headers["location"]; + if (!redirectUrl) { + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === "https:" && parsedUrl.protocol !== parsedRedirectUrl.protocol && !this._allowRedirectDowngrade) { + throw new Error("Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true."); + } + yield response.readBody(); + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + if (header.toLowerCase() === "authorization") { + delete headers[header]; + } + } + } + info2 = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info2, data); + redirectsRemaining--; + } + if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) { + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info2, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve2, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } else if (!res) { + reject(new Error("Unknown error")); + } else { + resolve2(res); + } + } + this.requestRawWithCallback(info2, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info2, data, onResult) { + if (typeof data === "string") { + if (!info2.options.headers) { + info2.options.headers = {}; + } + info2.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8"); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info2.httpModule.request(info2.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(void 0, res); + }); + let socket; + req.on("socket", (sock) => { + socket = sock; + }); + req.setTimeout(this._socketTimeout || 3 * 6e4, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info2.options.path}`)); + }); + req.on("error", function(err) { + handleResult(err); + }); + if (data && typeof data === "string") { + req.write(data, "utf8"); + } + if (data && typeof data !== "string") { + data.on("close", function() { + req.end(); + }); + data.pipe(req); + } else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + getAgentDispatcher(serverUrl) { + const parsedUrl = new URL(serverUrl); + const proxyUrl = getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (!useProxy) { + return; + } + return this._getProxyAgentDispatcher(parsedUrl, proxyUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info2 = {}; + info2.parsedUrl = requestUrl; + const usingSsl = info2.parsedUrl.protocol === "https:"; + info2.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info2.options = {}; + info2.options.host = info2.parsedUrl.hostname; + info2.options.port = info2.parsedUrl.port ? parseInt(info2.parsedUrl.port) : defaultPort; + info2.options.path = (info2.parsedUrl.pathname || "") + (info2.parsedUrl.search || ""); + info2.options.method = method; + info2.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info2.options.headers["user-agent"] = this.userAgent; + } + info2.options.agent = this._getAgent(info2.parsedUrl); + if (this.handlers) { + for (const handler2 of this.handlers) { + handler2.prepareRequest(info2.options); + } + } + return info2; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + /** + * Gets an existing header value or returns a default. + * Handles converting number header values to strings since HTTP headers must be strings. + * Note: This returns string | string[] since some headers can have multiple values. + * For headers that must always be a single string (like Content-Type), use the + * specialized _getExistingOrDefaultContentTypeHeader method instead. + */ + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + const headerValue = lowercaseKeys(this.requestOptions.headers)[header]; + if (headerValue) { + clientHeader = typeof headerValue === "number" ? headerValue.toString() : headerValue; + } + } + const additionalValue = additionalHeaders[header]; + if (additionalValue !== void 0) { + return typeof additionalValue === "number" ? additionalValue.toString() : additionalValue; + } + if (clientHeader !== void 0) { + return clientHeader; + } + return _default; + } + /** + * Specialized version of _getExistingOrDefaultHeader for Content-Type header. + * Always returns a single string (not an array) since Content-Type should be a single value. + * Converts arrays to comma-separated strings and numbers to strings to ensure type safety. + * This was split from _getExistingOrDefaultHeader to provide stricter typing for callers + * that assign the result to places expecting a string (e.g., additionalHeaders[Headers.ContentType]). + */ + _getExistingOrDefaultContentTypeHeader(additionalHeaders, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + const headerValue = lowercaseKeys(this.requestOptions.headers)[Headers.ContentType]; + if (headerValue) { + if (typeof headerValue === "number") { + clientHeader = String(headerValue); + } else if (Array.isArray(headerValue)) { + clientHeader = headerValue.join(", "); + } else { + clientHeader = headerValue; + } + } + } + const additionalValue = additionalHeaders[Headers.ContentType]; + if (additionalValue !== void 0) { + if (typeof additionalValue === "number") { + return String(additionalValue); + } else if (Array.isArray(additionalValue)) { + return additionalValue.join(", "); + } else { + return additionalValue; + } + } + if (clientHeader !== void 0) { + return clientHeader; + } + return _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (!useProxy) { + agent = this._agent; + } + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === "https:"; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, (proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + }), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === "https:"; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + if (!agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + if (usingSsl && this._ignoreSslError) { + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _getProxyAgentDispatcher(parsedUrl, proxyUrl) { + let proxyAgent; + if (this._keepAlive) { + proxyAgent = this._proxyAgentDispatcher; + } + if (proxyAgent) { + return proxyAgent; + } + const usingSsl = parsedUrl.protocol === "https:"; + proxyAgent = new import_undici.ProxyAgent(Object.assign({ uri: proxyUrl.href, pipelining: !this._keepAlive ? 0 : 1 }, (proxyUrl.username || proxyUrl.password) && { + token: `Basic ${Buffer.from(`${proxyUrl.username}:${proxyUrl.password}`).toString("base64")}` + })); + this._proxyAgentDispatcher = proxyAgent; + if (usingSsl && this._ignoreSslError) { + proxyAgent.options = Object.assign(proxyAgent.options.requestTls || {}, { + rejectUnauthorized: false + }); + } + return proxyAgent; + } + _getUserAgentWithOrchestrationId(userAgent2) { + const baseUserAgent = userAgent2 || "actions/http-client"; + const orchId = process.env["ACTIONS_ORCHESTRATION_ID"]; + if (orchId) { + const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, "_"); + return `${baseUserAgent} actions_orchestration_id/${sanitizedId}`; + } + return baseUserAgent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise((resolve2) => setTimeout(() => resolve2(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve2, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + if (statusCode === HttpCodes.NotFound) { + resolve2(response); + } + function dateTimeDeserializer(key, value) { + if (typeof value === "string") { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } catch (err) { + } + if (statusCode > 299) { + let msg; + if (obj && obj.message) { + msg = obj.message; + } else if (contents && contents.length > 0) { + msg = contents; + } else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } else { + resolve2(response); + } + })); + }); + } +}; +var lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => (c[k.toLowerCase()] = obj[k], c), {}); + +// node_modules/@actions/http-client/lib/auth.js +var __awaiter2 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var BearerCredentialHandler = class { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error("The request has no headers"); + } + options.headers["Authorization"] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter2(this, void 0, void 0, function* () { + throw new Error("not implemented"); + }); + } +}; + +// node_modules/@actions/core/lib/oidc-utils.js +var __awaiter3 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var OidcClient = class _OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new HttpClient("actions/oidc-client", [new BearerCredentialHandler(_OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env["ACTIONS_ID_TOKEN_REQUEST_TOKEN"]; + if (!token) { + throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable"); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env["ACTIONS_ID_TOKEN_REQUEST_URL"]; + if (!runtimeUrl) { + throw new Error("Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable"); + } + return runtimeUrl; + } + static getCall(id_token_url) { + return __awaiter3(this, void 0, void 0, function* () { + var _a; + const httpclient = _OidcClient.createHttpClient(); + const res = yield httpclient.getJson(id_token_url).catch((error2) => { + throw new Error(`Failed to get ID Token. + + Error Code : ${error2.statusCode} + + Error Message: ${error2.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error("Response json body do not have ID Token field"); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter3(this, void 0, void 0, function* () { + try { + let id_token_url = _OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + debug(`ID token url is ${id_token_url}`); + const id_token = yield _OidcClient.getCall(id_token_url); + setSecret(id_token); + return id_token; + } catch (error2) { + throw new Error(`Error message: ${error2.message}`); + } + }); + } +}; + +// node_modules/@actions/core/lib/summary.js +var import_os = require("os"); +var import_fs = require("fs"); +var __awaiter4 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var { access, appendFile, writeFile } = import_fs.promises; +var SUMMARY_ENV_VAR = "GITHUB_STEP_SUMMARY"; +var Summary = class { + constructor() { + this._buffer = ""; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter4(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, import_fs.constants.R_OK | import_fs.constants.W_OK); + } catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs).map(([key, value]) => ` ${key}="${value}"`).join(""); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter4(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter4(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ""; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(import_os.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, lang && { lang }); + const element = this.wrap("pre", this.wrap("code", code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance */ - write(options) { - return __awaiter(this, void 0, void 0, function* () { - const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); - const filePath = yield this.filePath(); - const writeFunc = overwrite ? writeFile : appendFile; - yield writeFunc(filePath, this._buffer, { encoding: "utf8" }); - return this.emptyBuffer(); - }); + addList(items, ordered = false) { + const tag = ordered ? "ol" : "ul"; + const listItems = items.map((item) => this.wrap("li", item)).join(""); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); } /** - * Clears the summary buffer and wipes the summary file + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows * * @returns {Summary} summary instance */ - clear() { - return __awaiter(this, void 0, void 0, function* () { - return this.emptyBuffer().write({ overwrite: true }); + addTable(rows) { + const tableBody = rows.map((row) => { + const cells = row.map((cell) => { + if (typeof cell === "string") { + return this.wrap("td", cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? "th" : "td"; + const attrs = Object.assign(Object.assign({}, colspan && { colspan }), rowspan && { rowspan }); + return this.wrap(tag, data, attrs); + }).join(""); + return this.wrap("tr", cells); + }).join(""); + const element = this.wrap("table", tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap("details", this.wrap("summary", label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, width && { width }), height && { height }); + const element = this.wrap("img", null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ["h1", "h2", "h3", "h4", "h5", "h6"].includes(tag) ? tag : "h1"; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap("hr", null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap("br", null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, cite && { cite }); + const element = this.wrap("blockquote", text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap("a", text, { href }); + return this.addRaw(element).addEOL(); + } +}; +var _summary = new Summary(); +var markdownSummary = _summary; +var summary = _summary; + +// node_modules/@actions/core/lib/path-utils.js +var path = __toESM(require("path"), 1); +function toPosixPath(pth) { + return pth.replace(/[\\]/g, "/"); +} +function toWin32Path(pth) { + return pth.replace(/[/]/g, "\\"); +} +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} + +// node_modules/@actions/core/lib/platform.js +var platform_exports = {}; +__export(platform_exports, { + arch: () => arch, + getDetails: () => getDetails, + isLinux: () => isLinux, + isMacOS: () => isMacOS, + isWindows: () => isWindows, + platform: () => platform +}); +var import_os2 = __toESM(require("os"), 1); + +// node_modules/@actions/exec/lib/exec.js +var import_string_decoder = require("string_decoder"); + +// node_modules/@actions/exec/lib/toolrunner.js +var os3 = __toESM(require("os"), 1); +var events = __toESM(require("events"), 1); +var child = __toESM(require("child_process"), 1); +var path4 = __toESM(require("path"), 1); + +// node_modules/@actions/io/lib/io.js +var path3 = __toESM(require("path"), 1); + +// node_modules/@actions/io/lib/io-util.js +var fs2 = __toESM(require("fs"), 1); +var path2 = __toESM(require("path"), 1); +var __awaiter5 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var { chmod, copyFile, lstat, mkdir, open, readdir, rename, rm, rmdir, stat, symlink, unlink } = fs2.promises; +var IS_WINDOWS = process.platform === "win32"; +var READONLY = fs2.constants.O_RDONLY; +function exists(fsPath) { + return __awaiter5(this, void 0, void 0, function* () { + try { + yield stat(fsPath); + } catch (err) { + if (err.code === "ENOENT") { + return false; + } + throw err; + } + return true; + }); +} +function isRooted(p) { + p = normalizeSeparators(p); + if (!p) { + throw new Error('isRooted() parameter "p" cannot be empty'); + } + if (IS_WINDOWS) { + return p.startsWith("\\") || /^[A-Z]:/i.test(p); + } + return p.startsWith("/"); +} +function tryGetExecutablePath(filePath, extensions) { + return __awaiter5(this, void 0, void 0, function* () { + let stats = void 0; + try { + stats = yield stat(filePath); + } catch (err) { + if (err.code !== "ENOENT") { + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (IS_WINDOWS) { + const upperExt = path2.extname(filePath).toUpperCase(); + if (extensions.some((validExt) => validExt.toUpperCase() === upperExt)) { + return filePath; + } + } else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + const originalFilePath = filePath; + for (const extension of extensions) { + filePath = originalFilePath + extension; + stats = void 0; + try { + stats = yield stat(filePath); + } catch (err) { + if (err.code !== "ENOENT") { + console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); + } + } + if (stats && stats.isFile()) { + if (IS_WINDOWS) { + try { + const directory = path2.dirname(filePath); + const upperName = path2.basename(filePath).toUpperCase(); + for (const actualName of yield readdir(directory)) { + if (upperName === actualName.toUpperCase()) { + filePath = path2.join(directory, actualName); + break; + } + } + } catch (err) { + console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); + } + return filePath; + } else { + if (isUnixExecutable(stats)) { + return filePath; + } + } + } + } + return ""; + }); +} +function normalizeSeparators(p) { + p = p || ""; + if (IS_WINDOWS) { + p = p.replace(/\//g, "\\"); + return p.replace(/\\\\+/g, "\\"); + } + return p.replace(/\/\/+/g, "/"); +} +function isUnixExecutable(stats) { + return (stats.mode & 1) > 0 || (stats.mode & 8) > 0 && process.getgid !== void 0 && stats.gid === process.getgid() || (stats.mode & 64) > 0 && process.getuid !== void 0 && stats.uid === process.getuid(); +} + +// node_modules/@actions/io/lib/io.js +var __awaiter6 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function which(tool, check) { + return __awaiter6(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + if (check) { + const result = yield which(tool, false); + if (!result) { + if (IS_WINDOWS) { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); + } else { + throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); + } + } + return result; + } + const matches = yield findInPath(tool); + if (matches && matches.length > 0) { + return matches[0]; + } + return ""; + }); +} +function findInPath(tool) { + return __awaiter6(this, void 0, void 0, function* () { + if (!tool) { + throw new Error("parameter 'tool' is required"); + } + const extensions = []; + if (IS_WINDOWS && process.env["PATHEXT"]) { + for (const extension of process.env["PATHEXT"].split(path3.delimiter)) { + if (extension) { + extensions.push(extension); + } + } + } + if (isRooted(tool)) { + const filePath = yield tryGetExecutablePath(tool, extensions); + if (filePath) { + return [filePath]; + } + return []; + } + if (tool.includes(path3.sep)) { + return []; + } + const directories = []; + if (process.env.PATH) { + for (const p of process.env.PATH.split(path3.delimiter)) { + if (p) { + directories.push(p); + } + } + } + const matches = []; + for (const directory of directories) { + const filePath = yield tryGetExecutablePath(path3.join(directory, tool), extensions); + if (filePath) { + matches.push(filePath); + } + } + return matches; + }); +} + +// node_modules/@actions/exec/lib/toolrunner.js +var import_timers = require("timers"); +var __awaiter7 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); }); } - /** - * Returns the current summary buffer as a string - * - * @returns {string} string of summary buffer - */ - stringify() { - return this._buffer; + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var IS_WINDOWS2 = process.platform === "win32"; +var ToolRunner = class extends events.EventEmitter { + constructor(toolPath, args, options) { + super(); + if (!toolPath) { + throw new Error("Parameter 'toolPath' cannot be null or empty."); + } + this.toolPath = toolPath; + this.args = args || []; + this.options = options || {}; } - /** - * If the summary buffer is empty - * - * @returns {boolen} true if the buffer is empty - */ - isEmptyBuffer() { - return this._buffer.length === 0; + _debug(message) { + if (this.options.listeners && this.options.listeners.debug) { + this.options.listeners.debug(message); + } } - /** - * Resets the summary buffer without writing to summary file - * - * @returns {Summary} summary instance - */ - emptyBuffer() { - this._buffer = ""; - return this; + _getCommandString(options, noPrefix) { + const toolPath = this._getSpawnFileName(); + const args = this._getSpawnArgs(options); + let cmd = noPrefix ? "" : "[command]"; + if (IS_WINDOWS2) { + if (this._isCmdFile()) { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } else if (options.windowsVerbatimArguments) { + cmd += `"${toolPath}"`; + for (const a of args) { + cmd += ` ${a}`; + } + } else { + cmd += this._windowsQuoteCmdArg(toolPath); + for (const a of args) { + cmd += ` ${this._windowsQuoteCmdArg(a)}`; + } + } + } else { + cmd += toolPath; + for (const a of args) { + cmd += ` ${a}`; + } + } + return cmd; } - /** - * Adds raw text to the summary buffer - * - * @param {string} text content to add - * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) - * - * @returns {Summary} summary instance - */ - addRaw(text, addEOL = false) { - this._buffer += text; - return addEOL ? this.addEOL() : this; + _processLineBuffer(data, strBuffer, onLine) { + try { + let s = strBuffer + data.toString(); + let n = s.indexOf(os3.EOL); + while (n > -1) { + const line = s.substring(0, n); + onLine(line); + s = s.substring(n + os3.EOL.length); + n = s.indexOf(os3.EOL); + } + return s; + } catch (err) { + this._debug(`error processing line. Failed with error ${err}`); + return ""; + } } - /** - * Adds the operating system-specific end-of-line marker to the buffer - * - * @returns {Summary} summary instance - */ - addEOL() { - return this.addRaw(import_os.EOL); + _getSpawnFileName() { + if (IS_WINDOWS2) { + if (this._isCmdFile()) { + return process.env["COMSPEC"] || "cmd.exe"; + } + } + return this.toolPath; } - /** - * Adds an HTML codeblock to the summary buffer - * - * @param {string} code content to render within fenced code block - * @param {string} lang (optional) language to syntax highlight code - * - * @returns {Summary} summary instance - */ - addCodeBlock(code, lang) { - const attrs = Object.assign({}, lang && { lang }); - const element = this.wrap("pre", this.wrap("code", code), attrs); - return this.addRaw(element).addEOL(); + _getSpawnArgs(options) { + if (IS_WINDOWS2) { + if (this._isCmdFile()) { + let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; + for (const a of this.args) { + argline += " "; + argline += options.windowsVerbatimArguments ? a : this._windowsQuoteCmdArg(a); + } + argline += '"'; + return [argline]; + } + } + return this.args; } - /** - * Adds an HTML list to the summary buffer - * - * @param {string[]} items list of items to render - * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) - * - * @returns {Summary} summary instance - */ - addList(items, ordered = false) { - const tag = ordered ? "ol" : "ul"; - const listItems = items.map((item) => this.wrap("li", item)).join(""); - const element = this.wrap(tag, listItems); - return this.addRaw(element).addEOL(); + _endsWith(str, end) { + return str.endsWith(end); } - /** - * Adds an HTML table to the summary buffer - * - * @param {SummaryTableCell[]} rows table rows - * - * @returns {Summary} summary instance - */ - addTable(rows) { - const tableBody = rows.map((row) => { - const cells = row.map((cell) => { - if (typeof cell === "string") { - return this.wrap("td", cell); - } - const { header, data, colspan, rowspan } = cell; - const tag = header ? "th" : "td"; - const attrs = Object.assign(Object.assign({}, colspan && { colspan }), rowspan && { rowspan }); - return this.wrap(tag, data, attrs); - }).join(""); - return this.wrap("tr", cells); - }).join(""); - const element = this.wrap("table", tableBody); - return this.addRaw(element).addEOL(); + _isCmdFile() { + const upperToolPath = this.toolPath.toUpperCase(); + return this._endsWith(upperToolPath, ".CMD") || this._endsWith(upperToolPath, ".BAT"); } - /** - * Adds a collapsable HTML details element to the summary buffer - * - * @param {string} label text for the closed state - * @param {string} content collapsable content - * - * @returns {Summary} summary instance - */ - addDetails(label, content) { - const element = this.wrap("details", this.wrap("summary", label) + content); - return this.addRaw(element).addEOL(); + _windowsQuoteCmdArg(arg) { + if (!this._isCmdFile()) { + return this._uvQuoteCmdArg(arg); + } + if (!arg) { + return '""'; + } + const cmdSpecialChars = [ + " ", + " ", + "&", + "(", + ")", + "[", + "]", + "{", + "}", + "^", + "=", + ";", + "!", + "'", + "+", + ",", + "`", + "~", + "|", + "<", + ">", + '"' + ]; + let needsQuotes = false; + for (const char of arg) { + if (cmdSpecialChars.some((x) => x === char)) { + needsQuotes = true; + break; + } + } + if (!needsQuotes) { + return arg; + } + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === "\\") { + reverse += "\\"; + } else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += '"'; + } else { + quoteHit = false; + } + } + reverse += '"'; + return reverse.split("").reverse().join(""); } - /** - * Adds an HTML image tag to the summary buffer - * - * @param {string} src path to the image you to embed - * @param {string} alt text description of the image - * @param {SummaryImageOptions} options (optional) addition image attributes - * - * @returns {Summary} summary instance - */ - addImage(src, alt, options) { - const { width, height } = options || {}; - const attrs = Object.assign(Object.assign({}, width && { width }), height && { height }); - const element = this.wrap("img", null, Object.assign({ src, alt }, attrs)); - return this.addRaw(element).addEOL(); + _uvQuoteCmdArg(arg) { + if (!arg) { + return '""'; + } + if (!arg.includes(" ") && !arg.includes(" ") && !arg.includes('"')) { + return arg; + } + if (!arg.includes('"') && !arg.includes("\\")) { + return `"${arg}"`; + } + let reverse = '"'; + let quoteHit = true; + for (let i = arg.length; i > 0; i--) { + reverse += arg[i - 1]; + if (quoteHit && arg[i - 1] === "\\") { + reverse += "\\"; + } else if (arg[i - 1] === '"') { + quoteHit = true; + reverse += "\\"; + } else { + quoteHit = false; + } + } + reverse += '"'; + return reverse.split("").reverse().join(""); } - /** - * Adds an HTML section heading element - * - * @param {string} text heading text - * @param {number | string} [level=1] (optional) the heading level, default: 1 - * - * @returns {Summary} summary instance - */ - addHeading(text, level) { - const tag = `h${level}`; - const allowedTag = ["h1", "h2", "h3", "h4", "h5", "h6"].includes(tag) ? tag : "h1"; - const element = this.wrap(allowedTag, text); - return this.addRaw(element).addEOL(); + _cloneExecOptions(options) { + options = options || {}; + const result = { + cwd: options.cwd || process.cwd(), + env: options.env || process.env, + silent: options.silent || false, + windowsVerbatimArguments: options.windowsVerbatimArguments || false, + failOnStdErr: options.failOnStdErr || false, + ignoreReturnCode: options.ignoreReturnCode || false, + delay: options.delay || 1e4 + }; + result.outStream = options.outStream || process.stdout; + result.errStream = options.errStream || process.stderr; + return result; } - /** - * Adds an HTML thematic break (
) to the summary buffer - * - * @returns {Summary} summary instance - */ - addSeparator() { - const element = this.wrap("hr", null); - return this.addRaw(element).addEOL(); + _getSpawnOptions(options, toolPath) { + options = options || {}; + const result = {}; + result.cwd = options.cwd; + result.env = options.env; + result["windowsVerbatimArguments"] = options.windowsVerbatimArguments || this._isCmdFile(); + if (options.windowsVerbatimArguments) { + result.argv0 = `"${toolPath}"`; + } + return result; } /** - * Adds an HTML line break (
) to the summary buffer + * Exec a tool. + * Output will be streamed to the live console. + * Returns promise with return code * - * @returns {Summary} summary instance + * @param tool path to tool to exec + * @param options optional exec options. See ExecOptions + * @returns number */ - addBreak() { - const element = this.wrap("br", null); - return this.addRaw(element).addEOL(); + exec() { + return __awaiter7(this, void 0, void 0, function* () { + if (!isRooted(this.toolPath) && (this.toolPath.includes("/") || IS_WINDOWS2 && this.toolPath.includes("\\"))) { + this.toolPath = path4.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); + } + this.toolPath = yield which(this.toolPath, true); + return new Promise((resolve2, reject) => __awaiter7(this, void 0, void 0, function* () { + this._debug(`exec tool: ${this.toolPath}`); + this._debug("arguments:"); + for (const arg of this.args) { + this._debug(` ${arg}`); + } + const optionsNonNull = this._cloneExecOptions(this.options); + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os3.EOL); + } + const state = new ExecState(optionsNonNull, this.toolPath); + state.on("debug", (message) => { + this._debug(message); + }); + if (this.options.cwd && !(yield exists(this.options.cwd))) { + return reject(new Error(`The cwd: ${this.options.cwd} does not exist!`)); + } + const fileName = this._getSpawnFileName(); + const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); + let stdbuffer = ""; + if (cp.stdout) { + cp.stdout.on("data", (data) => { + if (this.options.listeners && this.options.listeners.stdout) { + this.options.listeners.stdout(data); + } + if (!optionsNonNull.silent && optionsNonNull.outStream) { + optionsNonNull.outStream.write(data); + } + stdbuffer = this._processLineBuffer(data, stdbuffer, (line) => { + if (this.options.listeners && this.options.listeners.stdline) { + this.options.listeners.stdline(line); + } + }); + }); + } + let errbuffer = ""; + if (cp.stderr) { + cp.stderr.on("data", (data) => { + state.processStderr = true; + if (this.options.listeners && this.options.listeners.stderr) { + this.options.listeners.stderr(data); + } + if (!optionsNonNull.silent && optionsNonNull.errStream && optionsNonNull.outStream) { + const s = optionsNonNull.failOnStdErr ? optionsNonNull.errStream : optionsNonNull.outStream; + s.write(data); + } + errbuffer = this._processLineBuffer(data, errbuffer, (line) => { + if (this.options.listeners && this.options.listeners.errline) { + this.options.listeners.errline(line); + } + }); + }); + } + cp.on("error", (err) => { + state.processError = err.message; + state.processExited = true; + state.processClosed = true; + state.CheckComplete(); + }); + cp.on("exit", (code) => { + state.processExitCode = code; + state.processExited = true; + this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); + state.CheckComplete(); + }); + cp.on("close", (code) => { + state.processExitCode = code; + state.processExited = true; + state.processClosed = true; + this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); + state.CheckComplete(); + }); + state.on("done", (error2, exitCode) => { + if (stdbuffer.length > 0) { + this.emit("stdline", stdbuffer); + } + if (errbuffer.length > 0) { + this.emit("errline", errbuffer); + } + cp.removeAllListeners(); + if (error2) { + reject(error2); + } else { + resolve2(exitCode); + } + }); + if (this.options.input) { + if (!cp.stdin) { + throw new Error("child process missing stdin"); + } + cp.stdin.end(this.options.input); + } + })); + }); } - /** - * Adds an HTML blockquote to the summary buffer - * - * @param {string} text quote text - * @param {string} cite (optional) citation url - * - * @returns {Summary} summary instance - */ - addQuote(text, cite) { - const attrs = Object.assign({}, cite && { cite }); - const element = this.wrap("blockquote", text, attrs); - return this.addRaw(element).addEOL(); +}; +function argStringToArray(argString) { + const args = []; + let inQuotes = false; + let escaped = false; + let arg = ""; + function append(c) { + if (escaped && c !== '"') { + arg += "\\"; + } + arg += c; + escaped = false; + } + for (let i = 0; i < argString.length; i++) { + const c = argString.charAt(i); + if (c === '"') { + if (!escaped) { + inQuotes = !inQuotes; + } else { + append(c); + } + continue; + } + if (c === "\\" && escaped) { + append(c); + continue; + } + if (c === "\\" && inQuotes) { + escaped = true; + continue; + } + if (c === " " && !inQuotes) { + if (arg.length > 0) { + args.push(arg); + arg = ""; + } + continue; + } + append(c); + } + if (arg.length > 0) { + args.push(arg.trim()); } - /** - * Adds an HTML anchor tag to the summary buffer - * - * @param {string} text link text/content - * @param {string} href hyperlink - * - * @returns {Summary} summary instance - */ - addLink(text, href) { - const element = this.wrap("a", text, { href }); - return this.addRaw(element).addEOL(); + return args; +} +var ExecState = class _ExecState extends events.EventEmitter { + constructor(options, toolPath) { + super(); + this.processClosed = false; + this.processError = ""; + this.processExitCode = 0; + this.processExited = false; + this.processStderr = false; + this.delay = 1e4; + this.done = false; + this.timeout = null; + if (!toolPath) { + throw new Error("toolPath must not be empty"); + } + this.options = options; + this.toolPath = toolPath; + if (options.delay) { + this.delay = options.delay; + } + } + CheckComplete() { + if (this.done) { + return; + } + if (this.processClosed) { + this._setResult(); + } else if (this.processExited) { + this.timeout = (0, import_timers.setTimeout)(_ExecState.HandleTimeout, this.delay, this); + } + } + _debug(message) { + this.emit("debug", message); + } + _setResult() { + let error2; + if (this.processExited) { + if (this.processError) { + error2 = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); + } else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { + error2 = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); + } else if (this.processStderr && this.options.failOnStdErr) { + error2 = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); + } + } + if (this.timeout) { + clearTimeout(this.timeout); + this.timeout = null; + } + this.done = true; + this.emit("done", error2, this.processExitCode); + } + static HandleTimeout(state) { + if (state.done) { + return; + } + if (!state.processClosed && state.processExited) { + const message = `The STDIO streams did not close within ${state.delay / 1e3} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; + state._debug(message); + } + state._setResult(); } }; -var _summary = new Summary(); - -// node_modules/@actions/core/lib/platform.js -var import_os2 = __toESM(require("os"), 1); - -// node_modules/@actions/io/lib/io-util.js -var fs2 = __toESM(require("fs"), 1); -var { chmod, copyFile, lstat, mkdir, open, readdir, rename, rm, rmdir, stat, symlink, unlink } = fs2.promises; -var IS_WINDOWS = process.platform === "win32"; -var READONLY = fs2.constants.O_RDONLY; -// node_modules/@actions/exec/lib/toolrunner.js -var IS_WINDOWS2 = process.platform === "win32"; +// node_modules/@actions/exec/lib/exec.js +var __awaiter8 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function exec(commandLine, args, options) { + return __awaiter8(this, void 0, void 0, function* () { + const commandArgs = argStringToArray(commandLine); + if (commandArgs.length === 0) { + throw new Error(`Parameter 'commandLine' cannot be null or empty.`); + } + const toolPath = commandArgs[0]; + args = commandArgs.slice(1).concat(args || []); + const runner = new ToolRunner(toolPath, args, options); + return runner.exec(); + }); +} +function getExecOutput(commandLine, args, options) { + return __awaiter8(this, void 0, void 0, function* () { + var _a, _b; + let stdout = ""; + let stderr = ""; + const stdoutDecoder = new import_string_decoder.StringDecoder("utf8"); + const stderrDecoder = new import_string_decoder.StringDecoder("utf8"); + const originalStdoutListener = (_a = options === null || options === void 0 ? void 0 : options.listeners) === null || _a === void 0 ? void 0 : _a.stdout; + const originalStdErrListener = (_b = options === null || options === void 0 ? void 0 : options.listeners) === null || _b === void 0 ? void 0 : _b.stderr; + const stdErrListener = (data) => { + stderr += stderrDecoder.write(data); + if (originalStdErrListener) { + originalStdErrListener(data); + } + }; + const stdOutListener = (data) => { + stdout += stdoutDecoder.write(data); + if (originalStdoutListener) { + originalStdoutListener(data); + } + }; + const listeners = Object.assign(Object.assign({}, options === null || options === void 0 ? void 0 : options.listeners), { stdout: stdOutListener, stderr: stdErrListener }); + const exitCode = yield exec(commandLine, args, Object.assign(Object.assign({}, options), { listeners })); + stdout += stdoutDecoder.end(); + stderr += stderrDecoder.end(); + return { + exitCode, + stdout, + stderr + }; + }); +} // node_modules/@actions/core/lib/platform.js +var __awaiter9 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var getWindowsInfo = () => __awaiter9(void 0, void 0, void 0, function* () { + const { stdout: version2 } = yield getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', void 0, { + silent: true + }); + const { stdout: name } = yield getExecOutput('powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', void 0, { + silent: true + }); + return { + name: name.trim(), + version: version2.trim() + }; +}); +var getMacOsInfo = () => __awaiter9(void 0, void 0, void 0, function* () { + var _a, _b, _c, _d; + const { stdout } = yield getExecOutput("sw_vers", void 0, { + silent: true + }); + const version2 = (_b = (_a = stdout.match(/ProductVersion:\s*(.+)/)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : ""; + const name = (_d = (_c = stdout.match(/ProductName:\s*(.+)/)) === null || _c === void 0 ? void 0 : _c[1]) !== null && _d !== void 0 ? _d : ""; + return { + name, + version: version2 + }; +}); +var getLinuxInfo = () => __awaiter9(void 0, void 0, void 0, function* () { + const { stdout } = yield getExecOutput("lsb_release", ["-i", "-r", "-s"], { + silent: true + }); + const [name, version2] = stdout.trim().split("\n"); + return { + name, + version: version2 + }; +}); var platform = import_os2.default.platform(); var arch = import_os2.default.arch(); +var isWindows = platform === "win32"; +var isMacOS = platform === "darwin"; +var isLinux = platform === "linux"; +function getDetails() { + return __awaiter9(this, void 0, void 0, function* () { + return Object.assign(Object.assign({}, yield isWindows ? getWindowsInfo() : isMacOS ? getMacOsInfo() : getLinuxInfo()), { + platform, + arch, + isWindows, + isMacOS, + isLinux + }); + }); +} // node_modules/@actions/core/lib/core.js +var __awaiter10 = function(thisArg, _arguments, P, generator) { + function adopt(value) { + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); + }); + } + return new (P || (P = Promise))(function(resolve2, reject) { + function fulfilled(value) { + try { + step(generator.next(value)); + } catch (e) { + reject(e); + } + } + function rejected(value) { + try { + step(generator["throw"](value)); + } catch (e) { + reject(e); + } + } + function step(result) { + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); + } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; var ExitCode; (function(ExitCode2) { ExitCode2[ExitCode2["Success"] = 0] = "Success"; ExitCode2[ExitCode2["Failure"] = 1] = "Failure"; })(ExitCode || (ExitCode = {})); +function exportVariable(name, val) { + const convertedVal = toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env["GITHUB_ENV"] || ""; + if (filePath) { + return issueFileCommand("ENV", prepareKeyValueMessage(name, val)); + } + issueCommand("set-env", { name }, convertedVal); +} +function setSecret(secret) { + issueCommand("add-mask", {}, secret); +} +function addPath(inputPath) { + const filePath = process.env["GITHUB_PATH"] || ""; + if (filePath) { + issueFileCommand("PATH", inputPath); + } else { + issueCommand("add-path", {}, inputPath); + } + process.env["PATH"] = `${inputPath}${path5.delimiter}${process.env["PATH"]}`; +} function getInput(name, options) { const val = process.env[`INPUT_${name.replace(/ /g, "_").toUpperCase()}`] || ""; if (options && options.required && !val) { @@ -19853,18 +22891,42 @@ function getInput(name, options) { } return val.trim(); } +function getMultilineInput(name, options) { + const inputs = getInput(name, options).split("\n").filter((x) => x !== ""); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map((input) => input.trim()); +} +function getBooleanInput(name, options) { + const trueValue = ["true", "True", "TRUE"]; + const falseValue = ["false", "False", "FALSE"]; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name} +Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} function setOutput(name, value) { const filePath = process.env["GITHUB_OUTPUT"] || ""; if (filePath) { return issueFileCommand("OUTPUT", prepareKeyValueMessage(name, value)); } - process.stdout.write(os4.EOL); + process.stdout.write(os5.EOL); issueCommand("set-output", { name }, toCommandValue(value)); } +function setCommandEcho(enabled) { + issue("echo", enabled ? "on" : "off"); +} function setFailed(message) { process.exitCode = ExitCode.Failure; error(message); } +function isDebug() { + return process.env["RUNNER_DEBUG"] === "1"; +} function debug(message) { issueCommand("debug", {}, message); } @@ -19874,8 +22936,44 @@ function error(message, properties = {}) { function warning(message, properties = {}) { issueCommand("warning", toCommandProperties(properties), message instanceof Error ? message.toString() : message); } +function notice(message, properties = {}) { + issueCommand("notice", toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} function info(message) { - process.stdout.write(message + os4.EOL); + process.stdout.write(message + os5.EOL); +} +function startGroup(name) { + issue("group", name); +} +function endGroup() { + issue("endgroup"); +} +function group(name, fn) { + return __awaiter10(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } finally { + endGroup(); + } + return result; + }); +} +function saveState(name, value) { + const filePath = process.env["GITHUB_STATE"] || ""; + if (filePath) { + return issueFileCommand("STATE", prepareKeyValueMessage(name, value)); + } + issueCommand("save-state", { name }, toCommandValue(value)); +} +function getState(name) { + return process.env[`STATE_${name}`] || ""; +} +function getIDToken(aud) { + return __awaiter10(this, void 0, void 0, function* () { + return yield OidcClient.getIDToken(aud); + }); } // node_modules/@actions/github/lib/context.js @@ -19892,8 +22990,8 @@ var Context = class { if ((0, import_fs2.existsSync)(process.env.GITHUB_EVENT_PATH)) { this.payload = JSON.parse((0, import_fs2.readFileSync)(process.env.GITHUB_EVENT_PATH, { encoding: "utf8" })); } else { - const path = process.env.GITHUB_EVENT_PATH; - process.stdout.write(`GITHUB_EVENT_PATH ${path} does not exist${import_os3.EOL}`); + const path6 = process.env.GITHUB_EVENT_PATH; + process.stdout.write(`GITHUB_EVENT_PATH ${path6} does not exist${import_os3.EOL}`); } } this.eventName = process.env.GITHUB_EVENT_NAME; @@ -19932,13 +23030,13 @@ var Context = class { // node_modules/@actions/github/lib/internal/utils.js var httpClient = __toESM(require_lib(), 1); var import_undici2 = __toESM(require_undici(), 1); -var __awaiter2 = function(thisArg, _arguments, P, generator) { +var __awaiter11 = function(thisArg, _arguments, P, generator) { function adopt(value) { - return value instanceof P ? value : new P(function(resolve) { - resolve(value); + return value instanceof P ? value : new P(function(resolve2) { + resolve2(value); }); } - return new (P || (P = Promise))(function(resolve, reject) { + return new (P || (P = Promise))(function(resolve2, reject) { function fulfilled(value) { try { step(generator.next(value)); @@ -19954,7 +23052,7 @@ var __awaiter2 = function(thisArg, _arguments, P, generator) { } } function step(result) { - result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); + result.done ? resolve2(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); @@ -19977,7 +23075,7 @@ function getProxyAgentDispatcher(destinationUrl) { } function getProxyFetch(destinationUrl) { const httpDispatcher = getProxyAgentDispatcher(destinationUrl); - const proxyFetch = (url, opts) => __awaiter2(this, void 0, void 0, function* () { + const proxyFetch = (url, opts) => __awaiter11(this, void 0, void 0, function* () { return (0, import_undici2.fetch)(url, Object.assign(Object.assign({}, opts), { dispatcher: httpDispatcher })); }); return proxyFetch; @@ -19985,6 +23083,19 @@ function getProxyFetch(destinationUrl) { function getApiBaseUrl() { return process.env["GITHUB_API_URL"] || "https://api.github.com"; } +function getUserAgentWithOrchestrationId(baseUserAgent) { + var _a; + const orchId = (_a = process.env["ACTIONS_ORCHESTRATION_ID"]) === null || _a === void 0 ? void 0 : _a.trim(); + if (orchId) { + const sanitizedId = orchId.replace(/[^a-z0-9_.-]/gi, "_"); + const tag = `actions_orchestration_id/${sanitizedId}`; + if (baseUserAgent === null || baseUserAgent === void 0 ? void 0 : baseUserAgent.includes(tag)) + return baseUserAgent; + const ua = baseUserAgent ? `${baseUserAgent} ` : ""; + return `${ua}${tag}`; + } + return baseUserAgent; +} // node_modules/universal-user-agent/index.js function getUserAgent() { @@ -20117,7 +23228,7 @@ var DEFAULTS = { format: "" } }; -function lowercaseKeys(object) { +function lowercaseKeys2(object) { if (!object) { return {}; } @@ -20161,7 +23272,7 @@ function merge(defaults2, route, options) { } else { options = Object.assign({}, route); } - options.headers = lowercaseKeys(options.headers); + options.headers = lowercaseKeys2(options.headers); removeUndefinedProperties(options); removeUndefinedProperties(options.headers); const mergedOptions = mergeDeep(defaults2 || {}, options); @@ -20825,8 +23936,8 @@ function withCustomRequest(customRequest) { // node_modules/@octokit/auth-token/dist-bundle/index.js var b64url = "(?:[a-zA-Z0-9_-]+)"; -var sep = "\\."; -var jwtRE = new RegExp(`^${b64url}${sep}${b64url}${sep}${b64url}$`); +var sep3 = "\\."; +var jwtRE = new RegExp(`^${b64url}${sep3}${b64url}${sep3}${b64url}$`); var isJWT = jwtRE.test.bind(jwtRE); async function auth(token) { const isApp = isJWT(token); @@ -23573,6 +26684,10 @@ function getOctokitOptions(token, options) { if (auth2) { opts.auth = auth2; } + const userAgent2 = getUserAgentWithOrchestrationId(opts.userAgent); + if (userAgent2) { + opts.userAgent = userAgent2; + } return opts; } @@ -23586,6 +26701,372 @@ function getOctokit(token, options, ...additionalPlugins) { // package.json var version = "1.3.3"; +// node_modules/@octokit/plugin-retry/dist-bundle/index.js +var import_light = __toESM(require_light(), 1); +var VERSION7 = "0.0.0-development"; +function isRequestError(error2) { + return error2.request !== void 0; +} +async function errorRequest(state, octokit, error2, options) { + if (!isRequestError(error2) || !error2?.request.request) { + throw error2; + } + if (error2.status >= 400 && !state.doNotRetry.includes(error2.status)) { + const retries = options.request.retries != null ? options.request.retries : state.retries; + const retryAfter = Math.pow((options.request.retryCount || 0) + 1, 2); + throw octokit.retry.retryRequest(error2, retries, retryAfter); + } + throw error2; +} +async function wrapRequest(state, octokit, request2, options) { + const limiter = new import_light.default(); + limiter.on("failed", function(error2, info2) { + const maxRetries = ~~error2.request.request?.retries; + const after = ~~error2.request.request?.retryAfter; + options.request.retryCount = info2.retryCount + 1; + if (maxRetries > info2.retryCount) { + return after * state.retryAfterBaseValue; + } + }); + return limiter.schedule( + requestWithGraphqlErrorHandling.bind(null, state, octokit, request2), + options + ); +} +async function requestWithGraphqlErrorHandling(state, octokit, request2, options) { + const response = await request2(options); + if (response.data && response.data.errors && response.data.errors.length > 0 && /Something went wrong while executing your query/.test( + response.data.errors[0].message + )) { + const error2 = new RequestError(response.data.errors[0].message, 500, { + request: options, + response + }); + return errorRequest(state, octokit, error2, options); + } + return response; +} +function retry(octokit, octokitOptions) { + const state = Object.assign( + { + enabled: true, + retryAfterBaseValue: 1e3, + doNotRetry: [400, 401, 403, 404, 410, 422, 451], + retries: 3 + }, + octokitOptions.retry + ); + const retryPlugin = { + retry: { + retryRequest: (error2, retries, retryAfter) => { + error2.request.request = Object.assign({}, error2.request.request, { + retries, + retryAfter + }); + return error2; + } + } + }; + if (state.enabled) { + octokit.hook.error("request", errorRequest.bind(null, state, retryPlugin)); + octokit.hook.wrap("request", wrapRequest.bind(null, state, retryPlugin)); + } + return retryPlugin; +} +retry.VERSION = VERSION7; + +// node_modules/@octokit/plugin-throttling/dist-bundle/index.js +var import_light2 = __toESM(require_light(), 1); +var VERSION8 = "0.0.0-development"; +var noop3 = () => Promise.resolve(); +function wrapRequest2(state, request2, options) { + return state.retryLimiter.schedule(doRequest, state, request2, options); +} +async function doRequest(state, request2, options) { + const { pathname } = new URL(options.url, "http://github.test"); + const isAuth = isAuthRequest(options.method, pathname); + const isWrite = !isAuth && options.method !== "GET" && options.method !== "HEAD"; + const isSearch = options.method === "GET" && pathname.startsWith("/search/"); + const isGraphQL = pathname.startsWith("/graphql"); + const retryCount = ~~request2.retryCount; + const jobOptions = retryCount > 0 ? { priority: 0, weight: 0 } : {}; + if (state.clustering) { + jobOptions.expiration = 1e3 * 60; + } + if (isWrite || isGraphQL) { + await state.write.key(state.id).schedule(jobOptions, noop3); + } + if (isWrite && state.triggersNotification(pathname)) { + await state.notifications.key(state.id).schedule(jobOptions, noop3); + } + if (isSearch) { + await state.search.key(state.id).schedule(jobOptions, noop3); + } + const req = (isAuth ? state.auth : state.global).key(state.id).schedule(jobOptions, request2, options); + if (isGraphQL) { + const res = await req; + if (res.data.errors != null && res.data.errors.some((error2) => error2.type === "RATE_LIMITED")) { + const error2 = Object.assign(new Error("GraphQL Rate Limit Exceeded"), { + response: res, + data: res.data + }); + throw error2; + } + } + return req; +} +function isAuthRequest(method, pathname) { + return method === "PATCH" && // https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-a-scoped-access-token + /^\/applications\/[^/]+\/token\/scoped$/.test(pathname) || method === "POST" && // https://docs.github.com/en/rest/apps/oauth-applications?apiVersion=2022-11-28#reset-a-token + (/^\/applications\/[^/]+\/token$/.test(pathname) || // https://docs.github.com/en/rest/apps/apps?apiVersion=2022-11-28#create-an-installation-access-token-for-an-app + /^\/app\/installations\/[^/]+\/access_tokens$/.test(pathname) || // https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps + pathname === "/login/oauth/access_token"); +} +var triggers_notification_paths_default = [ + "/orgs/{org}/invitations", + "/orgs/{org}/invitations/{invitation_id}", + "/orgs/{org}/teams/{team_slug}/discussions", + "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", + "/repos/{owner}/{repo}/collaborators/{username}", + "/repos/{owner}/{repo}/commits/{commit_sha}/comments", + "/repos/{owner}/{repo}/issues", + "/repos/{owner}/{repo}/issues/{issue_number}/comments", + "/repos/{owner}/{repo}/issues/{issue_number}/sub_issue", + "/repos/{owner}/{repo}/issues/{issue_number}/sub_issues/priority", + "/repos/{owner}/{repo}/pulls", + "/repos/{owner}/{repo}/pulls/{pull_number}/comments", + "/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies", + "/repos/{owner}/{repo}/pulls/{pull_number}/merge", + "/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", + "/repos/{owner}/{repo}/pulls/{pull_number}/reviews", + "/repos/{owner}/{repo}/releases", + "/teams/{team_id}/discussions", + "/teams/{team_id}/discussions/{discussion_number}/comments" +]; +function routeMatcher(paths) { + const regexes = paths.map( + (path6) => path6.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/") + ); + const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`; + return new RegExp(regex2, "i"); +} +var regex = routeMatcher(triggers_notification_paths_default); +var triggersNotification = regex.test.bind(regex); +var groups = {}; +var createGroups = function(Bottleneck2, common) { + groups.global = new Bottleneck2.Group({ + id: "octokit-global", + maxConcurrent: 10, + ...common + }); + groups.auth = new Bottleneck2.Group({ + id: "octokit-auth", + maxConcurrent: 1, + ...common + }); + groups.search = new Bottleneck2.Group({ + id: "octokit-search", + maxConcurrent: 1, + minTime: 2e3, + ...common + }); + groups.write = new Bottleneck2.Group({ + id: "octokit-write", + maxConcurrent: 1, + minTime: 1e3, + ...common + }); + groups.notifications = new Bottleneck2.Group({ + id: "octokit-notifications", + maxConcurrent: 1, + minTime: 3e3, + ...common + }); +}; +function throttling(octokit, octokitOptions) { + const { + enabled = true, + Bottleneck: Bottleneck2 = import_light2.default, + id = "no-id", + timeout = 1e3 * 60 * 2, + // Redis TTL: 2 minutes + connection + } = octokitOptions.throttle || {}; + if (!enabled) { + return {}; + } + const common = { timeout }; + if (typeof connection !== "undefined") { + common.connection = connection; + } + const state = Object.assign( + { + clustering: connection != null, + triggersNotification, + fallbackSecondaryRateRetryAfter: 60, + retryAfterBaseValue: 1e3, + id + }, + octokitOptions.throttle + ); + if (typeof state.onSecondaryRateLimit !== "function" || typeof state.onRateLimit !== "function") { + throw new Error(`octokit/plugin-throttling error: + You must pass the onSecondaryRateLimit and onRateLimit error handlers. + See https://octokit.github.io/rest.js/#throttling + + const octokit = new Octokit({ + throttle: { + onSecondaryRateLimit: (retryAfter, options) => {/* ... */}, + onRateLimit: (retryAfter, options) => {/* ... */} + } + }) + `); + } + let initialized = false; + const initializeBottleneck = () => { + if (initialized) { + return; + } + initialized = true; + if (groups.global == null) { + createGroups(Bottleneck2, common); + } + state.global = state.global ?? groups.global; + state.auth = state.auth ?? groups.auth; + state.search = state.search ?? groups.search; + state.write = state.write ?? groups.write; + state.notifications = state.notifications ?? groups.notifications; + state.retryLimiter = state.retryLimiter ?? new Bottleneck2(); + const events2 = {}; + const emitter = new Bottleneck2.Events(events2); + events2.on("secondary-limit", state.onSecondaryRateLimit); + events2.on("rate-limit", state.onRateLimit); + events2.on( + "error", + (e) => octokit.log.warn("Error in throttling-plugin limit handler", e) + ); + state.retryLimiter.on("failed", async function(error2, info2) { + const [state2, request2, options] = info2.args; + const { pathname } = new URL(options.url, "http://github.test"); + const shouldRetryGraphQL = pathname.startsWith("/graphql") && error2.status !== 401; + if (!(shouldRetryGraphQL || error2.status === 403 || error2.status === 429)) { + return; + } + const retryCount = ~~request2.retryCount; + request2.retryCount = retryCount; + options.request.retryCount = retryCount; + const { wantRetry, retryAfter = 0 } = await (async function() { + if (/\bsecondary rate\b/i.test(error2.message)) { + const retryAfter2 = Number(error2.response.headers["retry-after"]) || state2.fallbackSecondaryRateRetryAfter; + const wantRetry2 = await emitter.trigger( + "secondary-limit", + retryAfter2, + options, + octokit, + retryCount + ); + return { wantRetry: wantRetry2, retryAfter: retryAfter2 }; + } + if (error2.response.headers != null && error2.response.headers["x-ratelimit-remaining"] === "0" || (error2.response.data?.errors ?? []).some( + (error22) => error22.type === "RATE_LIMITED" + )) { + const rateLimitReset = new Date( + ~~error2.response.headers["x-ratelimit-reset"] * 1e3 + ).getTime(); + const retryAfter2 = Math.max( + // Add one second so we retry _after_ the reset time + // https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#exceeding-the-rate-limit + Math.ceil((rateLimitReset - Date.now()) / 1e3) + 1, + 0 + ); + const wantRetry2 = await emitter.trigger( + "rate-limit", + retryAfter2, + options, + octokit, + retryCount + ); + return { wantRetry: wantRetry2, retryAfter: retryAfter2 }; + } + return {}; + })(); + if (wantRetry) { + request2.retryCount++; + return retryAfter * state2.retryAfterBaseValue; + } + }); + }; + octokit.hook.wrap("request", (request2, options) => { + initializeBottleneck(); + return wrapRequest2(state, request2, options); + }); + return {}; +} +throttling.VERSION = VERSION8; +throttling.triggersNotification = triggersNotification; + +// src/octokit-client.ts +var MAX_RATE_LIMIT_RETRIES = 3; +var DO_NOT_RETRY_STATUS_CODES = [400, 401, 403, 404, 410, 422, 451]; +var NO_RETRY_REQUEST_OPTIONS = { retries: 0 }; +function isTransientError(error2) { + const status = error2?.status; + return typeof status === "number" && status >= 400 && !DO_NOT_RETRY_STATUS_CODES.includes(status); +} +function shouldRetryAfterRateLimit(retryCount) { + return retryCount < MAX_RATE_LIMIT_RETRIES; +} +function rateLimitHandler(kind, log) { + return (retryAfter, request2, _octokit, retryCount) => { + const willRetry = shouldRetryAfterRateLimit(retryCount); + log( + willRetry ? `${kind} hit for ${request2.method} ${request2.url}, retry ${retryCount + 1} after ${retryAfter}s` : `${kind} hit for ${request2.method} ${request2.url}, giving up after ${retryCount} retries` + ); + return willRetry; + }; +} +function buildOctokitOptions(log = warning) { + return { + retry: { doNotRetry: DO_NOT_RETRY_STATUS_CODES }, + throttle: { + onRateLimit: rateLimitHandler("Rate limit", log), + onSecondaryRateLimit: rateLimitHandler("Secondary rate limit", log) + } + }; +} +function createOctokit(token, getOctokit2 = getOctokit) { + return getOctokit2(token, buildOctokitOptions(), retry, throttling); +} + +// src/wait-for-run.ts +var ACTIVE_RUN_STATUSES = ["in_progress", "queued", "waiting", "pending"]; +var TIMED_OUT = "timed_out"; +async function waitForRunCompletion({ + getStatus, + timeoutSeconds, + intervalSeconds, + log = core_exports, + sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)), + now = Date.now +}) { + const startTime = now(); + let runStatus = "in_progress"; + while (ACTIVE_RUN_STATUSES.includes(runStatus)) { + if ((now() - startTime) / 1e3 > timeoutSeconds) return TIMED_OUT; + await sleep(intervalSeconds * 1e3); + try { + runStatus = await getStatus(); + log.info(`\u{1F504} Current run status: ${runStatus}`); + } catch (error2) { + if (!isTransientError(error2)) throw error2; + log.warning( + `\u26A0\uFE0F Failed to get run status, will try again: ${error2 instanceof Error ? error2.message : String(error2)}` + ); + } + } + return runStatus; +} + // src/main.ts var API_VERSION = "2026-03-10"; async function run() { @@ -23606,7 +27087,7 @@ async function run() { }); } } - const octokit = getOctokit(token); + const octokit = createOctokit(token); const workflows = await octokit.paginate( octokit.rest.actions.listRepoWorkflows.endpoint.merge({ owner, @@ -23629,7 +27110,8 @@ async function run() { ref, inputs, return_run_details: true, - headers: { "x-github-api-version": API_VERSION } + headers: { "x-github-api-version": API_VERSION }, + request: NO_RETRY_REQUEST_OPTIONS } ); info(`\u{1F3C6} API response status: ${dispatchResp.status}`); @@ -23638,32 +27120,28 @@ async function run() { const syncStatus = getInput("sync-status") === "true"; const timeoutSeconds = parseInt(getInput("wait-timeout-seconds") || "900", 10); const waitIntervalSeconds = parseInt(getInput("wait-interval-seconds") || "5", 10); - let runStatus = "in_progress"; if (waitForCompletion) { info(`\u23F3 Waiting for workflow run to complete with a timeout of ${timeoutSeconds} seconds...`); - const startTime = Date.now(); - while (runStatus === "in_progress" || runStatus === "queued" || runStatus === "waiting" || runStatus === "pending") { - if ((Date.now() - startTime) / 1e3 > timeoutSeconds) { - warning( - `\u26A0\uFE0F Workflow run did not complete within ${timeoutSeconds} seconds, timing out. -Note: The workflow is still running but we have stopped waiting. You can check the run status here: ${dispatchResp.data.html_url}` + const runStatus = await waitForRunCompletion({ + getStatus: async () => { + const { data: runData } = await octokit.request( + `GET /repos/${owner}/${repo}/actions/runs/${dispatchResp.data.workflow_run_id}`, + { + headers: { "x-github-api-version": API_VERSION } + } ); - runStatus = "timed_out"; - break; - } - await new Promise((resolve) => setTimeout(resolve, waitIntervalSeconds * 1e3)); - const { data: runData } = await octokit.request( - `GET /repos/${owner}/${repo}/actions/runs/${dispatchResp.data.workflow_run_id}`, - { - headers: { "x-github-api-version": API_VERSION } - } - ); - runStatus = runData.status; - info(`\u{1F504} Current run status: ${runStatus}`); - } + return runData.status; + }, + timeoutSeconds, + intervalSeconds: waitIntervalSeconds + }); if (runStatus === "completed") { info("\u2705 Workflow run completed, the final status can be found in the workflow run details."); - } else if (runStatus === "timed_out") { + } else if (runStatus === TIMED_OUT) { + warning( + `\u26A0\uFE0F Workflow run did not complete within ${timeoutSeconds} seconds, timing out. +Note: The workflow is still running but we have stopped waiting. You can check the run status here: ${dispatchResp.data.html_url}` + ); warning(`\u26A0\uFE0F Workflow run did not complete within the timeout period.`); } else { warning(`\u26A0\uFE0F Workflow run completed with status: ${runStatus}`); diff --git a/package-lock.json b/package-lock.json index 9861730..31e4f5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,15 @@ "name": "workflow-dispatch", "version": "1.3.3", "license": "MIT", + "dependencies": { + "@octokit/plugin-retry": "^8.1.1", + "@octokit/plugin-throttling": "^11.0.5" + }, "devDependencies": { - "@actions/core": "^3.0.0", - "@actions/github": "^9.0.0", + "@actions/core": "^3.0.1", + "@actions/github": "^9.1.1", "@eslint/js": "^10.0.1", + "@types/node": "^24.19.2", "esbuild": "^0.25.0", "eslint": "^10.0.1", "prettier": "^3.8.1", @@ -20,9 +25,9 @@ } }, "node_modules/@actions/core": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.0.tgz", - "integrity": "sha512-zYt6cz+ivnTmiT/ksRVriMBOiuoUpDCJJlZ5KPl2/FRdvwU3f7MPh9qftvbkXJThragzUZieit2nyHUyw53Seg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.1.tgz", + "integrity": "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==", "dev": true, "license": "MIT", "dependencies": { @@ -41,9 +46,9 @@ } }, "node_modules/@actions/github": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-9.0.0.tgz", - "integrity": "sha512-yJ0RoswsAaKcvkmpCE4XxBRiy/whH2SdTBHWzs0gi4wkqTDhXMChjSdqBz/F4AeiDlP28rQqL33iHb+kjAMX6w==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-9.1.1.tgz", + "integrity": "sha512-tL5JbYOBZHc0ngEnCsaDcryUizIUIlQyIMwy1Wkx93H5HzbBJ7TbiPx2PnFjBwZW0Vh05JmfFZhecE6gglYegA==", "dev": true, "license": "MIT", "dependencies": { @@ -711,7 +716,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 20" @@ -721,7 +725,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/auth-token": "^6.0.0", @@ -740,7 +743,6 @@ "version": "11.0.3", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/types": "^16.0.0", @@ -754,7 +756,6 @@ "version": "9.0.3", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/request": "^10.0.6", @@ -769,7 +770,6 @@ "version": "27.0.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", - "dev": true, "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { @@ -804,11 +804,73 @@ "@octokit/core": ">=6" } }, + "node_modules/@octokit/plugin-retry": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.1.1.tgz", + "integrity": "sha512-VCVvZ/R1+u3WuiBWpNavZ0mY4aaJNAsENrpBP9aLSR2QyOpQgd7DhM5j4AW7z4MQpnJYgwBPf0XqPQoNBRdQwg==", + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^7.1.1", + "@octokit/types": "^17.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=7" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", + "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", + "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^28.0.0" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-11.0.5.tgz", + "integrity": "sha512-LIdrkrUv+DWbKeg/49rGuFJ3SU0d3hUS+B4MhNZLepBoNUFXms8Ic9edJjrlx+zycqJHjrMRudVpVb/bAXM2Lw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^17.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": "^7.0.0" + } + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { + "version": "28.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-28.0.0.tgz", + "integrity": "sha512-0rFyLuyHvIj6uuZWuDslxkowFYdPXoNIkeAv4b27dzm2Tf4vGWXnPsMcxs7d65kLdMERgP3wc1AEPlqMz8e1cQ==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-17.0.0.tgz", + "integrity": "sha512-ByP1v7YL5SMveFPP7+sj0/ZuWCOOg/Chs4NafOMpq6WNIM/hdGY0S7C0TCGDBWu1aGmOxmUIhMx3cO+IdwYZ1Q==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^28.0.0" + } + }, "node_modules/@octokit/request": { "version": "10.0.8", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.8.tgz", "integrity": "sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/endpoint": "^11.0.3", @@ -823,23 +885,36 @@ } }, "node_modules/@octokit/request-error": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", - "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", - "dev": true, + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.2.tgz", + "integrity": "sha512-XZRuT3xZ84D3gYErI1DZvhJ33dCWVV6uzBtWkaBB4TvA/L6eOeTZodxLFVB44bBEEo3vEx7y00UfX1tBLrtLRg==", "license": "MIT", "dependencies": { - "@octokit/types": "^16.0.0" + "@octokit/types": "^18.0.0" }, "engines": { "node": ">= 20" } }, + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-29.0.1.tgz", + "integrity": "sha512-9qWOMFNxxLokERcms42rU0PTLqQmVs7g5E41TI4mCOxmpFayD1rfC7XxOL55cG9MBZLFlC31BrR37myMKardwg==", + "license": "MIT" + }, + "node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-18.0.0.tgz", + "integrity": "sha512-l6bAF43PNxkJp6g+W4PjoUSSkxHomXw2nOum5CTftJz1NlV3vu93NImgOYtLf6CbBUb5j+fiuzW0PPQ5JTSvZA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^29.0.1" + } + }, "node_modules/@octokit/types": { "version": "16.0.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", - "dev": true, "license": "MIT", "dependencies": { "@octokit/openapi-types": "^27.0.0" @@ -866,6 +941,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/node": { + "version": "24.19.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.19.2.tgz", + "integrity": "sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.56.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.56.0.tgz", @@ -1183,9 +1268,14 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", - "dev": true, "license": "Apache-2.0" }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "license": "MIT" + }, "node_modules/brace-expansion": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.2.tgz", @@ -1450,7 +1540,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", - "dev": true, "funding": [ { "type": "github", @@ -1641,7 +1730,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.3.tgz", "integrity": "sha512-QObKu6nxy7NsxqR0VK4rkXnsNr5L9ElJaGEg+ucJ6J7/suoKZ0n+p76cu9aCqowytxEbwYNzvrMerfMkXneF5A==", - "dev": true, "license": "MIT" }, "node_modules/keyv": { @@ -1970,11 +2058,17 @@ "node": ">=18.17" } }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT" + }, "node_modules/universal-user-agent": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "dev": true, "license": "ISC" }, "node_modules/uri-js": { @@ -2027,4 +2121,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index d52519f..52fa327 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "main": "dist/index.js", "scripts": { "build": "esbuild src/main.ts --bundle --platform=node --target=node24 --outfile=dist/index.js", + "typecheck": "tsc --noEmit", + "test": "node --test \"src/**/*.test.ts\"", "lint": "eslint src/ --ext .ts && prettier --check src/", "lint-fix": "eslint src/ --fix && prettier --write src/", "format": "prettier --write src/" @@ -15,14 +17,19 @@ "github", "actions" ], + "dependencies": { + "@actions/core": "^3.0.1", + "@actions/github": "^9.1.1", + "@octokit/plugin-retry": "^8.1.1", + "@octokit/plugin-throttling": "^11.0.5" + }, "devDependencies": { - "@actions/core": "^3.0.0", - "@actions/github": "^9.0.0", "@eslint/js": "^10.0.1", + "@types/node": "^24.19.2", "esbuild": "^0.25.0", "eslint": "^10.0.1", "prettier": "^3.8.1", "typescript": "^5.9.3", "typescript-eslint": "^8.56.0" } -} \ No newline at end of file +} diff --git a/src/main.ts b/src/main.ts index 6bf1095..73d2bc9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,6 +8,8 @@ import * as core from '@actions/core' import * as github from '@actions/github' import * as PackageJSON from '../package.json' +import { createOctokit, NO_RETRY_REQUEST_OPTIONS } from './octokit-client.ts' +import { TIMED_OUT, waitForRunCompletion } from './wait-for-run.ts' const API_VERSION = '2026-03-10' // Latest API version as of March 2026, update as needed @@ -46,8 +48,8 @@ async function run(): Promise { } } - // Get octokit client for making API calls - const octokit = github.getOctokit(token) + // Get octokit client for making API calls (with retry + throttling plugins) + const octokit = createOctokit(token) // List workflows via API, and handle paginated results const workflows: Workflow[] = await octokit.paginate( @@ -76,7 +78,7 @@ async function run(): Promise { core.info(`🔎 Found workflow, id: ${foundWorkflow.id}, name: ${foundWorkflow.name}, path: ${foundWorkflow.path}`) - // Call workflow_dispatch API + // Call workflow_dispatch API, never retried on server errors as that could trigger a duplicate run core.info('🚀 Calling GitHub API to dispatch workflow...') const dispatchResp = await octokit.request( `POST /repos/${owner}/${repo}/actions/workflows/${foundWorkflow.id}/dispatches`, @@ -85,6 +87,7 @@ async function run(): Promise { inputs: inputs, return_run_details: true, headers: { 'x-github-api-version': API_VERSION }, + request: NO_RETRY_REQUEST_OPTIONS, }, ) @@ -96,41 +99,30 @@ async function run(): Promise { const syncStatus = core.getInput('sync-status') === 'true' const timeoutSeconds = parseInt(core.getInput('wait-timeout-seconds') || '900', 10) // Default to 15 minutes const waitIntervalSeconds = parseInt(core.getInput('wait-interval-seconds') || '5', 10) // Default to 5 seconds - let runStatus = 'in_progress' - // Polling loop to check workflow run status until it completes or times out + // Poll the workflow run status until it completes or times out if (waitForCompletion) { core.info(`⏳ Waiting for workflow run to complete with a timeout of ${timeoutSeconds} seconds...`) - const startTime = Date.now() - while ( - runStatus === 'in_progress' || - runStatus === 'queued' || - runStatus === 'waiting' || - runStatus === 'pending' - ) { - if ((Date.now() - startTime) / 1000 > timeoutSeconds) { - core.warning( - `⚠️ Workflow run did not complete within ${timeoutSeconds} seconds, timing out.\nNote: The workflow is still running but we have stopped waiting. You can check the run status here: ${dispatchResp.data.html_url}`, + const runStatus = await waitForRunCompletion({ + getStatus: async () => { + const { data: runData } = await octokit.request( + `GET /repos/${owner}/${repo}/actions/runs/${dispatchResp.data.workflow_run_id}`, + { + headers: { 'x-github-api-version': API_VERSION }, + }, ) - runStatus = 'timed_out' - break - } - - await new Promise((resolve) => setTimeout(resolve, waitIntervalSeconds * 1000)) // Wait for waitIntervalSeconds before polling again - - const { data: runData } = await octokit.request( - `GET /repos/${owner}/${repo}/actions/runs/${dispatchResp.data.workflow_run_id}`, - { - headers: { 'x-github-api-version': API_VERSION }, - }, - ) - runStatus = runData.status - core.info(`🔄 Current run status: ${runStatus}`) - } + return runData.status + }, + timeoutSeconds, + intervalSeconds: waitIntervalSeconds, + }) if (runStatus === 'completed') { core.info('✅ Workflow run completed, the final status can be found in the workflow run details.') - } else if (runStatus === 'timed_out') { + } else if (runStatus === TIMED_OUT) { + core.warning( + `⚠️ Workflow run did not complete within ${timeoutSeconds} seconds, timing out.\nNote: The workflow is still running but we have stopped waiting. You can check the run status here: ${dispatchResp.data.html_url}`, + ) core.warning(`⚠️ Workflow run did not complete within the timeout period.`) } else { core.warning(`⚠️ Workflow run completed with status: ${runStatus}`) diff --git a/src/octokit-client.test.ts b/src/octokit-client.test.ts new file mode 100644 index 0000000..28cbbad --- /dev/null +++ b/src/octokit-client.test.ts @@ -0,0 +1,211 @@ +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' +import * as github from '@actions/github' +import { retry } from '@octokit/plugin-retry' +import { throttling, type ThrottlingOptions } from '@octokit/plugin-throttling' +import { + buildOctokitOptions, + createOctokit, + isTransientError, + MAX_RATE_LIMIT_RETRIES, + NO_RETRY_REQUEST_OPTIONS, +} from './octokit-client.ts' + +const request = { method: 'POST', url: '/repos/o/r/actions/workflows/1/dispatches' } +const SECONDARY_RATE_LIMIT = 'You have exceeded a secondary rate limit' + +// A scripted response: [status, body?, headers?], or 'network-error' to make fetch reject +type FakeResponse = [number, object?, Record?] | 'network-error' + +// The throttling plugin spaces write requests 1s apart through a limiter shared by every client in the +// process, so each POST would wait for the previous test's POST. Pass writes straight through instead, +// retry and rate limit handling don't depend on it. +const unthrottledWrites = { + key: () => ({ schedule: (_options: unknown, job: () => Promise) => job() }), +} as unknown as ThrottlingOptions['write'] + +// Real client config and plugins, with a scripted fetch and no backoff delays +function fakeClient(responses: FakeResponse[]) { + const calls: string[] = [] + const warnings: string[] = [] + const fetch = async (url: string, init: { method: string }) => { + calls.push(`${init.method} ${new URL(url).pathname}`) + const next = responses[Math.min(calls.length, responses.length) - 1] + if (next === 'network-error') throw new TypeError('fetch failed') + + const [status, body = {}, headers = {}] = next + return new Response(JSON.stringify(body), { + status, + headers: { 'content-type': 'application/json', ...headers }, + }) + } + + const options = buildOctokitOptions((message) => warnings.push(message)) + const octokit = github.getOctokit( + 'token', + { + retry: { ...options.retry, retryAfterBaseValue: 0 }, + throttle: { + ...options.throttle, + retryAfterBaseValue: 0, + fallbackSecondaryRateRetryAfter: 0, + write: unthrottledWrites, + }, + request: { fetch }, + }, + retry, + throttling, + ) + + return { octokit, calls, warnings } +} + +const getRun = (octokit: ReturnType['octokit']) => octokit.request('GET /repos/o/r/actions/runs/1') +const dispatch = (octokit: ReturnType['octokit']) => + octokit.request('POST /repos/o/r/actions/workflows/1/dispatches', { ref: 'main', request: NO_RETRY_REQUEST_OPTIONS }) + +describe('isTransientError', () => { + it('is true for server errors, network failures and 429', () => { + for (const status of [429, 500, 502, 503, 504]) { + assert.equal(isTransientError({ status }), true, `expected ${status} to be transient`) + } + }) + + it('is false for client errors', () => { + for (const status of [400, 401, 403, 404, 410, 422, 451]) { + assert.equal(isTransientError({ status }), false, `expected ${status} not to be transient`) + } + }) + + it('is false for errors without an HTTP status', () => { + for (const error of [new Error('boom'), new TypeError('x is undefined'), null, undefined, 'string']) { + assert.equal(isTransientError(error), false) + } + }) +}) + +describe('rate limit handlers', () => { + for (const name of ['onRateLimit', 'onSecondaryRateLimit'] as const) { + it(`${name} retries while under the limit`, () => { + const warnings: string[] = [] + const handler = buildOctokitOptions((message) => warnings.push(message)).throttle[name] + + assert.equal(handler(60, request, {}, 0), true) + assert.equal(handler(60, request, {}, MAX_RATE_LIMIT_RETRIES - 1), true) + assert.match(warnings[0], /retry 1 after 60s/) + }) + + it(`${name} gives up at the limit`, () => { + const warnings: string[] = [] + const handler = buildOctokitOptions((message) => warnings.push(message)).throttle[name] + + assert.equal(handler(60, request, {}, MAX_RATE_LIMIT_RETRIES), false) + assert.equal(handler(60, request, {}, MAX_RATE_LIMIT_RETRIES + 1), false) + assert.match(warnings[0], new RegExp(`giving up after ${MAX_RATE_LIMIT_RETRIES} retries`)) + }) + } +}) + +// Every request through the plugins' Bottleneck limiters costs ~50-200ms of scheduling, so run these +// concurrently, each test has its own client and fetch. +describe('retry behaviour', { concurrency: true }, () => { + it('retries a server error and returns the later success', async () => { + const { octokit, calls } = fakeClient([[502], [200, { status: 'queued' }]]) + + const response = await getRun(octokit) + + assert.equal(response.status, 200) + assert.equal(calls.length, 2) + }) + + it('gives up after the default 3 retries with the last error', async () => { + const { octokit, calls } = fakeClient([[502]]) + + await assert.rejects(getRun(octokit), { status: 502 }) + assert.equal(calls.length, 4) + }) + + it('retries a network failure', async () => { + const { octokit, calls } = fakeClient(['network-error', [200]]) + + const response = await getRun(octokit) + + assert.equal(response.status, 200) + assert.equal(calls.length, 2) + }) + + it('does not retry a client error', async () => { + const { octokit, calls } = fakeClient([[404, { message: 'Not Found' }]]) + + await assert.rejects(getRun(octokit), { status: 404 }) + assert.equal(calls.length, 1) + }) + + it('retries a secondary rate limit via the throttling plugin', async () => { + const { octokit, calls, warnings } = fakeClient([[403, { message: SECONDARY_RATE_LIMIT }], [200]]) + + const response = await getRun(octokit) + + assert.equal(response.status, 200) + assert.equal(calls.length, 2) + assert.equal(warnings.length, 1) + }) +}) + +describe('NO_RETRY_REQUEST_OPTIONS', { concurrency: true }, () => { + it('does not retry a server error, as the dispatch may have been processed', async () => { + const { octokit, calls } = fakeClient([[500], [200]]) + + await assert.rejects(dispatch(octokit), { status: 500 }) + assert.deepEqual(calls, ['POST /repos/o/r/actions/workflows/1/dispatches']) + }) + + it('does not retry a network failure', async () => { + const { octokit, calls } = fakeClient(['network-error', [200]]) + + await assert.rejects(dispatch(octokit), { status: 500 }) + assert.equal(calls.length, 1) + }) + + it('still retries a secondary rate limit, as the dispatch was rejected unprocessed', async () => { + const { octokit, calls } = fakeClient([[403, { message: SECONDARY_RATE_LIMIT }], [200]]) + + const response = await dispatch(octokit) + + assert.equal(response.status, 200) + assert.equal(calls.length, 2) + }) +}) + +describe('createOctokit', () => { + it('wires token, options and both official plugins into getOctokit', () => { + const calls: Array<{ token: unknown; options: unknown; plugins: unknown[] }> = [] + const stubClient = { stub: 'octokit' } + const stubGetOctokit = ((token: unknown, options: unknown, ...plugins: unknown[]) => { + calls.push({ token, options, plugins }) + return stubClient + }) as unknown as typeof github.getOctokit + + const octokit = createOctokit('secret-token', stubGetOctokit) + + assert.equal(octokit, stubClient) + assert.equal(calls.length, 1) + assert.equal(calls[0].token, 'secret-token') + assert.deepEqual(calls[0].plugins, [retry, throttling]) + }) + + it('passes retry and throttle options through', () => { + let seenOptions: unknown + const stubGetOctokit = ((...args: unknown[]) => { + seenOptions = args[1] + return {} + }) as unknown as typeof github.getOctokit + + createOctokit('secret-token', stubGetOctokit) + + const options = seenOptions as ReturnType + assert.deepEqual(options.retry, buildOctokitOptions().retry) + assert.equal(typeof options.throttle.onRateLimit, 'function') + assert.equal(typeof options.throttle.onSecondaryRateLimit, 'function') + }) +}) diff --git a/src/octokit-client.ts b/src/octokit-client.ts new file mode 100644 index 0000000..6bd7a81 --- /dev/null +++ b/src/octokit-client.ts @@ -0,0 +1,60 @@ +import * as core from '@actions/core' +import * as github from '@actions/github' +import { retry } from '@octokit/plugin-retry' +import { throttling } from '@octokit/plugin-throttling' + +export const MAX_RATE_LIMIT_RETRIES = 3 + +// Client errors are not transient, never retry them. +// Same as the plugin-retry default, pinned here so a plugin upgrade can't silently change it. +// Note: 403 stays on this list even though GitHub reports secondary rate +// limits as 403 — those are handled by the throttling plugin, not retry. +export const DO_NOT_RETRY_STATUS_CODES = [400, 401, 403, 404, 410, 422, 451] + +// Per-request options for non-idempotent calls (e.g. workflow dispatch). When GitHub processed the +// request but the response was lost (5xx / network error), a retry would repeat the side effect. +// Rate limited requests are still retried by the throttling plugin, as GitHub rejected them unprocessed. +export const NO_RETRY_REQUEST_OPTIONS = { retries: 0 } + +type ThrottledRequest = { + method: string + url: string +} + +type Logger = (message: string) => void + +// Same rule plugin-retry uses to decide on a retry; network failures surface as status 500 +export function isTransientError(error: unknown): boolean { + const status = (error as { status?: unknown } | null)?.status + return typeof status === 'number' && status >= 400 && !DO_NOT_RETRY_STATUS_CODES.includes(status) +} + +export function shouldRetryAfterRateLimit(retryCount: number): boolean { + return retryCount < MAX_RATE_LIMIT_RETRIES +} + +function rateLimitHandler(kind: string, log: Logger) { + return (retryAfter: number, request: ThrottledRequest, _octokit: unknown, retryCount: number): boolean => { + const willRetry = shouldRetryAfterRateLimit(retryCount) + log( + willRetry + ? `${kind} hit for ${request.method} ${request.url}, retry ${retryCount + 1} after ${retryAfter}s` + : `${kind} hit for ${request.method} ${request.url}, giving up after ${retryCount} retries`, + ) + return willRetry + } +} + +export function buildOctokitOptions(log: Logger = core.warning) { + return { + retry: { doNotRetry: DO_NOT_RETRY_STATUS_CODES }, + throttle: { + onRateLimit: rateLimitHandler('Rate limit', log), + onSecondaryRateLimit: rateLimitHandler('Secondary rate limit', log), + }, + } +} + +export function createOctokit(token: string, getOctokit: typeof github.getOctokit = github.getOctokit) { + return getOctokit(token, buildOctokitOptions(), retry, throttling) +} diff --git a/src/wait-for-run.test.ts b/src/wait-for-run.test.ts new file mode 100644 index 0000000..07d4b44 --- /dev/null +++ b/src/wait-for-run.test.ts @@ -0,0 +1,108 @@ +import { describe, it } from 'node:test' +import assert from 'node:assert/strict' +import { TIMED_OUT, waitForRunCompletion } from './wait-for-run.ts' + +const httpError = (status: number, message: string) => Object.assign(new Error(message), { status }) + +// A scripted poll result: a run status, or an error for getStatus to throw +type Poll = string | Error + +// Fake clock which advances only when the poller sleeps, so tests never wait for real +function fakePoller(polls: Poll[]) { + let clock = 0 + const sleeps: number[] = [] + const infos: string[] = [] + const warnings: string[] = [] + let calls = 0 + + const deps = { + getStatus: async () => { + const next = polls[Math.min(calls, polls.length - 1)] + calls++ + if (next instanceof Error) throw next + return next + }, + log: { info: (message: string) => infos.push(message), warning: (message: string) => warnings.push(message) }, + sleep: async (ms: number) => { + sleeps.push(ms) + clock += ms + }, + now: () => clock, + } + + return { deps, sleeps, infos, warnings, calls: () => calls } +} + +describe('waitForRunCompletion', () => { + it('polls every interval until the run completes', async () => { + const { deps, sleeps, infos } = fakePoller(['queued', 'in_progress', 'completed']) + + const status = await waitForRunCompletion({ ...deps, timeoutSeconds: 60, intervalSeconds: 5 }) + + assert.equal(status, 'completed') + assert.deepEqual(sleeps, [5000, 5000, 5000]) + assert.deepEqual(infos, [ + '🔄 Current run status: queued', + '🔄 Current run status: in_progress', + '🔄 Current run status: completed', + ]) + }) + + it('returns a non active status as is', async () => { + const { deps } = fakePoller(['pending', 'waiting', 'requested']) + + const status = await waitForRunCompletion({ ...deps, timeoutSeconds: 60, intervalSeconds: 5 }) + + assert.equal(status, 'requested') + }) + + it('keeps polling through transient errors', async () => { + const { deps, warnings, calls } = fakePoller([ + httpError(502, 'Bad Gateway'), + httpError(500, 'fetch failed'), // How @octokit/request reports network failures + httpError(429, 'Too Many Requests'), + 'completed', + ]) + + const status = await waitForRunCompletion({ ...deps, timeoutSeconds: 60, intervalSeconds: 5 }) + + assert.equal(status, 'completed') + assert.equal(calls(), 4) + assert.equal(warnings.length, 3) + assert.match(warnings[0], /Failed to get run status, will try again: Bad Gateway/) + }) + + it('fails immediately on a non transient error', async () => { + const { deps, calls } = fakePoller([httpError(404, 'Not Found'), 'completed']) + + await assert.rejects(waitForRunCompletion({ ...deps, timeoutSeconds: 60, intervalSeconds: 5 }), { + message: 'Not Found', + }) + assert.equal(calls(), 1) + }) + + it('fails immediately on an error without an HTTP status', async () => { + const { deps, calls } = fakePoller([new TypeError('runData is undefined'), 'completed']) + + await assert.rejects(waitForRunCompletion({ ...deps, timeoutSeconds: 60, intervalSeconds: 5 }), TypeError) + assert.equal(calls(), 1) + }) + + it('times out while the run stays active', async () => { + const { deps, calls } = fakePoller(['in_progress']) + + const status = await waitForRunCompletion({ ...deps, timeoutSeconds: 10, intervalSeconds: 5 }) + + assert.equal(status, TIMED_OUT) + assert.equal(calls(), 3) // Polled at 5s, 10s and 15s, the timeout is checked before each sleep + }) + + it('times out when transient errors never stop', async () => { + const { deps, warnings } = fakePoller([httpError(503, 'Service Unavailable')]) + + const status = await waitForRunCompletion({ ...deps, timeoutSeconds: 10, intervalSeconds: 5 }) + + assert.equal(status, TIMED_OUT) + assert.equal(warnings.length, 3) + }) +}) diff --git a/src/wait-for-run.ts b/src/wait-for-run.ts new file mode 100644 index 0000000..44140ba --- /dev/null +++ b/src/wait-for-run.ts @@ -0,0 +1,54 @@ +import * as core from '@actions/core' +import { isTransientError } from './octokit-client.ts' + +// Run statuses which mean the run has not finished yet +export const ACTIVE_RUN_STATUSES = ['in_progress', 'queued', 'waiting', 'pending'] + +export const TIMED_OUT = 'timed_out' + +type Logger = { + info: (message: string) => void + warning: (message: string) => void +} + +export type WaitForRunOptions = { + getStatus: () => Promise + timeoutSeconds: number + intervalSeconds: number + log?: Logger + sleep?: (ms: number) => Promise + now?: () => number +} + +// Polls the run status until the run is no longer active, returns the last status or TIMED_OUT. +// Transient errors which outlast the client retries are logged and polling continues, the timeout still applies. +export async function waitForRunCompletion({ + getStatus, + timeoutSeconds, + intervalSeconds, + log = core, + sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), + now = Date.now, +}: WaitForRunOptions): Promise { + const startTime = now() + let runStatus = 'in_progress' + + while (ACTIVE_RUN_STATUSES.includes(runStatus)) { + if ((now() - startTime) / 1000 > timeoutSeconds) return TIMED_OUT + + await sleep(intervalSeconds * 1000) + + try { + runStatus = await getStatus() + log.info(`🔄 Current run status: ${runStatus}`) + } catch (error) { + if (!isTransientError(error)) throw error + + log.warning( + `⚠️ Failed to get run status, will try again: ${error instanceof Error ? error.message : String(error)}`, + ) + } + } + + return runStatus +} diff --git a/tsconfig.json b/tsconfig.json index b873194..50fc446 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,9 @@ "noImplicitAny": true, "esModuleInterop": true, "resolveJsonModule": true, - "skipLibCheck": true + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true }, - "exclude": ["node_modules", "**/*.test.ts"] + "exclude": ["node_modules", "dist"] }