fix: multiple test-workflow bugs — draft wipe, dark date pickers, Jira status strings, Tempo gate, hold timer
Aegis CI / lint-and-test (push) Has been cancelled
Snyk Security Scan / Python vulnerabilities (backend) (push) Has been cancelled
Snyk Security Scan / npm vulnerabilities (frontend) (push) Has been cancelled
Snyk Security Scan / Docker image vulnerabilities (backend) (push) Has been cancelled

- Fix the red/blue draft form losing unsaved fields (e.g. execution_start_time) whenever an evidence upload refetches the test — the hydration effect now runs once per test, not on every refetch.
- Add color-scheme: dark so native date/time picker popups match the app theme instead of rendering white.
- Fix _STATE_TO_JIRA_STATUS: real Jira statuses are 'To Do' and 'Red Team test review', not 'To-Do' and 'RT Test Review' — confirmed live against the actual workflow transitions, which is why Submit to Blue Team never moved the ticket past 'In Progress'.
- Tempo worklog sync was silently blocked by TEMPO_ENABLED defaulting to False with no admin-facing toggle, even after configuring a Tempo token via Settings. Now bypassed once an admin or personal token is actually configured, mirroring Jira's DB-backed enabled flag.
- Hold now actually pauses the running phase timer (paused_at), and Resume accumulates the held duration into red/blue_paused_seconds — previously the timer kept counting through a hold.
This commit is contained in:
kitos
2026-07-10 15:24:19 +02:00
parent 997b38d333
commit be2a3fdced
8 changed files with 180 additions and 13 deletions
+15
View File
@@ -1354,6 +1354,10 @@ def hold_test(
test.hold_reason = payload.reason
test.held_at = _dt.utcnow()
# A running phase timer must stop counting while on hold.
if test.state in (TestState.red_executing, TestState.blue_evaluating) and test.paused_at is None:
test.paused_at = test.held_at
log_action(db, current_user.id, "hold_test", str(test_id), {"reason": payload.reason})
db.commit()
db.refresh(test)
@@ -1375,6 +1379,7 @@ def resume_test(
current_user: User = Depends(require_any_role_strict("red_tech", "blue_tech")),
):
"""Resume a test that was placed on hold."""
from datetime import datetime as _dt
from app.services.jira_service import push_hold_event
test = crud_get_test_or_raise(db, test_id)
@@ -1386,6 +1391,16 @@ def resume_test(
test.hold_reason = None
test.held_at = None
# Resume the phase timer that hold_test paused, accumulating the held
# duration the same way pause/resume-timer does.
if test.paused_at is not None:
held_seconds = max(int((_dt.utcnow() - test.paused_at).total_seconds()), 0)
if test.state == TestState.red_executing:
test.red_paused_seconds = (test.red_paused_seconds or 0) + held_seconds
elif test.state == TestState.blue_evaluating:
test.blue_paused_seconds = (test.blue_paused_seconds or 0) + held_seconds
test.paused_at = None
log_action(db, current_user.id, "resume_test", str(test_id), {})
db.commit()
db.refresh(test)
+3 -3
View File
@@ -379,11 +379,11 @@ _STATE_EMOJI: dict[str, str] = {
# (reopen_blue_review), that's pushed as "In Progress" directly instead of
# through this table — see push_bt_review_reopened().
_STATE_TO_JIRA_STATUS: dict[str, str] = {
"draft": "To-Do",
"draft": "To Do",
"red_executing": "In Progress",
"red_review": "RT Test Review",
"red_review": "Red Team test review",
"blue_evaluating": "Queued Blue Team",
"blue_review": "Blue Team Test Review",
"blue_review": "Blue Team test review",
"in_review": "Validation",
"validated": "Done",
"rejected": "Rejected",
+11 -4
View File
@@ -6,8 +6,11 @@ Each user authenticates to Tempo with their own personal Tempo API token,
stored in ``user.tempo_api_token``. This is different from the Jira API token.
Obtain a Tempo token at: Jira → Apps → Tempo → Settings → API Integration.
The global ``settings.TEMPO_ENABLED`` flag acts as a kill-switch. When False,
all Tempo calls are silently skipped regardless of whether users have tokens.
The global ``settings.TEMPO_ENABLED`` env var is an optional hard kill-switch
for ops (e.g. disable entirely in a demo environment). It defaults to False,
but that default is bypassed automatically once an admin or personal Tempo
token is actually configured — configuring a token via Settings is enough
to turn Tempo sync on, same as Jira's DB-backed "enabled" toggle.
What goes to Tempo
------------------
@@ -223,8 +226,12 @@ def auto_log_test_worklog(
logger.debug("Skipping Tempo sync for activity_type=%s", activity_type)
return None
# Global kill-switch
if not settings.TEMPO_ENABLED:
# Global kill-switch — bypassed once an admin or personal Tempo token
# is actually configured, mirroring how Jira's DB-backed "enabled"
# toggle takes priority over its env-var default. Without this, an
# admin who configures a Tempo token via Settings still gets silent
# no-ops because TEMPO_ENABLED defaults to False and has no UI toggle.
if not settings.TEMPO_ENABLED and not has_admin_tempo_configured(db) and not has_tempo_configured(user):
return None
# Compute duration from test timestamps when not supplied by the caller