A developer once lost an hour each morning to repetitive test failures. The fixes were predictable, yet the time vanished. That hour became a script that runs every morning.
This article builds a small automation loop for free tiers. It uses a free model and a free server. The loop reads test output, explains failures, and posts a verifiable report. This is not a product review or a benchmark. It is a workflow you can copy.
Why this matters
Free tiers usually mean manual work, even with a model. You still glue it to your own workflow. MonkeyCode offers both free model access and a free server option. That combination enables a real, running service for free.
Disclosure: This article was prepared as part of MonkeyCode's product outreach.
The workflow
We build three small pieces: a fetcher, a summarizer, and a verifier. The fetcher reads raw test output from a file. The summarizer calls the free model with that text. The verifier checks the final result for key names.
Step 1: Configure the model
Set two environment variables for the model access. One holds the endpoint, and one holds the key.
export MONKEY_ENDPOINT="https://your-endpoint.example"
export MONKEY_KEY="your-key"
Do not commit these values to version control. Use a local .env file for your development work. On the server, rely on a secret manager.
Step 2: Write the summarizer
The script below is a template for your model. Replace the request body with your model's expected format.
import os
import requests
def summarize_failures(text: str) -> str:
endpoint = os.environ["MONKEY_ENDPOINT"]
key = os.environ["MONKEY_KEY"]
payload = {
"model": "your-model",
"messages": [
{"role": "user", "content": f"Explain these test failures:\n{text}"}
]
}
resp = requests.post(endpoint, json=payload, headers={"Authorization": f"Bearer {key}"})
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"]
This is pseudocode, so your model may use a different schema. Always check the current docs before running the script.
Step 3: Verify the output
A model can hallucinate, so we add a simple check. The report must mention every failing test name to pass.
def verify_report(report: str, test_names: list) -> bool:
return all(name in report for name in test_names)
This is not perfect, but it catches missing references. It does not catch wrong explanations, yet that is enough for a daily digest.
Step 4: Fetch test output
Use a small function to read a test file. In a real setup, this file comes from your CI.
def read_test_output(path: str) -> str:
with open(path) as f:
return f.read()
Step 5: Combine everything in a script
Create a single run.py with the functions above. Add a main block that ties them together.
import os
import requests
def read_test_output(path: str) -> str:
with open(path) as f:
return f.read()
def summarize_failures(text: str) -> str:
endpoint = os.environ["MONKEY_ENDPOINT"]
key = os.environ["MONKEY_KEY"]
payload = {
"model": "your-model",
"messages": [
{"role": "user", "content": f"Explain these test failures:\n{text}"}
]
}
resp = requests.post(endpoint, json=payload, headers={"Authorization": f"Bearer {key}"})
resp.raise_for_status()
return resp.json()["choices"][0]["message"]["content"]
def verify_report(report: str, test_names: list) -> bool:
return all(name in report for name in test_names)
if __name__ == "__main__":
text = read_test_output("tests.log")
report = summarize_failures(text)
if verify_report(report, ["test_a", "test_b"]):
print(report)
else:
print("Report missing test names.")
This is a complete script, so save it as run.py. Run it locally first to confirm the flow works.
Now we have a single entry point, which makes deployment easier.
Test the loop with a sample file
Create a sample test log with a known failure. Run the script and check the output.
echo "FAIL test_login" > tests.log
python run.py
The report should mention the failing test name, like test_login. If it does not, your model may need a different prompt. This test gives you confidence before you deploy.
Step 6: Deploy to the free server
MonkeyCode's free server option hosts small scripts like this. Copy your code to the server, then set the same environment variables.
Create a cron job to run the script every morning.
0 7 * * * cd /path/to/app && python run.py >> report.log 2>&1
The server must stay on for the cron job. Free servers often sleep, so check your provider's policy.
Step 7: Verify the deployment
After the first run, inspect the log file. Confirm the report appears and the verification passed.
cat report.log
If the report is empty, test the API manually. If the cron did not run, check the timezone.
Error handling
The script should handle API failures in a graceful way. Wrap the request in a try-except block to catch errors.
try:
resp = requests.post(...)
resp.raise_for_status()
except requests.RequestException as e:
print(f"API call failed: {e}")
raise
But for a daily cron, you may want to exit with a non-zero code. That way cron can alert you to problems.
import sys
sys.exit(1)
Add this exit call to the exception handler block.
Limitations
Free models have rate limits and can be slow. They may change without notice, so treat this loop as a personal tool.
The free server may have limited storage and no long-running processes. Keep the script short and simple to fit those limits. The free server may also have a cold start, so your cron job may run a few minutes late.
Token allowances shift over time, so check the current docs before relying on them.
Who should not use this
Do not use this for production alerts or security-critical decisions. If you need guaranteed uptime or low latency, pay for a service. If your team depends on immediate alerts, use a paid monitoring service instead.
The point
Limitation forces simplicity, and that is a good thing. A free model and a free server are enough for a useful tool. The loop runs while you sleep, and the report waits in the morning. That extra hour every morning is the real win.
Top comments (0)