Lint / JS (eslint) (push) Successful in 12s
Lint / PHP (phpcs PSR-12) (push) Successful in 27s
Lint / PHP requirements (version + extensions) (push) Successful in 33s
Lint / Notify on failure (push) Skipped
Lint / Deploy (push) Successful in 9s
Lint / PHP (phpcs PSR-12) (pull_request) Successful in 1m12s
Security / PHP Security (semgrep) (push) Successful in 3m26s
Lint / PHP requirements (version + extensions) (pull_request) Successful in 35s
Lint / JS (eslint) (pull_request) Successful in 11s
Lint / Deploy (pull_request) Skipped
Lint / Notify on failure (pull_request) Skipped
Security / PHP Security (semgrep) (pull_request) Successful in 1m48s
Network tickets never set issue_subtype, so every automated network alert for a host hashed alike: Gandalf's "Interface enp3s0 link-down" for micro1 matched closed reboot ticket 993441773, got noted there as a recurrence, and never got its own ticket. Automated network tickets now key on the optional `check_code` payload field when sent (it must name the instance, e.g. iface_down:enp3s0), otherwise on the title text outside the [tags], normalised with digits kept. Manual tickets and every other category hash exactly as before. The hash logic moves to helpers/TicketHash.php so the new scripts/rehash_network_tickets.php can re-key open network tickets once after deploy (--dry-run first). Closed tickets keep their old hash so they stop catching unrelated alerts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
79 lines
2.6 KiB
PHP
79 lines
2.6 KiB
PHP
#!/usr/bin/env php
|
|
<?php
|
|
|
|
/**
|
|
* Re-key open automated network tickets after #116.
|
|
*
|
|
* Network tickets used to hash on host alone, so every network alert for a
|
|
* host shared one ticket. They now hash on host + the problem's heading (see
|
|
* helpers/TicketHash.php). Without this script, each open network ticket
|
|
* keeps its old hash and its next alert opens a duplicate instead of
|
|
* updating it. Run once after deploying #116:
|
|
*
|
|
* php scripts/rehash_network_tickets.php --dry-run # report only
|
|
* php scripts/rehash_network_tickets.php
|
|
*
|
|
* Closed tickets keep their old hash on purpose: they stop catching
|
|
* unrelated alerts. A ticket whose new hash already belongs to another ticket
|
|
* is skipped and reported (resolve it by hand). Safe to re-run.
|
|
*/
|
|
|
|
if (php_sapi_name() !== 'cli') {
|
|
http_response_code(403);
|
|
exit('CLI access only');
|
|
}
|
|
|
|
require_once dirname(__DIR__) . '/config/config.php';
|
|
require_once dirname(__DIR__) . '/helpers/Database.php';
|
|
require_once dirname(__DIR__) . '/helpers/TicketHash.php';
|
|
|
|
$dryRun = in_array('--dry-run', $argv, true);
|
|
$conn = Database::getConnection();
|
|
|
|
$rows = $conn->query("SELECT ticket_id, title, hash FROM tickets WHERE status <> 'Closed' ORDER BY ticket_id")
|
|
->fetch_all(MYSQLI_ASSOC);
|
|
|
|
$counts = ['updated' => 0, 'unchanged' => 0, 'conflict' => 0];
|
|
$lookup = $conn->prepare("SELECT ticket_id FROM tickets WHERE hash = ? AND ticket_id <> ? LIMIT 1");
|
|
$update = $conn->prepare("UPDATE tickets SET hash = ? WHERE ticket_id = ?");
|
|
|
|
foreach ($rows as $row) {
|
|
$data = ['title' => (string)$row['title']];
|
|
$components = TicketHash::components($data);
|
|
if ($components['issue_category'] !== 'network' || $components['source_type'] !== 'auto') {
|
|
continue;
|
|
}
|
|
$newHash = TicketHash::generate($data);
|
|
$id = $row['ticket_id'];
|
|
|
|
if ($newHash === $row['hash']) {
|
|
$counts['unchanged']++;
|
|
echo "unchanged $id {$row['title']}\n";
|
|
continue;
|
|
}
|
|
|
|
$lookup->bind_param('ss', $newHash, $id);
|
|
$lookup->execute();
|
|
$other = $lookup->get_result()->fetch_assoc();
|
|
if ($other) {
|
|
$counts['conflict']++;
|
|
echo "CONFLICT $id {$row['title']} (new hash already on ticket {$other['ticket_id']})\n";
|
|
continue;
|
|
}
|
|
|
|
if (!$dryRun) {
|
|
$update->bind_param('ss', $newHash, $id);
|
|
$update->execute();
|
|
}
|
|
$counts['updated']++;
|
|
echo ($dryRun ? 'would update' : 'updated ') . " $id {$row['title']}\n";
|
|
}
|
|
|
|
printf(
|
|
"%s%d updated, %d already current, %d conflicts\n",
|
|
$dryRun ? '[dry run] ' : '',
|
|
$counts['updated'],
|
|
$counts['unchanged'],
|
|
$counts['conflict']
|
|
);
|