GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#1085)
by Markus
03:13
created

functions.php ➔ task()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 30
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6.288

Importance

Changes 0
Metric Value
cc 6
eloc 19
nc 8
nop 2
dl 0
loc 30
ccs 16
cts 20
cp 0.8
crap 6.288
rs 8.439
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
namespace Deployer;
8
9
use Deployer\Builder\BuilderInterface;
10
use Deployer\Server\Local;
11
use Deployer\Server\Remote;
12
use Deployer\Server\Builder;
13
use Deployer\Server\Configuration;
14
use Deployer\Server\Environment;
15
use Deployer\Task\Task as T;
16
use Deployer\Task\Context;
17
use Deployer\Task\GroupTask;
18
use Deployer\Type\Result;
19
use Monolog\Logger;
20
use Symfony\Component\Console\Question\ChoiceQuestion;
21
use Symfony\Component\Console\Question\ConfirmationQuestion;
22
use Symfony\Component\Console\Question\Question;
23
use Symfony\Component\Finder\Finder;
24
use Symfony\Component\Process\Exception\ProcessFailedException;
25
use Symfony\Component\Process\Process;
26
use Deployer\Cluster\ClusterFactory;
27
use Symfony\Component\Console\Input\InputArgument;
28
use Symfony\Component\Console\Input\InputInterface;
29
use Symfony\Component\Console\Input\InputOption;
30
use Symfony\Component\Console\Output\OutputInterface;
31
use Symfony\Component\Console\Helper\ProgressBar;
32
33
// There are two types of functions: Deployer dependent and Context dependent.
34
// Deployer dependent function uses in definition stage of recipe and may require Deployer::get() method.
35
// Context dependent function uses while task execution and must require only Context::get() method.
36
// But there is also a third type of functions: mixed. Mixed function uses in definition stage and in task
37
// execution stage. They are acts like two different function, but have same name. Example of such function
38
// is set() func. This function determine in which stage it was called by Context::get() method.
39
40
/**
41
 * @param string $name
42
 * @param string|null $host
43
 * @param int $port
44
 * @return BuilderInterface
45
 */
46
function server($name, $host = null, $port = 22)
47
{
48 2
    $deployer = Deployer::get();
49
50 2
    $env = new Environment();
51 2
    $config = new Configuration($name, $host, $port);
52
53 2
    if (get('ssh_type') === 'ext-ssh2') {
54
        $server = new Remote\SshExtension($config);
55 2
    } elseif (get('ssh_type') && get('ssh_type') === 'native') {
56
        $server = new Remote\NativeSsh($config);
57
    } else {
58 2
        $server = new Remote\PhpSecLib($config);
59
    }
60
61 2
    $deployer->servers->set($name, $server);
62 2
    $deployer->environments->set($name, $env);
63
64 2
    return new Builder($config, $env);
65
}
66
67
68
/**
69
 * @param string $name
70
 * @return BuilderInterface
71
 */
72
function localServer($name)
73
{
74 12
    $deployer = Deployer::get();
75
76 12
    $env = new Environment();
77 12
    $config = new Configuration($name, 'localhost'); // Builder requires server configuration.
78 12
    $server = new Local($config);
79
80 12
    $deployer->servers->set($name, $server);
81 12
    $deployer->environments->set($name, $env);
82
83 12
    return new Builder($config, $env);
84
}
85
86
/**
87
 * @param string $name Name of the cluster
88
 * @param array $nodes An array of nodes' host/ip
89
 * @param int $port Ssh port of the nodes
90
 *
91
 * Example:
92
 * You should pass a cluster name and nodes array.
93
 * Nodes array should be as following:
94
 * [ '192.168.1.1', 'example.com', '192.168.1.5' ]
95
 * @return BuilderInterface
96
 */
97
function cluster($name, $nodes, $port = 22)
98
{
99 2
    $deployer = Deployer::get();
100
101 3
    $cluster = ClusterFactory::create($deployer, $name, $nodes, $port);
102
103 2
    return $cluster->getBuilder();
104
}
105
106
107
/**
108
 * Load server list file.
109
 * @param string $file
110
 */
111
function serverList($file)
112
{
113 1
    $bootstrap = new Bootstrap\BootstrapByConfigFile();
114 1
    $bootstrap->setConfig($file);
115 7
    $bootstrap->parseConfig();
116 1
    $bootstrap->initServers();
117 1
    $bootstrap->initClusters();
118 7
}
119
120
/**
121
 * Set task description.
122
 *
123
 * @param string $title
124
 * @return string
125
 */
