commit 711c3f2365611c33374430fd49a3efa62b299e73
parent ac40eef32632dbd71c44d2f9b81b49301d274309
Author: Chris Roberts <chris.roberts@learningunix.net>
Date: Thu, 16 Jul 2026 19:15:01 -0500
Add POST /jobs/<name>/run for the override path
Wires run_job() into the app: looks up the job (reusing the
same 404 behavior as the GET route), then spawns it via
pexpect using the job's prompt pattern and a response supplied
in the request body. Response text is per-request data, not
config, since it's inherently different every call (e.g. rip's
movie name) - see jobs.toml.example for the prompt field shape.
Does not yet handle the "no response, let the script's own
60s timeout apply" case, or rip's second (duplicate-rip)
prompt - both deliberately deferred as separate next steps.
Diffstat:
3 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/jobs.toml.example b/jobs.toml.example
@@ -1,2 +1,3 @@
[jobs.example]
path = "/path/to/your/script"
+prompt = "Enter something:"
diff --git a/src/simplefe/app.py b/src/simplefe/app.py
@@ -1,7 +1,9 @@
-from flask import Flask, abort
+from flask import Flask, abort, request
from simplefe.config import load_jobs
+from simplefe.runner import run_job
+
def create_app(jobs=None):
app = Flask(__name__)
@@ -26,4 +28,14 @@ def create_app(jobs=None):
abort(404)
return jobs[name]
+ @app.route("/jobs/<name>/run", methods=["POST"])
+ def trigger_job(name):
+ jobs = app.config["JOBS"]
+ if name not in jobs:
+ abort(404)
+ job = jobs[name]
+ response = request.json["response"]
+ output = run_job(job["path"], job["prompt"], response)
+ return {"output": output.decode()}
+
return app
diff --git a/tests/test_app.py b/tests/test_app.py
@@ -1,3 +1,10 @@
+from pathlib import Path
+
+from simplefe.app import create_app
+
+FIXTURES = Path(__file__).parent / "fixtures"
+
+
def test_list_jobs(client):
response = client.get("/jobs")
assert response.json == {"jobs": ["rip"]}
@@ -11,3 +18,22 @@ def test_get_job(client):
def test_get_job_not_found(client):
response = client.get("/jobs/nonexistent")
assert response.status_code == 404
+
+
+def test_trigger_job():
+ fake_job = FIXTURES / "fake_job.py"
+ app = create_app(
+ jobs={
+ "rip": {
+ "path": f"python3 {fake_job}",
+ "prompt": "Enter movie name:",
+ }
+ }
+ )
+ app.config.update({"TESTING": True})
+ client = app.test_client()
+
+ response = client.post("/jobs/rip/run", json={"response": "The Matrix"})
+
+ assert response.status_code == 200
+ assert "Got: The Matrix" in response.json["output"]