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