Skip to content

Commit 12d8072

Browse files
committed
Fix format
1 parent 489729a commit 12d8072

4 files changed

Lines changed: 326 additions & 179 deletions

File tree

Tools/test_plan_visualization/README.md

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,49 @@ A web application to inspect, filter, and explore Checkbox jobs and test plans.
44

55
## Overview
66

7-
This application parses the [Checkbox](https://github.com/canonical/checkbox) repository and provides a local search engine for job units and test plans. It supports two views:
7+
This application parses the
8+
[Checkbox](https://github.com/canonical/checkbox) repository and provides
9+
a local search engine for job units and test plans. It supports two views:
810

911
- **Jobs View** — browse and filter individual job units
10-
- **Test Plans View** — search test plans and explore their nested structure down to included jobs
12+
- **Test Plans View** — search test plans and explore their nested structure
13+
down to included jobs
1114

1215
## Features
1316

1417
- **Two-View UI**: Toggle between Jobs and Test Plans views from the header.
15-
- **Automated Parsing**: Scans `.pxu` files and extracts both job units (including legacy `plugin:`-style entries) and test plan units.
16-
- **Job Filters**: Filter by Provider, Category, Environ, Manifest Keys, and Template ID presence.
17-
- **Search**: Search by job ID, test plan ID, or plan name — searches across both jobs and the test plans they belong to.
18-
- **Test Plan Tree**: In the Test Plans view, expand plans to see nested sub-plans and directly included jobs.
19-
- **Exclude Support**: Jobs excluded by a test plan's `exclude:` field are shown with a strikethrough and an EXCLUDED badge — they remain visible but clearly marked.
20-
- **Job Details Modal**: Click Details on any job to see its full attributes and the complete test plan hierarchy it belongs to.
21-
- **Plan Details Modal**: Click Details on any test plan card to see all raw plan attributes, include/exclude patterns, and nested parts.
22-
- **Dynamic Filters**: Dropdown options update dynamically based on current selections.
23-
- **Provider Resolution**: Automatically resolves provider namespaces from `manage.py`.
24-
- **Compare Plans**: Switch to the Compare view, enter two plan IDs, and see a three-column diff — jobs only in Plan 1, jobs in both, and jobs only in Plan 2 (excludes are applied before comparing).
18+
- **Automated Parsing**: Scans `.pxu` files and extracts both job units
19+
(including legacy `plugin:`-style entries) and test plan units.
20+
- **Job Filters**: Filter by Provider, Category, Environ, Manifest Keys,
21+
and Template ID presence.
22+
- **Search**: Search by job ID, test plan ID, or plan name — searches across
23+
both jobs and the test plans they belong to.
24+
- **Test Plan Tree**: In the Test Plans view, expand plans to see nested
25+
sub-plans and directly included jobs.
26+
- **Exclude Support**: Jobs excluded by a test plan's `exclude:` field are
27+
shown with a strikethrough and an EXCLUDED badge — they remain visible
28+
but clearly marked.
29+
- **Job Details Modal**: Click Details on any job to see its full attributes
30+
and the complete test plan hierarchy it belongs to.
31+
- **Plan Details Modal**: Click Details on any test plan card to see all raw
32+
plan attributes, include/exclude patterns, and nested parts.
33+
- **Dynamic Filters**: Dropdown options update dynamically based on
34+
current selections.
35+
- **Provider Resolution**: Automatically resolves provider namespaces
36+
from `manage.py`.
37+
- **Compare Plans**: Switch to the Compare view, enter two plan IDs, and see
38+
a three-column diff — jobs only in Plan 1, jobs in both, and jobs only in
39+
Plan 2 (excludes are applied before comparing).
2540

2641
## Getting Started
2742

2843
### Option A: Run Locally
2944

3045
**Prerequisites:** Python 3.10+, `git`
3146

32-
1. **Run the startup script** — it automatically creates a virtual environment, installs dependencies, clones/updates the checkbox repo, builds the database, and starts the server:
47+
1. **Run the startup script** — it automatically creates a virtual
48+
environment, installs dependencies, clones/updates the checkbox repo,
49+
builds the database, and starts the server:
3350
```bash
3451
./run.sh
3552
```
@@ -53,16 +70,19 @@ This application parses the [Checkbox](https://github.com/canonical/checkbox) re
5370
sudo docker build -t checkbox-job-db .
5471
```
5572

56-
2. **Run the container** (the startup script runs automatically inside the container):
73+
2. **Run the container** (the startup script runs automatically
74+
inside the container):
5775
```bash
5876
sudo docker run -p 8888:8888 checkbox-job-db
5977
```
6078

61-
> If you get a "port already allocated" error, stop any existing container first:
79+
> If you get a "port already allocated" error, stop any existing
80+
> container first:
6281
> ```bash
6382
> sudo docker stop $(sudo docker ps -q --filter publish=8888)
6483
> ```
65-
> If the port still appears stuck with no process using it, restart the Docker daemon:
84+
> If the port still appears stuck with no process using it, restart
85+
> the Docker daemon:
6686
> ```bash
6787
> sudo systemctl restart docker
6888
> ```
@@ -84,19 +104,27 @@ This application parses the [Checkbox](https://github.com/canonical/checkbox) re
84104

85105
| Endpoint | Description |
86106
|---|---|
87-
| `GET /api/jobs` | List jobs with optional filters: `provider`, `category`, `environ`, `manifest`, `has_template_id`, `search` |
88-
| `GET /api/options` | Get available filter values for the current filter selection |
89-
| `GET /api/testplans?job_id=` | Get the full test plan ancestry for a given job ID |
90-
| `GET /api/plan-tree?search=` | Search test plans and return their full nested tree with included jobs (excluded jobs marked) |
91-
| `GET /api/plan-details?plan_id=` | Get all attributes, include/exclude patterns, and nested parts for a single test plan |
92-
| `GET /api/compare-plans?plan1=&plan2=` | Compare effective job sets of two test plans (excludes applied), returning only-in-1, in-both, only-in-2 |
107+
| `GET /api/jobs` | List jobs with optional filters: `provider`,
108+
`category`, `environ`, `manifest`, `has_template_id`, `search` |
109+
| `GET /api/options` | Get available filter values for the
110+
current filter selection |
111+
| `GET /api/testplans?job_id=` | Get the full test plan ancestry
112+
for a given job ID |
113+
| `GET /api/plan-tree?search=` | Search test plans and return their
114+
full nested tree with included jobs (excluded jobs marked) |
115+
| `GET /api/plan-details?plan_id=` | Get all attributes,
116+
include/exclude patterns, and nested parts for a single test plan |
117+
| `GET /api/compare-plans?plan1=&plan2=` | Compare effective job sets
118+
of two test plans (excludes applied), returning only-in-1,
119+
in-both, only-in-2 |
93120

94121
## Troubleshooting: Port 8888
95122

96123
**Check what is using port 8888:**
97124
```bash
98125
ss -tlnp sport = :8888 # shows process if owned by current user
99-
sudo ss -tlnp sport = :8888 # shows process for all users (including Docker/root)
126+
sudo ss -tlnp sport = :8888 # shows process for all users
127+
# (including Docker/root)
100128
```
101129

102130
**Kill local uvicorn process:**
@@ -126,8 +154,14 @@ sudo systemctl restart docker
126154

127155
## Notes
128156

129-
- The database is rebuilt every time the server starts (both locally and in Docker).
157+
- The database is rebuilt every time the server starts
158+
(both locally and in Docker).
130159
- Both `unit: job` and legacy `plugin:`-style job blocks are parsed.
131-
- Test plan nested hierarchy is traversed recursively; cycle detection is built in.
132-
- The `exclude:` field in test plans is parsed and stored. Excluded jobs are shown with a strikethrough in the plan tree and are removed from the effective job set when comparing plans.
133-
- Environment variables referenced in a job's `command:` field (e.g. `$SERIAL_PORTS_STATIC`) are automatically added to the Environ filter even if no explicit `environ:` field is declared.
160+
- Test plan nested hierarchy is traversed recursively;
161+
cycle detection is built in.
162+
- The `exclude:` field in test plans is parsed and stored. Excluded jobs
163+
are shown with a strikethrough in the plan tree and are removed from
164+
the effective job set when comparing plans.
165+
- Environment variables referenced in a job's `command:` field
166+
(e.g. `$SERIAL_PORTS_STATIC`) are automatically added to the Environ
167+
filter even if no explicit `environ:` field is declared.

Tools/test_plan_visualization/app/database.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,40 @@
1111

1212
Base = declarative_base()
1313

14+
1415
class Job(Base):
1516
__tablename__ = "jobs"
1617

1718
id = Column(Integer, primary_key=True, index=True)
1819
job_id = Column(String, index=True)
1920
provider = Column(String, index=True)
2021
category_id = Column(String, index=True)
21-
environ = Column(Text) # Stored as JSON string or comma separated
22-
manifest = Column(Text) # Stored as JSON string or comma separated keywords from `requires`
22+
environ = Column(Text) # Stored as JSON string or comma separated
23+
manifest = Column(
24+
Text
25+
) # Stored as JSON string or comma separated keywords from `requires`
2326
command = Column(Text)
2427
summary = Column(Text)
2528
description = Column(Text)
26-
unit_type = Column(String) # 'job', 'test plan', etc.
27-
data = Column(Text) # JSON string of all attributes
29+
unit_type = Column(String) # 'job', 'test plan', etc.
30+
data = Column(Text) # JSON string of all attributes
31+
2832

2933
class TestPlan(Base):
3034
__tablename__ = "test_plans"
3135

3236
id = Column(Integer, primary_key=True, index=True)
33-
plan_id = Column(String, index=True) # e.g. bluetooth-cert-automated
34-
full_id = Column(String, index=True) # with namespace, e.g. com.canonical.certification::bluetooth-cert-automated
37+
plan_id = Column(String, index=True) # e.g. bluetooth-cert-automated
38+
full_id = Column(
39+
String, index=True
40+
) # e.g. com.canonical.certification::bluetooth-cert-automated
3541
provider = Column(String, index=True)
3642
name = Column(Text)
37-
include = Column(Text) # JSON list of raw include patterns
38-
exclude = Column(Text) # JSON list of raw exclude patterns
43+
include = Column(Text) # JSON list of raw include patterns
44+
exclude = Column(Text) # JSON list of raw exclude patterns
3945
nested_part = Column(Text) # JSON list of nested test plan IDs
40-
data = Column(Text) # JSON of all raw attributes
46+
data = Column(Text) # JSON of all raw attributes
47+
4148

4249
def get_db():
4350
db = SessionLocal()

0 commit comments

Comments
 (0)