Skip to content

Commit 3db0700

Browse files
committed
Add shared_dirs_populate option to populate shared dirs from release
1 parent 7bdc3f7 commit 3db0700

3 files changed

Lines changed: 134 additions & 2 deletions

File tree

docs/recipe/deploy/shared.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,20 @@ set('shared_dirs', ['storage']);
2323

2424

2525

26+
### shared_dirs_populate
27+
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L18)
28+
29+
When true, populate existing shared dirs with any new files/dirs present in the release.
30+
Useful when new subdirectories are added to the repo over time and should be propagated to shared.
31+
Existing files in shared are never overwritten.
32+
33+
```php title="Default value"
34+
true
35+
```
36+
37+
2638
### shared_files
27-
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L20)
39+
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L25)
2840

2941
List of files what will be shared between releases.
3042
Each release will have symlink to those files stored in [deploy_path](/docs/recipe/common.md#deploy_path)/shared dir.
@@ -38,7 +50,7 @@ set('shared_files', ['.env']);
3850
## Tasks
3951

4052
### deploy\:shared {#deploy-shared}
41-
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L23)
53+
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L28)
4254

4355
Creates symlinks for shared files and dirs.
4456

recipe/deploy/shared.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
// ```
1313
set('shared_dirs', []);
1414

15+
// When true, populate existing shared dirs with any new files/dirs present in the release.
16+
// Useful when new subdirectories are added to the repo over time and should be propagated to shared.
17+
// Existing files in shared are never overwritten.
18+
set('shared_dirs_populate', true);
19+
1520
// List of files what will be shared between releases.
1621
// Each release will have symlink to those files stored in {{deploy_path}}/shared dir.
1722
// ```php
@@ -46,6 +51,9 @@
4651
if (test("[ -d $(echo {{release_path}}/$dir) ]")) {
4752
run("cp -r$copyVerbosity {{release_path}}/$dir $sharedPath/" . dirname($dir));
4853
}
54+
} elseif (get('shared_dirs_populate') && test("[ -d $(echo {{release_path}}/$dir) ]")) {
55+
// Populate shared dir with new files/dirs from release without overwriting existing content.
56+
run("cp -r$copyVerbosity --no-dereference --no-clobber {{release_path}}/$dir/. $sharedPath/$dir/");
4957
}
5058

5159
// Remove from source.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
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+
12+
use const __TEMP_DIR__;
13+
14+
class SharedDirsPopulateTest extends SpecTest
15+
{
16+
public function testPopulateCopiesNewReleaseFilesWithoutOverwriting()
17+
{
18+
$repo = $this->createRepo('populate_repo', ['data/a.txt' => 'first']);
19+
$recipe = $this->writeRecipe('prod1', $repo, true);
20+
$deployPath = __TEMP_DIR__ . '/prod1';
21+
22+
$this->depFile($recipe, 'deploy');
23+
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());
24+
self::assertFileExists($deployPath . '/shared/data/a.txt');
25+
self::assertSame('first', file_get_contents($deployPath . '/shared/data/a.txt'));
26+
27+
// Simulate a new file being added to the repository over time.
28+
$this->addFileAndCommit($repo, 'data/b.txt', 'second');
29+
30+
$this->depFile($recipe, 'deploy');
31+
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());
32+
33+
self::assertFileExists($deployPath . '/shared/data/b.txt');
34+
self::assertSame('second', file_get_contents($deployPath . '/shared/data/b.txt'));
35+
self::assertFileExists($deployPath . '/current/data/b.txt');
36+
37+
// Existing shared file must not be overwritten by the release content.
38+
self::assertSame('first', file_get_contents($deployPath . '/shared/data/a.txt'));
39+
}
40+
41+
public function testPopulateDisabledByDefaultDoesNotSyncNewFiles()
42+
{
43+
$repo = $this->createRepo('no_populate_repo', ['data/a.txt' => 'first']);
44+
$recipe = $this->writeRecipe('prod2', $repo, false);
45+
$deployPath = __TEMP_DIR__ . '/prod2';
46+
47+
$this->depFile($recipe, 'deploy');
48+
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());
49+
self::assertFileExists($deployPath . '/shared/data/a.txt');
50+
51+
$this->addFileAndCommit($repo, 'data/b.txt', 'second');
52+
53+
$this->depFile($recipe, 'deploy');
54+
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());
55+
56+
self::assertFileDoesNotExist($deployPath . '/shared/data/b.txt');
57+
}
58+
59+
private function createRepo(string $name, array $files): string
60+
{
61+
$dir = __TEMP_DIR__ . '/' . $name;
62+
mkdir($dir, 0777, true);
63+
64+
foreach ($files as $path => $content) {
65+
$full = $dir . '/' . $path;
66+
if (!is_dir(dirname($full))) {
67+
mkdir(dirname($full), 0777, true);
68+
}
69+
file_put_contents($full, $content);
70+
}
71+
72+
exec("cd $dir && git init 2>&1");
73+
exec("cd $dir && git config user.name 'Deployer Test' && git config user.email 'test@example.com'");
74+
exec("cd $dir && git add . && git commit -m 'init' 2>&1");
75+
76+
return $dir;
77+
}
78+
79+
private function addFileAndCommit(string $repo, string $path, string $content): void
80+
{
81+
$full = $repo . '/' . $path;
82+
if (!is_dir(dirname($full))) {
83+
mkdir(dirname($full), 0777, true);
84+
}
85+
file_put_contents($full, $content);
86+
87+
exec("cd $repo && git add . && git commit -m 'add file' 2>&1");
88+
}
89+
90+
private function writeRecipe(string $hostname, string $repository, bool $populate): string
91+
{
92+
$populateValue = $populate ? 'true' : 'false';
93+
$recipe = <<<PHP
94+
<?php
95+
namespace Deployer;
96+
require 'recipe/common.php';
97+
set('application', 'deployer');
98+
set('repository', '$repository');
99+
set('shared_dirs', ['data']);
100+
set('shared_dirs_populate', $populateValue);
101+
set('keep_releases', 5);
102+
set('http_user', false);
103+
localhost('$hostname');
104+
task('deploy:vendors', function () {
105+
});
106+
PHP;
107+
$file = __TEMP_DIR__ . "/$hostname.php";
108+
file_put_contents($file, $recipe);
109+
110+
return $file;
111+
}
112+
}

0 commit comments

Comments
 (0)