From a46801ebe05c057aa94051338df9fd0c6e094c65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 09:27:43 +0000 Subject: [PATCH 1/3] Initial plan From 6c1c38e611960e91bdffbd3911cdcb554b5ea251 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 09:36:22 +0000 Subject: [PATCH 2/3] Initial plan Co-authored-by: nigelfpowers <202913696+nigelfpowers@users.noreply.github.com> --- package-lock.json | 6 ------ 1 file changed, 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9bfbaa3fb5..a8772e464b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -953,7 +953,6 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -2001,7 +2000,6 @@ "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/utils": "3.2.4", "fflate": "^0.8.2", @@ -4828,7 +4826,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -6252,7 +6249,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6347,7 +6343,6 @@ "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", @@ -6446,7 +6441,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", From 2bde3d9b670510f933369cc2c3de664dc94e1ad8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 09:44:52 +0000 Subject: [PATCH 3/3] Fix recover function: add recover() method to Probot class When Probot initialization fails, initializationState gets permanently stuck as INITIALIZING with no way to retry. Add a public recover() method that resets the initialization state and retries, enabling recovery from transient failures without creating a new Probot instance. No existing code was deleted; only additions were made. Co-authored-by: nigelfpowers <202913696+nigelfpowers@users.noreply.github.com> --- src/probot.ts | 9 +++++++++ test/probot.test.ts | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/probot.ts b/src/probot.ts index 54fad52646..3e1fd12a2f 100644 --- a/src/probot.ts +++ b/src/probot.ts @@ -310,6 +310,15 @@ export class Probot { return this; } + public async recover(): Promise { + if (this.#state.initializationState === INITIALIZED) { + return; + } + this.#state.initializationState = UNINITIALIZED; + this.#state.initializedPromise = createDeferredPromise(); + await this.#initialize(); + } + public async receive(event: WebhookEvent): Promise { await this.#state.initializedPromise.promise; diff --git a/test/probot.test.ts b/test/probot.test.ts index b68998a47f..1369ccf560 100644 --- a/test/probot.test.ts +++ b/test/probot.test.ts @@ -772,4 +772,41 @@ describe("Probot", () => { ); }); }); + + describe("recover", () => { + it("allows re-initialization after a failed initialization", async () => { + let constructorCallCount = 0; + + class FailOnFirstConstruct extends ProbotOctokit { + constructor(options?: ConstructorParameters[0]) { + super(options); + constructorCallCount++; + if (constructorCallCount === 1) { + throw new Error("Simulated initialization failure"); + } + } + } + + const probot = new Probot({ + appId, + privateKey, + Octokit: FailOnFirstConstruct, + }); + + let firstError: Error | undefined; + try { + await probot.auth(); + } catch (e) { + firstError = e as Error; + } + + expect(firstError).toBeDefined(); + expect(firstError?.message).toContain("Simulated initialization failure"); + + await probot.recover(); + + const octokit = await probot.auth(); + expect(octokit).toBeDefined(); + }); + }); });