Skip to content

Commit da02de1

Browse files
Merge pull request #13 from codenamephp/addTasks
Add tasks
2 parents 9406a1b + 27d931d commit da02de1

File tree

13 files changed

+318
-0
lines changed

13 files changed

+318
-0
lines changed

.idea/deployer.crontab.iml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/php.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,8 @@
5252
"composer-require-checker": "Checks for missing required composer packages",
5353
"infection": "Creates mutation tests to discover missing test coverage",
5454
"ci-all": "Runs all ci tools in sequence"
55+
},
56+
"require-dev": {
57+
"mockery/mockery": "^1.5"
5558
}
5659
}

psalm.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
cacheDirectory=".cache/psalm"
2525
findUnusedBaselineEntry="true"
2626
findUnusedCode="true"
27+
errorLevel="1"
2728
>
2829
<projectFiles>
2930
<directory name="src"/>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace de\codenamephp\deployer\crontab\Task;
4+
5+
use de\codenamephp\deployer\base\task\iTask;
6+
use de\codenamephp\deployer\command\runner\iRunner;
7+
use de\codenamephp\deployer\command\runner\WithDeployerFunctions;
8+
use de\codenamephp\deployer\crontab\Command\CrontabCommandFactoryInterface;
9+
use de\codenamephp\deployer\crontab\Command\WithBinaryFromDeployer;
10+
11+
/**
12+
* Abstract class for crontab commands that allows an optional user. If the user is given it is set with -u to the crontab command.
13+
* The command to run is passed to the constructor and is executed by the command runner.
14+
*
15+
* Implementations can implement HasOptionsInterface to add additional options to the command.
16+
*/
17+
abstract class AbstractCrontabCommand implements iTask {
18+
19+
public function __construct(
20+
public readonly ?string $user = null,
21+
public readonly CrontabCommandFactoryInterface $crontabCommandFactory = new WithBinaryFromDeployer(),
22+
public readonly iRunner $commandRunner = new WithDeployerFunctions()
23+
) {}
24+
25+
/**
26+
* Checks for the HasOptionsInterface and if it's implemented the return value is used as base. Then adds the user option if it is set.
27+
*
28+
* @return array<int, string> The options to pass to the crontab command
29+
*/
30+
final public function getOptionsWithUser() : array {
31+
$options = $this instanceof HasOptionsInterface ? $this->getOptions() : [];
32+
!$this->user ?: $options[] = "-u $this->user";
33+
return $options;
34+
}
35+
36+
final public function __invoke() : void {
37+
$this->commandRunner->run($this->crontabCommandFactory->build($this->getOptionsWithUser()));
38+
}
39+
}

src/Task/Delete.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace de\codenamephp\deployer\crontab\Task;
4+
5+
use de\codenamephp\deployer\base\task\iTaskWithDescription;
6+
use de\codenamephp\deployer\base\task\iTaskWithName;
7+
8+
/**
9+
* Deletes the crontab without asking for confirmation
10+
*
11+
* @psalm-api
12+
*/
13+
final class Delete extends AbstractCrontabCommand implements iTaskWithName, iTaskWithDescription {
14+
15+
public const NAME = 'crontab:delete';
16+
17+
public function getOptions() : array {
18+
return ['-r'];
19+
}
20+
21+
public function getDescription() : string {
22+
return 'Deletes the crontab';
23+
}
24+
25+
public function getName() : string {
26+
return self::NAME;
27+
}
28+
}

src/Task/HasOptionsInterface.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace de\codenamephp\deployer\crontab\Task;
4+
5+
/**
6+
* Interface for tasks that have additional options
7+
*/
8+
interface HasOptionsInterface {
9+
10+
/**
11+
* Returns the options for the task
12+
*
13+
* @return array<int, string> The options for the task
14+
*/
15+
public function getOptions() : array;
16+
}

src/Task/Install.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace de\codenamephp\deployer\crontab\Task;
4+
5+
use de\codenamephp\deployer\base\task\iTaskWithDescription;
6+
use de\codenamephp\deployer\base\task\iTaskWithName;
7+
use de\codenamephp\deployer\command\runner\iRunner;
8+
use de\codenamephp\deployer\command\runner\WithDeployerFunctions;
9+
use de\codenamephp\deployer\crontab\Command\CrontabCommandFactoryInterface;
10+
use de\codenamephp\deployer\crontab\Command\WithBinaryFromDeployer;
11+
12+
/**
13+
* Installs the given crontab file
14+
*
15+
* @psalm-api
16+
*/
17+
final class Install extends AbstractCrontabCommand implements iTaskWithName, iTaskWithDescription, HasOptionsInterface {
18+
19+
public const NAME = 'crontab:install';
20+
21+
public function __construct(
22+
public readonly string $file = '{{release_or_current_path}}/crontab',
23+
?string $user = null,
24+
CrontabCommandFactoryInterface $crontabCommandFactory = new WithBinaryFromDeployer(),
25+
iRunner $commandRunner = new WithDeployerFunctions()
26+
) {
27+
parent::__construct($user, $crontabCommandFactory, $commandRunner);
28+
}
29+
30+
public function getOptions() : array {
31+
return [$this->file];
32+
}
33+
34+
public function getDescription() : string {
35+
return 'Installs the given crontab file.';
36+
}
37+
38+
public function getName() : string {
39+
return self::NAME;
40+
}
41+
}

