run(); (new Process(['rm', '-rf', $repo]))->run(); return $process; } it('counts the releases ahead without taking the agent down with it', function () { // The exact shape that failed: the newest tag is ahead, and the tags after // it in the list are not — so the loop's final iteration is a false one. $process = runRelease( 'release_tags_ahead 1.2.0', ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], ); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('1'); }); it('survives a run where no tag at all is ahead', function () { // Every iteration false, including the last. This is the ordinary state of // an up-to-date server, which is to say: most ticks, on most machines. $process = runRelease( 'release_tags_ahead 1.2.1', ['v1.1.0', 'v1.2.0', 'v1.2.1'], ); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('0'); }); it('survives a repository with no tags whatsoever', function () { $process = runRelease('release_tags_ahead 1.0.0'); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('0'); }); it('counts several releases ahead', function () { $process = runRelease( 'release_tags_ahead 1.1.0', ['v1.1.0', 'v1.1.1', 'v1.2.0', 'v1.2.1'], ); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('3'); }); it('picks the newest tag out of a long list without dying on a broken pipe', function () { // The second instance of the same trap. `git tag … | head -1` makes head // exit after one line, git takes SIGPIPE, and pipefail ends the caller. // Few tags hide it — git finishes writing before head leaves — so it needs // enough of them to actually fill a pipe buffer. $tags = []; for ($i = 1; $i <= 400; $i++) { $tags[] = 'v1.'.$i.'.0'; } $process = runRelease('release_newest_tag', $tags); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('v1.400.0'); }); it('answers with nothing, and cleanly, when there are no releases yet', function () { $process = runRelease('release_newest_tag; echo "[$?]"'); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('[0]'); }); it('orders by version, not alphabetically', function () { // v1.10.0 is newer than v1.9.0 and sorts earlier as a string. Getting this // wrong means a server sitting on 1.9.0 is told it is current. $process = runRelease( 'release_tags_ahead 1.9.0', ['v1.9.0', 'v1.10.0'], ); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe('1'); }); it('answers the pairwise comparison the same way, and exits cleanly either way', function () { $cases = [ ['1.2.1', '1.2.0', 'ja'], ['1.2.0', '1.2.1', 'nein'], ['1.2.0', '1.2.0', 'nein'], ['1.10.0', '1.9.0', 'ja'], ['2.0.0', '1.99.99', 'ja'], ]; foreach ($cases as [$a, $b, $expected]) { $process = runRelease("if release_version_gt {$a} {$b}; then echo ja; else echo nein; fi"); expect($process->getExitCode())->toBe(0) ->and(trim($process->getOutput()))->toBe($expected, "{$a} > {$b}"); } });