Completed
Push — master ( f0d93b...12af13 )
by Emmanuel
04:54
created

RoboFile::startPHP()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 16
nc 4
nop 2
1
<?php
2
/**
3
 * This is project's console commands configuration for Robo task runner.
4
 *
5
 * @see http://robo.li/
6
 */
7
8
class RoboFile extends \Robo\Tasks
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
9
{
10
    /**
11
     * A test command just to make sure robo works on that computer
12
     */
13
    public function dockertest()
14
    {
15
        $this->stopOnFail(true);
16
17
        $this->taskDockerStop('robo_test')->run();
18
19
        $this->taskDockerRun('edyan/php:7.1')
20
             ->name('robo_test')
21
             ->detached()
22
             ->option('--rm')
23
             ->run();
24
25
        $this->taskDockerExec('robo_test')
26
             ->interactive()
27
             ->exec($this->taskExec('php -v'))
28
             ->run();
29
30
        $this->taskDockerStop('robo_test')->run();
31
    }
32
33
34
    /**
35
     * Run All Unit Test
36
     * @param  array  $opts
37
     */
38
    public function test(
39
        $opts = ['php' => '7.1', 'db' => 'mysql', 'keep-cts' => false, 'wait' => 5]
40
    ) {
41
        $this->stopOnFail(true);
42
43
        $this->setupDocker($opts['php'], $opts['db'], $opts['wait']);
44
45
        // Run the tests
46
        $this->taskDockerExec('robo_php')
47
            ->interactive()
48
            ->option('--user', 'www-data')
49
            ->exec($this->taskExec('/bin/bash -c "cd /var/www/html ; vendor/bin/phpunit"'))
50
            ->run();
51
52
        if ($opts['keep-cts'] === false) {
53
            $this->destroyDocker();
54
        }
55
    }
56
57
58
    /**
59
     * Build an executable phar
60
     */
61
    public function phar()
62
    {
63
        if ((int)ini_get('phar.readonly') === 1) {
64
            throw new \RuntimeException(
65
                'You must have phar.readonly = 1 or run' . PHP_EOL .
66
                'php -d phar.readonly=0 vendor/bin/robo release'
67
            );
68
        }
69
        // Create a collection builder to hold the temporary
70
        // directory until the pack phar task runs.
71
        $collection = $this->collectionBuilder();
72
        $workDir = $collection->tmpDir();
73
        $buildDir = "$workDir/neuralyzer";
74
75
        $prepTasks = $this->collectionBuilder();
76
        $preparationResult = $prepTasks
77
            ->taskFilesystemStack()
78
                ->mkdir($workDir)
79
                ->taskCopyDir([__DIR__ . '/src' => $buildDir . '/src'])
80
            ->taskFilesystemStack()
81
                ->copy(__DIR__ . '/bin/neuralyzer', $buildDir . '/bin/neuralyzer')
82
                ->copy(__DIR__ . '/composer.json', $buildDir . '/composer.json')
83
                ->copy(__DIR__ . '/composer.lock', $buildDir . '/composer.lock')
84
                ->copy(__DIR__ . '/LICENSE', $buildDir . '/LICENSE')
85
                ->copy(__DIR__ . '/README.md', $buildDir . '/README.md')
86
87
            ->taskComposerInstall()
88
                ->dir($buildDir)
89
                ->noDev()
90
                ->noScripts()
91
                ->printOutput(true)
92
                ->optimizeAutoloader()
93
                ->run();
94
95
        // Exit if the preparation step failed
96
        if (!$preparationResult->wasSuccessful()) {
97
            return $preparationResult;
98
        }
99
100
        // Decide which files we're going to pack
101
        $files = \Symfony\Component\Finder\Finder::create()->ignoreVCS(true)
102
            ->files()
103
            ->name('*.php')
104
            ->name('*.exe') // for 1symfony/console/Resources/bin/hiddeninput.exe
105
            ->path('src')
106
            ->path('vendor')
107
            ->notPath('docs')
108
            ->notPath('/vendor\/.*\/[Tt]est/')
109
            ->in(is_dir($buildDir) ? $buildDir : __DIR__);
110
111
        // Build the phar
112
        return $collection
113
            ->taskPackPhar('neuralyzer.phar')
114
                ->compress()
115
                ->addFile('bin/neuralyzer', 'bin/neuralyzer')
116
                ->addFiles($files)
117
                ->executable('bin/neuralyzer')
118
            ->taskFilesystemStack()
119
                ->chmod(__DIR__ . '/neuralyzer.phar', 0755)
120
            ->run();
121
    }
122
123
124
    public function release()
125
    {
126
        $this->stopOnFail(true);
127
128
        $this->gitVerifyEverythingIsCommited();
129
        $this->gitVerifyBranchIsMaster();
130
        $this->gitVerifyBranchIsUpToDate();
131
132
        $version = null;
133
        $currentVersion = \Edyan\Neuralyzer\Console\Application::VERSION;
134
        while (empty($version)) {
135
            $version = $this->ask("Whats the version number ? (current : $currentVersion)");
136
        }
137
        $versionDesc = null;
138
        while (empty($versionDesc)) {
139
            $versionDesc = $this->ask('Describe your release');
140
        }
141
142
        $this->say("Preparing version $version");
143
144
        // Patch the right files
145
        $this->taskReplaceInFile(__DIR__ . '/src/Console/Application.php')
146
             ->from("const VERSION = '$currentVersion';")
147
             ->to("const VERSION = '$version';")
148
             ->run();
149
150
        $this->phar();
151
152
        // Commit a bump version
153
        $this->taskGitStack()
154
             ->add(__DIR__ . '/src/Console/Application.php')
155
             ->add(__DIR__ . '/neuralyzer.phar')
156
             ->commit("Bump version $version")
157
             ->push('origin', 'master')
158
             ->tag($version)
159
             ->push('origin', $version)
160
             ->run();
161
162
        // Create a release
163
        $this->taskGitHubRelease($version)
164
             ->uri('edyan/neuralyzer')
165
             ->description($versionDesc)
166
             ->run();
167
168
         // Create a release
169
         $this->taskGitHubRelease($version)
170
              ->name($versionDesc)
171
              ->tag($version)
172
              ->description('')
173
              ->owner('edyan')
174
              ->repo('neuralyzer')
175
              ->accessToken(Robo::Config()->get('settings.github_token'))
176
              ->run();
177
178
        $this->say('Release ready, you can push');
179
    }
180
181
182
    private function setupDocker(
183
        string $php = '7.1',
184
        string $dbType = 'mysql',
185
        int $wait = 10
186
    ) {
187
        $this->destroyDocker();
188
189
        if (!in_array($dbType, ['mysql', 'pgsql', 'sqlsrv'])) {
190
            throw new \InvalidArgumentException('Database can be only mysql, pgsql or sqlsrv');
191
        }
192
193
        $this->startDb($dbType);
194
        $this->say("Waiting $wait seconds $dbType to start");
195
        sleep($wait);
196
        // Now create a DB For SQL Server as there is no option in the docker image
197
        if ($dbType === 'sqlsrv') {
198
            $this->createSQLServerDB();
199
        }
200
201
        $this->startPHP($php, $dbType);
202
    }
203
204
    private function startDb($type)
205
    {
206
        $image = $type;
207
        if ($type === 'sqlsrv') {
208
            $image = 'microsoft/mssql-server-linux:2017-latest';
209
        } elseif ($type === 'pgsql') {
210
            $image = 'postgres';
211
        }
212
213
        $dbCt = $this->taskDockerRun($image)->detached()->name('robo_db')->option('--rm');
214
        if ($type === 'mysql') {
215
            $dbCt = $dbCt->env('MYSQL_ROOT_PASSWORD', 'rootRoot44root')->env('MYSQL_DATABASE', 'test_db');
216
        } elseif ($type === 'pgsql') {
217
            $dbCt = $dbCt->env('POSTGRES_PASSWORD', 'rootRoot44root')->env('POSTGRES_DB', 'test_db');
218
        } elseif ($type === 'sqlsrv') {
219
            $dbCt = $dbCt->env('ACCEPT_EULA', 'Y')->env('SA_PASSWORD', 'rootRoot44root');
220
        }
221
222
        $dbCt->run();
223
    }
224
225
226
    private function createSQLServerDB()
227
    {
228
        $createSqlQuery = '/opt/mssql-tools/bin/sqlcmd -U sa -P rootRoot44root ';
229
        $createSqlQuery.= '-S localhost -Q "CREATE DATABASE test_db"';
230
        $this->taskDockerExec('robo_db')
231
             ->interactive()
232
             ->exec($this->taskExec($createSqlQuery))
233
             ->run();
234
    }
235
236
237
    private function startPHP(string $version, string $dbType)
238
    {
239
        if (!in_array($version, ['7.1', '7.2'])) {
240
            throw new \InvalidArgumentException('PHP Version must be 7.1 or 7.2');
241
        }
242
243
        $dbUser = 'root';
244
        if ($dbType === 'pgsql') {
245
            $dbUser = 'postgres';
246
        } elseif ($dbType === 'sqlsrv') {
247
            $dbUser = 'sa';
248
        }
249
250
        $this->taskDockerRun('edyan/php:' . $version . '-sqlsrv')
251
            ->detached()->name('robo_php')->option('--rm')
252
            ->env('FPM_UID', getmyuid())->env('FPM_GID', getmygid())
253
            ->env('DB_HOST', 'robo_db')->env('DB_DRIVER', 'pdo_' . $dbType)
254
            ->env('DB_PASSWORD', 'rootRoot44root')->env('DB_USER', $dbUser)
255
            ->volume(__DIR__, '/var/www/html')
256
            ->link('robo_db', 'robo_db')
257
            ->run();
258
    }
259
260
261
    private function destroyDocker()
262
    {
263
        $cts = ['robo_db', 'robo_php'];
264
        foreach ($cts as $ct) {
265
            $this->stopContainer($ct);
266
        }
267
    }
268
269
270
    private function stopContainer(string $ct)
271
    {
272
        $process = new \Symfony\Component\Process\Process("docker ps | grep $ct | wc -l");
273
        $process->run();
274
275
        if ((int)$process->getOutput() === 0) {
276
            return;
277
        }
278
279
        $this->say('Destroying container ' . $ct);
280
        $this->taskDockerStop($ct)->run();
281
    }
282
283
    private function gitVerifyBranchIsMaster()
284
    {
285
        $branch = $this->taskGitStack()
286
                        ->silent(true)
287
                        ->exec('rev-parse --abbrev-ref HEAD')
288
                        ->run();
289
        if ($branch->getMessage() !== 'master') {
290
            throw new \RuntimeException('You must be on the master branch');
291
        }
292
    }
293
294
    private function gitVerifyEverythingIsCommited()
295
    {
296
        $modifiedFiles = $this->taskGitStack()
297
                              ->silent(true)
298
                              ->exec('status -s')
299
                              ->run();
300
        if (!empty($modifiedFiles->getMessage())) {
301
            throw new \RuntimeException('Some files have not been commited yet');
302
        }
303
    }
304
305
    private function gitVerifyBranchIsUpToDate()
306
    {
307
        $modifiedFiles = $this->taskGitStack()
308
                              ->silent(true)
309
                              ->exec('fetch --dry-run')
310
                              ->run();
311
        if (!empty($modifiedFiles->getMessage())) {
312
            throw new \RuntimeException('Your local repo is not up to date, run "git pull"');
313
        }
314
    }
315
}
316