GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( bca213...99993e )
by Sam
03:50
created

Module::createEntrypoint()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 58
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 3.0987

Importance

Changes 0
Metric Value
dl 0
loc 58
ccs 14
cts 18
cp 0.7778
rs 9.639
c 0
b 0
f 0
cc 3
eloc 24
nc 4
nop 0
crap 3.0987

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
declare(strict_types=1);
3
4
namespace SamIT\Yii2\PhpFpm;
5
6
use Docker\Context\Context;
7
use Docker\Context\ContextBuilder;
8
use yii\base\InvalidConfigException;
9
use yii\helpers\Console;
10
use yii\mutex\Mutex;
11
12
class Module extends \yii\base\Module
13
{
14
15
    /**
16
     * @var bool Whether the container should attempt to run migrations on launch.
17
     */
18
    public $runMigrations = false;
19
20
    /**
21
     * @var bool whether migrations should acquire a lock.
22
     * It must be configured in the 'mutex' component of this module or the application
23
     * Note that this mutex must be shared between all instances of your application.
24
     * Consider using something like redis or mysql mutex.
25
     */
26
    public $migrationsUseMutex = true;
27
28
    /**
29
     * The variables will be written to /runtime/env.json as JSON, where your application can read them.
30
     * @var string[] List of required environment variables. If one is missing the container will exit.
31
     *
32
     */
33
    public $environmentVariables = [];
34
35
    /**
36
     * @var array Pool directives
37
     * @see http://php.net/manual/en/install.fpm.configuration.php
38
     *
39
     */
40
    public $poolConfig = [
41
        'user' => 'nobody',
42
        'group' => 'nobody',
43
        'listen' => 9000,
44
        'pm' => 'dynamic',
45
        'pm.max_children' => 40,
46
        'pm.start_servers' => 3,
47
        'pm.min_spare_servers' => 1,
48
        'pm.max_spare_servers' => 3,
49
        'access.log' => '/proc/self/fd/2',
50
        'clear_env' => 'yes',
51
        'catch_workers_output' => 'yes'
52
    ];
53
54
    /**
55
     * @var array PHP configuration, supplied via php_admin_value in fpm config.
56
     */
57
    public $phpConfig = [
58
        'upload_max_filesize' => '20M',
59
        'post_max_size' => '25M'
60
    ];
61
62
    /**
63
     * @var array Global directives
64
     * @see http://php.net/manual/en/install.fpm.configuration.php
65
     *
66
     */
67
    public $fpmConfig = [
68
        'error_log' => '/proc/self/fd/2',
69
        'daemonize' => 'no',
70
    ];
71
72
    public $extensions = [
73
        'ctype',
74
        'gd',
75
        'iconv',
76
        'intl',
77
        'json',
78
        'mbstring',
79
        'session',
80
        'pdo_mysql',
81
        'session',
82
        'curl'
83
    ];
84
85
    /**
86
     * @var string The name of the created image.
87
     */
88
    public $image;
89
90
    /**
91
     * @var string The tag of the created image.
92
     */
93
    public $tag = 'latest';
94
95
    /**
96
     * @var bool wheter to push successful builds.
97
     */
98
    public $push = false;
99
100
    /**
101
     * @var string Location of composer.json / composer.lock
102
     */
103
    public $composerFilePath = '@app/../';
104
    /**
105
     * @return string A PHP-FPM config file.
106
     */
107 3
    protected function createFpmConfig()
108
    {
109 3
        $config = [];
110
        // Add global directives.
111 3
        if (!empty($this->fpmConfig)) {
112 3
            $config[] = '[global]';
113 3
            foreach ($this->fpmConfig as $key => $value) {
114 3
                $config[] = "$key = $value";
115
            }
116
        }
117
118
        // Add pool directives.
119 3
        $poolConfig = $this->poolConfig;
120 3
        foreach($this->phpConfig as $key => $value) {
121 3
            $poolConfig["php_admin_value[$key]"] = $value;
122
        }
123
124 3
        if (!empty($poolConfig)) {
125 3
            $config[] = '[www]';
126 3
            foreach ($poolConfig as $key => $value) {
127 3
                $config[] = "$key = $value";
128
            }
129
        }
130
131 3
        return \implode("\n", $config);
132
    }
133
134
    /**
135
     * @return string A shell script that checks for existence of (non-empty) variables and runs php-fpm.
136
     */
137 3
    protected function createEntrypoint(): string
138
    {
139
        // Get the route.
140 3
        $route = "{$this->getUniqueId()}/migrate/up";
141 3
        $script = "/project/{$this->getConsoleEntryScript()}";
142 3
        $result = [];
143 3
        $result[] = '#!/bin/sh';
144
        // Check for variables.
145 3
        foreach($this->environmentVariables as $name) {
146
            $result[] = \strtr('if [ -z "${name}" ]; then echo "Variable \${name} is required."; exit 1; fi', [
147
                '{name}' => $name
148
            ]);
149
        }
150
151 3
        if ($this->runMigrations) {
152
            $result[] = <<<SH
153
ATTEMPTS=0
154
while [ \$ATTEMPTS -lt 10 ]; do
155
  # First run migrations.
156
  $script $route --interactive=0
157
  if [ $? -eq 0 ]; then
158
    echo "Migrations done";
159
    break;
160
  fi
161
  echo "Failed to run migrations, retrying in 10s.";
162
  sleep 10;
163
  let ATTEMPTS=ATTEMPTS+1
164
done
165
166
if [ \$ATTEMPTS -gt 9 ]; then
167
  echo "Migrations failed.."
168
  exit 1;
169
fi
170
SH;
171
        }
172
        // Check if runtime directory is writable.
173 3
        $result[] = <<<SH
174
    su nobody -s /bin/touch /runtime/testfile && rm /runtime/testfile;
175
    if [ $? -ne 0 ]; then
176
      echo Runtime directory is not writable;
177
      exit 1
178
    fi
179
SH;
180
181
182
183
        // Check if runtime is a tmpfs.
184 3
        $message = Console::ansiFormat('/runtime should really be a tmpfs.', [Console::FG_RED]);
185 3
        $result[] = <<<SH
186
mount | grep '/runtime type tmpfs';
187
if [ $? -ne 0 ]; then
188 3
  echo $message; 
189
fi
190
SH;
191 3
        $result[] = 'jq  > /runtime/env.json';
192 3
        $result[] = 'exec php-fpm7 --force-stderr --fpm-config /php-fpm.conf';
193 3
        return \implode("\n", $result);
194
    }
195
196 3
    public function createBuildContext(): Context
197
    {
198 3
        $builder = new ContextBuilder();
199
200
        /**
201
         * BEGIN COMPOSER
202
         */
203 3
        $builder->from('composer');
204 3
        $builder->addFile('/build/composer.json', \Yii::getAlias($this->composerFilePath) .'/composer.json');
205 3
        if (\file_exists(\Yii::getAlias($this->composerFilePath) . '/composer.lock')) {
206 3
            $builder->addFile('/build/composer.lock', \Yii::getAlias($this->composerFilePath) . '/composer.lock');
207
        }
208
209 3
        $builder->run('cd /build && composer install --no-dev --no-autoloader --ignore-platform-reqs --prefer-dist && rm -rf /root/.composer');
210
211
212
        // Add the actual source code.
213 3
        $root = \Yii::getAlias('@app');
214 3
        if (!\is_string($root)) {
215
            throw new \Exception('Alias @app must be defined.');
216
        }
217 3
        $builder->addFile('/build/' . \basename($root), $root);
218 3
        $builder->run('cd /build && composer dumpautoload -o');
219
        /**
220
         * END COMPOSER
221
         */
222
223
224 3
        $builder->from('alpine:edge');
225
        $packages = [
226 3
            'php7',
227
            'php7-fpm',
228
            'tini',
229
            'ca-certificates',
230
            /**
231
             * @see https://stedolan.github.io/jq/
232
             * This is used for converting the env to JSON.
233
             */
234
            'jq'
235
        ];
236 3
        foreach ($this->extensions as $extension) {
237
            $packages[] = "php7-$extension";
238
        }
239 3
        $builder->run('apk add --update --no-cache ' . \implode(' ', $packages));
240 3
        $builder->run('mkdir /runtime && chown nobody:nobody /runtime');
241 3
        $builder->volume('/runtime');
242 3
        $builder->copy('--from=0 /build', '/project');
243 3
        $builder->add('/entrypoint.sh', $this->createEntrypoint());
244 3
        $builder->run('chmod +x /entrypoint.sh');
245 3
        $builder->add('/php-fpm.conf', $this->createFpmConfig());
246 3
        $builder->run("php-fpm7 --force-stderr --fpm-config /php-fpm.conf -t");
247 3
        $builder->entrypoint('["/sbin/tini", "--", "/entrypoint.sh"]');
248
249
        // Test if we can run a console command.
250 3
        $script = "[ -f /project/{$this->getConsoleEntryScript()} ]";
251 3
        $builder->run($script);
252
253
254 3
        return $builder->getContext();
255
    }
256
257 3
    public function getLock(int $timeout = 0)
258
    {
259 3
        if ($this->has('mutex')) {
260 1
            $mutex = $this->get('mutex');
261 1
            if ($mutex instanceof Mutex
262 1
                && $mutex->acquire(__CLASS__, $timeout)
263
            ) {
264 1
                \register_shutdown_function(function() use ($mutex): void {
265
                    $mutex->release(__CLASS__);
266 1
                });
267 1
                return true;
268
            }
269
        }
270 3
        return false;
271
    }
272
273
    /**
274
     * @throws InvalidConfigException in case the app is not configured as expected
275
     * @return string the relative path of the (console) entry script with respect to the project (not app) root.
276
     */
277 3
    private function getConsoleEntryScript(): string
278
    {
279 3
        $full = \array_slice(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), -1)[0]['file'];
280 3
        $relative = \strtr($full, [\dirname(\Yii::getAlias('@app')) => '']);
281 3
        if ($relative === $full){
282
            throw new InvalidConfigException("The console entry script must be located inside the @app directory.");
283
        }
284 3
        return \ltrim($relative, '/');
285
    }
286
}