Test Failed
Push — master ( c51706...f968f3 )
by Anton
01:54
created

TaskCommand::parseOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.5

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 8
ccs 3
cts 6
cp 0.5
crap 2.5
rs 10
c 0
b 0
f 0
1
<?php
2
/* (c) Anton Medvedev <[email protected]>
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\Console;
9
10
use Deployer\Deployer;
11
use Deployer\Exception\Exception;
12
use Deployer\Exception\GracefulShutdownException;
13
use Deployer\Executor\ExecutorInterface;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputArgument;
16
use Symfony\Component\Console\Input\InputInterface as Input;
17
use Symfony\Component\Console\Input\InputOption as Option;
18
use Symfony\Component\Console\Output\OutputInterface as Output;
19
20
class TaskCommand extends Command
21
{
22
    /**
23
     * @var Deployer
24
     */
25
    private $deployer;
26
27
    /**
28
     * @var ExecutorInterface
29
     */
30
    public $executor;
31
32
    /**
33
     * @param string $name
34
     * @param string $description
35
     * @param Deployer $deployer
36
     */
37 4
    public function __construct($name, $description, Deployer $deployer)
38
    {
39 4
        parent::__construct($name);
40 4
        if ($description) {
41 1
            $this->setDescription($description);
42
        }
43 4
        $this->deployer = $deployer;
44 4
    }
45
46
    /**
47
     * Configures the command
48
     */
49 4
    protected function configure()
50
    {
51 4
        $this->addArgument(
52 4
            'stage',
53 4
            InputArgument::OPTIONAL,
54 4
            'Stage or hostname'
55
        );
56 4
        $this->addOption(
57 4
            'parallel',
58 4
            'p',
59 4
            Option::VALUE_NONE,
60 4
            'Run tasks in parallel'
61
        );
62 4
        $this->addOption(
63 4
            'limit',
64 4
            'l',
65 4
            Option::VALUE_REQUIRED,
66 4
            'How many host to run in parallel?'
67
        );
68 4
        $this->addOption(
69 4
            'no-hooks',
70 4
            null,
71 4
            Option::VALUE_NONE,
72 4
            'Run task without after/before hooks'
73
        );
74 4
        $this->addOption(
75 4
            'log',
76 4
            null,
77 4
            Option::VALUE_REQUIRED,
78 4
            'Log to file'
79
        );
80 4
        $this->addOption(
81 4
            'roles',
82 4
            null,
83 4
            Option::VALUE_REQUIRED,
84 4
            'Roles to deploy'
85
        );
86 4
        $this->addOption(
87 4
            'hosts',
88 4
            null,
89 4
            Option::VALUE_REQUIRED,
90 4
            'Host to deploy, comma separated, supports ranges [:]'
91
        );
92 4
        $this->addOption(
93 4
            'option',
94 4
            'o',
95 4
            Option::VALUE_REQUIRED | Option::VALUE_IS_ARRAY,
96 4
            'Sets configuration option'
97
        );
98 4
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 3
    protected function execute(Input $input, Output $output)
104
    {
105 3
        $stage = $input->hasArgument('stage') ? $input->getArgument('stage') : null;
106 3
        $roles = $input->getOption('roles');
107 3
        $hosts = $input->getOption('hosts');
108 3
        $this->parseOptions($input->getOption('option'));
109
110 3
        $hooksEnabled = !$input->getOption('no-hooks');
111 3
        if (!empty($input->getOption('log'))) {
112
            $this->deployer->config['log_file'] = $input->getOption('log');
113
        }
114
115 3 View Code Duplication
        if (!empty($hosts)) {
116
            $hosts = $this->deployer->hostSelector->getByHostnames($hosts);
117 3
        } elseif (!empty($roles)) {
118
            $hosts = $this->deployer->hostSelector->getByRoles($roles);
119
        } else {
120 3
            $hosts = $this->deployer->hostSelector->getHosts($stage);
0 ignored issues
show
Bug introduced by Anton Medvedev
It seems like $stage defined by $input->hasArgument('sta...rgument('stage') : null on line 105 can also be of type array<integer,string> or null; however, Deployer\Host\HostSelector::getHosts() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
121
        }
122
123 3
        if (empty($hosts)) {
124
            throw new Exception('No host selected');
125
        }
126
127 3
        $tasks = $this->deployer->scriptManager->getTasks(
128 3
            $this->getName(),
129 3
            $hosts,
130 3
            $hooksEnabled
131
        );
132
133 3
        if (empty($tasks)) {
134
            throw new Exception('No task will be executed, because the selected hosts do not meet the conditions of the tasks');
135
        }
136
137 3
        if ($input->getOption('parallel')) {
138
            $executor = $this->deployer->parallelExecutor;
139
        } else {
140 3
            $executor = $this->deployer->seriesExecutor;
141
        }
142
143
        try {
144 3
            $executor->run($tasks, $hosts);
145
        } catch (\Throwable $exception) {
146
            $this->deployer->logger->log('['. get_class($exception) .'] '. $exception->getMessage());
147
            $this->deployer->logger->log($exception->getTraceAsString());
148
149
            if ($exception instanceof GracefulShutdownException) {
150
                throw $exception;
151
            } else {
152
                // Check if we have tasks to execute on failure
153
                if ($this->deployer['fail']->has($this->getName())) {
154
                    $taskName = $this->deployer['fail']->get($this->getName());
155
                    $tasks = $this->deployer->scriptManager->getTasks($taskName, $hosts, $hooksEnabled);
156
157
                    $executor->run($tasks, $hosts);
158
                }
159
                throw $exception;
160
            }
161
        }
162
163 3
        return 0;
164
    }
165
166 3
    private function parseOptions(array $options)
167
    {
168 3
        foreach ($options as $option) {
169
            list($name, $value) = explode('=', $option);
170
            $value = $this->castValueToPhpType($value);
171
            $this->deployer->config->set($name, $value);
172
        }
173 3
    }
174
175
    private function castValueToPhpType($value)
176
    {
177
        switch ($value) {
178
            case 'true':
179
                return true;
180
            case 'false':
181
                return false;
182
            default:
183
                return $value;
184
        }
185
    }
186
}
187