Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/concurrent-boot-artifact-race.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"everything-dev": patch
---

Concurrent `bos dev` sessions in one config dir no longer crash artifact generation: `.bos/bos.resolved-config.json` is now written atomically (tmp + rename) so a sibling session never reads a torn file, and the contract-bridge stale sweep removes gen files with `rmSync(…, { force: true })` so a file vanishing between the existence check and the removal no longer fails the boot with `ENOENT … lstat`.
5 changes: 5 additions & 0 deletions .changeset/pglite-only-local-db.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"everything-dev": minor
---

PGlite is the only local database — docker-compose is retired (ADR 0038). The zero-config dev default is now a persistent, file-backed PGlite data dir (`pglite:.bos/db`, per workspace process), so concurrent local projects can never collide on DB ports and data survives restarts without any `.env`. `bos dev` migrates leftovers once: compose-era `postgres://everythingdev:…@localhost:543x/…` URLs in `.env` are rewritten to the pglite defaults and a scaffold-shaped `docker-compose.yml` is relocated to `.bos/compose-retired/`. `db:*` commands work against pglite (drizzle-kit pglite dialect selected by URL scheme); the CLI/scaffold drop the compose template, `dev:postgres*` scripts, post-init docker prompt, and preflight auto-start; regression tests and the deploy smoke run on pglite (`TEST_DATABASE=postgres` + an external URL remains the parity escape hatch). Production `postgres://` URLs are unchanged.
19 changes: 3 additions & 16 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,13 @@
CORS_ORIGIN=http://localhost:3000

# app.api
# Leave empty to run dev on ephemeral pglite; set a postgres:// URL to opt into compose Postgres.
# Leave empty for the persistent local PGlite default (.bos/db); set a postgres:// URL for production or shared access.
API_DATABASE_URL=

# apps/upload (standalone upload service — BOS_STORAGE_* are service-side env,
# not composed-plugin secrets; the deploy CLI uses BOS_STORAGE_ORIGIN +
# BOS_STORAGE_API_KEY from its own env/session, see .github/workflows/deploy.yml)
BOS_STORAGE_ENDPOINT=
BOS_STORAGE_BUCKET=
BOS_STORAGE_ACCESS_KEY_ID=
BOS_STORAGE_SECRET_ACCESS_KEY=
BOS_STORAGE_REGION=
BOS_STORAGE_AUTH_ORIGIN=http://localhost:3000
BOS_STORAGE_BOOTSTRAP_API_KEY=
BOS_STORAGE_BOOTSTRAP_ACCOUNT=
BOS_STORAGE_BOOTSTRAP_GATEWAY=
BETTER_AUTH_SECRET=

# app.auth
# Leave empty to run dev on ephemeral pglite; set a postgres:// URL to opt into compose Postgres.
# Leave empty for the persistent local PGlite default (.bos/db); set a postgres:// URL for production or shared access.
AUTH_DATABASE_URL=
BETTER_AUTH_SECRET=
GITHUB_CLIENT_SECRET=
GOOGLE_CLIENT_SECRET=
FASTNEAR_API_KEY=
Expand Down
12 changes: 6 additions & 6 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# Generated test environment — loaded by test suites instead of .env
# Test databases run on dedicated *-test docker-compose services
# Test databases run on in-memory pglite — no docker involved

# app.api
API_DATABASE_URL=postgres://everythingdev:everythingdev@localhost:5434/api_test_db
API_DATABASE_URL=pglite::memory:
BETTER_AUTH_SECRET=regression-test-secret-do-not-use-in-production

# app.auth
AUTH_DATABASE_URL=postgres://everythingdev:everythingdev@localhost:5435/auth_test_db
AUTH_DATABASE_URL=pglite::memory:

# plugins.template
TEMPLATE_DATABASE_URL=postgres://everythingdev:everythingdev@localhost:5434/api_test_db
TEMPLATE_DATABASE_URL=pglite::memory:

# plugins.proposals
PROPOSALS_DATABASE_URL=postgres://everythingdev:everythingdev@localhost:5434/api_test_db
PROPOSALS_DATABASE_URL=pglite::memory:

# plugins.votes
VOTES_DATABASE_URL=postgres://everythingdev:everythingdev@localhost:5434/api_test_db
VOTES_DATABASE_URL=pglite::memory:

13 changes: 8 additions & 5 deletions .github/templates/api/drizzle.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@
* issue: https://github.com/NEARBuilders/everything-dev/issues
*/
import { defineConfig } from "drizzle-kit";
import { resolveDatabaseUrl, workspaceIdentityFromModuleUrl } from "everything-dev/db";
import {
drizzleCredentialsFor,
resolveDatabaseUrl,
workspaceIdentityFromModuleUrl,
} from "everything-dev/db";

const identity = workspaceIdentityFromModuleUrl(import.meta.url);
const credentials = drizzleCredentialsFor(resolveDatabaseUrl(identity));

