Passed
Push — master ( a18808...143631 )
by Tom
04:16
created

StepScriptRunner::runStepScript()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 17
c 1
b 0
f 0
nc 6
nop 4
dl 0
loc 28
ccs 18
cts 18
cp 1
crap 4
rs 9.7
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\Step;
10
use Ktomk\Pipelines\Lib;
11
12
/**
13
 * Class StepScriptRunner
14
 *
15
 * Running step and after-step scripts or exec scripts in a running docker container
16
 *
17
 * @package Ktomk\Pipelines\Runner
18
 *
19
 * @see StepRunner::runStepScript
20
 */
21
class StepScriptRunner
22
{
23
    /**
24
     * Static factory method to create a run step script
25
     *
26
     * @param Step $step
27
     * @param Streams $streams
28
     * @param Exec $exec
29
     * @param string $name container name
30
     *
31
     * @return int status of step script, non-zero if a script command failed
32
     */
33 1
    public static function createRunStepScript(Step $step, Streams $streams, Exec $exec, $name)
34
    {
35 1
        $runner = new self();
36
37 1
        return $runner->runStepScript($step, $streams, $exec, $name);
38
    }
39
40
    /**
41
     * @param Step $step
42
     * @param Streams $streams
43
     * @param Exec $exec
44
     * @param string $name container name
45
     *
46
     * @return int status of step script, non-zero if a script command failed
47
     */
48 4
    public function runStepScript(Step $step, Streams $streams, Exec $exec, $name)
49
    {
50 4
        $buffer = "# this /bin/sh script is generated from a pipeline step.\n";
51 4
        $buffer .= "set -e\n";
52 4
        $buffer .= $this->generateScript($step->getScript());
53
54 4
        $status = $this->execScript($buffer, $exec, $name);
55 4
        if (0 !== $status) {
56 2
            $streams->err(sprintf("script non-zero exit status: %d\n", $status));
57
        }
58
59 4
        if (!($script = $step->getAfterScript())) {
60 3
            return $status;
61
        }
62
63 1
        $streams->out("After script:\n");
64
65 1
        $buffer = "# pipelines generated after-script.\n";
66 1
        $buffer .= sprintf("BITBUCKET_EXIT_CODE=%d\n", $status);
67 1
        $buffer .= "export BITBUCKET_EXIT_CODE\n";
68 1
        $buffer .= $this->generateScript($script);
69
70 1
        $afterStatus = $this->execScript($buffer, $exec, $name);
71 1
        if (0 !== $afterStatus) {
72 1
            $streams->err(sprintf("after-script non-zero exit status: %d\n", $afterStatus));
73
        }
74
75 1
        return $status;
76
    }
77
78
    /**
79
     *
80
     * @param string $script "\n" terminated script lines
81
     * @param Exec $exec
82
     * @param string $name
83
     *
84
     * @return int
85
     */
86 4
    private function execScript($script, Exec $exec, $name)
87
    {
88 4
        $buffer = Lib::cmd("<<'SCRIPT' docker", array(
89 4
                'exec', '-i', $name, '/bin/sh',
90 4
            )) . "\n";
91 4
        $buffer .= $script;
92 4
        $buffer .= "SCRIPT\n";
93
94 4
        return $exec->pass($buffer, array());
95
    }
96
97
    /**
98
     * @param array|string[] $script
99
     *
100
     * @return string
101
     */
102 4
    private function generateScript(array $script)
103
    {
104 4
        $buffer = '';
105 4
        foreach ($script as $index => $line) {
106 3
            $command = $this->generateCommand($line);
107 3
            $line && $buffer .= 'printf \'\\n\'' . "\n";
108 3
            $buffer .= 'printf \'\\035+ %s\\n\' ' . Lib::quoteArg($command) . "\n";
109 3
            $buffer .= $command . "\n";
110
        }
111
112 4
        return $buffer;
113
    }
114
115
    /**
116
     * @param array|string $line
117
     *
118
     * @return string
119
     */
120 3
    private function generateCommand($line)
121
    {
122 3
        $standard = is_scalar($line) || null === $line;
123 3
        $pipe = is_array($line) && isset($line['pipe']) && is_string($line['pipe']);
124
125 3
        if ($standard) {
126 3
            return (string)$line;
127
        }
128
129 1
        $buffer = '';
130
131 1
        if ($pipe) {
132 1
            $buffer .= "echo \"pipe: {$line['pipe']} (pending feature)\" # pipe feature is pending\n";
133 1
            if (isset($line['variables']) && is_array($line['variables'])) {
134 1
                foreach ($line['variables'] as $name => $value) {
135 1
                    $buffer .= "echo '  ${name} (${value}):' ${value}\n";
136
                }
137
            }
138
        }
139
140 1
        return $buffer;
141
    }
142
}
143