Added GitHub webhook functionality and configuration for API interaction

This commit introduces functionality for GitHub webhook interaction and API calls. The git operations are handled by a custom GitHub client in PHP, details for API endpoints are outlined in a new OpenAPI schema, and the project setup includes PHP FPM and NGINX configuration using Docker. A webhook receiver is also added to process incoming webhook payloads.
This commit is contained in:
stephan.kasdorf
2024-05-29 15:32:08 +02:00
commit 40139d144b
8 changed files with 482 additions and 0 deletions

5
.env Normal file
View File

@@ -0,0 +1,5 @@
COMPOSE_PROJECT_NAME=nibiru-framework-api
VIRTUAL_HOST=agent.api.nibiru-framework.com
VIRTUAL_PORT=80
PROXY_NETWORK=nginx-proxy
GITHUB_TOKEN=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

29
docker-compose.yml Normal file
View File

@@ -0,0 +1,29 @@
version: '3.8'
services:
php-fpm:
build:
context: ./php-fpm
volumes:
- ./src:/var/www/html
networks:
- nginx-proxy
restart: always
nginx:
image: nginx:latest
environment:
- VIRTUAL_HOST=${VIRTUAL_HOST}
- VIRTUAL_PORT=${VIRTUAL_PORT}
volumes:
- ./src:/var/www/html
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php-fpm
networks:
- nginx-proxy
restart: always
networks:
nginx-proxy:
external: true

302
gpt-schema.yml Normal file
View File

@@ -0,0 +1,302 @@
openapi: 3.0.0
info:
title: UpdateGPTOnPush Webhook
description: Webhook to update GPT on push events from a GitHub repository.
version: 1.0.0
servers:
- url: https://api.github.com
description: GitHub API Server
paths:
/repos/{owner}/{repo}/contents/{path}:
get:
operationId: getRepositoryContent
summary: Get the contents of a repository
description: Fetch the contents of a file or directory in a repository.
parameters:
- name: owner
in: path
required: true
schema:
type: string
description: The owner of the repository.
- name: repo
in: path
required: true
schema:
type: string
description: The name of the repository.
- name: path
in: path
required: true
schema:
type: string
description: The content path.
- name: ref
in: query
schema:
type: string
description: The name of the commit/branch/tag. Default is the repositorys default branch (usually master).
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: object
properties:
type:
type: string
description: Type of content (file, directory, symlink, submodule).
encoding:
type: string
description: Encoding of the content (if file).
size:
type: integer
description: Size of the content (if file).
name:
type: string
description: Name of the content.
path:
type: string
description: Path of the content.
content:
type: string
description: Base64 encoded content (if file).
sha:
type: string
description: SHA identifier of the content.
url:
type: string
description: URL to access the content.
git_url:
type: string
description: Git URL to access the content.
html_url:
type: string
description: HTML URL to access the content.
download_url:
type: string
description: Download URL to access the content.
_links:
type: object
properties:
self:
type: string
description: Self link.
git:
type: string
description: Git link.
html:
type: string
description: HTML link.
'404':
description: Content not found
/repos/{owner}/{repo}/commits:
get:
operationId: listCommits
summary: List commits in a repository
description: Retrieve a list of commits in a repository.
parameters:
- name: owner
in: path
required: true
schema:
type: string
description: The owner of the repository.
- name: repo
in: path
required: true
schema:
type: string
description: The name of the repository.
- name: sha
in: query
schema:
type: string
description: SHA or branch to start listing commits from.
- name: path
in: query
schema:
type: string
description: Only commits containing this file path will be returned.
- name: author
in: query
schema:
type: string
description: GitHub username or email of the author.
- name: since
in: query
schema:
type: string
format: date-time
description: Only commits after this date will be returned.
- name: until
in: query
schema:
type: string
format: date-time
description: Only commits before this date will be returned.
- name: per_page
in: query
schema:
type: integer
default: 30
description: Number of results per page (max 100).
- name: page
in: query
schema:
type: integer
default: 1
description: Page number of the results to fetch.
responses:
'200':
description: Successful response
content:
application/json:
schema:
type: array
items:
type: object
properties:
sha:
type: string
description: SHA of the commit.
node_id:
type: string
description: Node ID of the commit.
commit:
type: object
properties:
author:
type: object
properties:
name:
type: string
email:
type: string
date:
type: string
format: date-time
committer:
type: object
properties:
name:
type: string
email:
type: string
date:
type: string
format: date-time
message:
type: string
tree:
type: object
properties:
sha:
type: string
url:
type: string
url:
type: string
comment_count:
type: integer
url:
type: string
html_url:
type: string
comments_url:
type: string
author:
type: object
properties:
login:
type: string
id:
type: integer
node_id:
type: string
avatar_url:
type: string
gravatar_id:
type: string
url:
type: string
html_url:
type: string
followers_url:
type: string
following_url:
type: string
gists_url:
type: string
starred_url:
type: string
subscriptions_url:
type: string
organizations_url:
type: string
repos_url:
type: string
events_url:
type: string
received_events_url:
type: string
type:
type: string
site_admin:
type: boolean
committer:
type: object
properties:
login:
type: string
id:
type: integer
node_id:
type: string
avatar_url:
type: string
gravatar_id:
type: string
url:
type: string
html_url:
type: string
followers_url:
type: string
following_url:
type: string
gists_url:
type: string
starred_url:
type: string
subscriptions_url:
type: string
organizations_url:
type: string
repos_url:
type: string
events_url:
type: string
received_events_url:
type: string
type:
type: string
site_admin:
type: boolean
parents:
type: array
items:
type: object
properties:
sha:
type: string
url:
type: string
html_url:
type: string
'404':
description: Repository not found
components:
schemas: {}