126
function desc($title = null)
127 8
{
128 15
    static $store = null;
129
130 15
    if ($title === null) {
131 15
        return $store;
132
    } else {
133 11
        return $store = $title;
134
    }
135
}
136
137
/**
138
 * Define a new task and save to tasks list.
139
 *
140
 * Alternatively get a defined task.
141
 *
142
 * @param string $name Name of current task.
143
 * @param callable|array|string|null $body Callable task, array of other tasks names or nothing to get a defined tasks
144
 * @return Task\Task
145
 * @throws \InvalidArgumentException
146
 */
147
function task($name, $body = null)
148 1
{
149 15
    $deployer = Deployer::get();
150
151 16
    if (empty($body)) {
152 2
        $task = $deployer->tasks->get($name);
153 2
        return $task;
154
    }
155
156 15
    if ($body instanceof \Closure) {
157 15
        $task = new T($name, $body);
158 15
    } elseif (is_array($body)) {
159 6
        $task = new GroupTask($name, $body);
160 4
    } elseif (is_string($body)) {
161
        $task = new T($name, function () use ($body) {
162
            run($body);
163
        });
164
    } else {
165
        throw new \InvalidArgumentException('Task should be an closure or array of other tasks.');
166
    }
167
168 15
    $deployer->tasks->set($name, $task);
169
170 15
    if (!empty(desc())) {
171 11
        $task->desc(desc());
172 11
        desc(''); // Clear title.
173 11
    }
174
175 16
    return $task;
176
}
177
178
/**
179
 * Call that task before specified task runs.
180
 *
181
 * @param string $it
182
 * @param string $that
183
 */
184
function before($it, $that)
185
{
186 2
    $deployer = Deployer::get();
187 2
    $beforeTask = $deployer->tasks->get($it);
188
189 2
    $beforeTask->addBefore($that);
190 2
}
191
192
/**
193
 * Call that task after specified task runs.
194
 *
195
 * @param string $it
196
 * @param string $that
197
 */
198
function after($it, $that)
199
{
200 2
    $deployer = Deployer::get();
201 2
    $afterTask = $deployer->tasks->get($it);
202
203 2
    $afterTask->addAfter($that);
204 2
}
205
206
/**
207
 * Setup which task run on failure of first.
208
 *
209
 * @param string $it
210
 * @param string $that
211
 */
212
function onFailure($it, $that)
213
{
214 11
    $deployer = Deployer::get();
215 11
    $deployer['onFailure']->set($it, $that);
216 16
}
217
218
/**
219
 * Add users arguments.
220
 *
221
 * Note what Deployer already has one argument: "stage".
222
 *
223
 * @param string $name
224
 * @param int $mode
225
 * @param string $description
226
 * @param mixed $default
227
 */
228
function argument($name, $mode = null, $description = '', $default = null)
229
{
230 11
    Deployer::get()->getConsole()->getUserDefinition()->addArgument(
231 11
        new InputArgument($name, $mode, $description, $default)
232 11
    );
233 11
}
234
235
/**
236
 * Add users options.
237
 *
238
 * @param string $name
239
 * @param string $shortcut
240
 * @param int $mode
241
 * @param string $description
242
 * @param mixed $default
243
 */
244
function option($name, $shortcut = null, $mode = null, $description = '', $default = null)
245
{
246 11
    Deployer::get()->getConsole()->getUserDefinition()->addOption(
247 11
        new InputOption($name, $shortcut, $mode, $description, $default)
248 11
    );
249 11
}
250
251
/**
252
 * Change the current working directory.
253
 *
254
 * @param string $path
255
 */
256
function cd($path)
257
{
258 3
    set('working_path', parse($path));
259 3
}
260
261
/**
262
 * Execute a callback within a specific directory and revert back to the initial working directory.
263
 *
264
 * @param string $path
265
 * @param callable $callback
266
 */
267
function within($path, $callback)
268
{
269
    $lastWorkingPath = workingPath();
270
    set('working_path', $path);
271
    $callback();
272
    set('working_path', $lastWorkingPath);
273
}
274
275
/**
276
 * Return the current working path.
277
 *
278
 * @return string
279
 */
280
function workingPath()
281
{
282 9
    return get('working_path', false);
283
}
284
285
/**
286
 * Run command on server.
287
 *
288
 * @param string $command
289
 * @return Result
290
 */
