Skip to content

Commit b2a285c

Browse files
committed
Add regression test for local_archive parallel deploy race
Refs #4232
1 parent d5fdaac commit b2a285c

2 files changed

Lines changed: 80 additions & 0 deletions

File tree

tests/spec/LocalArchiveTest.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/* (c) Anton Medvedev <anton@medv.io>
3+
*
4+
* For the full copyright and license information, please view the LICENSE
5+
* file that was distributed with this source code.
6+
*/
7+
8+
namespace Deployer;
9+
10+
use spec\SpecTest;
11+
use Symfony\Component\Console\Output\Output;
12+
13+
class LocalArchiveTest extends SpecTest
14+
{
15+
public const RECIPE = __DIR__ . '/recipe/local_archive.php';
16+
17+
public static function setUpBeforeClass(): void
18+
{
19+
parent::setUpBeforeClass();
20+
putenv('DEPLOYER_LOCAL_WORKER=false');
21+
}
22+
23+
public static function tearDownAfterClass(): void
24+
{
25+
putenv('DEPLOYER_LOCAL_WORKER=true');
26+
parent::tearDownAfterClass();
27+
}
28+
29+
public function testParallelLocalArchiveDeploy()
30+
{
31+
$this->init(self::RECIPE);
32+
$this->tester->run([
33+
'deploy',
34+
'selector' => 'all',
35+
'-f' => self::RECIPE,
36+
], [
37+
'verbosity' => Output::VERBOSITY_VERBOSE,
38+
]);
39+
40+
$display = $this->tester->getDisplay();
41+
self::assertEquals(0, $this->tester->getStatusCode(), $display);
42+
43+
// Every host must end up with the archived code, not just the worker
44+
// that won the race for the shared archive file.
45+
foreach ($this->deployer->hosts as $host) {
46+
$deployPath = $host->get('deploy_path');
47+
self::assertFileExists($deployPath . '/current/README.md', $display);
48+
}
49+
50+
// The fix builds the archive in a unique temp file and cleans it up,
51+
// so nothing is left behind in the local git root.
52+
$gitRoot = trim((string) shell_exec('git rev-parse --show-toplevel'));
53+
self::assertFileDoesNotExist($gitRoot . '/archive.tar');
54+
}
55+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Deployer;
4+
5+
require 'recipe/common.php';
6+
7+
set('update_code_strategy', 'local_archive');
8+
9+
// Worker processes don't inherit the master's in-memory config, so the
10+
// deploy path has to live in the recipe itself. Mirrors __TEMP_DIR__ from
11+
// the test bootstrap without relying on test-only constants.
12+
set('deploy_path', sys_get_temp_dir() . '/deployer/{{hostname}}');
13+
14+
// Archive only the small fixture subtree of the local working copy instead
15+
// of the whole Deployer tree, so each parallel host uploads a tiny,
16+
// well-defined payload.
17+
set('sub_directory', 'tests/fixtures/repository');
18+
set('keep_releases', 1);
19+
20+
// Several hosts so deploy:update_code runs in multiple parallel workers at
21+
// once — the scenario in which the shared local archive file used to race
22+
// (see issue #4232 / PR #4235).
23+
localhost('alpha');
24+
localhost('beta');
25+
localhost('gamma');

0 commit comments

Comments
 (0)