Add PostgreSQL 18 infra sample

This commit is contained in:
Chris Hendrickson 2026-05-04 23:34:30 -04:00
parent 7f5896ec5c
commit 2f69bff301
11 changed files with 155 additions and 1 deletions

View file

@ -0,0 +1,7 @@
# Dew Infrastructure Samples
This directory contains sample services that exercise `dew infra` using the same
layout a project would use for local infrastructure.
Each service lives under `services/<service-id>/` and is discovered from its
`manifest.yaml`.

View file

@ -0,0 +1,25 @@
# PostgreSQL 18
Sample local PostgreSQL 18 service managed by `dew infra` and Podman Quadlets.
```bash
dew infra validate postgresql-18
dew infra up postgresql-18
dew infra status postgresql-18
dew infra logs postgresql-18 --lines 100
```
The sample binds PostgreSQL to `127.0.0.1:5432` with:
- database: `dew`
- user: `dew`
- password: `dew_dev_password`
- data volume: `dew_postgresql_18_data`
Stop it with:
```bash
dew infra down postgresql-18
```
The named volume is intentionally retained after stopping the service.

View file

@ -0,0 +1,36 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://artificery.dev/dew/samples/postgresql-18/configure.schema.json",
"title": "PostgreSQL 18 Sample Configuration",
"description": "Configuration values represented by the sample PostgreSQL 18 Quadlet.",
"type": "object",
"additionalProperties": false,
"properties": {
"host_port": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"default": 5432
},
"database": {
"type": "string",
"minLength": 1,
"default": "dew"
},
"username": {
"type": "string",
"minLength": 1,
"default": "dew"
},
"password": {
"type": "string",
"minLength": 8,
"default": "dew_dev_password"
},
"volume": {
"type": "string",
"minLength": 1,
"default": "dew_postgresql_18_data"
}
}
}

View file

@ -0,0 +1,24 @@
[Unit]
Description=Dew sample PostgreSQL 18 database
Wants=network-online.target
After=network-online.target
[Container]
Image=docker.io/library/postgres:18
ContainerName=dew_postgresql_18
Environment=POSTGRES_DB=dew
Environment=POSTGRES_USER=dew
Environment=POSTGRES_PASSWORD=dew_dev_password
PublishPort=127.0.0.1:5432:5432
Volume=dew_postgresql_18_data:/var/lib/postgresql/data:Z
HealthCmd=pg_isready -U dew -d dew
HealthInterval=10s
HealthTimeout=5s
HealthRetries=5
[Service]
Restart=on-failure
TimeoutStartSec=120
[Install]
WantedBy=default.target

View file

@ -0,0 +1,22 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://artificery.dev/dew/samples/postgresql-18/init.schema.json",
"title": "PostgreSQL 18 Sample Initialization",
"description": "Optional initialization notes for the sample PostgreSQL 18 service.",
"type": "object",
"additionalProperties": false,
"properties": {
"create_database": {
"type": "boolean",
"default": true
},
"seed_sample_data": {
"type": "boolean",
"default": false
},
"notes": {
"type": "string",
"default": ""
}
}
}

View file

@ -0,0 +1,17 @@
service:
id: postgresql-18
name: PostgreSQL 18
unit: dew_postgresql_18.service
container_name: dew_postgresql_18
runtime:
type: podman-quadlet
container:
file: dew_postgresql_18.container
dropins_dir: dew_postgresql_18.container.d
profiles_dir: dew_postgresql_18.profiles.d
schemas:
configure: configure.schema.json
init: init.schema.json

View file

@ -0,0 +1,8 @@
---
id: DEW-0031
title: Add PostgreSQL 18 infra sample
type: task
created: 2026-05-05T03:31:50.153499Z
---
Add a sample Dew infrastructure service that brings up PostgreSQL 18 through a Podman Quadlet manifest, including manifest.yaml, schemas, profile/drop-in directories, and documentation.

View file

@ -73,3 +73,16 @@ user systemd path or `--scope system` for `/etc/containers/systemd`.
`dew infra up` installs missing Quadlet files, reloads systemd, then starts the
unit.
## Samples
The Dew repository includes sample service bringups under
`.project/infrastructure/services/`.
`postgresql-18` brings up a local PostgreSQL 18 container through Podman
Quadlets:
```bash
dew infra validate postgresql-18
dew infra up postgresql-18
```

View file

@ -245,7 +245,7 @@ class PodmanQuadletRuntime implements ContainerRuntime {
() => fs.directory(targetDropins).create(recursive: true),
);
await for (final entity in fs.directory(dropinsPath).list()) {
if (entity is! File) continue;
if (entity is! File || p.extension(entity.path) != '.conf') continue;
await _link(
actions,
dryRun,