Completed
Push — master ( 113f3e...69688c )
by Emmanuel
05:58 queued 02:14
created

RoboFile.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * This is project's console commands configuration for Robo task runner.
4
 *
5
 * @see http://robo.li/
6
 */
7
8
use Symfony\Component\Console\Helper\ProgressBar;
9
10
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...
11
{
12
    private $phpVersion = 7.1;
13
    private $dbType = 'mysql';
14
    private $dbVersion = 'latest';
15
    private $dbWait = 10;
16
17
    /**
18
     * A test command just to make sure robo works on that computer
19
     */
20
    public function dockertest()
21
    {
22
        $this->stopOnFail(true);
23
24
        $this->taskDockerStop('robo_test')->run();
25
26
        $this->taskDockerRun('edyan/php:7.1')
27
             ->name('robo_test')
28
             ->detached()
29
             ->option('--rm')
30
             ->run();
31
32
        $this->taskDockerExec('robo_test')
33
             ->interactive()
34
             ->exec($this->taskExec('php -v'))
35
             ->run();
36
37
        $this->taskDockerStop('robo_test')->run();
38
    }
39
40
41
    /**
42
     * Run All Unit Test
43
     * @param  array  $opts
44
     */
45
    public function test($opts = [
46
        'php' => '7.1',
47
        'db' => 'mysql',
48
        'keep-cts' => false,
49
        'wait' => 5,
50
        'db-version' => 'latest'
51
    ]) : void
52
    {
53
        $this->stopOnFail(true);
54
55
        $this->phpVersion = $opts['php'];
56
        $this->dbType = $opts['db'];
57
        $this->dbVersion = $opts['db-version'];
58
        $this->dbWait = $opts['wait'];
59
60
        $this->setupDocker();
61
62
        // Run the tests
63
        $this->taskDockerExec('robo_php')
64
            ->interactive()
65
            ->option('--user', 'www-data')
66
            ->exec($this->taskExec('/bin/bash -c "cd /var/www/html ; vendor/bin/phpunit"'))
67
            ->run();
68
69
        if ($opts['keep-cts'] === false) {
70
            $this->destroyDocker();
71
        }
72
    }
73
74
75
    /**
76
     * Build an executable phar
77
     */
78
    public function phar()
79
    {
80
        if ((int)ini_get('phar.readonly') === 1) {
81
            throw new \RuntimeException(
82
                'You must have phar.readonly = 1 or run' . PHP_EOL .
83
                'php -d phar.readonly=0 vendor/bin/robo (phar|release)'
84
            );
85
        }
86
        // Create a collection builder to hold the temporary
87
        // directory until the pack phar task runs.Call to undefined method RoboFile::startProgressIndicator()
88
        $collection = $this->collectionBuilder();
89
        $workDir = $collection->tmpDir();
90
        $buildDir = "$workDir/neuralyzer";
91
92
        $prepTasks = $this->collectionBuilder();
93
        $preparationResult = $prepTasks
94
            ->taskFilesystemStack()
95
                ->mkdir($workDir)
96
                ->taskCopyDir([__DIR__ . '/src' => $buildDir . '/src'])
97
            ->taskFilesystemStack()
98
                ->copy(__DIR__ . '/bin/neuralyzer', $buildDir . '/bin/neuralyzer')
99
                ->copy(__DIR__ . '/composer.json', $buildDir . '/composer.json')
100
                ->copy(__DIR__ . '/composer.lock', $buildDir . '/composer.lock')
101
                ->copy(__DIR__ . '/LICENSE', $buildDir . '/LICENSE')
102
                ->copy(__DIR__ . '/README.md', $buildDir . '/README.md')
103
104
            ->taskComposerInstall()
105
                ->dir($buildDir)
106
                ->noDev()
107
                ->noScripts()
108
                ->printOutput(true)
109
                ->optimizeAutoloader()
110
                ->run();
111
112
        // Exit if the preparation step failed
113
        if (!$preparationResult->wasSuccessful()) {
114
            return $preparationResult;
115
        }
116
117
        // Decide which files we're going to pack
118
        $files = \Symfony\Component\Finder\Finder::create()->ignoreVCS(true)
119
            ->files()
120
            ->name('*.php')
121
            ->name('*.exe') // for 1symfony/console/Resources/bin/hiddeninput.exe
122
            ->path('src')
123
            ->path('vendor')
124
            ->notPath('docs')
125
            ->notPath('/vendor\/.*\/[Tt]est/')
126
            // incomplete and need to reduce for phar compression
127
            //->notPath('ro_MD')
128
            //->notPath('sr_Cyrl_RS')
129
            //->notPath('sr_Latn_RS')
130
            ->in(is_dir($buildDir) ? $buildDir : __DIR__);
131
132
        // Build the phar
133
        return $collection
134
            ->taskPackPhar('neuralyzer.phar')
135
                ->compress()
136
                ->addFile('bin/neuralyzer', 'bin/neuralyzer')
137
                ->addFiles($files)
138
                ->executable('bin/neuralyzer')
139
            ->taskFilesystemStack()
140
                ->chmod(__DIR__ . '/neuralyzer.phar', 0755)
141
            ->run();
142
    }
143
144
145
    public function release()
146
    {
147
        $this->stopOnFail(true);
148
149
        $this->gitVerifyEverythingIsCommited();
150
        $this->gitVerifyBranchIsMaster();
151
        $this->gitVerifyBranchIsUpToDate();
152
153
        $version = null;
154
        $currentVersion = \Edyan\Neuralyzer\Console\Application::VERSION;
155
        while (empty($version)) {
156
            $version = $this->ask("Whats the version number ? (current : $currentVersion)");
157
        }
158
        $versionDesc = null;
159
        while (empty($versionDesc)) {
160
            $versionDesc = $this->ask('Describe your release');
161
        }
162
163
        $this->say("Preparing version $version");
164
165
        // Patch the right files
166
        $this->taskReplaceInFile(__DIR__ . '/src/Console/Application.php')
167
             ->from("const VERSION = '$currentVersion';")
168
             ->to("const VERSION = '$version';")
169
             ->run();
170
171
        $this->phar();
172
173
        // Commit a bump version
174
        $this->taskGitStack()
175
             ->add(__DIR__ . '/src/Console/Application.php')
176
             ->add(__DIR__ . '/neuralyzer.phar')
177
             ->commit("Bump version $version")
178
             ->push('origin', 'master')
179
             ->tag($version)
180
             ->push('origin', $version)
181
             ->run();
182
183
         // Create a release
184
         $this->taskGitHubRelease($version)
185
              ->name($versionDesc)
186
              ->tag($version)
187
              ->description('')
188
              ->owner('edyan')
189
              ->repo('neuralyzer')
190
              ->accessToken(\Robo\Robo::config()->get('settings.github_token'))
191
              ->run();
192
193
        $this->say('Release ready, you can push');
194
    }
195
196
197
    private function setupDocker() : void {
198
        $this->destroyDocker();
199
200
        if (!in_array($this->dbType, ['mysql', 'pgsql', 'sqlsrv'])) {
201
            throw new \InvalidArgumentException('Database can be only mysql, pgsql or sqlsrv');
202
        }
203
204
        // Start DB And display a progress bar
205
        $this->startDb();
206
        $this->waitForDB();
207
208
        // Now create a DB For SQL Server as there is no option in the docker image
209
        if ($this->dbType === 'sqlsrv') {
210
            $this->createSQLServerDB();
211
        }
212
213
        $this->startPHP();
214
    }
215
216
217
    private function startDb(): void
218
    {
219
        $dbCt = $this
220
                    ->taskDockerRun($this->getDBImageName())
221
                    ->detached()
222
                    ->name('robo_db')
223
                    ->option('--rm');
224
225
        if ($this->dbType === 'mysql') {
226
            $dbCt = $dbCt->env('MYSQL_ROOT_PASSWORD', 'rootRoot44root')->env('MYSQL_DATABASE', 'test_db');
227
        } elseif ($this->dbType === 'pgsql') {
228
            $dbCt = $dbCt->env('POSTGRES_PASSWORD', 'rootRoot44root')->env('POSTGRES_DB', 'test_db');
229
        } elseif ($this->dbType === 'sqlsrv') {
230
            $dbCt = $dbCt->env('ACCEPT_EULA', 'Y')->env('SA_PASSWORD', 'rootRoot44root');
231
        }
232
233
        $dbCt->run();
234
    }
235
236
237
    private function getDBImageName(): string
238
    {
239
        $image = $this->dbType . ':' . $this->dbVersion;
240
        if ($this->dbType === 'sqlsrv') {
241
            $dbVersion = $this->dbVersion === 'latest' ? '2017-latest' : $this->dbVersion;
242
            $image = 'microsoft/mssql-server-linux:' . $dbVersion;
243
        } elseif ($this->dbType === 'pgsql') {
244
            $image = 'postgres:' . $this->dbVersion;
245
        }
246
247
        return $image;
248
    }
249
250
251
    private function waitForDB(): void
252
    {
253
        $this->say("Waiting {$this->dbWait} seconds for DB to start");
254
        $progressBar = new ProgressBar($this->getOutput(), $this->dbWait);
0 ignored issues
show
Deprecated Code introduced by
The method Robo\Common\OutputAwareTrait::getOutput() has been deprecated.

This method has been deprecated.

Loading history...
255
        $progressBar->start();
256
        for ($i = 0; $i < $this->dbWait; ++$i) {
257
            sleep(1);
258
            $progressBar->advance();
259
        }
260
        $progressBar->finish();
261
262
        echo PHP_EOL;
263
    }
264
265
266
    private function createSQLServerDB(): void
267
    {
268
        $createSqlQuery = '/opt/mssql-tools/bin/sqlcmd -U sa -P rootRoot44root ';
269
        $createSqlQuery.= '-S localhost -Q "CREATE DATABASE test_db"';
270
        $this->taskDockerExec('robo_db')
271
             ->interactive()
272
             ->exec($this->taskExec($createSqlQuery))
273
             ->run();
274
    }
275
276
277
    private function startPHP(): void
278
    {
279
        if (!in_array($this->phpVersion, ['7.1', '7.2'])) {
280
            throw new \InvalidArgumentException('PHP Version must be 7.1 or 7.2');
281
        }
282
283
        $dbUser = 'root';
284
        if ($this->dbType === 'pgsql') {
285
            $dbUser = 'postgres';
286
        } elseif ($this->dbType === 'sqlsrv') {
287
            $dbUser = 'sa';
288
        }
289
290
        $this->taskDockerRun('edyan/php:' . $this->phpVersion . '-sqlsrv')
291
            ->detached()->name('robo_php')->option('--rm')
292
            ->env('FPM_UID', getmyuid())->env('FPM_GID', getmygid())
293
            ->env('DB_HOST', 'robo_db')->env('DB_DRIVER', 'pdo_' . $this->dbType)
294
            ->env('DB_PASSWORD', 'rootRoot44root')->env('DB_USER', $dbUser)
295
            ->volume(__DIR__, '/var/www/html')
296
            ->link('robo_db', 'robo_db')
297
            ->run();
298
    }
299
300
301
    private function destroyDocker(): void
302
    {
303
        $cts = ['robo_db', 'robo_php'];
304
        foreach ($cts as $ct) {
305
            $this->stopContainer($ct);
306
        }
307
    }
308
309
310
    private function stopContainer(string $ct): void
311
    {
312
        $process = new \Symfony\Component\Process\Process("docker ps | grep $ct | wc -l");
313
        $process->run();
314
315
        if ((int)$process->getOutput() === 0) {
316
            return;
317
        }
318
319
        $this->say('Destroying container ' . $ct);
320
        $this->taskDockerStop($ct)->run();
321
    }
322
323
324
    private function gitVerifyBranchIsMaster(): void
325
    {
326
        $branch = $this->taskGitStack()
327
                        ->silent(true)
328
                        ->exec('rev-parse --abbrev-ref HEAD')
329
                        ->run();
330
        if ($branch->getMessage() !== 'master') {
331
            throw new \RuntimeException('You must be on the master branch');
332
        }
333
    }
334
335
336
    private function gitVerifyEverythingIsCommited(): void
337
    {
338
        $modifiedFiles = $this->taskGitStack()
339
                              ->silent(true)
340
                              ->exec('status -s')
341
                              ->run();
342
        if (!empty($modifiedFiles->getMessage())) {
343
            throw new \RuntimeException('Some files have not been commited yet');
344
        }
345
    }
346
347
348
    private function gitVerifyBranchIsUpToDate(): void
349
    {
350
        $modifiedFiles = $this->taskGitStack()
351
                              ->silent(true)
352
                              ->exec('fetch --dry-run')
353
                              ->run();
354
        if (!empty($modifiedFiles->getMessage())) {
355
            throw new \RuntimeException('Your local repo is not up to date, run "git pull"');
356
        }
357
    }
358
}
359