src/Task/Show.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace de\codenamephp\deployer\crontab\Task;
4+
5+
use de\codenamephp\deployer\base\task\iTaskWithDescription;
6+
use de\codenamephp\deployer\base\task\iTaskWithName;
7+
8+
/**
9+
* Lists the crontab ... should have been called 'List' but that is a reserved word
10+
*
11+
* @psalm-api
12+
*/
13+
final class Show extends AbstractCrontabCommand implements iTaskWithName, iTaskWithDescription {
14+
15+
public const NAME = 'crontab:show';
16+
17+
public function getOptions() : array {
18+
return ['-l'];
19+
}
20+
21+
public function getDescription() : string {
22+
return 'Shows the crontab';
23+
}
24+
25+
public function getName() : string {
26+
return self::NAME;
27+
}
28+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace de\codenamephp\deployer\crontab\test\Task;
4+
5+
use de\codenamephp\deployer\command\iCommand;
6+
use de\codenamephp\deployer\command\runner\iRunner;
7+
use de\codenamephp\deployer\command\runner\WithDeployerFunctions;
8+
use de\codenamephp\deployer\crontab\Command\CrontabCommandFactoryInterface;
9+
use de\codenamephp\deployer\crontab\Command\WithBinaryFromDeployer;
10+
use de\codenamephp\deployer\crontab\Task\AbstractCrontabCommand;
11+
use de\codenamephp\deployer\crontab\Task\HasOptionsInterface;
12+
use Mockery;
13+
use PHPUnit\Framework\TestCase;
14+
15+
final class AbstractCrontabCommandTest extends TestCase {
16+
17+
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
18+
19+
public function testGetOptionsWithUser() : void {
20+
$sut = $this->getMockForAbstractClass(AbstractCrontabCommand::class);
21+
22+
self::assertSame([], $sut->getOptionsWithUser());
23+
}
24+
25+
public function testGetOptionsWithUser_withSetUser() : void {
26+
$sut = $this->getMockForAbstractClass(AbstractCrontabCommand::class, ['some user']);
27+
28+
self::assertSame(['-u some user'], $sut->getOptionsWithUser());
29+
}
30+
31+
public function testGetOptionsWithUser_withSetUser_andOptions() : void {
32+
$sut = Mockery::mock(AbstractCrontabCommand::class, HasOptionsInterface::class, ['some user'])->makePartial();
33+
$sut->allows('getOptions')->once()->andReturn(['some option']);
34+
35+
self::assertSame(['some option', '-u some user'], $sut->getOptionsWithUser());
36+
}
37+
38+
public function test__construct() : void {
39+
$sut = $this->getMockForAbstractClass(AbstractCrontabCommand::class);
40+
41+
self::assertNull($sut->user);
42+
self::assertInstanceOf(WithBinaryFromDeployer::class, $sut->crontabCommandFactory);
43+
self::assertInstanceOf(WithDeployerFunctions::class, $sut->commandRunner);
44+
}
45+
46+
public function test__construct_withOptionalArguments() : void {
47+
$user = 'some user';
48+
$crontabCommandFactory = $this->createMock(CrontabCommandFactoryInterface::class);
49+
$commandRunner = $this->createMock(iRunner::class);
50+
51+
$sut = $this->getMockForAbstractClass(AbstractCrontabCommand::class, [$user, $crontabCommandFactory, $commandRunner]);
52+
53+
self::assertSame($user, $sut->user);
54+
self::assertSame($crontabCommandFactory, $sut->crontabCommandFactory);
55+
self::assertSame($commandRunner, $sut->commandRunner);
56+
}
57+
58+
public function test__invoke() : void {
59+
$user = 'some user';
60+
$command = $this->createMock(iCommand::class);
61+
62+
$crontabCommandFactory = $this->createMock(CrontabCommandFactoryInterface::class);
63+
$crontabCommandFactory->expects(self::once())->method('build')->with(['-u some user'])->willReturn($command);
64+
65+
$commandRunner = $this->createMock(iRunner::class);
66+
$commandRunner->expects(self::once())->method('run')->with($command);
67+
68+
$sut = $this->getMockForAbstractClass(AbstractCrontabCommand::class, [$user, $crontabCommandFactory, $commandRunner]);
69+
$sut->__invoke();
70+
}
71+
}

0 commit comments

Comments
 (0)