Clarify provisioning source labels and filters
This commit is contained in:
@@ -3,7 +3,29 @@ import type { ProvisioningDeployment } from './provisioning-detail.js';
|
||||
import type { ProvisioningSource } from './provisioning-detail.js';
|
||||
|
||||
export const provisioningListStatuses = ['pending', 'running', 'awaiting-health', 'done', 'attention', 'failed', 'interrupted', 'warning', 'cancelled'] as const;
|
||||
export const provisioningListSources = ['manual', 'campaign', 'beta', 'maintenance', 'rebalance', 'system'] as const;
|
||||
export const provisioningListSources = ['manual', 'campaign', 'beta', 'maintenance', 'recovery', 'autoscaling', 'rebalance', 'system'] as const;
|
||||
export type ProvisioningListSource = typeof provisioningListSources[number];
|
||||
export const provisioningSourceLabels: Record<ProvisioningListSource, string> = {
|
||||
manual: 'Manual', campaign: 'Campaign', beta: 'Beta', maintenance: 'Maintenance',
|
||||
recovery: 'Recovery', autoscaling: 'Autoscaling', rebalance: 'Rebalance', system: 'System'
|
||||
};
|
||||
export const provisioningSourceKinds = {
|
||||
campaign: ['campaign'], beta: ['beta'], maintenance: ['maintenance'],
|
||||
recovery: ['watchdog'], autoscaling: ['autoscaling'], rebalance: ['rebalance']
|
||||
} as const satisfies Record<Exclude<ProvisioningListSource, 'manual' | 'system'>, readonly ProvisioningSource['kind'][]>;
|
||||
|
||||
/** Record titles and incident summaries belong in expanded details, not the source column. */
|
||||
export function provisioningSourceLabel(row: Pick<ProvisioningListRow, 'sources' | 'triggered_by'>): string {
|
||||
const kind = row.sources?.[0]?.kind;
|
||||
return provisioningSourceLabels[kind === 'watchdog' ? 'recovery' : kind ?? (row.triggered_by === 'ui' ? 'manual' : 'system')];
|
||||
}
|
||||
|
||||
export function provisioningMatchesSource(row: Pick<ProvisioningListRow, 'sources' | 'triggered_by'>, source: ProvisioningListSource): boolean {
|
||||
const sources = row.sources ?? [];
|
||||
if (source === 'manual' || source === 'system') return !sources.length && (source === 'manual' ? row.triggered_by === 'ui' : row.triggered_by !== 'ui');
|
||||
const kinds: readonly ProvisioningSource['kind'][] = provisioningSourceKinds[source];
|
||||
return sources.some(item => kinds.includes(item.kind));
|
||||
}
|
||||
|
||||
export type ProvisioningListRow = Pick<ProvisioningDeployment,
|
||||
'id' | 'server' | 'server_deleted_at' | 'action' | 'state' | 'stage' | 'started_at' |
|
||||
@@ -16,7 +38,7 @@ export interface ProvisioningListOptions {
|
||||
view?: 'active' | 'history' | 'all';
|
||||
action?: ProvisioningAction;
|
||||
status?: typeof provisioningListStatuses[number];
|
||||
source?: typeof provisioningListSources[number];
|
||||
source?: ProvisioningListSource;
|
||||
server?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ensureHostSchema } from '../hosts/schema.js';
|
||||
import { safetyOverride, safetyOverrideAvailability } from './safety-override.js';
|
||||
import { serverTitle } from '../../ui/server-labels.js';
|
||||
import { provisioningQueueStatus } from '../../ui/provisioning-queue.js';
|
||||
import { provisioningPageSize, provisioningPageOffset, type ProvisioningListOptions, type ProvisioningListPage, type ProvisioningListRow } from '../../provisioning-list.js';
|
||||
import { provisioningPageSize, provisioningPageOffset, provisioningSourceKinds, type ProvisioningListOptions, type ProvisioningListPage, type ProvisioningListRow } from '../../provisioning-list.js';
|
||||
|
||||
export function beginDeployment(server: string, action: ProvisioningAction, triggeredBy = 'ui'): string {
|
||||
const id = randomUUID();
|
||||
@@ -320,15 +320,12 @@ function deploymentListQuery(options: ProvisioningListOptions) {
|
||||
if (options.status === 'attention') conditions.push(reviewDeployment);
|
||||
else if (options.status === 'pending') conditions.push("d.state IN ('queued','waiting')");
|
||||
else if (options.status) { conditions.push('d.state=?'); parameters.push(options.status); }
|
||||
const linked = (kinds: string[]) => `(EXISTS (SELECT 1 FROM provisioning_sources src WHERE src.operation_id=d.id AND src.kind IN (${kinds.map(kind => `'${kind}'`).join(',')}))
|
||||
const linked = (kinds: readonly string[]) => `(EXISTS (SELECT 1 FROM provisioning_sources src WHERE src.operation_id=d.id AND src.kind IN (${kinds.map(kind => `'${kind}'`).join(',')}))
|
||||
OR ${kinds.map(kind => `d.triggered_by LIKE '${kind}:%'`).join(' OR ')})`;
|
||||
if (options.source === 'campaign' || options.source === 'beta') conditions.push(linked([options.source]));
|
||||
else if (options.source === 'maintenance') conditions.push(linked(['maintenance', 'watchdog']));
|
||||
else if (options.source === 'rebalance') conditions.push("d.triggered_by LIKE 'rebalance:%'");
|
||||
else if (options.source === 'manual' || options.source === 'system') {
|
||||
conditions.push(`NOT ${linked(['campaign', 'beta', 'maintenance', 'watchdog', 'rebalance'])}`);
|
||||
if (options.source === 'manual' || options.source === 'system') {
|
||||
conditions.push(`NOT ${linked(Object.values(provisioningSourceKinds).flat())}`);
|
||||
conditions.push(options.source === 'manual' ? "d.triggered_by='ui'" : "d.triggered_by!='ui'");
|
||||
}
|
||||
} else if (options.source) conditions.push(linked(provisioningSourceKinds[options.source]));
|
||||
const search = (options.server ?? '').slice(0, 100).toLowerCase();
|
||||
if (search) {
|
||||
// Read only distinct names to preserve friendly map/lobby searches, including deleted servers.
|
||||
|
||||
Reference in New Issue
Block a user