Add required human review gate to the Agent pipeline #1
@@ -63,6 +63,8 @@ jobs:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
build-args: |
|
||||
APP_BUILD=sha-${{ steps.meta.outputs.short_sha }}
|
||||
|
||||
release:
|
||||
needs: build-and-push
|
||||
|
||||
@@ -19,6 +19,10 @@ COPY cli cli
|
||||
RUN mkdir -p backend/uploads backend/outputs backend/.llm_cache
|
||||
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
# Build identifier baked in by CI (sha-<short_sha>, matches the image tag);
|
||||
# defaults to "dev" for local builds. Surfaced in /health and the site header.
|
||||
ARG APP_BUILD=dev
|
||||
ENV APP_BUILD=${APP_BUILD}
|
||||
EXPOSE 8099
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
|
||||
@@ -45,7 +45,8 @@ EXTRACT_CONCURRENCY=4
|
||||
REASON_CONCURRENCY=4
|
||||
|
||||
# Public URL users reach this server on (used for the link in result emails)
|
||||
APP_BASE_URL=http://localhost:8099
|
||||
APP_BASE_URL=https://conchecker.scoutitsystems.com
|
||||
# APP_BUILD is set by CI at image build time (sha-<short_sha>) - do not set manually.
|
||||
|
||||
# Email notifications (optional). Leave SMTP_HOST blank to disable.
|
||||
# Examples:
|
||||
|
||||
+4
-1
@@ -123,7 +123,10 @@ APP_VERSION = "0.1.0"
|
||||
# Public base URL used to build the "view results" link in notification
|
||||
# emails. Set to whatever address users reach this server on (e.g. the
|
||||
# Tailscale/LAN URL) so the link in the email actually resolves.
|
||||
APP_BASE_URL = os.getenv("APP_BASE_URL", "http://localhost:8099")
|
||||
APP_BASE_URL = os.getenv("APP_BASE_URL", "https://conchecker.scoutitsystems.com")
|
||||
# Build identifier baked into the Docker image by CI (sha-<short_sha>, matching
|
||||
# the image tag). Shown in the site header and /health. "dev" for local runs.
|
||||
APP_BUILD = os.getenv("APP_BUILD", "dev")
|
||||
|
||||
# -- Email / SMTP (optional notification on completion) -------------
|
||||
# If unset, the app still works; it just logs "SMTP not configured" and
|
||||
|
||||
@@ -35,6 +35,8 @@ _FRONTEND_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {"status": "ok", "model": config.MODEL,
|
||||
"version": config.APP_VERSION,
|
||||
"build": config.APP_BUILD,
|
||||
"key_configured": bool(config.AI_API_KEY),
|
||||
"email_configured": bool(config.SMTP_HOST and config.SMTP_USER and config.SMTP_PASSWORD)}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ services:
|
||||
env_file:
|
||||
- backend/.env
|
||||
environment:
|
||||
APP_BASE_URL: ${APP_BASE_URL:-http://localhost:8099}
|
||||
APP_BASE_URL: ${APP_BASE_URL:-https://conchecker.scoutitsystems.com}
|
||||
volumes:
|
||||
- uploads:/app/backend/uploads
|
||||
- outputs:/app/backend/outputs
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ services:
|
||||
- backend/.env
|
||||
environment:
|
||||
# Override in backend/.env for production (email links, etc.)
|
||||
APP_BASE_URL: ${APP_BASE_URL:-http://localhost:8099}
|
||||
APP_BASE_URL: ${APP_BASE_URL:-https://conchecker.scoutitsystems.com}
|
||||
volumes:
|
||||
- uploads:/app/backend/uploads
|
||||
- outputs:/app/backend/outputs
|
||||
|
||||
+5
-1
@@ -87,7 +87,7 @@
|
||||
<body>
|
||||
<header>
|
||||
<h1>Conflict Checker</h1>
|
||||
<div class="sub">Cross-discipline design contradiction review for construction drawing sets</div>
|
||||
<div class="sub">Cross-discipline design contradiction review for construction drawing sets<span id="buildTag"></span></div>
|
||||
</header>
|
||||
<main>
|
||||
<div class="drop" id="drop">
|
||||
@@ -504,6 +504,10 @@ async function finalizeReview(){
|
||||
|
||||
// If opened from an email link (/?job=<id>), load that job's results directly.
|
||||
(function init(){
|
||||
// Show the deployed build in the header so it's obvious which version is up.
|
||||
fetch('/health').then(r=>r.ok?r.json():null).then(h=>{
|
||||
if(h&&h.build) document.getElementById('buildTag').textContent=' · build '+h.build;
|
||||
}).catch(()=>{});
|
||||
const jobId=new URLSearchParams(location.search).get('job');
|
||||
if(jobId){ statusEl.innerHTML='<span class="spinner"></span>Loading job '+esc(jobId)+'...'; poll(jobId); }
|
||||
})();
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from backend import config
|
||||
from backend.main import app
|
||||
|
||||
|
||||
def test_health_includes_version_and_build():
|
||||
client = TestClient(app)
|
||||
response = client.get("/health")
|
||||
assert response.status_code == 200
|
||||
body = response.json()
|
||||
assert body["version"] == config.APP_VERSION
|
||||
assert body["build"] == config.APP_BUILD
|
||||
|
||||
|
||||
def test_app_base_url_default_is_public_site():
|
||||
assert config.APP_BASE_URL == "https://conchecker.scoutitsystems.com"
|
||||
|
||||
|
||||
def test_app_build_defaults_to_dev():
|
||||
assert config.APP_BUILD == "dev"
|
||||
Reference in New Issue
Block a user