Compare commits
2 Commits
fix/536
...
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,75 +0,0 @@
|
||||
# Issue #536 Verification
|
||||
|
||||
Status: already implemented on `main`
|
||||
|
||||
## Acceptance criteria check
|
||||
|
||||
1. 9 rooms with descriptions and exits
|
||||
- Verified in `evennia_tools/bezalel_layout.py`:
|
||||
- `ROOMS` defines exactly 9 themed rooms
|
||||
- `EXITS` defines the room graph including Limbo, Gatehouse, Great Hall, The Library of Bezalel, The Observatory, The Workshop, The Server Room, The Garden of Code, and The Portal Room
|
||||
- Verified by `tests/test_bezalel_evennia_layout.py::test_room_graph_matches_issue_shape`
|
||||
- Verified by `python3 scripts/evennia/build_bezalel_world.py --plan`
|
||||
|
||||
2. 4 characters with descriptions
|
||||
- Verified in `evennia_tools/bezalel_layout.py`:
|
||||
- `CHARACTERS` contains Timmy, Bezalel, Marcus, and Kimi with starting rooms and narrative descriptions
|
||||
- Verified by `tests/test_bezalel_evennia_layout.py::test_items_characters_and_portal_commands_are_all_defined`
|
||||
|
||||
3. Each room has appropriate items
|
||||
- Verified in `evennia_tools/bezalel_layout.py`:
|
||||
- `OBJECTS` contains 14 themed objects including Threshold Ledger, Bridge Schematics, Tri-Axis Telescope, Forge Anvil, Bridge Workbench, Heartbeat Console, Server Racks, Code Orchard, and portal markers
|
||||
- The object count exceeds the issue minimum and covers the named room themes
|
||||
|
||||
4. Portal Room has working travel commands to other worlds
|
||||
- Verified in `evennia_tools/bezalel_layout.py`:
|
||||
- `PORTAL_COMMANDS` defines the portal commands `mac`, `vps`, and `net`
|
||||
- each travel command resolves to a real exit surface now and preserves target metadata
|
||||
- current fallback room is `Limbo`, which keeps the command surface truthful until cross-world transport is wired live
|
||||
- Verified by `tests/test_bezalel_evennia_layout.py::test_items_characters_and_portal_commands_are_all_defined`
|
||||
|
||||
5. World persists across Evennia restarts
|
||||
- Verified by builder design in `scripts/evennia/build_bezalel_world.py`
|
||||
- The builder is idempotent: it creates or updates existing rooms, exits, objects, and account-backed characters rather than duplicating them
|
||||
- `docs/BEZALEL_EVENNIA_WORLD.md` explicitly documents this persistence note
|
||||
|
||||
6. Timmy character can move between rooms
|
||||
- Verified by reachability test:
|
||||
- `tests/test_bezalel_evennia_layout.py::test_timmy_can_reach_every_room_from_gatehouse`
|
||||
- `reachable_rooms_from("Gatehouse") == set(room_keys())` proves the full graph is traversable from Timmy’s starting region
|
||||
|
||||
## Evidence on main
|
||||
|
||||
Repo-side artifacts already present on `main`:
|
||||
- `evennia_tools/bezalel_layout.py`
|
||||
- `scripts/evennia/build_bezalel_world.py`
|
||||
- `evennia_tools/build_bezalel_world.py`
|
||||
- `evennia_tools/batch_cmds_bezalel.ev`
|
||||
- `docs/BEZALEL_EVENNIA_WORLD.md`
|
||||
- `tests/test_bezalel_evennia_layout.py`
|
||||
|
||||
## Verification commands run
|
||||
|
||||
```bash
|
||||
python3 -m pytest -q tests/test_bezalel_evennia_layout.py
|
||||
python3 -m py_compile evennia_tools/bezalel_layout.py scripts/evennia/build_bezalel_world.py tests/test_bezalel_evennia_layout.py
|
||||
python3 scripts/evennia/build_bezalel_world.py --plan
|
||||
```
|
||||
|
||||
Observed results:
|
||||
- `5 passed`
|
||||
- build plan reported:
|
||||
- `room_count: 9`
|
||||
- `character_count: 4`
|
||||
- `portal_command_count: 3`
|
||||
- Bezalel starts in `The Workshop`
|
||||
|
||||
## Prior PR trail
|
||||
|
||||
Closed unmerged prior work exists, but the underlying scaffold is already present on `main` today:
|
||||
- PR #723 — `feat: add Bezalel Evennia world scaffold` (`fix/536`)
|
||||
- PR #774 — `feat: Bezalel Evennia world builder - rooms, exits, objects (#536)` (`fix/536-bezalel-evennia-world`)
|
||||
|
||||
## Recommendation
|
||||
|
||||
Close issue #536 as already implemented on `main`.
|
||||
@@ -1,19 +0,0 @@
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
DOC = ROOT / "docs" / "issue-536-verification.md"
|
||||
|
||||
|
||||
def test_issue_536_verification_doc_exists_and_points_to_real_artifacts() -> None:
|
||||
assert DOC.exists(), "missing docs/issue-536-verification.md"
|
||||
text = DOC.read_text(encoding="utf-8")
|
||||
for snippet in (
|
||||
"# Issue #536 Verification",
|
||||
"evennia_tools/bezalel_layout.py",
|
||||
"scripts/evennia/build_bezalel_world.py",
|
||||
"tests/test_bezalel_evennia_layout.py",
|
||||
"docs/BEZALEL_EVENNIA_WORLD.md",
|
||||
"portal commands",
|
||||
"already implemented on `main`",
|
||||
):
|
||||
assert snippet in text
|
||||
Reference in New Issue
Block a user