126 lines
4.5 KiB
PHP
126 lines
4.5 KiB
PHP
<?php
|
|
|
|
use App\Models\Operator;
|
|
use App\Services\Deployment\Release;
|
|
use Illuminate\Support\Facades\File;
|
|
|
|
/**
|
|
* What the console says it is running. The point of the distinction is that a
|
|
* bug report has to name the right code: a deployment somewhere after 1.0.0 is
|
|
* not 1.0.0, and reporting it as one sends someone reading the wrong source.
|
|
*/
|
|
function writeManifest(array $manifest): void
|
|
{
|
|
File::ensureDirectoryExists(storage_path('app'));
|
|
File::put(storage_path('app/deployment.json'), json_encode($manifest));
|
|
}
|
|
|
|
afterEach(fn () => File::delete(storage_path('app/deployment.json')));
|
|
|
|
it('reads the release number from the VERSION file', function () {
|
|
// One source of truth, and it is a file — a source archive, a shallow CI
|
|
// checkout and a container built without .git have no tags to describe.
|
|
expect(config('app.version'))->toBe(trim(File::get(base_path('VERSION'))))
|
|
->and(config('app.version'))->toMatch('/^\d+\.\d+\.\d+$/');
|
|
});
|
|
|
|
it('reports a pinned release as that release', function () {
|
|
writeManifest([
|
|
'version' => config('app.version'),
|
|
'commit' => 'abc1234567890',
|
|
'source' => 'refs/tags/v'.config('app.version'),
|
|
'mode' => 'release',
|
|
'deployed_at' => now()->toIso8601String(),
|
|
]);
|
|
|
|
$release = Release::current();
|
|
|
|
expect($release->isTaggedRelease)->toBeTrue()
|
|
->and($release->label())->toBe(config('app.version').' (abc1234)');
|
|
});
|
|
|
|
it('does not call a deployment after the release by the release\'s name', function () {
|
|
// Every commit after v1.0.0 still carries VERSION=1.0.0 and is not 1.0.0.
|
|
writeManifest([
|
|
'commit' => 'def4567890123',
|
|
'source' => 'main',
|
|
'mode' => 'branch',
|
|
'deployed_at' => now()->toIso8601String(),
|
|
]);
|
|
|
|
$release = Release::current();
|
|
|
|
expect($release->isTaggedRelease)->toBeFalse()
|
|
->and($release->label())->toBe(config('app.version').'-dev (def4567) · main');
|
|
});
|
|
|
|
it('keeps reporting the deployed version when an update fails halfway', function () {
|
|
// The checkout moves before the migrations run, so a run that dies in
|
|
// between leaves a newer VERSION on disk than is actually serving. Pairing
|
|
// that number with the still-deployed commit would describe a build that
|
|
// never existed.
|
|
writeManifest([
|
|
'version' => '0.9.0',
|
|
'commit' => 'aaa1111222333',
|
|
'source' => 'refs/tags/v0.9.0',
|
|
'mode' => 'release',
|
|
'deployed_at' => now()->subDay()->toIso8601String(),
|
|
]);
|
|
|
|
$release = Release::current();
|
|
|
|
expect($release->version)->toBe('0.9.0')
|
|
->and($release->version)->not->toBe(config('app.version'))
|
|
// Still a clean release label: 0.9.0 is genuinely what is running.
|
|
->and($release->isTaggedRelease)->toBeTrue()
|
|
->and($release->label())->toBe('0.9.0 (aaa1111)');
|
|
});
|
|
|
|
it('says something sensible before anything has been deployed', function () {
|
|
File::delete(storage_path('app/deployment.json'));
|
|
|
|
expect(Release::current()->commit)->toBeNull()
|
|
->and(Release::current()->label())->toBe(config('app.version').'-dev');
|
|
});
|
|
|
|
it('does not take the console down over an unparseable timestamp', function () {
|
|
writeManifest([
|
|
'version' => '1.0.0',
|
|
'commit' => 'abc1234567890',
|
|
'source' => 'main',
|
|
'mode' => 'branch',
|
|
'deployed_at' => 'not-a-date',
|
|
]);
|
|
|
|
// A line of small print in the sidebar must not 500 every admin page.
|
|
expect(Release::current()->deployedAt)->toBeNull()
|
|
->and(Release::current()->label())->toBe('1.0.0-dev (abc1234) · main');
|
|
|
|
$this->actingAs(Operator::factory()->role()->create(), 'operator')
|
|
->get(route('admin.overview'))
|
|
->assertOk();
|
|
});
|
|
|
|
it('survives a manifest that is not readable json', function () {
|
|
File::ensureDirectoryExists(storage_path('app'));
|
|
File::put(storage_path('app/deployment.json'), '{ half-written');
|
|
|
|
// The console reporting nothing is a nuisance; the console 500ing because
|
|
// a deployment was interrupted mid-write is an outage.
|
|
expect(Release::current()->label())->toBe(config('app.version').'-dev');
|
|
});
|
|
|
|
it('shows the running version in the console', function () {
|
|
writeManifest([
|
|
'commit' => 'abc1234567890',
|
|
'source' => 'refs/tags/v'.config('app.version'),
|
|
'mode' => 'release',
|
|
'deployed_at' => now()->toIso8601String(),
|
|
]);
|
|
|
|
$this->actingAs(Operator::factory()->role()->create(), 'operator')
|
|
->get(route('admin.overview'))
|
|
->assertOk()
|
|
->assertSee(config('app.version').' (abc1234)');
|
|
});
|