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
43 lines
1.3 KiB
JavaScript
43 lines
1.3 KiB
JavaScript
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));
|
|
}
|