291
function run($command)
292
{
293 9
    $server = Context::get()->getServer();
294 9
    $serverName = $server->getConfiguration()->getName();
295 9
    $command = parse($command);
296 9
    $workingPath = workingPath();
297
298 9
    if (!empty($workingPath)) {
299 3
        $command = "cd $workingPath && ($command)";
300 3
    }
301
302 9
    if (isVeryVerbose()) {
303
        writeln("[$serverName] <fg=red>></fg=red> $command");
304
    }
305
306 9
    logger("[$serverName] > $command");
307
308 9
    if ($server instanceof Local) {
309
        $output = $server->mustRun($command, function ($type, $buffer) use ($serverName) {
310 9 View Code Duplication
            if (isDebug()) {
311
                output()->writeln(array_map(function ($line) use ($serverName) {
312
                    return output()->isDecorated()
313
                        ? "[$serverName] \033[1;30m< $line\033[0m"
314
                        : "[$serverName] < $line";
315
                }, explode("\n", rtrim($buffer))), OutputInterface::OUTPUT_RAW);
316
            }
317 9
        });
318 9
    } else {
319
        $output = $server->run($command);
320 View Code Duplication
        if (isDebug() && !empty($output)) {
321
            output()->writeln(array_map(function ($line) use ($serverName) {
322
                return output()->isDecorated()
323
                    ? "[$serverName] \033[1;30m< $line\033[0m"
324
                    : "[$serverName] < $line";
325
            }, explode("\n", rtrim($output))), OutputInterface::OUTPUT_RAW);
326
        }
327
    }
328
329 9
    if (!empty(rtrim($output))) {
330 9
        logger("[$serverName] < $output");
331 9
    }
332
333 9
    return new Result($output);
334
}
335
336
/**
337
 * Execute commands on local machine.
338
 * @param string $command Command to run locally.
339
 * @param int $timeout (optional) Override process command timeout in seconds.
340
 * @return Result Output of command.
341
 * @throws \RuntimeException
342
 */
343
function runLocally($command, $timeout = 300)
344
{
345 5
    $command = parse($command);
346
347 5
    if (isVeryVerbose()) {
348
        writeln("[localhost] <fg=red>></fg=red> : $command");
349
    }
350
351 5
    logger("[localhost] > $command");
352
353 5
    $process = new Process($command);
354 5
    $process->setTimeout($timeout);
355
    $process->run(function ($type, $buffer) {
356 4
        if (isDebug()) {
357
            if ('err' === $type) {
358
                write("<fg=red>></fg=red> $buffer");
359
            } else {
360
                write("<fg=green>></fg=green> $buffer");
361
            }
362
        }
363 5
    });
364
365 5
    if (!$process->isSuccessful()) {
366
        throw new ProcessFailedException($process);
367
    }
368
369 5
    $output = $process->getOutput();
370
371 5
    logger("[localhost] < $output");
372
373 5
    return new Result($output);
374
}
375
376
/**
377
 * Run test command.
378
 * Example:
379
 *
380
 *     test('[ -d {{release_path}} ]')
381
 *
382
 * @param string $command
383
 * @return bool
384
 */
385
function test($command)
386
{
387 2
    return run("if $command; then echo 'true'; fi")->toBool();
388
}
389
390
/**
391
 * Run test command locally.
392
 * Example:
393
 *
394
 *     testLocally('[ -d {{local_release_path}} ]')
395
 *
396
 * @param string $command
397
 * @return bool
398
 */
399
function testLocally($command)
400
{
401
    return runLocally("if $command; then echo 'true'; fi")->toBool();
402
}
403
404
/**
405
 * Upload file or directory to current server.
406
 * @param string $local
407
 * @param string $remote
408
 * @throws \RuntimeException
409
 */
