Skip to content

feat(doctor,update): global doctor checks and isobox update --check (#50, #58, #59) - #64

Merged
parthashirolkar merged 2 commits into
mainfrom
feat/local-diagnostics-update-check
Jun 28, 2026
Merged

parthashirolkar merged 2 commits into
mainfrom
feat/local-diagnostics-update-check

Conversation

@parthashirolkar

@parthashirolkar parthashirolkar commented Jun 28, 2026 •

Copy link
Copy Markdown
Contributor

Implements the three 0.1.1 first-run usability issues from PRD #56.

Summary

This PR implements the global isobox doctor checks (issue #50), the
isobox update --check observability command (issue #58), and the
Update Target resolution with duplicate and managed-path guardrails
(issue #59).

Issue #50: Global isobox doctor checks

The doctor command now reports the following global checks on every
invocation:

  • version metadata as ok (a dev version is never treated as a
    warning or update-eligibility error)
  • git on PATH (error when missing, with consequence and fix)
  • bubblewrap (bwrap) on PATH (warning with Tool-Call Sandbox
    consequence when missing, plus a fix to install bubblewrap)
  • isobox on PATH (warning when missing)
  • multiple isobox binaries on PATH (warning listing the
    active binary plus duplicates)

The checks use an injectable PathLookup (internal/doctorenv)
so the unit tests run without depending on the host's actual
dependency state, and they never call the network, evaluate
self-update eligibility, or run a bubblewrap self-test.

Issue #58: isobox update --check

Adds the isobox update --check observability-only update check.
The command:

  • uses the GitHub Releases API to identify the latest stable
    release (drafts and prereleases are ignored)
  • reports the current version, latest version, status
    (up-to-date / behind / ahead), and selected Update Target
  • exits 0 for already-latest and for newer-stable-available
  • refuses dev builds with an actionable message
  • exposes the release metadata source as an injectable
    ReleaseClient (internal/update) so the integration tests
    do not depend on live GitHub

The release metadata wire format uses GitHub's tag_name,
prerelease, draft, and published_at JSON keys.

Issue #59: Update Target resolution with duplicate and managed-path guardrails

  • Update Target is resolved from the first isobox executable on
    the host PATH.
  • isobox update --check reports the selected Update Target.
  • Additional isobox executables on PATH are reported as
    warnings without changing the selected target.
  • Clearly package-manager- or system-managed targets (e.g.
    /usr/bin, /opt/homebrew, /snap, /var/lib/dpkg,
    /var/lib/rpm, /var/lib/pacman, /nix/store) are refused
    with guidance to use the package manager or move the binary to a
    writable manual-style directory (${HOME}/.local/bin or
    /usr/local/bin).
  • Power users with unusual system-managed install locations can
    teach the updater about additional managed prefixes by exporting
    ISOBOX_UPDATE_MANAGED_PATH_PREFIXES (one path per line) before
    running the check. The default behavior is unchanged.

Target resolution and eligibility behavior are covered by unit
tests in internal/update/target_test.go using a fake
PathLookup, plus an end-to-end integration test that
manipulates the test process PATH and uses
ISOBOX_UPDATE_MANAGED_PATH_PREFIXES to simulate a managed
target without requiring write access to /opt or /usr/bin.

Documentation

  • CHANGELOG.md records the new doctor global checks and
    isobox update --check under Unreleased.
  • README.md documents the isobox update --check flow and
    the global doctor checks.
  • isobox <command> --help and the top-level isobox --help
    now include update alongside the existing commands.
  • docs_test.go adds TestReadmeDocumentsUpdateCheckCommand
    and TestReadmeDocumentsGlobalDoctorChecks to guard the
    documentation.

Pre-PR checks

All pre-PR checks pass:

go test -count=1 ./...   # ok
go vet ./...             # clean
gofmt -l .               # clean (excluding site/node_modules)
go build ./...           # builds

The global doctor and update-check integration tests are
hermetic: they build a fake bwrap in a temp directory so the
tests do not depend on bubblewrap being installed on the host,
and they use a fully controlled PATH for tests that exercise
the missing-bwrap branch.

Out of scope (deferred to follow-up slices)

  • isobox update (the full update flow with download, checksum
    verification, replace, backup, and rollback) is intentionally
    not implemented in this PR. The --check slice is the
    observability-only vertical slice from PRD PRD: isobox 0.1.1 CLI help and self-update #56.
  • No signed checksums or embedded public-key verification.
  • No prerelease, channel, or specific-version update selection.
  • No --force, --target, --install-dir, or --yes
    update flags.
  • install.sh remains the first-install path only; update does
    not download or execute installer scripts.

@blacksmith-sh

This comment has been minimized.

isobox-agent added 2 commits June 28, 2026 16:27
, #58, #59)

Adds the global isobox doctor checks (issue #50):
- git on PATH (error when missing)
- bwrap on PATH (warning with Tool-Call Sandbox consequence when missing)
- isobox on PATH (warning when missing)
- multiple isobox binaries on PATH (warning listing the active and duplicates)
- version metadata as ok (dev is never treated as a warning)

The checks use an injectable PathLookup so they are unit-tested
without depending on the host's actual dependency state, and they
never call the network or evaluate self-update eligibility.

Adds isobox update --check (issue #58) and Update Target resolution
with duplicate and managed-path guardrails (issue #59):
- isobox update --check is the observability-only update check
  using the GitHub Releases API
- drafts and prereleases are ignored
- already-latest exits 0
- the Update Target is resolved from the first isobox on PATH
- duplicate isobox binaries are reported as warnings
- dev builds are refused with an actionable message
- clearly package-manager-managed targets are refused with guidance
  to use the package manager or move to a writable manual-style dir
- the release metadata source is injectable so tests do not depend
  on live GitHub
The previous integration tests relied on the host having git,
bubblewrap (bwrap), and isobox on PATH. CI runners do not have
bwrap installed, so several tests failed:

- TestDoctorReportsBwrapOnPathAsOK
- TestDoctorReportsBwrapMissingAsWarningNamingToolCallSandbox
- TestDoctorReportsIsoboxMissingAsWarning
- TestDoctorReportsDuplicateIsoboxAsWarning
- TestDoctorReportsVersionMetadataAsOKForDevBuild
- TestUpdateCheckRefusesPackageManagedUpdateTarget

The fix introduces:

1. A writeFakeExecutable helper that creates an empty file with
   the execute bit set in a temp dir. The doctor global checks
   call exec.LookPath only to test for presence, so a fake bwrap
   is sufficient and the test no longer depends on bubblewrap
   being installed on the host.

2. Fully controlled PATHs that exclude the host PATH for tests
   that exercise the bwrap-missing and the version-metadata
   branches, so a real bwrap installed on the host cannot
   accidentally satisfy the check.

3. ISOBOX_UPDATE_MANAGED_PATH_PREFIXES, an environment variable
   that adds extra managed path prefixes to the updater's
   refusal list. The default list still covers the common
   package-manager-managed locations; the env var exists for
   power users with unusual system-managed install locations and
   for the integration test suite, which can now teach the
   updater about a temp directory without requiring write
   access to /opt or /usr/bin.

The PR-ready state covers issues #50, #58, #59 with all
hermetic tests passing on environments with and without
bubblewrap.
@parthashirolkar
parthashirolkar merged commit 50c8ba2 into main Jun 28, 2026
1 check passed
@parthashirolkar
parthashirolkar deleted the feat/local-diagnostics-update-check branch June 28, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant