Passed
Push — steps ( 0036b0...307a73 )
by Tom
02:42
created

Runner::runSteps()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 8
c 1
b 0
f 0
nc 6
nop 1
dl 0
loc 16
ccs 9
cts 9
cp 1
crap 4
rs 10
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
     *
61
     * @return Runner
62
     */
63 1
    public static function createEx(
64
        RunOpts $runOpts,
65
        Directories $directories,
66
        Exec $exec,
67
        Flags $flags = null,
68
        Env $env = null,
69
        Streams $streams = null
70
    )
71
    {
72 1
        $flags = null === $flags ? new Flags() : $flags;
73 1
        $env = null === $env ? Env::create() : $env;
74 1
        $streams = null === $streams ? Streams::create() : $streams;
75
76 1
        return new self($runOpts, $directories, $exec, $flags, $env, $streams);
77
    }
78
79
    /**
80
     * Runner constructor.
81
     *
82
     * @param string $runOpts
83
     * @param Directories $directories source repository root directory based directories object
84
     * @param Exec $exec
85
     * @param Flags $flags
86
     * @param Env $env
87
     * @param Streams $streams
88
     */
89 7
    public function __construct(
90
        RunOpts $runOpts,
91
        Directories $directories,
92
        Exec $exec,
93
        Flags $flags,
94
        Env $env,
95
        Streams $streams
96
    )
97
    {
98 7
        $this->runOpts = $runOpts;
99 7
        $this->directories = $directories;
100 7
        $this->exec = $exec;
101 7
        $this->flags = $flags;
102 7
        $this->env = $env;
103 7
        $this->streams = $streams;
104 7
    }
105
106
    /**
107
     * @param Pipeline $pipeline
108
     *
109
     * @throws \RuntimeException
110
     * @return int status (as in exit status, 0 OK, !0 NOK)
111
     */
112 5
    public function run(Pipeline $pipeline)
113
    {
114 5
        $hasId = $this->env->setPipelinesId($pipeline->getId()); # TODO give Env an addPipeline() method (compare addReference)
115 5
        if ($hasId) {
116 1
            $this->streams->err(sprintf(
117 1
                "pipelines: won't start pipeline '%s'; pipeline inside pipelines recursion detected\n",
118 1
                $pipeline->getId()
119
            ));
120
121 1
            return self::STATUS_RECURSION_DETECTED;
122
        }
123
124 4
        $steps = $pipeline->getSteps()->getIterator();
125 4
        $steps->setNoManual($this->runOpts->isNoManual());
126 4
        list($status, $steps) = $this->runSteps($steps);
127
128 4
        if (0 === $status && $steps->isManual()) {
129 1
            $this->streams->err(sprintf(
130 1
                "pipelines: step #%d is manual. use `--steps %d-` to continue or `--no-manual` to override\n",
131 1
                $steps->getStepIndex() + 1,
132 1
                $steps->getStepIndex() + 1
133
            ));
134
        }
135
136 4
        return $status;
137
    }
138
139
    /**
140
     * @param \Ktomk\Pipelines\File\Pipeline\Step $step
141
     *
142
     * @return int status (as in exit status, 0 OK, !0 NOK)
143
     */
144 2
    public function runStep(Step $step)
145
    {
146 2
        $stepRunner = new StepRunner(
147 2
            $this->runOpts,
148 2
            $this->directories,
149 2
            $this->exec,
150 2
            $this->flags,
151 2
            $this->env,
152 2
            $this->streams
153
        );
154
155 2
        return $stepRunner->runStep($step);
156
    }
157
158
    /**
159
     * @param Pipeline\StepsIterator $steps
160
     *
161
     * @return array(int, Pipeline\StepsIterator)
162
     */
163 4
    private function runSteps(Pipeline\StepsIterator $steps)
164
    {
165 4
        foreach ($steps as $step) {
166 3
            $status = $this->runStep($step);
167 3
            if (0 !== $status) {
168 1
                break;
169
            }
170
        }
171
172 4
        if (!isset($status)) {
173 1
            $this->streams->err("pipelines: pipeline with no step to execute\n");
174
175 1
            return array(self::STATUS_NO_STEPS, $steps);
176
        }
177
178 3
        return array($status, $steps);
179
    }
180
}
181