Design for batch-update and batch-map subcommands across all entity types (feature, test, module, library) with shared filter infrastructure and dry-run-by-default safety.
121 lines
4.7 KiB
Markdown
121 lines
4.7 KiB
Markdown
# PortTracker Batch Operations Design
|
|
|
|
**Date:** 2026-02-27
|
|
**Status:** Approved
|
|
|
|
## Problem
|
|
|
|
The PortTracker CLI only supports one-at-a-time operations for status updates, mappings, and N/A marking. With ~3700 features and ~3300 tests, bulk operations require dropping to raw `sqlite3` commands. This is error-prone and bypasses any validation the CLI could provide.
|
|
|
|
## Design
|
|
|
|
### Approach
|
|
|
|
Add `batch-update` and `batch-map` subcommands under each existing entity command (`feature`, `test`, `module`, `library`). All batch commands share a common filter + dry-run infrastructure.
|
|
|
|
### Shared Batch Infrastructure
|
|
|
|
A new `BatchFilters` static class in `Commands/BatchFilters.cs` provides:
|
|
|
|
**Filter Options** (combined with AND logic):
|
|
- `--ids <range>` — ID range like `100-200`, comma-separated `1,5,10`, or mixed `1-5,10,20-25`
|
|
- `--module <id>` — filter by module_id (feature/test only)
|
|
- `--status <status>` — filter by current status value
|
|
|
|
**Dry-Run Default:**
|
|
- Without `--execute`, commands show a preview: "Would affect N items:" + table of matching rows
|
|
- With `--execute`, changes are applied inside a transaction and "Updated N items." is printed
|
|
- At least one filter is required (no accidental "update everything" with zero filters)
|
|
|
|
**Shared Methods:**
|
|
- `AddFilterOptions(Command cmd, bool includeModuleFilter)` — adds the common options to a command
|
|
- `BuildWhereClause(...)` — returns SQL WHERE clause + parameters from parsed filter values
|
|
- `PreviewOrExecute(Database db, string table, string selectSql, string updateSql, params[], bool execute)` — handles dry-run preview vs actual execution
|
|
|
|
### Feature Batch Commands
|
|
|
|
**`feature batch-update`**
|
|
- Filters: `--ids`, `--module`, `--status`
|
|
- Setters: `--set-status` (required), `--set-notes` (optional)
|
|
- Flag: `--execute`
|
|
|
|
**`feature batch-map`**
|
|
- Filters: `--ids`, `--module`, `--status`
|
|
- Setters: `--set-project`, `--set-class`, `--set-method` (at least one required)
|
|
- Flag: `--execute`
|
|
|
|
### Test Batch Commands
|
|
|
|
**`test batch-update`**
|
|
- Filters: `--ids`, `--module`, `--status`
|
|
- Setters: `--set-status` (required), `--set-notes` (optional)
|
|
- Flag: `--execute`
|
|
|
|
**`test batch-map`**
|
|
- Filters: `--ids`, `--module`, `--status`
|
|
- Setters: `--set-project`, `--set-class`, `--set-method` (at least one required)
|
|
- Flag: `--execute`
|
|
|
|
### Module Batch Commands
|
|
|
|
**`module batch-update`**
|
|
- Filters: `--ids`, `--status`
|
|
- Setters: `--set-status` (required), `--set-notes` (optional)
|
|
- Flag: `--execute`
|
|
|
|
**`module batch-map`**
|
|
- Filters: `--ids`, `--status`
|
|
- Setters: `--set-project`, `--set-namespace`, `--set-class` (at least one required)
|
|
- Flag: `--execute`
|
|
|
|
### Library Batch Commands
|
|
|
|
**`library batch-update`**
|
|
- Filters: `--ids`, `--status`
|
|
- Setters: `--set-status` (required), `--set-notes` (optional, maps to `dotnet_usage_notes`)
|
|
- Flag: `--execute`
|
|
|
|
**`library batch-map`**
|
|
- Filters: `--ids`, `--status`
|
|
- Setters: `--set-package`, `--set-namespace`, `--set-notes` (at least one required)
|
|
- Flag: `--execute`
|
|
|
|
## Examples
|
|
|
|
```bash
|
|
# Preview: which features in module 5 are not_started?
|
|
porttracker feature batch-update --module 5 --status not_started --set-status deferred
|
|
|
|
# Execute: defer all features in module 5 with a reason
|
|
porttracker feature batch-update --module 5 --status not_started --set-status deferred --set-notes "needs server runtime" --execute
|
|
|
|
# Execute: mark tests 500-750 as deferred
|
|
porttracker test batch-update --ids 500-750 --set-status deferred --set-notes "server-integration" --execute
|
|
|
|
# Execute: batch-map all features in module 3 to a .NET project
|
|
porttracker feature batch-map --module 3 --set-project "ZB.MOM.NatsNet.Server" --execute
|
|
|
|
# Preview: what libraries are unmapped?
|
|
porttracker library batch-update --status not_mapped --set-status mapped
|
|
|
|
# Execute: batch-map libraries
|
|
porttracker library batch-map --ids 1-20 --set-package "Microsoft.Extensions.Logging" --set-namespace "Microsoft.Extensions.Logging" --execute
|
|
```
|
|
|
|
## File Changes
|
|
|
|
| File | Change |
|
|
|------|--------|
|
|
| `Commands/BatchFilters.cs` | New — shared filter options, WHERE builder, preview/execute logic |
|
|
| `Commands/FeatureCommands.cs` | Add `batch-update` and `batch-map` subcommands |
|
|
| `Commands/TestCommands.cs` | Add `batch-update` and `batch-map` subcommands |
|
|
| `Commands/ModuleCommands.cs` | Add `batch-update` and `batch-map` subcommands |
|
|
| `Commands/LibraryCommands.cs` | Add `batch-update` and `batch-map` subcommands |
|
|
| `Data/Database.cs` | Add `ExecuteInTransaction` helper for batch safety |
|
|
|
|
## Non-Goals
|
|
|
|
- No batch create or batch delete — not needed for the porting workflow
|
|
- No raw `--where` SQL escape hatch — structured filters cover all use cases
|
|
- No interactive y/n prompts — dry-run + `--execute` flag is sufficient and scriptable
|