export default defineConfig({
schema: "./src/db/schema.ts",
out: "./src/db/migrations",
dialect: "postgresql",
dbCredentials: {
url: resolveDatabaseUrl(identity),
},
dialect: credentials.dialect,
dbCredentials: credentials.dbCredentials,
migrations: {
schema: identity.journal.schema,
table: identity.journal.table,
Expand Down
2 changes: 1 addition & 1 deletion .github/templates/api/plugin.dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default {
variables: {},
// child-owned-end
secrets: {
API_DATABASE_URL: process.env.API_DATABASE_URL || "pglite:.bos/api/:memory:",
API_DATABASE_URL: process.env.API_DATABASE_URL || "pglite:.bos/db",
BETTER_AUTH_SECRET: devAuthSecret,
},
} satisfies PluginConfigInput<typeof Plugin>,
Expand Down
6 changes: 4 additions & 2 deletions .github/templates/api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ export default createPlugin({
secrets: z.object({
API_DATABASE_URL: z
.string()
.default("pglite:.bos/api/:memory:")
.describe("Database connection string. Use pglite: for local, postgres:// for production."),
.default("pglite:.bos/db")
.describe(
"Database connection string. pglite: is a persistent local data dir (.bos/db); postgres:// for production or shared access.",
),
}),

context: ContextSchema,
Expand Down
42 changes: 0 additions & 42 deletions .github/templates/docker-compose.yml

This file was deleted.

116 changes: 0 additions & 116 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -515,37 +515,8 @@ jobs:
timeout-minutes: 15
env:
CI: true
API_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5434/api_test_db
AUTH_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5435/auth_test_db
CORS_ORIGIN: http://localhost:4100
BETTER_AUTH_SECRET: regression-test-secret-do-not-use-in-production
services:
postgres-api-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: api_test_db
ports:
- 5434:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d api_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
postgres-auth-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: auth_test_db
ports:
- 5435:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d auth_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
steps:
- name: Checkout repository
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 (Node 24)
Expand Down Expand Up @@ -608,38 +579,9 @@ jobs:
timeout-minutes: 20
env:
CI: true
API_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5434/api_test_db
AUTH_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5435/auth_test_db
CORS_ORIGIN: http://localhost:4100
BETTER_AUTH_SECRET: regression-test-secret-do-not-use-in-production
REGRESSION_PREBUILT_IMAGE: ${{ needs.regression-image.result == 'success' && needs.regression-image.outputs.image || '' }}
services:
postgres-api-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: api_test_db
ports:
- 5434:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d api_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
postgres-auth-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: auth_test_db
ports:
- 5435:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d auth_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
steps:
- name: Checkout repository
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 (Node 24)
Expand Down Expand Up @@ -789,37 +731,8 @@ jobs:
timeout-minutes: 20
env:
CI: true
API_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5434/api_test_db
AUTH_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5435/auth_test_db
CORS_ORIGIN: http://localhost:4100
BETTER_AUTH_SECRET: regression-test-secret-do-not-use-in-production
services:
postgres-api-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: api_test_db
ports:
- 5434:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d api_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
postgres-auth-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: auth_test_db
ports:
- 5435:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d auth_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
steps:
- name: Checkout repository
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 (Node 24)
Expand Down Expand Up @@ -929,38 +842,9 @@ jobs:
timeout-minutes: ${{ matrix.timeout }}
env:
CI: true
API_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5434/api_test_db
AUTH_DATABASE_URL: postgres://everythingdev:everythingdev@127.0.0.1:5435/auth_test_db
CORS_ORIGIN: http://localhost:4100
BETTER_AUTH_SECRET: regression-test-secret-do-not-use-in-production
REGRESSION_PREBUILT_IMAGE: ${{ needs.regression-image.result == 'success' && needs.regression-image.outputs.image || '' }}
services:
postgres-api-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: api_test_db
ports:
- 5434:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d api_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
postgres-auth-test:
image: ghcr.io/nearbuilders/mirror-postgres:17-alpine@sha256:b0f9560a2de083e2cc7382e75f808c7381a32852a7ec49117deedb300e552b24
env:
POSTGRES_USER: everythingdev
POSTGRES_PASSWORD: everythingdev
POSTGRES_DB: auth_test_db
ports:
- 5435:5432
options: >-
--health-cmd "pg_isready -U everythingdev -d auth_test_db"
--health-interval 3s
--health-timeout 3s
--health-retries 10
steps:
- name: Checkout repository
uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 (Node 24)
Expand Down
6 changes: 0 additions & 6 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,6 @@ jobs:
- name: Log in to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin

# The post-publish smoke boots the runtime image identity-driven; its
# boot surface needs the compose test databases (the smoke-container
# idiom: host.docker.internal:5434/5435).
- name: Start test databases
run: docker compose up -d --wait postgres-api-test postgres-auth-test

- name: Deploy (preflight → build → upload → publish → smoke → Railway pin)
timeout-minutes: 55
# One command runs the deploy train (ADR 0020/0021, image leg split
Expand Down
7 changes: 2 additions & 5 deletions .github/workflows/mirror-images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ name: Mirror base images
# Docker Hub and ECR Public both rate-limit GitHub-hosted runners' shared
# egress IPs (Docker Hub 504s motivated the ECR move; ECR then throttled with
# `toomanyrequests: Data limit exceeded`, killing jobs before setup). The
# org's GHCR mirror is the pull source for the three library base images;
# org's GHCR mirror is the pull source for the library base images;
# this workflow refreshes it from upstream. Renovate tracks the mirrors and
# PRs the digest bumps. New GHCR packages land private — flip them public in
# package settings once (local dev docker compose pulls them unauthenticated).
# package settings once.

on:
workflow_dispatch:
Expand All @@ -27,9 +27,6 @@ jobs:
- source: public.ecr.aws/docker/library/node:24-alpine
fallback: docker.io/library/node:24-alpine
target: ghcr.io/nearbuilders/mirror-node:24-alpine
- source: public.ecr.aws/docker/library/postgres:17-alpine
fallback: docker.io/library/postgres:17-alpine
target: ghcr.io/nearbuilders/mirror-postgres:17-alpine
- source: public.ecr.aws/docker/library/redis:7-alpine
fallback: docker.io/library/redis:7-alpine
target: ghcr.io/nearbuilders/mirror-redis:7-alpine
Expand Down
Loading
Loading