Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

Passed
Push — add-update-command ( 3eac9b )
by Pedro
15:29
created

UpgradeCommand   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 233
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 117
c 1
b 0
f 1
dl 0
loc 233
rs 9.92
wmc 31

7 Methods

Rating   Name   Duplication   Size   Complexity  
A resolveStepsForMajor() 0 15 1
A printResultDetails() 0 18 3
A extractMajorVersion() 0 7 2
B outputSummary() 0 60 8
A outputFormat() 0 5 2
A shouldOfferFix() 0 15 4
B handle() 0 88 11
1
<?php
2
3
namespace Backpack\CRUD\app\Console\Commands\Upgrade;
4
5
use Backpack\CRUD\app\Console\Commands\Traits\PrettyCommandOutput;
6
use Illuminate\Console\Command;
7
8
class UpgradeCommand extends Command
9
{
10
    use PrettyCommandOutput;
0 ignored issues
show
introduced by
The trait Backpack\CRUD\app\Consol...its\PrettyCommandOutput requires some properties which are not provided by Backpack\CRUD\app\Consol...\Upgrade\UpgradeCommand: $progressBar, $statusColor, $status
Loading history...
11
12
    protected $signature = 'backpack:upgrade
13
                                {version=7 : Target Backpack version to prepare for.}
14
                                {--stop-on-failure : Stop executing once a step fails.}
15
                                {--format=cli : Output format (cli, json).}
16
                                {--debug : Show debug information for executed processes.}';
17
18
    protected $description = 'Run opinionated upgrade checks to help you move between Backpack major versions.';
19
20
    public function handle(): int
21
    {
22
        $format = $this->outputFormat();
23
24
        if (! in_array($format, ['cli', 'json'], true)) {
25
            $this->errorBlock(sprintf('Unknown output format "%s". Supported formats: cli, json.', $format));
26
27
            return Command::INVALID;
28
        }
29
30
        $version = (string) $this->argument('version');
31
        $majorVersion = $this->extractMajorVersion($version);
32
33
        $stepClasses = $this->resolveStepsForMajor($majorVersion);
34
35
        if (empty($stepClasses)) {
36
            $this->errorBlock("No automated checks registered for Backpack v{$majorVersion}.");
37
38
            return Command::INVALID;
39
        }
40
41
        $context = new UpgradeContext($majorVersion);
42
43
        $this->infoBlock("Backpack v{$majorVersion} upgrade assistant", 'upgrade');
44
45
        $results = [];
46
47
        foreach ($stepClasses as $stepClass) {
48
            /** @var Step $step */
49
            $step = new $stepClass($context);
50
51
            $this->progressBlock($step->title());
52
53
            try {
54
                $result = $step->run();
55
            } catch (\Throwable $exception) {
56
                $result = StepResult::failure(
57
                    $exception->getMessage(),
58
                    [
59
                        'Step: '.$stepClass,
60
                    ]
61
                );
62
            }
63
64
            $this->closeProgressBlock(strtoupper($result->status->label()), $result->status->color());
65
66
            $this->printResultDetails($result);
67
68
            if ($this->shouldOfferFix($step, $result)) {
69
                $applyFix = $this->confirm('  Apply automatic fix?', false);
70
71
                if ($applyFix) {
72
                    $this->progressBlock('Applying automatic fix');
73
                    $fixResult = $step->fix($result);
74
                    $this->closeProgressBlock(strtoupper($fixResult->status->label()), $fixResult->status->color());
75
                    $this->printResultDetails($fixResult);
76
77
                    if (! $fixResult->status->isFailure()) {
78
                        $this->progressBlock('Re-running '.$step->title());
79
80
                        try {
81
                            $result = $step->run();
82
                        } catch (\Throwable $exception) {
83
                            $result = StepResult::failure(
84
                                $exception->getMessage(),
85
                                [
86
                                    'Step: '.$stepClass,
87
                                ]
88
                            );
89
                        }
90
91
                        $this->closeProgressBlock(strtoupper($result->status->label()), $result->status->color());
92
                        $this->printResultDetails($result);
93
                    }
94
                }
95
            }
96
97
            $results[] = [
98
                'step' => $stepClass,
99
                'result' => $result,
100
            ];
101
102
            if ($this->option('stop-on-failure') && $result->status->isFailure()) {
103
                break;
104
            }
105
        }
106
107
        return $this->outputSummary($majorVersion, $results);
108
    }
109
110
    protected function outputSummary(string $majorVersion, array $results): int
111
    {
112
        $format = $this->outputFormat();
113
114
        $hasFailure = collect($results)->contains(function ($entry) {
0 ignored issues
show
Bug introduced by
$results of type array is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

114
        $hasFailure = collect(/** @scrutinizer ignore-type */ $results)->contains(function ($entry) {
Loading history...
115
            /** @var StepResult $result */
116
            $result = $entry['result'];
117
118
            return $result->status->isFailure();
119
        });
120
121
        $warnings = collect($results)->filter(function ($entry) {
122
            /** @var StepResult $result */
123
            $result = $entry['result'];
124
125
            return $result->status === StepStatus::Warning;
126
        });
127
128
        if ($format === 'json') {
129
            $payload = [
130
                'version' => $majorVersion,
131
                'results' => collect($results)->map(function ($entry) {
132
                    /** @var StepResult $result */
133
                    $result = $entry['result'];
134
135
                    return [
136
                        'step' => $entry['step'],
137
                        'status' => $result->status->value,
138
                        'summary' => $result->summary,
139
                        'details' => $result->details,
140
                    ];
141
                })->values()->all(),
142
            ];
143
144
            $this->newLine();
145
            $this->line(json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
146
147
            return $hasFailure ? Command::FAILURE : Command::SUCCESS;
148
        }
149
150
        $this->newLine();
151
        $this->infoBlock('Summary', 'done');
152
153
        $this->note(sprintf('Checked %d upgrade steps.', count($results)), 'gray');
154
155
        if ($hasFailure) {
156
            $this->note('At least one step reported a failure. Review the messages above before continuing.', 'red', 'red');
157
        }
158
159
        if ($warnings->isNotEmpty()) {
160
            $this->note(sprintf('%d step(s) reported warnings.', $warnings->count()), 'yellow', 'yellow');
161
        }
162
163
        if (! $hasFailure && $warnings->isEmpty()) {
164
            $this->note('All checks passed, you are ready to continue with the manual steps from the upgrade guide.', 'green', 'green');
165
        }
166
167
        $this->newLine();
168
169
        return $hasFailure ? Command::FAILURE : Command::SUCCESS;
170
    }
171
172
    protected function printResultDetails(StepResult $result): void
173
    {
174
        $color = match ($result->status) {
175
            StepStatus::Passed => 'green',
176
            StepStatus::Warning => 'yellow',
177
            StepStatus::Failed => 'red',
178
            StepStatus::Skipped => 'gray',
179
        };
180
181
        if ($result->summary !== '') {
182
            $this->note($result->summary, $color, $color);
183
        }
184
185
        foreach ($result->details as $detail) {
186
            $this->note($detail, 'gray');
187
        }
188
189
        $this->newLine();
190
    }
191
192
    protected function shouldOfferFix(Step $step, StepResult $result): bool
193
    {
194
        if ($this->outputFormat() === 'json') {
195
            return false;
196
        }
197
198
        if (! $this->input->isInteractive()) {
199
            return false;
200
        }
201
202
        if (! in_array($result->status, [StepStatus::Warning, StepStatus::Failed], true)) {
203
            return false;
204
        }
205
206
        return $step->canFix($result);
207
    }
208
209
    protected function outputFormat(): string
210
    {
211
        $format = strtolower((string) $this->option('format'));
212
213
        return $format !== '' ? $format : 'cli';
214
    }
215
216
    protected function resolveStepsForMajor(string $majorVersion): array
217
    {
218
        return match ($majorVersion) {
219
            '7' => [
220
                v7\Steps\EnsureLaravelVersionStep::class,
221
                v7\Steps\EnsureBackpackCrudRequirementStep::class,
222
                v7\Steps\EnsureMinimumStabilityStep::class,
223
                v7\Steps\EnsureFirstPartyAddonsAreCompatibleStep::class,
224
                v7\Steps\CheckShowOperationComponentStep::class,
225
                v7\Steps\CheckOperationConfigFilesStep::class,
226
                v7\Steps\CheckThemeTablerConfigStep::class,
227
                v7\Steps\DetectDeprecatedWysiwygUsageStep::class,
228
                v7\Steps\DetectEditorAddonRequirementsStep::class,
229
            ],
230
            default => [],
231
        };
232
    }
233
234
    protected function extractMajorVersion(string $version): string
235
    {
236
        if (preg_match('/^(\d+)/', $version, $matches)) {
237
            return $matches[1];
238
        }
239
240
        return $version;
241
    }
242
}
243