• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eiriksm / cosy-composer / 16469015360

23 Jul 2025 11:10AM UTC coverage: 86.578% (-0.4%) from 86.939%
16469015360

push

github

web-flow
More accurate parsing of named prs  (#427)

82 of 102 new or added lines in 9 files covered. (80.39%)

1 existing line in 1 file now uncovered.

2019 of 2332 relevant lines covered (86.58%)

44.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.32
/src/Providers/PublicGithubWrapper.php
1
<?php
2

3
namespace eiriksm\CosyComposer\Providers;
4

5
use Github\Exception\ValidationFailedException;
6
use GuzzleHttp\Psr7\Request;
7
use Http\Client\HttpClient;
8
use Psr\Http\Message\ResponseInterface;
9
use Violinist\Slug\Slug;
10
use GuzzleHttp\Psr7\Utils;
11
use Http\Discovery\HttpClientDiscovery;
12

13
class PublicGithubWrapper extends Github
14
{
15
    /**
16
     * @var string
17
     */
18
    private $userToken;
19

20
    /**
21
     * @var string
22
     */
23
    private $baseUrl;
24

25
    /**
26
     * @var \Violinist\ProjectData\ProjectData
27
     */
28
    private $project;
29

30
    private $httpClient;
31

32
    /**
33
     * @param string $userToken
34
     */
35
    public function setUserToken($userToken)
36
    {
37
        $this->userToken = $userToken;
16✔
38
    }
39

40
    public function setUrlFromTokenUrl($url)
41
    {
42
        $parsed_url = parse_url($url);
16✔
43
        if (empty($parsed_url['scheme'])) {
16✔
NEW
44
            $parsed_url['scheme'] = 'https';
×
45
        }
46
        if (empty($parsed_url['host'])) {
16✔
NEW
47
            $parsed_url['host'] = 'github.com';
×
48
        }
49
        $this->baseUrl = sprintf('%s://%s', $parsed_url['scheme'], $parsed_url['host']);
16✔
50
    }
51

52
    /**
53
     * @param \Violinist\ProjectData\ProjectData $project
54
     */
55
    public function setProject($project)
56
    {
57
        $this->project = $project;
16✔
58
    }
59

60
    public function forceUpdateBranch($branch, $sha)
61
    {
62
        $client = $this->getHttpClient();
3✔
63
        $url = sprintf('%s/api/github/update_branch?nid=%d&token=%s&branch=%s&new_sha=%s', $this->baseUrl, $this->project->getNid(), $this->userToken, $branch, $sha);
3✔
64
        $request = new Request('GET', $url);
3✔
65
        $resp = $client->sendRequest($request);
3✔
66
        $this->handleStatusCodeAndJsonResponse($resp, 'update branch');
3✔
67
    }
68

69
    public function createFork($user, $repo, $fork_user)
70
    {
71
        // Send all this data to the website endpoint.
72
        $client = $this->getHttpClient();
3✔
73
        $request = new Request('GET', $this->baseUrl . '/api/github/create_fork?nid=' . $this->project->getNid() . '&token=' . $this->userToken);
3✔
74
        $resp = $client->sendRequest($request);
3✔
75
        $this->handleStatusCodeAndJsonResponse($resp, 'create fork');
3✔
76
    }
77

78
    protected function handleStatusCodeAndJsonResponse(ResponseInterface $response, string $response_name)
79
    {
80
        if ($response->getStatusCode() != 200) {
15✔
81
            throw new \Exception(sprintf('Wrong status code on %s request (%d)', $response_name, $response->getStatusCode()));
5✔
82
        }
83
        if (!$json = @json_decode((string) $response->getBody())) {
10✔
84
            throw new \Exception(sprintf('No json parsed in the %s response', $response_name));
5✔
85
        }
86
        return $json;
5✔
87
    }
88

89
    public function createPullRequest(Slug $slug, $params)
90
    {
91
        $user_name = $slug->getUserName();
4✔
92
        $user_repo = $slug->getUserRepo();
4✔
93
        $request = $this->createPullRequestRequest($user_name, $user_repo, $params);
4✔
94
        $client = $this->getHttpClient();
4✔
95
        $resp = $client->sendRequest($request);
4✔
96
        if ($resp->getStatusCode() == 422) {
4✔
97
            $msg = 'Remote create PR request failed';
1✔
98
            if ($json = @json_decode($resp->getBody())) {
1✔
99
                if (!empty($json->error) && is_string($json->error)) {
1✔
100
                    $msg = $json->error;
1✔
101
                }
102
            }
103
            throw new ValidationFailedException($msg);
1✔
104
        }
105
        $json = $this->handleStatusCodeAndJsonResponse($resp, 'create PR');
3✔
106
        return (array) $json;
1✔
107
    }
108

109
    public function updatePullRequest(Slug $slug, $id, $params)
110
    {
111
        $user_name = $slug->getUserName();
3✔
112
        $user_repo = $slug->getUserRepo();
3✔
113
        $client = $this->getHttpClient();
3✔
114
        $params['id'] = $id;
3✔
115
        $request = $this->createPullRequestRequest($user_name, $user_repo, $params, 'update_pr');
3✔
116
        $resp = $client->sendRequest($request);
3✔
117
        $this->handleStatusCodeAndJsonResponse($resp, 'update PR');
3✔
118
    }
119

120
    protected function createPullRequestRequest($user_name, $user_repo, $params, $path = 'create_pr')
121
    {
122
        $data = array_merge($params, [
7✔
123
            'nid' => $this->project->getNid(),
7✔
124
            'token' => $this->userToken,
7✔
125
            'user_name' => $user_name,
7✔
126
            'user_repo' => $user_repo,
7✔
127
        ]);
7✔
128
        $request = new Request('POST', $this->baseUrl . '/api/github/' . $path, [
7✔
129
            'Content-type' => 'application/json',
7✔
130
            'Accept' => 'application/json',
7✔
131
        ]);
7✔
132
        $request = $request->withBody(Utils::streamFor(json_encode($data)));
7✔
133
        return $request;
7✔
134
    }
135

136
    public function commitNewFiles($tmp_dir, $sha, $branch, $message, $lock_file_contents)
137
    {
138
        // Get the contents of all composer related files.
139
        $files = [
3✔
140
            'composer.json',
3✔
141
        ];
3✔
142
        if ($lock_file_contents) {
3✔
143
            $files[] = 'composer.lock';
2✔
144
        }
145
        $files_with_contents = [];
3✔
146
        foreach ($files as $file) {
3✔
147
            $subdir = '';
3✔
148
            if ($this->project->getComposerJsonDir()) {
3✔
149
                $subdir = $this->project->getComposerJsonDir() . '/';
×
150
            }
151
            $filename = "$tmp_dir/$subdir$file";
3✔
152
            if (!file_exists($filename)) {
3✔
153
                continue;
×
154
            }
155
            $files_with_contents[$file] = file_get_contents($filename);
3✔
156
        }
157
        $data = [
3✔
158
            'nid' => $this->project->getNid(),
3✔
159
            'token' => $this->userToken,
3✔
160
            'files' => $files_with_contents,
3✔
161
            'sha' => $sha,
3✔
162
            'branch' => $branch,
3✔
163
            'message' => $message,
3✔
164
        ];
3✔
165
        $client = $this->getHttpClient();
3✔
166
        $request = new Request('POST', $this->baseUrl . '/api/github/create_commit', [
3✔
167
            'Content-type' => 'application/json',
3✔
168
            'Accept' => 'application/json',
3✔
169
        ]);
3✔
170
        $request = $request->withBody(Utils::streamFor(json_encode($data)));
3✔
171
        $response = $client->sendRequest($request);
3✔
172
        $this->handleStatusCodeAndJsonResponse($response, 'commit files');
3✔
173
    }
174

175
    public function setHttpClient(HttpClient $client)
176
    {
177
        $this->httpClient = $client;
16✔
178
    }
179

180
    protected function getHttpClient()
181
    {
182
        if (!$this->httpClient) {
16✔
183
            $this->httpClient = HttpClientDiscovery::find();
×
184
        }
185
        return $this->httpClient;
16✔
186
    }
187
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc