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