feat: add --offline flag to skip network access during up#316
feat: add --offline flag to skip network access during up#316hubertdeng123 wants to merge 5 commits intomainfrom
Conversation
Allows using cached dependencies and local docker images when working without internet. Useful for airplane/train work or spotty connections. Closes #315 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| if offline: | ||
| are_dependencies_valid = verify_local_dependencies(matching_dependencies) | ||
| if not are_dependencies_valid: | ||
| raise DependencyError( | ||
| repo_name="", | ||
| repo_link="", | ||
| branch="", | ||
| stderr="Cannot use --offline: some dependencies are not cached locally. Run 'devservices up' without --offline first to cache dependencies", | ||
| ) | ||
| return get_installed_remote_dependencies(matching_dependencies) |
There was a problem hiding this comment.
Bug: The DependencyError raised in offline mode doesn't display the helpful error message from stderr because its __str__ method omits it, showing a malformed message instead.
Severity: MEDIUM
Suggested Fix
Update the __str__ method for the DependencyError class in exceptions.py to include the self.stderr attribute in the output string. This will ensure the helpful error message is displayed when the exception is printed.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: devservices/utils/dependencies.py#L239-L248
Potential issue: When running with the `--offline` flag where dependencies are not
cached, a `DependencyError` is raised. The helpful error message is stored in the
`stderr` attribute of this exception. However, the `DependencyError.__str__` method does
not include the `stderr` attribute in its output. As a result, when the exception is
caught and displayed to the user, they see a confusing, malformed error message like
`DependencyError: () on .` instead of the intended actionable message.
Did we get this right? 👍 / 👎 to inform future reviews.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use de.stderr for offline DependencyError instead of garbled __str__ - Remove "try purge" suggestion for offline errors (not applicable) - Change skip_pull message to "using cached images" (no abstraction leak) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| branch="", | ||
| stderr="Cannot use --offline: some dependencies are not cached locally. Run 'devservices up' without --offline first to cache dependencies", | ||
| ) | ||
| return get_installed_remote_dependencies(matching_dependencies) |
There was a problem hiding this comment.
Offline validation misses nested dependencies, yields confusing error
Medium Severity
In offline mode, verify_local_dependencies only validates direct dependencies, but then get_installed_remote_dependencies recursively traverses nested (transitive) dependencies. If a nested dependency isn't cached, it raises DependencyNotInstalledError (with stderr=None). In the error handler, since offline is true, no helpful guidance is appended — the user just sees a generic "Dependency not installed correctly" message without being told to run without --offline first.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 9f976b4. Configure here.
Mocks DEVSERVICES_SUPERVISOR_CONFIG_DIR to tmp_path to prevent xdist race conditions when multiple workers write supervisor configs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
There are 3 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 48f958a. Configure here.
| for future in concurrent.futures.as_completed(futures): | ||
| _ = future.result() | ||
| else: | ||
| status.info("Skipping image pull (using cached images)") |
There was a problem hiding this comment.
Offline mode doesn't prevent docker compose up from pulling
Medium Severity
When skip_pull is True (offline mode), the explicit docker compose pull step is skipped, but the subsequent docker compose up -d command is still issued without --pull never. By default, docker compose up uses --pull policy (which resolves to pulling missing images). In a truly offline environment, if any image isn't locally cached (e.g., after a docker image prune), docker compose up will still attempt a network pull — causing hangs or timeouts rather than a clear immediate failure. The options list needs to include --pull never when skip_pull is True.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 48f958a. Configure here.
| msg = de.stderr if de.stderr else str(de) | ||
| if not offline: | ||
| msg = f"{msg}. If this error persists, try running `devservices purge`" | ||
| status.failure(msg) |
There was a problem hiding this comment.
Error message displays raw bytes in non-offline path
Medium Severity
The changed error handling now uses de.stderr if de.stderr else str(de) for the failure message. However, DependencyError.stderr is populated from CalledProcessError.stderr (via stderr=e.stderr in _update_dependency, _checkout_dependency, etc.), and _run_command calls subprocess.run without text=True, meaning e.stderr is bytes, not str. In the non-offline path, when a git operation fails, msg becomes a bytes object, and the subsequent f-string renders it as b'fatal: ...' — producing a confusing, ugly user-facing error message. Previously, str(de) was always used, which gave a clean formatted message.
Reviewed by Cursor Bugbot for commit 48f958a. Configure here.


Summary
--offlineflag that allowsdevservices upto work without network access by using cached dependencies and skipping docker image pulls--offlineis used and dependencies are not cached locally, a clear error message is shown asking the user to run without--offlinefirstCloses #315
Test plan
install_and_verify_dependenciestests still pass🤖 Generated with Claude Code