Issues (21)

src/Controller/Project/ApiController.php (1 issue)

Labels
Severity
1
<?php
2
3
namespace App\Controller\Project;
4
5
use App\Controller\Traits\ApiTrait;
6
use App\Controller\Traits\ProjectTrait;
7
use App\Facades\Log;
8
use App\Facades\Provider;
9
use App\Facades\Security;
10
use App\Model\Deployment;
11
use App\Model\Event;
12
use App\Model\Project;
13
use App\Queue\DeployJob;
14
use Exception;
15
use Psr\Http\Message\ResponseInterface;
16
use Psr\Http\Message\ServerRequestInterface;
17
use Ronanchilvers\Foundation\Facade\Queue;
18
use Ronanchilvers\Orm\Orm;
19
use RuntimeException;
20
21
/**
22
 * API Controller supporting the project UI
23
 *
24
 * @author Ronan Chilvers <[email protected]>
25
 */
26
class ApiController
27
{
28
    use ProjectTrait;
29
    use ApiTrait;
30
31
    /**
32
     * Get the event data for a project
33
     *
34
     * @param ServerRequestInterface $request
35
     * @param ResponseInterface $response
36
     * @param array $args
37
     * @return ResponseInterface
38
     * @author Ronan Chilvers <[email protected]>
39
     */
40
    public function events(
41
        ServerRequestInterface $request,
42
        ResponseInterface $response,
43
        array $args
44
    ) {
45
        if (!$project = $this->projectFromArgs($args)) {
46
            return $this->apiError(
47
                $response,
48
                'Invalid project'
49
            );
50
        }
51
        if (!isset($args['number']) || 0 == (int) $args['number']) {
52
            return $this->apiError(
53
                $response,
54
                'Invalid deployment number'
55
            );
56
        }
57
        $number = (int) $args['number'];
58
        $deployment = Orm::finder(Deployment::class)->forProjectIdAndNumber(
59
            $project->id,
60
            $number
61
        );
62
        if (!$deployment instanceof Deployment) {
63
            return $this->apiError(
64
                $response,
65
                'Deployment not found for project'
66
            );
67
        }
68
        $data = [
69
            // 'project' => $project->toArray(),
70
            'deployment' => $deployment->toArray(),
71
        ];
72
        $events = Orm::finder(Event::class)->arrayForDeploymentId(
73
            $deployment->id
74
        );
75
        $data['events'] = $events;
76
77
        return $this->apiResponse(
78
            $response,
79
            $data
80
        );
81
    }
82
83
    /**
84
     * Trigger a build of a project specified by the project token
85
     *
86
     * @author Ronan Chilvers <[email protected]>
87
     */
88
    public function webhookDeploy(
89
        ServerRequestInterface $request,
90
        ResponseInterface $response,
91
        $args
92
    ) {
93
        try {
94
            $project = Orm::finder(Project::class)->forToken($args['token']);
95
            if (!$project instanceof Project) {
96
                throw new RuntimeException(
97
                    'Invalid or unknown project token',
98
                    400
99
                );
100
            }
101
            if (!$project->isDeployable()) {
102
                throw new RuntimeException(
103
                    'Project is not deployable at the moment',
104
                    400
105
                );
106
            }
107
            $branch = $request->getQueryParam('branch', null);
0 ignored issues
show
The method getQueryParam() does not exist on Psr\Http\Message\ServerRequestInterface. Did you maybe mean getQueryParams()? ( Ignorable by Annotation )

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

107
            /** @scrutinizer ignore-call */ 
108
            $branch = $request->getQueryParam('branch', null);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
108
            if (!is_null($branch)) {
109
                $branch = filter_var($branch, FILTER_SANITIZE_STRING);
110
            } else {
111
                $branch = $project->branch;
112
            }
113
            Log::debug("Queueing project from webhook for branch {$branch}", [
114
                'project' => $project->toArray(),
115
            ]);
116
            $provider = Provider::forProject(
117
                $project
118
            );
119
            $finder = Orm::finder(Event::class);
120
            Orm::transaction(function() use ($project, $provider, $finder, $branch) {
121
                try {
122
                    $deployment = Orm::finder(Deployment::class)->nextForProject(
123
                        $project
124
                    );
125
                    $deployment->source = 'webhook'; //Security::email();
126
                    if (!$deployment->save()) {
127
                        Log::debug('Unable to create new deployment object', [
128
                            'project' => $project->toArray(),
129
                        ]);
130
                        throw new RuntimeException('Unable to create new deployment');
131
                    }
132
                    $finder->event(
133
                        'info',
134
                        $deployment,
135
                        'Initialise',
136
                        sprintf("Querying %s for head commit data", $provider->getLabel())
137
                    );
138
                    $head = $provider->getHeadInfo($project->repository, $branch);
139
                    $finder->event(
140
                        'info',
141
                        $deployment,
142
                        'Initialise',
143
                        "Commit data : " . json_encode($head, JSON_PRETTY_PRINT)
144
                    );
145
                    Log::debug('Updating deployment commit information', $head);
146
                    $deployment->branch    = $branch;
147
                    $deployment->sha       = $head['sha'];
148
                    $deployment->author    = $head['author'];
149
                    $deployment->committer = $head['committer'];
150
                    $deployment->message   = $head['message'];
151
                    if (!$deployment->save()) {
152
                        throw new RuntimeException(
153
                            'Unable to create new deployment',
154
                            500
155
                        );
156
                    }
157
                    if (!$project->markDeploying()) {
158
                        throw new RuntimeException(
159
                            'Unable to mark project as deploying',
160
                            500
161
                        );
162
                    }
163
                    Queue::dispatch(
164
                        new DeployJob($deployment)
165
                    );
166
                } catch (Exception $ex) {
167
                    if (isset($deployment) && $deployment instanceof Deployment) {
168
                        $finder->event(
169
                            'error',
170
                            $deployment,
171
                            'Initialise',
172
                            $ex->getMessage()
173
                        );
174
                    }
175
                    throw $ex;
176
                }
177
            });
178
179
            Log::error('Queued deployment from webhook', [
180
                'project' => $project->toArray(),
181
            ]);
182
            return $this->apiResponse(
183
                $response,
184
                []
185
            );
186
        } catch (Exception $ex) {
187
            Log::error('Failed to initialise new deployment', [
188
                'exception' => $ex,
189
            ]);
190
            return $this->apiError(
191
                $response,
192
                $ex->getMessage(),
193
                $ex->getCode()
194
            );
195
        }
196
    }
197
}
198