Git
17 files changed +458 −11
Review
Insert
app/Http/Controllers/PullRequestController.php (+128 −0) added


  
1
<?php


  
2


      


  
3
namespace App\Http\Controllers;


  
4


      


  
5
use App\Services\RepositoryService;


  
6
use App\Models\PullRequest;


  
7
use App\Models\GithubUser;


  
8
use App\Models\Item;


  
9
use App\Helpers\DiffRenderer;


  
10
use App\GithubConfig;


  
11
use App\Helpers\ApiHelper;


  
12
use Illuminate\Support\Facades\DB;


  
13


      


  
14
class PullRequestController extends Controller


  
15
{


  
16
    public function metadata($organizationName, $repositoryName)


  
17
    {


  
18
        [$organization, $repository] = RepositoryService::getRepositoryWithOrganization($organizationName, $repositoryName);


  
19


      


  
20
        $branches = $repository->branches()->get();


  
21
        $branchNames = $branches->pluck('name');


  
22


      


  
23
        $assignees = $repository->contributors()->with('githubUser')->get()->map(function ($contributor) {


  
24
            return $contributor->githubUser;


  
25
        });


  
26


      


  
27
        $master_branch = $repository->master_branch;


  
28
        $default_assignee = GithubConfig::USERID;


  
29


      


  
30
        return response()->json([


  
31
            'branches' => $branchNames,


  
32
            'assignees' => $assignees,


  
33
            'default_assignee' => $default_assignee,


  
34
            'master_branch' => $master_branch,


  
35
        ]);


  
36
    }


  
37


      


  
38
    public function create($organizationName, $repositoryName)


  
39
    {


  
40
        [$organization, $repository] = RepositoryService::getRepositoryWithOrganization($organizationName, $repositoryName);


  
41


      


  
42
        $response = \GrahamCampbell\GitHub\Facades\Github::pullRequests()->create($organization->name, $repository->name, [


  
43
            'title' => request()->input('title'),


  
44
            'head' => request()->input('head_branch'),


  
45
            'base' => request()->input('base_branch'),


  
46
            'assignee' => request()->input('assignee'),


  
47
            'body' => request()->input('body', ''),


  
48
            'draft' => true,


  
49
        ]);


  
50


      


  
51
        // Ensure we have a proper structure to work with


  
52
        if (!is_array($response) || !isset($response['id'])) {


  
53
            return response()->json(['message' => 'Failed to create PR on GitHub'], 500);


  
54
        }


  
55


      


  
56
        // Create/update the user who opened the pull request


  
57
        if (isset($response['user']) && is_array($response['user'])) {


  
58
            GithubUser::updateFromWebhook((object) $response['user']);


  
59
        }


  
60


      


  
61
        $state = $response['state'] ?? 'open';


  
62
        if (($state === 'closed') && !empty($response['merged'])) {


  
63
            $state = 'merged';


  
64
        }


  
65


      


  
66
        // Determine merge base sha for accurate diffing


  
67
        $mergeBaseSha = null;


  
68
        $headSha = $response['head']['sha'] ?? null;


  
69
        $baseRef = $response['base']['ref'] ?? null;


  
70
        $headRef = $response['head']['ref'] ?? null;


  
71


      


  
72
        if ($headSha && $baseRef && $headRef) {


  
73
            $compareData = ApiHelper::githubApi("/repos/{$organization->name}/{$repository->name}/compare/{$baseRef}...{$headRef}");


  
74
            if ($compareData && isset($compareData->merge_base_commit->sha)) {


  
75
                $mergeBaseSha = $compareData->merge_base_commit->sha;


  
76
            }


  
77
        }


  
78


      


  
79
        // Persist base fields in items table


  
80
        $pr = PullRequest::updateOrCreate(


  
81
            ['id' => $response['id']],


  
82
            [


  
83
                'repository_id' => $repository->id,


  
84
                'number' => $response['number'] ?? null,


  
85
                'title' => $response['title'] ?? '',


  
86
                'body' => $response['body'] ?? '',


  
87
                'state' => $state,


  
88
                'labels' => json_encode($response['labels'] ?? []),


  
89
                'opened_by_id' => $response['user']['id'] ?? null,


  
90
            ]


  
91
        );


  
92


      


  
93
        // Persist PR-specific fields in pull_requests table


  
94
        DB::table('pull_requests')->updateOrInsert(


  
95
            ['id' => $response['id']],


  
96
            [


  
97
                'head_branch' => $headRef,


  
98
                'head_sha' => $headSha,


  
99
                'base_branch' => $baseRef,


  
100
                'merge_base_sha' => $mergeBaseSha,


  
101
                'updated_at' => now(),


  
102
            ]


  
103
        );


  
104


      


  
105
        // Sync assignees (uses issue_assignees table)


  
106
        $assigneeGithubIds = [];


  
107
        if (!empty($response['assignees']) && is_array($response['assignees'])) {


  
108
            foreach ($response['assignees'] as $assignee) {


  
109
                if (is_array($assignee) && isset($assignee['id'])) {


  
110
                    $assigneeGithubIds[] = $assignee['id'];


  
111
                    GithubUser::updateFromWebhook((object) $assignee);


  
112
                }


  
113
            }


  
114
        } elseif (!empty($response['assignee']) && is_array($response['assignee']) && isset($response['assignee']['id'])) {


  
115
            // GitHub may return a single assignee


  
116
            $assigneeGithubIds[] = $response['assignee']['id'];


  
117
            GithubUser::updateFromWebhook((object) $response['assignee']);


  
118
        }


  
119
        if ($pr) {


  
120
            $pr->assignees()->sync($assigneeGithubIds);


  
121
        }


  
122


      


  
123
        return response()->json([


  
124
            'number' => $response['number'] ?? null,


  
125
            'state' => $state,


  
126
        ]);


  
127
    }


  
128
}