Skip to content

Commit 2d9e855

Browse files
Fix dw upgrade post-replace exit-code autoload
1 parent d6e6857 commit 2d9e855

2 files changed

Lines changed: 53 additions & 11 deletions

File tree

src/Commands/UpgradeCommand.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
9696
}
9797
$asJson = $outputMode === OutputMode::JSON;
9898

99+
// Prime exit-code constants before any self-replacement so the current
100+
// process never needs to autoload ExitCode from a swapped archive.
101+
$successExit = ExitCode::SUCCESS;
102+
$failureExit = ExitCode::FAILURE;
103+
99104
$target = $this->detector !== null ? ($this->detector)() : InstallationTarget::detect(
100105
argv0: (string) ($_SERVER['argv'][0] ?? ''),
101106
pharRunning: \Phar::running(false),
@@ -122,7 +127,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
122127
'installation' => $target->toArray(),
123128
'current_version' => $currentVersion,
124129
'target_version' => null,
125-
], ExitCode::FAILURE);
130+
], $failureExit);
126131
}
127132

128133
$catalog = $this->catalog ?? ReleaseCatalog::create();
@@ -136,7 +141,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
136141
'installation' => $target->toArray(),
137142
'current_version' => $currentVersion,
138143
'target_version' => null,
139-
], ExitCode::FAILURE);
144+
], $failureExit);
140145
}
141146

142147
if ($target->assetName === null) {
@@ -146,7 +151,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
146151
'installation' => $target->toArray(),
147152
'current_version' => $currentVersion,
148153
'target_version' => $targetVersion,
149-
], ExitCode::FAILURE);
154+
], $failureExit);
150155
}
151156

152157
$sameVersion = $this->versionsMatch($currentVersion, $targetVersion);
@@ -158,7 +163,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
158163
'installation' => $target->toArray(),
159164
'current_version' => $currentVersion,
160165
'target_version' => $targetVersion,
161-
], ExitCode::SUCCESS);
166+
], $successExit);
162167
}
163168

164169
$binaryUrl = $catalog->downloadUrl($targetVersion, $target->assetName);
@@ -172,7 +177,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
172177
'target_version' => $targetVersion,
173178
'asset_url' => $binaryUrl,
174179
'checksum_url' => $sumsUrl,
175-
], ExitCode::SUCCESS);
180+
], $successExit);
176181
}
177182

178183
if (! $target->upgradeable) {
@@ -182,7 +187,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
182187
'installation' => $target->toArray(),
183188
'current_version' => $currentVersion,
184189
'target_version' => $targetVersion,
185-
], ExitCode::FAILURE);
190+
], $failureExit);
186191
}
187192

188193
try {
@@ -196,7 +201,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
196201
'installation' => $target->toArray(),
197202
'current_version' => $currentVersion,
198203
'target_version' => $targetVersion,
199-
], ExitCode::FAILURE);
204+
], $failureExit);
200205
}
201206

202207
$actual = hash('sha256', $binary);
@@ -207,7 +212,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
207212
'installation' => $target->toArray(),
208213
'current_version' => $currentVersion,
209214
'target_version' => $targetVersion,
210-
], ExitCode::FAILURE);
215+
], $failureExit);
211216
}
212217

213218
$replacer = $this->replacer ?? self::defaultReplacer(...);
@@ -221,23 +226,23 @@ protected function execute(InputInterface $input, OutputInterface $output): int
221226
'installation' => $target->toArray(),
222227
'current_version' => $currentVersion,
223228
'target_version' => $targetVersion,
224-
], ExitCode::FAILURE);
229+
], $failureExit);
225230
} catch (\RuntimeException $e) {
226231
return $this->emit($output, $asJson, [
227232
'status' => 'error',
228233
'reason' => $e->getMessage(),
229234
'installation' => $target->toArray(),
230235
'current_version' => $currentVersion,
231236
'target_version' => $targetVersion,
232-
], ExitCode::FAILURE);
237+
], $failureExit);
233238
}
234239

235240
return $this->emit($output, $asJson, [
236241
'status' => 'upgraded',
237242
'installation' => $target->toArray(),
238243
'current_version' => $currentVersion,
239244
'target_version' => $targetVersion,
240-
], ExitCode::SUCCESS);
245+
], $successExit);
241246
}
242247

243248
private function emit(OutputInterface $output, bool $asJson, array $payload, int $exit): int

tests/Commands/UpgradeCommandTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use DurableWorkflow\Cli\Commands\UpgradePermissionException;
1010
use DurableWorkflow\Cli\Support\InstallationTarget;
1111
use DurableWorkflow\Cli\Support\ReleaseCatalog;
12+
use PHPUnit\Framework\Attributes\RunInSeparateProcess;
1213
use PHPUnit\Framework\TestCase;
1314
use Symfony\Component\Console\Command\Command;
1415
use Symfony\Component\Console\Tester\CommandTester;
@@ -196,6 +197,42 @@ public function test_full_upgrade_downloads_and_replaces_when_checksum_matches()
196197
self::assertSame(0755, $replaced[0]['mode']);
197198
}
198199

200+
#[RunInSeparateProcess]
201+
public function test_exit_code_is_loaded_before_binary_replacement(): void
202+
{
203+
self::assertFalse(class_exists(\DurableWorkflow\Cli\Support\ExitCode::class, false));
204+
205+
$binary = 'new-binary-bytes';
206+
$hash = hash('sha256', $binary);
207+
$sums = "{$hash} dw-linux-x86_64\n";
208+
209+
$exitCodeLoadedDuringReplace = null;
210+
$replacer = function (string $path, string $bytes, int $mode) use (&$exitCodeLoadedDuringReplace): void {
211+
$exitCodeLoadedDuringReplace = class_exists(\DurableWorkflow\Cli\Support\ExitCode::class, false);
212+
};
213+
214+
$command = $this->command(
215+
catalog: $this->catalog([
216+
'latest-tag' => '0.1.9',
217+
'sums' => $sums,
218+
'asset' => $binary,
219+
]),
220+
detector: fn () => new InstallationTarget(
221+
kind: InstallationTarget::KIND_BINARY,
222+
path: '/home/user/.local/bin/dw',
223+
upgradeable: true,
224+
assetName: 'dw-linux-x86_64',
225+
),
226+
replacer: $replacer,
227+
);
228+
229+
$tester = new CommandTester($command);
230+
$exit = $tester->execute(['--output' => 'json']);
231+
232+
self::assertSame(Command::SUCCESS, $exit);
233+
self::assertTrue($exitCodeLoadedDuringReplace, 'ExitCode should already be loaded before the replacer runs.');
234+
}
235+
199236
public function test_fails_on_checksum_mismatch(): void
200237
{
201238
$binary = 'mismatched-bytes';

0 commit comments

Comments
 (0)