forgebot applied its schema by executing an inline DDL string on every boot,
with no version tracking and no lock, so two API replicas starting together
raced and the SQL had nowhere to grow. golib/pg already owns that mechanic for
the estate; take it and keep owning the SQL.
- Move the schema into migrations/0001_init.sql, embedded via migrations.FS.
The DDL is verbatim.
- The four legacy-status UPDATEs move into 0001 unchanged. Each reads only
retired statuses (pending/failed/running/succeeded/cancelled) and writes only
current ones, and no current status is a source, so replaying 0001 once
against the live database is a no-op. A test pins that property.
- Build the pool with pg.NewMigrated, LockName "forgebot-migrations": the
advisory lock serializes replicas, schema_migrations records what ran, and a
migration failure fails startup instead of half-migrating. database.New and
apiserver.New take a context and logger for it.
- Render the DSN with pg.DSN, which percent-escapes the credentials the
fmt.Sprintf builder pasted in raw. LoadConfig still reads the environment
itself: pg.DSNFromEnv has no defaults for user and database name, where
forgebot defaults both to "forgebot", and would newly honour DATABASE_URL and
PG*. The deployed DBHOST/DBPORT/DBUSER/DBPASS/DBNAME/DBSSL contract and its
defaults are unchanged, and pinned by a test.
- Plumb GOPRIVATE=git.unkin.net for the first cross-repo Go dependency:
exported by the Makefile, set in both Dockerfiles and the woodpecker Go
steps, documented in the README.
- gofmt the four files that were already unformatted on main, so the
pre-commit step can pass.
Forgebot is a K8s operator + API service for dispatching AI agent
jobs from git forge commands. Includes:
- CRDs: AgentPool, AgentTask, ProviderQueue, RepositoryBinding
- API server with webhook handler, task queue, and comment proxy
- Operator controllers for task scheduling and job management
- Gitea provider with webhook parsing and signature verification
- PostgreSQL database with auto-migration
- Woodpecker CI pipelines and multi-stage Dockerfiles