Skip to content

fix(store): legacy install actually runs DockerInstaller / PipInstaller (closes #410)#419

Merged
jaylfc merged 3 commits intomasterfrom
fix/legacy-install-actually-runs-docker-pip
May 8, 2026
Merged

fix(store): legacy install actually runs DockerInstaller / PipInstaller (closes #410)#419
jaylfc merged 3 commits intomasterfrom
fix/legacy-install-actually-runs-docker-pip

Conversation

@jaylfc
Copy link
Copy Markdown
Owner

@jaylfc jaylfc commented May 8, 2026

Summary

Reported in #410 — open-webui / perplexica / anything-llm POST install returned 200 OK but no docker container ever ran. Cards stayed "stale" forever.

`_legacy_install`'s docker/pip branch was a stub: it skipped past the installer code and just marked the app installed in the registry. Comment said "delegate to InstalledAppsStore (docker/pip/download)" but the delegation was a registry write only.

Now: when `backend in ("docker", "pip")`, instantiate the corresponding installer and call install(). Failures bubble up as 500 with the installer's error message. For docker we also auto-start compose so the service is actually serving on its declared ports without a separate user step.

This unblocks the new chat-UI manifests landed earlier tonight (anything-llm, librechat, jan, farfalle, plus the existing open-webui / perplexica) and the docker-method services from packs 2-9.

Test plan

  • `pytest tests/routes/test_store_install_v2.py tests/test_routes_store.py` — 26 passed
  • Live: install open-webui on the Pi after merge — expect docker container running on :3000 within ~30 s
  • Live: re-install (idempotency) — expect 'compose pull' to find image cached and 'compose up' to no-op

Closes #410.


Jay is asleep right now so this PR was opened by Claude Opus 4.7.

…closes #410)

Reported in #410 — open-webui / perplexica / anything-llm POST install
returned 200 OK but no docker container ever ran. Card stayed "stale"
forever.

Cause: the docker/pip branch in _legacy_install fell straight through
to the installed-apps store, which only records the install in the db
without invoking any actual installer. Comment said "delegate to
InstalledAppsStore (docker/pip/download)" but the delegation was just
a registry write.

Now: when backend is "docker" or "pip", instantiate the corresponding
installer and run install(). Failures bubble up as 500 with the
installer's error message instead of silent success. For docker we
also auto-start compose so the service is actually serving on its
declared ports without a separate user step (pip installs don't have
a generic start command — those are libraries the caller invokes).

Existing 26 store + install-v2 tests still pass.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Warning

Rate limit exceeded

@jaylfc has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 4 minutes and 12 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 539a8214-e3a4-4310-8184-5586882c6a22

📥 Commits

Reviewing files that changed from the base of the PR and between fda7ae7 and a515a4b.

📒 Files selected for processing (1)
  • tinyagentos/routes/store_install.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/legacy-install-actually-runs-docker-pip

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Default to data_dir/apps when app.state.apps_dir isn't set so installs
work without /opt write access (no root needed) and so pytest's tmp
data_dir captures the install side-effect cleanly. Tests for the
default install branch now pass — the earlier 2 PermissionErrors on
/opt/tinyagentos/apps were because the installer code was actually
running for the first time.
@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot Bot commented May 8, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 1
Issue Details (click to expand)

CRITICAL

WARNING

SUGGESTION

File Line Issue
tinyagentos/routes/store_install.py 375 SUGGESTION: If docker start fails, the app is still marked installed
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

Files Reviewed (1 files)
  • tinyagentos/routes/store_install.py - 1 issue

Reviewed by grok-code-fast-1:optimized:free · 208,743 tokens

# app.state.apps_dir on a tmp path.
apps_dir = getattr(request.app.state, "apps_dir", None)
if apps_dir is None:
data_dir = getattr(request.app.state, "data_dir", None)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Only catching FileNotFoundError for installer availability, but ImportError (if installer modules not found) will not be caught, leading to unhandled 500 error.

Add except ImportError as exc: before the general Exception handler.

from pathlib import Path as _Path
apps_dir = _Path(data_dir) / "apps"
try:
from tinyagentos.installers.docker_installer import DockerInstaller
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Broad exception catching with except Exception may hide important errors. Consider catching more specific exceptions related to installer failures.

)
except Exception as exc: # noqa: BLE001
logger.exception("_legacy_install: %s installer raised", backend)
return JSONResponse({"error": f"{backend} install failed: {exc}"}, status_code=500)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: If docker start fails, the app is still marked as installed, but the service may not be serving. Consider whether install should fail if start fails, or at least return a warning to the client.

return JSONResponse(
{"error": inst_result.get("error", f"{backend} install failed")},
status_code=500,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Broad exception catching with except Exception may hide important errors during docker start. Consider catching more specific exceptions.

- Catch FileNotFoundError + ImportError on installer construction
- Narrow broad Exception → OSError + RuntimeError (real failure modes
  for installer.install which exec processes + touches the filesystem)
- Same narrowing on docker compose-up. logger.exception still captures
  the traceback so debuggability is unchanged.
- Documented the design choice on docker start: image is on disk after
  pull succeeds, so we warn instead of failing the install when compose
  up trips on a port collision / daemon hiccup. User can manually
  'docker compose up -d' without re-pulling.
@jaylfc jaylfc merged commit 7f2c2c4 into master May 8, 2026
5 of 7 checks passed
@jaylfc jaylfc deleted the fix/legacy-install-actually-runs-docker-pip branch May 8, 2026 03:25
@github-project-automation github-project-automation Bot moved this from Todo to Done in TinyAgentOS Roadmap May 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

bug(install-v2): type=service docker installs return 'installed' but never run docker

1 participant