Fetch and analyze component health regressions for OpenShift releases
Inherits all available tools
Additional assets for this skill
This skill inherits all available tools. When active, it can use any tool Claude has access to.
README.mdlist_regressions.pyThis skill provides functionality to fetch regression data for OpenShift components across different releases. It uses a Python script to query a component health API and retrieve regression information.
Use this skill when you need to:
Python 3 Installation
which python3Network Access
API Endpoint Configuration
base_url in list_regressions.py with the actual component health API endpointFirst, ensure Python 3 is available:
python3 --version
If Python 3 is not installed, guide the user through installation for their platform.
The script is located at:
plugins/component-health/skills/list-regressions/list_regressions.py
Execute the script with appropriate arguments:
# Basic usage - all regressions for a release
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.17
# Filter by specific components
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.21 \
--components Monitoring "kube-apiserver"
# Filter by multiple components
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.21 \
--components Monitoring etcd "kube-apiserver"
# Filter by development window (GA'd release - both start and end)
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.17 \
--start 2024-05-17 \
--end 2024-10-01
# Filter by development window (in-development release - start only)
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.21 \
--start 2025-09-02
The script outputs JSON data with the following structure:
{
"summary": {
"total": <number>,
"triaged": <number>,
"triage_percentage": <number>,
"time_to_triage_hrs_avg": <number or null>,
"time_to_triage_hrs_max": <number or null>,
"time_to_close_hrs_avg": <number or null>,
"time_to_close_hrs_max": <number or null>,
"open": {
"total": <number>,
"triaged": <number>,
"triage_percentage": <number>,
"time_to_triage_hrs_avg": <number or null>,
"time_to_triage_hrs_max": <number or null>,
"open_hrs_avg": <number or null>,
"open_hrs_max": <number or null>
},
"closed": {
"total": <number>,
"triaged": <number>,
"triage_percentage": <number>,
"time_to_triage_hrs_avg": <number or null>,
"time_to_triage_hrs_max": <number or null>,
"time_to_close_hrs_avg": <number or null>,
"time_to_close_hrs_max": <number or null>,
"time_triaged_closed_hrs_avg": <number or null>,
"time_triaged_closed_hrs_max": <number or null>
}
},
"components": {
"ComponentName": {
"summary": {
"total": <number>,
"triaged": <number>,
"triage_percentage": <number>,
"time_to_triage_hrs_avg": <number or null>,
"time_to_triage_hrs_max": <number or null>,
"time_to_close_hrs_avg": <number or null>,
"time_to_close_hrs_max": <number or null>,
"open": {
"total": <number>,
"triaged": <number>,
"triage_percentage": <number>,
"time_to_triage_hrs_avg": <number or null>,
"time_to_triage_hrs_max": <number or null>,
"open_hrs_avg": <number or null>,
"open_hrs_max": <number or null>
},
"closed": {
"total": <number>,
"triaged": <number>,
"triage_percentage": <number>,
"time_to_triage_hrs_avg": <number or null>,
"time_to_triage_hrs_max": <number or null>,
"time_to_close_hrs_avg": <number or null>,
"time_to_close_hrs_max": <number or null>,
"time_triaged_closed_hrs_avg": <number or null>,
"time_triaged_closed_hrs_max": <number or null>
}
},
"open": [...],
"closed": [...]
}
}
}
CRITICAL: The output includes pre-calculated counts and health metrics:
summary: Overall statistics across all components
summary.total: Total number of regressionssummary.triaged: Total number of regressions triaged (open + closed)summary.triage_percentage: Percentage of all regressions that have been triaged (KEY HEALTH METRIC)summary.time_to_triage_hrs_avg: Overall average hours to triage (combining open and closed, KEY HEALTH METRIC)summary.time_to_triage_hrs_max: Overall maximum hours to triagesummary.time_to_close_hrs_avg: Overall average hours to close regressions (closed only, KEY HEALTH METRIC)summary.time_to_close_hrs_max: Overall maximum hours to close regressions (closed only)summary.open.total: Number of open regressions (where closed is null)summary.open.triaged: Number of open regressions that have been triaged to a JIRA bugsummary.open.triage_percentage: Percentage of open regressions triagedsummary.open.time_to_triage_hrs_avg: Average hours from opened to first triage (open only)summary.open.time_to_triage_hrs_max: Maximum hours from opened to first triage (open only)summary.open.open_hrs_avg: Average hours that open regressions have been open (from opened to current time)summary.open.open_hrs_max: Maximum hours that open regressions have been open (from opened to current time)summary.closed.total: Number of closed regressions (where closed is not null)summary.closed.triaged: Number of closed regressions that have been triaged to a JIRA bugsummary.closed.triage_percentage: Percentage of closed regressions triagedsummary.closed.time_to_triage_hrs_avg: Average hours from opened to first triage (closed only)summary.closed.time_to_triage_hrs_max: Maximum hours from opened to first triage (closed only)summary.closed.time_to_close_hrs_avg: Average hours from opened to closed timestamp (null if no valid data)summary.closed.time_to_close_hrs_max: Maximum hours from opened to closed timestamp (null if no valid data)summary.closed.time_triaged_closed_hrs_avg: Average hours from first triage to closed (null if no triaged closed regressions)summary.closed.time_triaged_closed_hrs_max: Maximum hours from first triage to closed (null if no triaged closed regressions)components: Dictionary mapping component names to objects containing:
summary: Per-component statistics (includes same fields as overall summary)open: Array of open regression objects for that componentclosed: Array of closed regression objects for that componentTime to Triage Calculation:
The time_to_triage_hrs_avg field is calculated as:
created_at timestamp in the triages arrayopened timestamp and the earliest triage timestampnull if no regressions have valid time-to-triage data in that categoryTime to Close Calculation:
The time_to_close_hrs_avg and time_to_close_hrs_max fields (only for closed regressions) are calculated as:
opened and closed timestampsnull if no closed regressions have valid time dataOpen Duration Calculation:
The open_hrs_avg and open_hrs_max fields (only for open regressions) are calculated as:
opened timestamp and current timenull if no open regressions have valid time dataTime Triaged to Closed Calculation:
The time_triaged_closed_hrs_avg and time_triaged_closed_hrs_max fields (only for triaged closed regressions) are calculated as:
triages.created_at timestamp and closed timestampnull if no triaged closed regressions have valid time dataALWAYS use these summary counts rather than attempting to count the regression arrays yourself. This ensures accuracy even when the output is truncated due to size.
The script automatically simplifies and optimizes the response:
Time field simplification (closed and last_failure):
{"Time": "2025-09-27T12:04:24.966914Z", "Valid": true}"closed": "2025-09-27T12:04:24.966914Z" (if Valid is true)"closed": null (if Valid is false)last_failure fieldField removal for response size optimization:
links: Removed from each regression (reduces response size significantly)test_id: Removed from each regression (large field, can be reconstructed from test_name if needed)Date filtering (optional):
--start and --end parameters to filter regressions to a specific time window--start YYYY-MM-DD: Excludes regressions that were closed before this date--end YYYY-MM-DD: Excludes regressions that were opened after this date--start: development_start date from get-release-dates skill (always applied)--end: GA date from get-release-dates skill (only for GA'd releases)Parse this JSON output to extract relevant information for analysis.
Based on the regression data:
summary and components.*.summary objects (do NOT count the arrays)components.*.summary.open.totalNetwork Errors
URLError or connection timeoutHTTP Errors
Invalid Release
Invalid Boolean Value
ValueError: Invalid boolean valueEnable verbose output by examining stderr:
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.17 2>&1 | tee debug.log
--release: Release version to query
"X.Y" (e.g., "4.17", "4.16")--components: Filter by component names
--components Monitoring etcd "kube-apiserver"The script outputs JSON with summaries and regressions grouped by component:
{
"summary": {
"total": 62,
"triaged": 59,
"triage_percentage": 95.2,
"time_to_triage_hrs_avg": 68,
"time_to_triage_hrs_max": 240,
"time_to_close_hrs_avg": 168,
"time_to_close_hrs_max": 480,
"open": {
"total": 2,
"triaged": 1,
"triage_percentage": 50.0,
"time_to_triage_hrs_avg": 48,
"time_to_triage_hrs_max": 48,
"open_hrs_avg": 120,
"open_hrs_max": 200
},
"closed": {
"total": 60,
"triaged": 58,
"triage_percentage": 96.7,
"time_to_triage_hrs_avg": 72,
"time_to_triage_hrs_max": 240,
"time_to_close_hrs_avg": 168,
"time_to_close_hrs_max": 480,
"time_triaged_closed_hrs_avg": 96,
"time_triaged_closed_hrs_max": 240
}
},
"components": {
"Monitoring": {
"summary": {
"total": 15,
"triaged": 13,
"triage_percentage": 86.7,
"time_to_triage_hrs_avg": 68,
"time_to_triage_hrs_max": 180,
"time_to_close_hrs_avg": 156,
"time_to_close_hrs_max": 360,
"open": {
"total": 1,
"triaged": 0,
"triage_percentage": 0.0,
"time_to_triage_hrs_avg": null,
"time_to_triage_hrs_max": null,
"open_hrs_avg": 72,
"open_hrs_max": 72
},
"closed": {
"total": 14,
"triaged": 13,
"triage_percentage": 92.9,
"time_to_triage_hrs_avg": 68,
"time_to_triage_hrs_max": 180,
"time_to_close_hrs_avg": 156,
"time_to_close_hrs_max": 360,
"time_triaged_closed_hrs_avg": 88,
"time_triaged_closed_hrs_max": 180
}
},
"open": [
{
"id": 12894,
"component": "Monitoring",
"closed": null,
...
}
],
"closed": [
{
"id": 12893,
"view": "4.21-main",
"release": "4.21",
"base_release": "4.18",
"component": "Monitoring",
"capability": "operator-conditions",
"test_name": "...",
"variants": [...],
"opened": "2025-09-26T00:02:51.385944Z",
"closed": "2025-09-27T12:04:24.966914Z",
"triages": [],
"last_failure": "2025-09-25T14:41:17Z",
"max_failures": 9
}
]
},
"etcd": {
"summary": {
"total": 20,
"triaged": 19,
"triage_percentage": 95.0,
"time_to_triage_hrs_avg": 84,
"time_to_triage_hrs_max": 220,
"time_to_close_hrs_avg": 192,
"time_to_close_hrs_max": 500,
"open": {
"total": 0,
"triaged": 0,
"triage_percentage": 0.0,
"time_to_triage_hrs_avg": null,
"time_to_triage_hrs_max": null,
"open_hrs_avg": null,
"open_hrs_max": null
},
"closed": {
"total": 20,
"triaged": 19,
"triage_percentage": 95.0,
"time_to_triage_hrs_avg": 84,
"time_to_triage_hrs_max": 220,
"time_to_close_hrs_avg": 192,
"time_to_close_hrs_max": 500,
"time_triaged_closed_hrs_avg": 108,
"time_triaged_closed_hrs_max": 280
}
},
"open": [],
"closed": [...]
},
"kube-apiserver": {
"summary": {
"total": 27,
"triaged": 27,
"triage_percentage": 100.0,
"time_to_triage_hrs_avg": 58,
"time_to_triage_hrs_max": 168,
"time_to_close_hrs_avg": 144,
"time_to_close_hrs_max": 400,
"open": {
"total": 1,
"triaged": 1,
"triage_percentage": 100.0,
"time_to_triage_hrs_avg": 36,
"time_to_triage_hrs_max": 36,
"open_hrs_avg": 96,
"open_hrs_max": 96
},
"closed": {
"total": 26,
"triaged": 26,
"triage_percentage": 100.0,
"time_to_triage_hrs_avg": 60,
"time_to_triage_hrs_max": 168,
"time_to_close_hrs_avg": 144,
"time_to_close_hrs_max": 400,
"time_triaged_closed_hrs_avg": 84,
"time_triaged_closed_hrs_max": 232
}
},
"open": [...],
"closed": [...]
}
}
}
Important - Summary Objects:
summary object contains overall pre-calculated counts for accuracycomponents object has its own summary with per-component countscomponents object maps component names (sorted alphabetically) to objects containing:
summary: Statistics for this component (total, open, closed)open: Array of open regression objects (where closed is null)closed: Array of closed regression objects (where closed has a timestamp)summary and components.*.summary fields for counts (including total, open.total, open.triaged, closed.total, closed.triaged)components.*.open or components.*.closed arrays yourselfNote: Time fields are simplified from the API response:
closed: If the regression is closed: "closed": "2025-09-27T12:04:24.966914Z" (timestamp string), otherwise nulllast_failure: If valid: "last_failure": "2025-09-25T14:41:17Z" (timestamp string), otherwise nullpython3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.17
Expected Output: JSON containing all regressions for release 4.17
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.21 \
--components Monitoring etcd
Expected Output: JSON containing regressions for only Monitoring and etcd components in release 4.21
python3 plugins/component-health/skills/list-regressions/list_regressions.py \
--release 4.21 \
--components "kube-apiserver"
Expected Output: JSON containing regressions for the kube-apiserver component in release 4.21
The script includes a placeholder API endpoint. Update it in list_regressions.py:
# Current placeholder
base_url = f"https://component-health-api.example.com/api/v1/regressions"
# Update to actual endpoint
base_url = f"https://actual-api.example.com/api/v1/regressions"
To add additional query parameters, modify the fetch_regressions function:
def fetch_regressions(release: str, opened: Optional[bool] = None,
component: Optional[str] = None) -> dict:
params = [f"release={release}"]
if opened is not None:
params.append(f"opened={'true' if opened else 'false'}")
if component is not None:
params.append(f"component={component}")
# ... rest of function
This skill is designed to be used by the /component-health:analyze-regressions command, but can also be invoked directly by other commands or scripts that need regression data.
urllib module (no external dependencies)