Skip to content

Commit 865fad2

Browse files
authored
Release v0.15.0
Release v0.15.0
2 parents 50d3754 + 0017553 commit 865fad2

61 files changed

Lines changed: 836980 additions & 244 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-db.yml

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
name: DB Integrity
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
db-integrity:
8+
name: Migration smoke test + seed freshness
9+
runs-on: ubuntu-latest
10+
11+
services:
12+
postgres:
13+
image: postgres:16-alpine
14+
env:
15+
POSTGRES_USER: power2plant
16+
POSTGRES_PASSWORD: power2plant
17+
POSTGRES_DB: power2plant
18+
options: >-
19+
--health-cmd pg_isready
20+
--health-interval 5s
21+
--health-timeout 5s
22+
--health-retries 5
23+
ports:
24+
- 5432:5432
25+
26+
env:
27+
DATABASE_URL: postgresql://power2plant:power2plant@localhost:5432/power2plant
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
- uses: pnpm/action-setup@v4
33+
34+
- uses: actions/setup-node@v4
35+
with:
36+
node-version: 22
37+
cache: pnpm
38+
39+
- run: pnpm install --frozen-lockfile
40+
41+
- run: pnpm exec prisma generate
42+
43+
- name: Load seed.sql
44+
run: psql "$DATABASE_URL" < db/seed.sql
45+
46+
- name: Apply pending migrations
47+
run: |
48+
BEFORE_TS=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
49+
echo "BEFORE_TS=$BEFORE_TS" >> "$GITHUB_ENV"
50+
pnpm exec prisma migrate deploy
51+
52+
- name: Check seed.sql freshness
53+
run: |
54+
APPLIED=$(psql "$DATABASE_URL" -t -c \
55+
"SELECT count(*) FROM \"_prisma_migrations\" WHERE started_at > '$BEFORE_TS' AND finished_at IS NOT NULL AND logs IS NULL;" \
56+
| tr -d ' ')
57+
echo "Migrations applied on top of seed.sql: $APPLIED"
58+
if [ "$APPLIED" -gt 0 ]; then
59+
echo "::warning::seed.sql is stale — $APPLIED migration(s) missing. Run \`pnpm db:dump\` and commit db/seed.sql."
60+
if [[ "${{ github.head_ref }}" == release/* ]]; then
61+
echo "::error::seed.sql must include all migrations on release branches. Run \`pnpm db:dump\` and commit."
62+
exit 1
63+
fi
64+
fi
65+
66+
upgrade-path:
67+
name: Upgrade path from last release
68+
runs-on: ubuntu-latest
69+
70+
services:
71+
postgres:
72+
image: postgres:16-alpine
73+
env:
74+
POSTGRES_USER: power2plant
75+
POSTGRES_PASSWORD: power2plant
76+
POSTGRES_DB: power2plant
77+
options: >-
78+
--health-cmd pg_isready
79+
--health-interval 5s
80+
--health-timeout 5s
81+
--health-retries 5
82+
ports:
83+
- 5432:5432
84+
85+
env:
86+
DATABASE_URL: postgresql://power2plant:power2plant@localhost:5432/power2plant
87+
88+
steps:
89+
- uses: actions/checkout@v4
90+
with:
91+
fetch-depth: 0
92+
93+
- uses: pnpm/action-setup@v4
94+
95+
- uses: actions/setup-node@v4
96+
with:
97+
node-version: 22
98+
cache: pnpm
99+
100+
- run: pnpm install --frozen-lockfile
101+
102+
- run: pnpm exec prisma generate
103+
104+
- name: Load last release seed.sql
105+
run: |
106+
LAST_TAG=$(git tag --sort=-version:refname | grep -E '^v[0-9]' | head -1)
107+
if [ -z "$LAST_TAG" ]; then
108+
echo "No release tag found — skipping"
109+
exit 0
110+
fi
111+
echo "Testing upgrade path from $LAST_TAG"
112+
echo "LAST_TAG=$LAST_TAG" >> "$GITHUB_ENV"
113+
git show "$LAST_TAG:db/seed.sql" | psql "$DATABASE_URL"
114+
115+
- name: Apply current migrations on top
116+
run: pnpm exec prisma migrate deploy

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ autodev/orchestrate/orchestrator.pid
1515
autodev/logs/
1616
.claude/settings.local.json
1717
.env.prod
18+
db/seed-enrichment-attempts.sql

Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ RUN if [ -n "$AGENT_PUBKEY" ]; then \
3838
fi
3939
RUN passwd -d node && \
4040
printf '\nPort 2222\nPasswordAuthentication no\nPermitRootLogin prohibit-password\nStrictModes no\n' >> /etc/ssh/sshd_config
41+
# Align node uid/gid with the host/agent user so shared /app volume files
42+
# are mutually writable. Pass SHELL_UID/SHELL_GID at build time.
43+
ARG SHELL_UID=1000
44+
ARG SHELL_GID=1000
45+
RUN if [ "$SHELL_UID" != "1000" ] || [ "$SHELL_GID" != "1000" ]; then \
46+
apk add --no-cache shadow && \
47+
groupmod -g "$SHELL_GID" node && \
48+
usermod -u "$SHELL_UID" node && \
49+
chown -R node:node /home/node && \
50+
apk del shadow; \
51+
fi
4152

4253
# ---- prod-deps ----
4354
# Flat (hoisted) layout so .bin shims have no absolute paths baked in —
@@ -88,3 +99,11 @@ ENV PORT=3000
8899
ENV HOSTNAME="0.0.0.0"
89100

90101
CMD ["sh", "-c", "prisma migrate deploy && node server.js"]
102+
103+
# ---- scripts ----
104+
# On-demand admin/research container. Not started by default.
105+
# Usage: docker compose --profile scripts run --rm scripts pnpm research:import
106+
FROM deps AS scripts
107+
WORKDIR /app
108+
COPY . .
109+
RUN pnpm exec prisma generate

db/dump.sh

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
11
#!/bin/sh
22
set -e
33

4-
# Produces db/seed.sql — a spin-up snapshot for new contributors. Schema for
5-
# every table is included, but data is dumped only for the canonical plant
6-
# datasets (Crop / CropRelationship / their sources). Auth and per-user
7-
# garden tables stay empty so we never commit personal data.
4+
# Produces two seed files:
5+
# db/seed.sql — schema + canonical plant data
6+
# db/seed-enrichment-attempts.sql.gz — CropEnrichmentAttempt rows (gzipped; never diffed)
7+
# Auth and per-user garden tables are schema-only so no personal data is committed.
88

99
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
1010
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
1111
[ -f "$ROOT_DIR/.env" ] && . "$ROOT_DIR/.env"
1212

1313
DB_URL="${DATABASE_URL:-postgresql://power2plant:power2plant@localhost:5432/power2plant}"
14-
OUT="$(dirname "$0")/seed.sql"
14+
OUT="$SCRIPT_DIR/seed.sql"
15+
OUT_ENRICHMENT="$SCRIPT_DIR/seed-enrichment-attempts.sql.gz"
1516

1617
if ! pg_isready -d "$DB_URL" -q; then
1718
echo "ERROR: Database not reachable at $DB_URL" >&2
1819
exit 1
1920
fi
2021

21-
echo "Dumping plant data to $OUT (user-generated tables: schema only) ..."
22+
echo "Dumping canonical plant data to $OUT ..."
2223

2324
pg_dump "$DB_URL" \
2425
--format=plain \
@@ -31,8 +32,19 @@ pg_dump "$DB_URL" \
3132
--exclude-table-data='public."UserGarden"' \
3233
--exclude-table-data='public."Bed"' \
3334
--exclude-table-data='public."Planting"' \
35+
--exclude-table-data='public."CropEnrichmentAttempt"' \
3436
--file="$OUT"
3537

36-
LINES=$(wc -l < "$OUT")
37-
SIZE=$(du -sh "$OUT" | cut -f1)
38-
echo "Done — $SIZE, $LINES lines"
38+
echo "Done — $(du -sh "$OUT" | cut -f1), $(wc -l < "$OUT") lines"
39+
40+
echo "Dumping CropEnrichmentAttempt to $OUT_ENRICHMENT ..."
41+
42+
pg_dump "$DB_URL" \
43+
--format=plain \
44+
--no-owner \
45+
--no-acl \
46+
--table='public."CropEnrichmentAttempt"' \
47+
--data-only \
48+
| gzip > "$OUT_ENRICHMENT"
49+
50+
echo "Done — $(du -sh "$OUT_ENRICHMENT" | cut -f1)"

db/restore.sh

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ ROOT_DIR="$(dirname "$SCRIPT_DIR")"
66
[ -f "$ROOT_DIR/.env" ] && . "$ROOT_DIR/.env"
77

88
DB_URL="${DATABASE_URL:-postgresql://power2plant:power2plant@localhost:5432/power2plant}"
9-
DUMP="$(dirname "$0")/seed.sql"
9+
DUMP="$SCRIPT_DIR/seed.sql"
10+
DUMP_ENRICHMENT="$SCRIPT_DIR/seed-enrichment-attempts.sql.gz"
1011

1112
if [ ! -f "$DUMP" ]; then
1213
echo "ERROR: No dump found at $DUMP" >&2
@@ -21,3 +22,9 @@ fi
2122
echo "Restoring from $DUMP ..."
2223
psql "$DB_URL" --file="$DUMP" --quiet
2324
echo "Done"
25+
26+
if [ -f "$DUMP_ENRICHMENT" ]; then
27+
echo "Restoring enrichment attempts from $DUMP_ENRICHMENT ..."
28+
gunzip -c "$DUMP_ENRICHMENT" | psql "$DB_URL" --quiet
29+
echo "Done"
30+
fi

0 commit comments

Comments
 (0)