Skip to content

fix(selfupdate): use LookPath instead of Executable for binary verification (fixes #836)#886

Merged
liangshuo-1 merged 7 commits into
larksuite:mainfrom
CatfishGG:fix-issue-836
May 14, 2026
Merged

fix(selfupdate): use LookPath instead of Executable for binary verification (fixes #836)#886
liangshuo-1 merged 7 commits into
larksuite:mainfrom
CatfishGG:fix-issue-836

Conversation

@CatfishGG
Copy link
Copy Markdown
Contributor

@CatfishGG CatfishGG commented May 14, 2026

Summary

Issue: #836lark-cli update reports "binary verification failed" on Linux global npm install even though the new version is correctly installed and working.

Root Cause

VerifyBinary() in internal/selfupdate/updater.go was using vfs.Executable() (wrapping os.Executable()) as the primary way to locate the binary to run --version against.

On Linux, os.Executable() returns the inode path of the currently running binary — the old version. After npm installs the new version to node_modules/.bin/lark-cli, the running process is still the old binary at its original inode path. The verification step was running lark-cli --version on the old binary, which reported the old version → verification failed even though the new version was correctly installed and fully functional.

Fix

Flip the lookup priority: use exec.LookPath("lark-cli") as the primary mechanism instead of vfs.Executable().

LookPath searches PATH and follows symlinks — on Linux with a global npm install, the PATH entry for lark-cli resolves through npm's bin symlink to the newly installed version. This is exactly what the user gets when they run lark-cli normally, and matches the suggested fix in the issue ("verify the final resolved executable after npm install").

The old comment even noted this was a known edge case but chose the wrong approach. The fix aligns with the issue's own suggested direction.

Changes

  • Remove vfs.Executable() as primary lookup in VerifyBinary
  • Remove LookPath fallback (now the primary and only lookup)
  • Simplify error handling (single return path instead of nested)
  • Update comment to explain the correct rationale

Testing

go test ./internal/selfupdate/... and go test ./cmd/update/... — all pass.

Fixes #836

Summary by CodeRabbit

  • Bug Fixes

    • Self-update now reliably locates and runs the newly installed CLI binary by following system binary resolution behavior.
  • Tests

    • Reworked tests to mock binary discovery instead of altering the environment; added cases for successful resolution, missing binary, and empty-version output; removed a brittle environment-dependent test.

Review Change Stack

…cation (fixes larksuite#836)

VerifyBinary was using vfs.Executable() to find the binary to run --version against.
On Linux with global npm install, this returns the inode of the running binary (old version),
not the newly installed one that sits behind npm's bin symlink.

Switch to exec.LookPath("lark-cli") which resolves the PATH entry and follows npm's
bin symlink to the correct newly installed version, matching what the user actually runs.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 14, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

VerifyBinary now resolves the executable by calling execLookPath("lark-cli") directly; tests add a package-level execLookPath hook and three lookup-focused test cases (success, not found, empty output).

Changes

Binary verification executable resolution

Layer / File(s) Summary
Executable resolution via npm's bin symlink
internal/selfupdate/updater.go, internal/selfupdate/lookpath.go
VerifyBinary switches from vfs.Executable() with fallback to exec.LookPath() to directly calling execLookPath("lark-cli"); added package-level execLookPath variable defaulting to exec.LookPath and updated comments and binary-not-found error handling.
Tests: execLookPath hook and lookup-focused cases
internal/selfupdate/updater_test.go
Adds lookPathMock helper to override execLookPath, adjusts imports, and replaces PATH-based test with three focused cases: matching version via a temp script, lookup failure (not found), and empty output.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

size/L

Suggested reviewers

  • liangshuo-1

Poem

🐰 I sniffed for lark-cli in the hay,
execLookPath hopped out to say hey.
Tests mock paths with scripts neat and spry,
Found, not-found, and silence—no lie.
A carrot for CI as changes fly!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: switching from Executable to LookPath for binary verification to fix the Linux npm update issue.
Description check ✅ Passed The description comprehensively covers the issue summary, root cause, fix rationale, changes made, and test verification following the template structure.
Linked Issues check ✅ Passed The PR fully addresses issue #836 by changing VerifyBinary to use exec.LookPath instead of vfs.Executable, which resolves the binary lookup to the actual installed version after npm install, following symlinks to the newly installed binary.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the binary verification issue: modifying VerifyBinary logic, introducing the execLookPath variable for testability, and updating tests to verify the new behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@github-actions github-actions Bot added the size/M Single-domain feat or fix with limited business impact label May 14, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.91%. Comparing base (37459b6) to head (b9f2019).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #886      +/-   ##
==========================================
+ Coverage   65.89%   65.91%   +0.02%     
==========================================
  Files         518      520       +2     
  Lines       48945    49277     +332     
==========================================
+ Hits        32254    32483     +229     
- Misses      13921    14022     +101     
- Partials     2770     2772       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 14, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@b9f20192f713a47e063333ee715275398fbc8049

🧩 Skill update

npx skills add CatfishGG/cli#fix-issue-836 -y -g

@liangshuo-1
Copy link
Copy Markdown
Collaborator

Hi @CatfishGG, thanks for the fix 👍 The direction matches suggestion #1 from issue #836.

One thing blocking merge: the CLA hasn't been signed yet. Please sign at https://cla-assistant.io/larksuite/cli?pullRequest=886 — once license/cla turns green we can move forward with review/merge.

Add TestVerifyBinaryLookPath, TestVerifyBinaryLookPathNotFound, and
TestVerifyBinaryEmptyOutput. Expose execLookPath variable so tests can
inject a mock LookPath and cover the full VerifyBinary execution path
including version parsing and error branches.
@CatfishGG
Copy link
Copy Markdown
Contributor Author

CatfishGG commented May 14, 2026

Thanks for the review @liangshuo-1! CLA is now signed (see the green license/cla check). I've also just pushed a fix for the 50% patch coverage issue — added tests that inject a mock LookPath to cover the full VerifyBinary execution path. PTAL when you get a chance 👍

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/selfupdate/updater_test.go (1)

6-14: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Add missing os/exec import.

Line 47 uses exec.LookPath, which requires importing os/exec. The import is not present in the file's import block (lines 6-14), causing a compile failure.

Proposed fix
 import (
 	"fmt"
+	"os/exec"
 	"os"
 	"path/filepath"
 	"runtime"
 	"testing"

 	"github.com/larksuite/cli/internal/vfs"
 )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/selfupdate/updater_test.go` around lines 6 - 14, The test file is
missing the os/exec import used by exec.LookPath; update the import block in
internal/selfupdate/updater_test.go to include "os/exec" so calls to
exec.LookPath resolve (locate the import alongside existing imports like "os",
"path/filepath", "runtime", "testing" and
"github.com/larksuite/cli/internal/vfs").
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/selfupdate/updater_test.go`:
- Around line 74-128: The new tests (TestVerifyBinaryLookPath,
TestVerifyBinaryLookPathNotFound, TestVerifyBinaryEmptyOutput) do not isolate
CLI config state; add t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) at the
start of each test (before calling New() or anything that may read config) so
the calls to New().VerifyBinary use an isolated config directory and avoid
cross-test coupling.

---

Outside diff comments:
In `@internal/selfupdate/updater_test.go`:
- Around line 6-14: The test file is missing the os/exec import used by
exec.LookPath; update the import block in internal/selfupdate/updater_test.go to
include "os/exec" so calls to exec.LookPath resolve (locate the import alongside
existing imports like "os", "path/filepath", "runtime", "testing" and
"github.com/larksuite/cli/internal/vfs").
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5125e095-c98d-429b-80af-e3a62faf75f6

📥 Commits

Reviewing files that changed from the base of the PR and between b33383c and e30a4f5.

📒 Files selected for processing (2)
  • internal/selfupdate/updater.go
  • internal/selfupdate/updater_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/selfupdate/updater.go

Comment thread internal/selfupdate/updater_test.go Outdated
CatfishGG and others added 5 commits May 14, 2026 20:14
…Binary tests

CodeRabbit feedback:
- Add missing os/exec import for execLookPath variable
- Add t.Setenv(LARKSUITE_CLI_CONFIG_DIR, ...) to each new test for config isolation
Move the execLookPath variable declaration to its own file so it is
accessible to updater.go without the test-only import cycle.
- Move execLookPath into updater.go (drops redundant lookpath.go)
- Document package-level mock: no t.Parallel()
- Extend TestVerifyBinaryLookPath with exact-match regressions (0.0, 12.1.0 vs 2.1.0)

Fixes fast-gate gofmt failure on PR larksuite#886.

Change-Id: Ia6c784754fa8c8a917df7bf58fe821a23b017945
Co-authored-by: Cursor <cursoragent@cursor.com>
Claude F4 / option A: keep LookPath first for npm bin symlink (larksuite#836), but
restore Executable fallback for absolute-path launches without PATH entry.

- Adjust LookPath-not-found test to mock DefaultFS Executable
- Add TestVerifyBinaryFallbackExecutableWhenNotOnPath

Change-Id: If8acf96f757c3454ba2f670a1fbbc0ae511c93e5
Co-authored-by: Cursor <cursoragent@cursor.com>
@liangshuo-1
Copy link
Copy Markdown
Collaborator

Process note (review-side)

During review, I pushed two commits directly to this PR branch on your fork (`4f03752`, `b9f2019`) to address CI (gofmt / fast-gate), version-matching regression tests, and the `LookPath` vs `vfs.Executable` fallback discussed in review.

That was a mistake on process: I should not have updated your fork without your explicit OK. Sorry for bypassing your ownership of the branch.

Please treat those commits as optional: you are welcome to `revert`, `reset`, `cherry-pick`, squash, or re-implement the same changes yourself. If you prefer, you can ask maintainers to land follow-up fixes via a separate branch/PR instead.

Going forward (my side): for external-contributor PRs I will stick to review comments and patches in the thread, or a maintainer-owned follow-up PR—not direct pushes to the author’s fork unless you’ve asked for that explicitly.

Again, apologies for the churn.

@liangshuo-1 liangshuo-1 merged commit ed9eecf into larksuite:main May 14, 2026
17 checks passed
@CatfishGG
Copy link
Copy Markdown
Contributor Author

CatfishGG commented May 14, 2026

Hey @liangshuo-1 no apology needed, really. The commits you pushed were exactly what the PR needed: the gofmt fix, the version-matching regression tests, and the LookPath + vfs.Executable fallback that made the whole thing robust. All of that was genuinely helpful.

If anything, the process was refreshingly direct, you saw what needed fixing and just did it rather than going back and forth endlessly. Much appreciated.

As for going forward: your proposed approach (review comments + patches in-thread, or a maintainer follow-up PR) makes total sense for larger changes. For small fixes like this one, direct pushes with a heads-up work fine too, so no need to be overly formal about it.

Thanks for the smooth experience overall, and glad the PR landed cleanly in main.

@liangshuo-1 liangshuo-1 mentioned this pull request May 15, 2026
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lark-cli update reports binary verification failure on Linux global npm install, but package is updated

3 participants