Passed
Push — master ( e915ce...0edbb7 )
by Emmanuel
02:13
created

RoboFile::dockertest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

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

This method has been deprecated.

Loading history...
203
        $progressBar->start();
204
        for ($i = 0; $i < $wait; ++$i) {
205
            sleep(1);
206
            $progressBar->advance();
207
        }
208
        $progressBar->finish();
209
        echo PHP_EOL;
210
211
212
        // Now create a DB For SQL Server as there is no option in the docker image
213
        if ($dbType === 'sqlsrv') {
214
            $this->createSQLServerDB();
215
        }
216
217
        $this->startPHP($php, $dbType);
218
    }
219
220
    protected $steps = 10;
221
222
    public function progressIndicatorSteps()
223
    {
224
        return $this->steps;
225
    }
226
227
    private function startDb(string $type, string $dbVersion): void
228
    {
229
        $image = $type . ':' . $dbVersion;
230
        if ($type === 'sqlsrv') {
231
            $dbVersion = $dbVersion === 'latest' ? '2017-latest' : $dbVersion;
232
            $image = 'microsoft/mssql-server-linux:' . $dbVersion;
233
        } elseif ($type === 'pgsql') {
234
            $image = 'postgres:' . $dbVersion;
235
        }
236
237
        $this->say("Starting $type version $dbVersion");
238
        $dbCt = $this->taskDockerRun($image)->detached()->name('robo_db')->option('--rm');
239
        if ($type === 'mysql') {
240
            $dbCt = $dbCt->env('MYSQL_ROOT_PASSWORD', 'rootRoot44root')->env('MYSQL_DATABASE', 'test_db');
241
        } elseif ($type === 'pgsql') {
242
            $dbCt = $dbCt->env('POSTGRES_PASSWORD', 'rootRoot44root')->env('POSTGRES_DB', 'test_db');
243
        } elseif ($type === 'sqlsrv') {
244
            $dbCt = $dbCt->env('ACCEPT_EULA', 'Y')->env('SA_PASSWORD', 'rootRoot44root');
245
        }
246
247
        $dbCt->run();
248
    }
249
250
251
    private function createSQLServerDB()
252
    {
253
        $createSqlQuery = '/opt/mssql-tools/bin/sqlcmd -U sa -P rootRoot44root ';
254
        $createSqlQuery.= '-S localhost -Q "CREATE DATABASE test_db"';
255
        $this->taskDockerExec('robo_db')
256
             ->interactive()
257
             ->exec($this->taskExec($createSqlQuery))
258
             ->run();
259
    }
260
261
262
    private function startPHP(string $version, string $dbType)
263
    {
264
        if (!in_array($version, ['7.1', '7.2'])) {
265
            throw new \InvalidArgumentException('PHP Version must be 7.1 or 7.2');
266
        }
267
268
        $dbUser = 'root';
269
        if ($dbType === 'pgsql') {
270
            $dbUser = 'postgres';
271
        } elseif ($dbType === 'sqlsrv') {
272
            $dbUser = 'sa';
273
        }
274
275
        $this->taskDockerRun('edyan/php:' . $version . '-sqlsrv')
276
            ->detached()->name('robo_php')->option('--rm')
277
            ->env('FPM_UID', getmyuid())->env('FPM_GID', getmygid())
278
            ->env('DB_HOST', 'robo_db')->env('DB_DRIVER', 'pdo_' . $dbType)
279
            ->env('DB_PASSWORD', 'rootRoot44root')->env('DB_USER', $dbUser)
280
            ->volume(__DIR__, '/var/www/html')
281
            ->link('robo_db', 'robo_db')
282
            ->run();
283
    }
284
285
286
    private function destroyDocker()
287
    {
288
        $cts = ['robo_db', 'robo_php'];
289
        foreach ($cts as $ct) {
290
            $this->stopContainer($ct);
291
        }
292
    }
293
294
295
    private function stopContainer(string $ct)
296
    {
297
        $process = new \Symfony\Component\Process\Process("docker ps | grep $ct | wc -l");
298
        $process->run();
299
300
        if ((int)$process->getOutput() === 0) {
301
            return;
302
        }
303
304
        $this->say('Destroying container ' . $ct);
305
        $this->taskDockerStop($ct)->run();
306
    }
307
308
    private function gitVerifyBranchIsMaster()
309
    {
310
        $branch = $this->taskGitStack()
311
                        ->silent(true)
312
                        ->exec('rev-parse --abbrev-ref HEAD')
313
                        ->run();
314
        if ($branch->getMessage() !== 'master') {
315
            throw new \RuntimeException('You must be on the master branch');
316
        }
317
    }
318
319
    private function gitVerifyEverythingIsCommited()
320
    {
321
        $modifiedFiles = $this->taskGitStack()
322
                              ->silent(true)
323
                              ->exec('status -s')
324
                              ->run();
325
        if (!empty($modifiedFiles->getMessage())) {
326
            throw new \RuntimeException('Some files have not been commited yet');
327
        }
328
    }
329
330
    private function gitVerifyBranchIsUpToDate()
331
    {
332
        $modifiedFiles = $this->taskGitStack()
333
                              ->silent(true)
334
                              ->exec('fetch --dry-run')
335
                              ->run();
336
        if (!empty($modifiedFiles->getMessage())) {
337
            throw new \RuntimeException('Your local repo is not up to date, run "git pull"');
338
        }
339
    }
340
}
341