Completed
Push — 2.0 ( e8af7e...491a66 )
by David
15s
created

RunCommand::addFilesToMessage()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 4
1
<?php
2
namespace TheCodingMachine\WashingMachine\Commands;
3
4
use Gitlab\Client;
5
use Gitlab\Model\Project;
6
use Psr\Log\LoggerInterface;
7
use Symfony\Component\Console\Command\Command;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Logger\ConsoleLogger;
11
use Symfony\Component\Console\Output\OutputInterface;
12
use TheCodingMachine\WashingMachine\Clover\CloverFile;
13
use TheCodingMachine\WashingMachine\Clover\Crap4JFile;
14
use TheCodingMachine\WashingMachine\Clover\CrapMethodMerger;
15
use TheCodingMachine\WashingMachine\Clover\DiffService;
16
use TheCodingMachine\WashingMachine\Clover\EmptyCloverFile;
17
use TheCodingMachine\WashingMachine\Git\GitRepository;
18
use TheCodingMachine\WashingMachine\Gitlab\BuildNotFoundException;
19
use TheCodingMachine\WashingMachine\Gitlab\BuildService;
20
use TheCodingMachine\WashingMachine\Gitlab\MergeRequestNotFoundException;
21
use TheCodingMachine\WashingMachine\Gitlab\Message;
22
use TheCodingMachine\WashingMachine\Gitlab\SendCommentService;
23
24
class RunCommand extends Command
25
{
26
    /**
27
     * @var LoggerInterface
28
     */
29
    private $logger;
30
31
    protected function configure()
32
    {
33
        $this
34
            ->setName('run')
35
            ->setDescription('Analyses the coverage report files and upload the result to Gitlab')
36
            //->setHelp("This command allows you to create users...")
37
            ->addOption('clover',
38
                'c',
39
                InputOption::VALUE_REQUIRED,
40
                'The path to the clover.xml file generated by PHPUnit.',
41
                'clover.xml')
42
            ->addOption('crap4j',
43
                'j',
44
                InputOption::VALUE_REQUIRED,
45
                'The path to the crap4j.xml file generated by PHPUnit.',
46
                'crap4j.xml')
47
            ->addOption('gitlab-url',
48
                'u',
49
                InputOption::VALUE_REQUIRED,
50
                'The Gitlab URL. If not specified, it is deduced from the CI_REPOSITORY_URL environment variable.',
51
                null)
52
            ->addOption('gitlab-api-token',
53
                't',
54
                InputOption::VALUE_REQUIRED,
55
                'The Gitlab API token. If not specified, it is fetched from the GITLAB_API_TOKEN environment variable.',
56
                null)
57
            /*->addOption('gitlab-project-id',
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
58
                'p',
59
                InputOption::VALUE_REQUIRED,
60
                'The Gitlab project ID. If not specified, it is fetched from the CI_PROJECT_ID environment variable.',
61
                null)*/
62
            ->addOption('gitlab-project-name',
63
                'p',
64
                InputOption::VALUE_REQUIRED,
65
                'The Gitlab project name (in the form "group/name"). If not specified, it is deduced from the CI_PROJECT_DIR environment variable.',
66
                null)
67
            ->addOption('commit-sha',
68
                'r',
69
                InputOption::VALUE_REQUIRED,
70
                'The commit SHA. If not specified, it is deduced from the CI_COMMIT_SHA environment variable.',
71
                null)
72
            ->addOption('gitlab-job-id',
73
                'b',
74
                InputOption::VALUE_REQUIRED,
75
                'The Gitlab CI build/job id. If not specified, it is deduced from the CI_JOB_ID environment variable.',
76
                null)
77
            ->addOption('gitlab-build-name',
78
                'a',
79
                InputOption::VALUE_REQUIRED,
80
                'The Gitlab CI build name (the name of this build in the job). If not specified, it is deduced from the CI_BUILD_NAME environment variable.',
81
                null)
82
            ->addOption('gitlab-pipeline-id',
83
                'e',
84
                InputOption::VALUE_REQUIRED,
85
                'The Gitlab CI pipeline ID. If not specified, it is deduced from the CI_PIPELINE_ID environment variable.',
86
                null)
87
            ->addOption('job-stage',
88
                's',
89
                InputOption::VALUE_REQUIRED,
90
                'The Gitlab CI job stage. If not specified, it is deduced from the CI_JOB_STAGE environment variable.',
91
                null)
92
            ->addOption('file',
93
                'f',
94
                InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED,
95
                'Text file to be sent in the merge request comments (can be used multiple times).',
96
                [])
97
            ->addOption('open-issue',
98
                'i',
99
                InputOption::VALUE_NONE,
100
                'Opens an issue (if the build is not part of a merge request)')
101
            ->addOption('add-comments-in-commits',
102
                null,
103
                InputOption::VALUE_NONE,
104
                'Add comments directly in the commit')
105
        ;
106
    }
107
108
    protected function execute(InputInterface $input, OutputInterface $output)
109
    {
110
        $this->logger = new ConsoleLogger($output);
111
        $config = new Config($input);
112
113
        $cloverFilePath = $config->getCloverFilePath();
114
115
        $cloverFile = null;
116
        if (file_exists($cloverFilePath)) {
117
            $cloverFile = CloverFile::fromFile($cloverFilePath, getcwd());
118
            //$output->writeln(sprintf('Code coverage: %.2f%%', $cloverFile->getCoveragePercentage() * 100));
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
119
        }
120
121
        $crap4JFilePath = $config->getCrap4JFilePath();
122
123
        $crap4jFile = null;
124
        if (file_exists($crap4JFilePath)) {
125
            $crap4jFile = Crap4JFile::fromFile($crap4JFilePath);
126
        }
127
128
        $files = $config->getFiles();
129
130
        $methodsProvider = null;
131
        $codeCoverageProvider = null;
132
133
        if ($cloverFile !== null && $crap4jFile !== null) {
134
            $methodsProvider = new CrapMethodMerger($cloverFile, $crap4jFile);
135
            $codeCoverageProvider = $cloverFile;
136
        } elseif ($cloverFile !== null) {
137
            $methodsProvider = $cloverFile;
138
            $codeCoverageProvider = $cloverFile;
139
        } elseif ($crap4jFile !== null) {
140
            $methodsProvider = $crap4jFile;
141
        } elseif (empty($files)) {
142
            throw new \RuntimeException('Could not find neither clover file, nor crap4j file for analysis nor files to send in comments. Nothing done. Searched paths: '.$cloverFilePath.' and '.$crap4JFilePath);
143
        }
144
145
        $gitlabApiToken = $config->getGitlabApiToken();
146
147
        $gitlabUrl = $config->getGitlabUrl();
148
        $gitlabApiUrl = $config->getGitlabApiUrl();
149
150
151
        /*$projectId = $input->getOption('gitlab-project-id');
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
152
        if ($projectId === null) {
153
            $projectId = getenv('CI_PROJECT_ID');
154
            if ($projectId === false) {
155
                throw new \RuntimeException('Could not find the Gitlab project ID in the "CI_PROJECT_ID" environment variable (usually set by Gitlab CI). Either set this environment variable or pass the ID via the --gitlab-project-id command line option.');
156
            }
157
        }*/
158
159
        $projectName = $config->getGitlabProjectName();
160
161
        $commitSha = $config->getCommitSha();
162
163
        $currentBranchName = $config->getCurrentBranchName();
164
165
        $client = Client::create($gitlabApiUrl);
166
        $client->authenticate($gitlabApiToken);
167
168
        $diffService = new DiffService(5, 30, 20);
169
170
        $sendCommentService = new SendCommentService($client, $diffService);
171
172
        // From CI_COMMIT_SHA, we can get the commit ( -> project -> build -> commit )
173
        // From the merge_requests API, we can get the list of commits for a single merge request
174
        // Hence, we can find the merge_request matching a build!
175
176
        $buildService = new BuildService($client);
177
178
        $inMergeRequest = false;
179
180
        try {
181
            $mergeRequest = $buildService->findMergeRequestByCommitSha($projectName, $commitSha);
182
183
            $repo = new GitRepository(getcwd());
184
            $targetCommit = $repo->getLatestCommitForBranch('origin/'.$mergeRequest['target_branch']);
185
            $lastCommonCommit = $repo->getMergeBase($targetCommit, $commitSha);
186
187
            $output->writeln('Pipeline current commit: '.$commitSha, OutputInterface::VERBOSITY_DEBUG);
188
            $output->writeln('Target branch: '.$mergeRequest['target_branch'], OutputInterface::VERBOSITY_DEBUG);
189
            $output->writeln('Target commit: '.$targetCommit, OutputInterface::VERBOSITY_DEBUG);
190
            $output->writeln('Last common commit: '.$lastCommonCommit, OutputInterface::VERBOSITY_DEBUG);
191
192
            list($previousCodeCoverageProvider, $previousMethodsProvider) = $this->getMeasuresFromCommit($buildService, $mergeRequest['target_project_id'], $lastCommonCommit, $cloverFilePath, $crap4JFilePath, $config->getJobStage(), $config->getGitlabBuildName(), null);
193
            //list($previousCodeCoverageProvider, $previousMethodsProvider) = $this->getMeasuresFromBranch($buildService, $mergeRequest['target_project_id'], $mergeRequest['target_branch'], $cloverFilePath, $crap4JFilePath);
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
194
195
            $message = new Message();
196
            if ($codeCoverageProvider !== null) {
197
                $message->addCoverageMessage($codeCoverageProvider, $previousCodeCoverageProvider);
198
            } else {
199
                $output->writeln('Could not find clover file for code coverage analysis.');
200
            }
201
            if ($methodsProvider !== null) {
202
                $message->addDifferencesHtml($methodsProvider, $previousMethodsProvider, $diffService, $commitSha, $gitlabUrl, $projectName);
203
            } else {
204
                $output->writeln('Could not find clover file nor crap4j file for CRAP score analysis.');
205
            }
206
207
            $this->addFilesToMessage($message, $files, $output, $config);
208
209
            $client->merge_requests->addNote($projectName, $mergeRequest['iid'], (string) $message);
210
211
            $inMergeRequest = true;
212
        } catch (MergeRequestNotFoundException $e) {
213
            // If there is no merge request attached to this build, let's skip the merge request comment. We can still make some comments on the commit itself!
214
            $output->writeln('It seems that this CI build is not part of a merge request.');
215
        }
216
217
        try {
218
            $targetProjectId = $mergeRequest['target_project_id'] ?? $projectName;
219
            list($lastCommitCoverage, $lastCommitMethodsProvider) = $this->getMeasuresFromBranch($buildService, $targetProjectId, $currentBranchName, $cloverFilePath, $crap4JFilePath, $config->getJobStage(), $config->getGitlabBuildName(), $config->getGitlabPipelineId());
220
221
            if ($config->isAddCommentsInCommits()) {
222
                $sendCommentService->sendDifferencesCommentsInCommit($methodsProvider, $lastCommitMethodsProvider, $projectName, $commitSha, $gitlabUrl);
0 ignored issues
show
Bug introduced by
It seems like $methodsProvider defined by null on line 130 can also be of type null; however, TheCodingMachine\Washing...encesCommentsInCommit() does only seem to accept object<TheCodingMachine\...MethodFetcherInterface>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
223
            }
224
225
            if ($config->isOpenIssue() && !$inMergeRequest) {
226
                $message = new Message();
227
228
                if ($codeCoverageProvider !== null) {
229
                    $message->addCoverageMessage($codeCoverageProvider, $lastCommitCoverage);
230
                } else {
231
                    $output->writeln('Could not find clover file for code coverage analysis.');
232
                }
233
234
                if ($methodsProvider !== null) {
235
                    $message->addDifferencesHtml($methodsProvider, $lastCommitMethodsProvider, $diffService, $commitSha, $gitlabUrl, $projectName);
236
                } else {
237
                    $output->writeln('Could not find clover file nor crap4j file for CRAP score analysis.');
238
                }
239
240
                $this->addFilesToMessage($message, $files, $output, $config);
241
242
                $project = new Project($projectName, $client);
243
244
                $options = [
245
                    'description' => (string) $message
246
                ];
247
248
                $userId = $this->getCommiterId($project, $commitSha);
249
                if ($userId !== null) {
250
                    $options['assignee_id'] = $userId;
251
                }
252
253
                $project->createIssue('Build failed', $options);
254
            }
255
        } catch (BuildNotFoundException $e) {
256
            $output->writeln('Unable to find a previous build for this branch. Skipping adding comments inside the commit. '.$e->getMessage());
257
        }
258
    }
259
260
    /**
261
     * Returns the user id of the committer.
262
     *
263
     * @param Project $project
264
     * @param string $commitRef
265
     * @return int|null
266
     */
267
    private function getCommiterId(Project $project, $commitRef)
268
    {
269
270
        $commit = $project->commit($commitRef);
271
272
        return $commit->committer ? $commit->committer->id :  null;
273
    }
274
275
    /**
276
     * @param BuildService $buildService
277
     * @param string $projectName
278
     * @param string $targetBranch
279
     * @param string $cloverPath
280
     * @param string $crap4JPath
281
     * @return array First element: code coverage, second element: list of methods.
282
     * @throws BuildNotFoundException
283
     */
284
    public function getMeasuresFromBranch(BuildService $buildService, string $projectName, string $targetBranch, string $cloverPath, string $crap4JPath, string $jobStage, string $buildName, string $excludePipelineId) : array
285
    {
286
        try {
287
            $tmpFile = tempnam(sys_get_temp_dir(), 'art').'.zip';
288
289
            $buildService->dumpArtifactFromBranch($projectName, $targetBranch, $buildName, $jobStage, $tmpFile, $excludePipelineId);
290
            $zipFile = new \ZipArchive();
291
            if ($zipFile->open($tmpFile)!==true) {
292
                throw new \RuntimeException('Invalid ZIP archive '.$tmpFile);
293
            }
294
            return $this->getMeasuresFromZipFile($zipFile, $cloverPath, $crap4JPath);
295
        } catch (\RuntimeException $e) {
296
            if ($e->getCode() === 404) {
297
                // We could not find a previous clover file in the master branch.
298
                // Maybe this branch is the first to contain clover files?
299
                // Let's deal with this by generating a fake "empty" clover file.
300
                $this->logger->info('We could not find a previous clover file in the build attached to branch '.$targetBranch.'. Maybe this commit is the first on this branch?');
301
                return [EmptyCloverFile::create(), EmptyCloverFile::create()];
302
            } else {
303
                throw $e;
304
            }
305
        }
306
    }
307
308
    public function getMeasuresFromCommit(BuildService $buildService, string $projectName, string $commitId, string $cloverPath, string $crap4JPath, string $jobStage, string $buildName, ?string $excludePipelineId) : array
309
    {
310
        try {
311
            $tmpFile = tempnam(sys_get_temp_dir(), 'art').'.zip';
312
313
            $pipeline = $buildService->getLatestPipelineFromCommitId($projectName, $commitId, $excludePipelineId);
314
            $buildService->dumpArtifact($projectName, $pipeline['id'], $buildName, $jobStage, $tmpFile);
315
            $zipFile = new \ZipArchive();
316
            if ($zipFile->open($tmpFile)!==true) {
317
                throw new \RuntimeException('Invalid ZIP archive '.$tmpFile);
318
            }
319
            return $this->getMeasuresFromZipFile($zipFile, $cloverPath, $crap4JPath);
320
        } catch (\RuntimeException $e) {
321
            if ($e->getCode() === 404) {
322
                // We could not find a previous clover file in the given commit.
323
                // Maybe this branch is the first to contain clover files?
324
                // Let's deal with this by generating a fake "empty" clover file.
325
                $this->logger->warning('We could not find a previous clover file in the build attached to commit '.$commitId.'. Maybe this branch is the first to contain clover files?');
326
                $this->logger->debug($e->getMessage().' - '.$e->getTraceAsString(), [
327
                    'exception' => $e
328
                ]);
329
                return [EmptyCloverFile::create(), EmptyCloverFile::create()];
330
            } else {
331
                throw $e;
332
            }
333
        } catch (BuildNotFoundException $e) {
334
            // Maybe there is no .gitlab-ci.yml file on the target branch? In this case, there is no build.
335
            $this->logger->warning('We could not find a build for commit '.$commitId.'.');
336
            return [EmptyCloverFile::create(), EmptyCloverFile::create()];
337
        }
338
    }
339
340
    private function getMeasuresFromZipFile(\ZipArchive $zipFile, string $cloverPath, string $crap4JPath) : array
341
    {
342
        $cloverFileString = $zipFile->getFromName($cloverPath);
343
344
        $cloverFile = null;
345
        if ($cloverFileString !== false) {
346
            $cloverFile = CloverFile::fromString($cloverFileString, getcwd());
347
        }
348
349
        $crap4JString = $zipFile->getFromName($crap4JPath);
350
351
        $crap4JFile = null;
352
        if ($crap4JString !== false) {
353
            $crap4JFile = Crap4JFile::fromString($crap4JString);
354
        }
355
356
        $methodsProvider = null;
0 ignored issues
show
Unused Code introduced by
$methodsProvider is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
357
        $codeCoverageProvider = null;
358
359
        if ($cloverFile !== null && $crap4JFile !== null) {
360
            $methodsProvider = new CrapMethodMerger($cloverFile, $crap4JFile);
361
            $codeCoverageProvider = $cloverFile;
362
        } elseif ($cloverFile !== null) {
363
            $methodsProvider = $cloverFile;
364
            $codeCoverageProvider = $cloverFile;
365
        } elseif ($crap4JFile !== null) {
366
            $methodsProvider = $crap4JFile;
367
        } else {
368
            return [EmptyCloverFile::create(), EmptyCloverFile::create()];
369
        }
370
371
        return [$codeCoverageProvider, $methodsProvider];
372
    }
373
374
    private function addFilesToMessage(Message $message, array $files, OutputInterface $output, Config $config) {
375
        foreach ($files as $file) {
376
            if (!file_exists($file)) {
377
                $output->writeln('<error>Could not find file to send "'.$file.'". Skipping this file.</error>');
378
                continue;
379
            }
380
381
            $message->addFile(new \SplFileInfo($file), $config->getGitlabUrl(), $config->getGitlabProjectName(), $config->getGitlabJobId());
382
        }
383
    }
384
}
385
386
/*
387
=================ENV IN A PR CONTEXT =========================
388
389
CI_BUILD_TOKEN=xxxxxx
390
HOSTNAME=runner-9431b96d-project-428-concurrent-0
391
PHP_INI_DIR=/usr/local/etc/php
392
PHP_ASC_URL=https://secure.php.net/get/php-7.0.15.tar.xz.asc/from/this/mirror
393
CI_BUILD_BEFORE_SHA=7af13f8e3bd090c7c34750e4badfc66a5f0af110
394
CI_SERVER_VERSION=
395
CI_BUILD_ID=109
396
OLDPWD=/
397
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2
398
PHP_MD5=dca23412f3e3b3987e582091b751925d
399
CI_PROJECT_ID=428
400
PHPIZE_DEPS=autoconf 		file 		g++ 		gcc 		libc-dev 		make 		pkg-config 		re2c
401
PHP_URL=https://secure.php.net/get/php-7.0.15.tar.xz/from/this/mirror
402
CI_BUILD_REF_NAME=feature/js-ci
403
CI_BUILD_REF=7af13f8e3bd090c7c34750e4badfc66a5f0af110
404
PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie
405
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
406
CI_BUILD_STAGE=test
407
CI_PROJECT_DIR=/builds/tcm-projects/uneo
408
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2
409
GPG_KEYS=1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
410
PWD=/builds/tcm-projects/uneo
411
CI_DEBUG_TRACE=false
412
CI_SERVER_NAME=GitLab CI
413
XDEBUG_VERSION=2.5.0
414
GITLAB_CI=true
415
CI_SERVER_REVISION=
416
CI_BUILD_NAME=test:app
417
HOME=/root
418
SHLVL=1
419
PHP_SHA256=300364d57fc4a6176ff7d52d390ee870ab6e30df121026649f8e7e0b9657fe93
420
CI_SERVER=yes
421
CI=true
422
CI_BUILD_REPO=http://gitlab-ci-token:[email protected]/tcm-projects/uneo.git
423
PHP_VERSION=7.0.15
424
425
===================ENV IN A COMMIT CONTEXT
426
427
CI_BUILD_TOKEN=xxxxxx
428
HOSTNAME=runner-9431b96d-project-447-concurrent-0
429
PHP_INI_DIR=/usr/local/etc/php
430
PHP_ASC_URL=https://secure.php.net/get/php-7.0.15.tar.xz.asc/from/this/mirror
431
CI_BUILD_BEFORE_SHA=42dd9686eafc2e8fb0a6b4d2c6785baec229c94a
432
CI_SERVER_VERSION=
433
CI_BUILD_ID=192
434
OLDPWD=/
435
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2
436
PHP_MD5=dca23412f3e3b3987e582091b751925d
437
CI_PROJECT_ID=447
438
GITLAB_API_TOKEN=xxxxxxxxxxxxxxchangedmanually
439
PHPIZE_DEPS=autoconf 		file 		g++ 		gcc 		libc-dev 		make 		pkg-config 		re2c
440
PHP_URL=https://secure.php.net/get/php-7.0.15.tar.xz/from/this/mirror
441
CI_BUILD_REF_NAME=master
442
CI_BUILD_REF=42dd9686eafc2e8fb0a6b4d2c6785baec229c94a
443
PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie
444
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
445
CI_BUILD_STAGE=test
446
CI_PROJECT_DIR=/builds/dan/washing-test
447
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2
448
GPG_KEYS=1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
449
PWD=/builds/dan/washing-test
450
CI_DEBUG_TRACE=false
451
CI_SERVER_NAME=GitLab CI
452
XDEBUG_VERSION=2.5.0
453
GITLAB_CI=true
454
CI_SERVER_REVISION=
455
CI_BUILD_NAME=test
456
HOME=/root
457
SHLVL=1
458
PHP_SHA256=300364d57fc4a6176ff7d52d390ee870ab6e30df121026649f8e7e0b9657fe93
459
CI_SERVER=yes
460
CI=true
461
CI_BUILD_REPO=http://gitlab-ci-token:[email protected]/dan/washing-test.git
462
PHP_VERSION=7.0.15
463
*/