Add per-metric remediation plans and improve CI pipeline

Per-metric remediation plan scoping (GitLab issue #19):
- Add metric_id column to compliance_item_history table (migration)
- Extend PATCH /items/:hostname/metadata to accept metric_id/metric_ids
  for targeting specific metrics instead of all active items
- Add MetricChipSelector UI in detail panel for choosing which metrics
  to apply resolution_date and remediation_plan changes to
- Display per-metric labels (MetricChip or 'All metrics') on history entries
- Backward compatible: omitting metric_ids preserves hostname-level behavior

CI/CD pipeline improvements:
- Add migration idempotency integration test (runs against real Postgres)
- Add post-deploy smoke tests for compliance and VCL endpoints
- Bump lint --max-warnings from 10 to 25
- Configure varsIgnorePattern for _ prefix convention on unused vars

Closes #19
This commit is contained in:
Jordan Ramos
2026-05-26 11:16:28 -06:00
parent 33e449f520
commit caf6ca4008
9 changed files with 936 additions and 78 deletions

View File

@@ -0,0 +1,42 @@
const pool = require('../db');
async function run() {
console.log('Starting compliance_item_history metric_id column migration...');
try {
// Idempotent: only add column if it doesn't already exist
const { rows } = await pool.query(`
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'compliance_item_history'
AND column_name = 'metric_id'
`);
if (rows.length === 0) {
await pool.query(`
ALTER TABLE compliance_item_history
ADD COLUMN metric_id TEXT
`);
console.log('✓ metric_id column added to compliance_item_history');
} else {
console.log('✓ metric_id column already exists (skipped)');
}
await pool.query(`
CREATE INDEX IF NOT EXISTS idx_compliance_history_hostname_metric
ON compliance_item_history(hostname, metric_id)
`);
console.log('✓ hostname/metric_id index created');
console.log('Migration complete.');
} catch (err) {
console.error('Migration failed:', err.message);
throw err;
}
}
module.exports = { run };
// Self-execute when run directly
if (require.main === module) {
run().then(() => process.exit(0)).catch(() => process.exit(1));
}

View File

@@ -25,6 +25,7 @@ const POSTGRES_MIGRATIONS = [
'add_flexible_jira_ticket_creation.js',
'add_multi_item_jira_ticket.js',
'drop_jira_status_check_constraint.js',
'add_compliance_history_metric_id.js',
];
async function runAll() {