Passed
Push — steps ( cace08...74de34 )
by Tom
02:51
created

Runner::run()   B

Complexity

Conditions 6
Paths 8

Size

Total Lines 38
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 6

Importance

Changes 0
Metric Value
cc 6
eloc 22
nc 8
nop 1
dl 0
loc 38
ccs 23
cts 23
cp 1
crap 6
rs 8.9457
c 0
b 0
f 0
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines\Runner;
6
7
use Ktomk\Pipelines\Cli\Exec;
8
use Ktomk\Pipelines\Cli\Streams;
9
use Ktomk\Pipelines\File\Pipeline;
10
use Ktomk\Pipelines\File\Pipeline\Step;
11
12
/**
13
 * Pipeline runner with docker under the hood
14
 */
15
class Runner
16
{
17
    const STATUS_NO_STEPS = 1;
18
    const STATUS_RECURSION_DETECTED = 127;
19
20
    /**
21
     * @var RunOpts
22
     */
23
    private $runOpts;
24
25
    /**
26
     * @var Directories
27
     */
28
    private $directories;
29
30
    /**
31
     * @var Exec
32
     */
33
    private $exec;
34
35
    /**
36
     * @var Flags
37
     */
38
    private $flags;
39
40
    /**
41
     * @var Env
42
     */
43
    private $env;
44
    /**
45
     * @var Streams
46
     */
47
    private $streams;
48
49
    /**
50
     * Static factory method.
51
     *
52
     * The "ex" version of runner creation, moving creation out of the ctor itself.
53
     *
54
     * @param RunOpts $runOpts
55
     * @param Directories $directories source repository root directory based directories object
56
     * @param Exec $exec
57
     * @param Flags $flags [optional]
58
     * @param Env $env [optional]
59
     * @param Streams $streams [optional]
60
     * @return Runner
61
     */
62 1
    public static function createEx(
63
        RunOpts $runOpts,
64
        Directories $directories,
65
        Exec $exec,
66
        Flags $flags = null,
67
        Env $env = null,
68
        Streams $streams = null
69
    )
70
    {
71 1
        $flags = null === $flags ? new Flags() : $flags;
72 1
        $env = null === $env ? Env::create() : $env;
73 1
        $streams = null === $streams ? Streams::create() : $streams;
74
75 1
        return new self($runOpts, $directories, $exec, $flags, $env, $streams);
76
    }
77
78
    /**
79
     * Runner constructor.
80
     *
81
     * @param string $runOpts
82
     * @param Directories $directories source repository root directory based directories object
83
     * @param Exec $exec
84
     * @param Flags $flags
85
     * @param Env $env
86
     * @param Streams $streams
87
     */
88 7
    public function __construct(
89
        RunOpts $runOpts,
90
        Directories $directories,
91
        Exec $exec,
92
        Flags $flags,
93
        Env $env,
94
        Streams $streams
95
    )
96
    {
97 7
        $this->runOpts = $runOpts;
98 7
        $this->directories = $directories;
99 7
        $this->exec = $exec;
100 7
        $this->flags = $flags;
101 7
        $this->env = $env;
102 7
        $this->streams = $streams;
103 7
    }
104
105
    /**
106
     * @param Pipeline $pipeline
107
     * @throws \RuntimeException
108
     * @return int status (as in exit status, 0 OK, !0 NOK)
109
     */
110 5
    public function run(Pipeline $pipeline)
111
    {
112 5
        $hasId = $this->env->setPipelinesId($pipeline->getId()); # TODO give Env an addPipeline() method (compare addReference)
113 5
        if ($hasId) {
114 1
            $this->streams->err(sprintf(
115 1
                "pipelines: won't start pipeline '%s'; pipeline inside pipelines recursion detected\n",
116 1
                $pipeline->getId()
117
            ));
118
119 1
            return self::STATUS_RECURSION_DETECTED;
120
        }
121
122 4
        $steps = $pipeline->getSteps()->getIterator();
123 4
        $steps->setNoManual($this->runOpts->isNoManual());
124 4
        foreach ($steps as $step) {
125 3
            $status = $this->runStep($step);
126 3
            if (0 !== $status) {
127 1
                return $status;
128
            }
129
        }
130
131 3
        if ($steps->isManual()) {
132 1
            $this->streams->out(sprintf(
133 1
                "pipelines: step #%d is manual. use `--steps %d-` to continue or `--no-manual` to override\n",
134 1
                $steps->getStepIndex() + 1,
135 1
                $steps->getStepIndex() + 1
136
            ));
137
138 1
            return 0;
139
        }
140
141 2
        if (!isset($status)) {
142 1
            $this->streams->err("pipelines: pipeline with no step to execute\n");
143
144 1
            return self::STATUS_NO_STEPS;
145
        }
146
147 1
        return $status;
148
    }
149
150
    /**
151
     * @param \Ktomk\Pipelines\File\Pipeline\Step $step
152
     *
153
     * @return int status (as in exit status, 0 OK, !0 NOK)
154
     */
155 2
    public function runStep(Step $step) {
156 2
        $stepRunner = new StepRunner(
157 2
            $this->runOpts,
158 2
            $this->directories,
159 2
            $this->exec,
160 2
            $this->flags,
161 2
            $this->env,
162 2
            $this->streams
163
        );
164
165 2
        return $stepRunner->runStep($step);
166
    }
167
}
168