36
nginx/nginx.conf Normal file
View File

@@ -0,0 +1,36 @@
server {
listen 80;
server_name ${VIRTUAL_HOST};
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss;
location / {
proxy_read_timeout 7200;
proxy_connect_timeout 7200;
if (!-e $request_filename){
rewrite ^(.*)$ / break;
}
root /usr/share/nginx/html;
index index.php;
}
location ~ \.php$ {
root /var/www/html;
fastcgi_pass php-fpm:9000;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include fastcgi_params;
fastcgi_buffers 16 32k;
fastcgi_buffer_size 64k;
fastcgi_busy_buffers_size 64k;
fastcgi_read_timeout 900;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location ~ /\.ht {
deny all;
}
}

21
php-fpm/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
# Use the official PHP-FPM image for PHP 8.3
FROM php:8.3-fpm
# Set the working directory
WORKDIR /var/www/html
# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Install system dependencies
RUN apt-get update && apt-get install -y \
zip \
unzip \
git \
&& apt-get clean
# Expose port 9000 for PHP-FPM
EXPOSE 9000
# Start PHP-FPM
CMD ["php-fpm"]

39
src/GitHubClient.php Normal file
View File

@@ -0,0 +1,39 @@
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
class GitHubClient
{
private $client;
private $token;
public function __construct($token)
{
$this->client = new Client([
'base_uri' => 'https://api.github.com/',
'headers' => [
'Authorization' => "token $token",
'Accept' => 'application/vnd.github.v3+json',
],
]);
$this->token = $token;
}
public function getRepositoryContent($owner, $repo, $path, $ref = 'main')
{
$response = $this->client->get("repos/$owner/$repo/contents/$path", [
'query' => ['ref' => $ref]
]);
return json_decode($response->getBody(), true);
}
public function listCommits($owner, $repo, $params = [])
{
$response = $this->client->get("repos/$owner/$repo/commits", [
'query' => $params
]);
return json_decode($response->getBody(), true);
}
}

29
src/composer.json Normal file
View File

@@ -0,0 +1,29 @@
{
"name": "vendor_name/nibiru-framework-agent",
"description": "A project to interact with GitHub API using PHP",
"authors": [
{
"name": "Stephan Kasdorf",
"email": "stephan.kasdorf@bittomine.com"
}
],
"require": {
"php": "^8.3",
"guzzlehttp/guzzle": "^7.3"
},
"autoload": {
"psr-4": {
"": "src/"
}
},
"scripts": {
"post-install-cmd": [
"chmod -R 777 storage"
]
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
}
}

21
src/webhookReceiver.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
require 'GitHubClient.php';
$token = getenv('GITHUB_TOKEN');
$client = new GitHubClient($token);
// Get the webhook payload
$payload = file_get_contents('php://input');
$data = json_decode($payload, true);
if (isset($data['commits'])) {
foreach ($data['commits'] as $commit) {
// Process each commit
echo "Commit message: " . $commit['message'] . "\n";
}
}
// Respond to GitHub
http_response_code(200);
echo json_encode(['status' => 'Webhook received']);