Files
tinker_tickets/scripts/rehash_network_tickets.php
T
jaredandClaude Opus 5.5 aad3e8eb44
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
Key network dedup tickets on the problem, not just the host (#116)
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>
2026-11-11 01:35:48 -05:00

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']
);