Skip to content

feat(cli): add self-update mechanism (omnigraph update) [MR-612]#79

Open
devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
devin/mr-612-add-cli-self-update
Open

feat(cli): add self-update mechanism (omnigraph update) [MR-612]#79
devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
devin/mr-612-add-cli-self-update

Conversation

@devin-ai-integration
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot commented May 10, 2026

Summary

Implements MR-612. Adds a CLI self-update flow with three pieces:

Phase 1 — omnigraph update subcommand (crates/omnigraph-cli/src/update.rs)

  • Detects platform automatically (Linux x86_64, macOS arm64).
  • Hits the GitHub Releases API for the configured channel, compares against CARGO_PKG_VERSION, and short-circuits with omnigraph is up to date (vX.Y.Z) if nothing newer is available.
  • Downloads the matching omnigraph-<platform>.tar.gz and .sha256, verifies the digest before touching anything, extracts into a temp dir on the same filesystem as the install dir, and replaces both omnigraph and omnigraph-server (when present) via POSIX rename(2) so the running binary is never partially overwritten.
  • Detects Homebrew installs (/opt/homebrew/, /usr/local/Cellar/, /usr/local/opt/, /home/linuxbrew/.linuxbrew/, plus a fallback to brew --prefix) and prints a one-liner directing the user to brew upgrade ModernRelay/tap/omnigraph.
  • Flags: --channel <stable|edge> (default stable), --check, -y/--yes. --channel edge always reinstalls because the edge tag moves with every push to main.

Phase 2 — startup notification (crates/omnigraph-cli/src/version_check.rs)

  • Best-effort one-line stderr notice ("A new version of omnigraph is available …") gated on a 24-hour cache.
  • Cache lives at $XDG_CACHE_HOME/omnigraph/update-check.json (default ~/.cache/omnigraph/update-check.json). Override for tests via OMNIGRAPH_UPDATE_CACHE_DIR.
  • Refresh runs in a detached child process (hidden __refresh-update-cache subcommand, setsid on Unix) so the foreground command never blocks on the network — same pattern as npm/update-notifier and gh.
  • Suppression: OMNIGRAPH_NO_UPDATE_CHECK=1, CI truthy, stdout not a TTY, and the version / update / __refresh-update-cache subcommands.

Phase 3 — Homebrew tap auto-update — already implemented in .github/workflows/release.yml (the update_homebrew_tap job runs scripts/update-homebrew-formula.sh, gated on the HOMEBREW_TAP_TOKEN secret). No code changes needed; verified the workflow matches the ticket's verification criteria.

Best-practice deltas from the literal ticket text

Per request, applied best-practice defaults rather than the literal spec:

  • Cache path is ~/.cache/omnigraph/ (XDG cache, where volatile data belongs), not ~/.config/omnigraph/.
  • Background refresh uses a detached subprocess rather than a tokio task that would be cancelled when the foreground command exits.
  • --check exits 0 in both up-to-date and "upgrade available" cases (matches apt list --upgradable); errors still exit non-zero. Easy to add a terraform-style --exit-code opt-in later if scripting demands it.
  • --channel edge always reinstalls — no fragile sha-compare against a tag that moves with main.

Tests

  • 6 integration tests in crates/omnigraph-cli/tests/update.rs use a hermetic in-process raw-TCP HTTP fixture (no extra dev-deps) and override OMNIGRAPH_UPDATE_API_BASE / OMNIGRAPH_UPDATE_DOWNLOAD_BASE. Coverage: up-to-date, newer-available, full download+verify+rename flow (asserts both binaries replaced byte-for-byte), checksum mismatch leaves the original binary in place, missing release metadata, and the case where omnigraph-server isn't present (must not be created).
  • 7 unit tests cover semver compare, Homebrew prefix detection, cache round-trip, and env-var truthiness rules.

Docs

  • docs/install.md — new "Updating" section.
  • docs/cli.md — new "Updating" section.
  • docs/cli-reference.mdupdate row added to the top-level command table.

Review & Testing Checklist for Human

  • On a real macOS arm64 / Linux x86_64 host with a fresh stable release published, run omnigraph update --check and omnigraph update --yes against an actual GitHub release and confirm both binaries get replaced and run the new version. The integration tests cover the logic but not the live-network path.
  • On a Homebrew install, confirm omnigraph update prints the brew upgrade hint without making network calls or modifying anything.
  • Confirm HOMEBREW_TAP_TOKEN is configured at the repo level and that the next stable tag actually triggers update_homebrew_tap to push a formula update to ModernRelay/homebrew-tap.

