All   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 15
Bugs 1 Features 3
Metric Value
wmc 16
c 15
b 1
f 3
lcom 1
cbo 6
dl 0
loc 178
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 17 1
A __destruct() 0 7 2
A setBranch() 0 4 1
A getCommits() 0 6 1
B execute() 0 48 6
A getImportedCommits() 0 13 2
A getDefaultBranch() 0 7 2
A getEnvironment() 0 17 1
1
<?php
2
3
namespace Cauditor\Runners;
4
5
use Cauditor\Aggregator;
6
use Cauditor\Analyzers\AnalyzerInterface;
7
use Cauditor\Api;
8
use Cauditor\Exception;
9
use MatthiasMullie\CI\Factory as CIFactory;
10
11
/**
12
 * @author Matthias Mullie <[email protected]>
13
 * @copyright Copyright (c) 2016, Matthias Mullie. All rights reserved.
14
 * @license LICENSE MIT
15
 */
16
class All implements RunnerInterface
17
{
18
    /**
19
     * @var Api
20
     */
21
    protected $api;
22
23
    /**
24
     * @var AnalyzerInterface
25
     */
26
    protected $analyzer;
27
28
    /**
29
     * @var bool
30
     */
31
    protected $stashed;
32
33
    /**
34
     * @var string
35
     */
36
    protected $branch;
37
38
    /**
39
     * @param Api               $api
40
     * @param AnalyzerInterface $analyzer
41
     */
42
    public function __construct(Api $api, AnalyzerInterface $analyzer)
43
    {
44
        $this->api = $api;
45
        $this->analyzer = $analyzer;
46
47
        // lets make sure the code we're testing is this specific commit,
48
        // without lingering uncommitted bits
49
        $output = exec('git stash');
50
        $this->stashed = $output !== 'No local changes to save';
51
52
        // store current branch
53
        $environment = $this->getEnvironment();
54
        $this->branch = $environment['branch'];
55
56
        // move to default branch, which is likely the one we want to analyze
57
        $this->setBranch($this->getDefaultBranch());
58
    }
59
60
    /**
61
     * Restores the original environment after analyzing.
62
     */
63
    public function __destruct()
64
    {
65
        exec("git checkout $this->branch");
66
        if ($this->stashed) {
67
            exec('git stash pop');
68
        }
69
    }
70
71
    /**
72
     * @param string $branch
73
     */
74
    public function setBranch($branch)
75
    {
76
        exec("git checkout $branch && git reset --hard && git pull");
77
    }
78
79
    /**
80
     * @return string[]
81
     */
82
    protected function getCommits()
83
    {
84
        exec("git log --pretty=format:'%H'", $commits);
85
86
        return $commits;
87
    }
88
89
    /**
90
     * @throws Exception
91
     */
92
    public function execute()
93
    {
94
        // exclude commits that have already been imported
95
        $commits = $this->getCommits();
96
        $imported = $this->getImportedCommits();
97
        $missing = array_diff($commits, $imported);
98
        foreach ($missing as $commit) {
99
            exec("git reset $commit --hard");
100
101
            do {
102
                try {
103
                    $metrics = $this->analyzer->execute();
104
                    break;
105
                } catch (Exception $e) {
106
                    // keep trying...
107
                }
108
            } while (true);
109
110
            $aggregator = new Aggregator($metrics);
111
            $data = array(
112
                'default-branch' => $this->getDefaultBranch(),
113
                'metrics' => $metrics,
114
                'avg' => $aggregator->average(),
115
                'min' => $aggregator->min(),
116
                'max' => $aggregator->max(),
117
                'weighed' => $aggregator->weigh(),
118
            ) + $this->getEnvironment();
119
120
            // submit to cauditor (note that branch can be empty for PRs)
121
            $uri = "/api/v1/{$data['slug']}/{$data['branch']}/{$data['commit']}";
122
            $uri = preg_replace('/(?<!:)\/+/', '/', $uri);
123
            $result = $this->api->put($uri, $data);
124
125
            $domain = $this->api->getDomain();
126
            if ($result !== false) {
127
                $result = json_decode($result, true);
128
                if (isset($result['error'])) {
129
                    echo "Failed to submit metrics to {$domain}/{$data['slug']}/{$data['commit']}/metrics: {$result['error']}\n";
130
                } else {
131
                    echo "Submitted metrics to {$domain}/{$data['slug']}/{$data['commit']}/metrics\n";
132
                }
133
            } else {
134
                echo "Failed to submit metrics to {$domain}/{$data['slug']}/{$data['commit']}/metrics\n";
135
            }
136
        }
137
138
        echo "Done!\n";
139
    }
140
141
    /**
142
     * Returns array of commit hashes that have already been imported.
143
     *
144
     * @return string[]
145
     *
146
     * @throws Exception
147
     */
148
    protected function getImportedCommits()
149
    {
150
        $environment = $this->getEnvironment();
151
        $slug = $environment['slug'];
152
        $branch = $environment['branch'];
153
154
        $imported = $this->api->get("/api/v1/$slug/$branch");
155
        if ($imported === false) {
156
            throw new Exception('Failed to reach API.');
157
        }
158
159
        return json_decode($imported, true);
160
    }
161
162
    /**
163
     * @return string
164
     */
165
    protected function getDefaultBranch()
166
    {
167
        $config = shell_exec('cat .git/config');
168
        preg_match('/\[branch "(.+)"\]/', $config, $match);
169
170
        return isset($match[1]) ? $match[1] : 'master';
171
    }
172
173
    /**
174
     * @return array
175
     */
176
    protected function getEnvironment()
177
    {
178
        // get build data from CI
179
        $factory = new CIFactory();
180
        $environment = $factory->getCurrent();
181
182
        return array(
183
            'repo' => $environment->getRepo(),
184
            'slug' => $environment->getSlug(),
185
            'branch' => $environment->getBranch(),
186
            'pull-request' => $environment->getPullRequest(),
187
            'commit' => $environment->getCommit(),
188
            'previous-commit' => $environment->getPreviousCommit(),
189
            'author-email' => $environment->getAuthorEmail(),
190
            'timestamp' => $environment->getTimestamp(),
191
        );
192
    }
193
}
194