Completed
Push — 1.0 ( 0ccbd9...8938f0 )
by David
03:58
created

RunCommand::configure()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 38
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 38
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 29
nc 1
nop 0
1
<?php
2
namespace TheCodingMachine\WashingMachine\Commands;
3
4
use Gitlab\Client;
5
use Gitlab\Exception\RuntimeException;
6
use Symfony\Component\Console\Command\Command;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Input\InputOption;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use TheCodingMachine\WashingMachine\Clover\CloverFile;
11
use TheCodingMachine\WashingMachine\Clover\CloverFileInterface;
12
use TheCodingMachine\WashingMachine\Clover\DiffService;
13
use TheCodingMachine\WashingMachine\Clover\EmptyCloverFile;
14
use TheCodingMachine\WashingMachine\Gitlab\BuildNotFoundException;
15
use TheCodingMachine\WashingMachine\Gitlab\BuildService;
16
use TheCodingMachine\WashingMachine\Gitlab\MergeRequestNotFoundException;
17
use TheCodingMachine\WashingMachine\Gitlab\SendCommentService;
18
19
class RunCommand extends Command
20
{
21
22
    protected function configure()
23
    {
24
        $this
25
            ->setName('run')
26
            ->setDescription('Analyses the coverage report files and upload the result to Gitlab')
27
            //->setHelp("This command allows you to create users...")
28
            ->addOption('clover',
29
                'c',
30
                InputOption::VALUE_REQUIRED,
31
                'The path to the clover file generated by PHPUnit.',
32
                'clover.xml')
33
            ->addOption('gitlab-url',
34
                'u',
35
                InputOption::VALUE_REQUIRED,
36
                'The Gitlab URL. If not specified, it is deduced from the CI_BUILD_REPO environment variable.',
37
                null)
38
            ->addOption('gitlab-api-token',
39
                't',
40
                InputOption::VALUE_REQUIRED,
41
                'The Gitlab API token. If not specified, it is fetched from the GITLAB_API_TOKEN environment variable.',
42
                null)
43
            /*->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...
44
                'p',
45
                InputOption::VALUE_REQUIRED,
46
                'The Gitlab project ID. If not specified, it is fetched from the CI_PROJECT_ID environment variable.',
47
                null)*/
48
            ->addOption('gitlab-project-name',
49
                'p',
50
                InputOption::VALUE_REQUIRED,
51
                'The Gitlab project name (in the form "group/name"). If not specified, it is deduced from the CI_PROJECT_DIR environment variable.',
52
                null)
53
            ->addOption('gitlab-build-ref',
54
                'r',
55
                InputOption::VALUE_REQUIRED,
56
                'The Gitlab CI build reference. If not specified, it is deduced from the CI_BUILD_REF environment variable.',
57
                null)
58
        ;
59
    }
60
61
    protected function execute(InputInterface $input, OutputInterface $output)
62
    {
63
        $config = new Config($input);
64
65
        $cloverFilePath = $config->getCloverFilePath();
66
67
        $cloverFile = CloverFile::fromFile($cloverFilePath, getcwd());
68
        $output->writeln(sprintf('Code coverage: %.2f%%', $cloverFile->getCoveragePercentage()*100));
69
70
        $gitlabApiToken = $config->getGitlabApiToken();
71
72
        $gitlabUrl = $config->getGitlabUrl();
73
        $gitlabApiUrl = $config->getGitlabApiUrl();
74
75
76
77
        /*$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...
78
        if ($projectId === null) {
79
            $projectId = getenv('CI_PROJECT_ID');
80
            if ($projectId === false) {
81
                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.');
82
            }
83
        }*/
84
85
        $projectName = $config->getGitlabProjectName();
86
87
        $buildRef = $config->getGitlabBuildRef();
88
89
        $currentBranchName = $config->getCurrentBranchName();
90
91
        $client = new Client($gitlabApiUrl);
92
        $client->authenticate($gitlabApiToken);
93
94
        $diffService = new DiffService(1, 20);
95
96
        $sendCommentService = new SendCommentService($client, $diffService);
97
98
        // From CI_BUILD_REF, we can get the commit ( -> project -> build -> commit )
99
        // From the merge_requests API, we can get the list of commits for a single merge request
100
        // Hence, we can find the merge_request matching a build!
101
102
        $buildService = new BuildService($client);
103
104
        try {
105
            $mergeRequest = $buildService->findMergeRequestByBuildRef($projectName, $buildRef);
106
107
108
            try {
109
                $previousCloverFile = $this->getCloverFileFromBranch($buildService, $mergeRequest['target_project_id'], $mergeRequest['target_branch']);
110
            } catch (RuntimeException $e) {
111
                if ($e->getCode() === 404) {
112
                    // We could not find a previous clover file in the master branch.
113
                    // Maybe this branch is the first to contain clover files?
114
                    // Let's deal with this by generating a fake "empty" clover file.
115
                    $previousCloverFile = EmptyCloverFile::create();
116
                } else {
117
                    throw $e;
118
                }
119
            }
120
121
            $sendCommentService->sendCodeCoverageCommentToMergeRequest($cloverFile, $previousCloverFile, $projectName, $mergeRequest['id'], $buildRef, $gitlabUrl);
0 ignored issues
show
Documentation introduced by
$cloverFile is of type object<TheCodingMachine\...hine\Clover\CloverFile>, but the function expects a object<TheCodingMachine\...ab\CloverFileInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$previousCloverFile is of type object<TheCodingMachine\...er\CloverFileInterface>, but the function expects a object<TheCodingMachine\...ab\CloverFileInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
122
123
        } catch (MergeRequestNotFoundException $e) {
124
            // 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!
125
126
            $output->writeln('It seems that this CI build is not part of a merge request. Skipping.');
127
        }
128
129
        try {
130
            $lastCommitCloverFile = $this->getCloverFileFromBranch($buildService, $mergeRequest['target_project_id'], $currentBranchName);
131
            $sendCommentService->sendDifferencesCommentsInCommit($cloverFile, $lastCommitCloverFile, $projectName, $buildRef, $gitlabUrl);
0 ignored issues
show
Documentation introduced by
$cloverFile is of type object<TheCodingMachine\...hine\Clover\CloverFile>, but the function expects a object<TheCodingMachine\...ab\CloverFileInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$lastCommitCloverFile is of type object<TheCodingMachine\...er\CloverFileInterface>, but the function expects a object<TheCodingMachine\...ab\CloverFileInterface>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
132
        } catch (BuildNotFoundException $e) {
133
            $output->writeln('Unable to find a previous build for this branch. Skipping adding comments inside the commit. '.$e->getMessage());
134
        }
135
136
    }
137
138
    public function getCloverFileFromBranch(BuildService $buildService, string $projectName, string $targetBranch) : CloverFileInterface
139
    {
140
        $tmpFile = tempnam(sys_get_temp_dir(), 'art').'.zip';
141
142
        $buildService->dumpArtifactFromBranch($projectName, $targetBranch, $tmpFile);
143
        $zipFile = new \ZipArchive();
144
        if ($zipFile->open($tmpFile)!==true) {
145
            throw new \RuntimeException('Invalid ZIP archive '.$tmpFile);
146
        }
147
        $cloverFileString = $zipFile->getFromName('clover.xml');
148
149
        $cloverFile = CloverFile::fromString($cloverFileString, getcwd());
150
        return $cloverFile;
151
    }
152
}
153
154
/*
155
=================ENV IN A PR CONTEXT =========================
156
157
CI_BUILD_TOKEN=xxxxxx
158
HOSTNAME=runner-9431b96d-project-428-concurrent-0
159
PHP_INI_DIR=/usr/local/etc/php
160
PHP_ASC_URL=https://secure.php.net/get/php-7.0.15.tar.xz.asc/from/this/mirror
161
CI_BUILD_BEFORE_SHA=7af13f8e3bd090c7c34750e4badfc66a5f0af110
162
CI_SERVER_VERSION=
163
CI_BUILD_ID=109
164
OLDPWD=/
165
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2
166
PHP_MD5=dca23412f3e3b3987e582091b751925d
167
CI_PROJECT_ID=428
168
PHPIZE_DEPS=autoconf 		file 		g++ 		gcc 		libc-dev 		make 		pkg-config 		re2c
169
PHP_URL=https://secure.php.net/get/php-7.0.15.tar.xz/from/this/mirror
170
CI_BUILD_REF_NAME=feature/js-ci
171
CI_BUILD_REF=7af13f8e3bd090c7c34750e4badfc66a5f0af110
172
PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie
173
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
174
CI_BUILD_STAGE=test
175
CI_PROJECT_DIR=/builds/tcm-projects/uneo
176
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2
177
GPG_KEYS=1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
178
PWD=/builds/tcm-projects/uneo
179
CI_DEBUG_TRACE=false
180
CI_SERVER_NAME=GitLab CI
181
XDEBUG_VERSION=2.5.0
182
GITLAB_CI=true
183
CI_SERVER_REVISION=
184
CI_BUILD_NAME=test:app
185
HOME=/root
186
SHLVL=1
187
PHP_SHA256=300364d57fc4a6176ff7d52d390ee870ab6e30df121026649f8e7e0b9657fe93
188
CI_SERVER=yes
189
CI=true
190
CI_BUILD_REPO=http://gitlab-ci-token:[email protected]/tcm-projects/uneo.git
191
PHP_VERSION=7.0.15
192
193
===================ENV IN A COMMIT CONTEXT
194
195
CI_BUILD_TOKEN=xxxxxx
196
HOSTNAME=runner-9431b96d-project-447-concurrent-0
197
PHP_INI_DIR=/usr/local/etc/php
198
PHP_ASC_URL=https://secure.php.net/get/php-7.0.15.tar.xz.asc/from/this/mirror
199
CI_BUILD_BEFORE_SHA=42dd9686eafc2e8fb0a6b4d2c6785baec229c94a
200
CI_SERVER_VERSION=
201
CI_BUILD_ID=192
202
OLDPWD=/
203
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2
204
PHP_MD5=dca23412f3e3b3987e582091b751925d
205
CI_PROJECT_ID=447
206
GITLAB_API_TOKEN=xxxxxxxxxxxxxxchangedmanually
207
PHPIZE_DEPS=autoconf 		file 		g++ 		gcc 		libc-dev 		make 		pkg-config 		re2c
208
PHP_URL=https://secure.php.net/get/php-7.0.15.tar.xz/from/this/mirror
209
CI_BUILD_REF_NAME=master
210
CI_BUILD_REF=42dd9686eafc2e8fb0a6b4d2c6785baec229c94a
211
PHP_LDFLAGS=-Wl,-O1 -Wl,--hash-style=both -pie
212
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
213
CI_BUILD_STAGE=test
214
CI_PROJECT_DIR=/builds/dan/washing-test
215
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2
216
GPG_KEYS=1A4E8B7277C42E53DBA9C7B9BCAA30EA9C0D5763 6E4F6AB321FDC07F2C332E3AC2BF0BC433CFC8B3
217
PWD=/builds/dan/washing-test
218
CI_DEBUG_TRACE=false
219
CI_SERVER_NAME=GitLab CI
220
XDEBUG_VERSION=2.5.0
221
GITLAB_CI=true
222
CI_SERVER_REVISION=
223
CI_BUILD_NAME=test
224
HOME=/root
225
SHLVL=1
226
PHP_SHA256=300364d57fc4a6176ff7d52d390ee870ab6e30df121026649f8e7e0b9657fe93
227
CI_SERVER=yes
228
CI=true
229
CI_BUILD_REPO=http://gitlab-ci-token:[email protected]/dan/washing-test.git
230
PHP_VERSION=7.0.15
231
*/