github webhooks
This commit is contained in:
parent
19ad184cd6
commit
76bf601e1b
@ -72,7 +72,7 @@ public function loadRepositories($github_app_id)
|
||||
$this->repositories = collect();
|
||||
$this->page = 1;
|
||||
$this->github_app = GithubApp::where('id', $github_app_id)->first();
|
||||
$this->token = generate_github_token($this->github_app);
|
||||
$this->token = generate_github_installation_token($this->github_app);
|
||||
$this->loadRepositoryByPage();
|
||||
if ($this->repositories->count() < $this->total_repositories_count) {
|
||||
while ($this->repositories->count() < $this->total_repositories_count) {
|
||||
@ -123,6 +123,7 @@ public function submit()
|
||||
}
|
||||
$application = Application::create([
|
||||
'name' => "{$this->selected_repository_owner}/{$this->selected_repository_repo}:{$this->selected_branch_name}",
|
||||
'project_id' => $this->selected_repository_id,
|
||||
'git_repository' => "{$this->selected_repository_owner}/{$this->selected_repository_repo}",
|
||||
'git_branch' => $this->selected_branch_name,
|
||||
'build_pack' => 'nixpacks',
|
||||
|
@ -469,7 +469,7 @@ private function gitImport()
|
||||
$this->execute_in_builder($git_clone_command)
|
||||
];
|
||||
} else {
|
||||
$github_access_token = generate_github_token($this->source);
|
||||
$github_access_token = generate_github_installation_token($this->source);
|
||||
return [
|
||||
$this->execute_in_builder("git clone -q -b {$this->application->git_branch} $source_html_url_scheme://x-access-token:$github_access_token@$source_html_url_host/{$this->application->git_repository}.git {$this->workdir}")
|
||||
];
|
||||
|
@ -24,6 +24,7 @@ protected static function booted()
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'project_id',
|
||||
'description',
|
||||
'git_repository',
|
||||
'git_branch',
|
||||
|
@ -12,7 +12,10 @@ protected static function boot()
|
||||
parent::boot();
|
||||
|
||||
static::creating(function (Model $model) {
|
||||
$model->uuid = (string) new Cuid2(7);
|
||||
// Generate a UUID if one isn't set
|
||||
if (!$model->uuid) {
|
||||
$model->uuid = (string) new Cuid2(7);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
class GithubApp extends BaseModel
|
||||
{
|
||||
protected $fillable = ['name', 'organization', 'api_url', 'html_url', 'custom_user', 'custom_port', 'team_id'];
|
||||
protected $fillable = ['name', 'uuid', 'organization', 'api_url', 'html_url', 'custom_user', 'custom_port', 'team_id'];
|
||||
protected $casts = [
|
||||
'is_public' => 'boolean',
|
||||
];
|
||||
|
14
app/Models/GithubEventsApplications.php
Normal file
14
app/Models/GithubEventsApplications.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class GithubEventsApplications extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'delivery_guid',
|
||||
'application_id',
|
||||
];
|
||||
}
|
@ -189,8 +189,8 @@ function generateRandomName()
|
||||
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
||||
use Lcobucci\JWT\Token\Builder;
|
||||
|
||||
if (!function_exists('generate_github_token')) {
|
||||
function generate_github_token(GithubApp $source)
|
||||
if (!function_exists('generate_github_installation_token')) {
|
||||
function generate_github_installation_token(GithubApp $source)
|
||||
{
|
||||
$signingKey = InMemory::plainText($source->privateKey->private_key);
|
||||
$algorithm = new Sha256();
|
||||
@ -213,6 +213,23 @@ function generate_github_token(GithubApp $source)
|
||||
return $token->json()['token'];
|
||||
}
|
||||
}
|
||||
if (!function_exists('generate_github_jwt_token')) {
|
||||
function generate_github_jwt_token(GithubApp $source)
|
||||
{
|
||||
$signingKey = InMemory::plainText($source->privateKey->private_key);
|
||||
$algorithm = new Sha256();
|
||||
$tokenBuilder = (new Builder(new JoseEncoder(), ChainedFormatter::default()));
|
||||
$now = new DateTimeImmutable();
|
||||
$now = $now->setTime($now->format('H'), $now->format('i'));
|
||||
$issuedToken = $tokenBuilder
|
||||
->issuedBy($source->app_id)
|
||||
->issuedAt($now->modify('-1 minute'))
|
||||
->expiresAt($now->modify('+10 minutes'))
|
||||
->getToken($algorithm, $signingKey)
|
||||
->toString();
|
||||
return $issuedToken;
|
||||
}
|
||||
}
|
||||
if (!function_exists('getParameters')) {
|
||||
function getParameters()
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ public function up(): void
|
||||
{
|
||||
Schema::create('applications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('project_id')->nullable();
|
||||
$table->string('uuid')->unique();
|
||||
$table->string('name');
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('github_events_applications', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('delivery_guid');
|
||||
$table->foreignId('application_id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('github_events_applications');
|
||||
}
|
||||
};
|
@ -25,6 +25,7 @@ public function run(): void
|
||||
|
||||
Application::create([
|
||||
'name' => 'coollabsio/coolify-examples:nodejs-fastify',
|
||||
'project_id' => 603035348,
|
||||
'git_repository' => 'coollabsio/coolify-examples',
|
||||
'git_branch' => 'nodejs-fastify',
|
||||
'build_pack' => 'nixpacks',
|
||||
|
@ -26,7 +26,8 @@ public function run(): void
|
||||
'team_id' => $root_team->id,
|
||||
]);
|
||||
GithubApp::create([
|
||||
'name' => 'coolify-laravel-development-private-github',
|
||||
'name' => 'coolify-laravel-development-public',
|
||||
'uuid' => '69420',
|
||||
'api_url' => 'https://api.github.com',
|
||||
'html_url' => 'https://github.com',
|
||||
'is_public' => false,
|
||||
|
@ -1,5 +1,5 @@
|
||||
<x-layout>
|
||||
<div>v{{ config('coolify.version') }}</div>
|
||||
<div>v{{ config('version') }}</div>
|
||||
<a href="/login">Login</a>
|
||||
@if ($is_registration_enabled)
|
||||
<a href="/register">Register</a>
|
||||
|
@ -18,13 +18,6 @@
|
||||
Route::get('/health', function () {
|
||||
return 'OK';
|
||||
});
|
||||
Route::get('/webhooks/source/github/redirect', function () {
|
||||
$code = request()->get('code');
|
||||
$state = request()->get('state');
|
||||
$github_app = GithubApp::where('uuid', $state)->firstOrFail();
|
||||
return 'OK';
|
||||
});
|
||||
|
||||
// Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
|
||||
// return $request->user();
|
||||
// });
|
||||
|
@ -38,7 +38,6 @@
|
||||
})->flatten();
|
||||
$private_keys = PrivateKey::where('team_id', $id)->get();
|
||||
$github_apps = GithubApp::private();
|
||||
|
||||
return view('dashboard', [
|
||||
'servers' => $servers->sortBy('name'),
|
||||
'projects' => $projects->sortBy('name'),
|
||||
@ -86,7 +85,7 @@
|
||||
Route::get('/source/new', fn () => view('source.new'))->name('source.new');
|
||||
Route::get('/source/github/{github_app_uuid}', function (Request $request) {
|
||||
$github_app = GithubApp::where('uuid', request()->github_app_uuid)->first();
|
||||
$name = Str::kebab('coolify' . $github_app->name);
|
||||
$name = Str::of(Str::kebab($github_app->name))->start('coolify-');
|
||||
$settings = InstanceSettings::first();
|
||||
$host = $request->schemeAndHttpHost();
|
||||
if ($settings->fqdn) {
|
||||
|
@ -1,9 +1,14 @@
|
||||
<?php
|
||||
|
||||
use App\Jobs\DeployApplicationJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\PrivateKey;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\GithubEventsApplications;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Str;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
Route::get('/source/github/redirect', function () {
|
||||
try {
|
||||
@ -50,3 +55,58 @@
|
||||
return generalErrorHandler($e);
|
||||
}
|
||||
});
|
||||
Route::post('/source/github/events', function () {
|
||||
try {
|
||||
$x_github_delivery = request()->header('X-GitHub-Delivery');
|
||||
$x_github_event = Str::lower(request()->header('X-GitHub-Event'));
|
||||
$x_github_hook_installation_target_id = request()->header('X-GitHub-Hook-Installation-Target-Id');
|
||||
$x_hub_signature_256 = request()->header('X-Hub-Signature-256');
|
||||
$payload = request()->collect();
|
||||
if ($x_github_event === 'ping') {
|
||||
// Just pong
|
||||
return response('pong');
|
||||
}
|
||||
if ($x_github_event === 'installation') {
|
||||
// Installation handled by setup redirect url. Repositories queried on-demand.
|
||||
return response('cool');
|
||||
}
|
||||
$github_app = GithubApp::where('app_id', $x_github_hook_installation_target_id)->firstOrFail();
|
||||
// TODO: Verify signature
|
||||
// $webhook_secret = data_get($github_app, 'webhook_secret');
|
||||
// $key = hash('sha256', $webhook_secret, true);
|
||||
// $hmac = hash_hmac('sha256', request()->getContent(), $key);
|
||||
// if (!hash_equals($hmac, $x_hub_signature_256)) {
|
||||
// return response('not cool');
|
||||
// }
|
||||
|
||||
if ($x_github_event === 'push') {
|
||||
$id = data_get($payload, 'repository.id');
|
||||
$branch = data_get($payload, 'ref');
|
||||
if (Str::isMatch('/refs\/heads\/*/', $branch)) {
|
||||
$branch = Str::after($branch, 'refs/heads/');
|
||||
}
|
||||
}
|
||||
if ($x_github_event === 'pull_request') {
|
||||
$id = data_get($payload, 'pull_request.base.repo.id');
|
||||
$branch = data_get($payload, 'pull_request.base.ref');
|
||||
}
|
||||
if (!$id || !$branch) {
|
||||
return response('not cool');
|
||||
}
|
||||
$applications = Application::where('project_id', $id)->where('git_branch', $branch)->get();
|
||||
foreach ($applications as $application) {
|
||||
GithubEventsApplications::create([
|
||||
"delivery_guid" => $x_github_delivery,
|
||||
"application_id" => $application->id
|
||||
]);
|
||||
$deployment_uuid = new Cuid2(7);
|
||||
dispatch(new DeployApplicationJob(
|
||||
deployment_uuid: $deployment_uuid,
|
||||
application_uuid: $application->uuid,
|
||||
force_rebuild: false,
|
||||
));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return generalErrorHandler($e);
|
||||
}
|
||||
});
|
||||
|
@ -1 +1,17 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"_id": "e6458286-eef1-401c-be84-860b111d66f0",
|
||||
"colName": "Webhooks",
|
||||
"created": "2023-05-09T11:45:36.504Z",
|
||||
"sortNum": 10000,
|
||||
"folders": [
|
||||
{
|
||||
"_id": "b8cfd093-5467-44a2-9221-ad0207717310",
|
||||
"name": "GitHub",
|
||||
"containerId": "",
|
||||
"created": "2023-05-09T11:45:40.630Z",
|
||||
"sortNum": 10000
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@ -1 +1,13 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"_id": "bd3f3c2e-b161-40c9-9077-efcf40dfe1f4",
|
||||
"name": "(Local Env)",
|
||||
"default": false,
|
||||
"global": true,
|
||||
"local": true,
|
||||
"sortNum": -1,
|
||||
"created": "2023-05-09T11:48:22.144Z",
|
||||
"modified": "2023-05-09T11:48:22.144Z",
|
||||
"data": []
|
||||
}
|
||||
]
|
@ -1 +1,50 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"_id": "b3d379ab-e5e4-4ba4-991d-b6c8c6bbcb98",
|
||||
"colId": "e6458286-eef1-401c-be84-860b111d66f0",
|
||||
"containerId": "b8cfd093-5467-44a2-9221-ad0207717310",
|
||||
"name": "Push",
|
||||
"url": "http://localhost:8000/webhooks/source/github/events",
|
||||
"method": "POST",
|
||||
"sortNum": 10000,
|
||||
"created": "2023-05-09T11:45:50.227Z",
|
||||
"modified": "2023-05-09T12:22:27.192Z",
|
||||
"headers": [
|
||||
{
|
||||
"name": "X-GitHub-Delivery",
|
||||
"value": "9b4bc300-ee63-11ed-9133-5f71dd83487d"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Event",
|
||||
"value": "push"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-ID",
|
||||
"value": "400873078"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-ID",
|
||||
"value": "292941"
|
||||
},
|
||||
{
|
||||
"name": "X-GitHub-Hook-Installation-Target-Type",
|
||||
"value": "integration"
|
||||
},
|
||||
{
|
||||
"name": "X-Hub-Signature-256",
|
||||
"value": "sha256=d5c8d05cc6de14422ab3661d37ec4b98e71f4fdd63d1116f5dedfcb0213ee03d"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"params": [],
|
||||
"body": {
|
||||
"type": "json",
|
||||
"raw": "{\n \"ref\": \"{{repository_ref}}\",\n \"repository\": {\n \"id\": \"{{repository_id}}\",\n \"full_name\": \"{{repository_name}}\"\n }\n}",
|
||||
"form": []
|
||||
},
|
||||
"tests": []
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue
Block a user