container update notifications now fire properly
This commit is contained in:
3 files changed
+51
-19
No files matched your search
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Pure notification-event decision logic - NO db/docker imports, so it unit-tests
|
||||
* under the bun runner. index.ts re-exports and uses these; keeping the decisions here
|
||||
* means the full "which events fire for which input" matrix is testable in isolation.
|
||||
*
|
||||
* `NotificationEventType` is a type-only import (erased at build), so it doesn't pull
|
||||
* better-sqlite3 in through db.ts.
|
||||
*/
|
||||
|
||||
import type { NotificationEventType } from '../db';
|
||||
|
||||
/**
|
||||
* Map a raw Docker event action to the notification event type it should raise, or null
|
||||
* when the action isn't one we notify on. Docker has no "updated" action - a container
|
||||
* update is a die/kill of the old container followed by start of the new one, so those
|
||||
* map to container_exited/container_started here. The "container was updated" signal is
|
||||
* raised separately (see updateEventTypes) from the recreate flow, not from a raw event.
|
||||
*/
|
||||
export function mapActionToEventType(action: string): NotificationEventType | null {
|
||||
const mapping: Record<string, NotificationEventType> = {
|
||||
start: 'container_started',
|
||||
stop: 'container_stopped',
|
||||
restart: 'container_restarted',
|
||||
die: 'container_exited',
|
||||
kill: 'container_exited',
|
||||
oom: 'container_oom',
|
||||
'health_status: unhealthy': 'container_unhealthy',
|
||||
'health_status: healthy': 'container_healthy',
|
||||
pull: 'image_pulled'
|
||||
};
|
||||
return mapping[action] || null;
|
||||
}
|
||||
@@ -26,6 +26,9 @@ import {
|
||||
|
||||
import type { NotificationPayload, NotificationResult } from './shared';
|
||||
export type { NotificationPayload, NotificationResult } from './shared';
|
||||
// The pure docker-action -> event-type map lives in events-core (unit-testable).
|
||||
import { mapActionToEventType } from './events-core';
|
||||
export { mapActionToEventType } from './events-core';
|
||||
|
||||
import { sendSmtpNotification } from './smtp';
|
||||
import { sendDiscord } from './discord';
|
||||
@@ -166,21 +169,6 @@ export async function testNotification(setting: NotificationSettingData): Promis
|
||||
return { success: false, error: 'Unknown notification type' };
|
||||
}
|
||||
|
||||
// Map Docker action to notification event type
|
||||
function mapActionToEventType(action: string): NotificationEventType | null {
|
||||
const mapping: Record<string, NotificationEventType> = {
|
||||
'start': 'container_started',
|
||||
'stop': 'container_stopped',
|
||||
'restart': 'container_restarted',
|
||||
'die': 'container_exited',
|
||||
'kill': 'container_exited',
|
||||
'oom': 'container_oom',
|
||||
'health_status: unhealthy': 'container_unhealthy',
|
||||
'health_status: healthy': 'container_healthy',
|
||||
'pull': 'image_pulled'
|
||||
};
|
||||
return mapping[action] || null;
|
||||
}
|
||||
|
||||
// Scanner image patterns to exclude from notifications
|
||||
const SCANNER_IMAGE_PATTERNS = [
|
||||
@@ -257,10 +245,7 @@ export async function sendEventNotification(
|
||||
payload: NotificationPayload,
|
||||
environmentId?: number
|
||||
): Promise<{ success: boolean; sent: number }> {
|
||||
let enrichedPayload: NotificationPayload = {
|
||||
...payload,
|
||||
eventType
|
||||
};
|
||||
let enrichedPayload: NotificationPayload = { ...payload, eventType };
|
||||
if (environmentId) {
|
||||
const env = await getEnvironment(environmentId);
|
||||
if (env) {
|
||||
|
||||
@@ -693,6 +693,21 @@ export async function recreateContainer(
|
||||
} catch (e: any) {
|
||||
log?.(`WARNING: dependent-child reconnect step errored (parent update stands): ${e?.message}`);
|
||||
}
|
||||
|
||||
// recreateContainer is only ever called to UPDATE a container's image (scheduled
|
||||
// auto-update AND the manual batch-update UI), so a successful recreate is a
|
||||
// container_updated event. This is what the UI's "container updated" toggle
|
||||
// promises; auto_update_success is raised separately by the scheduler path. (#1424)
|
||||
try {
|
||||
await sendEventNotification('container_updated', {
|
||||
title: 'Container updated',
|
||||
message: `Container "${containerName}" was updated to a new image (${imageName})`,
|
||||
type: 'success'
|
||||
}, envId);
|
||||
} catch (e: any) {
|
||||
log?.(`WARNING: container_updated notification failed (update stands): ${e?.message}`);
|
||||
}
|
||||
|
||||
return { success: true };
|
||||
} catch (error: any) {
|
||||
log?.(`Failed to recreate container: ${error.message}`);
|
||||
|
||||
Reference in new issue
Block a user