Passed
Push — master ( 092d2b...e915ce )
by Emmanuel
02:59
created

RoboFile.php (1 issue)

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
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 (phar|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
            // incomplete and need to reduce for phar compression
110
            //->notPath('ro_MD')
111
            //->notPath('sr_Cyrl_RS')
112
            //->notPath('sr_Latn_RS')
113
            ->in(is_dir($buildDir) ? $buildDir : __DIR__);
114
115
        // Build the phar
116
        return $collection
117
            ->taskPackPhar('neuralyzer.phar')
118
                ->compress()
119
                ->addFile('bin/neuralyzer', 'bin/neuralyzer')
120
                ->addFiles($files)
121
                ->executable('bin/neuralyzer')
122
            ->taskFilesystemStack()
123
                ->chmod(__DIR__ . '/neuralyzer.phar', 0755)
124
            ->run();
125
    }
126
127
128
    public function release()
129
    {
130
        $this->stopOnFail(true);
131
132
        $this->gitVerifyEverythingIsCommited();
133
        $this->gitVerifyBranchIsMaster();
134
        $this->gitVerifyBranchIsUpToDate();
135
136
        $version = null;
137
        $currentVersion = \Edyan\Neuralyzer\Console\Application::VERSION;
138
        while (empty($version)) {
139
            $version = $this->ask("Whats the version number ? (current : $currentVersion)");
140
        }
141
        $versionDesc = null;
142
        while (empty($versionDesc)) {
143
            $versionDesc = $this->ask('Describe your release');
144
        }
145
146
        $this->say("Preparing version $version");
147
148
        // Patch the right files
149
        $this->taskReplaceInFile(__DIR__ . '/src/Console/Application.php')
150
             ->from("const VERSION = '$currentVersion';")
151
             ->to("const VERSION = '$version';")
152
             ->run();
153
154
        $this->phar();
155
156
        // Commit a bump version
157
        $this->taskGitStack()
158
             ->add(__DIR__ . '/src/Console/Application.php')
159
             ->add(__DIR__ . '/neuralyzer.phar')
160
             ->commit("Bump version $version")
161
             ->push('origin', 'master')
162
             ->tag($version)
163
             ->push('origin', $version)
164
             ->run();
165
166
         // Create a release
167
         $this->taskGitHubRelease($version)
168
              ->name($versionDesc)
169
              ->tag($version)
170
              ->description('')
171
              ->owner('edyan')
172
              ->repo('neuralyzer')
173
              ->accessToken(\Robo\Robo::config()->get('settings.github_token'))
174
              ->run();
175
176
        $this->say('Release ready, you can push');
177
    }
178
179
180
    private function setupDocker(
181
        string $php = '7.1',
182
        string $dbType = 'mysql',
183
        int $wait = 10
184
    ) {
185
        $this->destroyDocker();
186
187
        if (!in_array($dbType, ['mysql', 'pgsql', 'sqlsrv'])) {
188
            throw new \InvalidArgumentException('Database can be only mysql, pgsql or sqlsrv');
189
        }
190
191
        $this->startDb($dbType);
192
        $this->say("Waiting $wait seconds $dbType to start");
193
        sleep($wait);
194
        // Now create a DB For SQL Server as there is no option in the docker image
195
        if ($dbType === 'sqlsrv') {
196
            $this->createSQLServerDB();
197
        }
198
199
        $this->startPHP($php, $dbType);
200
    }
201
202
    private function startDb($type)
