Compare commits

..
4 Commits
Author SHA1 Message Date
Lyncoln 9e937d7686 Changed log level of self.address_string
Build and Publish RMManager Image / build (push) Successful in 56s
2026-10-31 09:11:39 -04:00
Lyncoln 75b4cc92da Repaired build workflow
Build and Publish RMManager Image / build (push) Successful in 46s
2026-10-30 23:41:42 -04:00
Lyncoln f90c3b1424 Added gitea workflow build
Build and Publish RMManager Image / build (push) Failing after 1m31s
2026-10-30 23:37:45 -04:00
Lyncoln 12b28f037a Updated Server to used buildListener for pings and updated the listener and firewall to handle definitions accordingly 2026-10-30 22:50:36 -04:00
6 changed files with 346 additions and 120 deletions
+182
View File
@@ -0,0 +1,182 @@
name: Build and Publish RMManager Image
on:
push:
branches: [main]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
# ---------------------------------------------
# Checkout repository (no external actions)
# ---------------------------------------------
- name: Checkout repository
env:
GITEA_TOKEN: ${{ secrets.TEA_TOKEN }}
run: |
set -euo pipefail
BASE="${GITHUB_SERVER_URL%/}"
REPO="${GITHUB_REPOSITORY}"
git init .
git remote add origin "$BASE/$REPO.git"
if [ -n "${GITEA_TOKEN:-}" ]; then
AUTH="$(printf 'oauth2:%s' "$GITEA_TOKEN" | base64 -w0)"
git -c "http.extraHeader=Authorization: Basic $AUTH" \
fetch --depth 1 origin "$GITHUB_SHA"
else
git fetch --depth 1 origin "$GITHUB_SHA"
fi
git checkout --detach FETCH_HEAD
git config --global --add safe.directory "$PWD"
# ---------------------------------------------
# Determine image version and commit SHA
# ---------------------------------------------
- name: Determine version
id: version
run: |
set -euo pipefail
SHORT_SHA="$(git rev-parse --short=7 HEAD)"
echo "sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
if [ -f VERSION ]; then
VERSION="$(tr -d '[:space:]' < VERSION)"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
else
echo "version=" >> "$GITHUB_OUTPUT"
fi
# ---------------------------------------------
# Login to Gitea container registry
# ---------------------------------------------
- name: Docker login
env:
REGISTRY: ${{ vars.REGISTRY }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_TOKEN: ${{ secrets.TEA_TOKEN }}
run: |
set -euo pipefail
echo "$REGISTRY_TOKEN" | docker login "$REGISTRY" \
-u "$REGISTRY_USER" \
--password-stdin
# ---------------------------------------------
# Build and export container image
# ---------------------------------------------
- name: Build RMManager image
env:
REGISTRY: ${{ vars.REGISTRY }}
VERSION: ${{ steps.version.outputs.version }}
SHORT_SHA: ${{ steps.version.outputs.sha }}
run: |
set -euo pipefail
FULL_IMAGE="$REGISTRY/david/rmmanager"
docker build \
-f Containerfile \
-t "$FULL_IMAGE:latest" \
-t "$FULL_IMAGE:sha-$SHORT_SHA" \
--output "type=docker,dest=$RUNNER_TEMP/rmmanager-built.tar" \
.
# ---------------------------------------------
# Load exported image into Docker
# ---------------------------------------------
- name: Load RMManager image
run: |
set -euo pipefail
docker load \
--input "$RUNNER_TEMP/rmmanager-built.tar"
# ---------------------------------------------
# Add optional version tag
# ---------------------------------------------
- name: Tag RMManager image
env:
REGISTRY: ${{ vars.REGISTRY }}
VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
FULL_IMAGE="$REGISTRY/david/rmmanager"
if [ -n "$VERSION" ]; then
docker tag \
"$FULL_IMAGE:latest" \
"$FULL_IMAGE:v$VERSION"
fi
# ---------------------------------------------
# Verify local image and tags
# ---------------------------------------------
- name: Verify RMManager image
env:
REGISTRY: ${{ vars.REGISTRY }}
VERSION: ${{ steps.version.outputs.version }}
SHORT_SHA: ${{ steps.version.outputs.sha }}
run: |
set -euo pipefail
FULL_IMAGE="$REGISTRY/david/rmmanager"
docker version
docker image ls
docker image inspect "$FULL_IMAGE:latest"
docker image inspect "$FULL_IMAGE:sha-$SHORT_SHA"
if [ -n "$VERSION" ]; then
docker image inspect "$FULL_IMAGE:v$VERSION"
fi
# ---------------------------------------------
# Publish image to Gitea registry
# ---------------------------------------------
- name: Push RMManager image
env:
REGISTRY: ${{ vars.REGISTRY }}
VERSION: ${{ steps.version.outputs.version }}
SHORT_SHA: ${{ steps.version.outputs.sha }}
run: |
set -euo pipefail
FULL_IMAGE="$REGISTRY/david/rmmanager"
docker push "$FULL_IMAGE:latest"
docker push "$FULL_IMAGE:sha-$SHORT_SHA"
if [ -n "$VERSION" ]; then
docker push "$FULL_IMAGE:v$VERSION"
fi
# ---------------------------------------------
# Report successful build
# ---------------------------------------------
- name: Report build
env:
REGISTRY: ${{ vars.REGISTRY }}
VERSION: ${{ steps.version.outputs.version }}
SHORT_SHA: ${{ steps.version.outputs.sha }}
run: |
set -euo pipefail
echo "RMManager build and publish completed"
echo "Image: $REGISTRY/david/rmmanager"
echo "Latest tag: latest"
echo "Commit tag: sha-$SHORT_SHA"
if [ -n "$VERSION" ]; then
echo "Version tag: v$VERSION"
fi
+22 -21
View File
@@ -6,33 +6,34 @@ from core.runtime.resolver import resolveItem
def buildFirewall(listener, outputs): def buildFirewall(listener, outputs):
#firewall_log = os.environ.get("LOGS_FIREWALL", "false").lower() == "true" if hasattr(listener, "filters"):
firewall_log = True #firewall_log = os.environ.get("LOGS_FIREWALL", "false").lower() == "true"
firewall_log = True
status_code = 200 status_code = 200
outputs["firewall_allowed"] = [] outputs["firewall_allowed"] = []
for item in outputs[listener.recursive["source"]]: for item in outputs[listener.recursive["source"]]:
resolved = resolveItem(listener, item) resolved = resolveItem(listener, item)
match, filter = applyConditions(listener, resolved, outputs) match, filter = applyConditions(listener, resolved, outputs)
if match: if match:
status_code = filter.get("status_code", 200) status_code = filter.get("status_code", 200)
if filter.get("execute", False): if filter.get("execute", False):
from core.execution.createthread import buildThread from core.execution.createthread import buildThread
thread = buildThread(filter["execute"]) thread = buildThread(filter["execute"])
if firewall_log: if firewall_log:
logging.info(filter.get("print")) logging.info(filter.get("print"))
logging.info(f"Returning status_code: {status_code}") logging.info(f"Returning status_code: {status_code}")
continue continue
outputs["firewall_allowed"].append(item) outputs["firewall_allowed"].append(item)
if outputs["firewall_allowed"] != []: if outputs["firewall_allowed"] != []:
return True, status_code return True, status_code
#Needs to be present to prevent TypeError #Needs to be present to prevent TypeError
return False, status_code return False, status_code
+29 -15
View File
@@ -4,34 +4,48 @@ import logging
from core.runtime.outputs import buildOutput from core.runtime.outputs import buildOutput
from core.runtime.firewall import buildFirewall from core.runtime.firewall import buildFirewall
from core.runtime.createruntime import outputs from core.runtime.createruntime import outputs
from core.execution.processregistry import processes
def buildListener(listener, self): def buildListener(listener, self):
if self.path.startswith(listener.acceptpath): if self.path.startswith(listener.acceptpath):
if hasattr(listener, "print"):
#Prints can used buildlog for listener runtime logging.info(listener.print)
logging.info("Matrix transaction received")
content_length = int(self.headers["Content-Length"]) content_length = int(self.headers["Content-Length"])
data = self.rfile.read(content_length) bytes = self.rfile.read(content_length)
request = json.loads(data)
#outputs = {} #request = json.loads(data)
buildOutput(data, listener, outputs) buildOutput(bytes, listener, outputs)
allow, status_code = buildFirewall(listener, outputs) if hasattr(listener, "filters"):
allow, status_code = buildFirewall(listener, outputs)
if allow: if allow:
#from core.execution.createthread import buildThread logging.info(outputs["firewall_allowed"])
from core.execution.executioncontract import executeContract
logging.info(outputs["firewall_allowed"]) if hasattr(listener, "execute"):
if listener.execute["engine"] == "thread":
from core.execution.createthread import buildThread
buildThread(listener.execute["module"])
#thread = buildThread(listener.execute) elif listener.execute["engine"] == "contract":
executeContract(listener.execute) from core.execution.executioncontract import executeContract
executeContract(listener.execute["module"])
else:
if hasattr(listener, "execute"):
if listener.execute["engine"] == "thread":
from core.execution.createthread import buildThread
buildThread(listener.execute["module"])
elif listener.execute["engine"] == "contract":
from core.execution.executioncontract import executeContract
executeContract(listener.execute["module"])
status_code = listener.status_code["success"]
self.send_response(status_code) self.send_response(status_code)
self.send_header("Content-Type", "application/json") self.send_header("Content-Type", "application/json")
@@ -42,4 +56,4 @@ def buildListener(listener, self):
else: else:
self.send_error(404) self.send_error(404)
return outputs return
+89 -80
View File
@@ -4,119 +4,128 @@ import logging
from http.server import HTTPServer, BaseHTTPRequestHandler from http.server import HTTPServer, BaseHTTPRequestHandler
from .dispatcher import dispatchRequest
from .createresponse import buildResponse #from .dispatcher import dispatchRequest
from plugins.rmass.listeners import synapselistener #from .createresponse import buildResponse
from plugins.rmass.listeners import synapselistener, matrixpinglistener
from core.server.createlistener import buildListener from core.server.createlistener import buildListener
from plugins.rmass.actions import synapsesetbridgeonline #from plugins.rmass.actions import synapsesetbridgeonline
port = int(os.environ.get("SERVER_PORT", 19001)) port = int(os.environ.get("SERVER_PORT", 19001))
class RequestHandler(BaseHTTPRequestHandler): class RequestHandler(BaseHTTPRequestHandler):
def log_message(self, format, *args):
logging.info(
"%s - %s",
self.address_string(),
format % args
)
def do_POST(self): def do_POST(self):
if self.path == "/_matrix/app/v1/ping": logging.debug("POST request received")
from core.execution.createthread import buildThread buildListener(matrixpinglistener, self)
thread = buildThread(synapsesetbridgeonline)
self.send_response(200) # if self.path == "/_matrix/app/v1/ping":
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", "2")
self.end_headers()
self.wfile.write(b"{}")
return
else: # from core.execution.createthread import buildThread
#lifecycles = {} # thread = buildThread(synapsesetbridgeonline)
print("POST request received")
max_request_size = 1024 # self.send_response(200)
# self.send_header("Content-Type", "application/json")
# self.send_header("Content-Length", "2")
# self.end_headers()
# self.wfile.write(b"{}")
# return
content_length = self.headers.get("Content-Length") # else:
# print("POST request received")
# Check whether Content-Length exists # max_request_size = 1024
if content_length is None:
response = {
"status": "error",
"message": "Content length required"
}
status = 411
else: # content_length = self.headers.get("Content-Length")
# Attempt to convert the header into an integer
try:
length = int(content_length)
except ValueError:
length = None
# Validate the converted length # # Check whether Content-Length exists
if length is None: # if content_length is None:
response = { # response = {
"status": "error", # "status": "error",
"message": "Invalid Content-Length" # "message": "Content length required"
} # }
status = 400 # status = 411
elif length < 0: # else:
response = { # # Attempt to convert the header into an integer
"status": "error", # try:
"message": "Bad Request" # length = int(content_length)
} # except ValueError:
status = 400 # length = None
elif length > max_request_size: # # Validate the converted length
response = { # if length is None:
"status": "error", # response = {
"message": "Content exceeds maximum request size" # "status": "error",
} # "message": "Invalid Content-Length"
status = 413 # }
# status = 400
else: # elif length < 0:
# Content-Length is valid, so read the body # response = {
data = self.rfile.read(length) # "status": "error",
# "message": "Bad Request"
# }
# status = 400
try: # elif length > max_request_size:
request = json.loads(data) # response = {
# "status": "error",
# "message": "Content exceeds maximum request size"
# }
# status = 413
except json.JSONDecodeError: # else:
response = { # # Content-Length is valid, so read the body
"status": "error", # data = self.rfile.read(length)
"message": "Invalid JSON received"
}
status = 400
else: # try:
# Only valid JSON reaches the dispatcher # request = json.loads(data)
thread, lifecycles, module, mode = dispatchRequest(
request, lifecycles
)
response = buildResponse(module, thread, mode) # except json.JSONDecodeError:
status = 200 # response = {
# "status": "error",
# "message": "Invalid JSON received"
# }
# status = 400
# Serialize the response # else:
responsebytes = json.dumps(response).encode("utf-8") # # Only valid JSON reaches the dispatcher
# thread, lifecycles, module, mode = dispatchRequest(
# request, lifecycles
# )
# Send one HTTP response # response = buildResponse(module, thread, mode)
self.send_response(status) # status = 200
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(responsebytes)))
self.end_headers()
self.wfile.write(responsebytes) # # Serialize the response
# responsebytes = json.dumps(response).encode("utf-8")
# # Send one HTTP response
# self.send_response(status)
# self.send_header("Content-Type", "application/json")
# self.send_header("Content-Length", str(len(responsebytes)))
# self.end_headers()
# self.wfile.write(responsebytes)
def do_PUT(self): def do_PUT(self):
#print("PUT request received") logging.debug("PUT request received")
outputs = buildListener(synapselistener, self) buildListener(synapselistener, self)
def startServer(): def startServer():
server = HTTPServer(("0.0.0.0", port), RequestHandler) server = HTTPServer(("0.0.0.0", port), RequestHandler)
logging.info(f"Server listening on port {port}") logging.info(f"Server listening on port {port}")
#outputs = {}
#outputs, response = buildAction(pingsynapse, outputs)
server.serve_forever() server.serve_forever()
@@ -0,0 +1,16 @@
from plugins.rmass.actions import synapsesetbridgeonline
name = "Matrix Ping Listener"
kind = "listener"
acceptpath = "/_matrix/app/v1/ping"
execute = {
"module": synapsesetbridgeonline,
"engine": "thread",
}
status_code = {
"success": 200
}
+5 -1
View File
@@ -30,7 +30,10 @@ recursive = {
acceptpath = "/_matrix/app/v1/transactions/" acceptpath = "/_matrix/app/v1/transactions/"
execute = rmassmessagepush execute = {
"module": rmassmessagepush,
"engine": "contract",
}
filters = [ filters = [
{ {
@@ -74,3 +77,4 @@ filters = [
] ]
print = "Matrix transaction received"