Plan-Korrektur vor der Umsetzung: Task-2-Test isolieren

Zwei Defekte im Vorab-Abgleich gefunden, beide im Testaufbau von Task 2:

- Der Test haette echte Tags (v9.9.8, v9.9.9) im GETEILTEN Repository
  angelegt. Tags liegen im gemeinsamen .git und sind damit auch fuer den
  Hauptbaum und jede Parallelsitzung sichtbar. Stirbt der Test vor seinem
  Aufraeumen, beantwortet ein liegengebliebenes v9.9.9 die Frage
  `git tag -l 'v*' --sort=-v:refname | head -1` falsch — und die entscheidet,
  wohin ein Server aktualisiert. Jetzt laeuft der Agent in einem Wegwerf-
  Checkout mit eigenem .git; er bestimmt seine Wurzel ohnehin aus dem eigenen
  Pfad, es genuegt also, deploy/ dorthin zu kopieren.
- Falscher Manifest-Pfad: der Test schrieb nach storage/app/deploy/
  deployment.json, gelesen wird storage/app/deployment.json (lib/release.sh:19)
  — eine Ebene darueber. Der Test haette die ausgelieferte Version nie gesetzt
  und etwas anderes gemessen, als er behauptet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
feat/versandtakt
nexxo 2026-08-04 14:38:59 +02:00
parent 40e42a88fe
commit d4a9166c7a
1 changed files with 35 additions and 16 deletions

View File

@ -275,29 +275,50 @@ use Illuminate\Support\Facades\Process;
*/
function runAgentWithCeiling(?string $ceiling, array $tags, string $deployedVersion = '1.7.3'): array
{
$dir = storage_path('app/deploy');
File::ensureDirectoryExists($dir);
File::delete(File::glob($dir.'/*'));
// Ein WEGWERF-Checkout mit EIGENEM .git — niemals das Repository dieses
// Arbeitsbaums.
//
// Tags liegen im gemeinsamen .git und sind damit auch fuer den Hauptbaum
// und jede Parallelsitzung sichtbar. Ein hier angelegtes v9.9.9 wuerde
// `git tag -l 'v*' --sort=-v:refname | head -1` falsch beantworten — und
// genau diese Frage entscheidet, wohin ein Server aktualisiert. Stirbt der
// Test vor seinem Aufraeumen, bliebe es liegen.
//
// Der Agent bestimmt seine Wurzel aus dem eigenen Pfad
// (`ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"`). Es genuegt
// also, deploy/ zu kopieren und ihn dort zu starten.
$root = sys_get_temp_dir().'/clupilot-ceiling-'.bin2hex(random_bytes(6));
File::ensureDirectoryExists($root.'/deploy/lib');
File::ensureDirectoryExists($root.'/storage/app/deploy');
// Der Agent liest die ausgelieferte Version aus dem Manifest.
File::put($dir.'/deployment.json', json_encode([
File::copy(base_path('deploy/update-agent.sh'), $root.'/deploy/update-agent.sh');
File::copy(base_path('deploy/lib/release.sh'), $root.'/deploy/lib/release.sh');
// MANIFEST_FILE ist `storage/app/deployment.json` — eine Ebene UEBER
// storage/app/deploy/. Siehe deploy/lib/release.sh:19.
File::put($root.'/storage/app/deployment.json', json_encode([
'version' => $deployedVersion,
'commit' => 'deadbeef',
'source' => 'refs/tags/v'.$deployedVersion,
]));
if ($ceiling !== null) {
File::put($dir.'/release-ceiling', $ceiling);
File::put($root.'/storage/app/deploy/release-ceiling', $ceiling);
}
$tagCommands = '';
foreach ($tags as $tag) {
$tagCommands .= "git tag {$tag} 2>/dev/null || true\n";
$tagCommands .= "git tag {$tag}\n";
}
$result = Process::path(base_path())->timeout(90)->run(<<<BASH
$result = Process::path($root)->timeout(90)->run(<<<BASH
set -e
git init -q .
git -c user.email=t@example.com -c user.name=t commit -q --allow-empty -m init
{$tagCommands}
stub="\$(mktemp -d)"
# Nur `fetch` wird abgefangen; alles andere geht ans echte git.
# Nur `fetch` wird abgefangen — es gibt keine Gegenstelle. Alles andere
# geht ans echte git und wirkt im Wegwerf-Checkout.
cat > "\$stub/git" <<'GIT'
#!/bin/sh
if [ "\$1" = "fetch" ]; then exit 0; fi
@ -306,20 +327,18 @@ function runAgentWithCeiling(?string $ceiling, array $tags, string $deployedVers
chmod +x "\$stub/git"
printf '#!/bin/sh\nexit 1\n' > "\$stub/docker"
chmod +x "\$stub/docker"
{$tagCommands}
PATH="\$stub:\$PATH" bash deploy/update-agent.sh >/dev/null 2>&1 || true
rm -rf "\$stub"
BASH);
expect($result->successful())->toBeTrue($result->errorOutput());
return json_decode(File::get($dir.'/update-status.json'), true);
}
$status = json_decode(File::get($root.'/storage/app/deploy/update-status.json'), true);
afterEach(function () {
File::deleteDirectory(storage_path('app/deploy'));
Process::path(base_path())->run("git tag -d v9.9.8 v9.9.9 2>/dev/null || true");
});
File::deleteDirectory($root);
return $status;
}
it('offers only up to the ceiling', function () {
// Ausgeliefert 1.7.3, vorhanden bis v9.9.9, Decke auf v9.9.8: genau eine