From 6bbae4097ed5b93660a5e12a85087e6ae794fe6a Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 24 Feb 2026 09:06:26 +0100 Subject: [PATCH] chore: prepare for PR --- app/Jobs/ApplicationDeploymentJob.php | 21 ++++++++++++--------- bootstrap/helpers/github.php | 9 ++++++++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index e70829dd8..e63e47211 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -217,15 +217,6 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue $this->source = $source->getMorphClass()::where('id', $this->application->source->id)->first(); } - // Pre-generate GitHub installation token once to avoid multiple API calls during deployment - if ($this->source instanceof GithubApp && ! $this->source->is_public) { - try { - $this->github_access_token = generateGithubInstallationToken($this->source); - } catch (\Exception $e) { - // Token generation will be retried later if needed - $this->github_access_token = null; - } - } $this->server = Server::find($this->application_deployment_queue->server_id); $this->timeout = $this->server->settings->dynamic_timeout; $this->destination = $this->server->destinations()->where('id', $this->application_deployment_queue->destination_id)->first(); @@ -291,6 +282,18 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue return; } + + // Generate GitHub installation token once per deployment execution (not in constructor, + // since queued jobs may sit in the queue long enough for tokens to expire) + if ($this->source instanceof GithubApp && ! $this->source->is_public) { + try { + $this->github_access_token = generateGithubInstallationToken($this->source); + } catch (\Exception $e) { + // Token generation will be retried later via null-coalesce fallback + $this->github_access_token = null; + } + } + try { // Make sure the private key is stored in the filesystem $this->server->privateKey->storeInFileSystem(); diff --git a/bootstrap/helpers/github.php b/bootstrap/helpers/github.php index b8ea9a585..baa10f134 100644 --- a/bootstrap/helpers/github.php +++ b/bootstrap/helpers/github.php @@ -61,7 +61,14 @@ function generateGithubToken(GithubApp $source, string $type) 'Authorization' => "Bearer $jwt", 'Accept' => 'application/vnd.github.machine-man-preview+json', ])->timeout($timeout) - ->retry(3, 200, throw: false) + ->retry(3, 200, function (\Exception $exception) { + // Don't retry auth errors — the same JWT won't become valid on retry + if ($exception instanceof \Illuminate\Http\Client\RequestException) { + return ! in_array($exception->response->status(), [401, 403]); + } + + return true; + }, throw: false) ->post("{$source->api_url}/app/installations/{$source->installation_id}/access_tokens"); if (! $response->successful()) {