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:
5
.env
Normal file
5
.env
Normal 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
29
docker-compose.yml
Normal 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
302
gpt-schema.yml
Normal 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 repository’s 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
36
nginx/nginx.conf
Normal 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
21
php-fpm/Dockerfile
Normal 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
39
src/GitHubClient.php
Normal 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
29
src/composer.json
Normal 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
21
src/webhookReceiver.php
Normal 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']);
|
||||||
Reference in New Issue
Block a user