Notes

  • Phase 3 was already implemented before this PR (release workflow + script). The only verification action items are the secret check and an end-to-end run on the next tagged release.
  • The startup notice is gated in CI by both CI and the non-TTY check, so it should never appear in release pipelines.
  • OMNIGRAPH_UPDATE_API_BASE / OMNIGRAPH_UPDATE_DOWNLOAD_BASE are documented only in the source — they're test-only knobs and intentionally not surfaced in user docs.

Link to Devin session: https://app.devin.ai/sessions/a22fd3c129a747679d520560ee683fc6
Requested by: @ragnorc


Open in Devin Review

- New `omnigraph update` subcommand: GitHub Releases API → archive download
  → SHA256 verification → atomic POSIX rename of both binaries.
- Detects Homebrew installs and short-circuits with a hint to run
  `brew upgrade ModernRelay/tap/omnigraph`.
- Channels: `--channel stable` (default) or `edge`. `--check` for
  check-only, `--yes` to skip the confirmation prompt.
- Best-effort startup version check (24h cached at
  `~/.cache/omnigraph/update-check.json`) with one-line stderr notice.
  Cache is refreshed via a detached `__refresh-update-cache` subprocess so
  the foreground command never blocks on the network. Suppression: CI,
  `OMNIGRAPH_NO_UPDATE_CHECK=1`, non-TTY stdout, and `version`/`update`
  subcommands.
- Integration tests use an in-process raw-TCP HTTP fixture (no extra
  dev-deps) and override `OMNIGRAPH_UPDATE_API_BASE` /
  `OMNIGRAPH_UPDATE_DOWNLOAD_BASE` to keep the suite hermetic.
- Docs: `install.md`, `cli.md`, `cli-reference.md` updated.

Co-Authored-By: Ragnor Comerford <ragnor.comerford@gmail.com>
@devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

cubic-dev-ai[bot]

This comment was marked as resolved.

- Refuse non-interactive update without --yes (Devin Review P1):
  bail with a clear error instead of silently replacing binaries when
  stdin is not a TTY. Matches gh / rustup / apt-get posture.
- Persist 24h cooldown on refresh failures (cubic P2): the hidden
  `__refresh-update-cache` subprocess now writes a fresh
  `checked_at_unix` even when the GitHub API call fails (keeping the
  previously-known tag), so a transient outage doesn't spam refreshes.
- Make the checksum-mismatch test platform-correct (cubic P2): compare
  byte-for-byte against the snapshotted original binary instead of
  ELF/shebang magic, which excluded macOS arm64 (Mach-O).
- Bump cli-reference top-level family count 17 -> 18 (cubic P3).
- Add a new integration test asserting non-interactive bail-out.

Co-Authored-By: Ragnor Comerford <ragnor.comerford@gmail.com>
cubic-dev-ai[bot]

This comment was marked as resolved.

devin-ai-integration Bot and others added 3 commits May 10, 2026 21:52
…R-612)

cubic P2 follow-up. `touch_cooldown` previously carried forward
`latest_version` from any prior cache entry, even one written by a
binary pointed at a different fork. After this change we only reuse the
cached version when its `repo_slug` matches the repo this binary was
built for; otherwise we fall back to the current binary's own version,
which never fires a spurious "newer available" notice.

Adds two unit tests covering both cases.

Co-Authored-By: Ragnor Comerford <ragnor.comerford@gmail.com>
Previous run failed only on `concurrent_branch_ops_morphological_matrix`
in omnigraph-server, a new concurrency stress test introduced by #75.
This PR touches only omnigraph-cli; the same test passed on the main
branch run immediately before this PR's CI executed. Empty commit to
re-trigger CI and confirm flake.

Co-Authored-By: Ragnor Comerford <ragnor.comerford@gmail.com>
`concurrent_branch_ops_morphological_matrix` (added by #75) fails ~20%
locally on plain main; tracked separately. No code change in this commit.

Co-Authored-By: Ragnor Comerford <ragnor.comerford@gmail.com>
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