Passed
Push — master ( 800fb3...1ce7d0 )
by Tom
04:22
created

Runner::getProjectDirectory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
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 Env
37
     */
38
    private $env;
39
40
    /**
41
     * @var Flags
42
     */
43
    private $flags;
44
45
    /**
46
     * @var Streams
47
     */
48
    private $streams;
49
50
    /**
51
     * Static factory method.
52
     *
53
     * The "ex" version of runner creation, moving creation out of the ctor itself.
54
     *
55
     * @param RunOpts $runOpts
56
     * @param Directories $directories source repository root directory based directories object
57
     * @param Exec $exec
58
     * @param Flags $flags [optional]
59
     * @param Env $env [optional]
60
     * @param Streams $streams [optional]
61
     *
62
     * @return Runner
63
     */
64 1
    public static function createEx(
65
        RunOpts $runOpts,
66
        Directories $directories,
67
        Exec $exec,
68
        Flags $flags = null,
69
        Env $env = null,
70
        Streams $streams = null
71
    )
72
    {
73 1
        $flags = null === $flags ? new Flags() : $flags;
74 1
        $env = null === $env ? Env::createEx() : $env;
75 1
        $streams = null === $streams ? Streams::create() : $streams;
76
77 1
        return new self($runOpts, $directories, $exec, $flags, $env, $streams);
78
    }
79
80
    /**
81
     * Runner constructor.
82
     *
83
     * @param RunOpts $runOpts
84
     * @param Directories $directories source repository root directory based directories object
85
     * @param Exec $exec
86
     * @param Flags $flags
87
     * @param Env $env
88
     * @param Streams $streams
89
     */
90 7
    public function __construct(
91
        RunOpts $runOpts,
92
        Directories $directories,
93
        Exec $exec,
94
        Flags $flags,
95
        Env $env,
96
        Streams $streams
97
    )
98
    {
99 7
        $this->runOpts = $runOpts;
100 7
        $this->directories = $directories;
101 7
        $this->exec = $exec;
102 7
        $this->flags = $flags;
103 7
        $this->env = $env;
104 7
        $this->streams = $streams;
105 7
    }
106
107
    /**
108
     * @param Pipeline $pipeline
109
     *
110
     * @throws \RuntimeException
111
     *
112
     * @return int status (as in exit status, 0 OK, !0 NOK)
113
     */
114 5
    public function run(Pipeline $pipeline)
115
    {
116 5
        $hasId = $this->env->setPipelinesId($pipeline->getId()); # TODO give Env an addPipeline() method (compare addReference)
117 5
        if ($hasId) {
118 1
            $this->streams->err(sprintf(
119 1
                "pipelines: won't start pipeline '%s'; pipeline inside pipelines recursion detected\n",
120 1
                $pipeline->getId()
121
            ));
122
123 1
            return self::STATUS_RECURSION_DETECTED;
124
        }
125
126 4
        $steps = $pipeline->getSteps()->getIterator();
127 4
        $steps->setNoManual($this->runOpts->isNoManual());
128 4
        list($status, $steps) = $this->runSteps($steps);
129
130 4
        if (0 === $status && $steps->isManual()) {
131 1
            $this->streams->err(sprintf(
132 1
                "pipelines: step #%d is manual. use `--steps %d-` to continue or `--no-manual` to override\n",
133 1
                $steps->getStepIndex() + 1,
134 1
                $steps->getStepIndex() + 1
135
            ));
136
        }
137
138 4
        return $status;
139
    }
140
141
    /**
142
     * @param Step $step
143
     *
144
     * @return int status (as in exit status, 0 OK, !0 NOK)
145
     */
146 2
    public function runStep(Step $step)
147
    {
148 2
        $stepRunner = new StepRunner($this);
149
150 2
        return $stepRunner->runStep($step);
151
    }
152
153
    /**
154
     * @return RunOpts
155
     */
156 2
    public function getRunOpts()
157
    {
158 2
        return $this->runOpts;
159
    }
160
161
    /**
162
     * @return Directories
163
     */
164 2
    public function getDirectories()
165
    {
166 2
        return $this->directories;
167
    }
168
169
    /**
170
     * @return Exec
171
     */
172 2
    public function getExec()
173
    {
174 2
        return $this->exec;
175
    }
176
177
    /**
178
     * @return Env
179
     */
180 2
    public function getEnv()
181
    {
182 2
        return $this->env;
183
    }
184
185
    /**
186
     * @return Flags
187
     */
188 2
    public function getFlags()
189
    {
190 2
        return $this->flags;
191
    }
192
193
    /**
194
     * @return Streams
195
     */
196 2
    public function getStreams()
197
    {
198 2
        return $this->streams;
199
    }
200
201
    /**
202
     * Project name (basename) in runner context (as used in running pipelines)
203
     *
204
     * @return string
205
     */
206 2
    public function getProject()
207
    {
208 2
        return $this->env->getValue('BITBUCKET_REPO_SLUG') ?: $this->directories->getName();
209
    }
210
211
    /**
212
     * Project directory
213
     *
214
     * @return string
215
     */
216 3
    public function getProjectDirectory()
217
    {
218 3
        return $this->getDirectories()->getProjectDirectory();
219
    }
220
221
    /**
222
     * Get Prefix
223
     *
224
     * The prefix is used when creating containers for the container name and
225
     * acts as name-spacing for pipelines resources (like containers).
226
     *
227
     * The default prefix is "pipelines", see --prefix option.
228
     *
229
     * @see Prefix::verify()
230
     *
231
     * @return string
232
     */
233 2
    public function getPrefix()
234
    {
235 2
        return $this->runOpts->getPrefix();
236
    }
237
238
    /**
239
     * @param Pipeline\StepsIterator $steps
240
     *
241
     * @return array(int, Pipeline\StepsIterator)
242
     */
243 4
    private function runSteps(Pipeline\StepsIterator $steps)
244
    {
245 4
        foreach ($steps as $step) {
246 3
            $status = $this->runStep($step);
247 3
            if (0 !== $status) {
248 1
                break;
249
            }
250 2
            $this->env->resetStepRunNumber();
251
        }
252
253 4
        if (!isset($status)) {
254 1
            $this->streams->err("pipelines: pipeline with no step to execute\n");
255
256 1
            return array(self::STATUS_NO_STEPS, $steps);
257
        }
258
259 3
        return array($status, $steps);
260
    }
261
}
262