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 ( e11e84...669d0f )
by Sam
02:18
created

Module::getConsoleEntryScript()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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