Test Failed
Push — test ( 9d8e99...8d4b30 )
by Tom
03:04
created

Env::setPipelinesProjectPath()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 5
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 12
ccs 2
cts 2
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\Args\Args;
8
use Ktomk\Pipelines\Cli\Args\Collector;
9
use Ktomk\Pipelines\Lib;
10
11
/**
12
 * Pipeline environment collaborator
13
 */
14
class Env
15
{
16
    /**
17
     * @var array pipelines (bitbucket) environment variables
18
     */
19
    private $vars = array();
20
21
    /**
22
     * collected arguments
23
     *
24
     * @var array
25
     */
26
    private $collected = array();
27
28
    /**
29
     * environment variables to inherit from
30
     *
31
     * @var array
32
     */
33
    private $inherit = array();
34
35
    /**
36
     * @var null|EnvResolver
37
     */
38
    private $resolver;
39
40
    /**
41
     * @param null|array $inherit
42
     *
43
     * @return Env
44 15
     */
45
    public static function create(array $inherit = array())
46 15
    {
47 15
        $env = new self();
48
        $env->initDefaultVars($inherit);
49 15
50
        return $env;
51
    }
52
53
    /**
54
     * Initialize default environment used in a Bitbucket Pipeline
55
     *
56
     * As the runner mimic some values, defaults are available
57
     *
58
     * @param array $inherit Environment variable store to inherit from
59 18
     */
60
    public function initDefaultVars(array $inherit)
61 18
    {
62
        $this->inherit = $inherit;
63
64 18
        $inheritable = array(
65
            'BITBUCKET_BOOKMARK' => null,
66 18
            'BITBUCKET_BRANCH' => null,
67 18
            'BITBUCKET_BUILD_NUMBER' => '0',
68 18
            'BITBUCKET_COMMIT' => '0000000000000000000000000000000000000000',
69 18
            'BITBUCKET_REPO_OWNER' => '' . Lib::r($inherit['USER'], 'nobody'),
70
            'BITBUCKET_REPO_SLUG' => 'local-has-no-slug',
71 18
            'BITBUCKET_TAG' => null,
72
            'CI' => 'true',
73
            'PIPELINES_CONTAINER_NAME' => null,
74
            'PIPELINES_IDS' => null,
75
            'PIPELINES_PARENT_CONTAINER_NAME' => null,
76
            'PIPELINES_PROJECT_PATH' => null,
77
        );
78 18
79
        $invariant = array(
80
            'PIPELINES_ID' => null,
81 18
        );
82 18
83
        foreach ($inheritable as $name => $value) {
84
            isset($inherit[$name]) ? $inheritable[$name] = $inherit[$name] : null;
85 18
        }
86 18
87
        $var = $invariant + $inheritable;
88 18
        ksort($var);
89 18
90
        $this->vars = $var;
91
    }
92
93
    /**
94
     * Map reference to environment variable setting
95
     *
96
     * Only add the BITBUCKET_BOOKMARK/_BRANCH/_TAG variable
97
     * if not yet set.
98
     *
99 4
     * @param Reference $ref
100
     */
101 4
    public function addReference(Reference $ref)
102 2
    {
103
        if (null === $type = $ref->getType()) {
104
            return;
105
        }
106 4
107
        $map = array(
108
            'bookmark' => 'BITBUCKET_BOOKMARK',
109
            'branch' => 'BITBUCKET_BRANCH',
110
            'tag' => 'BITBUCKET_TAG',
111
            'pr' => 'BITBUCKET_BRANCH',
112 4
        );
113 1
114
        if (!isset($map[$type])) {
115 3
            throw new \UnexpectedValueException(sprintf('Unknown reference type: "%s"', $type));
116
        }
117 3
        $var = $map[$type];
118 2
119
        if (!isset($this->vars[$var])) {
120 3
            $this->vars[$var] = $ref->getName();
121
        }
122
    }
123
124
    /**
125 2
     * @param string $name of container
126
     */
127 2
    public function setContainerName($name)
128 2
    {
129 2
        if (isset($this->vars['PIPELINES_CONTAINER_NAME'])) {
130
            $this->vars['PIPELINES_PARENT_CONTAINER_NAME']
131
                = $this->vars['PIPELINES_CONTAINER_NAME'];
132 2
        }
133 2
134
        $this->vars['PIPELINES_CONTAINER_NAME'] = $name;
135
    }
136
137
    /**
138
     * set the pipelines environment's running pipeline id
139
     *
140
     * @param string $id of pipeline, e.g. "default" or "branch/feature/*"
141 1
     *
142
     * @return bool whether was used before (endless pipelines in pipelines loop)
143 1
     */
144 1
    public function setPipelinesId($id)
145 1
    {
146
        $list = (string)$this->getValue('PIPELINES_IDS');
147 1
        $hashes = preg_split('~\s+~', $list, -1, PREG_SPLIT_NO_EMPTY);
148 1
        $hashes = array_map('strtolower', /** @scrutinizer ignore-type */ $hashes);
149 1
150
        $idHash = md5($id);
151 1
        $hasId = in_array($idHash, $hashes, true);
152 1
        $hashes[] = $idHash;
153
154 1
        $this->vars['PIPELINES_ID'] = $id;
155
        $this->vars['PIPELINES_IDS'] = implode(' ', $hashes);
156
157
        return $hasId;
158
    }
159
160
    /**
161 12
     * set PIPELINES_PROJECT_PATH
162
     *
163 12
     * can never be overwritten, must be set by pipelines itself for the
164
     * initial pipeline. will be taken over into each sub-pipeline.
165 12
     *
166 11
     * @param string $path absolute path to the project directory (deploy source path)
167 11
     */
168
    public function setPipelinesProjectPath($path)
169
    {
170 12
        // TODO $path must be absolute
171
172
        if (isset($this->vars['PIPELINES_PROJECT_PATH'])
173
            || !isset($this->vars['PIPELINES_ID'], $this->vars['PIPELINES_IDS'])
174
            || $this->vars['PIPELINES_IDS'] !== md5($this->vars['PIPELINES_ID'])
175
        ) {
176
            return;
177
        }
178
179 5
        $this->vars['PIPELINES_PROJECT_PATH'] = $path;
180
    }
181 5
182 4
    /**
183 5
     * @param null|string $default [optional]
184
     *
185
     * @return null|string
186
     */
187
    public function getPipelinesProjectPath($default = null)
188
    {
189
        if (isset($this->vars['PIPELINES_PROJECT_PATH'])) {
190
            return $this->vars['PIPELINES_PROJECT_PATH'];
191
        }
192
193
        return $default;
194
    }
195
196
    /**
197
     * @param string $option "-e" typically for Docker binary
198 1
     *
199
     * @return array of options (from $option) and values, ['-e', 'val1', '-e', 'val2', ...]
200 1
     */
201 1
    public function getArgs($option)
202 1
    {
203
        $args = $this->collected;
204 1
205 1
        foreach ($this->getVarDefinitions() as $definition) {
206
            $args[] = $option;
207
            $args[] = $definition;
208
        }
209
210
        return $args;
211 2
    }
212
213 2
    /**
214 2
     * get a variables value or null if not set
215 2
     *
216 2
     * @param string $name
217 2
     *
218
     * @return null|string
219
     */
220 2
    public function getValue($name)
221
    {
222
        return isset($this->vars[$name])
223
            ? $this->vars[$name]
224
            : null;
225 4
    }
226
227 4
    /**
228 4
     * collect option arguments
229
     *
230
     * those options to be passed to docker client, normally -e,
231 4
     * --env and --env-file.
232
     *
233
     * @param Args $args
234
     * @param string|string[] $option
235
     *
236
     * @throws \InvalidArgumentException
237 12
     * @throws \Ktomk\Pipelines\Cli\ArgsException
238
     */
239 12
    public function collect(Args $args, $option)
240
    {
241 12
        $collector = new Collector($args);
242 11
        $collector->collect($option);
243 11
        $this->collected = array_merge($this->collected, $collector->getArgs());
244
245
        $this->getResolver()->addArguments($collector);
246
    }
247 12
248
    /**
249
     * @param array $paths
250
     *
251
     * @throws \InvalidArgumentException
252
     */
253
    public function collectFiles(array $paths)
254
    {
255
        $resolver = $this->getResolver();
256
        foreach ($paths as $path) {
257
            if ($resolver->addFileIfExists($path)) {
258
                $this->collected[] = '--env-file';
259
                $this->collected[] = $path;
260
            }
261
        }
262
    }
263
264
    /**
265
     * @return EnvResolver
266
     */
267
    public function getResolver()
268
    {
269
        if (null === $this->resolver) {
270
            $this->resolver = new EnvResolver($this->inherit);
271
        }
272
273
        return $this->resolver;
274
    }
275
276
    /**
277
     * @return array w/ a string variable definition (name=value) per value
278
     */
279
    private function getVarDefinitions()
280
    {
281
        $array = array();
282
283
        foreach ($this->vars as $name => $value) {
284
            if (isset($value)) {
285
                $array[] = sprintf('%s=%s', $name, $value);
286
            }
287
        }
288
289
        return $array;
290
    }
291
}
292