410
function upload($local, $remote)
411
{
412 1
    $server = Context::get()->getServer();
413 1
    $local = parse($local);
414 1
    $remote = parse($remote);
415
416 1
    if (is_file($local)) {
417 1
        writeln("Upload file <info>$local</info> to <info>$remote</info>");
418
419 1
        $server->upload($local, $remote);
420 1
    } elseif (is_dir($local)) {
421 1
        writeln("Upload from <info>$local</info> to <info>$remote</info>");
422
423 1
        $finder = new Finder();
424
        $files = $finder
425 1
            ->files()
426 1
            ->ignoreUnreadableDirs()
427 1
            ->ignoreVCS(true)
428 1
            ->ignoreDotFiles(false)
429 1
            ->in($local);
430
431 1
        $progress = null;
432 1
        if (!isDebug()) {
433 1
            $progress = new ProgressBar(output(), count($files));
434 1
        }
435
436
        /** @var $file \Symfony\Component\Finder\SplFileInfo */
437 1
        foreach ($files as $file) {
438 1
            if (isDebug()) {
439
                writeln("Uploading <info>{$file->getRealPath()}</info>");
440
            }
441
442 1
            $server->upload(
443 1
                $file->getRealPath(),
444 1
                $remote . '/' . $file->getRelativePathname()
445 1
            );
446
447 1
            if ($progress) {
448 1
                $progress->advance();
449 1
            }
450 1
        }
451
452 1
        if ($progress) {
453 1
            $progress->finish();
454
            // make sure the "Ok" text will be rendered on a newline
455 1
            output()->writeln('');
456 1
        }
457 1
    } else {
458
        throw new \RuntimeException("Uploading path '$local' does not exist.");
459
    }
460 1
}
461
462
/**
463
 * Download file from remote server.
464
 *
465
 * @param string $local
466
 * @param string $remote
467
 */
468
function download($local, $remote)
469
{
470 2
    $server = Context::get()->getServer();
471 2
    $local = parse($local);
472 2
    $remote = parse($remote);
473
474 2
    writeln("Download file <info>$remote</info> to <info>$local</info>");
475 2
    $server->download($local, $remote);
476 2
}
477
478
/**
479
 * Writes a message to the output and adds a newline at the end.
480
 * @param string|array $message
481
 */
482
function writeln($message)
483
{
484 6
    output()->writeln($message);
485 6
}
486
487
/**
488
 * Writes a message to the output.
489
 * @param string $message
490
 */
491
function write($message)
492
{
493
    output()->write($message);
494
}
495
496
/**
497
 * @param string $message
498
 * @param int $level
499
 */
500
function logger($message, $level = Logger::DEBUG)
501
{
502 13
    if (is_array($message)) {
503
        $message = join("\n", $message);
504
    }
505
506 13
    Deployer::get()->getLogger()->log($level, $message);
507 13
}
508
509
/**
510
 * Setup configuration option.
511
 *
512
 * @param string $name
513
 * @param mixed $value
514
 */
515
function set($name, $value)
516
{
517 11
    if (Context::get() === false) {
518 11
        Deployer::setDefault($name, $value);
519 11
    } else {
520 3
        Context::get()->getEnvironment()->set($name, $value);
521
    }
522 11
}
523
524
/**
525
 * Merge new config params to existing config array.
526
 *
527
 * @param string $name
528
 * @param array $array
529
 */
530
function add($name, $array)
531
{
532
    if (Context::get() === false) {
533
        Deployer::addDefault($name, $array);
534
    } else {
535
        Context::get()->getEnvironment()->add($name, $array);
536
    }
537
}
538
539
/**
540
 * Get configuration value.
541
 *
542
 * @param string $name
543
 * @param mixed|null $default
544
 * @return mixed
545
 */
546
function get($name, $default = null)
547
{
548 16
    if (Context::get() === false) {
549 14
        return Deployer::getDefault($name, $default);
550
    } else {
551 11
        return Context::get()->getEnvironment()->get($name, $default);
552
    }
553
}
554
555
/**
556
 * Check if there is such configuration option.
557
 *
558
 * @param string $name
559
 * @return boolean
560
 */
561
function has($name)
562
{
563 4
    if (Context::get() === false) {
564 2
        return Deployer::hasDefault($name);
565
    } else {
566 2
        return Context::get()->getEnvironment()->has($name);
567
    }
568
}
569
570
/**
571
 * @param string $message
572
 * @param string|null $default
573
 * @param string[]|null $suggestedChoices
574
 * @return string
575
 * @codeCoverageIgnore
576
 */
