@@ -24,6 +24,10 @@ type GrafanaDatasourceConfig = {
2424 datasources ?: GrafanaDatasource [ ] ;
2525} ;
2626
27+ type DockerComposeConfig = {
28+ services ?: Record < string , { restart ?: unknown } > ;
29+ } ;
30+
2731// These UIDs are referenced by provisioned Grafana dashboards.
2832// Changing them without updating dashboard JSON silently breaks panels.
2933const expectedGrafanaDatasourceUids = new Map ( [
@@ -259,6 +263,32 @@ describe("Config consistency", () => {
259263 expect ( envExample ) . toContain ( "openssl rand -base64 18" ) ;
260264 } ) ;
261265
266+ test ( "long-running Docker Compose services survive host reboot" , ( ) => {
267+ const composeConfig = Bun . YAML . parse (
268+ readFileSync ( composePath , "utf8" )
269+ ) as DockerComposeConfig ;
270+ const services = composeConfig . services ?? { } ;
271+
272+ // All services should survive host reboot unless they are one-shot setup jobs.
273+ const oneShotServices = new Set ( [ "config-init" , "sources-generator" ] ) ;
274+ const serviceEntries = Object . entries ( services ) ;
275+
276+ expect ( serviceEntries . length ) . toBeGreaterThan ( 0 ) ;
277+
278+ for ( const serviceName of oneShotServices ) {
279+ expect ( services [ serviceName ] ) . toBeDefined ( ) ;
280+ expect ( services [ serviceName ] ?. restart ) . toBeUndefined ( ) ;
281+ }
282+
283+ for ( const [ serviceName , serviceConfig ] of serviceEntries ) {
284+ if ( oneShotServices . has ( serviceName ) ) {
285+ continue ;
286+ }
287+
288+ expect ( serviceConfig . restart ) . toBe ( "unless-stopped" ) ;
289+ }
290+ } ) ;
291+
262292 test ( "pgwatch presets only reference configured metrics" , ( ) => {
263293 const pgwatchConfig = loadPgwatchConfig ( ) ;
264294 const metricNames = new Set ( Object . keys ( pgwatchConfig . metrics ) ) ;
0 commit comments