Conversation
…eploy workflow Adds all config needed to deploy to Fly.io without any application code changes. - supervisord.conf: runs api, mcp, and bot (long-polling) as supervised processes inside a single container - Dockerfile: installs supervisor; copies supervisord.conf; changes default CMD to supervisord (Pi deploys override CMD via docker-compose.yml as before) - fly.toml: prod app (tether-prod, sea, 512mb, min_machines=1 for bot polling) - fly.dev.toml: dev app (tether-dev, sea, 256mb, min_machines=0 — can sleep) - fly-deploy.yml: single workflow handling both prod (main) and dev (dev) branches; Fly remote build, no self-hosted runner needed
Telegram bot_token and chat_id were only written to TETHER_CONFIG_DIR
by configure.py, leaving no fallback for cloud deployments where no
local config dir is mounted. Adding ${TELEGRAM_BOT_TOKEN} placeholders
lets the config loader resolve them from env vars (Fly.io secrets) the
same way auth_config.yaml handles JWT, OAuth, and vault credentials.
Pi deployments are unaffected — local override in TETHER_CONFIG_DIR
still wins per the loader's resolution chain.
Without this, flyctl uploads source to Fly's builder but PREMIUM_GIT_TOKEN is empty, so the Dockerfile silently skips the premium install and deploys community edition. TETHER_PREMIUM_TOKEN is already in GitHub secrets (same token used by the Pi build) — forwarded here as a Docker build arg.
Replace hardcoded 'tether' database name in GRANT/REVOKE CONNECT statements with the actual database name from the connection URL. Fixes fresh installs on managed Postgres (Neon) where the database is named 'neondb' rather than 'tether'.
fix: use dynamic db name in tether_app role migration (Neon compat)
feat(infra): Fly.io deployment scaffolding (Phase 3a)
Fly.io deprecated the sea region — new machines cannot be provisioned there. sjc (San Jose) is the recommended alternative for west coast.
fix(infra): Fly.io region sea → sjc
…onfig singleton All load_config() call sites in bot/message_handler.py replaced with tether_config.get() / get_bool() from the unified TetherConfig singleton (config/loader.py). config.yaml is no longer read at runtime. Missing sections added to app_config.yaml: - llm.use_v3, llm.v2_fallback, llm.mcp_server_url, llm.roles.main_agent.model - api.base_url, api.bot_token telegram.bot_token / chat_id already present (baked-in placeholder values). Fly.io entrypoint now only needs auth_config.yaml + app_config.yaml; the separate config.yaml download step can be removed. Dead code removed: load_config(), _CONFIG_PATH, yaml import. Tests updated to mock tether_config instead of load_config.
…-config refactor(bot): migrate message_handler off load_config() onto TetherConfig singleton
Bot crashes on Fly.io because ~/.tether-config/config.yaml doesn't exist in the container. Adds docker-entrypoint.sh which downloads config.yaml and anchors.yaml from CONFIG_SOURCE_URL before handing off to supervisord. URL scheme determines backend: https:// uses curl (with optional CONFIG_SOURCE_TOKEN for private gists), s3:// uses aws s3 cp. Switching from gist to S3 only requires changing the URL and adding AWS credentials. CONFIG_SOURCE_URL is set per Fly app (tether-prod vs tether-dev) so each environment pulls from its own gist. Also adds --ha=false to both deploy jobs to prevent Fly from creating a second HA machine on every deploy.
Config files in gist use ${PLACEHOLDER} markers for secrets. envsubst
fills them in from Fly secrets at container start — mirrors the Pi's
configure.py pattern. Non-secret config stays as literal values in the
gist. Adds gettext-base to Dockerfile for envsubst.
…load_config paths Downloads auth_config.yaml and app_config.yaml for TetherConfig (no envsubst — loader resolves placeholders itself). Also downloads config.yaml with envsubst for bot/message_handler.py:load_config() which reads it raw. config.yaml path removed once bot migrates to TetherConfig (tracked separately).
PR #327 migrated message_handler.py to TetherConfig. The loader resolves ${VAR} placeholders from env vars itself, so config.yaml and envsubst are no longer needed in the entrypoint. Entrypoint now downloads only auth_config.yaml and app_config.yaml (the TetherConfig local override layer). If CONFIG_SOURCE_URL is unset, the stack boots from baked-in defaults + Fly secrets alone. Removes gettext-base from Dockerfile since envsubst is no longer used.
feat(infra): docker entrypoint downloads tether config from gist/S3 at startup
Pi is no longer the primary deployment target. Moving all pi-* workflows to .github/workflows/archive/ so they no longer trigger on push. Fly.io (fly-deploy.yml) is now the active deployment path.
chore(ci): archive Pi workflows + simplify Fly.io entrypoint
Fly.io runs the release_command in a temporary machine before cutting traffic over to the new version. If migrations fail, the deploy is rolled back automatically. Uses ADMIN_DATABASE_URL (neondb_owner) if set, falls back to DATABASE_URL per alembic env.py.
feat(infra): alembic migrations via Fly release_command
alembic upgrade head fails with 'No script_location key found' because alembic.ini was not included in the COPY layer. Release command runs in /app but alembic.ini was missing.
fix(infra): copy alembic.ini into Docker image
Alembic uses psycopg2 dialect by default. psycopg2-binary was present in a Pi-specific fix branch but never landed in main's requirements.txt, causing alembic upgrade head to fail in the Fly release_command machine.
fix(deps): add psycopg2-binary for alembic Fly release_command
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.
No description provided.