Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions docs/recipe/deploy/shared.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,20 @@ set('shared_dirs', ['storage']);



### shared_dirs_populate
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L18)

When true, populate existing shared dirs with any new files/dirs present in the release.
Useful when new subdirectories are added to the repo over time and should be propagated to shared.
Existing files in shared are never overwritten.

```php title="Default value"
true
```


### shared_files
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L20)
[Source](https://github.com/deployphp/deployer/blob/master/recipe/deploy/shared.php#L25)

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

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

Creates symlinks for shared files and dirs.

Expand Down
8 changes: 8 additions & 0 deletions recipe/deploy/shared.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
// ```
set('shared_dirs', []);

// When true, populate existing shared dirs with any new files/dirs present in the release.
// Useful when new subdirectories are added to the repo over time and should be propagated to shared.
// Existing files in shared are never overwritten.
set('shared_dirs_populate', true);

// List of files what will be shared between releases.
// Each release will have symlink to those files stored in {{deploy_path}}/shared dir.
// ```php
Expand Down Expand Up @@ -46,6 +51,9 @@
if (test("[ -d $(echo {{release_path}}/$dir) ]")) {
run("cp -r$copyVerbosity {{release_path}}/$dir $sharedPath/" . dirname($dir));
}
} elseif (get('shared_dirs_populate') && test("[ -d $(echo {{release_path}}/$dir) ]")) {
// Populate shared dir with new files/dirs from release without overwriting existing content.
run("cp -r$copyVerbosity --no-dereference --no-clobber {{release_path}}/$dir/. $sharedPath/$dir/");
}

// Remove from source.
Expand Down
112 changes: 112 additions & 0 deletions tests/spec/SharedDirsPopulateTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/* (c) Anton Medvedev <anton@medv.io>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Deployer;

use spec\SpecTest;

use const __TEMP_DIR__;

class SharedDirsPopulateTest extends SpecTest
{
public function testPopulateCopiesNewReleaseFilesWithoutOverwriting()
{
$repo = $this->createRepo('populate_repo', ['data/a.txt' => 'first']);
$recipe = $this->writeRecipe('prod1', $repo, true);
$deployPath = __TEMP_DIR__ . '/prod1';

$this->depFile($recipe, 'deploy');
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());
self::assertFileExists($deployPath . '/shared/data/a.txt');
self::assertSame('first', file_get_contents($deployPath . '/shared/data/a.txt'));

// Simulate a new file being added to the repository over time.
$this->addFileAndCommit($repo, 'data/b.txt', 'second');

$this->depFile($recipe, 'deploy');
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());

self::assertFileExists($deployPath . '/shared/data/b.txt');
self::assertSame('second', file_get_contents($deployPath . '/shared/data/b.txt'));
self::assertFileExists($deployPath . '/current/data/b.txt');

// Existing shared file must not be overwritten by the release content.
self::assertSame('first', file_get_contents($deployPath . '/shared/data/a.txt'));
}

public function testPopulateDisabledByDefaultDoesNotSyncNewFiles()
{
$repo = $this->createRepo('no_populate_repo', ['data/a.txt' => 'first']);
$recipe = $this->writeRecipe('prod2', $repo, false);
$deployPath = __TEMP_DIR__ . '/prod2';

$this->depFile($recipe, 'deploy');
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());
self::assertFileExists($deployPath . '/shared/data/a.txt');

$this->addFileAndCommit($repo, 'data/b.txt', 'second');

$this->depFile($recipe, 'deploy');
self::assertEquals(0, $this->tester->getStatusCode(), $this->tester->getDisplay());

self::assertFileDoesNotExist($deployPath . '/shared/data/b.txt');
}

private function createRepo(string $name, array $files): string
{
$dir = __TEMP_DIR__ . '/' . $name;
mkdir($dir, 0777, true);

foreach ($files as $path => $content) {
$full = $dir . '/' . $path;
if (!is_dir(dirname($full))) {
mkdir(dirname($full), 0777, true);
}
file_put_contents($full, $content);
}

exec("cd $dir && git init 2>&1");
exec("cd $dir && git config user.name 'Deployer Test' && git config user.email 'test@example.com'");
exec("cd $dir && git add . && git commit -m 'init' 2>&1");

return $dir;
}

private function addFileAndCommit(string $repo, string $path, string $content): void
{
$full = $repo . '/' . $path;
if (!is_dir(dirname($full))) {
mkdir(dirname($full), 0777, true);
}
file_put_contents($full, $content);

exec("cd $repo && git add . && git commit -m 'add file' 2>&1");
}

private function writeRecipe(string $hostname, string $repository, bool $populate): string
{
$populateValue = $populate ? 'true' : 'false';
$recipe = <<<PHP
<?php
namespace Deployer;
require 'recipe/common.php';
set('application', 'deployer');
set('repository', '$repository');
set('shared_dirs', ['data']);
set('shared_dirs_populate', $populateValue);
set('keep_releases', 5);
set('http_user', false);
localhost('$hostname');
task('deploy:vendors', function () {
});
PHP;
$file = __TEMP_DIR__ . "/$hostname.php";
file_put_contents($file, $recipe);

return $file;
}
}