203
    {
204
        $image = $type;
205
        if ($type === 'sqlsrv') {
206
            $image = 'microsoft/mssql-server-linux:2017-latest';
207
        } elseif ($type === 'pgsql') {
208
            $image = 'postgres';
209
        }
210
211
        $dbCt = $this->taskDockerRun($image)->detached()->name('robo_db')->option('--rm');
212
        if ($type === 'mysql') {
213
            $dbCt = $dbCt->env('MYSQL_ROOT_PASSWORD', 'rootRoot44root')->env('MYSQL_DATABASE', 'test_db');
214
        } elseif ($type === 'pgsql') {
215
            $dbCt = $dbCt->env('POSTGRES_PASSWORD', 'rootRoot44root')->env('POSTGRES_DB', 'test_db');
216
        } elseif ($type === 'sqlsrv') {
217
            $dbCt = $dbCt->env('ACCEPT_EULA', 'Y')->env('SA_PASSWORD', 'rootRoot44root');
218
        }
219
220
        $dbCt->run();
221
    }
222
223
224
    private function createSQLServerDB()
225
    {
226
        $createSqlQuery = '/opt/mssql-tools/bin/sqlcmd -U sa -P rootRoot44root ';
227
        $createSqlQuery.= '-S localhost -Q "CREATE DATABASE test_db"';
228
        $this->taskDockerExec('robo_db')
229
             ->interactive()
230
             ->exec($this->taskExec($createSqlQuery))
231
             ->run();
232
    }
233
234
235
    private function startPHP(string $version, string $dbType)
236
    {
237
        if (!in_array($version, ['7.1', '7.2'])) {
238
            throw new \InvalidArgumentException('PHP Version must be 7.1 or 7.2');
239
        }
240
241
        $dbUser = 'root';
242
        if ($dbType === 'pgsql') {
243
            $dbUser = 'postgres';
244
        } elseif ($dbType === 'sqlsrv') {
245
            $dbUser = 'sa';
246
        }
247
248
        $this->taskDockerRun('edyan/php:' . $version . '-sqlsrv')
249
            ->detached()->name('robo_php')->option('--rm')
250
            ->env('FPM_UID', getmyuid())->env('FPM_GID', getmygid())
251
            ->env('DB_HOST', 'robo_db')->env('DB_DRIVER', 'pdo_' . $dbType)
252
            ->env('DB_PASSWORD', 'rootRoot44root')->env('DB_USER', $dbUser)
253
            ->volume(__DIR__, '/var/www/html')
254
            ->link('robo_db', 'robo_db')
255
            ->run();
256
    }
257
258
259
    private function destroyDocker()
260
    {
261
        $cts = ['robo_db', 'robo_php'];
262
        foreach ($cts as $ct) {
263
            $this->stopContainer($ct);
264
        }
265
    }
266
267
268
    private function stopContainer(string $ct)
269
    {
270
        $process = new \Symfony\Component\Process\Process("docker ps | grep $ct | wc -l");
271
        $process->run();
272
273
        if ((int)$process->getOutput() === 0) {
274
            return;
275
        }
276
277
        $this->say('Destroying container ' . $ct);
278
        $this->taskDockerStop($ct)->run();
279
    }
280
281
    private function gitVerifyBranchIsMaster()
282
    {
283
        $branch = $this->taskGitStack()
284
                        ->silent(true)
285
                        ->exec('rev-parse --abbrev-ref HEAD')
286
                        ->run();
287
        if ($branch->getMessage() !== 'master') {
288
            throw new \RuntimeException('You must be on the master branch');
289
        }
290
    }
291
292
    private function gitVerifyEverythingIsCommited()
293
    {
294
        $modifiedFiles = $this->taskGitStack()
295
                              ->silent(true)
296
                              ->exec('status -s')
297
                              ->run();
298
        if (!empty($modifiedFiles->getMessage())) {
299
            throw new \RuntimeException('Some files have not been commited yet');
300
        }
301
    }
302
303
    private function gitVerifyBranchIsUpToDate()
304
    {
305
        $modifiedFiles = $this->taskGitStack()
306
                              ->silent(true)
307
                              ->exec('fetch --dry-run')
308
                              ->run();
309
        if (!empty($modifiedFiles->getMessage())) {
310
            throw new \RuntimeException('Your local repo is not up to date, run "git pull"');
311
        }
312
    }
313
}
314