577
function ask($message, $default = null, $suggestedChoices = null)
578
{
579
    if (($suggestedChoices !== null) && (empty($suggestedChoices))) {
580
        throw new \InvalidArgumentException('Suggested choices should not be empty');
581
    }
582
583
    if (isQuiet()) {
584
        return $default;
585
    }
586
587
    $helper = Deployer::get()->getHelper('question');
588
589
    $message = "<question>$message" . (($default === null) ? "" : " [$default]") . "</question> ";
590
591
    $question = new Question($message, $default);
592
593
    if (empty($suggestedChoices) === false) {
594
        $question->setAutocompleterValues($suggestedChoices);
595
    }
596
597
    return $helper->ask(input(), output(), $question);
598
}
599
600
/**
601
 * @param string $message
602
 * @param string[] $availableChoices
603
 * @param string|null $default
604
 * @param bool|false $multiselect
605
 * @return array
606
 * @codeCoverageIgnore
607
 */
608
function askChoice($message, array $availableChoices, $default = null, $multiselect = false)
609
{
610
    if (empty($availableChoices)) {
611
        throw new \InvalidArgumentException('Available choices should not be empty');
612
    }
613
614
    if ($default !== null && !array_key_exists($default, $availableChoices)) {
615
        throw new \InvalidArgumentException('Default choice is not available');
616
    }
617
618
    if (isQuiet()) {
619
        if ($default === null) {
620
            $default = key($availableChoices);
621
        }
622
        return [ $default => $availableChoices[$default] ];
623
    }
624
625
    $helper = Deployer::get()->getHelper('question');
626
627
    $message = "<question>$message" . (($default === null) ? "" : " [$default]") . "</question> ";
628
629
    $question = new ChoiceQuestion($message, $availableChoices, $default);
630
    $question->setMultiselect($multiselect);
631
632
    return $helper->ask(input(), output(), $question);
633
}
634
635
/**
636
 * @param string $message
637
 * @param bool $default
638
 * @return bool
639
 * @codeCoverageIgnore
640
 */
641
function askConfirmation($message, $default = false)
642
{
643
    if (isQuiet()) {
644
        return $default;
645
    }
646
647
    $helper = Deployer::get()->getHelper('question');
648
649
    $yesOrNo = $default ? 'Y/n' : 'y/N';
650
    $message = "<question>$message [$yesOrNo]</question> ";
651
652
    $question = new ConfirmationQuestion($message, $default);
653
654
    return $helper->ask(input(), output(), $question);
655
}
656
657
/**
658
 * @param string $message
659
 * @return string
660
 * @codeCoverageIgnore
661
 */
662
function askHiddenResponse($message)
663
{
664
    if (isQuiet()) {
665
        return '';
666
    }
667
668
    $helper = Deployer::get()->getHelper('question');
669
670
    $message = "<question>$message</question> ";
671
672
    $question = new Question($message);
673
    $question->setHidden(true);
674
    $question->setHiddenFallback(false);
675
676
    return $helper->ask(input(), output(), $question);
677
}
678
679
/**
680
 * @return InputInterface
681
 */
682
function input()
683
{
684
    return Context::get()->getInput();
685
}
686
687
688
/**
689
 * @return OutputInterface
690
 */
691
function output()
692
{
693 16
    return Context::get()->getOutput();
694
}
695
696
/**
697
 * @return bool
698
 */
699
function isQuiet()
700
{
701
    return OutputInterface::VERBOSITY_QUIET === output()->getVerbosity();
702
}
703
704
705
/**
706
 * @return bool
707
 */
708
function isVerbose()
709
{
710
    return OutputInterface::VERBOSITY_VERBOSE <= output()->getVerbosity();
711
}
712
713
714
/**
715
 * @return bool
716
 */
717
function isVeryVerbose()
718
{
719 13
    return OutputInterface::VERBOSITY_VERY_VERBOSE <= output()->getVerbosity();
720
}
721
722
723
/**
724
 * @return bool
725
 */
726
function isDebug()
727
{
728 14
    return OutputInterface::VERBOSITY_DEBUG <= output()->getVerbosity();
729
}
730
731
/**
732
 * Deprecated, use set()/get().
733
 * @deprecated
734
 */
735
function env()
736
{
737
    throw new \RuntimeException('env() function deprecated. Please, use set() or get() instead of.');
738
}
739
740
/**
741
 * Check if command exist in bash.
742
 *
743
 * @param string $command
744
 * @return bool
745
 */
746
function commandExist($command)
747
{
748
    return run("if hash $command 2>/dev/null; then echo 'true'; fi")->toBool();
749
}
750
751
/**
752
 * Parse set values.
753
 *
754
 * @param string $value
755
 * @return string
756
 */
757
function parse($value)
758
{
759 16
    return Context::get()->getEnvironment()->parse($value);
760
}
761