feat(jira+tests): 5 improvements from review
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled

1. Jira status → In Progress on Start Execution
   - push_test_event calls set_issue_status("In Progress") when
     new_state == "red_executing" (non-fatal, separate try/except)

2. Jira assignee set on Start Execution
   - assign_issue() called with actor.jira_account_id when operator
     clicks Start (non-fatal)

3. Standalone tests parent ticket (OFS-20798)
   - New jira.parent_ticket_standalone config key
   - get_jira_parent_ticket_standalone() falls back to parent_ticket
   - auto_create_test_issue uses standalone parent for non-campaign tests
   - Exposed in /system/jira-config GET+PATCH and SettingsPage UI

4. Tests table: Created + Updated columns
   - Add Created column (created_at), fix Updated to show updated_at
   - Both use UTC-aware date parsing (append Z if no tz suffix)
   - updated_at added to Test TypeScript interface

5. Sortable columns in tests table
   - All 7 columns sortable: Name, Technique, State, Current Team,
     Platform, Created, Updated
   - Click to sort asc, click again to reverse; ChevronUp/Down indicator
   - Default sort: Created desc (newest first)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kitos
2026-05-27 13:07:46 +02:00
parent 43c8b241dc
commit eeee17d260
6 changed files with 169 additions and 19 deletions

View File

@@ -88,10 +88,21 @@ def is_jira_enabled(db: Session) -> bool:
def get_jira_parent_ticket(db: Session) -> Optional[str]:
"""Return the configured parent ticket key, or None if not set."""
"""Return the configured parent ticket key for campaigns, or None if not set."""
return _read_system_config(db, "jira.parent_ticket") or None
def get_jira_parent_ticket_standalone(db: Session) -> Optional[str]:
"""Return the parent ticket for standalone tests (not in a campaign).
Falls back to get_jira_parent_ticket() if not explicitly configured.
"""
return (
_read_system_config(db, "jira.parent_ticket_standalone")
or get_jira_parent_ticket(db)
)
def upsert_jira_config(db: Session, key: str, value: str) -> None:
"""Persist a Jira config key-value pair."""
from app.models.system_config import SystemConfig
@@ -482,9 +493,10 @@ def auto_create_test_issue(
"labels": ["aegis", "security-test", mitre_id.replace(".", "-")],
}
# Use campaign ticket as parent when provided, otherwise fall back to
# the system-configured parent (e.g. OFS-9107)
parent = parent_ticket_override or get_jira_parent_ticket(db)
# Use campaign ticket as parent when provided; otherwise use the
# standalone-tests parent (e.g. OFS-20798), falling back to the
# general parent ticket if the standalone one is not configured.
parent = parent_ticket_override or get_jira_parent_ticket_standalone(db)
if parent:
fields["parent"] = {"key": parent}
@@ -548,6 +560,34 @@ def push_test_event(
jira = get_user_jira_client(actor, db)
comment = _build_state_comment(test, new_state, actor, extra)
jira.issue_add_comment(link.jira_issue_key, comment)
# When the operator starts execution: transition to "In Progress"
# and assign the ticket to that operator.
if new_state == "red_executing":
try:
jira.set_issue_status(link.jira_issue_key, "In Progress")
logger.info(
"Transitioned Jira ticket %s to In Progress", link.jira_issue_key
)
except Exception as exc_t:
logger.warning(
"Could not transition %s to In Progress: %s",
link.jira_issue_key, exc_t,
)
jira_account_id = getattr(actor, "jira_account_id", None)
if jira_account_id:
try:
jira.assign_issue(link.jira_issue_key, account_id=jira_account_id)
logger.info(
"Assigned Jira ticket %s to account %s",
link.jira_issue_key, jira_account_id,
)
except Exception as exc_a:
logger.warning(
"Could not assign %s to %s: %s",
link.jira_issue_key, jira_account_id, exc_a,
)
link.last_synced_at = datetime.utcnow()
db.flush()
logger.info(