Compare commits
2 Commits
fix/534-v2
...
test-failu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99aab6c530 | ||
|
|
9def37e208 |
84
.gitea/workflows/minimum-pr-gate.yml
Normal file
84
.gitea/workflows/minimum-pr-gate.yml
Normal file
@@ -0,0 +1,84 @@
|
||||
name: Minimum PR Gate
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
minimum-pr-gate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Determine changed files
|
||||
id: changes
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
CHANGED=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }})
|
||||
else
|
||||
CHANGED=$(git ls-files)
|
||||
fi
|
||||
echo "changed=${CHANGED}" >> $GITHUB_OUTPUT
|
||||
echo "Changed files:"
|
||||
echo "$CHANGED"
|
||||
|
||||
- name: Python syntax check
|
||||
if: steps.changes.outputs.changed != ''
|
||||
run: |
|
||||
CHANGED_FILES="${{ steps.changes.outputs.changed }}"
|
||||
PY_FILES=$(echo "$CHANGED_FILES" | grep '\.py$' || true)
|
||||
if [ -z "$PY_FILES" ]; then
|
||||
echo "No Python files changed."
|
||||
exit 0
|
||||
fi
|
||||
echo "Checking Python syntax on:"
|
||||
echo "$PY_FILES"
|
||||
echo "$PY_FILES" | while IFS= read -r f; do
|
||||
python3 -m py_compile "$f" || { echo "FAIL: syntax error in $f"; exit 1; }
|
||||
done
|
||||
echo "PASS: Python syntax"
|
||||
|
||||
- name: Secret scan
|
||||
if: steps.changes.outputs.changed != ''
|
||||
run: |
|
||||
CHANGED_FILES="${{ steps.changes.outputs.changed }}"
|
||||
SCAN_FILES=$(echo "$CHANGED_FILES" | grep -E '\.(py|yaml|yml|sh|json)$' || true)
|
||||
if [ -z "$SCAN_FILES" ]; then
|
||||
echo "No files to scan for secrets."
|
||||
exit 0
|
||||
fi
|
||||
echo "Scanning files for secrets:"
|
||||
echo "$SCAN_FILES"
|
||||
if echo "$SCAN_FILES" | xargs -r grep -E 'sk-or-|sk-ant-|ghp_|AKIA' 2>/dev/null | \
|
||||
grep -v '.gitea' | grep -v 'detect_secrets' | grep -v 'test_trajectory_sanitize' | grep -v 'test_secret_detection' | grep -q .; then
|
||||
echo "FAIL: Secrets or hardcoded tokens detected"
|
||||
exit 1
|
||||
fi
|
||||
echo "PASS: No secrets detected"
|
||||
|
||||
- name: Markdown sanity check
|
||||
if: steps.changes.outputs.changed != ''
|
||||
run: |
|
||||
CHANGED_FILES="${{ steps.changes.outputs.changed }}"
|
||||
MD_FILES=$(echo "$CHANGED_FILES" | grep '\.md$' || true)
|
||||
if [ -z "$MD_FILES" ]; then
|
||||
echo "No markdown files changed."
|
||||
exit 0
|
||||
fi
|
||||
echo "Checking markdown sanity on:"
|
||||
echo "$MD_FILES"
|
||||
echo "$MD_FILES" | while IFS= read -r f; do
|
||||
if [ ! -s "$f" ]; then
|
||||
echo "FAIL: empty markdown file: $f"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -q '[^[:space:]]' "$f"; then
|
||||
echo "FAIL: markdown file contains only whitespace: $f"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
echo "PASS: Markdown sanity"
|
||||
13
README.md
13
README.md
@@ -99,6 +99,19 @@ python3 scripts/detect_secrets.py /tmp/test_secret.py
|
||||
# Should report: OpenAI API key detected
|
||||
```
|
||||
|
||||
|
||||
## CI / PR Gate
|
||||
|
||||
A lightweight minimum PR gate runs automatically on every pull request targeting `main`. The gate performs:
|
||||
|
||||
- **Python syntax**: All changed Python files must compile without errors.
|
||||
- **Secret scan**: Changed code files are scanned for common hardcoded tokens (OpenAI, Anthropic, GitHub, AWS keys).
|
||||
- **Markdown sanity**: Changed Markdown documentation files must be non‑empty and contain meaningful text.
|
||||
|
||||
The workflow is defined in `.gitea/workflows/minimum-pr-gate.yml`. It can also be triggered manually from the *Actions* panel (workflow_dispatch).
|
||||
|
||||
This gate protects the repository from introducing broken code, leaked credentials, or empty documentation.
|
||||
|
||||
## Development
|
||||
|
||||
### Running Tests
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
# Bezalel World Server Configuration
|
||||
|
||||
This directory contains the Evennia server configuration for Bezalel, the forge-and-testbed wizard house.
|
||||
|
||||
## Quick Start
|
||||
|
||||
To fix the Evennia settings on the Bezalel VPS (104.131.15.18):
|
||||
|
||||
```bash
|
||||
# SSH to Bezalel and run the fix script
|
||||
ssh root@104.131.15.18 'bash -s' < scripts/fix_evennia_settings.sh
|
||||
```
|
||||
|
||||
Or manually:
|
||||
|
||||
```bash
|
||||
cd /root/wizards/bezalel/evennia/bezalel_world/server/conf
|
||||
|
||||
# Copy the fixed settings
|
||||
cp ~/timmy-home/evennia/bezalel_world/server/conf/settings.py ./settings.py
|
||||
|
||||
# Clean and reinitialize DB
|
||||
cd /root/wizards/bezalel/evennia/bezalel_world
|
||||
rm -f server/evennia.db3
|
||||
/root/wizards/bezalel/evennia/venv/bin/evennia migrate
|
||||
|
||||
# Create superuser
|
||||
/root/wizards/bezalel/evennia/venv/bin/python3 -c "
|
||||
import sys, os
|
||||
sys.setrecursionlimit(5000)
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'server.conf.settings'
|
||||
import django
|
||||
django.setup()
|
||||
from evennia.accounts.accounts import AccountDB
|
||||
AccountDB.objects.create_superuser('Timmy', 'timmy@tower.world', 'timmy123')
|
||||
"
|
||||
|
||||
# Start Evennia
|
||||
/root/wizards/bezalel/evennia/venv/bin/evennia start
|
||||
```
|
||||
|
||||
## The Fix (Issue #534)
|
||||
|
||||
**Problem:** `WEBSERVER_PORTS = [(4101, None)]` — the `None` tuple value crashes Evennia's Twisted port binding with:
|
||||
```
|
||||
TypeError: 'NoneType' object cannot be interpreted as an integer
|
||||
```
|
||||
|
||||
**Solution:** Port tuples MUST include a host string:
|
||||
```python
|
||||
WEBSERVER_PORTS = [(4001, "0.0.0.0")]
|
||||
TELNET_PORTS = [(4000, "0.0.0.0")]
|
||||
WEBSOCKET_PORTS = [(4002, "0.0.0.0")]
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
After starting Evennia:
|
||||
|
||||
```bash
|
||||
evennia status # Should show Portal and Server running
|
||||
ss -tlnp | grep 4000 # Telnet port
|
||||
ss -tlnp | grep 4001 # Web port
|
||||
ss -tlnp | grep 4002 # WebSocket port
|
||||
```
|
||||
|
||||
Test connection:
|
||||
```bash
|
||||
telnet 104.131.15.18 4000
|
||||
```
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
server/
|
||||
├── conf/
|
||||
│ ├── __init__.py
|
||||
│ └── settings.py # Main settings file (FIXED for #534)
|
||||
├── logs/ # Evennia logs
|
||||
└── evennia.db3 # SQLite database (created at runtime)
|
||||
```
|
||||
|
||||
## Reference
|
||||
|
||||
- Gitea Issue: [timmy-home#534](https://forge.alexanderwhitestone.com/Timmy_Foundation/timmy-home/issues/534)
|
||||
- Evennia Docs: https://www.evennia.com/docs/latest/Setup/Settings-Default.html
|
||||
- World Plan: docs/BEZALEL_EVENNIA_WORLD.md
|
||||
@@ -1,87 +0,0 @@
|
||||
r"""
|
||||
Evennia settings file for Bezalel World.
|
||||
|
||||
This is the sovereign Evennia configuration for the Bezalel forge-and-testbed wizard.
|
||||
Reference: timmy-home#534
|
||||
|
||||
The available options are found in the default settings file found here:
|
||||
https://www.evennia.com/docs/latest/Setup/Settings-Default.html
|
||||
"""
|
||||
|
||||
# Use the defaults from Evennia unless explicitly overridden
|
||||
from evennia.settings_default import *
|
||||
|
||||
######################################################################
|
||||
# Evennia base server config
|
||||
######################################################################
|
||||
|
||||
# Server name
|
||||
SERVERNAME = "bezalel_world"
|
||||
|
||||
######################################################################
|
||||
# Network ports - FIXED for #534
|
||||
# Port tuples MUST include a host string, not None
|
||||
######################################################################
|
||||
|
||||
# Web server port (HTTP)
|
||||
WEBSERVER_PORTS = [(4001, "0.0.0.0")]
|
||||
|
||||
# Telnet server port
|
||||
TELNET_PORTS = [(4000, "0.0.0.0")]
|
||||
|
||||
# WebSocket port for webclient
|
||||
WEBSOCKET_PORTS = [(4002, "0.0.0.0")]
|
||||
|
||||
######################################################################
|
||||
# Database configuration
|
||||
# Using SQLite for sovereign local deployment
|
||||
######################################################################
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(GAME_DIR, 'server', 'evennia.db3'),
|
||||
'USER': '',
|
||||
'PASSWORD': '',
|
||||
'HOST': '',
|
||||
'PORT': ''
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Security settings
|
||||
######################################################################
|
||||
|
||||
# Lockdown mode for VPS - only bind to localhost unless needed
|
||||
# To allow external connections, use 0.0.0.0 in port tuples above
|
||||
ALLOWED_HOSTS = ['*'] # VPS needs this for external access
|
||||
|
||||
######################################################################
|
||||
# Game world defaults
|
||||
######################################################################
|
||||
|
||||
# Start location for new characters
|
||||
DEFAULT_HOME = "#2" # Limbo
|
||||
|
||||
# Start location for guests
|
||||
GUEST_HOME = "#2"
|
||||
|
||||
######################################################################
|
||||
# Telnet settings
|
||||
######################################################################
|
||||
|
||||
TELNET_INTERFACES = ['0.0.0.0']
|
||||
|
||||
######################################################################
|
||||
# Web server settings
|
||||
######################################################################
|
||||
|
||||
WEBSERVER_INTERFACES = ['0.0.0.0']
|
||||
|
||||
######################################################################
|
||||
# Settings given in secret_settings.py override those in this file.
|
||||
######################################################################
|
||||
try:
|
||||
from server.conf.secret_settings import *
|
||||
except ImportError:
|
||||
print("secret_settings.py file not found or failed to import.")
|
||||
@@ -15,20 +15,13 @@ EVENNIA_DIR="/root/wizards/bezalel/evennia/bezalel_world"
|
||||
SETTINGS="${EVENNIA_DIR}/server/conf/settings.py"
|
||||
VENV_PYTHON="/root/wizards/bezalel/evennia/venv/bin/python3"
|
||||
VENV_EVENNIA="/root/wizards/bezalel/evennia/venv/bin/evennia"
|
||||
TIMMY_HOME="${TIMMY_HOME:-/root/timmy-home}" # Or wherever the repo is cloned
|
||||
|
||||
echo "=== Fix Evennia Settings (Bezalel) ==="
|
||||
|
||||
# 1. Fix settings.py — prefer repo version, fallback to sed patch
|
||||
# 1. Fix settings.py — remove bad port tuples
|
||||
echo "Fixing settings.py..."
|
||||
if [ -f "${TIMMY_HOME}/evennia/bezalel_world/server/conf/settings.py" ]; then
|
||||
# Use the fixed settings from the repo
|
||||
mkdir -p "$(dirname "$SETTINGS")"
|
||||
cp "${TIMMY_HOME}/evennia/bezalel_world/server/conf/settings.py" "$SETTINGS"
|
||||
echo "Copied fixed settings from timmy-home repo."
|
||||
elif [ -f "$SETTINGS" ]; then
|
||||
# Fallback: patch in place
|
||||
echo "Patching existing settings..."
|
||||
if [ -f "$SETTINGS" ]; then
|
||||
# Remove broken port lines
|
||||
sed -i '/WEBSERVER_PORTS/d' "$SETTINGS"
|
||||
sed -i '/TELNET_PORTS/d' "$SETTINGS"
|
||||
sed -i '/WEBSOCKET_PORTS/d' "$SETTINGS"
|
||||
@@ -42,7 +35,7 @@ elif [ -f "$SETTINGS" ]; then
|
||||
echo 'TELNET_PORTS = [(4000, "0.0.0.0")]' >> "$SETTINGS"
|
||||
echo 'WEBSOCKET_PORTS = [(4002, "0.0.0.0")]' >> "$SETTINGS"
|
||||
|
||||
echo "Patched existing settings file."
|
||||
echo "Settings fixed."
|
||||
else
|
||||
echo "ERROR: Settings file not found at $SETTINGS"
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user