mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 15:51:26 +00:00
- internal/deployqueue: serialized FIFO per service — concurrent deploys of one service no longer race (the container-name-conflict failure mode); different services still run in parallel. - Deploys and rollbacks enqueue through the queue; a busy service returns status 'queued' and promotes when the active job finishes. - POST /deployments/:id/cancel — queued jobs drop immediately (200 cancelled); active jobs get ctx cancelled so build/reconcile abort (202 cancelling, settles 'cancelled'); finished deployments return 409 NOT_CANCELLABLE. - Redeploy and variables save now route through the same queue so they can't overlap a build; PUT /services/:id/variables accepts redeploy:true to apply env changes to running containers. - no_cache on deployment create plumbs BuildRequest -> BuildOptions for nixpacks, dockerfile and railpack builders. - CLI: deployments cancel, deploy --no-cache, variables set/unset --redeploy. MCP: containr_deployments_cancel; deploy/variables_set document no_cache/redeploy. UI: Cancel button + queued/cancelled badges on the deployments table. OpenAPI + types regenerated. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2.7 KiB
2.7 KiB
AGENTS.md — Containr
Containr is a self-hosted Docker PaaS (Railway-style). Backend: Go + Gin + PostgreSQL (sqlc) + Redis-compatible cache (Dragonfly) + Docker API. Frontend: React + Vite + TypeScript + React Query. API contract: docs/api/openapi.yaml (generated types: app/frontend/src/generated/api-types.ts).
This file is for coding agents working on the repo. For operating Containr as a deployed product, see llms.txt.
Layout
app/backend— Go monolith. Entrypoints:cmd/server(API),cmd/cli(containrCLI),cmd/mcp(containr-mcpMCP server).app/backend/internal/api— Gin handlers + route groups (routes.go: public /readOptionalAuth /authed/admin).app/backend/internal/middleware—Auth(JWT + Better Auth session + PAT),RequireAdmin,Idempotency.app/backend/internal/cli/commands— all CLI commands; sharedClient,Output,confirmhelpers live here.app/backend/internal/mcpserver— declarative MCP tool registry mirroring the API.app/backend/sqlc—schema.sql+queries/*.sql; generate viasqlc generateintointernal/database/sqlcdb.app/backend/migrations_goose— goose migrations (YYYYMMDDHHMMSS_name.sql).app/frontend— React app. Pages undersrc/features/, API calls viasrc/lib/api-client.ts.
Build / test / verify
cd app/backend && go build ./... && go vet ./... && go test ./...
cd app/frontend && npx tsc --noEmit && npm run lint && npm run build
cd app/frontend && npm run generate:api # after any openapi.yaml change
Dev stack: Postgres on :15432 (containr-postgres-1), Dragonfly on :16379 (containr-dragonfly-1). Server needs DATABASE_URL, REDIS_URL, JWT_SECRET, PORT=8080.
Conventions that matter
- New endpoints go in the right route group; mutations on
authed/adminget idempotency for free. - Deploy work goes through
deploy_queue(internal/deployqueue) — per-service FIFO; enqueue jobs instead ofgo-ing deployment/reconcile goroutines so they never race a build. - New list endpoints use
pageWindow/paginationMeta(internal/api/pagination.go) — cursor + page,next_cursorin the envelope. - New errors use stable codes via
respondError(c, status, code, msg)ininternal/api/errors.go. - New CLI command → also register an MCP tool in
internal/mcpserver/server.goand document in OpenAPI. All three surfaces ship together. - Destructive CLI commands must gate on
--yes/confirmviacommands.confirm; destructive MCP tools requireconfirm: true. - sqlc: edit
schema.sql+queries/*.sql, runsqlc generate, add the goose migration. - Don't commit secrets. PATs (
cnp_…) and agent tokens (cagt_…) are sha256-hashed at rest; raw values are shown once.