feat: deployable Helm chart + analytics-agent bootstrap CLI#12
Merged
Conversation
shirshanka
added a commit
that referenced
this pull request
May 2, 2026
- CLAUDE.md: /path/to/talkster → /path/to/analytics-agent - skills/*/SKILL.md: author: talkster → author: analytics-agent - frontend/package.json: datahub-talk-to-data-ui → datahub-analytics-agent-ui - tests/unit/test_config.py: test_talkster_* → test_yaml_* Runtime renames (docker-compose.yml, quickstart.sh) are intentionally deferred — they require a one-time migration path which will be added on top of the bootstrap CLI (PR #12). Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
shirshanka
added a commit
that referenced
this pull request
May 2, 2026
- CLAUDE.md: /path/to/talkster → /path/to/analytics-agent - skills/*/SKILL.md: author: talkster → author: analytics-agent - frontend/package.json: datahub-talk-to-data-ui → datahub-analytics-agent-ui - tests/unit/test_config.py: test_talkster_* → test_yaml_* Runtime renames (docker-compose.yml, quickstart.sh) are intentionally deferred — they require a one-time migration path which will be added on top of the bootstrap CLI (PR #12). Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds the initial helm/analytics-agent chart (Chart.yaml, deployment, service, ingress, secret-env, serviceaccount) and a /health endpoint in main.py used by the chart's liveness/readiness probes.
…rt recipes Ensures migrations and yaml seeds are applied on first run (and are a no-op on subsequent runs) for serve, dev, start, and dev-full targets. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
531b50b to
1472356
Compare
Dockerfile binds uvicorn to 8100; values.yaml had the legacy default of 8000 which would have caused liveness/readiness probe failures. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- docker/Dockerfile: add .venv/bin to PATH so analytics-agent CLI is reachable by name in the container (Helm job command was exit 127) - pyproject.toml: add psycopg2-binary so Alembic's sync engine can connect to PostgreSQL (asyncpg is async-only; Alembic needs psycopg2) - helm/templates: make ServiceAccount and Secret pre-install/pre-upgrade hooks at weight -1 so they exist before the bootstrap Job (weight 0) fires; without this the Job pod fails with SA/Secret not found - cli.py: consolidate bootstrap seeds into one asyncio.run() call; multiple sequential asyncio.run() calls in the same process cause "Future attached to a different loop" with asyncpg because the cached SQLAlchemy engine is bound to the first (now-closed) event loop Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Three checks that would have caught the bugs found during local deploy: - helm lint: template syntax validation - port check: asserts Dockerfile EXPOSE == values.yaml targetPort - hook ordering: asserts SA and Secret weight < bootstrap Job weight Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Triggers only on changes to helm/** or docker/Dockerfile — not on every Python or frontend change. Removes the helm-chart job from ci.yml. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Spins up a kind cluster, builds the image, starts Postgres, runs helm install, and verifies the /health endpoint responds 200. Runs after the static lint job passes (needs: helm-chart). Docker layer caching keeps repeat runs fast. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Direct curl+chmod to /usr/local/bin fails on GitHub-hosted runners (permission denied). helm/kind-action handles installation correctly. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
GHA cache export is unsupported with the docker buildx driver, which is required for kind load docker-image to work. Plain docker build is simpler and sufficient for a local kind-based integration test. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The action defaults to cluster name "chart-testing"; kind load docker-image expects "kind". Explicitly set the name to match. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
helm/analytics-agent/) with deployment, service, ingress, secret-env, serviceaccount, and a newbootstrap-job.yamlthat runs as apre-install/pre-upgradehook.analytics-agentCLI (Click-based) with subcommandsmigrate,seed-integrations,seed-context-platforms,seed-defaults, and an umbrellabootstrap. The umbrella is what the Helm hook invokes.register_engines_from_db,propagate_datahub_env, LLM-config load, MCP discovery bg task. All DB-mutating bootstrap work (Alembic + yaml seeds + first-run defaults) now lives inanalytics_agent.bootstrapand runs out-of-band via the CLI.Why
Running migrations and yaml→DB seeding inside the lifespan was wrong for Kubernetes: every replica racing to migrate on scale-out, slower pod boot, and shared-state mutations that should happen once per release. The CLI + Helm hook model fixes both.
What changed
backend/src/analytics_agent/cli.py,backend/src/analytics_agent/bootstrap.pybackend/src/analytics_agent/main.py(540 → 355 lines)pyproject.toml,uv.lockhelm/analytics-agent/**(chart + bootstrap-job hook + values defaultbootstrap.enabled=true)README.md,AGENTS.md,CLAUDE.md,helm/analytics-agent/README.mdtests/unit/test_bootstrap.py(8 tests),tests/unit/test_cli.py(3 tests)Behavior change
Dev / pip / docker users must run
analytics-agent bootstraponce before the firstuvicornstart (and after any release that adds migrations). README documents this. Helm users get it automatically via the pre-install/pre-upgrade hook.If a pod boots without the bootstrap having run, the lifespan crashes loudly with a SQLAlchemy "no such table" error — verified end-to-end during implementation.
Verification
uv run pytest tests/unit/— 90 passed (was 79, +11 new bootstrap/cli tests)uv run ruff check backend/ tests/— clean (pre-existing errors inscripts/unaffected)helm lint helm/analytics-agent— 0 chart(s) failedhelm template ... --set bootstrap.enabled=false— Job omitted as expected/healthreturns okno such table: context_platforms